Facing issue with Stm32F303 + FreeRTOS : xQueueSendFromISR in UART Rx interrupt.

mukeshtalks wrote on Friday, July 31, 2015:

Hello All,

I am new to FreeRTOS with STM32F303 (ARM CM4F). I am trying to send data received from UART in queue using xQueueSendFromISR call. I am always entering into assert while accessing xQueueSendFromISR from UART interrupt. If i call xQueueSend() from same ISR it works.
Is there anyone gives the clue what could be wrong.

Regards,
Mukesh

rtel wrote on Friday, July 31, 2015:

Is there anyone gives the clue what could be wrong.

Probably not unless you give us some clues first. You have not said which assert is being hit, or shown any code as to how the xQueueSendFromISR() is being called.

Please say which assert is being triggered, as that should tell you what is wrong. If not, place a break point in the assert then either look at the call stack to see how you got there, or step out of the assert function back to where the assert was triggered so you can easily see the values of the variables at that point - as that will probably tell you.

If you still have a problem then please post some code so we can see how you are using the function.

mukeshtalks wrote on Friday, July 31, 2015:

Thanks for Quick reply.

After geeting the USART receive interrupt it hits the assert as explained below:

configASSERT( ucCurrentPriority >= ucMaxSysCallPriority );

I tried the diffrent priorities setting with the interrupt and NVIC controller still not able to understand the issue.

as per call stack it is entering into assert from
xQueueGenericSendFromISR().

Please find the code bellow for your reference.:
controller used STM32f303 (ARM CORTEX M4), ST Standard peripheral library used. IAR EWARM 7.20 is used.

USART Initialization
void vUsartConfig(void)
{
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;

SerialComm_vGPIOInit();	


/* USARTx configuration ----------------------------------------------------*/
/* USARTx configured as follow:
- BaudRate = 230400 baud  
- Word Length = 8 Bits
- One Stop Bit
- No parity
- Hardware flow control disabled (RTS and CTS signals)
- Receive and transmit enabled
*/
USART_InitStructure.USART_BaudRate = 38400;//19200;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_Init(COMM2_PORT, &USART_InitStructure);

/* NVIC configuration */
/* Configure the Priority Group to 2 bits */
//NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);

/* Enable the USARTx Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = COMM2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority =0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);

/* Enable USART */
USART_Cmd(COMM2_PORT, ENABLE);
USART_ITConfig(COMM2_PORT, USART_IT_RXNE, ENABLE);

}

USART RX Interrupt where Queue send is called
void USART2_IRQHandler(void)
{
UBYTE ubData =0;
/* USART in mode Receiver */
if (USART_GetITStatus(COMM2_PORT, USART_IT_RXNE) == SET)
{
ubData = USART_ReceiveData(COMM2_PORT);
xQueueSendFromISR(xRXQueueHandle, &ubData, &isPriorityTaskWoken);
//xQueueSend(xRXQueueHandle,&ubData,100);
}
}

Task Creattion and Que Creation
void vCommServiceInit(void)
{
vSerialCommInit();
xRXQueueHandle = xQueueCreate(USB_SERIAL_RX_BUFFER_SIZE, sizeof(UBYTE));
xRXQueueHandle = xQueueCreate(USB_SERIAL_TX_BUFFER_SIZE,sizeof(UBYTE));
/* Create one of the two tasks. /
xTaskCreate( vSerialCommTask, “Serial Comm Task”, 1000, NULL, 2, NULL ); /
We are not using the task handle. */
}

void vSerialCommTask( void pvParameters )
{
UBYTE ubRxData=0;
portBASE_TYPE myErrorVal = 0;
/
As per most tasks, this task is implemented in an infinite loop. /
for( ;; )
{
myErrorVal = xQueueReceive(xRXQueueHandle, &ubRxData, portMAX_DELAY);
/
Print out the name of this task. */
if(myErrorVal == 1)
{
vByteRecieved(ubRxData);
}
vSerialCommunication();
}
}

