I've got two different SPI ports in use, in polled mode, each with a similar and fairly simple bit of code handling the transfer, but in both cases I've occasionally had it hang with all outgoing bytes having been sent but it's still missing one byte on the receive side. Here's the code for one instance:
taskENTER_CRITICAL();
SPI_PORT->FIFOCFG |= SPI_FIFOCFG_EMPTYTX_MASK | SPI_FIFOCFG_EMPTYRX_MASK;
SPI_PORT->FIFOSTAT |= SPI_FIFOSTAT_TXERR_MASK | SPI_FIFOSTAT_RXERR_MASK;
mosi = pu8Mosi ? pu8Mosi : &dummy;
miso = pu8Miso ? pu8Miso : &dummy;
tx_ctrl = SPI_FIFOWR_LEN(kSPI_Data8Bits);
to_rx = u16Sz;
to_tx = u16Sz;
while (to_rx)
{
if ((SPI_PORT->FIFOSTAT & SPI_FIFOSTAT_RXNOTEMPTY_MASK) != 0U)
{
// FIFO is not empty, read a word
tmp = SPI_PORT->FIFORD;
if (pu8Miso != NULL)
{
*miso = tmp & 0xff;
miso++;
}
to_rx--;
}
if (to_tx && (SPI_PORT->FIFOSTAT & SPI_FIFOSTAT_TXNOTFULL_MASK) != 0U)
{
if (to_tx == 1)
{
// Last byte
tx_ctrl |= SPI_FIFOWR_EOT_MASK;
}
SPI_PORT->FIFOWR = tx_ctrl | *mosi;
if (pu8Mosi != NULL)
{
mosi++;
}
to_tx--;
}
}
taskEXIT_CRITICAL();
I've been using similar code on Kinetis K22 devices for years without trouble. to_rx and to_tx are each set to the same value, and each byte sent should result in one byte being received, right? What am I missing?
I've read over the fsl_spi.c SPI_MasterTransferBlocking() function and it looks to be essentially the same, except with some added complexity to handle different data widths. I don't see how it's missing a byte.
Thanks,
Scott