Simple DMA ISR Not Firing on Teensy 4.1

lerible

Member
Hello,

I can't seem to get a simple DMA transfer to work. Attached is the code I am trying to make work. I am running on a Teensy 4.1.

Thanks for any help I can get.

------

#include <Arduino.h>
#include <imxrt.h>
#include <DMAChannel.h>

DMAChannel dma;

DMAMEM uint32_t src[4] = { 10, 20, 30, 40 };
DMAMEM uint32_t dst[4];

volatile bool dmaDone = false;

void dmaISR() {
dma.clearInterrupt();
dmaDone = true;
Serial.println("✅ DMA ISR fired!");
}

void setup() {
Serial.begin(115200);
while (!Serial);

dma.begin(true); // Force allocation

Serial.print("DMA channel assigned: ");
Serial.println(dma.channel);

dma.sourceBuffer(src, sizeof(src));
dma.destinationBuffer(dst, sizeof(dst));
dma.disableOnCompletion();
dma.interruptAtCompletion();

attachInterruptVector((IRQ_NUMBER_t)(IRQ_DMA_CH0 + dma.channel), dmaISR);
NVIC_ENABLE_IRQ((IRQ_NUMBER_t)(IRQ_DMA_CH0 + dma.channel));

dma.enable();

Serial.println("Triggering DMA manually...");
dma.triggerManual();
}

void loop() {
if (dmaDone) {
dmaDone = false;
Serial.println("✅ DMA transfer complete. Verifying data...");
for (int i = 0; i < 4; i++) {
Serial.print("dst[");
Serial.print(i);
Serial.print("] = ");
Serial.println(dst);
}
}
}
 
When you post code can you do it between CODE tags using the </> button. This maintains formatting and makes you code more readable and easier to understand. Here below is you code between code tags. Bye the way IT DOES NOT COMPILE.
Code:
#include <Arduino.h>
#include <imxrt.h>
#include <DMAChannel.h>

DMAChannel dma;

DMAMEM uint32_t src[4] = { 10, 20, 30, 40 };
DMAMEM uint32_t dst[4];

volatile bool dmaDone = false;

void dmaISR() {
    dma.clearInterrupt();
    dmaDone = true;
    Serial.println("✅ DMA ISR fired!");
}

void setup() {
    Serial.begin(115200);
    while (!Serial);

    dma.begin(true); // Force allocation

    Serial.print("DMA channel assigned: ");
    Serial.println(dma.channel);

    dma.sourceBuffer(src, sizeof(src));
    dma.destinationBuffer(dst, sizeof(dst));
    dma.disableOnCompletion();
    dma.interruptAtCompletion();

    attachInterruptVector((IRQ_NUMBER_t)(IRQ_DMA_CH0 + dma.channel), dmaISR);
    NVIC_ENABLE_IRQ((IRQ_NUMBER_t)(IRQ_DMA_CH0 + dma.channel));

    dma.enable();

    Serial.println("Triggering DMA manually...");
    dma.triggerManual();
}

void loop() {
    if (dmaDone) {
        dmaDone = false;
        Serial.println("✅ DMA transfer complete. Verifying data...");
        for (int i = 0; i < 4; i++) {
            Serial.print("dst[");
            Serial.print(i);
            Serial.print("] = ");
            Serial.println(dst);
        }
    }
}
 
When you post code can you do it between CODE tags using the </> button. This maintains formatting and makes you code more readable and easier to understand. Here below is you code between code tags. Bye the way IT DOES NOT COMPILE.
Code:
#include <Arduino.h>
#include <imxrt.h>
#include <DMAChannel.h>

DMAChannel dma;

DMAMEM uint32_t src[4] = { 10, 20, 30, 40 };
DMAMEM uint32_t dst[4];

volatile bool dmaDone = false;

void dmaISR() {
    dma.clearInterrupt();
    dmaDone = true;
    Serial.println("✅ DMA ISR fired!");
}

void setup() {
    Serial.begin(115200);
    while (!Serial);

    dma.begin(true); // Force allocation

    Serial.print("DMA channel assigned: ");
    Serial.println(dma.channel);

    dma.sourceBuffer(src, sizeof(src));
    dma.destinationBuffer(dst, sizeof(dst));
    dma.disableOnCompletion();
    dma.interruptAtCompletion();

    attachInterruptVector((IRQ_NUMBER_t)(IRQ_DMA_CH0 + dma.channel), dmaISR);
    NVIC_ENABLE_IRQ((IRQ_NUMBER_t)(IRQ_DMA_CH0 + dma.channel));

    dma.enable();

    Serial.println("Triggering DMA manually...");
    dma.triggerManual();
}

