K64 SPI + DMA eats Data

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

K64 SPI + DMA eats Data

1,760 Views
JHinkle
Senior Contributor I

I'm hoping someone can explain this behavior

K64 SPI set for 8 bit transfers, FIFO disabled, fed by DMA

Before the SPI process takes place -- as a note -- the CMD 16 bits of the SPI's Push Register is zero (0).

DMA is set for 8 bit transfers.

No CMD pushed into the SPI by the application.

The SPI transfer is started by setting DMA_SSRT

The Source pointer of the DMA channel is pointing to memory which holds an array of bytes increasing by 1.

Data array ===   0,1,2,3,4,5 ..... 255

I use a logic probe to capture the actual SPI data and clock coming off the K64

Data on MOSI line is ====  0,1,3,4,5 ... 255

Notice byte three (3) of the input data (byte value 2) is eaten and never appears on the MOSI line out of the K64. 

NXP/Freescale has never really published good documentation on using DMA with SPI and only pushing DATA - never the upper 16 bits of COMMAND.

Is there any published documentation that can explain this behavior?

Any ideas as to why byte 3 is ALWAYS eaten and never appears on the output?

Note:  the rest of the data is always transferred - independent of number of bytes -- the behavior is only at the start of the transfer and always byte 3

Thanks.

Joe

Tags (3)
15 Replies

1,260 Views
JHinkle
Senior Contributor I

Mike

Never mind - I solved it.

It turn out the issue was me -- I think I was attempting to start the DMA twice

Code that causes the issue ... from above

SPI1_RSER = My_SPI_RSER; // spi serviced by dma

DMA_SSRT = DMA_SSRT_SSRT(12); // start transfer

Turns out the DMA transfer is NOT started with the write to DMA_SSRT but starts with the write to SPI1_RSER 

SPI1_RSER = My_SPI_RSER; // spi serviced by dma

//DMA_SSRT = DMA_SSRT_SSRT(12); // start transfer

By removing the DMA_SSRT  line -- all is correct and now well understood.

Thanks for helping.

Joe

1,260 Views
Hui_Ma
NXP TechSupport
NXP TechSupport

Hi Joe,

Thank you let us know the root cause.

best regards,

Mike

0 Kudos

1,260 Views
JHinkle
Senior Contributor I

Mike

Link below is the most basic - bare-metal implementation of the test to illustrate the issue.

I use Crossworks as my development IDE so I don't think you can outright use the project but there are only a couple of files required to import the test into your own development IDE.

I am running on a Custom K64 board that has a 25mhz oscillator.  Clocks.c is used to set the CPU clock to 120mhz.  Your implementation will change depending on the board you use to test and what crystal/oscillator is driving it.

By default the SPI Push register comes up as Zero so there is no need to prime the upper 16 bits for command.

Thanks for taking the time to investigate this.

As a side note - in the process of checking out this implementation I set my break point inside the actual Perform_SPI_Xfer() and the output did NOT show the missing third byte. 

That is a puzzle!!! 

Since the real application does not pause keep your break point at the actual call to Perform_SPI_Xfer() and let you logic probe capture the output -- no DMA errors, and byte 3 is missing.

Found out where the DMA error came from you earlier noted -- if you set break points within Perform_SPI_Xfer() you can cause the DMA error to set.

Thanks.

Joe

http://www.joehinkle.com/download/SPI_DMA_Test_Project.zip

0 Kudos

1,260 Views
JHinkle
Senior Contributor I

Mike:

I will create a bare-bones project that demonstrates the issue.

It may take me a day or two to accomplish.

Thanks.

Joe 

0 Kudos

1,260 Views
Hui_Ma
NXP TechSupport
NXP TechSupport

Thank you, Joe.

0 Kudos

1,260 Views
JHinkle
Senior Contributor I

Mike:

I can't explain that DMA error.

I can tell you that I just ran the test above (code cycles every 25 msec writing out the test data) for the last hour with no DMA errors yet every run byte 3 of the input stream is missing from the output stream.

Thanks.

Joe

0 Kudos

1,260 Views
Hui_Ma
NXP TechSupport
NXP TechSupport

Hi Joe,

Thanks.

Could you post your test project here?

If not possible, just post SPI0 and eDMA related code.

I will do a test on my site with FRDM-K64F board next week.

best regards,

Mike

0 Kudos

1,260 Views
JHinkle
Senior Contributor I

Thanks for looking into this Mike

Below is a snap shot just before kicking off the SPI-DMA transfer.

You can see the SPI code in the editor window, the array of data to be transferred in the bottom memory window, and all the SPI1 registers just prior to starting the process

SPI1.png

Here is the capture of that SPI transfer - notice that the output goes 0,1,3,4.

The third byte should be 2 but its 3

Logic1.png

I've attached pictures of the DMA registers for your review.

I've also included the complete logic probe capture should you want to dig into it further.

Thanks again.

Joe

http://www.joehinkle.com/download/SPI Capture.logicdata

http://www.joehinkle.com/download/DMA20.png

http://www.joehinkle.com/download/DMA21.png

http://www.joehinkle.com/download/DMA22.png

http://www.joehinkle.com/download/DMA23.png

http://www.joehinkle.com/download/DMA24.png

https://community.nxp.com/thread/joehinkle.com/download/SPI Capture.logicdata

0 Kudos

1,260 Views
Hui_Ma
NXP TechSupport
NXP TechSupport

Hi Joe,

From the DMA register value, I could find there with error at channel 13:

pastedImage_1.png

The error type is a source read bus error.

From your DMA initialization code, what's the "dword" definition?pastedImage_2.png

