Kuba0040
Well-known member
Hello,
I am trying to get the DMA working on a Teensy 4.0. To do so I’m currently in the process of reverse-engineering the DMAChannel.cpp and .h file, along with the datasheet's help. However, I have encountered a peculiar problem. When I try to configure the DMA, writes to some registers immediately crash the CPU.
Here is an example:
This is one function I am working on to setup the DMA. The clock for the DMA in the CCM_CCGR5 register has already been activated like so: CCM_CCGR5 |= CCM_CCGR5_DMA(CCM_CCGR_ON) before this function. The CPU executes the DMA_CR, DMA_TCD0_BITER, DMA_TCD0_CITER lines just fine, however crashes instantly on the DMA_TCD0_NBYTES_MLOFFYES line. And I can’t figure out why?
What am I missing? I couldn't find (or missed) any mention of a seperate action I have to perform before I can use this register.
Thank You for the help.
I am trying to get the DMA working on a Teensy 4.0. To do so I’m currently in the process of reverse-engineering the DMAChannel.cpp and .h file, along with the datasheet's help. However, I have encountered a peculiar problem. When I try to configure the DMA, writes to some registers immediately crash the CPU.
Here is an example:
Code:
void setupDMAChannel_0_Main(int32_t BytesToTransfer, int32_t HowManyTransfers, int32_t MinorLoopOffset)
{
DMA_CR = DMA_CR_GRP0PRI | DMA_CR_EMLM | DMA_CR_EDBG;
/*
* A GROUP PRIORITY MUST ALWAYS BE SET!
* GRP1PRI - Group 1 Priority. Group 1 gets set as the most important.
* GRP0PRI - Group 0 Priority. Same thing as group 1
*
* EMLM - Enable Minor Loop Mapping
* Minor loops allow us to have offsets to the Source and Destination adress after each minor loop completes.
*
* Minor loops are individual requests. So if I request to copy X bytes from A to B that action occurs inside a Minor Loop.
* However, If I'd want to have that copy operation start with a diffrenet offset each time a request fires then that Copy Minor Loop will start working inside a larger Major Loop.
* The Major Loop isn't a loop really, it's just waits uintil CITER reaches 0. At which point it finishes by applying it's own Major Loop offset.
*
* EDBG - Enable Debug Mode. The DMA stalls when a debugger is plugged in
*/
DMA_TCD0_BITER = HowManyTransfers;
DMA_TCD0_CITER = HowManyTransfers;
/*
* CITER - Current Major Loop Interation Cout. It's a counter that starts at the number of transfers we want to do (BITER - Beggining Iteration Count)
* and then decrements down until 0. When it reaches 0, we know that a transfer has finished and we can fire a INTMAJOR
* interrupt for example.
*
*/
//Minor Loop Offset Enabled, we pretty much always want to use it. And if not, we can juts set it to 0.
DMA_TCD0_NBYTES_MLOFFYES = BytesToTransfer | DMA_TCD_NBYTES_MLOFFYES_MLOFF(MinorLoopOffset); //<---- Crashes here!
/*
* NBYTES - How many bytes in total are we transfering per request? Think of it as the i<64 part in a for loop
* MLOFF - As described before, each time a Minor Loop finishes (a DMA request finishes) we add a offset to the Source and Destination adress
* ONLY IF the enable bits are set
*/
//DMA_TCD0_CSR = DMA_TCD_CSR_INTMAJOR(MajorInterrupt);
/*
* BWC - Bandwith Control
* If we want to slow the DMA down we can stall it every 4 or 8 CPU cycles. Writing a 0 here will have the DMA run at full speed.
*
* INTMAJOR - Setting this to 1 will couse the DMA to fire a interrupt when it finishes the transfer
*/
}
This is one function I am working on to setup the DMA. The clock for the DMA in the CCM_CCGR5 register has already been activated like so: CCM_CCGR5 |= CCM_CCGR5_DMA(CCM_CCGR_ON) before this function. The CPU executes the DMA_CR, DMA_TCD0_BITER, DMA_TCD0_CITER lines just fine, however crashes instantly on the DMA_TCD0_NBYTES_MLOFFYES line. And I can’t figure out why?
What am I missing? I couldn't find (or missed) any mention of a seperate action I have to perform before I can use this register.
Thank You for the help.