diff --git a/src/shared/drivers/spi/SPIBus.h b/src/shared/drivers/spi/SPIBus.h
index 2781a9c7a8d670a55e61ca3cd9c0cf568d297599..ef71a7d4c52e00ca0eda587308651b7ee2f6c676 100644
--- a/src/shared/drivers/spi/SPIBus.h
+++ b/src/shared/drivers/spi/SPIBus.h
@@ -132,6 +132,8 @@ public:
void waitPeripheral();
+ void flushRxBuffer();
+
/**
* @brief Configures and enables the bus with the provided configuration.
*
@@ -402,6 +404,12 @@ inline void SPIBus::waitPeripheral()
;
}
+inline void SPIBus::flushRxBuffer()
+{
+ while ((spi->SR & SPI_SR_RXNE) != 0)
+ spi->DR;
+}
+
inline void SPIBus::configure(SPIBusConfig newConfig)
{
// Do not reconfigure if already in the correct configuration.
@@ -520,8 +528,18 @@ inline void SPIBus::write16(const uint16_t* data, size_t nBytes)
inline uint8_t SPIBus::transfer(uint8_t data)
{
- // At the start of the transfer we assume that the RX FIFO is empty
- assert((spi->SR & SPI_SR_RXNE) == 0);
+ /*
+ * On STM32F7xx and STM32F4xx series chips, on SPI3 only, the RXNE flag
+ * may be erroneously set at the beginning of the transaction with the
+ * RX buffer containing garbage data.
+ * On F7xx chips the issue can be reproduced by re-configuring the SPI from
+ * Mode 0 (CPOL=0, CPHA=0) to Mode 3 (CPOL=1, CPHA=1), after performing at
+ * least one transaction in Mode 0.
+ *
+ * We work around this issue by flushing the RX buffer at the beginning of
+ * the transaction.
+ */
+ flushRxBuffer();
// Wait until the peripheral is ready to transmit
while ((spi->SR & SPI_SR_TXE) == 0)