This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

SAADC EasyDMA gets out of sync

I am using a timer to trigger the SAADC via PPI, and scan 4 channels to EasyDMA, which alternates between two buffers. This all works great most of the time, but if I halt with the debugger or if other areas of my code prevent the interrupt from being serviced in time, sometimes it gets stuck in a state where the DMA sync is off, so the 4 channels don't go to the correct locations and each conversion ends at the wrong time (DMA fills up, causing an interrupt). This is not a major problem because I can detect it and I thought I would be able to reset everything to re-synchronize, but this resetting usually doesn't help. Here's what I'm doing to reset:

    nrfx_timer_pause(&IR_DRV_AND_SAMPLE_TIMER);
    nrfx_saadc_uninit();
    nrf_saadc_buffer_init(nullptr, 0);  // Just in case setting the EasyDMA MAXCNT to 0 resets it

    // Configure the whole SAADC as usual (code omitted)
    
    // Setup two buffers, since we want one to still be active while we are processing the data from the first:
    err_code = nrf_drv_saadc_buffer_convert(m_buffer_pool[0], ADC_NUM_SCAN_CHS);
    APP_ERROR_CHECK(err_code);
    err_code = nrf_drv_saadc_buffer_convert(m_buffer_pool[1], ADC_NUM_SCAN_CHS);
    APP_ERROR_CHECK(err_code);

    nrfx_timer_clear(&IR_DRV_AND_SAMPLE_TIMER);
    nrf_drv_timer_enable(&IR_DRV_AND_SAMPLE_TIMER);

Are nrfx_saadc_uninit() and nrf_saadc_buffer_init(nullptr, 0) somehow not sufficient to reset the EasyDMA?

  • Hello chris-ergo,

    Please have a look at the answer by my colleague Jørgen in this ticket. It sounds to me like the issue you describe matches well with the criterias that Jørgen detail, and so the workaround he details should resolve your issue.
    Please do not hesitate to let me know if this should not be the case.

    Best regards,
    Karl

  • This seems to have eliminated the DMA getting out of sync. I unfortunately had to edit nrfx_saadc.c to remove the START task triggers in nrfx_saadc_buffer_convert() and nrfx_saadc_irq_handler(). While I was in there, I noticed that the way double buffering is handled doesn't actually gain me any extra time for interrupt latency since it does the buffer swap after an END event instead of a STARTED event.

    I noticed that the NRFX_SAADC_API_V2 seems to fix both of these problems. Should I consider changing to this? The saadc example in the SDK still uses the old API; does that mean the V2 isn't really supported?

  • Hello again, Chris

    I am glad to hear that this fixed the buffer shift issues!
    I would not recommend that you make changes directly into the nrfx_saadc driver, since this may break the driver or force it into an invalid state that it can not recover from.

    I would recommend that you make use of the improved NRFX_SAADC_API_V2, yes. The V2 is fully supported - the example has just not been updated to use it. You can find some examples using the V2 in the NordicPlayground github repository
    You could make use of the v2 by adding NRFX_SAADC_API_V2 into your project option's preprocessor defines for the common configuration. The nrfx_saadc v2 api has unfortunately not had its documentation updated in Infocenter yet, but the information is available in the header file.

    Best regards,
    Karl

Related