S32K344 bare-metal DMA initialization

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

S32K344 bare-metal DMA initialization

Jump to solution
649 Views
mateusz_swiszcz
Contributor II

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;
}

 

0 Kudos
Reply
1 Solution
558 Views
danielmartynek
NXP TechSupport
NXP TechSupport

HI Mateusz,

Thanks for the project.

 

First, I enabled DMAMUX_0_CH0 at 4028_0000h + 0x3.

IP_DMAMUX_0->CHCFG[3] = 0xAE;

danielmartynek_0-1743512787294.png

 

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:

danielmartynek_1-1743513063363.png

 

Regards,

Daniel

View solution in original post

8 Replies
630 Views
danielmartynek
NXP TechSupport
NXP TechSupport

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

 

0 Kudos
Reply
602 Views
mateusz_swiszcz
Contributor II
Hi,

I disabled a source address offset but nothing changed. There's no error flags in EDMA. I have buffers in non-cacheable SRAM. 

NVIC->ISER[0] = 0x10; NVIC->ISER[5] = 0x40; NVIC->ICER[0] = 0x10; NVIC->ICER[5] = 0x40

EDMA->CSR = 0x300000

Other register fields in EDMA and NVIC are null.
0 Kudos
Reply
588 Views
danielmartynek
NXP TechSupport
NXP TechSupport

Hi @mateusz_swiszcz,

Could you share the whole project so that I can test it?

It can be shared privately via a support ticket.

 

 

0 Kudos
Reply
566 Views
mateusz_swiszcz
Contributor II

Hi, @danielmartynek 

The whole projects is in the attachment.

0 Kudos
Reply
559 Views
danielmartynek
NXP TechSupport
NXP TechSupport

HI Mateusz,

Thanks for the project.

 

First, I enabled DMAMUX_0_CH0 at 4028_0000h + 0x3.

IP_DMAMUX_0->CHCFG[3] = 0xAE;

danielmartynek_0-1743512787294.png

 

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:

danielmartynek_1-1743513063363.png

 

Regards,

Daniel

448 Views
mateusz_swiszcz
Contributor II

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?

0 Kudos
Reply
444 Views
danielmartynek
NXP TechSupport
NXP TechSupport

Hi @mateusz_swiszcz,

Here is the offset of the registers:

danielmartynek_0-1744022054705.png

danielmartynek_1-1744022091817.png

 

501 Views
mateusz_swiszcz
Contributor II
Thanks for the help, it works
0 Kudos
Reply