Have a great day,
Mike

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 Kudos

1,260 Views
JHinkle
Senior Contributor I

Mike

Early on in the application I write a 32 bit zero to the push register to properly load the upper 16 bits.

Since only DMA loads the SPI after the initial 32 bit zero is pushed -- the upper 16 bits never change.

I manually set and clear the SPI chip select since it is normally in the upper 16 bits of the SPI Push register -- but I keep that at zero.

Thanks for thinking some more on this issue.

Joe

0 Kudos

1,260 Views
Hui_Ma
NXP TechSupport
NXP TechSupport

Hi Joe,

Do you have recorded the SPI communication signals?

With the SPI_TX signal we could analyze the actual communication behavior.

pastedImage_1.png


Have a great day,
Mike

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 Kudos

1,260 Views
Hui_Ma
NXP TechSupport
NXP TechSupport

Hi,

From the posted code, I don't find there with any code to write the SPIx_PUSHR high 16-bit command filed.

Could you probe the SPI communication signals?

If there with chip select signal asserted during SPI communication?


Have a great day,
Mike

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 Kudos

1,260 Views
JHinkle
Senior Contributor I

If it is helpful - 

Here is my DMA and SPI setup.

[CODE]

********************************************

DMA

********************************************

DMA_CERQ = DMA_CERQ_CERQ(13) ; // now disable chan13 for triggers
DMA_TCD13_SOFF = 1; // 1 byte move address offset 
DMA_TCD13_ATTR = DMA_ATTR_SMOD(0) | DMA_ATTR_SSIZE(0) | DMA_ATTR_DMOD(0) | DMA_ATTR_DSIZE(0); // no circular addressing S&D, 8 bit S&D 
DMA_TCD13_NBYTES_MLNO = 1; // 8bit sample every minor loop 
DMA_TCD13_NBYTES_MLOFFNO = 1;
DMA_TCD13_NBYTES_MLOFFYES = 1;
DMA_TCD13_SLAST = 0; // not needed -- IRQ will set new start
DMA_TCD13_DOFF = 0; // no offset - always spi xmit
DMA_TCD13_DLASTSGA = 0; // no final last adjustment ( does not move )
DMA_TCD13_CSR = DMA_CSR_INTMAJOR_MASK ; // interrupt when done 
DMA_TCD13_DADDR = (dword)&SPI0_PUSHR;

********************************************

SPI

******************************************

SPI0_SR = 0xffff0000; // clear all pending status flags

SPI0_MCR = SPI_MCR_MSTR_MASK | // master mode
SPI_MCR_DIS_TXF_MASK |
SPI_MCR_CLR_RXF_MASK | SPI_MCR_CLR_TXF_MASK | // // clr both FIFO's .. debug
SPI_MCR_PCSIS(0); // no chip selects

My_SPI_RSER = SPI_RSER_TFFF_RE_MASK | SPI_RSER_TFFF_DIRS_MASK; // xmit avail dma flag

SPI0_CTAR0 = SPI_CTAR_FMSZ(7) | // Data is 8 bits

SPI_CTAR_DBR_MASK | // double clock speed so baud is 12mhz

SPI_CTAR_CPOL_MASK | // Clock Polarity HI at Idle
SPI_CTAR_CPHA_MASK | // Clock Phase - out on leading edge, in on falling
SPI_CTAR_PCSSCK(0) | // delay prescaler - CS and Clock Edge
SPI_CTAR_PASC(0) | // delay prescaler - last clk edge and CS off
SPI_CTAR_PDT(0) | // delay prescaler between CS off and CS on -- between frames
SPI_CTAR_PBR(2) | // Bard Rate .. 2 == divide by 5 ... 60/5 = 12
SPI_CTAR_CSSCK(0) | // actual delay between CS and first clk edge
SPI_CTAR_ASC(0) | // actual delay last clk and CS off
SPI_CTAR_DT(0) | // actual delay between frames 
SPI_CTAR_BR(0); // baud rate scaler ... 12 / 2 = 6

DMA_TCD13_SADDR = (dword)Work.Data;


DMA_TCD13_CITER_ELINKNO = NumberOfBytes;
DMA_TCD13_BITER_ELINKNO = NumberOfBytes;

SPI0_MCR |= SPI_MCR_CLR_TXF_MASK; // clear any waiting data

DMA_SERQ = DMA_SERQ_SERQ(13) ; // now enable chan13 for triggers

SPI0_RSER = My_SPI_RSER;

DMA_SSRT = DMA_SSRT_SSRT(13); // start transfer

[/CODE]

0 Kudos

1,260 Views
JHinkle
Senior Contributor I

Thanks for the reply but I don't think your statement addresses the issue.

Please see post https://community.nxp.com/thread/381726

That's on a K80 but I suspect the SPI and DMA cells are the same on a K64

As I said in the post, the upper 16 bits of the push register are zero and I agree - they are passed to the SPI as a command.  A SPI command of zero (0) does not affect or explain the third byte missing from the output steam.

I've been using this SPI DMA combination for a while now.  I have a work-around that provides the first 3 bytes of the input with known data and the receiver ignores the first two bytes it receives.

I was hoping a long term Freescale engineer was still around that could explain why this occurs.

0 Kudos

1,260 Views
Hui_Ma
NXP TechSupport
NXP TechSupport

Hi,

Please check below description about SPIx_PUSHR register write requirement:

pastedImage_1.png

When you are using DMA mode, it need to transfer all 32bits (command+8bit data) to this register at the same time.

Thank you for the attention.


Have a great day,
Mike

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 Kudos