PSoC 6 SPI Slave TX problem

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
lock attach
Attachments are accessible only for community members.
PeBe_1604221
Level 3
Level 3
10 sign-ins 5 sign-ins 5 questions asked

Hi,

I have a problem implementing a SPI slave on a PSoC 6 device (CYBLE-416045-02). I have an interrupt routine on the Rx FIFO Not Empty event. It is working fine receiving data from the master. The problem is that when sending data back to the master, the bytes placed into the TX FIFO occur on MISO one byte later than expected.

I am clearing the TX FIFO at the beginning of a SPI frame using an interrupt on the SS line. Then, at the SPI interrupt after receiving the first byte, I place a byte into the TX FIFO (using Cy_SCB_SPI_Write) and expect that byte to appear on MISO when the next byte is clocked by the master, but it does not appear then, it only appears on the byte following the next one.

Attached is the code, and also an analyzer trace. Note that I am outputting some additional debug signals on spare pins to show when events are occurring.

I have tried many combinations of API calls to clear the FIFO at different times but nothing seems to fix this problem. I have also tried slowing down the clock from the master, which also increases the inter-byte spacing, but that also makes no difference. I have seen in other posts some talk of there being some inherent delay with writes to the TX FIFO, but I cannot find any hard information on this.

Any help with this would be very much appreciated.

Peter

0 Likes
1 Solution
PSa_795526
Level 4
Level 4
First question asked 10 sign-ins First like given

Hi Peter,

If you are using the default Mode 0(CPHA=0,CPOL=0) of SPI, then this behavior is probably occurring because the next byte to be sent out by the SPI slave is already loaded on the last clock edge (falling edge) of the previous byte itself. Below is a screenshot of the SPI component timing diagram that shows this:

SPI mode 0 last clock edge data transfer screenshot.jpg

So, in your case, the data is loaded in the last clock edge when the address byte is transmitted itself.

To overcome this, would it be possible to try:

1) Loading the Tx FIFO with data on or before the address byte(first byte) transmission from the master ?

But if this does not satisfy your application requirement(where the response data is decided only after the first address byte), then can you try:

2) Changing the SPI SCLK mode to Mode 1(CPHA=1,CPOL=0). In this mode, the loading of the shift register seems to happen only the first clock edge of the current byte, as shown in the below screenshot:

SPI mode 1 first clock edge data transfer screenshot.jpg

But note that the SPI master also has to be changed to this mode.

