SPI Stops Transmitting on K64F

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

SPI Stops Transmitting on K64F

1,624 Views
jerrygardner
Contributor III

I've got a strange problem with SPI transmits on the K64F that's on the Freedom board that's got me stumped.

I've written my own bare-metal, interrupt driven driver for SPI master mode. I've initialized the SPI peripheral to generate TC interrupts when SR[TC] gets set. I'm using the FIFOs (MCR[DIS_TXF] and MCR[DIS_RXF] are both set to 0).

My strategy for writes is as follows:

1) Check if the SR[TFFF] is set indicating the TX FIFO is not full.

2) Write the data to PUSHR.

3) Wait for the interrupt, and if SR[RFDF] is 1, then read the data in the RX FIFO from POPR. Clear SR[TC] by writing a 1 to SR[TC] at the end of the interrupt handler.

When I do multiple transfers, I only see N+1 interrupts, where N is the depth of the TX FIFO, despite the fact that I'm doing more than N+1 writes to PUSHR. So, for SPI0, which has a 4 deep FIFO, I see five transfers on the SPI bus and five interrupts. For SPI1, which has a 1 deep FIFO, I see two transfers on the SPI bus and two interrupts.

If I try to do 7 writes on SPI0, for example, I see only five transfers on the SPI bus and only five interrupts. The last two writes don't generate any SPI bus activity nor any interrupts. The TCR register stays set to 5. When I do writes #6 and #7, the SR[TFFF] bit is set to 1 indicating the TX FIFO is not full, so it should accept the writes to PUSHR and transfer the data on the SPI bus, but it doesn't.

This seems to be related to something subtle in the timing of the requests. When I write new data to PUSHR, I check first that SR[TFFF] = 1 indicating the FIFO is not full. If I put a small delay after writing the first 5 (N+1 on SPI0 with its 4-deep FIFO) times to PUSHR before writing additional times, I do see the expected number of interrupts. I suspect that the delay is giving the FIFO time to drain. It seems that the SR[TFFF] flag is not being cleared when the FIFO is full and my writes to PUSHR beyond the first 5 are being ignored. The reference manual says that SR[TFFF] can be cleared by writing a 1 to it, but why would one have to do this? Wouldn't the SPI peripheral clear it automatically when the FIFO is full? Am I missing something here?

Can anyone give me a clue? What should I look for? Is there something I'm not configuring right?

0 Kudos
Reply
5 Replies

1,160 Views
Robin_Shen
NXP TechSupport
NXP TechSupport

Hi Gardner,

You can download the K64P144M120SF5RM first and read the "50.4.2.4 Transmit First In First Out (TX FIFO) buffering mechanism":

Don't write 7 data into PUSHR at a time, the Transmit FIFO size of SPI0 is only 4.

The module ignores attempts to push data to a full TX FIFO, and the state of the TX FIFO does not change and no error condition is indicated.

TFFF flag clears automatically when DMA is used to fill TX FIFO.

To clear TFFF when not using DMA, follow these steps for every PUSH performed using CPU to fill TX FIFO:

  1. Wait until TFFF = 1.

  2. Write data to PUSHR using CPU.

  3. Clear TFFF by writing a 1 to its location. If TX FIFO is not full, this flag will not clear.

The TX FIFO Counter field (TXCTR) in the module Status Register (SR) indicates the number of valid entries in the TX FIFO.

It may help you to know: how many data need to be write into PUSHR to full the TX FIFO.

Best Regards

Robin

0 Kudos
Reply

1,160 Views
jerrygardner
Contributor III

Thanks for the reply!

I'm already doing steps 1-2. I'm not trying to write 7 times to the FIFO, since, as you say, it's only 4 data items wide. I'm using TXCTR to determine how many PUSHR write I can do and then I only do that many PUSHR writes.

The behavior of the TFFF flag is surprising to me. Why should driver code need to write a '1' to it to clear it? Why doesn't the chip just clear it itself when the FIFO is full? If the FIFO is not full, then "clearing" TFFF doesn't make sense--the chip is just going to turn it back on again immediately because the FIFO is not full.

I've already tried "clearing" TFFF by writing '1' to it before I saw your post, and it does work, but it's one of those illogical things that just don't make sense.

0 Kudos
Reply

1,160 Views
Robin_Shen
NXP TechSupport
NXP TechSupport

Hi Gardner,

I didn't find the reason in the reference manual. It seems a little strange.

I can only find the description in below Note.(just only how to deal with the TFFF)

50.4.7.2 Transmit FIFO Fill Interrupt or DMA Request.jpg

Best Regard

Robin

0 Kudos
Reply

1,160 Views
jerrygardner
Contributor III

A couple of potential gotchas for the unwary related to the SPI peripheral:

1) Several of the flags in the status register (SR) are cleared by writing a '1' to the bit. If you use something like SPI_SR |= SPI_TFFF_MASK; to clear the TFFF bit, then the read-modify-write nature of this code will write back '1's to any other bit set to '1' in the register, and if that bit is also cleared by writing a '1' to it, it will get cleared as well. Beware! The best way to handle this is to use bit-banding.

2) The RFDF bit in the status register (SR[RFDF]) is never '0'!!!  Even when SR[RXCTR] = 0, which indicates the RX FIFO is empty,  SR[RFDF] will still be '1'. Writing a '1' to SR[RFDF] will not clear it as the reference manual says it will.

0 Kudos
Reply

1,160 Views
jerrygardner
Contributor III

I've looked at this in more depth and am convinced that the SR[TFFF] flag is not getting cleared when the TX FIFO is full. I've checked the chip errata but didn't see anything mentioned.

Has anyone else seen this issue? I've been looking for sample code to look at that might reveal a clue, but have only found code that uses library calls--if anyone know of some bare-metal code please let me know.

0 Kudos
Reply