SAADC Calibration Lock Up

I am trying to implement a periodic calibration routine that is transparent to upper layers of my application.

I have the SAADC set up to continuously sample one channel (oversample X4) and I am dual buffering into two 512-byte buffers. I call calibration every 5 seconds using a Ticker provided by mbed.

My calibration routine, executed in the interrupt context, used to look like this:

void calibrate_saadc(void) { 

while(nrf_drv_saadc_calibrate_offset() != NRF_SUCCESS);


What I found was that it would hang on the while() loop since the ADC would stay busy... not sure why.

So then I tried changing it to trigger calibration in the SAADC driver callback (which should get executed when nrf_drv_saadc_abort() is called, it will report a smaller buffer than expected). If the buffer was smaller than expected (meaning it was aborted for calibration), I then execute the while(nrf_drv_saadc_calibrate_offset() != NRF_SUCCESS) line...

However, this line never ends up getting called and my application just halts since there are no more SAADC events to drive execution.

Could someone explain the events the SAADC driver/HAL should see for calibration to be carried out properly?

EDIT: I have viewed the examples in the github repository found here:

They flag the calibration event and execute it in the thread context. I am writing a low level driver that doesn't currently have a convenient way to defer processing to a thread with the current structure. How is the nrf_drv_saadc_calibrate_offset() function supposed to be used?

  • What priority is the Ticker running at? If it runs at a higher or equal priority to the SAADC, the SAADC IRQ handler will not be able to run to pull the driver out of BUSY state.

    Also make sure you do not init the buffers again in the SAADC handler after a abort call. This will put the SAADC driver back in BUSY state. You can set a flag in the ticker handler when you call abort and check this flag before setting up buffers.

Reply Children