I've got a problem with DMA init. I was unable to initialize DMA by using bare-metal programming. The interrupt is not called and no data is passed. Meanwhile interrupt from SPI is working. Could you check my DMA configuration? I also set a "LPSPI_DER_RDDE" bit in "IP_LPSPI/n/->DER" register. This should set DMA for receive data.
void DMA_Init(volatile uint32_t rxBuffer) {
/*
For remaining S32K3xx devices: DMAMUX_0 channel 0-15 and DMAMUX_1 channel 0-15 are
mapped to eDMA Transfer Control Descriptor(TCD) 0-15 and eDMA Transfer Control Descriptor(TCD)
16-31, respectively
*/
// TCD register init
IP_TCD->TCD0_SADDR = 0U;
IP_TCD->TCD0_SOFF = 0;
IP_TCD->TCD0_ATTR = 0U;
IP_TCD->NBYTES0.TCD0_NBYTES_MLOFFNO = 0U;
IP_TCD->NBYTES0.TCD0_NBYTES_MLOFFYES = 0U;
IP_TCD->TCD0_SLAST_SDA = 0;
IP_TCD->TCD0_DADDR = 0U;
IP_TCD->TCD0_DOFF = 0;
IP_TCD->CITER0.TCD0_CITER_ELINKNO = 0U;
IP_TCD->CITER0.TCD0_CITER_ELINKYES = 0U;
IP_TCD->TCD0_DLAST_SGA = 0;
IP_TCD->TCD0_CSR = 0U;
IP_TCD->BITER0.TCD0_BITER_ELINKNO = 0U;
IP_TCD->BITER0.TCD0_BITER_ELINKYES = 0U;
//===== DMA MUX =====//
// Enable a source without periodic triggering
// 1. Determine the DMA channel with which the source is associated.
// LPSPI1 DMA RX Request -> Source 46
// 2. Write 0 to CHCFGn[ENBL] and CHCFGn[TRIG] of the DMA channel.
IP_DMAMUX_0->CHCFG[0] &= ~DMAMUX_CHCFG_ENBL_MASK;
IP_DMAMUX_0->CHCFG[0] &= ~DMAMUX_CHCFG_TRIG_MASK;
// 3. You can enable the DMA channel at this point.
IP_DMAMUX_0->CHCFG[0] |= DMAMUX_CHCFG_ENBL_MASK;
// 4. Select the source to be routed to the DMA channel.
IP_DMAMUX_0->CHCFG[0] |= DMAMUX_CHCFG_SOURCE(46);
//===== eDMA =====//
// 1. Write to the CSR if a configuration other than the default is wanted.
// 2. Write the channel priority levels to the CHn_PRI registers and group priority levels to the CHn_GRPRI registers if a
// configuration other than the default is wanted.
// 3. Enable error interrupts in the CHn_CSR[EEI] registers if they are wanted.
// 4. Write the 32-byte TCD for each channel that may request service.
// CH0_SBR_MID: Default master id -> 0b10
// Source address -> SPI receive buffer
IP_TCD->TCD0_SADDR = IP_LPSPI_1->RDR;
// Destination address
IP_TCD->TCD0_DADDR = rxBuffer;
// Source Address Offset
IP_TCD->TCD0_SOFF = 4;
// Destination Address Offset
IP_TCD->TCD0_DOFF = 4;
// Source size: 32-bit
IP_TCD->TCD0_ATTR |= DMA_TCD_TCD0_ATTR_SSIZE(0b10);
// Destination size: 32-bit
IP_TCD->TCD0_ATTR |= DMA_TCD_TCD0_ATTR_DSIZE(0b10);
// 4 byte transfer
IP_TCD->NBYTES0.TCD0_NBYTES_MLOFFNO = 4;
// Current Major Loop Count
IP_TCD->CITER0.TCD0_CITER_ELINKNO = 1;
// Beginning Major Loop Count
IP_TCD->BITER0.TCD0_BITER_ELINKNO = 1;
// Interrupt after transfer is complete
IP_TCD->TCD0_CSR |= DMA_TCD_TCD0_CSR_INTMAJOR_MASK;
// Enable interrupt
__NVIC_ClearPendingIRQ(DMATCD0_IRQn);
__NVIC_SetPriority(DMATCD0_IRQn, 0);
__NVIC_EnableIRQ(DMATCD0_IRQn);
// 5. Enable any hardware service requests via the CHn_CSR[ERQ] registers.
IP_TCD->CH0_CSR |= DMA_TCD_CH0_CSR_ERQ_MASK;
}
void DMATCD0_Handler(void) {
// Print rxBuffer
printf("rxBuffer: %ld", rxBuffer);
// Clear interrupt request
IP_TCD->CH0_INT = 1;
}
Solved! Go to Solution.
HI Mateusz,
Thanks for the project.
First, I enabled DMAMUX_0_CH0 at 4028_0000h + 0x3.
IP_DMAMUX_0->CHCFG[3] = 0xAE;
Then I saw that SBE = 1 Source bus error in the TCD0 descriptor.
The TCD0_SADDR register was not configured (checked in the register view)
IP_TCD->TCD0_SADDR = &IP_LPSPI_1->RDR;
Now, it gets to the DMA handler:
Regards,
Daniel
Hi @mateusz_swiszcz,
You should not offset the source address (TCD0_SOFF), but otherwise I don't see any issue in the code.
Is there any error flag set in EDMA?
Do you have the buffers in non-cacheable SRAM?
Can you dump the EDMA and NVIC registers and share it?
Thanks,
Daniel
Hi @mateusz_swiszcz,
Could you share the whole project so that I can test it?
It can be shared privately via a support ticket.
HI Mateusz,
Thanks for the project.
First, I enabled DMAMUX_0_CH0 at 4028_0000h + 0x3.
IP_DMAMUX_0->CHCFG[3] = 0xAE;
Then I saw that SBE = 1 Source bus error in the TCD0 descriptor.
The TCD0_SADDR register was not configured (checked in the register view)
IP_TCD->TCD0_SADDR = &IP_LPSPI_1->RDR;
Now, it gets to the DMA handler:
Regards,
Daniel
Hi, @danielmartynek
Why does CHCFG[3] works and CHCFG[0] not when I'm using TCD0 and Channel 0 of DMA? How can i match numbers of CHCFG[n], TCDn, CHn in case of other instances of SPI or other peripheries?