void loop() {
    if (dmaDone) {
        dmaDone = false;
        Serial.println("✅ DMA transfer complete. Verifying data...");
        for (int i = 0; i < 4; i++) {
            Serial.print("dst[");
            Serial.print(i);
            Serial.print("] = ");
            Serial.println(dst);
        }
    }
}
Sorry about that. See corrected code that compiles.

/
#include <Arduino.h>
#include <imxrt.h>
#include <DMAChannel.h>

DMAChannel dma;

DMAMEM uint32_t src[4] = { 10, 20, 30, 40 };
DMAMEM uint32_t dst[4];

volatile bool dmaDone = false;

void dmaISR() {
dma.clearInterrupt();
dmaDone = true;
Serial.println("✅ DMA ISR fired!");
}

void setup() {
Serial.begin(115200);
while (!Serial);

dma.begin(true); // Force allocation

Serial.print("DMA channel assigned: ");
Serial.println(dma.channel);

dma.sourceBuffer(src, sizeof(src));
dma.destinationBuffer(dst, sizeof(dst));
dma.disableOnCompletion();
dma.interruptAtCompletion();

attachInterruptVector((IRQ_NUMBER_t)(IRQ_DMA_CH0 + dma.channel), dmaISR);
NVIC_ENABLE_IRQ((IRQ_NUMBER_t)(IRQ_DMA_CH0 + dma.channel));

dma.enable();

Serial.println("Triggering DMA manually...");
dma.triggerManual();
}

void loop() {
if (dmaDone) {
dmaDone = false;
Serial.println("✅ DMA transfer complete. Verifying data...");
for (int i = 0; i < 4; i++) {
Serial.print("dst[");
Serial.print(i);
Serial.print("] = ");
Serial.println(dst);
}
}
}/
 
When you post code can you do it between CODE tags using the </> button. This maintains formatting and makes you code more readable and easier to understand. Here below is you code between code tags. Bye the way IT DOES NOT COMPILE.
Code:
#include <Arduino.h>
#include <imxrt.h>
#include <DMAChannel.h>

DMAChannel dma;

DMAMEM uint32_t src[4] = { 10, 20, 30, 40 };
DMAMEM uint32_t dst[4];

volatile bool dmaDone = false;

void dmaISR() {
    dma.clearInterrupt();
    dmaDone = true;
    Serial.println("✅ DMA ISR fired!");
}

void setup() {
    Serial.begin(115200);
    while (!Serial);

    dma.begin(true); // Force allocation

    Serial.print("DMA channel assigned: ");
    Serial.println(dma.channel);

    dma.sourceBuffer(src, sizeof(src));
    dma.destinationBuffer(dst, sizeof(dst));
    dma.disableOnCompletion();
    dma.interruptAtCompletion();

    attachInterruptVector((IRQ_NUMBER_t)(IRQ_DMA_CH0 + dma.channel), dmaISR);
    NVIC_ENABLE_IRQ((IRQ_NUMBER_t)(IRQ_DMA_CH0 + dma.channel));

    dma.enable();

    Serial.println("Triggering DMA manually...");
    dma.triggerManual();
}

void loop() {
    if (dmaDone) {
        dmaDone = false;
        Serial.println("✅ DMA transfer complete. Verifying data...");
        for (int i = 0; i < 4; i++) {
            Serial.print("dst[");
            Serial.print(i);
            Serial.print("] = ");
            Serial.println(dst);
        }
    }
}
Posting code seems to be removing content on final Serial.println. Should read: Serial.println(dst);

Not sure why.
 
You might want to check out this post that is about Teensy DMA usage.
As @BriComp mentioned you need to put your code between code tags. That is accomplished by clicking on the "</>" symbol in the upper left corner of the post window. It will bring up a text window that you can paste your code into. That will preserve the formatting of the code.

The only compile error I got was at line 51 inside a for loop:
Code:
void loop() {
    if (dmaDone) {
        dmaDone = false;
        Serial.println("✅ DMA transfer complete. Verifying data...");
        for (int i = 0; i < 4; i++) {
            Serial.print("dst[");
            Serial.print(i);
            Serial.print("] = ");
    //        Serial.println(dst); <----- this is incorrect use of the println() function. dst is an array so:
            Serial.println(dst[i]); <----- prints out each uint32_t element of the dst[] array.
        }
    }
}

