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

FreeRTOS xSemaphoreTake crash on nRF52x

I have a ADC interrupt that occurs every 17ms and which copies the samples into a global static array, after which GivesFromISR to a binary semaphore so that the samples may be processed with a thread in the foreground. However, if I use xSemaphoreTake instead of xSemaphoreTakeFromISR in the thread the scheduler seems to stop. The strange part is that this only started happening after incorporating a 3rd party function call that uses the global static array modified by the ISR (closed source binary that was linked in the final binary..it does some CMSIS-DSP arm math calcs). Also, the ISR I mentioned is actually a function that gets called from the actual ISR and it is not the ISR it self (sorry for the formatting below)

Some code to better illustrate:

void app_drv_tasks_init(void){
m_sem_samples_event_ready = xSemaphoreCreateBinary(); //static var already declared
if (NULL == m_sem_samples_event_ready)
{
    APP_ERROR_HANDLER(NRF_ERROR_NO_MEM);
}

if (pdPASS != xTaskCreate(saadc_sample_done_event_thread,
                          "SAMPLES", 256, NULL, 1,
                          &m_saadc_sample_done_thread))
{
    APP_ERROR_HANDLER(NRF_ERROR_NO_MEM);
}

/** SAADC Interrupt handler */
void saadc_callback(nrf_drv_saadc_evt_t const * p_event){
if (p_event->type == NRF_DRV_SAADC_EVT_DONE)
{
    ret_code_t err_code;
    err_code = nrf_drv_saadc_buffer_convert(p_event->data.done.p_buffer, SAMPLE_COUNT);
    APP_ERROR_CHECK(err_code);

    for (int i = 0; i < SAMPLE_COUNT; i++)
    {
        m_app_buffer[i] = p_event->data.done.p_buffer[i];
    }
    saadc_sample_done_event_signal();
}

}

uint32_t saadc_sample_done_event_signal(void){
BaseType_t yield_req = pdFALSE;
xSemaphoreGiveFromISR(m_sem_samples_event_ready, &yield_req);
portYIELD_FROM_ISR(yield_req);
return NRF_SUCCESS;

}

void saadc_sample_done_event_thread(void * arg){
uint8_t i;
uint8_t result;
adc_init(); // generates interrupts, but started after scheduler
three_party_code_init();

for(;;)
    {
        // Need to figure out why *FromISR fixes the crash
        while (pdFALSE == xSemaphoreTakeFromISR(m_sem_samples_event_ready, portMAX_DELAY))
        {
        }
        // If this line is removed xSemaphoreTake works fine
        three_party_code(m_app_buffer, &result);
    }

}

int main(void){

app_drv_tasks_init();

SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;

vTaskStartScheduler();

while (true)
{
    APP_ERROR_HANDLER(NRF_ERROR_FORBIDDEN);
}

}

Related