This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

FreeRTOS Queues seem broken.

Hi,

The xQueueReceive function in FreeRTOS seems to be broken, when a non-zero timeout is specified.

Example, I'm trying to create and ordered output mechanism for the UART using a task and a FIFO queue:

static void uart_output_task(void * arg)
{
    for (;;)
    {
        struct SerialPortOutput spo;

        printf("uart_output_task: Waiting for data to send, come on.\n");
        
        // Block waiting on data in the queue.
        if (xQueueReceive(m_uart_output_queue, &spo, 100))
        {
            printf("Sending data to UART.\n");
            
            // Send data to UART.
            nrf_drv_uart_tx(spo.output, spo.length);
        }
        else
        {
            printf("uart_output_task: xQueueReceive had nothing to send.\n");
        }
        
        // char test[8] = "test\r\n";
        // nrf_drv_uart_tx(test, 6);
    }
}

If I specify a timeout to the xQueueReceive method (in this case 100 ticks), the task prints the first printf() and stops forever while waiting. I should be seeing that printf() every 100 ticks. If I set the queue receive timeout to 0, it loops appropriately, but this is of course not the behavior I want. This also happens if I set it to portDELAY_MAX.

Thanks, Max

Parents
  • Unbelievable. The problem was that the default configTOTAL_HEAP_SIZE

    #define configTOTAL_HEAP_SIZE                                                     ( 4096 )
    

    Breaks after only 2 user tasks have been implemented. Trying to start a third task causes vTaskStartScheduler to fail.

    Reconfiguring this, for now, to:

    #define configTOTAL_HEAP_SIZE                                                     ( 8192 )
    

    Fixes the problem.

    So it's not a problem in the Queue. Thanks for the help guys.

    Here's the sample code with gdb trace:

    /**@brief Function for application main entry.
     */
    int main(void)
    {
        // Do not start any interrupt that uses system functions before system initialisation.
        // The best solution is to start the OS before any other initalisation.
    
        // Init a semaphore for the BLE thread.
        m_ble_event_ready = xSemaphoreCreateBinary();
    
        if(NULL == m_ble_event_ready)
        {
            APP_ERROR_HANDLER(NRF_ERROR_NO_MEM);
        }
        
        m_uart_output_queue = xQueueCreate(5, sizeof (struct SerialPortOutput));
        
        if (m_uart_output_queue)
        {
            printf("UART output queue created successfully!\n");
        }
        else
        {
            printf("UART output queue could not be created!\n");    
        }
    
        // Start execution.
        if(pdPASS != xTaskCreate(ble_stack_thread, "BLE", 256, NULL, 1, &m_ble_stack_thread))
        {
            APP_ERROR_HANDLER(NRF_ERROR_NO_MEM);
        }
    
        nrf_drv_uart_config_t uart_config = NRF_DRV_UART_DEFAULT_CONFIG;
    
        if (NRF_SUCCESS == nrf_drv_uart_init(&uart_config, uart_event_handler))
        {
            printf("UART initialized properly.\n");
        }
        else
        {
            printf("UART failed to initialize properly.\n");
        }
        
        if (pdPASS != xTaskCreate(uart_output_task, "UART Output Task", 256, NULL, 1, &m_uart_output_thread))
        {
            printf("Out of memory.");
            APP_ERROR_HANDLER(NRF_ERROR_NO_MEM);
        }
    
        if (pdPASS != xTaskCreate(uart_test_task, "Test UART Task", 256, NULL, 1, &m_uart_test_task))
        {
            printf("Out of memory.");
            APP_ERROR_HANDLER(NRF_ERROR_NO_MEM);
        }
        
        /* Activate deep sleep mode */
        // SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
    
        // Start FreeRTOS scheduler.
        vTaskStartScheduler();
    
        while (true)
        {
            printf("Oops.\n");
            APP_ERROR_HANDLER(NRF_ERROR_FORBIDDEN);
        }
    }
    

    gdb output is:

    Breakpoint 1, main () at /home/max/nRF5_SDK_11.0.0_89a8197/examples/ble_peripheral/ble_app_hrs_freertos/main.c:1205
    1205	{
    
    (gdb) break vTaskStartScheduler
    Breakpoint 2 at 0x1e2c0: file /home/max/nRF5_SDK_11.0.0_89a8197/external/freertos/source/tasks.c, line 1544.
    (gdb) continue
    Continuing.
    
    Breakpoint 2, vTaskStartScheduler () at /home/max/nRF5_SDK_11.0.0_89a8197/external/freertos/source/tasks.c:1544
    1544	{
    (gdb) n
    1552			xReturn = xTaskCreate( prvIdleTask, "IDLE", tskIDLE_STACK_SIZE, ( void * ) NULL, ( tskIDLE_PRIORITY | portPRIVILEGE_BIT ), &xIdleTaskHandle ); /*lint !e961 MISRA exception, justified as it is not a redundant explicit cast to all supported compilers. */
    (gdb) n
    1565				xReturn = xTimerCreateTimerTask();
    (gdb) n
    1574		if( xReturn == pdPASS )
    (gdb) n
    main () at /home/max/nRF5_SDK_11.0.0_89a8197/examples/ble_peripheral/ble_app_hrs_freertos/main.c:1304
    1304	        printf("Oops.\n");
    (gdb) 
    
Reply
  • Unbelievable. The problem was that the default configTOTAL_HEAP_SIZE

    #define configTOTAL_HEAP_SIZE                                                     ( 4096 )
    

    Breaks after only 2 user tasks have been implemented. Trying to start a third task causes vTaskStartScheduler to fail.

    Reconfiguring this, for now, to:

    #define configTOTAL_HEAP_SIZE                                                     ( 8192 )
    

    Fixes the problem.

    So it's not a problem in the Queue. Thanks for the help guys.

    Here's the sample code with gdb trace:

    /**@brief Function for application main entry.
     */
    int main(void)
    {
        // Do not start any interrupt that uses system functions before system initialisation.
        // The best solution is to start the OS before any other initalisation.
    
        // Init a semaphore for the BLE thread.
        m_ble_event_ready = xSemaphoreCreateBinary();
    
        if(NULL == m_ble_event_ready)
        {
            APP_ERROR_HANDLER(NRF_ERROR_NO_MEM);
        }
        
        m_uart_output_queue = xQueueCreate(5, sizeof (struct SerialPortOutput));
        
        if (m_uart_output_queue)
        {
            printf("UART output queue created successfully!\n");
        }
        else
        {
            printf("UART output queue could not be created!\n");    
        }
    
        // Start execution.
        if(pdPASS != xTaskCreate(ble_stack_thread, "BLE", 256, NULL, 1, &m_ble_stack_thread))
        {
            APP_ERROR_HANDLER(NRF_ERROR_NO_MEM);
        }
    
        nrf_drv_uart_config_t uart_config = NRF_DRV_UART_DEFAULT_CONFIG;
    
        if (NRF_SUCCESS == nrf_drv_uart_init(&uart_config, uart_event_handler))
        {
            printf("UART initialized properly.\n");
        }
        else
        {
            printf("UART failed to initialize properly.\n");
        }
        
        if (pdPASS != xTaskCreate(uart_output_task, "UART Output Task", 256, NULL, 1, &m_uart_output_thread))
        {
            printf("Out of memory.");
            APP_ERROR_HANDLER(NRF_ERROR_NO_MEM);
        }
    
        if (pdPASS != xTaskCreate(uart_test_task, "Test UART Task", 256, NULL, 1, &m_uart_test_task))
        {
            printf("Out of memory.");
            APP_ERROR_HANDLER(NRF_ERROR_NO_MEM);
        }
        
        /* Activate deep sleep mode */
        // SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
    
        // Start FreeRTOS scheduler.
        vTaskStartScheduler();
    
        while (true)
        {
            printf("Oops.\n");
            APP_ERROR_HANDLER(NRF_ERROR_FORBIDDEN);
        }
    }
    

    gdb output is:

    Breakpoint 1, main () at /home/max/nRF5_SDK_11.0.0_89a8197/examples/ble_peripheral/ble_app_hrs_freertos/main.c:1205
    1205	{
    
    (gdb) break vTaskStartScheduler
    Breakpoint 2 at 0x1e2c0: file /home/max/nRF5_SDK_11.0.0_89a8197/external/freertos/source/tasks.c, line 1544.
    (gdb) continue
    Continuing.
    
    Breakpoint 2, vTaskStartScheduler () at /home/max/nRF5_SDK_11.0.0_89a8197/external/freertos/source/tasks.c:1544
    1544	{
    (gdb) n
    1552			xReturn = xTaskCreate( prvIdleTask, "IDLE", tskIDLE_STACK_SIZE, ( void * ) NULL, ( tskIDLE_PRIORITY | portPRIVILEGE_BIT ), &xIdleTaskHandle ); /*lint !e961 MISRA exception, justified as it is not a redundant explicit cast to all supported compilers. */
    (gdb) n
    1565				xReturn = xTimerCreateTimerTask();
    (gdb) n
    1574		if( xReturn == pdPASS )
    (gdb) n
    main () at /home/max/nRF5_SDK_11.0.0_89a8197/examples/ble_peripheral/ble_app_hrs_freertos/main.c:1304
    1304	        printf("Oops.\n");
    (gdb) 
    
Children
No Data
Related