After modifying the code and changing:
Code:
    dma.triggerManually();
To:
Code:
    dma.disableOnCompletion();
    dma.triggerContinuously();
as per the post above, the sketch compiles and runs. The trigger fires but the the values in the dst[] array are not the values in the src[] array.
Output:
Code:
DMA channel assigned: 1
Triggering DMA manually...
✅ DMA ISR fired!
✅ DMA transfer complete. Verifying data...
dst[0] = 478977
dst[1] = 3146312
dst[2] = 15
dst[3] = 65024
I can't help you with that as I am not that familiar with DMA usage;)
You can further search the forum for more information about DMA usage.
Here is the modified code:
Code:
// DMA_Test.ino

#include <Arduino.h>
#include <imxrt.h>
#include <DMAChannel.h>

DMAChannel dma;

DMAMEM uint32_t src[4] = { 10, 20, 30, 40 };
DMAMEM uint32_t dst[4] = { 0, 0, 0, 0 };

volatile bool dmaDone = false;

void dmaISR() {
    dma.clearInterrupt();
    dmaDone = true;
    Serial.println("✅ DMA ISR fired!");
}

void setup() {
    Serial.begin(115200);
    while (!Serial);

    dma.begin(true); // Force allocation

    Serial.print("DMA channel assigned: ");
    Serial.println(dma.channel);

    dma.sourceBuffer(src, sizeof(src));
    dma.destinationBuffer(dst, sizeof(dst));
    dma.disableOnCompletion();
    dma.interruptAtCompletion();

    attachInterruptVector((IRQ_NUMBER_t)(IRQ_DMA_CH0 + dma.channel), dmaISR);
    NVIC_ENABLE_IRQ((IRQ_NUMBER_t)(IRQ_DMA_CH0 + dma.channel));

    dma.enable();

    Serial.println("Triggering DMA manually...");
    dma.disableOnCompletion();
    dma.triggerContinuously();
}

void loop() {
    if (dmaDone) {
        dmaDone = false;
        Serial.println("✅ DMA transfer complete. Verifying data...");
        for (int i = 0; i < 4; i++) {
            Serial.print("dst[");
            Serial.print(i);
            Serial.print("] = ");
            Serial.println(dst[i]);
        }
    }
}
Hopefully this will get you going in the right direction...
 
They might be … DMAMEM variables can’t be initialised at compile time, see memory static allocation keywords discussion here.
Thanks @h4yn0nnym0u5e, I had forgot about that. Modified the code by removing "DMAMEM" from src[] array:
Code:
uint32_t src[4] = { 10, 20, 30, 40 };
The code works as expected:
Code:
DMA channel assigned: 1
Triggering DMA manually...
✅ DMA ISR fired!
✅ DMA transfer complete. Verifying data...
dst[0] = 10
dst[1] = 20
dst[2] = 30
dst[3] = 40

Sketch now looks like this:
Code:
// DMA_Test.ino

#include <Arduino.h>
#include <imxrt.h>
#include <DMAChannel.h>

DMAChannel dma;

uint32_t src[4] = { 10, 20, 30, 40 };
DMAMEM uint32_t dst[4];

volatile bool dmaDone = false;

void dmaISR() {
    dma.clearInterrupt();
    dmaDone = true;
    Serial.println("✅ DMA ISR fired!");
}

void setup() {
    Serial.begin(115200);
    while (!Serial);

    dma.begin(true); // Force allocation

    Serial.print("DMA channel assigned: ");
    Serial.println(dma.channel);

    dma.sourceBuffer(src, sizeof(src));
    dma.destinationBuffer(dst, sizeof(dst));
    dma.disableOnCompletion();
    dma.interruptAtCompletion();

    attachInterruptVector((IRQ_NUMBER_t)(IRQ_DMA_CH0 + dma.channel), dmaISR);
    NVIC_ENABLE_IRQ((IRQ_NUMBER_t)(IRQ_DMA_CH0 + dma.channel));

    dma.enable();

    Serial.println("Triggering DMA manually...");
    dma.disableOnCompletion();
    dma.triggerContinuously();
}

void loop() {
    if (dmaDone) {
        dmaDone = false;
        Serial.println("✅ DMA transfer complete. Verifying data...");
        for (int i = 0; i < 4; i++) {
            Serial.print("dst[");
            Serial.print(i);
            Serial.print("] = ");
            Serial.println(dst[i]);
        }
    }
}
 
Back
Top