S32K 3-Wire SPI Drivers

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

S32K 3-Wire SPI Drivers

4,114 Views
Vijay_Arwapally
Contributor III

@nxp, @danielmartynek 

Can you provide me with example drivers for 3 Wire SPI or Half Duplex configuration?

SDK doesn't seem to have this capability directly.

Transaction with sensors looks like below:

Vijay_Arwapally_0-1632129021555.png

 

Tags (1)
0 Kudos
20 Replies

1,041 Views
Jembed
Contributor II

Hello @danielmartynek,

I want to use S32K148 LPSPI module to communicate with a RF module. I don't want to use SDK or RTD drivers. The module interface is based on 3-wire SPI (half duplex). The communication method is that first I send a byte(register address) on the data line and then the slave module puts a byte(register read data) on the SDIO (data line) in response. 

The image below is a part of the slave module datasheet. As shown in the picture, the manufacturer recommends that the MCU changes the state of its data line to the input before the last falling edge of the clock, so that it does not overlap with the time, slave turns to output state (which occurs after the mentioned falling edge). 

Jembed_1-1700314100605.png

As I have specified in the image above, I assume that the MCU changes the state of the SDIO line to input, after the recommended edge, and there is an interval of time in which both sides are at output state.

I want to use the register level routine, introduced in this topic. What should I do to make sure that the warned contention will not occur on the SDIO line?

Thanks a lot

0 Kudos

3,822 Views
danielmartynek
NXP TechSupport
NXP TechSupport

Hello @Vijay_Arwapally,

If you don't have to use SDK, the new RTD LPSPI driver supports the half-duplex mode.

danielmartynek_1-1634311714432.png

If you need to keep CS asserted between the TX and the RX functions, you would need to use GPIO as CS and disconnect the LPSPI signal from the pin in the PORT module.

 

Regards,

Daniel

0 Kudos

4,019 Views
Vijay_Arwapally
Contributor III

@danielmartynek:

Tried the above approach by modifying the required implementation in SDK files.

Below are the issues currently being faced:

Weather RXMSK is set/cleared, RDR has no valid data. Always reads Zero. Is there something I missing here?

RX Interrupt is triggered and the length seems to be matching with data on bus, but the data value isn't populated to RDR register.

0 Kudos

4,009 Views
danielmartynek
NXP TechSupport
NXP TechSupport

Hi @Vijay_Arwapally,

If RXMSK = 1, the RX data are masked so this is expected.

Please close the register/memory views in the debugger so that it can't read the RDR register.

The SDK does not support this implementation and I can't help you with the modifications.

I would focus on the TCR register and how the commends are being written.

But I think it would be easier to write your own LPSPI functions.

 

Regards,

Daniel

 

0 Kudos

3,980 Views
Vijay_Arwapally
Contributor III

@danielmartynek 

Tried to perform the below operation, but still unable to get the SPI transaction correct on the bus:

 

Command byte is 0x8F, expected 1 byte response from slave device.

 

Code snippet:

  while((LPSPI1->SR & LPSPI_SR_TDF_MASK)>>LPSPI_SR_MBF_SHIFT!=0);

  /* Reset FIFO */

  LPSPI1->CR |= LPSPI_CR_RRF(1)|LPSPI_CR_RTF(1);

  LPSPI1->CR |= LPSPI_CR_RRF(1)|LPSPI_CR_RTF(1);

  LPSPI1->SR = 0x3F00;

 

 

  /* Check for FIFO availablity */

  while((LPSPI1->SR & LPSPI_SR_TDF_MASK)>>LPSPI_SR_TDF_SHIFT==0);

  LPSPI1->TCR   = LPSPI_TCR_CPOL(1) | LPSPI_TCR_CPHA(1)|LPSPI_TCR_LSBF(0)|LPSPI_TCR_CONT(1)

                             |LPSPI_TCR_PRESCALE(2)

                             |LPSPI_TCR_PCS(0)

                             |LPSPI_TCR_FRAMESZ(7)|LPSPI_TCR_RXMSK(1);

  /* Send cmd byte of 0x8F */

  LPSPI1->TDR = 0x8F;

 

  /* Send command with TXMSK for response */

  while((LPSPI1->SR & LPSPI_SR_TDF_MASK)>>LPSPI_SR_TDF_SHIFT==0);

  LPSPI1->TCR = LPSPI_TCR_CPOL(1) | LPSPI_TCR_CPHA(1)|LPSPI_TCR_LSBF(0)|LPSPI_TCR_CONTC(1)|LPSPI_TCR_CONT(1)

                                           |LPSPI_TCR_PRESCALE(2)

                                           |LPSPI_TCR_PCS(0)

                                           |LPSPI_TCR_FRAMESZ(7)|LPSPI_TCR_RXMSK(0)|LPSPI_TCR_TXMSK(1);

 

 

  /* End of transfer */

  while((LPSPI1->SR & LPSPI_SR_TDF_MASK)>>LPSPI_SR_TDF_SHIFT==0);

  LPSPI1->TCR = ((LPSPI1->TCR) & (~LPSPI_TCR_CONTC_MASK));

 

 

