ADC and DMA

05 Feb 2011

Hi,

Does anyone have sample code of how to use MODDMA to perform a number of two channel ADC conversion?

The ADC conversions need to be timer driven (so their sample frequency can be programmed and is xtal stable).

I read the manual and see that the ADC needs some setup that is not include in MODDMA (probably not possible there).

05 Feb 2011

I'll have a quick look and write an example program. Give me a few minutes :)

[edit, well, a bit more than a few minutes, it's 3:30 in the morning and I need some bed :) ]

05 Feb 2011

ok, here it is:- example2.cpp

Note, please update your library as there is a bug fix. For those interested, the bug is actually in the NXP Software Team's DriverLibrary

Specifically, in lpc17xx_gpdma.c at line 128 it says:-

00128         GPDMA_BSIZE_4,                // ADC

This I believe should actually be:-

00128         GPDMA_BSIZE_1,                // ADC

Well, that's how I fixed it anyway in MODDMA!

05 Feb 2011

The example2.cpp test program outputs like this for me (I have +V to p15 and 0v to p16)

example2.cpp output on terminal

ADC with DMA example
====================
Array index 00 : ADC input channel 1 = 0xff1 3.288 volts
Array index 01 : ADC input channel 0 = 0x000 0.000 volts
Array index 02 : ADC input channel 1 = 0xfef 3.286 volts
Array index 03 : ADC input channel 0 = 0x000 0.000 volts
Array index 04 : ADC input channel 1 = 0xfef 3.286 volts
Array index 05 : ADC input channel 0 = 0x000 0.000 volts
Array index 06 : ADC input channel 1 = 0xff1 3.288 volts
Array index 07 : ADC input channel 0 = 0x000 0.000 volts
Array index 08 : ADC input channel 1 = 0xff1 3.288 volts
Array index 09 : ADC input channel 0 = 0x000 0.000 volts
Array index 10 : ADC input channel 1 = 0xfee 3.285 volts
Array index 11 : ADC input channel 0 = 0x000 0.000 volts
Array index 12 : ADC input channel 1 = 0xfee 3.285 volts
Array index 13 : ADC input channel 0 = 0x000 0.000 volts
Array index 14 : ADC input channel 1 = 0xff0 3.287 volts
Array index 15 : ADC input channel 0 = 0x000 0.000 volts
Array index 16 : ADC input channel 1 = 0xfef 3.286 volts
Array index 17 : ADC input channel 0 = 0x000 0.000 volts
Array index 18 : ADC input channel 1 = 0xfee 3.285 volts
Array index 19 : ADC input channel 0 = 0x000 0.000 volts
Array index 20 : ADC input channel 1 = 0xfef 3.286 volts
Array index 21 : ADC input channel 0 = 0x000 0.000 volts
Array index 22 : ADC input channel 1 = 0xff1 3.288 volts
Array index 23 : ADC input channel 0 = 0x000 0.000 volts
Array index 24 : ADC input channel 1 = 0xfef 3.286 volts
Array index 25 : ADC input channel 0 = 0x000 0.000 volts
Array index 26 : ADC input channel 1 = 0xfee 3.285 volts
Array index 27 : ADC input channel 0 = 0x000 0.000 volts
Array index 28 : ADC input channel 1 = 0xfee 3.285 volts
Array index 29 : ADC input channel 0 = 0x000 0.000 volts
Array index 30 : ADC input channel 1 = 0xffd 3.298 volts
Array index 31 : ADC input channel 0 = 0x000 0.000 volts
05 Feb 2011

Hi,

I'll check it out!

Thanks a a lot for spending some time on my problem!

08 Feb 2011

Hi

Works like charm! Thanks again.

Now I only have to tie the ADC conversions to a timer suitable for my needs.

Question: can I re-use the DMA config or must I recreate it before each DMA run?

08 Feb 2011

depends if you create the config with new and then throw away or use a static var to hold it. In some recent code I did I created a mem to mem DMA transfer. The source buffer never changed but the dst buffer did. All I did was create the config once and then just alter the dst each time (and the TransferSize, somes the length of the buffer to copy did alter), call Setup and then Enable. Worked fine for me.

08 Feb 2011

Hi,

So to be safe before re-user just memset a DMA config to zero and refill it and it should work.

08 Feb 2011

MODDMA_Config *conf = new MODDMA_Config;
conf
  ->channelNum    ( MODDMA::Channel_0 )
  ->srcMemAddr    ( 0 )
  ->transferType  ( MODDMA::p2m )
  ->transferWidth ( MODDMA::word )
  ->srcConn       ( MODDMA::ADC )
  ->dstConn       ( 0 )
  ->dmaLLI        ( 0 )
  ->attach_tc     ( &TC0_callback )
  ->attach_err    ( &ERR0_callback )
; // end conf.

while(1) {
  if (control) {
    conf->dstMemAddr( (uint32_t)some_destination );
    conf->transferSize  ( some_size )
    dma.Setup( conf );
    dma.Enable( conf );
  }
}

So long as you don't do delete conf; you'll be fine. Or you could just create a configuration variable in teh normal way:-

MODDMA_Config conf;
conf.channelNum    ( MODDMA::Channel_0 )
conf.srcMemAddr    ( 0 )
conf.transferType  ( MODDMA::p2m )
conf.transferWidth ( MODDMA::word )
conf.srcConn       ( MODDMA::ADC )
conf.dstConn       ( 0 )
conf.dmaLLI        ( 0 )
conf.attach_tc     ( &TC0_callback )
conf.attach_err    ( &ERR0_callback )
; // end conf.

while(1) {
  if (control) {
    conf.dstMemAddr( (uint32_t)some_destination );
    conf.transferSize  ( some_size )
    dma.Setup( &conf );  // <-- Notice, must pass a pointer so use & in this case.
    dma.Enable( &conf ); // <-- Notice, must pass a pointer so use & in this case.
  }
}

08 Feb 2011

Hi,

Thanks for the config code (I always am in a state of war with C pointers).

Btw did you notice the ADC channels are swapped? P15 = ADC0 and if I connect it to ground, it shows up as channel #1 (with a value of 0). And ADC1 values shows up as Channel #0.

I tried channel 0 and 2 and there it's the same, channel 0's value shows up with channel 2's channel number.

11 Feb 2011

Hi Andy,

Any suggestions to fix the ADC Channels mixup?

I already padded the array to see if there was any saving outside the designated area but all was perfect.

I'll try the code with 3 channels to see how that mixed up.

08 Mar 2011

Hi Andy

According to the manual there is a small typo in your example code

LPC_SC->PCLKSEL0 &= ~(3UL << 16) //PCLK_SPI

should read:

LPC_SC->PCLKSEL0 &= ~(3UL << 24) //PCLK_ADC
08 Mar 2011

Fixed in 1.6, thanks.

08 Mar 2011

Hi Andy

Any ideas why the channelnumbers are swapped?

11 Mar 2011

Hi Wim

I'm not sure why you see the channel numbers swapped. In the output above from my test the channels were correct for the voltages I applied to the pins.

The channel number is stored with the 32bit buffer and is derived by int channel = (adcInputBuffer[i] >> 24) & 0x7;

So, I'm not sure why you are seeing a "swap".

Btw, I saw http://mbed.org/forum/mbed/topic/486/?page=1#comment-9970. It's pretty easy to make into a library. Just import the entire program, create a "new folder as library" and move the cpp and h file into that library folder. Then simply publish it.

11 Mar 2011

Actually, I just decided to rerun this and take a closer look. In this test I added an extra AD input, AD0.2 (LPC17xx P0.25, Mbed p17). I applied voltages thus:-

  • p15 - P0.23 - AD0.0 - 0v
  • p16 - P0.24 - AD0.1 - +3.3v
  • p17 - P0.25 - AD0.2 - 1.65v (simple pair of resistors to make a voltage divider).

Imagine my surprise when I got this:-

Program output

Array index 00 : ADC input channel 1 = 0x000 0.000 volts
Array index 01 : ADC input channel 2 = 0xfff 3.299 volts
Array index 02 : ADC input channel 0 = 0x804 1.653 volts
Array index 03 : ADC input channel 1 = 0x000 0.000 volts
Array index 04 : ADC input channel 2 = 0xfff 3.299 volts
Array index 05 : ADC input channel 0 = 0x805 1.654 volts
... <snipped the rest off, just repeats>

I've gone over the code and the register defs and doubled checked. Unless someone else (from Mbed or NXP) can correct me there does appear to be a mismatch in the CHN (AD0GDR 26::24) channel reported for the conversion. I've looked in the errata but can't see any mention specific to this issue. Is this a bug in the LPC1768?

[Edit, to reproduce this experiment for yourself, connect up voltages to p15, p16 and p17 as shown above. Then import the following library and copy example2.cpp into your main.cpp, compile and run. You need a terminal to Serial(USBTX,USBRX) at 115200baud also)]

