cancel
Showing results for 
Search instead for 
Did you mean: 

SPI RXFIFO - Debugging

mikemillernow
Associate II
Posted on April 01, 2014 at 00:37

The original post was too long to process during our migration. Please click on the attachment to read the original post.
10 REPLIES 10
Posted on April 01, 2014 at 00:48

/**
* @brief Write a byte on the SD.
* @param Data: byte to send.
* @retval None
*/
uint8_t SD_WriteByte(uint8_t Data)
{
/*!< Wait until the transmit buffer is empty */
while(SPI_I2S_GetFlagStatus(SD_SPI, SPI_I2S_FLAG_TXE) == RESET)
{
}
/*!< Send the byte */
SPI_SendData8(SD_SPI, Data);
/*!< Wait to receive a byte*/
while(SPI_I2S_GetFlagStatus(SD_SPI, SPI_I2S_FLAG_RXNE) == RESET)
{
}
/*!< Return the byte read from the SPI bus */
return SPI_ReceiveData8(SD_SPI);
}

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
mikemillernow
Associate II
Posted on April 01, 2014 at 01:11

Clive,

Thanks for the post but I want to use the RXFIFO so I can just read the 3 bytes out without having to poll for each byte.

-Henk

Posted on April 01, 2014 at 01:30

Are you using the TX FIFO, and are you SURE that has evacuated completely across the wire before trying to read things that might have come back at you? Can you check that the RX FIFO has any content before trying to read back values? Have you confirmed you can talk to your device successfully using more conventional sequencing of the SPI bus?

/* Waiting until TX FIFO is empty */
while (SPI_GetTransmissionFIFOStatus(SPIx) != SPI_TransmissionFIFOStatus_Empty)
{}
/* Wait busy flag */
while(SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_BSY) == SET)
{}

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
mikemillernow
Associate II
Posted on April 01, 2014 at 02:19

I see my command 0x9F being sent out on the oscilloscope, but the code hangs at the last line waiting for a received byte.

 

        SPI_Cmd(SPI1, ENABLE);

        

        // Wait until transmit buffer is empty

        while(  !(SPI1->SR & 0x02)  );

        

        // Send the first byte

        SPI_SendData8(SPI1, 0x9F);

        

        // Wait to receive the first byte back.  - hangs here.

        while(  !(SPI1->SR & 0x01)  );

mikemillernow
Associate II
Posted on April 01, 2014 at 04:04

Below are the SPI1 register settings:

0690X00000602iaQAA.jpg

0690X00000602tCQAQ.jpg

Here if I see 8 clock edges, and the data being sent out I should be seeing something received.  Even if the data is all zero or FF's I shouldn't get stuck in this loop.

0690X00000602rpQAA.jpg

mikemillernow
Associate II
Posted on April 01, 2014 at 05:24

More debugging:

If I keep the following line below uncommented after my dummy write the code hangs''  while(  !(SPI1->SR & 0x01)  ); ''

If I comment that code out and  if I do several reads back to back I see the correct data on the 5th read of the data register.  There has to be a better way!

   received[0] = SPI1->DR;                  

        received[1] = SPI1->DR;                  

        received[2] = SPI1->DR;                

        received[3] = SPI1->DR;   

        

     SPI_Cmd(SPI1, ENABLE);

     SPI_SendData8(SPI1, 0x05);

     

      // Here is where I need to check to be sure that the read-> is empty.

      received[0] = SPI1->DR;                   // Reading back 0x00 but 0xFF on the scope.

      received[1] = SPI1->DR;                   // Reading back 0x00 but 0xFF on the scope.

      received[2] = SPI1->DR;                   // Reading back 0xFF but 0xFF on the scope.

      received[3] = SPI1->DR;                   // Reading back 0xFF but 0xFF on the scope.

      

      // Dummy data to read status register out

      SPI_SendData8(SPI1, 0xAA);

     

      // Wait until there is data in the receiver buffer and continue.

      while(  !(SPI1->SR & 0x01)  );                  // hangs here if uncommented!

      

      

      received[4] = SPI1->DR;                   // Reading back 0xFF but 0x02 on the scope.

      received[5] = SPI1->DR;                   // Reading back 0xFF but 0x02 on the scope.

      received[6] = SPI1->DR;                   // Reading back 0x02 but 0x02 on the scope.

      received[7] = SPI1->DR;                   // Reading back 0x02 but 0x02 on the scope.

          

      

      received[8] = SPI1->DR;                   // I see the correct data here.

Posted on April 01, 2014 at 05:43

There has to be a better way!

Presumably by qualifying that the FIFO has content? The FIFO provides some level of elastisity, in that you can blow all the way through the code before anything actually happens on the bus. I'm not using F0 parts.

while(SPI_GetReceptionFIFOStatus(SPI1) != SPI_ReceptionFIFOStatus_Empty) // Flush
received[0] = SPI1->DR;
// ...
while(SPI_GetTransmissionFIFOStatus(SPI1) != SPI_TransmissionFIFOStatus_Empty); // Spin for outbound completion
// ...
while(SPI_GetReceptionFIFOStatus(SPI1) == SPI_ReceptionFIFOStatus_Empty); // Spin if Nothing There
received[i++] = SPI1->DR;
while(SPI_GetReceptionFIFOStatus(SPI1) == SPI_ReceptionFIFOStatus_Empty); // Spin if Nothing There
received[i++] = SPI1->DR;

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
stm322399
Senior
Posted on April 01, 2014 at 10:26

Mike,

I'am sorry for only making assumptions here, I hope it will help anyway.

There are two things you may consider:

1) accessing SPI1->DR to copy into a byte array is a bad idea because, DR is 16-bit wide while byte is ... 8-bit wide.

Normally it does not hurt, but on STM32F0 (clive1 suggested you are using such a device) there is a packing data engine: reading

16-bit from DR, is (more or less) equivalent to two 8-bit reads. If the RXFIFO contains more than one byte, you loose the MSB ... this

might explain the 'scrambling' of data you observed.

2) SPI->SR bit RXNE may not be set for a single byte reception. This is because of the RXFIFO that can be coupled with DMA. See the

definition of the bit FRXTH or CR2 register. It must be set if you want RXNE to be set as soon as a single byte is received.

mikemillernow
Associate II
Posted on April 01, 2014 at 19:21

Laurent,

Thanks for the post.

1.) If I am not to read directly from the DR for a byte then how should I do this?

2.) You are correct about the FRXTH bit in the CR2 register.  Once I set the FRXTH bit

 to '1' , then when I received a byte the RXNE bit was changed. 

From the datasheet the RXNE event is triggered when data is stored in the RXFIFO

and

the threshold (defined by FRXTH bit) is reached.

-Mike