SPI Slave drops a byte from TX FIFO?

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.
PeWa_1510206
Level 2
Level 2
First like received

I'm using the SPIS component with an interrupt handler on "Interrupt On Rx FIFO Not Empty". The master performs two-byte writes before pulling the slave select line high again.

   

For testing purposes, after I receive the first byte, I send out 0x55 on MISO. After I recieve the second byte, I put 0x77 in the TX FIFO. This works fine except for the very first SPIS RX interrupt--in this case, one 0x77 that I put in the TX FIFO just isn't sent out. Notice in the spi.png file, there's a 0x55 following a 0x55 where 0x77 should be intervening.

   

The RX interrupt handler is as follows:

   

    static uint8 toggle = 0;
    uint8 data = SPIS_1_ReadRxData();
    uint8 status = SPIS_1_ReadRxStatus();
    if (toggle == 0)
    {
        SPIS_1_WriteTxData(0x55);
    }
    else
    {
        SPIS_1_WriteTxData(0x77);
    }
    
    toggle = ~toggle;

   

 

   

Any idea why one of the bytes in the FIFO isn't getting sent out? I also uploaded the project itself.

0 Likes
1 Solution
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

SPI works as follows: for every bit(byte) shifted in one bit (byte) is shifted out. Since you did not put a byte into Tx initially null is shifted out.

   

 

   

Bob

View solution in original post

0 Likes
9 Replies
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

SPI works as follows: for every bit(byte) shifted in one bit (byte) is shifted out. Since you did not put a byte into Tx initially null is shifted out.

   

 

   

Bob

0 Likes

By null, you mean 0x00, right? I'm fine with that for the first byte. My problem is the 3rd byte--it's missing. It should be 0x77.

0 Likes
HeLi_263931
Level 8
Level 8
100 solutions authored 50 solutions authored 25 solutions authored

Where is the place where you are missing the 0x77? The first ReadRxData() happens at a time where nothing has been read by the SPI master, so it returns 0x00. Then your ISR sends a byte out, which also receives another byte (and thus triggers the ISR again).

0 Likes

I'm running the SPI slave component on the PSoC, not SPI master. I know that there's RX data available for the slave because the code above is in the RX interrupt handler (which is driven by "Interrupt On Rx FIFO Not Empty"). Regarding the missing 0x77--that's shown in spi.png. According to the source, MISO should have 0x55, 0x77, 0x55, 0x77, etc. Instead, it has 0x55, 0x55, 0x77, 0x55, etc.

   

I would embed spi.png as an image, but I get an error: "The selected text format will not allow it to display images. The text format will need to be changed for this image to display properly when saved." when I attempt to do that with this forum. So for now, just download the attatchment from my original post.

   

   

0 Likes

Sorry, I somehow missed tha part about the SPI slave 😞

   

OK, so what you should get is a sequence of 0x00, 0x55, 0x77, 0x55, 0x77 (and so on). I have no idea, from looking at the code, why that one 0x77 gets swallowed.

   

What you could do for debugging: have two output pins. Set one high during the time in your ISR. Set the other one according to the 'toggle' variable as soon as its changed. Then you can watch these two lines with your LA, maybe this gives a clue. The only other idea I have is that some code is clearing the TX buffer for some reason (though I cannot see why for now).

lock attach
Attachments are accessible only for community members.

I added the two outputs you suggested, "Toggle" and "ISR". They look like I would expect, though. I've attached two images from the LA--one zoomed in.

0 Likes
PeWa_1510206
Level 2
Level 2
First like received

OK. I think I found the problem. Instead of calling SPIS_WriteTxData(), I should have been calling SPIS_WriteTxDataZero() to put a byte into the FIFO. This is because my SPI bus is configured in mode 0,0 (CPHA = 0, CPOL = 0). The comment on SPIS_WriteTxDataZero() reads as follows:

   
*  Write a byte zero of data to be sent across the SPI. This must be used in *  Mode 00 and 01 if the FIFO is empty and data is not being sent.
   

 

   

I believe that is the case for me. Now I can pre-load the TX FIFO with a byte and it will be clocked out as the first RX byte comes in. I also don't see a missing 0x77 when I use SPIS_WriteTxDataZero() instead of SPIS_WriteTxData().

Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

Wow! To find out that bug must have taken some time! Thank you for keeping us informed.

   

 

   

Bob

0 Likes
HeLi_263931
Level 8
Level 8
100 solutions authored 50 solutions authored 25 solutions authored

Good find!

   

I should have seen this while looking at the data sheet 😞 It actually is clearer than the code comment:

   

Places a byte/word directly into the shift register for transmission. This byte/word will be
sent to the master device during the next clock phase.

   

Required for modes where CPHA == 0 where data must be in the shift register before the
first clock edge.

   

This is probably because your ISR runs while the SPI transfer is already in progress. So when you place the byte with WriteTxData, it will be put into the FIFO, but it doesn't get fast enough into the SPI write register itself.