Main functiona and kernel initialization
void main()
{
SYSTICK_Init();
vCommServiceInit(); //Intializing the USART, Creating Task and Queue
ADC_vInit();
NVIC_SetPriorityGrouping(0);

    /* Create one of the two tasks. */
    xTaskCreate( vTask1, "Task 1", 1000, NULL, 1, NULL );		/* We are not using the task handle. */
    /* Create the other task in exactly the same way. */
    xTaskCreate( vTask2, "Task 2", 1000, NULL, 1, NULL );
    /* Create the other task in exactly the same way. */
    xTaskCreate( vTask3, "Task 3", 1000, NULL, 1, NULL );
    
    xAdcTimer = xTimerCreate("AdcTimer",10,pdTRUE,0,vAdcTimerCallBack);
    xTimerStart( xAdcTimer, 0 );
    
    /* Start the scheduler so our tasks start executing. */
    vTaskStartScheduler();	
    
    /* If all is well we will never reach here as the scheduler will now be
    running.  If we do reach here then it is likely that there was insufficient
    heap available for the idle task to be created. */
    for( ;; );

}

davedoors wrote on Friday, July 31, 2015:

Read the link to see the two things that are wrong in the code
http://www.freertos.org/RTOS-Cortex-M3-M4.html

mukeshtalks wrote on Friday, July 31, 2015:

Thanks dave for reply, found accroding the link shared by you i need to set the priority grouping to NVIC_SetPriorityGrouping(NVIC_PriorityGroup_4); an dtried with this with no sub pritoriy in the USART interrupt and Main pririty setting to 0x0f to make it low priority inteeurpt.
But still i am facinf the same issue.

I found when it is entering to Assert
if( ulCurrentInterrupt >= portFIRST_USER_INTERRUPT_NUMBER )
is getting true where ulCurrentInterrupt is 54 and portFIRST_USER_INTERRUPT_NUMBER is 16. this is in port.c file.
I didnt get any clue.

rtel wrote on Friday, July 31, 2015:

When you hit the line:

configASSERT( ucCurrentPriority >= ucMaxSysCallPriority );

What are the values of ucCurrentPriority and ucMaxSysCallPriority?

What are the settings for the following constants in your
FreeRTOSConfig.h file?

configPRIO_BITS
configLIBRARY_LOWEST_INTERRUPT_PRIORITY [optional]
configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY [optional]
configKERNEL_INTERRUPT_PRIORITY
configMAX_SYSCALL_INTERRUPT_PRIORITY

Regards.

mukeshtalks wrote on Friday, July 31, 2015:

ucCurrentPriority = 54
ucMaxSysCallPriority = 0x50
FreeRTOSConfig.h is attached in the post for reference.

rtel wrote on Friday, July 31, 2015:

…and you are still hitting the asset? If ucCurrentPriority is greater than ucMaxSysCallPriority, meaning it has a lower logical priority, so everything should be ok.

I’m not sure why ucCurrentPriority is 54 though. You say you are setting the priority to 0x0f, so I would expect it to be 0xf0 (240) when viewed in the debugger (because it is shifted up 4)

mukeshtalks wrote on Monday, August 03, 2015:

The value of these variable is

ucCurrentPriority = 54
ucMaxSysCallPriority = 0x50
at the time of entering the if condition
if( ulCurrentInterrupt >= portFIRST_USER_INTERRUPT_NUMBER )
and after entering here there is one more line of code
/* Look up the interrupt’s priority. */
ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ];
after exicution of this instruction the value of
ulCurrentInterrupt = 0;
and then hitting the assert.

I can also share the complete project which can run on STM32f3 Discovery board if nedded for understading the issue.
But still not get any idea why this is happening

rtel wrote on Monday, August 03, 2015:

I am confused.

Is ucCurrentPriority 54 before it is set (so when it holds a random value), or after it is set (so after the line ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ]; has executed.

If ulCurrentInterrupt is 0 (not ulCurrentInterrupt, not ucCurrentPriority) then it is not the interrupt you think it is, and has probably never had its priority set.

mukeshtalks wrote on Monday, August 03, 2015:

