Unable to achieve expected priorities of tasks on FreeRTOS (CMSIS v1) on STM32F4 DISC

developb wrote on Thursday, October 31, 2019:

Am analysing runtime behaviour of 2 tasks on STM32 board using tracelyzer shows unexpected behaviour. Task1 is a cyclic executive which receives data over UART and processes received data to be consumed by task2. task1 is interrupt driven (indefintely blocks on semaphore which is released in UART receive interrupt handler)
Tried reversing priority of tasks too but to no use.
The task2 always behaves as higher priority task, but I expect task2 to be preempted and task1 to be run whenever task1 is ready for execution (ie semaphore is released), which I could not achieve.

I have used HAL_UART_Receive_DMA() and HAL_UART_RxCpltCallback() for task1 and its interrupt handler respectively, whereas vTaskDelayUntil() for task2 with period 10ms.
Using STM32F407, FreeRTOS with CMSIS v1.

Configured timebase source as TIM8 in SYS TAB in STM32CubeIDE. Did not enable checkbox for System Wake-up.
In tracelyzer, though I observe that even though UART data received and interrupt handler has released semaphore1, rxhandler task is not scheduled when rxhandler and another task are ready, but another task is scheduled and only after another task calls vTaskDelay, rxhandler is scheduled.

I read HAL uses systick and FreeRTOS timebase source as per suggested guidelines, has been set to a timer, TIM8. But, interrupt handler/priority and pre-emption has got nothing to do with FreeRTOS I believed as interrupt priorities and handlers are cortex features and not FreeRTOS.

Is the cause for this using HAL interrupt handler instead of custom UART interrupt handling in FreeRTOS?

Thank you

richard_damon wrote on Thursday, October 31, 2019:

 Does your interrupt handler check the task woken flag from the xGiveSemaphoreFromISR function and invoke the scheduler? That is what should cause Task1 to start executing. If the ISR doesn't make that call, then Task1 won't be switched to until some other event happens that invokes the scheduler

aggarg-aws wrote on Thursday, October 31, 2019:

Did you call portYIELD_FROM_ISR as mentioned here: https://www.freertos.org/a00124.html


developb wrote on Thursday, October 31, 2019:

Yes, Done calling portYield_FROM_ISR, but not the scheduler call.
So, you mean to say, unless schedule call is done manually, scheduler will be invoked only during ticks?

It goes as below:

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
if(huart->Instance == USART6)
tick_insdata_arrival = xTaskGetTickCountFromISR();
BaseType_t xHigherPriorityTaskWoken;
xHigherPriorityTaskWoken = pdFALSE;
xSemaphoreGiveFromISR( xSemaphore1Handle, &xHigherPriorityTaskWoken);
portYIELD_FROM_ISR( xHigherPriorityTaskWoken );

developb wrote on Thursday, October 31, 2019:

I missed mentioning my FreeRTOSConfig.h detail. Attached it now.

rtel wrote on Thursday, October 31, 2019:

The use of the semaphore in the interrupt handler looks fine (although
using a direct to task notification would be more efficient).

When I look at the trace I see the xSemaphoreGiveFromISR() function
unblocking the RxHandler task, and that the next task to run after the
interrupt is the RxHandler task. It is not clear why that is not the
expected behaviour - could you describe the behaviour you would have
expected to see?