S32K144:SPI Transfer with GPIO as CS

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

S32K144:SPI Transfer with GPIO as CS

Jump to solution
2,947 Views
bjrajendra
Senior Contributor I

Hello all,

 

I tried to use SPI transfer with CS as GPIO. I'm performing following steps.

 

1. Making the CS LOW

2. Pushing to data in the FIFO

3. Making the CS HIGH

 

I'm able to transfer the data but my CS goit HIGH (Step 3) Far ahead of the transfer.

CS_LOW;

LPSPI0->TDR = LPSPI_TDR_DATA(n) ; 
while((LPSPI0->SR & LPSPI_SR_TCF_MASK)>>LPSPI_SR_TCF_SHIFT==0) {} 

CS_HIGH;

 

I tried waitng till 

while((LPSPI0->SR & LPSPI_SR_TCF_MASK)>>LPSPI_SR_TCF_SHIFT==0) {} 

 

Even I tried to wait for the FCF flag to set. I don't see any change considering by frame length as 7+1 bits

 

pastedImage_1.png

 

but, surprisingly the TCF, FCF, WCF flag will set immeadiately after writing the data into the tranmit buffer though theCS still holds the LOW.

 

Kindly help in this regard,

Raju

Labels (1)
0 Kudos
Reply
1 Solution
2,790 Views
danielmartynek
NXP TechSupport
NXP TechSupport

Hello Raju,

I'm not able to reproduce this behavior.

I tested the S32K144_Project_LPSPI example from S32DS with this modification:

void LPSPI1_transmit_16bits (uint16_t send)
{
    while((LPSPI1->SR & LPSPI_SR_TDF_MASK)>>LPSPI_SR_TDF_SHIFT==0);
    /* Wait for Tx FIFO available */

    PTD-> PCOR |= (1 << 0); // CS LOW
    LPSPI1->TDR = send; /* Transmit data */
 
    while((LPSPI1->SR & LPSPI_SR_TCF_MASK)>>LPSPI_SR_TCF_SHIFT==0) {}
    LPSPI1->SR |= LPSPI_SR_TCF_MASK;
 
    PTD-> PSOR |= (1 << 0); // CS HIGH
}‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

And it works:

pastedImage_1.png

Could you share your test project?

Thank you,

BR, Daniel

View solution in original post

0 Kudos
Reply
6 Replies
2,791 Views
danielmartynek
NXP TechSupport
NXP TechSupport

Hello Raju,

I'm not able to reproduce this behavior.

I tested the S32K144_Project_LPSPI example from S32DS with this modification:

void LPSPI1_transmit_16bits (uint16_t send)
{
    while((LPSPI1->SR & LPSPI_SR_TDF_MASK)>>LPSPI_SR_TDF_SHIFT==0);
    /* Wait for Tx FIFO available */

    PTD-> PCOR |= (1 << 0); // CS LOW
    LPSPI1->TDR = send; /* Transmit data */
 
    while((LPSPI1->SR & LPSPI_SR_TCF_MASK)>>LPSPI_SR_TCF_SHIFT==0) {}
    LPSPI1->SR |= LPSPI_SR_TCF_MASK;
 
    PTD-> PSOR |= (1 << 0); // CS HIGH
}‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

And it works:

pastedImage_1.png

Could you share your test project?

Thank you,

BR, Daniel

0 Kudos
Reply
2,790 Views
bjrajendra
Senior Contributor I

Hi Daniel,

 

Thanks for the response.

 

I tried as you suggested and now it's working fine.

 

But, I found my loop stuck in the line

while((LPSPI1->SR & LPSPI_SR_TCF_MASK)>>LPSPI_SR_TCF_SHIFT==0){} 

because after every transmit I tried to receive the data using

 

while((LPSPI0->SR & LPSPI_SR_RDF_MASK)>>LPSPI_SR_RDF_SHIFT==0){} 
receive= LPSPI0->RDR ;
LPSPI0->SR |= LPSPI_SR_RDF_MASK; /* Clear RDF flag */

It started working normally once I removed the below line while receiving the data.

LPSPI0->SR |= LPSPI_SR_RDF_MASK; /* Clear RDF flag */

Any explanation beyond this.

Raju

 

0 Kudos
Reply
2,790 Views
danielmartynek
NXP TechSupport
NXP TechSupport

Hi Raju,

The line that you removed does nothing anyway.

The RDF flag is a read only flag.

So I don't understand how this could help. 

pastedImage_1.png

Well, it will be stuck at the line below if there is no transfer that would need to be completed.

while((LPSPI1->SR & LPSPI_SR_TCF_MASK)>>LPSPI_SR_TCF_SHIFT==0){} 

The above example is just a very simple code to show that it works (CS deasserted once a transfer is complete), but it not a solution.

Can you share a test code?

BR, Daniel

0 Kudos
Reply
2,790 Views
bjrajendra
Senior Contributor I

Hi Daniel,

Attached is the project which will be behaved as mentioned in the previous post. 

Kindly check & confirm where exactly the mistake is?

Raju

0 Kudos
Reply
2,790 Views
danielmartynek
NXP TechSupport
NXP TechSupport

Hi Raju,

This is your code:

while((LPSPI0->SR & LPSPI_SR_TDF_MASK)>>LPSPI_SR_TDF_SHIFT==0) {}
LPSPI0->TDR = LPSPI_TDR_DATA(0x7A) ;

while((LPSPI0->SR & LPSPI_SR_RDF_MASK)>>LPSPI_SR_RDF_SHIFT==0){}
ret = LPSPI0->RDR ;

LPSPI0->SR |= LPSPI_SR_RDF_MASK; /* Clear RDF flag */

while((LPSPI0->SR & LPSPI_SR_TCF_MASK)>>LPSPI_SR_TCF_SHIFT==0) {}
LPSPI0->SR |= LPSPI_SR_TCF_MASK;‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

At the time you mask the RDF flag, the TCF flag is already set.

The read-modify-write operation (|=) reads the SR register with the TCF flag == 1 and writes it back to clear RDF.

But this cleared the TCF flag only.

In general, if you want to clear a w1c flag, don't use the read-modify-write operation but simply write the mask to the register.

Not this:

LPSPI0->SR |= LPSPI_SR_RDF_MASK; /* Clear RDF flag */

but this:

LPSPI0->SR = LPSPI_SR_RDF_MASK; /* Clear RDF flag */

Also, the RDF flag cannot be cleared by w1c.

The flag simply informs about the state of the RX FIFO.

You can clear the flag by reading the data from the RX FIFO only.

Regards,

Daniel 

0 Kudos
Reply
2,790 Views
bjrajendra
Senior Contributor I

Thanks Daniel for your valuable advice & Support.

 It really works & the information to clear a w1c flags using "=" operator instead of using read-modify-write operation (|=) really helps.

Actually I had looked into one of the example projects and followed the same procedure while reading & clearing the flag. Anyway, now everything works fine & once again many thanks for your support.

Raju

0 Kudos
Reply