54 i am getting before the line ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ]; has executed.
After exicution of this line I am getting zero. if I am not wrong it means USART pririty is still higher set to zero which is higher, if so please suggest where i am doing the mistake.

rtel wrote on Monday, August 03, 2015:

As per my previous email - the fact ulCurrentInterrupt is 0 would make
me think the interrupt is not the one you think it is. What is the
number of the interrupt you are setting the priority of?

mukeshtalks wrote on Monday, August 03, 2015:

I have 3 interrupt running i have given the same priority to all 0xf and sub prirority to 0.

Can you suggest me the interrupt pririty settings, I can try that.

mukeshtalks wrote on Tuesday, August 04, 2015:

Hey guys i could able to crack the issue. To set the usart priority i was using the code below:

NVIC_InitStructure.NVIC_IRQChannel = COMM2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority= configLIBRARY_LOWEST_INTERRUPT_PRIORITY; //0xf
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);

Ideally it should set the usart interrupt priority in NVIC but actally it was not, because of it in the NVIC the USART was always set to 0 means highest priority, and hitting the assert.

Now i used 
NVIC_SetPriority(COMM2_IRQn, 6); 
and now code is working as required.

But I am confused and not able to understand why this is not working because of the function defined in STM32f3 standard peripheral is not working, or compiler issue of IAR or something else.

Thanks RTE for quick responses.

rtel wrote on Tuesday, August 04, 2015:

Thanks for reporting back.

Did you try stepping into the NVIC_Init() function? Maybe it is
performing a test that fails and just returns without doing anything?

Regards.

mukeshtalks wrote on Tuesday, August 04, 2015:

This function is not returning anything out of that. for your reference function implemented in stm32f3 standard peipheral libray is

/**

  • @brief Initializes the NVIC peripheral according to the specified
  •     parameters in the NVIC_InitStruct.
    
  • @note To configure interrupts priority correctly, the NVIC_PriorityGroupConfig()
  •     function should be called before. 
    
  • @param NVIC_InitStruct: pointer to a NVIC_InitTypeDef structure that contains
  •     the configuration information for the specified NVIC peripheral.
    
  • @retval None
    /
    void NVIC_Init(NVIC_InitTypeDef
    NVIC_InitStruct)
    {
    uint32_t tmppriority = 0x00, tmppre = 0x00, tmpsub = 0x0F;

/* Check the parameters */
assert_param(IS_FUNCTIONAL_STATE(NVIC_InitStruct->NVIC_IRQChannelCmd));
assert_param(IS_NVIC_PREEMPTION_PRIORITY(NVIC_InitStruct->NVIC_IRQChannelPreemptionPriority));
assert_param(IS_NVIC_SUB_PRIORITY(NVIC_InitStruct->NVIC_IRQChannelSubPriority));

if (NVIC_InitStruct->NVIC_IRQChannelCmd != DISABLE)
{
/* Compute the Corresponding IRQ Priority --------------------------------*/
tmppriority = (0x700 - ((SCB->AIRCR) & (uint32_t)0x700))>> 0x08;
tmppre = (0x4 - tmppriority);
tmpsub = tmpsub >> tmppriority;

tmppriority = (uint32_t)NVIC_InitStruct->NVIC_IRQChannelPreemptionPriority << tmppre;
tmppriority |=  NVIC_InitStruct->NVIC_IRQChannelSubPriority & tmpsub;
tmppriority = tmppriority << 0x04;
    
NVIC->IP[NVIC_InitStruct->NVIC_IRQChannel] = tmppriority;

/* Enable the Selected IRQ Channels --------------------------------------*/
NVIC->ISER[NVIC_InitStruct->NVIC_IRQChannel >> 0x05] =
  (uint32_t)0x01 << (NVIC_InitStruct->NVIC_IRQChannel & (uint8_t)0x1F);

}
else
{
/* Disable the Selected IRQ Channels -------------------------------------*/
NVIC->ICER[NVIC_InitStruct->NVIC_IRQChannel >> 0x05] =
(uint32_t)0x01 << (NVIC_InitStruct->NVIC_IRQChannel & (uint8_t)0x1F);
}
}