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

Observer under FreeRTOS: Events stop coming after a few minutes.

Observer under FreeRTOS: Events stop coming after a few minutes.

Hi there,

I am using the nRF52832 as simple observer running under FreeRTOS on a custom board. The built is based on the SDK HRM peripheral example. I have stripped down my code so that only the task left is the one in which the SD runs. I have a handler for BLE_GAP_EVT_ADV_REPORT events installed. Nothing else is running (no UART or any other peripheral).

The SD stops calling my handler after a few minutes (completely random) if the runtime of the handler (artificial busy-loop) is longer than about 300us which, I guess, is roughly the minimum distance between two advertising reports minus caller overhead. The SD throws no hardfault or any other error, the BLE events just stop coming in. FreeRTOS continues running normally. With the handler runtime below 200us, everything is fine. Strangely, runtimes >>300us (e.g. 10ms) do not accelerate the occurrence of the error.

Any idea where this might come from?

Thanks.

Parents
  • found a race condition in nrf_sdh_freertos.c file

    softdevice task() tries to pull events from SD and then suspends the tasks unconditionally until the SD_EVT_IRQHandler resumes it.

    But, if the below happens

    nrf_sdh_evts_poll(); 

    ##### Interrupted by SD_EVT_IRQHandler which does a TaskResume##

    ### but when the context comes back to softdevice_task() it still suspends itself####


    vTaskSuspend(NULL);

    ###at this point we have lost the chance to enable the scanner again###

    SOLUTION

    replace  the task controls to TaskNotification as below

    void SD_EVT_IRQHandler(void)
    {
         BaseType_t xYieldRequired;
    
         //xYieldRequired = xTaskResumeFromISR( m_softdevice_task );
         vTaskNotifyGiveFromISR(m_softdevice_task, &xYieldRequired);
    
         if( xYieldRequired == pdTRUE )
         {
             portYIELD_FROM_ISR(xYieldRequired);
         }
    }
    
    
    /* This function gets events from the SoftDevice and processes them. */
    static void softdevice_task(void * pvParameter)
    {
        NRF_LOG_DEBUG("Enter softdevice_task.");
    
        if (m_task_hook != NULL)
        {
            m_task_hook(pvParameter);
        }
    
        while (true)
        {
            nrf_sdh_evts_poll(); // Let the handlers run first, in case the EVENT occured before creating this task.
            //vTaskSuspend(NULL);
    
          (void) ulTaskNotifyTake(pdTRUE,         /* Clear the notification value before exiting (equivalent to the binary semaphore). */
                          portMAX_DELAY); /* Block indefinitely (INCLUDE_vTaskSuspend has to be enabled).*/
    
        }
    }
    

    I am pretty sure this will fix the problem.

Reply
  • found a race condition in nrf_sdh_freertos.c file

    softdevice task() tries to pull events from SD and then suspends the tasks unconditionally until the SD_EVT_IRQHandler resumes it.

    But, if the below happens

    nrf_sdh_evts_poll(); 

    ##### Interrupted by SD_EVT_IRQHandler which does a TaskResume##

    ### but when the context comes back to softdevice_task() it still suspends itself####


    vTaskSuspend(NULL);

    ###at this point we have lost the chance to enable the scanner again###

    SOLUTION

    replace  the task controls to TaskNotification as below

    void SD_EVT_IRQHandler(void)
    {
         BaseType_t xYieldRequired;
    
         //xYieldRequired = xTaskResumeFromISR( m_softdevice_task );
         vTaskNotifyGiveFromISR(m_softdevice_task, &xYieldRequired);
    
         if( xYieldRequired == pdTRUE )
         {
             portYIELD_FROM_ISR(xYieldRequired);
         }
    }
    
    
    /* This function gets events from the SoftDevice and processes them. */
    static void softdevice_task(void * pvParameter)
    {
        NRF_LOG_DEBUG("Enter softdevice_task.");
    
        if (m_task_hook != NULL)
        {
            m_task_hook(pvParameter);
        }
    
        while (true)
        {
            nrf_sdh_evts_poll(); // Let the handlers run first, in case the EVENT occured before creating this task.
            //vTaskSuspend(NULL);
    
          (void) ulTaskNotifyTake(pdTRUE,         /* Clear the notification value before exiting (equivalent to the binary semaphore). */
                          portMAX_DELAY); /* Block indefinitely (INCLUDE_vTaskSuspend has to be enabled).*/
    
        }
    }
    

    I am pretty sure this will fix the problem.

Children
Related