NRF54L15 ADC sampling gets stuck inside adc_read

Hi Dev,

Development platform: NRF54L15 + NCS 3.2.3

We are facing an issue with ADC sampling. The code occasionally gets stuck/hangs inside the adc_read function. This issue does not occur every time — it happens sporadically after long-term operation or under certain unknown conditions.

I have already narrowed down the issue and confirmed that the hang occurs inside adc_read.

Here is the code snippet:

c
int adc_single_channel_poll(uint8_t chan)
{
    if (chan >= ADC_CH_COUNT) return -EINVAL;

    int16_t             local_sample = 0;
    struct adc_sequence seq          = {
                 .channels    = BIT(channel_cfgs[chan].channel_id),
                 .buffer      = &local_sample,
                 .buffer_size = sizeof(local_sample),
                 .resolution  = 12,
    };

    int err = adc_read(adc_dev, &seq);

    if (likely(err == 0))
    {
        adc_raw[chan] = (local_sample < 0) ? 0 : local_sample;
    }

    return err;
}

The execution gets stuck at adc_read() and never returns.

Could you please help clarify:

  1. Is this a driver-layer bug in the ADC driver provided with NCS 3.2.3?

  2. Or could it be a hardware issue with the NRF54L15 device itself?

  3. Are there any known issues or errata related to ADC on NRF54L15 that could cause occasional hangs in adc_read?

Any suggestions on how to further debug or work around this issue would be greatly appreciated.

Thanks,
Chen

Parents
  • Buffer size is usually the number of elements, not the number of bytes; the code as written will corrupt the stack, perhaps try this:

      .buffer_size = sizeof(local_sample)/sizeof(int16_t),

    For a more general case, I would recommend this form:

      .buffer_size = sizeof(local_sample)/sizeof(local_sample[0]),

  • Thank you for looking into this.

    However, I believe the suggestion about buffer_size may not be correct for the Zephyr ADC API used in NCS.

    According to the Zephyr documentation for struct adc_sequence, the buffer_size field is explicitly defined as:

    "Specifies the actual size of the buffer pointed by the 'buffer' field (in bytes)."

    So using sizeof(local_sample) is correct because local_sample is an int16_t (2 bytes), and we are taking a single sample.

    If I changed it to sizeof(local_sample) / sizeof(int16_t), that would evaluate to 1 byte, which is insufficient and would likely cause a buffer overflow or driver error.

    For reference, here is the relevant struct definition from the Zephyr ADC API:

    c
    struct adc_sequence {
        ...
        /**
         * Specifies the actual size of the buffer pointed by the "buffer"
         * field **(in bytes)**.
         */
        size_t buffer_size;
        ...
    };

    So the original code using sizeof(local_sample) is correct for a single int16_t sample.

    The hang issue likely has another root cause. Any other suggestions would be greatly appreciated.

    Thanks,
    Chen

Reply
  • Thank you for looking into this.

    However, I believe the suggestion about buffer_size may not be correct for the Zephyr ADC API used in NCS.

    According to the Zephyr documentation for struct adc_sequence, the buffer_size field is explicitly defined as:

    "Specifies the actual size of the buffer pointed by the 'buffer' field (in bytes)."

    So using sizeof(local_sample) is correct because local_sample is an int16_t (2 bytes), and we are taking a single sample.

    If I changed it to sizeof(local_sample) / sizeof(int16_t), that would evaluate to 1 byte, which is insufficient and would likely cause a buffer overflow or driver error.

    For reference, here is the relevant struct definition from the Zephyr ADC API:

    c
    struct adc_sequence {
        ...
        /**
         * Specifies the actual size of the buffer pointed by the "buffer"
         * field **(in bytes)**.
         */
        size_t buffer_size;
        ...
    };

    So the original code using sizeof(local_sample) is correct for a single int16_t sample.

    The hang issue likely has another root cause. Any other suggestions would be greatly appreciated.

    Thanks,
    Chen

Children
  • How curious; one would expect Zephyr to use DMA for the SAADC transfer, and the SAADC can only transfer 16-bit values regardless of the sample bit setting (8-, 10-, 12- or 14-bit). I would be suspicious about that description, probably correct in other architectures .. but then I use bare-metal for nRF SAADC and other peripherals.

    If using nRFx I would think the size-in-bytes description would be incorrect

    Edit: Belay that comment; I just realised that the nRF54L15 uses byte counts whereas the nRF52840 uses 16-bit word counts, hadn't noticed that hardware change:

    nRF52840: Maximum number of 16-bit samples to be written to output RAM buffer
    nRF54L15: Maximum number of buffer bytes to transfer. Note that one sample is two bytes

  • Has this or have you found a fix for this issue? I'm also experiencing the same problems, of doing an ADC read seems to hang. This is randomly, as I do an ADC read every 4 seconds. 

    I've left my device running over night, and the same thing has happened.

    I'm using SDK 3.1.1, with the nRF5340

  • Thanks @hmolesworth for the detailed analysis on SAADC transfer details. The difference you pointed out — nRF54L15 using byte count while nRF52840 uses 16‑bit word count — is indeed an important hardware change worth noting.

    However, the issue I'm facing is that adc_read() occasionally hangs completely and never returns, rather than a data length misconfiguration causing corrupted samples. I've already checked buffer size and alignment, but the problem still occurs randomly.

    Also thanks @jerome.sc for the feedback. Seeing that you're experiencing the same hang on nRF5340 with SDK 3.1.1 makes me more inclined to think this might not be nRF54L15‑specific, but rather a potential issue in the Zephyr ADC driver or the SAADC hardware state machine locking up under certain conditions.

    As of now, I still haven't found the root cause and am waiting for further response from Nordic official support. My current temporary workaround is to monitor the ADC hang and trigger a watchdog software reset.

    If you have any further debugging progress (e.g., checking register states to identify where it gets stuck), please do share.

  • @ I've switched from Zephyr API ADC to the nrfx drivers. It's hard to say if this has fixed anything, but I've ran my device for 3 hours without it crashing.

    I haven't done low level debugging, but if it does crash again, then I will have to.

    Unlike you, if the ADC hangs I can't do a software reset, as this will defeat the purpose of my application.

    Hopefully the Nordic team returns with a solution.

    If you do find a fix, please post it on here, as I'm often checking for updates on this thread.

Related