Teensy 4 DMA to LPUART?

Status
Not open for further replies.

ecurtz

Well-known member
Has anyone done any serial DMA yet? I'm trying to update a working piece of 3.2 code that dumps data to serial using DMA and I'm not having any luck so far on the 4.0. It doesn't go into my DMA completion ISR and I don't see any output so I'm guessing the transfer isn't even triggering, but I haven't used a scope or logic probe to verify that 100%. One thing I noticed was it looks from the docs that only certain DMA channels work with triggers, but AFAIK there isn't any way to specify one using the DMAChannel class.

Code:
#include "Teensy4_Serial_Data.h"
#include "DMAChannel.h"

// Not sure why these aren't in one of the serial headers

#ifdef KINETISK
#ifdef HAS_KINETISK_UART0_FIFO
#define UART0_C2_ENABLE    UART_C2_TE | UART_C2_RE | UART_C2_RIE | UART_C2_ILIE
#else
#define UART0_C2_ENABLE   UART_C2_TE | UART_C2_RE | UART_C2_RIE
#endif
#define UART0_C2_TX_ACTIVE    UART0_C2_ENABLE | UART_C2_TIE
#define UART0_C2_TX_COMPLETING  UART0_C2_ENABLE | UART_C2_TCIE
#define UART0_C2_TX_INACTIVE    UART0_C2_ENABLE

#else

#define CTRL_ENABLE     (LPUART_CTRL_TE | LPUART_CTRL_RE | LPUART_CTRL_RIE | LPUART_CTRL_ILIE)
#define CTRL_TX_ACTIVE    (CTRL_ENABLE | LPUART_CTRL_TIE)
#define CTRL_TX_COMPLETING  (CTRL_ENABLE | LPUART_CTRL_TCIE)
#define CTRL_TX_INACTIVE  CTRL_ENABLE 

#endif

DMAChannel dmaTX;
unsigned char magic_cookie[] = {0xBA,0x11,0x00,0x03,  0x00,  0x00,  0x00,0x00};

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
  Serial1.begin(3000000);
  pinMode(2, OUTPUT);
  digitalWrite(2, HIGH);
 
  delay(10);
  
  magic_cookie[COOKIE_CMD] = 11; // Set palette
  magic_cookie[COOKIE_ARG] = 255; // Streaming palette
  Serial1.write(magic_cookie, sizeof(magic_cookie));
  Serial1.write((const uint8_t *) palette_data, sizeof(palette_data));

  // Try to setup dma channel
  dmaTX.disable();
}


#ifdef KINETISK
void uart0_dma_tx_isr() {
  dmaTX.clearComplete();
  dmaTX.clearInterrupt();  // You need to clear the interrupt to do again later.

  // disable DMA on TX
  UART0_C2 = UART0_C2_ENABLE;
  UART0_C5 = 0;
}

#else

void lpuart6_dma_tx_isr() {
  dmaTX.clearComplete();
  dmaTX.clearInterrupt();  // You need to clear the interrupt to do again later.
 
  // disable DMA on TX
  LPUART6_CTRL = CTRL_ENABLE;
  LPUART6_BAUD &= ~LPUART_BAUD_TDMAE;
}

#endif

void loop() {

  delay(1000);

  unsigned long timeStart = micros();
  
  magic_cookie[COOKIE_CMD] = 6; // 8 bit indexed data
  magic_cookie[COOKIE_ARG] = 0; // No argument
  Serial1.write(magic_cookie, sizeof(magic_cookie));
  
  // Serial1.write((const uint8_t *) image_data, sizeof(image_data));

  // Send DMD via DMA
  dmaTX.interruptAtCompletion();
  dmaTX.disableOnCompletion();
  dmaTX.sourceBuffer(image_data, sizeof(image_data ));
  
#ifdef KINETISK
  dmaTX.attachInterrupt(uart0_dma_tx_isr);
  dmaTX.destination((volatile uint8_t&) UART0_D);
  dmaTX.triggerAtHardwareEvent(DMAMUX_SOURCE_UART0_TX);
  // enable DMA on TX
  UART0_C5 = UART_C5_TDMAS; 
  UART0_C2 = UART0_C2_TX_ACTIVE;
  
#else

  dmaTX.attachInterrupt(lpuart6_dma_tx_isr);
  dmaTX.destination((volatile uint8_t &) LPUART6_DATA);
  dmaTX.triggerAtHardwareEvent(DMAMUX_SOURCE_LPUART6_TX);
  // enable DMA on TX
  LPUART6_BAUD |= LPUART_BAUD_TDMAE;
  LPUART6_CTRL = CTRL_TX_ACTIVE;
  
#endif

  dmaTX.enable();

  unsigned long timeStop = micros();
  Serial.print("Elapsed time: ");
  Serial.println(timeStop - timeStart);
}
 

Attachments

  • Teensy4_Serial.ino
    2.8 KB · Views: 64
  • Teensy4_Serial_Data.h
    19.2 KB · Views: 86
Status
Not open for further replies.
Back
Top