cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F301 SPI read FIFO flush does not seem to work

STM32F301R8T6(Master)

M95160-WMN6TP EEPROM(Slave)

Low Level drivers

I've been trying to do a basic SPI EEPROM test based on the STM32F30x_DSP_StdPeriph_Lib_V1.2.3 SPI EEPROM example. Have finally gotten the write to work correctly but when we begin the read back from the EEPROM we see an extra three bytes of zeros in the receive buffer. The SPI bus analyzer shows the correct data coming out of the EEPROM chip so it seems that the RX FIFO still has data in it from the three read command bytes sent to the EEPROM(0x03, 0x00, 0x20, read command and address.) I've tried code examples from this site for flushing the RX FIFO but when running at full speed(i.e. not stopping in the debugger) there still is an extra three 0x00 getting into the receive buffer.

When stepping in the debugger as we enter the flush function the SPI3->SR register shows a receive buffer not empty(RXNE) and a FIFO reception level(FRLVL) of 0x3(FIFO full.) After a single read of the SPI3->DR register the RXNE clears and FRLVL changes to 0x0. If the FIFO receive buffer is full a single read should still leave 3 bytes in the FIFO not suddenly go to empty. I think we are missing something very basic here or are seeing some weird debugger induced issue. Any suggestions?

Thanks

TestStatus SPI_FlushRxFifo(SPI_TypeDef *hspi)
{
__IO uint32_t tmpreg;
uint8_t  count = 0U;
 
	while (SPI_GetReceptionFIFOStatus(SPI3) != SPI_ReceptionFIFOStatus_Empty)
	//while (hspi->SR & SPI_I2S_FLAG_RXNE)
	{
		count++;
		tmpreg = hspi->DR;
 
		/* To avoid GCC warning */
		(void)tmpreg;
		if (count == 4)
		{
			return FAILED;
		}
	}
	return PASSED;
}

1 ACCEPTED SOLUTION

Accepted Solutions

> Rx FIFO is flushed after read command to the EEPROM.

Is it flushed after all bytes of read command already left the SPI, or after you've written them to the Tx buffer (in which case they are still in the Tx FIFO and there's nothing to flush)?

JW

View solution in original post

5 REPLIES 5

Debugging is intrusive - observing SPI registers (mainly the DR register) using debugger has the same effect as reading it in program.

JW

Ok so that means that my FIFO RX flush is not working as there are an extra three bytes in the receive buffer and the SPI bus analyzer shows the correct data being read from the EEPROM(the Rx FIFO is flushed after read command to the EEPROM.)

0693W00000NpDjhQAF.jpg 

0693W00000NpDfpQAF.jpg 

> Rx FIFO is flushed after read command to the EEPROM.

Is it flushed after all bytes of read command already left the SPI, or after you've written them to the Tx buffer (in which case they are still in the Tx FIFO and there's nothing to flush)?

JW

Maybe that is the answer. Forgot all about the Tx FIFO. Let me go research some Tx FIFO flush code and try that.

Thanks. I'll update after I try it.

uint32_t spi_EEPROM_ReadBuffer_v2(uint8_t* pBuffer, uint16_t ReadAddr, uint16_t* NumByteToRead)
{
uint8_t cmdBuffer[32];
 
	cmdBuffer[0]	= sEE_CMD_READ;
	//cmdBuffer[1]	= 0x00;
	cmdBuffer[1]	= ((ReadAddr & 0xFF00) >> 8);
	cmdBuffer[2]	= (ReadAddr & 0xFF);
 
	/*!< Select the EEPROM: Chip Select low */
	GPIO_ResetBits(GPIOA, SPI3_CS);
 
	/*!< Send "Read from Memory" instruction */
	SPI_SendData8(SPI3, cmdBuffer[0]);
	SPI_SendData8(SPI3, cmdBuffer[1]);
	SPI_SendData8(SPI3, cmdBuffer[2]);
	// SPI_SendData8(SPI3, cmdBuffer[3]);
 
	// Test the rx fifo level and flush any residential data
	SPI_FlushRxFifo(SPI3);
 
	while ((*NumByteToRead)--) /*!< while there is data to be read */
	{
		/*!< Read a byte from the EEPROM */
		*pBuffer = spi_EEPROM_SendByte(sEE_DUMMY_BYTE);
		//*pBuffer = SPI_ReceiveData8(SPI3);
		/*!< Point to the next location where the byte read will be saved */
		pBuffer++;
	}
 
	delay(1);
 
	/*!< Deselect the EEPROM: Chip Select high */
	GPIO_SetBits(GPIOA, SPI3_CS);
 
	return 0;
}

Updated the SPI read sequence to wait until the TX FIFO is empty. We were waiting a system tick(1msec) before timing out but that did not work until we increased the SPI bus speed to 4Mhz. Thanks to waclawek.jan for the help.

	cmdBuffer[0]	= sEE_CMD_READ;
	cmdBuffer[1]	= ((ReadAddr & 0xFF00) >> 8);
	cmdBuffer[2]	= (ReadAddr & 0xFF);
 
	/*!< Select the EEPROM: Chip Select low */
	GPIO_ResetBits(GPIOA, SPI3_CS);
 
	/*!< Send "Read from Memory" instruction */
	SPI_SendData8(SPI3, cmdBuffer[0]);
	SPI_SendData8(SPI3, cmdBuffer[1]);
	SPI_SendData8(SPI3, cmdBuffer[2]);
 
	// Wait for the SPI to finish transmitting the read command.
	SPI_TxFifoFinishWait(SPI3);
 
	// Test the rx fifo level and flush any residential data
	SPI_FlushRxFifo(SPI3);
 
	while ((*NumByteToRead)--) /*!< while there is data to be read */
	{
		/*!< Read a byte from the EEPROM */
		*pBuffer = spi_EEPROM_SendByte(sEE_DUMMY_BYTE);
		//*pBuffer = SPI_ReceiveData8(SPI3);
		/*!< Point to the next location where the byte read will be saved */
		pBuffer++;
	}
 
	delay(1);
 
	/*!< Deselect the EEPROM: Chip Select high */
	GPIO_SetBits(GPIOA, SPI3_CS);

TestStatus SPI_TxFifoFinishWait(SPI_TypeDef *hspi)
{
__IO uint32_t tmpreg, startTick;
 
	startTick = getTickCount();
	while (SPI_GetTransmissionFIFOStatus(SPI3) != SPI_TransmissionFIFOStatus_Empty)
	{
		// Stay here until a system tick has passed.
		if (startTick != getTickCount())
		{
			return FAILED;
		}
	}
	return PASSED;
}