Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 5 of 5

Thread: Max DMA Buffer Size ?

  1. #1
    Senior Member Jp3141's Avatar
    Join Date
    Nov 2012
    Posts
    461

    Max DMA Buffer Size ?

    I am trying to build an arbitrary waveform generator by using DMA to drive the DAC diretly from a table in (flash) memory. I need at least 50,000 points. My code works with < 32767 points, but not more. I can't quite understand in the Kinetis docs if this is a limitation of the DMA engine, or just the DMA library in Teensy.

    For reference, here's my code:

    Code:
    #include <DMAChannel.h>
    // DAC on pin A14 
    #define LED 13
    #include "kinetis.h"
    
    #include "wave.h"
    
    // Multiple input & output objects use the Programmable Delay Block
    // to set their sample rate.  They must all configure the same
    // period to avoid chaos.
    
    #define PDB_CONFIG (PDB_SC_TRGSEL(15) | PDB_SC_PDBEN | PDB_SC_CONT | PDB_SC_PDBIE | PDB_SC_DMAEN)
    
    // 128 samples; PDB_Period = F_BUS/(128*1kHz)
    #if F_BUS == 6*1000*10000
      #define PDB_PERIOD (468-1)
    #elif F_BUS == 56*1000*1000
      #define PDB_PERIOD (437-1)
    #elif F_BUS == 48*1000*1000
      #define PDB_PERIOD (375-1)
    #elif F_BUS == 36*1000*1000
      #define PDB_PERIOD (281-1)
    #elif F_BUS == 24*1000*1000
     #define PDB_PERIOD (187-1)
    #elif F_BUS == 16*1000*1000
      #define PDB_PERIOD (125-1)
    #else
      #error "Unsupported F_BUS speed"
    #endif
    
    DMAChannel dma(false);
    
    // not much point in updating the DAC faster than 1 us
    #define FSTEP (1*1000*1000)
    
    void setup() {
      Serial.begin(0);  
      while (!Serial);
      pinMode(0, OUTPUT);
      Serial.println(__FILE__ " " __DATE__ " " __TIME__);
      Serial.printf("Arbitrary Wave Generator, Step F = %i\n\n", FSTEP);
      
      dma.begin(true); // allocate the DMA channel first
      pinMode(LED, OUTPUT);  
      SIM_SCGC2 |= SIM_SCGC2_DAC0; // enable DAC clock
      DAC0_C0 = DAC_C0_DACEN | DAC_C0_DACRFS; // enable the DAC module, 3.3V reference
     
      // set the programmable delay block to trigger DMA requests
      SIM_SCGC6 |= SIM_SCGC6_PDB; // enable PDB clock
      PDB0_IDLY = 0; // interrupt delay register
      PDB0_MOD = F_BUS/FSTEP-1; // modulus register, sets period
    
      Serial.printf("FBUS = %6i, PDB0_MOD = %6i (+1)\n", F_BUS, F_BUS/FSTEP-1);
    
      PDB0_SC = PDB_CONFIG | PDB_SC_LDOK; // load registers from buffers
      PDB0_SC = PDB_CONFIG | PDB_SC_SWTRIG; // reset and restart
      PDB0_CH0C1 = 0x0101; // channel n control register?
    //  dma.sourceBuffer(WiringWave, sizeof(WiringWave));  // Doesn't work if > 65534
      dma.sourceBuffer(WiringWave, 65534);
      Serial.printf("Waveform size = %i\n", sizeof(WiringWave));
      dma.destination(*(volatile uint16_t *)&(DAC0_DAT0L));
      dma.triggerAtHardwareEvent(DMAMUX_SOURCE_PDB);
      digitalWrite(LED, HIGH);
      dma.enable();
    }
    
    
    
    
    void loop() {
    }
    andf the waveform is defined like this:

    Code:
    static const uint16_t WiringWave[] = {
    1780,
    1755,
    1727,
    1696,
    1666,
    .
    .  // for ~ 50,000 total samples
    .
    .
    
    1635,
    1608,
    1582,
    1030};

  2. #2
    Senior Member+ Theremingenieur's Avatar
    Join Date
    Feb 2014
    Location
    Colmar, France
    Posts
    2,551
    The DAC has a ring buffer which can hold up to 16 words. It allows to trigger 1 DMA request to fill the lower half while the upper half is read and vice versa. This would allow to organize the lookup table as arrays[8] und thus reduce the # of table elements to <7000. Another thing is that transferring 8 words with one single DMA request is ways more efficient than transferring a single word at onc.

  3. #3
    Senior Member Jp3141's Avatar
    Join Date
    Nov 2012
    Posts
    461
    Thanks. With 16 word loops, does this still pump data to the DAC at a uniform and constant rate, or does it go in bursts ?

  4. #4
    Senior Member
    Join Date
    Jul 2014
    Posts
    2,521
    Quote Originally Posted by Jp3141 View Post
    I am trying to build an arbitrary waveform generator by using DMA to drive the DAC diretly from a table in (flash) memory. I need at least 50,000 points. My code works with < 32767 points, but not more. I can't quite understand in the Kinetis docs if this is a limitation of the DMA engine, or just the DMA library in Teensy.
    AFAIK, general DMA buffers are in RAM, which is rather limited (RAM inT3.1 is also smaller than T3.2).
    I would for constant waveform DAC hack the DMAChannel library and pass Flash memory as source buffer.

    (obviously you cannot use Flash for destination buffers, but you could Flash for source buffers)

  5. #5
    Senior Member+ Theremingenieur's Avatar
    Join Date
    Feb 2014
    Location
    Colmar, France
    Posts
    2,551
    Quote Originally Posted by Jp3141 View Post
    Thanks. With 16 word loops, does this still pump data to the DAC at a uniform and constant rate, or does it go in bursts ?
    The approach is slightly different. You use the PDB to directly trigger the DAC output at constant rate. Its hardware ring buffer does then (if the appropriate flags are set) raise either interrupts or DMA requests (your choice) when the read pointer of the ring buffer reaches specific values. When it reaches for example the top position, a DMA request will refill the 8 bottom words, and when it reaches the Watermark position (configurable from 1 to 4 away from the bottom position) another DMA request will refill the top 8 words.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •