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);
}