Logic analyser Capture:

Vijay_Arwapally_0-1633586225566.png

 

 

Can you please let me know why isn’t the CS extending for the TXMSK byte?

Tags (1)
0 Kudos

3,969 Views
Vijay_Arwapally
Contributor III

@danielmartynekAny comments on the code snippet?

0 Kudos

3,961 Views
danielmartynek
NXP TechSupport
NXP TechSupport

Hi @Vijay_Arwapally,

Please try without CONT/CONTC, these are for continuous transfer.

Do you see any LPSPI error flags?

Can you share the project so that I can test it?

 

Regards,

Daniel

0 Kudos

3,952 Views
Vijay_Arwapally
Contributor III

@danielmartynekAttached the sample project. CONT/CONTC needs to used, as I would need continuous transfer, without CS being reasserted for command and response.

0 Kudos

3,942 Views
danielmartynek
NXP TechSupport
NXP TechSupport

The project you posted uses SDK. I don't see the code you posted earlier.

Is this really it?

 

 

0 Kudos

3,933 Views
Vijay_Arwapally
Contributor III

Sorry for the wrong upload, Attached the correct project.

0 Kudos

3,886 Views
Vijay_Arwapally
Contributor III

@danielmartynek  Did you get a chance to review the code?

0 Kudos

3,878 Views
danielmartynek
NXP TechSupport
NXP TechSupport

Hi @Vijay_Arwapally,

I modified the project (attached), especially the LPSPI1_ReadReg() function.

I get 0x8F80 on the bus.

danielmartynek_0-1633955073379.png

Probably because I don't use any slave on the bus and the data line slowly discharges.

 

Regards,

Daniel

 

 

 

 

 

 

0 Kudos

3,856 Views
Vijay_Arwapally
Contributor III

@danielmartynekThis seems like working for only 1 byte read from slave.

What would be the sequence to TCR, incase it is required to read multiple bytes from slave?

Below sequence to TCR doesn't seem to work:

/* Check for FIFO availablity */
while((LPSPI1->SR & LPSPI_SR_TDF_MASK)>>LPSPI_SR_TDF_SHIFT==0);
LPSPI1->TCR = LPSPI_TCR_CPOL(1) | LPSPI_TCR_CPHA(1)|LPSPI_TCR_LSBF(0)|LPSPI_TCR_CONT(1)
|LPSPI_TCR_PRESCALE(2)
|LPSPI_TCR_PCS(0)
|LPSPI_TCR_FRAMESZ(7)|LPSPI_TCR_RXMSK(1)|LPSPI_TCR_TXMSK(0);
/* Send cmd byte of 0x8F */
LPSPI1->TDR = 0x8F;

/* Send command with TXMSK for response */
while((LPSPI1->SR & LPSPI_SR_TDF_MASK)>>LPSPI_SR_TDF_SHIFT==0);
LPSPI1->TCR = LPSPI_TCR_CPOL(1) | LPSPI_TCR_CPHA(1)|LPSPI_TCR_LSBF(0)|LPSPI_TCR_CONTC(1)|LPSPI_TCR_CONT(1)
|LPSPI_TCR_PRESCALE(2)
|LPSPI_TCR_PCS(0)
|LPSPI_TCR_FRAMESZ(7)|LPSPI_TCR_RXMSK(0)|LPSPI_TCR_TXMSK(1);