Import libraryMODDMA

MODDMA GPDMA Controller New features: transfer pins to memory buffer under periodic timer control and send double buffers to DAC

11 Mar 2011

Hi Andy,

Exactly what I observed, the readings are/seem OK but the channel numbers seem to belong to the next sample. It seems like the LPC interrupts and starts with the next sample by adjusting the channel number first. From what I read in the manual the LPC starts with the next conversion as soon as one is completed and interrupts in between.

My experimental code went already wrong with two channels.

Seems like a LPC1768 bug (I've been over your code and cannot find any strange things other that the typo I've reported. I hope this bug is confined to the channel number alone and not to the adjacent bits.

As for the ADC library, if I publish it, it will get my name on in but it's not my work. Is that a problem on this site?

11 Mar 2011

With regards to "republishing" someone elses work. It seems to me that the site's policy is of "use/edit/publish" in that it's fine to have a zillion libraries all with teh same name and all with slight variations and bug fixes (although I don't prefer that model, I would prefer to give my changes/fixes back to teh author and maintain one quality copy). I think the main point is to preserve any copyright statements however.

11 Mar 2011

Andy K wrote:

I've gone over the code and the register defs and doubled checked. Unless someone else (from Mbed or NXP) can correct me there does appear to be a mismatch in the CHN (AD0GDR 26::24) channel reported for the conversion.

Any chance of an overrun condition occurring? What do you see in bit 30 of adcInputBuffer[] entries, Andy?

11 Mar 2011

bit 30 is always 0.

Array index 00 : ADC input channel 1 = 0x000 0.000 volts OV=0
Array index 01 : ADC input channel 2 = 0xfe9 3.281 volts OV=0
Array index 02 : ADC input channel 0 = 0x7f5 1.641 volts OV=0
11 Mar 2011

I get the same results after porting your example to my test bed.

I'm going to play with the code a bit and will report back shortly...

11 Mar 2011

Andy K wrote:

With regards to "republishing" someone elses work. It seems to me that the site's policy is of "use/edit/publish" in that it's fine to have a zillion libraries all with teh same name and all with slight variations and bug fixes (although I don't prefer that model, I would prefer to give my changes/fixes back to teh author and maintain one quality copy). I think the main point is to preserve any copyright statements however.

Exactly what i would like: actively maintained libraries and not tons of copies where you have to find the correct one. I'll wait until Simon adds the bugfix I proposed (the ADC takes 65 PCLK instead of 64 which btw ruins a lot on timing).

11 Mar 2011

Hi Hexley, glad your running your eyes over it too. It's worth making sure you've read http://mbed.org/forum/mbed/topic/1798/?page=1#comment-8918. I decided to revisit that "bug" and re-read the manual to figure out the burst size. The manual says:-

29.6.4 DMA Control

For DMA transfers, only burst requests are supported. The burst size can be set to one in
the DMA channel control register (see Section 31.5.20). If the number of ADC channels is
not equal to one of the other DMA-supported burst sizes (applicable DMA burst sizes are
1, 4, 8 - see Section 31.5.20), set the burst size to one.

so setting it to _1 seems approriate. Playing around with the burst size away from _1 does appear to break it.

I have tried a few various changes such as just read .0, .1 .2 and stop. The reported values appear in the buffer in the correct order but with the wrong channel number.

25.5.1 A/D Control Register (AD0CR - 0x4003 4000)

16 BURST 1  The AD converter does repeated conversions at up to 200 kHz, scanning (if necessary)
            through the pins selected by bits set to ones in the SEL field. The first conversion after the
            start corresponds to the least-significant 1 in the SEL field, then higher numbered 1-bits
            (pins) if applicable. Repeated conversions can be terminated by clearing this bit, but the
            conversion that’s in progress when this bit is cleared will be completed.
            Remark: START bits must be 000 when BURST = 1 or conversions will not start.

This suggests for SEL 7::0 = 0x7 it starts with AD0.0, and then AD0.1 finally AD0.2. As said, the actual analog values read appear in the buffer in that order. It's the CHN (26:24) bits (in the same register as the value) that identify the channel that are incorrect (showing 1, 2, 0 when I expect 0, 1, 2).

12 Mar 2011

Andy, I don't think this has anything to do with your DMA routines.

I've written some tests that use interrupts or polling to retrieve the burst data, with comparable problems.

Here is the polling example. (I used the mbed AnalogIn calls to set up power and configure the pins, then used some of your code to set up burst mode at the hardware level.) The test just reads the first "BURST_CHANNELS" results, comparing the CHN channel number field with a pass counter. If all is well, the first ADC result retrieved will have CHN = 0, matching the pass count of 0; the next result will have CHN = 1, matching the pass count of 1; and so on until all channels have been retrieved.

If no problem is found, a "success" message is printed. If there is a mismatch, the test halts and prints the pass count and the value of CHN that was read.

As of the latest test, the correct channel number/data value pair is returned only if the number of ADC channels set to burst is 1 or 2. If I try 3 or more channels, it gives the offset problem.

[EDIT] Actually, the "working" cases don't work. The index and CHN match, but the associated data value is from a different channel. This is some sort of overrun problem, apparently. More digging is needed :-(

#include "mbed.h"

Serial pc(USBTX, USBRX);
AnalogIn ch0(p15);
AnalogIn ch1(p16);
AnalogIn ch2(p17);

#define BURST_CHANNELS 2    // Works for 1 and 2, fails for 3 and up

int main() {
    int testing = 1;
    int results, channel, overrun, match;
    int passes = 0;
    
    // Setup the serial port to print out results.
    pc.baud(921600);
           
    // Enable the ADC, 12MHz,  the final term should be (2**BURST_CHANNELS - 1)
    LPC_ADC->ADCR  = (1UL << 21) | (1UL << 8) | (3UL << 0); 
    
    // Enable burst mode on selected inputs
    LPC_ADC->ADCR |= (1UL << 16); 
    
    pc.printf("Starting test\r\n");
    
    while (testing) {    
        results = LPC_ADC->ADGDR;
        if(results & (1ul << 31) ) {
            // DONE flag is set, so determine channel from CHN bits
            channel = (results >> 24) & 7;
            overrun = (results & (1ul << 30)) ? 1 : 0;
            match = (channel == passes);
            if(!match) {
                pc.printf("Mismatch at pass = %d, CHN = %d. Terminating test.\r\n", passes, channel);
                testing = 0;
            }
            else if(++passes == BURST_CHANNELS) {
                pc.printf("Test completed successfully.\r\n");
                testing = 0;                
            }
        }
    }       
}
12 Mar 2011

Just for the record I have finally got to the bottom of the channel number problem. However, my write up will take a while so I will post it later. Just wanted to make a note here for those looking into it that I will be posting again soon the results of my experiments.

[Edit: P.S. it's going to be a long post.]

12 Mar 2011

Sorry to hijack the thread, but can someone explain what burst mode does. Specifically how it's different from the regular conversions. As I understand it, when you use burst mode, the conversions don't block for the 65 conversion cycles. Is that correct?

12 Mar 2011

In burst mode, the ADC does back-to-back conversions on the specified channels. No trigger is needed (or allowed). The channels cycle through continuously until burst mode is turned off.

I guess its advantage is in cases where you always want to convert several channels at a time. Then it saves you having to specify a new channel and restart the conversion after each channel. Not a huge advantage IMHO, but maybe there are other use cases that are more striking.

Anyway, results are stored in the results registers, and the corresponding DONE flags are set. If the user doesn't read a result register before it is reloaded on the next go-around, OVERRUN is set.

In principle, the ADC can interrupt every time a conversion completes, and that channel's data plus the channel number itself may be read from the global results register. Or you can poll, as shown in my snippet above (though there are issues that Andy is investigating). But interrupts are better if you are concerned about blocking.

There is some demo code available for interrupt-driven burst mode conversion. See http://mbed.org/forum/mbed/topic/486/.

hth

13 Mar 2011

Burst mode problems

This forum thread has thrown up an odd problem with reading the CHN(26::24) channel number from the ADGDR register. After some investigation (and oddly the solution came to me while driving my son to a birthday party rather than banging the keyboard) I realised what the root cause is. This issue is only an issue if you are using back-to-back burst mode.

I'm not going to describe the problem, there are enough posts in this thread that describe it. But the solution is hidden in the results:-

Progam output

Array index 00 : ADC input channel 1 = 0x000 0.000 volts OV=0
Array index 01 : ADC input channel 2 = 0xfe9 3.281 volts OV=0
Array index 02 : ADC input channel 0 = 0x7f5 1.641 volts OV=0

What I expected here was channel 0, 1, 2 but we got 1, 2, 0. What we are actually seeing here is the results of ADDR0, ADDR1 and ADDR2 however, the channel number isn't latched into ADGDR because the ADGDR is not a register, it's an amalgmation of various pieces of information. So what we actually are seeing is a channel result but the channel number is the currently converting channel, not the channel that made the conversion.

The proof is simple. Lowering the ADC clock rate down a a much lower level (thus spreading out the conversion times) suddenly makes it work as expected. After much trial and error I found that at around 8Mhz sampling rate all works fine. But as we tip over the 8Mhz limit suddenly the channel number begins to slip because a new conversion starts before ADGDR is read.

At first glance one might expect the overrun bit to be set. However, the next conversion isn't on the channel we are about to read, it's moved on. The ADGDR overrun bit is a copy of "the last channel converted" and this information appears to be conserved (lateched). It's the CHN(26::24) that doesn't get preserved (latched).

Oddly enough, after experimenting I found that the ADC conversion clock frequency differs with regards to the method of reading the ADGDR. I tried three basic methods.

  1. Reading the ADGDR within main's while(1) loop (polling)
  2. Reading the ADGDR by setting up interrupts
  3. Reading the ADGDR using the GPDMA system.

In all the following examples we sample AD0.0, AD0.1 and AD0.2 with known voltages applied to each (Mbed p15, p16 and p17) in burst mode. Setup is ommitted for clarity in code snippets.

Polling

OK, lets look at a simple real time polling example (the one I used):-

    int limit = 0; 
    while (1) {    
        uint32_t adval = LPC_ADC->ADGDR;
        if(adval & (1UL << 31) && limit < 9 ) {
            // DONE flag is set, so determine channel from CHN bits
            channel = (adval >> 24) & 7;            
            overrun = (adval & (1UL << 30)) ? 1 : 0;
            int value = (adval >> 4) & 0xFFF;
            double fVal = 3.3 * (double)((double)value) / ((double)0x1000); // scale to 0v to 3.3v 
            pc.printf("ADC input (channel=%d) = 0x%03x %01.3f volts OV=%d\n", channel, value, fVal, overrun);
            limit++; // Just used to prevent printf()ing forever, just display 9 conversions.
        }
    }       

Now, it's worth noting that I used my MODSERIAL library for the serial port with a large TX buffer so that printf() didn't skew things too much. The "real time" processing portion of this is minimal. So, playing with ADCR's CLKDIV(15:8) what did I find? Well, I started loose channel information at around 184.6kHz (yes, you read that right, kilohertz, no where near the 12MHz one would normally run the ADC conversion clock). Given that simple piece of information I am not even going to bother continue with the polling scenorio. Suffice to say, polling with multiple channels in burst mode is simple not an option. So, lets move onto the more obvious solution, interrupts.

Interrupt driven system

Once a conversion is complete it is possible for the ADC_Handler interrupt service routine (ISR) to be invoked. Once inside the ISR we have two methods of getting the data we need.

Method 1

    uint32_t stat = LPC_ADC->ADSTAT;
    if     (stat & 0x01) { values[limit] = LPC_ADC->ADDR0; ch[limit] = 0; }
    else if(stat & 0x02) { values[limit] = LPC_ADC->ADDR1; ch[limit] = 1; }
    else if(stat & 0x04) { values[limit] = LPC_ADC->ADDR2; ch[limit] = 2; }
    else if(stat & 0x08) { values[limit] = LPC_ADC->ADDR3; ch[limit] = 3; }
    else if(stat & 0x10) { values[limit] = LPC_ADC->ADDR4; ch[limit] = 4; }
    else if(stat & 0x20) { values[limit] = LPC_ADC->ADDR5; ch[limit] = 5; }
    else if(stat & 0x40) { values[limit] = LPC_ADC->ADDR6; ch[limit] = 6; }
    else if(stat & 0x80) { values[limit] = LPC_ADC->ADDR7; ch[limit] = 7; }
    limit++;
    if (limit == 9) {
        NVIC_DisableIRQ(ADC_IRQn);
    }

Method 2

    if (limit < 9) {
        values[limit] = LPC_ADC->ADGDR;
        ch[limit] = (values[limit] >> 24) & 0x7;
        // Reading ADGDR does not reset the DONE bit and so alone
        // will not clear the interrupt. The only way to clear it
        // is to either read ADGDR and write ADCR or by reading 
        // the ADDRx register directly. Since we are in burst mode
        // then we shouldn't be writing the ADCR so we are left with
        // a manual read of the actual ADDRx. 
        uint32_t trash __attribute__((unused));
        switch (ch[limit]) { // We might just aswell use stat like above.
            case 0: trash = LPC_ADC->ADDR0; break;
            case 1: trash = LPC_ADC->ADDR1; break;
            case 2: trash = LPC_ADC->ADDR2; break;
            case 3: trash = LPC_ADC->ADDR3; break;
            case 4: trash = LPC_ADC->ADDR4; break;
            case 5: trash = LPC_ADC->ADDR5; break;
            case 6: trash = LPC_ADC->ADDR6; break;        
            case 7: trash = LPC_ADC->ADDR7; break;
        }
        limit++;
    }
  
    if (limit == 9) {
        NVIC_DisableIRQ(ADC_IRQn);
    }    

Method 1

As expected this method produced a flawless set of results right up to 12MHz. However, it's worth noting here that in the ISR we are not doing any real time processing. We are just storing the results into a buffer. More about this in the concluesion at the end of this article.

Method 2

If you have looked at the code for Method 1 it should be obvious, why would you do this? Well, here's why. Even without doing any real time processing but only storing to a buffer the channel information within ADGDR began to slip at 3MHz. Below that ADC clock conversion frequency we kept value channel information. At or above that it became meaningless. And given that to clear the interrupt condition we still needed to read the ADDRx register this method is pointless. I did it for the sake of completeness of this investigation.

Using the GPDMA

Now, it's onto using the GPDMA to pipe the ADC results to a memory buffer, the method that cause this entire problem to be highlighted. By now you should have an understanding of the issues. It's all down to the ADC conversion frequency and just when ADGDR is read. And what it boils down to is even using the GPDMA and having the INT REQ line from the ADC feeding the GPDMA transfer logic, the CHN(26:24) began to slip at 8MHz. Given that the GPDMA mode relies totally on the existance of ADGDR (it cannot read an individual channel) then it would appear there's a flaw in the system somewhere. The idea of using the GPDMA to aquire a series of samples into a memory buffer seems like a good one. However, it seems it itself simply cannot keep up with back-to-back bursts when the ADC conversion frequency exceeds 8MHz.

It would appear on the whole to me that ADGDR only real purpose is to feed the GPDMA (there's no reason if using software not to read the actual real data within the ISR) it appears the ADGDR/GPDMA is flawed. It simply doesn't work upto the supposed "13MHz" the manual states.

Conclusions

Having got this far it should be obvious that burst mode isn't usable at all for "real time" processing. You need to buffer a series of samples and then post process these after capture (just like a digital storeage scope would, capture and then display).

If you want to use burst mode to gather a series of samples then there's really only two choices:-

  1. Use interrupts. This is really the only method that will get you up to 12MHz. However, if the CPU usage is too high and you need to "background it" then there's GPDMA mode.
  2. However, if you are going to use GPDMA you will need to use a workaround. If you want to go to 12MHz then you'll need to take into account the channel number slippage buried in your data buffer. Experimentation will be needed to ensure you understand how the slippage occurs depending on how many channels you sample and how long your data series is.
13 Mar 2011

Hi,

Hexley Ball wrote:

In burst mode, the ADC does back-to-back conversions on the specified channels. No trigger is needed (or allowed). The channels cycle through continuously until burst mode is turned off.

What about these registered?

Page 597 mentions a DMACSoftBReq register that can be used to initiate burst by writing a bit. On page 599 mentions DMACSync for syncronizing DMA requests.

Perhaps these might be of use (maybe you can setup interrupt on the pin and initiate a DMA burst).

Seems like you can kick the DMA to do small burst to me.

13 Mar 2011

Hi Andy,

Andy K wrote:

Reading the ADGDR using the GPDMA system.

Nice experiment and explanation (and a bit what I expected, although the 8 MHz barrier is a surprise). One for the errata/bug sheet!

Just a thought about the ADGDR usage: is it not possible to use a Linked List feature to read the other registers? You are supposed to use that if the channels are not contiguous (so you have to use something else in such list than ADGDR anyway).