Intermittent SPI hangs on LPC55S69

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Intermittent SPI hangs on LPC55S69

449 Views
scottm
Senior Contributor II

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

0 Kudos
3 Replies

421 Views
xiangjun_rong
NXP TechSupport
NXP TechSupport

Hi,

As you know that the SPI is a full-duplex communication, in one transfer cycle, it transmits a Byte and receives a byte simultaneously with assumption that you transfer a byte for each transfer.

I assume that you use master mode, how do you know that you miss a byte in receiver? I do not know if this is your scenario. In the slave spi side, the slave spi  transfers the byte it has received in the preceding transfer. In the case, the first received byte of the spi master is a random value because the slave has not received any byte for the first transfer. As a test, you can disconnect the spi slave, but connect the MOSI with MISO with a cable, then check if you can miss a byte, in the case, the byte missing can never happen I suppose.

Pls check if it is your case.

BR

XiangJun rong

 

0 Kudos

420 Views
xiangjun_rong
NXP TechSupport
NXP TechSupport

Hi,

For the spi code architecture in polling mode, I suppose you can just poll the transmitter flag, if the transmitter flag is set, you know that you have received a byte, you can read the receiver register directly, then write another byte to transmitter reg, then jump to the line to poll transmitter flag.

Hope it can help you

BR

XiangJun Rong

 

0 Kudos

414 Views
scottm
Senior Contributor II

Hi,

I figured it out - it looks like I didn't account for the possibility of the transmitter still being active, and the TX FIFO being full while it's still sending a previous word can cause it to overflow the RX FIFO. I've changed it to not send when the RX FIFO doesn't have an extra word free and it seems to be working now.

Thanks,

Scott

0 Kudos