FreeRTOS ISR API for STM32F411

Hello Forum, I am trying go handle a receive Interrupt on STM32F411 Eval board using the FreeRTOS API. However, xSemaphoreGiveFromISR is the API that is causing the problem. When the interrut occurs, i.e when the Rx line receives a character from user, the program freezes, remains stuck until Reset. If i do not use the FreeRTOS APIs for ISR , the Rx Interrupt works, please see code below. So i know the Interrupt is working, when i turn USE_FREERTOS_ISR_API in my code off and i can see the received byte on my terminal program. Also i have referred to chapter 6 of the FreeRTOS handson guide manual regarding Interrupt management. void USART2IRQHandler(void) { #ifndef USEFREERTOSISRAPI if (USARTGetITStatus(USART2, USARTITRXNE)) { RxCpltflag =1 Recvdword = USARTReceiveData(USART2); USARTClearITPendingBit(USART2, USARTITRXNE);
    }
        #else /*Freertos APIS are used*/
    static BaseType_t xHigherPriorityTaskWoken;

    xHigherPriorityTaskWoken = pdFALSE;
    xSemaphoreGiveFromISR( xBinarySemaphore, &xHigherPriorityTaskWoken );
    //xSemaphoreGive(xBinarySemaphore);

    taskENTER_CRITICAL() ;
    if (USART_GetITStatus(USART2, USART_IT_RXNE))
    {

        Recvd_word = USART_ReceiveData(USART2);
        USART_ClearITPendingBit(USART2, USART_IT_RXNE);

    }

    if ( xHigherPriorityTaskWoken != pdFALSE )
        portYIELD_FROM_ISR(xHigherPriorityTaskWoken);


    taskEXIT_CRITICAL();

        #endif
} ` I have created two other tasks which are running fine. Here are my sample task functions, ~~~ int main(void) {
SystemInit();

init_USART2();
init_led_gpios();
enable_usart2_irq();
xBinarySemaphore = xSemaphoreCreateBinary();

// Create a task
// Stack and TCB are placed in CCM of STM32F4
// The CCM block is connected directly to the core, which leads to zero wait states
if( xBinarySemaphore != NULL )
{
    xTaskCreateStatic(vTask1_print, "task1_print", TASK1_STACK_SIZE, NULL, 5,
            printTask1_Stack, &Task1Buff);
    xTaskCreateStatic(vTask2_print, "task2_print", TASK2_STACK_SIZE, NULL, 1,
            printTask2_Stack, &Task2Buff);

ifdef USEFREERTOSISR_API

    xTaskCreateStatic(vTask_ISR_Handler, "task3_isr", TASK3_STACK_SIZE, NULL, 2,
                    printTask3_Stack, &Task3Buff);

endif

    USART_TX_string("Starting scheduler...rn");

    vTaskStartScheduler();  // should never return
}
while (1)
{}
} void vTask1_print(void* p) { while (1) {
    USART_TX_string("Task1...rn");

ifndef USEFREERTOSISR_API

    if (Rx_Cplt_flag == 1)
    {
        USART_TX_byte(Recvd_word);
        Rx_Cplt_flag = 0;
    }

endif

    vTaskDelay(500);
}

vTaskDelete(NULL);
} void vTask2_print(void* p) { while (1) {
    toggle_leds();
    vTaskDelay(1000);
}
vTaskDelete(NULL);
} void vTaskISRHandler(void *p) { while(1) { xSemaphoreTake(xBinarySemaphore, 10000); USART_TX_byte(Recvd_word); vTaskDelay(5000); } } ~~~

FreeRTOS ISR API for STM32F411

You probably need to set the priority of the interrupt to somethng allowable by FreeRTOS to use the API in the interrupt. If you stop the program with a debugger, you will probably find it has hung inside an asssert.

FreeRTOS ISR API for STM32F411

Thank you for your response, im not able to Debug since OpenOCD is not working correctly on my Toolchain, However, i went through this https://www.freertos.org/RTOS-Cortex-M3-M4.html And did the following: ~~~ NVICUSARTStruct.NVICIRQChannelPreemptionPriority = 17; ~~~ in my USART IRQ init routine, since configMAX_SYSCALL_INTERRUPT_PRIORITY is defined as 16. It still does not work as expected From my FreeRTOSConfig.h file: ~~~ /* Cortex-M specific definitions. */

ifdef __NVICPRIOBITS

/* __BVICPRIOBITS will be specified when CMSIS is being used. */

define configPRIO_BITS __NVIC_PRIO_BITS

else

define configPRIO_BITS 4 /* 15 priority levels */

endif

define configLIBRARYLOWESTINTERRUPT_PRIORITY 0xf

define configLIBRARYMAXSYSCALLINTERRUPTPRIORITY 1

define configKERNELINTERRUPTPRIORITY ( configLIBRARYLOWESTINTERRUPTPRIORITY << (8 – configPRIOBITS) )

define configMAXSYSCALLINTERRUPTPRIORITY ( configLIBRARYMAXSYSCALLINTERRUPTPRIORITY << (8 – configPRIOBITS) )

define configASSERT( x ) if( ( x ) == 0 ) { taskDISABLE_INTERRUPTS(); for( ;; ); }

//#define configASSERT( x ) if( ( x ) == 0 ) vAssertCalled( FILE, LINE ) ~~~

FreeRTOS ISR API for STM32F411

Okay this might sound stupid and unreasonable but i left the priorities as they were (unchanged), and i removed taskENTER_CRITICAL(); and taskEXIT_CRITICAL(); calls and it worked as expected. I cannot explain why. And i still have this feeling that something is still terrribly wrong, since: a) the default NVIC priority of USART2 is set to 0 , b) configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY is set to 5.

FreeRTOS ISR API for STM32F411

You should not be using taskENTERCRITICAL() or taskEXITCRITICAL() in the interrupt handler anyway so it makes sense that removing those calls prevent unexpected behavior. They don’t end in FromISR, and they are the only functions that are allowed. FreeRTOS and the hardware manage the interrupt nesting for you. Which FreeRTOS version are you using? I think your IRQ priorities are screwy and using V10 with configASSERT() enabled may help find errors.

FreeRTOS ISR API for STM32F411

Thanks for the quick response, i am using FreeRTOSv9, and cofigASSERT is also enabled as I mentioned previously. Just so that i understand correct, if there is a critical section inside a IRQ Handler, would it not make sense to use those calls, since i do not want other interrupts to occur.

FreeRTOS ISR API for STM32F411

Although V10 has more asserts to try and catch all interrupt priority issues, even V9 should assert if you call taskENTERCRITICAL() from an interrupt. See line 419 here https://sourceforge.net/p/freertos/code/HEAD/tree/tags/V9.0.0/FreeRTOS/Source/portable/GCC/ARMCM4F/port.c .

FreeRTOS ISR API for STM32F411

V9 has a lot of asserts to try and catch interrupt configuration errs, but V10 has more (I think it checks just about everything, including the number of priority bits configured actually matches the hardware).

FreeRTOS ISR API for STM32F411

So a small update: Its clear to me what was wrong with the critical section calls, kernel is responsible for that purpose, theres no need to do it explicitly in an ISR. However, I still fail to understand fully whats happening with configASSERT; When i compiled and executed in Debug mode, seemed like configASSERT was ignored, but in Release mode , it sits in this eternal for loop,configASSERT( x ) if( ( x ) == 0 ) { taskDISABLE_INTERRUPTS(); for( ;; ); } once i commented this out, it works for Release as well.