I am trying to implement DMA for receiving I2S channel 0 on a FRDM K22F. I got the I2S working and the I2S0_RDR0 register is updating with data; FIFO Request DMA is enabled. I am trying to store the data in an array 1024 long, each bin with 32 bits. That should be 4096 bytes. Here is my code
SIM_SCGC6 |= 0x2; //DMAMUX Module Turn On
SIM_SCGC7 |= 0x2; //DMA Module Turn On
DMAMUX_CHCFG0 = 0x8C; //I2S Source: Slot 12 & Activate
DMA_TCD0_CSR &= 0xBF; //Inactive
NVIC_EnableIRQ(DMA0_IRQn); //Enable IRQ DMA Channel 0
DMA_CR = 0x80; //Enable Minor Looping
DMA_TCD0_SADDR = (uint32_t)&I2S0_RDR0; //Data Source
DMA_TCD0_DADDR = (uint32_t) BUFFER_A; //Destination
DMA_TCD0_SOFF = 0; //No Source Offset
DMA_TCD0_SLAST = 0; //Nothing Added to Source Address after Major Loop
DMA_TCD0_DLASTSGA = -4096; //Value Added to Destination Address after Major Loop
DMA_TCD0_DOFF = 4; //4 Byte Destination Offset
//DMA_TCD0_NBYTES_MLOFFYES = 0x40001004; //DMLOE Set, MLOFF = 4 bytes, NBYTES = 4
DMA_TCD0_NBYTES_MLNO = 4; //4 Bytes Transfered in each Minor Loop
DMA_TCD0_BITER_ELINKNO = 1024; //1024 Bins
DMA_TCD0_CITER_ELINKNO = 1024; //1024 Bins
DMA_TCD0_ATTR = 0x202; //32-Bit Transfer Size
DMA_TCD0_CSR = 0x2; //Interrupt Major Iteration
DMA_SERQ = 0x0; //Channel 0 Enable
DMA_TCD0_CSR |= 0x41; //Enable!
Right now my code is crashing, I am not sure why but I do think it has to do with the minor loop offset. What is the difference between DOFF and using the NBYTES_MLOFFYES offset?
Solved! Go to Solution.
The reason why the code crashes is that the compiler can't see the interrupt handler. I added a extern "c" void and now the code runs
extern "C" void DMA0_IRQHandler(){
pc.printf("something\r\n");
DMA_CINT = 0;
//RX_CALL();
//DMA_TCD0_DADDR = (uint32_t)BUFFER_A;
return;
}
The reason why the code crashes is that the compiler can't see the interrupt handler. I added a extern "c" void and now the code runs
extern "C" void DMA0_IRQHandler(){
pc.printf("something\r\n");
DMA_CINT = 0;
//RX_CALL();
//DMA_TCD0_DADDR = (uint32_t)BUFFER_A;
return;
}
Unfortunately no. I have a while(1) loop in main which just reads the DADDR register to make sure it is updating correctly. Right now it seems to be going out of range which makes my code crash. If I use DOFF < 4 the register doesn't update.
40009010 --> 1fff0230
40009010 --> 1fff04dc
40009010 --> 1fff0788
40009010 --> 1fff0a38
40009010 --> 1fff0ce4
40009010 --> 1fff0f90
...CODE CRASHES
SIM_SCGC6 |= 0x2; //DMAMUX Module Turn On
SIM_SCGC7 |= 0x2; //DMA Module Turn On
DMAMUX_CHCFG0 = 0x8C; //I2S Source: Slot 12 & Activate
DMA_TCD0_CSR &= 0xBF; //Inactive
NVIC_EnableIRQ(DMA0_IRQn); //Enable IRQ DMA Channel 0
//DMA_CR = 0x80; //Enable Minor Looping
DMA_TCD0_SADDR = (uint32_t)&I2S0_RDR0; //Data Source
DMA_TCD0_DADDR = (uint32_t) BUFFER_A; //Destination
DMA_TCD0_SOFF = 0; //No Source Offset
DMA_TCD0_SLAST = 0; //Nothing Added to Source Address after Major Loop
DMA_TCD0_DLASTSGA = -4096; //Value Added to Destination Address after Major Loop
DMA_TCD0_DOFF = 4; //4 Byte Destination Offset
DMA_TCD0_NBYTES_MLNO = 4; //4096 Bytes Transfered in Minor Loop
DMA_TCD0_BITER_ELINKNO = 1024; //1024 Bins
DMA_TCD0_CITER_ELINKNO = 1024; //1024 Bins
DMA_TCD0_ATTR = 0x202; //32-Bit Transfer Size
DMA_TCD0_CSR = 0x2; //Interrupt Major Iteration
DMA_SERQ = 0x0; //Channel 0 Enable
DMA_TCD0_CSR |= 0x41; //Enable!
I think your 'SGA' address-adjustment (at the end-of-loop) needs to be 'one transfer' (4 bytes) less than the total, as the LAST transfer won't increment the value, or 4092.
Indeed, There are some mistakes
sorry, just now, i upload the wrong picture!!
I am aware of that. See my code.
However, MLNO is minor loop disabled, but it is indeed enabled in DMA_CR. NBYTES_MLOFFYES doesn't work either, I tried the commented out code but the MLOFF offset doesn't add to the DADDR register.
Hi Eduardo,
Is this issue solved? Please kindly let me know if you have any issue.
Have a great day,
Kan
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------
AS to the difference between DOFF and using the NBYTES_MLOFFYES offset?
DOFF means the offset added to DADDR after every write to DADDR. But NBYTES_MLOFFYES offset means the offset added to DADDR after every minor loop if enabled.And one minor loop may include many times write.
you can see the example in the RMhttp://cache.freescale.com/files/microcontrollers/doc/ref_manual/K22P121M120SF7RM.pdf?fromsite=zh-Ha... P505
and you will get it.
oh, i get it
if you diable the minor loop remapping,the you shoud config DMA_TCD0_DOFF=4.
Or if you enable the minor loop remapping,then you should config the NBYTES_MLOFFYES
as showed the flowing two:
SIM_SCGC6 |= 0x2; //DMAMUX Module Turn On
SIM_SCGC7 |= 0x2; //DMA Module Turn On
DMAMUX_CHCFG0 = 0x8C; //I2S Source: Slot 12 & Activate
DMA_TCD0_CSR &= 0xBF; //Inactive
NVIC_EnableIRQ(DMA0_IRQn); //Enable IRQ DMA Channel 0
//DMA_CR = 0x80; //Enable Minor Looping
DMA_TCD0_SADDR = (uint32_t)&I2S0_RDR0; //Data Source
DMA_TCD0_DADDR = (uint32_t) BUFFER_A; //Destination
DMA_TCD0_SOFF = 0; //No Source Offset
DMA_TCD0_SLAST = 0; //Nothing Added to Source Address after Major Loop
DMA_TCD0_DLASTSGA = -4096; //Value Added to Destination Address after Major Loop
DMA_TCD0_DOFF = 4; //4 Byte Destination Offset
//DMA_TCD0_NBYTES_MLOFFYES = 0x40001004; //DMLOE Set, MLOFF = 4 bytes, NBYTES = 4
DMA_TCD0_NBYTES_MLNO = 4; //4 Bytes Transfered in each Minor Loop
DMA_TCD0_BITER_ELINKNO = 1024; //1024 Bins
DMA_TCD0_CITER_ELINKNO = 1024; //1024 Bins
DMA_TCD0_ATTR = 0x202; //32-Bit Transfer Size
DMA_TCD0_CSR = 0x2; //Interrupt Major Iteration
DMA_SERQ = 0x0; //Channel 0 Enable
DMA_TCD0_CSR |= 0x41; //Enable!
SIM_SCGC6 |= 0x2; //DMAMUX Module Turn On
SIM_SCGC7 |= 0x2; //DMA Module Turn On
DMAMUX_CHCFG0 = 0x8C; //I2S Source: Slot 12 & Activate
DMA_TCD0_CSR &= 0xBF; //Inactive
NVIC_EnableIRQ(DMA0_IRQn); //Enable IRQ DMA Channel 0
DMA_CR = 0x80; //Enable Minor Looping
DMA_TCD0_SADDR = (uint32_t)&I2S0_RDR0; //Data Source
DMA_TCD0_DADDR = (uint32_t) BUFFER_A; //Destination
DMA_TCD0_SOFF = 0; //No Source Offset
DMA_TCD0_SLAST = 0; //Nothing Added to Source Address after Major Loop
DMA_TCD0_DLASTSGA = -4096; //Value Added to Destination Address after Major Loop
//DMA_TCD0_DOFF = 4; //4 Byte Destination Offset
DMA_TCD0_NBYTES_MLOFFYES = 0x40001004; //DMLOE Set, MLOFF = 4 bytes, NBYTES = 4
//DMA_TCD0_NBYTES_MLNO = 4; //4 Bytes Transfered in each Minor Loop
DMA_TCD0_BITER_ELINKNO = 1024; //1024 Bins
DMA_TCD0_CITER_ELINKNO = 1024; //1024 Bins
DMA_TCD0_ATTR = 0x202; //32-Bit Transfer Size
DMA_TCD0_CSR = 0x2; //Interrupt Major Iteration
DMA_SERQ = 0x0; //Channel 0 Enable
DMA_TCD0_CSR |= 0x41; //Enable!
no,MLNO is dosn't mean minor loop disabled!! it means the remapping upon the minor loop completion! just like the remapping upon the major loop completion!
as to but the MLOFF offset doesn't add to the DADDR register.this is because,you enable the ninor loop remapping,but you don't set the MLOFF in value.