Beware that this post is related to an SDK in maintenance mode
More Info: Consider nRF Connect SDK for new designs

Lost sdh ble events with freeRTOS task

Good day,
Today I decided to share one solution that may save your nerves. Quite often there are questions on this forum related to the fact that sometimes radio events are "lost".

In the course of long-term observations, I found out that an interrupt occurs, but it does not fall into the task. The reason turned out to be quite banal: two events occurred very close to each other in time. 

So, using the standard code offered by Nordic, I quite often caught an error related to the loss of events.

void SD_EVT_IRQHandler(void)
{
    BaseType_t yield_req = pdFALSE;
    vTaskNotifyGiveFromISR(m_softdevice_task, &yield_req);
    /* Switch the task if required. */
    portYIELD_FROM_ISR(yield_req);
}


/* 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, incase the EVENT occured before creating this task */
        (void) ulTaskNotifyTake(pdTRUE,         /* Clear the notification value before exiting (equivalent to the binary semaphore). */
                                portMAX_DELAY); /* Block indefinitely (INCLUDE_vTaskSuspend has to be enabled).*/
    }
}

So I made assumptions: this code does not take into account that events can occur quite densely in time. resetting the flag on exit is a weak point, because if event B occurs at the time of processing event A, then clearing the flag on exit from the handler function will reset them both. while this is formal, the stack will not process the event and, accordingly, will "hang". I don't have analyzer records left from that time, so I'll draw (always draw if you can't put it into words))).

So, my change is that the task notification flag must be reset immediately upon entering the task. then for the subsequent event blocking will not happen and it will be correctly handled.

xTaskNotifyWait(0xffff,     // clear all flags on enter
                0x00,       // save all flags on exit
                NULL, 
                portMAX_DELAY); // block for next trigger, if all flags clear. if flags not's clear block is skipped

my testing revealed no problems with this code refinement. I understand that this SDK is no longer being developed, but perhaps this will help those who are faced with this problem.

Best Regards,

Parents Reply Children
No Data
Related