LPSPI RX DMA setup (non-PIT-triggered)

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

LPSPI RX DMA setup (non-PIT-triggered)

Jump to solution
1,171 Views
alex_baril
Contributor I

I'm using a S32K344 EVB and trying to setup the DMA to transfer from the LPSPI RX buffer, but not using the PIT-based trigger.  I am sending 1 command word to a sensor and receiving back at least 2 words of data, and I want to have these automatically transferred to memory whenever the transaction takes place (not periodically).

My understanding on how to enable DMA transfers from reading the Reference Manual:

  • Receive Data DMA Enable (LPSPI DER)
  • DMAMUX enabled with correct source (46 for LPSPI1)
  • TCD set with proper source and destination addresses, offset, etc.
  • Enable DMA Request (TCD_CH0_CSR, ERQ bit)

I'm assuming the LPSPI Status Register, (RDF bit) is the peripheral trigger to the DMAMUX, and that routes the request to the eDMA Engine, and this is what kicks off the data transfer.  Is that correct?  Is there any software intervention required, like an ISR needed to clear any flags?  Or does it transfer everytime the RDF flag is pulsed?

I verified the SPI is working as expected with a logic analyzer and am able to see the RDR register has data in it from my sensor and the RDF flag set, but I don't see any data in the destination memory location.

I have attached my code, for reference.  Please help to point out what I might have missed.

-Alex

0 Kudos
Reply
1 Solution
1,123 Views
PetrS
NXP TechSupport
NXP TechSupport

Hi,

your understanding is correct. the Receive Data Flag (SR[RDF]) is set when the number of words in the receive FIFO is greater than RXWATER. For default RXWATER=0 and your 48bit frame size there should be 2 words in RXFIFO so you should set DMA to read single word per DMA request, there should be 2 DMA requests from LPSPI. You should modify TCD little bit

IP_TCD->TCD0_DLAST_SGA = -8;
// Last destination address adjustment after a major loop

IP_TCD->NBYTES0.TCD0_NBYTES_MLOFFNO = 4;
// 12 bytes per a minor loop

IP_TCD->CITER0.TCD0_CITER_ELINKNO = 2;
IP_TCD->BITER0.TCD0_BITER_ELINKNO = 2;
// 1 major/2 minor loop

You can check within debugger if setting of TCD is really a desired one, then after transfer check if channel interrupt flag is set and DONE bit as well.

Also cache enabled could be a reason you see no data in destination buffer, put buffer in noncacheable area
__attribute__(( aligned(32) )) uint32 RxMasterBuffer[20] __attribute__ ((section (".mcal_bss_no_cacheable")));

BR, Petr

View solution in original post

0 Kudos
Reply
4 Replies
1,025 Views
alex_baril
Contributor I

Hi Petr,

Thanks again for the help.  I found the issue and I have the DMA working as expected, but I am hoping you can help me understand a little better.  Here is the change I made that enabled the DMA to work:

changed IP_DMAMUX_0->CHCFG[0] = 0xAE     to       IP_DMAMUX_0->CHCFG[3] = 0xAE

I noticed in the "Watch registers" tab that CHCFG0 address is 0x4028000while CHCFG3 address is 0x40280000.  After I noticed this and made the change, I also read in the datasheet the register address offset is the same as reflected above, so this was my fault for not noticing.  

So then my questions is why is the address offset not lined up as CHCFG0 = 0, CHCFG1 = 1, etc.; and why is the S32K344_DMAMUX.h also not reflecting this same offset convention?

Thanks, -Alex

0 Kudos
Reply
1,015 Views
PetrS
NXP TechSupport
NXP TechSupport

Hi,

well, I overlooked that too, but it is stated within the RM, as you wrote. Answer can be simple... It is implemented this way.
A S32K344_DMAMUX.h should follow this. If not, user need to be care in using right register.

BR, Petr

0 Kudos
Reply
1,090 Views
alex_baril
Contributor I

Thanks for the reply, Petr.  I will try your suggestions and reply again with the results.

0 Kudos
Reply
1,124 Views
PetrS
NXP TechSupport
NXP TechSupport

Hi,

your understanding is correct. the Receive Data Flag (SR[RDF]) is set when the number of words in the receive FIFO is greater than RXWATER. For default RXWATER=0 and your 48bit frame size there should be 2 words in RXFIFO so you should set DMA to read single word per DMA request, there should be 2 DMA requests from LPSPI. You should modify TCD little bit

IP_TCD->TCD0_DLAST_SGA = -8;
// Last destination address adjustment after a major loop

IP_TCD->NBYTES0.TCD0_NBYTES_MLOFFNO = 4;
// 12 bytes per a minor loop

IP_TCD->CITER0.TCD0_CITER_ELINKNO = 2;
IP_TCD->BITER0.TCD0_BITER_ELINKNO = 2;
// 1 major/2 minor loop

You can check within debugger if setting of TCD is really a desired one, then after transfer check if channel interrupt flag is set and DONE bit as well.

Also cache enabled could be a reason you see no data in destination buffer, put buffer in noncacheable area
__attribute__(( aligned(32) )) uint32 RxMasterBuffer[20] __attribute__ ((section (".mcal_bss_no_cacheable")));

BR, Petr

0 Kudos
Reply