SAADC oversampling, multiple channels and burst

Hi,

We are using an nRF52832 in a bare-metal project. (No SDK)

We have three input channels to the ADC that we wish to use. These must be oversampled. (256x)

To simplify the code, we would like to have it behave such that we configure the ADC, trigger a sample and get an interrupt when the results have been transfered to RAM by EasyDMA.

However, we find some conflicting information in the specification.

First, it say it can't be done.

Scan mode and oversampling cannot be combined.

 - Section 37.5

Oversampling and scan should not be combined, since oversampling and scan will average over input channels.

- Section 37.5.3

I don't exactly understand what the last one tries to say, but it seems to try to tell me you can get unexpected results.

But then you read about burst and it says:

Scan mode can be combined with BURST=1, if burst is enabled on all channels.

- Section 37.5.3

This seems to imply that it is possible, if you enable burst. It doesn't say, however, if "all channels" are all available channels (0-7), or just the once the enabled. ("A channel is considered enabled if CH[n].PSELP is set." - Section 37.5.4)

Finally, in the scan section it says:

In this mode, the RESULTDONE event signals has the same meaning as DONE when no oversampling takes place.

- Section 37.5.4

The next thing that is unclear to me is what tasks and events are associated with this. For instance, it says that DONE will be generated when a sample is completed. But is this the "256x samples", or a single sample? What is the difference with RESULTDONE?

My concrete questions:

  1. Is it possible to combine oversample and scan, if you enable burst? If so, do you need to enable it on all available channels, or just the active ones?
  2. What tasks do I need to set to start the sampling? Which events should I monitor in my interrupt handler?
  3. Do I need to repeatedly trigger the SAMPLE task? Once per channel, or 256 times per channel?

