A second look at DMA plus a firmware-update

A project log for Linear CCD module

TCD1304-based linear CCD module driven by a Nucleo F401RE or an STM32F103 blue pill

esben rosselesben rossel 07/08/2016 at 22:212 Comments

The firmware was not stable. I experienced crashes. They were infrequent, but still very annoying. Fiddling with the nucleos UART I'd been running into traps of interrupts - there's probably a technical term for it, but I don't know it.

Long story short: The DMA-controllers in the STM32F401RE can run in normal or circular mode. In the normal mode, the DMA stops once the read/write buffer is full. In the circular mode it ..runs in circles and overwrites the buffer from the beginning once it reaches the end.

The good thing about circular mode is you don't have to reinitialize the DMA every time you need to start over. This is especially practical if what you're doing is time-critical say digitizing the output from a CCD.

There are most likely better explanations, but hopefully this gives you a picture of the situation.

The catch, of course there is one, is that the DMA must be suspended if you want a chance to look at the data. I thought I was very clever to that with an interrupt. Piece of cake. Except suspending the DMA causes the same interrupt. Very loopy - yes pun intended.

I spent the entire evening speculating on how to break this loop, and finally, completely off the trail, I found a comment about when to start the ADC with software and when not to.

If you've been over the code you'll know the ADC is paced by one of the nucleo's timers. This means there's no need to start it with software. It also means that the ADC stops when the timer stops. Instead of suspending the DMA in the DMA-interrupt (causing an interrupt inside an interrupt), the DMA-interrupt now disables the timer pacing the ADC.

With the ADC on hold no DMA-requests are generated, effectively suspending the DMA. And so far no crashes :)

Firmware files will be updated asap.


esben rossel wrote 08/04/2016 at 15:52 point

The reason for suspending the DMA is that it's not desirable to read the CCD continuously (in fact I'm quite sure it's not even possible). So the idea with suspending the DMA is to only have it running during the 10.4 ms where the pixels are actually outputted, and then only restart it again the next time the CCD is read - thus avoiding DMA buffer(s) filled with garbage.

Rereading my post I see I didn't do a very good job of explaining this detail.

  Are you sure? yes | no

r.e.wolff wrote 08/02/2016 at 08:32 point

Huh? Why are you suspending the ADC? You should  just enable the "half transfer" interrupt. Once you get that interrupt, you get to process the first half of your buffer while the DMA fills the second half. In effect is it double buffering when you consider each half of the buffer a "buffer". 

  Are you sure? yes | no