danieljohansson
Member
Hi!
I would like to use the direct memory access (DMA) controller to transfer some values between two arrays and then run a interrupt on end-of-major loop. The data copying works fine but I can't get the interrupt to run. Below is an example sketch to demonstrate my problem. The B buffer fills up as expected but the interrupt never fires. (It should have fired 4 times for these 16 transfers)
The DMA interrupts have been working for me with the transfers being triggered by the ADC (see http://forum.pjrc.com/threads/24492-Using-the-PDB-on-Teensy-3#post_message_37659). I think the only difference now is that I need to trigger the transfers from software.
Any ideas are welcome!
I would like to use the direct memory access (DMA) controller to transfer some values between two arrays and then run a interrupt on end-of-major loop. The data copying works fine but I can't get the interrupt to run. Below is an example sketch to demonstrate my problem. The B buffer fills up as expected but the interrupt never fires. (It should have fired 4 times for these 16 transfers)
Code:
const uint16_t N = 16;
uint16_t bufferA[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
uint16_t bufferB[N];
uint16_t i = 0;
void setup() {
Serial.begin(9600);
while (!Serial);
dmaInit();
while (i < N) {
DMA_TCD1_CSR = DMA_TCD_CSR_START;
delay(10);
printBuffer();
i++;
}
}
void loop() {}
void dmaInit() {
// Enable DMA clock
SIM_SCGC7 |= SIM_SCGC7_DMA;
// Use default configuration
DMA_CR = 0;
// Source address
DMA_TCD1_SADDR = bufferA;
DMA_TCD1_SOFF = 2;
DMA_TCD1_SLAST = 0;
// Destination address
DMA_TCD1_DADDR = bufferB;
DMA_TCD1_DOFF = 2;
DMA_TCD1_DLASTSGA = 0;
// Source and destination size 16 bit
DMA_TCD1_ATTR = DMA_TCD_ATTR_SSIZE(1) | DMA_TCD_ATTR_DSIZE(1);
// Number of bytes to transfer (in each service request)
DMA_TCD1_NBYTES_MLNO = 2;
// Set loop counts
DMA_TCD1_CITER_ELINKNO = 4;
DMA_TCD1_BITER_ELINKNO = 4;
// Enable interrupt (end-of-major loop)
DMA_TCD1_CSR = DMA_TCD_CSR_INTMAJOR;
// Enable interrupt request
NVIC_ENABLE_IRQ(IRQ_DMA_CH1);
}
void dma_ch1_isr() {
Serial.println("ISR!");
// Clear interrupt request for channel 1
DMA_CINT = 1;
}
void printBuffer() {
Serial.print("B: ");
for (uint32_t i = 0; i < N; i++) {
if (i != 0) Serial.print(", ");
Serial.print(bufferB[i]);
}
Serial.println(" ");
}
The DMA interrupts have been working for me with the transfers being triggered by the ADC (see http://forum.pjrc.com/threads/24492-Using-the-PDB-on-Teensy-3#post_message_37659). I think the only difference now is that I need to trigger the transfers from software.
Any ideas are welcome!
Last edited: