LPSPI RX DMA setup (non-PIT-triggered)

取消
显示结果 
显示  仅  | 搜索替代 
您的意思是: 
已解决

LPSPI RX DMA setup (non-PIT-triggered)

跳至解决方案
3,323 次查看
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 项奖励
回复
1 解答
3,275 次查看
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 项奖励
回复
4 回复数
3,177 次查看
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 项奖励
回复
3,167 次查看
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 项奖励
回复
3,242 次查看
alex_baril
Contributor I

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

0 项奖励
回复
3,276 次查看
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 项奖励
回复