Hello
I'm playing with a modified version of code I found here.
It's essentially the same code, with some more comments as I looked stuff up.
I've modified some of the parameters so that DMA_TCD1_NBYTES_MLNO is set to transfer all 32 bytes in one block instead of transferring 2 bytes at a time.
In my setup(), I have a while loop that is set to trigger the dma operation once. The DMA operation continues and by looking at the serial monitor output, I can see that bufferB has been correctly populated with all the data.
I've noticed that if I only trigger the dma once, I do not get the DMA ISR (no "ISR!" printed in the serial monitor). I also get the "DMA complete" message printed, but no interrupt.
So the DMA operation completed, but it's corresponding interrupt was never raised.
If I re-trigger the dma by adding the following line below the while loop
DMA_TCD1_CSR |= DMA_TCD_CSR_START;
Then I get the ISR message.
I had assumed that once the major loop iteration completes and the DMA has transferred everything over, I would get the ISR callback.
I looks like I need trigger the DMA operation and if the system detects that the loop count conditions have been met, then the interrupt is raised.
Am I understanding this correctly?
Thanks
I'm playing with a modified version of code I found here.
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 < 1)
{
DMA_TCD1_CSR |= DMA_TCD_CSR_START;
delay(10);
printBuffer();
i++;
}
if(!(DMA_TCD1_CSR & DMA_TCD_CSR_DONE))
{
Serial.println("DMA not complete");
}
else
{
Serial.println("DMA complete");
}
}
void loop() {
}
void dmaInit() {
// Enable DMA clock
// system clock gating control register 7
// bit 1 controls the DMA clock.
SIM_SCGC7 |= SIM_SCGC7_DMA;
// bit 1 controls the DMA Mux clock
SIM_SCGC6 |= SIM_SCGC6_DMAMUX;
// Enable interrupt (end-of-major loop)
DMA_TCD1_CSR |= DMA_TCD_CSR_INTMAJOR;
// Enable interrupt request
// for DMA channel 1
NVIC_ENABLE_IRQ(IRQ_DMA_CH1);
// Use default configuration
// 21.3.1, kinetis manual, the DMA control register
// Use normal operation mode
DMA_CR = 0;
// Source address
DMA_TCD1_SADDR = bufferA;
// source address to increment after
// each dma tranfer completes, basically
// after each minor loop
DMA_TCD1_SOFF = 2;
// source address to increment after a major
// loop completes
DMA_TCD1_SLAST = 0;
// Destination address
DMA_TCD1_DADDR = bufferB;
DMA_TCD1_DOFF = 2;
DMA_TCD1_DLASTSGA = 0;
// Source and destination size 16 bit
// 000 (0) 8-bit
// 001 (1) 16-bit
// 010 (2) 32-bit
DMA_TCD1_ATTR = DMA_TCD_ATTR_SSIZE(1) | DMA_TCD_ATTR_DSIZE(1);
// Number of bytes to transfer (in each service request)
// Minor byte transfer count
DMA_TCD1_NBYTES_MLNO = N*sizeof(uint16_t);
// Set loop counts
DMA_TCD1_CITER_ELINKNO = 1;
DMA_TCD1_BITER_ELINKNO = 1;
}
void dma_ch1_isr() {
Serial.println("ISR!");
printBuffer();
// Clear interrupt request for channel 1
DMA_CINT = 1;
}
void dma_error_isr()
{
Serial.println("DMA error");
}
void printBuffer() {
Serial.print("B: ");
for (uint32_t i = 0; i < N; i++) {
if (i != 0) Serial.print(", ");
Serial.print(bufferB[i]);
}
Serial.println(" ");
}
It's essentially the same code, with some more comments as I looked stuff up.
I've modified some of the parameters so that DMA_TCD1_NBYTES_MLNO is set to transfer all 32 bytes in one block instead of transferring 2 bytes at a time.
In my setup(), I have a while loop that is set to trigger the dma operation once. The DMA operation continues and by looking at the serial monitor output, I can see that bufferB has been correctly populated with all the data.
I've noticed that if I only trigger the dma once, I do not get the DMA ISR (no "ISR!" printed in the serial monitor). I also get the "DMA complete" message printed, but no interrupt.
So the DMA operation completed, but it's corresponding interrupt was never raised.
If I re-trigger the dma by adding the following line below the while loop
DMA_TCD1_CSR |= DMA_TCD_CSR_START;
Then I get the ISR message.
I had assumed that once the major loop iteration completes and the DMA has transferred everything over, I would get the ISR callback.
I looks like I need trigger the DMA operation and if the system detects that the loop count conditions have been met, then the interrupt is raised.
Am I understanding this correctly?
Thanks