3) Or (on the SPI master's side) try lifting up the SPI SS after the first address byte, and lowering it before the next response byte (in between which you can load the slave response byte into the Tx FIFO).

Best Regards,

Prem Sai

View solution in original post

8 Replies
MotooTanaka
Level 9
Level 9
Distributor - Marubun (Japan)
First comment on blog Beta tester First comment on KBA

Hi,

I have seen an exactly same behavior of SPI Slave in a PSoC 5LP.

At that time, I was explained that because of nature of SPI Slave,

when writing an array to the TxBuffer, the first byte is written as 0

then the data we wanted to write was written from the second byte.

To avoid this they provided an API

   SPIS_WriteTxDataZero()

which will place the data at the first byte/word.

And I think that for the PSoC 6, they implemented SPI Slave similarly.

But so far, I have not been able to find a counterpart function of SPIS_WriteTxDataZero() for PSOC 6.

May be there is one with different name or may be they decided that the programmer needs to take care of it somehow.

moto

0 Likes

Thanks Motto for your response. It helps to know that someone else has seen something similar.

I had a look through the available PSoC 6 functions and I also could not find anything like the "zero" function you found for PSoC 5.

I hope we get something meaningful from Cypress on this one.

Peter

Here is a snip from the PDL documentation:

Cy_SCB_SPI_Write()

__STATIC_INLINE uint32_t Cy_SCB_SPI_Write(CySCB_Type *base,
uint32_tdata
)

Places a single data element in the SPI TX FIFO.

This function does not block. It returns how many data elements were placed in the TX FIFO.

Parameters
baseThe pointer to the SPI SCB instance.
dataData to put in the TX FIFO. The element size is defined by the data type, which depends on the configured TX data width.
Returns
The number of data elements placed in the TX FIFO: 0 or 1.
Note
  • When in the master mode, writing data into the TX FIFO starts an SPI transfer.
  • When in the slave mode, writing data into the TX FIFO does not start an SPI transfer. The data is loaded in the TX FIFO and will be sent to the master on its request.
  • The SPI interface is full-duplex, therefore reads and writes occur at the same time. Thus, for every data element transferred out of the TX FIFO, one is transferred into the RX FIFO.

It appears it is implied that a Cy_SCB_SPI_Write() places the first data in the shift register from the FIFO.

Len

Len
"Engineering is an Art. The Art of Compromise."
0 Likes

Hi Len, thanks for the response. I had seen this in the documentation. The data certainly is loaded into the TX FIFO and is being sent to the master - no problem there. The problem is the extra byte at the beginning which is appearing on MISO but was not placed into the FIFO, as you can see in the trace picture I attached.

Peter

0 Likes

Peter,

There is a PSoC6 SPI Master/Slave Example available under PSoC Creator.  It's listed as CE221120.

It has four SPI modes

  • High-level
  • low-level Polling
  • low-level Interrupt
  • low-level DMA

The projects all use a SPI master and a SPI slave on the same PSoC and the master needs to be physically connected to the slave.

The SPI slave preloads the first byte into its TxFIFO to acknowledge the status of the previous SPI master command.  No one byte delay.

Len

Len
"Engineering is an Art. The Art of Compromise."
0 Likes
PSa_795526
Level 4
Level 4
First question asked 10 sign-ins First like given

Hi Peter,

If you are using the default Mode 0(CPHA=0,CPOL=0) of SPI, then this behavior is probably occurring because the next byte to be sent out by the SPI slave is already loaded on the last clock edge (falling edge) of the previous byte itself. Below is a screenshot of the SPI component timing diagram that shows this:

SPI mode 0 last clock edge data transfer screenshot.jpg

So, in your case, the data is loaded in the last clock edge when the address byte is transmitted itself.

To overcome this, would it be possible to try:

1) Loading the Tx FIFO with data on or before the address byte(first byte) transmission from the master ?

But if this does not satisfy your application requirement(where the response data is decided only after the first address byte), then can you try:

2) Changing the SPI SCLK mode to Mode 1(CPHA=1,CPOL=0). In this mode, the loading of the shift register seems to happen only the first clock edge of the current byte, as shown in the below screenshot:

SPI mode 1 first clock edge data transfer screenshot.jpg

But note that the SPI master also has to be changed to this mode.

3) Or (on the SPI master's side) try lifting up the SPI SS after the first address byte, and lowering it before the next response byte (in between which you can load the slave response byte into the Tx FIFO).

Best Regards,

Prem Sai

Hi Prem,

Thank you for this very clear and comprehensive response. You are exactly correct. I have done some tests and confirmed it.

Did you find some reference documentation that states when this FIFO-to-shift register action occurs, or did you just figure out? I’ve had a look again through whatever documents I can find but there is no detailed description of this. If you did find something in some document, please would you give me a link to it?

It seems strange to me that the SPI Mode should affect the way the internal FIFO and shift register interact – I have not seen this in any other SPI interface I have dealt with. In fact, it doesn’t make sense because it actually affects the higher-level protocol that is implemented in the slave firmware.

Regarding your suggested work-arounds:

  1. I can’t do this because, as you say, the response data is determined by the first address byte.
  2. This is possible, but because of other wider implications in the master and with other slave devices, it’s not ideal.
  3. This could work, but again has other implications, and the entire frame is defined by the SS pulse.

I’ve decided to leave it as it is and actually use this “extra” byte as a status byte that is independent of the data pointed to by the address byte – which actually has some other advantages. At least now I understand what’s going on, which is a big help.

Thanks again for taking the time to write up this answer for me – very much appreciated.

Peter

Hi Peter,

Glad that this helps to get an understanding of the issue, though not much can be done about it.

I could not find the FIFO to shift-register transfer event mentioned as such in any document. I had only interpreted it based on observed behavior and the data transition indications in the timing diagram, previously on PSoC5LP, and guessed the same might be occurring here.

Best Regards,

Prem Sai

0 Likes