/* Send command with TXMSK for response */
while((LPSPI1->SR & LPSPI_SR_TDF_MASK)>>LPSPI_SR_TDF_SHIFT==0);
LPSPI1->TCR = LPSPI_TCR_CPOL(1) | LPSPI_TCR_CPHA(1)|LPSPI_TCR_LSBF(0)|LPSPI_TCR_CONTC(1)|LPSPI_TCR_CONT(1)
|LPSPI_TCR_PRESCALE(2)
|LPSPI_TCR_PCS(0)
|LPSPI_TCR_FRAMESZ(7)|LPSPI_TCR_RXMSK(0)|LPSPI_TCR_TXMSK(1);

while((LPSPI1->SR & LPSPI_SR_TDF_MASK)>>LPSPI_SR_TDF_SHIFT==0);
LPSPI1->TCR = LPSPI_TCR_CPOL(1) | LPSPI_TCR_CPHA(1)|LPSPI_TCR_LSBF(0)|LPSPI_TCR_CONTC(0)|LPSPI_TCR_CONT(0)
|LPSPI_TCR_PRESCALE(2)
|LPSPI_TCR_PCS(0)
|LPSPI_TCR_FRAMESZ(7)|LPSPI_TCR_RXMSK(0)|LPSPI_TCR_TXMSK(1);

0 Kudos

3,846 Views
Vijay_Arwapally
Contributor III

@danielmartynek  Also is there a better way to use FIFO, for TXMSK(1), without using RDF flag set status.

We would need a final driver to work in interrupt manner rather than polling mechanism.

0 Kudos

3,839 Views
danielmartynek
NXP TechSupport
NXP TechSupport

Hello@Vijay_Arwapally,

I haven't tested the new code, but I assume it does not work because you don't read the RX data.

Do you use the Receive Error Flag set?

You can increase the RXWATER level from 0, the RDF will be set once there are 3 words - for example, and then you can read the FIFO until RDF = 0.

And as you mentioned, you can use the Receive Data Interrupt (IER_RDIE) instead of polling.

 

BR, Daniel

 

0 Kudos

4,104 Views
danielmartynek
NXP TechSupport
NXP TechSupport

Hi @Vijay_Arwapally,

You can pass NULL to the receiveBuffer parameter.

danielmartynek_0-1632133587767.png

And you don't have to use any pin for the MISO signal in the PORT module.

 

Regards,

Daniel

 

 

0 Kudos

4,101 Views
Vijay_Arwapally
Contributor III

@danielmartynekThe communication to the interfaced sensor isn't unidirectional. S32K has to send and receive data from the sensor, as specified in the diagram.

Passing a NULL to receive isn't valid, basically the master still need to provide clk and cs while the data line is driven by slave.

Your answer doesn't seem to right in this context.

0 Kudos

4,094 Views
danielmartynek
NXP TechSupport
NXP TechSupport

I see, thank you.

The SDK does not support that but the LPSPI module does.

Please refer to the RM.

danielmartynek_0-1632135896990.pngdanielmartynek_1-1632135963889.pngdanielmartynek_2-1632136013826.png

 

Regards,

Daniel

 

 

0 Kudos

4,089 Views
Vijay_Arwapally
Contributor III

@danielmartynek:

Can you provide some additional information abt these register fields? how should they be controlled in below situations?

1. S32K sends 'n' bytes data to Sensor, no response expected.

2. S32K sends 'x' bytes of command, expected 'n' bytes response from slave, additionally PCS line shouldn't be re-asserted.

0 Kudos

4,084 Views
danielmartynek
NXP TechSupport
NXP TechSupport

Hi @Vijay_Arwapally,

You need to use different commands for the operations.

Please note that the Transmit Command Register (TCR) is not just a register, it is a FIFO, so do not use read-modify-write operations on the register but write the register with 32bit words.

In order to send data, first write a command with RXMSK set and then all the data to the Transmit Data Register (TDR).

To receive a frame from the Slave device, write a command with TXMSK set.

Please read Section 51.4.2.1 Transmit and Command FIFO commands in the RM.

 

Regards,

Daniel

0 Kudos