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

Race condition with ADC driver

There is a race condition in the SAADC driver when using buffer convert.

I am trying to drive ADC at maximum rate to sample 3 ADC channels, and so I call the following in the interrupt routine when it returns from completing an ADC and filling the first buffer. I am using

#define BUFFER_SAMPLES 3

in my application

        /* set up next buffer */
        err_code = nrfx_saadc_buffer_convert(p_buffer, BUFFER_SAMPLES);
        APP_ERROR_CHECK(err_code);
        /* start next sample */
        err_code = nrfx_saadc_sample();
        APP_ERROR_CHECK(err_code);

When I use the following

            channel_config.acq_time = NRF_SAADC_ACQTIME_40US;

the sampling process freezes and does not do any ADC

However if I use

            channel_config.acq_time = NRF_SAADC_ACQTIME_3US;

everything works.

Also if I set

#define BUFFER_SAMPLES 1

everything works.

I did some debugging and noticed if I set breakpoints everything worked, and I iterated to find a critical place. Eventually I determined if I placed a for...loop at ***** in the following the driver would work for 40US.

There appears to be a race condition in setting the NRF_SAADC_TASK_SAMPLE when a long acquisition is set, ie before the first sample is taken and written to RAM (not sure why one sample is taken after issuing a START but looking at memory shows this is the case).

nrfx_err_t nrfx_saadc_sample()
{
        
    NRFX_ASSERT(saadc_m_cb.state != NRFX_DRV_STATE_UNINITIALIZED);

    nrfx_err_t err_code = NRFX_SUCCESS;
    if (saadc_m_cb.adc_state != NRF_SAADC_STATE_BUSY)
    {
        err_code = NRFX_ERROR_INVALID_STATE;
    }
    else if (saadc_m_cb.low_power_mode)
    {
        nrf_saadc_task_trigger(NRF_SAADC_TASK_START);
    }
    else
    {

******
        nrf_saadc_task_trigger(NRF_SAADC_TASK_SAMPLE);
    }

    NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
    return err_code;
}

I have a workaround by using 3US but it would be good for this issue to be fixed.