Mini project: do something with dma

Status
Not open for further replies.

christoph

Well-known member
There seem to be few examples of DMA usage for the teensy 3 (the Cortex-M4 is my first step away from AVRs, so I'm probably not good at finding suitable tutorials and such), so I just tried it.

My first steps: transfer 1 (and then 2) bytes from memory location A to memory location B, no peripherals involved.

Why 1 or 2? Just to see if just 1 is transferred if I want 1, and if 2 are transferred when I want 2. After reading the relevant sections of the datasheet and the "Quick Reference User Guide", it was pretty simple. The different modes for some of the registers (NBYTES, CITER, BITER) were a bit puzzling, but somehow it all made sense. I use the teensyduino libs in Code::Blocks, so no setup() and loop() but just a main():
Code:
#include <WProgram.h>

int main(void)
{
  /** prepare LED **/
  pinMode(LED_BUILTIN, 1);
  /** source and destination **/
  static uint8_t source[2] = {0xAA, 0xBB};
  static uint8_t dest[2] = {0};

  /** configure dma channel 0 **/
  DMA_TCD0_SADDR = source;    // source address
  DMA_TCD0_SOFF = 1;          // after each read, increment source address by 1
  DMA_TCD0_ATTR = DMA_TCD_ATTR_SSIZE(0) | DMA_TCD_ATTR_DSIZE(0); // 8 bits source and dest
  DMA_TCD0_NBYTES_MLNO = 2;   // minor byte count
  DMA_TCD0_SLAST = 0;         // offset added to source address after completion of major loop
  DMA_TCD0_DADDR = dest;      // destination address
  DMA_TCD0_DOFF = 1;          // after each write, increment destination address by 1
  DMA_TCD0_CITER_ELINKNO = 1; // major loop count (must match CITER)
  DMA_TCD0_DLASTSGA = 0;      // offset added to dest address after completion of major loop
  DMA_TCD0_BITER_ELINKNO = 1; // major loop count (must match BITER)
  DMA_TCD0_CSR = 0;           // no special features

  /** start dma transfer **/
  DMA_SSRT = DMA_SSRT_SSRT(0);

  /** wait for transfer to be completed **/
  while(!(DMA_TCD0_CSR & DMA_TCD_CSR_DONE));

  if ((dest[0] == 0xAA) && (dest[1] == 0))
  {
    digitalWriteFast(LED_BUILTIN, 1);
    while(1);
  }
  else
  if ((dest[0] == 0xAA) && (dest[1] == 0xBB))
  {
    while (1)
    {
      digitalWriteFast(LED_BUILTIN, 1);
      delay(250);
      digitalWriteFast(LED_BUILTIN, 0);
      delay(250);
    }
  }
  else
  {
    while (1)
    {
      digitalWriteFast(LED_BUILTIN, 1);
      delay(500);
      digitalWriteFast(LED_BUILTIN, 0);
      delay(500);
    }
  }
}

When DMA_TCD0_NBYTES_MLNO is set to 1, the LED is just on. When it is set to two, it flashes twice a second, just as planned. Messing around with the source values makes it flash once a second.
 
I didn't see that thread, thanks! I searched for DMA using the forum search, but it didn't show any results. Maybe the search term is too short?
 
Status
Not open for further replies.
Back
Top