Thanks in advance!

  • Hi Obbe,

    I haven't looked that much into the ADC spec before. I can find someone who knows this better than I, but just to get a common understanding of it first: it doesn't look that conflicting to me. Scan will iterate through the different channels, and oversample will average over everything, so using both of these will likely not get the effect you want - unless you'd like to get the average over all the channels.

    Setting burst however, with "BURST = 1 the ADC will sample the input 2^OVERSAMPLE times as fast as it can, and scan mode can be combined with BURST=1, if burst is enabled on all channels."

    Is it possible to combine oversample and scan, if you enable burst? If so, do you need to enable it on all available channels, or just the active ones?

    That is an interesting question, as the documentation isn't as explicit about this. I would assume that this only counts for the active ones, but do you see a potential issue with setting it on an inactive one as well?

    What tasks do I need to set to start the sampling? Which events should I monitor in my interrupt handler?

    START, SAMPLE, and RESULTDONE

    "A DONE event signals that one sample has been taken. In this mode, the RESULTDONE event signals that enough conversions have taken place for an oversampled result to get transferred into RAM. Note that both events may occur before the actual value has been transferred into RAM by EasyDMA."

    Do I need to repeatedly trigger the SAMPLE task? Once per channel, or 256 times per channel?

    Just once. Like it says: "for the user it will just appear like the conversion took a bit longer time, but other than that, it is similar to one-shot mode. Scan mode can be combined with BURST=1, if burst is enabled on all channels"

    Regards,

    Elfving

  • Hi Elfving,

    Thanks for the response!

    I agree its reasonable that just Oversampling + Scan does not work, but I can't figure out if Oversampling + Scan + Burst is a valid combination with expected results. I can activate BURST on the other channels too, as long as it doesn't have unexpected side-effects I've missed. (Such as now being counted as an active channel by Scan)

    Regarding the events; if RESULTDONE is (potentially) signaled before EasyDMA has transferred the results to PTR, how do I check that? When is END signaled? By the way, what is the difference between START and SAMPLE?

    Just to verify; you mean once per channel, or once per all channels? (I.e., if I have three channels, do I need to request SAMPLE one or three times to get all results into PTR)

    I've tried implementing this, and with a single channel it seems to work. But if I enable Oversample + Scan + Burst, I only get DONE and RESULTDONE, but not END. (With a single channel I got END as well) So I'm not sure if what I was observering was that the combination does not work, that I was expecting the wrong events, or if there is something else missing in my configuration.

  • obbe said:
    I agree its reasonable that just Oversampling + Scan does not work, but I can't figure out if Oversampling + Scan + Burst is a valid combination with expected results.

    That's the thing I find the datasheet to be somewhat clearer with: try disabling oversample, but selecting burst. The datasheet first gives the general rule that oversampling can't be used with scan, then after it presents the variations, it says that this one variation is an exception to the previous rule - even  though burst does provide some oversampling features. 

    obbe said:
    I can activate BURST on the other channels too, as long as it doesn't have unexpected side-effects I've missed. (Such as now being counted as an active channel by Scan)

    That is the thing I am uncertain about. Did you try this?

    obbe said:
    Regarding the events; if RESULTDONE is (potentially) signaled before EasyDMA has transferred the results to PTR, how do I check that? When is END signaled?

    Regarding the first, I guess you would need to wait on the END signal.

    "the ADC will generate an END event when it has filled up the Result buffer"

    "The EasyDMA will have finished accessing the RAM when the END"

    obbe said:
    By the way, what is the difference between START and SAMPLE?

    This seems a bit more clear-cut here, so I assume I am misunderstanding some nuances you are referring to.

    "TASKS_START: Start the ADC and prepare the result buffer in RAM"

    "TASKS_SAMPLE: Take one ADC sample, if scan is enabled all channels are sampled"

    obbe said:
    I've tried implementing this, and with a single channel it seems to work. But if I enable Oversample + Scan + Burst, I only get DONE and RESULTDONE, but not END. (With a single channel I got END as well) So I'm not sure if what I was observering was that the combination does not work, that I was expecting the wrong events, or if there is something else missing in my configuration.

    With just scan and burst, my understanding is that it should function as a default scan mode. You should get the END signal when things have finished transfered. Could you try this?

    Regards,

    Elfving

  • Hi,

    Thanks again for your answer. Here are some more concrete details.

    These are the steps and results I'm observing.

    1. Configure ADC.
        - `RESOLUTION` = `0x00000002`
        - `OVERSAMPLE` = `0x00000008`
        - `ENABLE` = `0x00000001`
        - `INTEN` = `0x0000000F`
    2. Start calibration 
        - `INTEN` = `0x0000001F`
        - `STARTCALIBRATE = 1`
    3. Interrupt
         - `EVENTS_STARTED` = `0`
         - `EVENTS_DONE` = `1`
         - `EVENTS_RESULTDONE` = `1`
         - `EVENTS_CALIBRATEDONE` = `1`
         - `EVENTS_CALIBRATEDONE` = `1`
             - → `TASKS_STOP` = `1` (see errata)
     4. Enable channel `x`
         - `CH[x].CONFIG` = `0x01050003`
     5. Start conversion
         - `TASKS_START = 1`
         - `TASKS_SAMPLE = 1`
     6. Interrupt
         - `EVENTS_STARTED` = `1`
         - `EVENTS_DONE` = `1`
         - `EVENTS_RESULTDONE` = `1`
         - `EVENTS_END` = `1`
         - `EVENTS_CALIBRATEDONE` = `0`

    This works when running with a debug probe attached. I.e. I can see that when I periodically poll the status of my AdcDriver it has finished sampling and interrupts have fired.

    But if I don't debug but instead look at our SWO logs, I get the `STARTED` and `DONE` events, but never the `RESULTDONE` or `END` events. `STARTED` and `DONE` seem to trigger pretty much immediately.

    Edit: I'm an idiot. I didn't get second interrupt when sampling, because I disabled the interrupts when conversion was done. If I set them before the TASKS_START and TASKS_SAMPLE, I get repeated interrupts, but only with a debugger attached. In free-running it doesn't trigger.

    I've edited the reply to make more sense.

  • Thanks for the patience, I've asked the relevant R&D team about the ADC questions, and I'll let you know once I hear from them btw.

    obbe said:
    I get repeated interrupts, but only with a debugger attached. In free-running it doesn't trigger.

    I guess this could be multiple things, but the immediate thing that comes to mind when something only works when the debugger is attached is crystal configuration. Was this a custom board or a DK? It could also be related to eg. this or this.

    Regards,

    Elfving

Related