Showing results for 
Search instead for 
Did you mean: 

STM32U599 SPI1 EOT flag not updating

Associate III

I am using `HAL_SPI_Transmit_IT()` API to transmits 6 frames. The TXP interrupt correctly fires and feeds the TXDR register however after feeding the last frame into TXDR the EOT never fires, actually no interrupt fire after the last frame is feed.

  • Frame Size: 9 bits
  • FiFo threshold: 1 
  • All the interrupts that were enabled remain enabled including the EOT. (EIR=0x328)
  • TSIZE: 6 (does not change)
  • SCLK: 125KHz
    • Source CLK to SPI: HSI (16MHz
    • Prescaler: 128
    • The system clock is running 160MHz

It's worth noting polling mode also failed because EOT isn't being set either.

In other drivers we use HAL_SPI_Receive_DMA() and it works as expected. 

I reviewed  the STHAL driver but I do not see anything obvious wrong.

What criteria, besides TSIZE, triggers the hardware to set the EOT flag?


Accepted Solutions


When the SCLK signal is incorrectly routed to the GPIO block the EOT flag is not set.

Ensure you correctly routed the GPIO block to the SPI SCLK signal using the correct alternative function for the GPIO block.

View solution in original post

Senior III

9 bits on a SPI frame? (SPI byte)

As I understand SPI: it is byte oriented, entire transmission must have N * 8 clocks (bits). If receiving 9 bits - the last byte can be "incomplete" (still waiting to fill a byte).

No idea how if it is possible to configure 9 bits as a word (I do not think so, SPI is byte oriented).

What you are saying is incorrect. SPI is a glorified shift register with timing around it, it isn't word/byte/half-word oriented protocol.

On this MCU, I am using SPI1. The datasheet indicates it can handle 4 to 32bits. Additionally the STHAL API allows you to configure anything from 4 to 32 bits. 

The peripheral also has a packing feature but this isn't activated based on how it's accessed.

Given the setup I stated above the TXDR is accessed as 16 bits which means the threshold is hit because it's setup for 1 data packet and the frame is 9 bits wide. So on one access to TXDRAsU16 will push to the FIFO which hits the threshold, which causes the FIFO to offload into the shift register which shifts out 9 bits. However after the last frame is sent the EOT is not generated.

Please note I can observe the handling of `TXP` because it suppose to generate 6 events since I am using a data packet size of 1. So I get 6 TXP events which means the hardware FIFO is popping correctly.



How are you determining that EOT isn't getting set? It will be cleared in the HAL IRQ handler so won't ever be set if you're in user code.

The HAL supported method would be to handle the end of transfer action in HAL_SPI_TxRxCpltCallback.

> What are the criteria EOT to fire, the datasheet is not explicit?

The reference manual will have the details. EOT fires when TSIZE words have been written.

> TSIZE: 6 (does not change)

TSIZE is not meant to change. You can track the progress using the CTSIZE field in SPIx_SR register.

If you feel a post has answered your question, please click "Accept as Solution".
Associate III
  • Yes, I am using the provided callbacks but they are not firing. The `HAL_SPI_IRQHandler()` handler never makes it pass the code that handle end of transfers. I have started debugging the STHAL code. My observations are after the last TXP event fires the EOT event never fires which means the IRQ is never called again so there is no way for the `HAL_SPI_IRQHandler()` to handle anything because there is nothing generated by the hardware.
  • I have tried polling for the EOT flag using my own implementation as well as trying to use `HAL_SPI_Transmit()`. The `HAL_SPI_Transmit()` polls for the `EOT` in the last few lines but it is never set regardless of how long I wait.
  • I have read the reference manual. Is the criteria for EOT firing only dependent on TSIZE?
  • I have read similar issue on this forum but for other MCUs. I suspect it might affect this MCU unless STM makes a new IP block for each MCU, which I doubt 

I am sorry, desmond: You are right: the Word Size can be anything, even 9 bit (SPI_DATASIZE_9BIT).

I had in mind this: "Word Size" vs. "Frame Size" (what is your "Frame Size"?)

If I configure 9bit per word (DATASIZE, similar to "Word Size") but my frame looks like this: 9bit + 8bit +8bit (so, my "Frame Size" is 25bits - it will never complete (and even the words received might look wrong, shifted on bits).

"Frame Size" is the number of bits (simplified: the "Number of Words") in a chunk (one transaction).

The SPI waits (as I understand) for N x WordSize (DATASIZE). If the last word is not complete (like in the example: 2 bits are still expected with 9bits per word and 3 words per frame but just 25bits) - the EOT will never come.

Yes, "EOT fires when TSIZE words have been written" (or received): If number of bits are "incomplete" - EOT does come (still waiting for bits, to shift out or to shift in).

If you configure "Word Size" to 9bit - your "Frame" must have a length of N x 9bits.

The frame size is correctly set. It is set to 9 bits by configuring `CFG1::DSIZE[4:0]`. 

There is no 9 bit word, the access layer of the IP block is via TXDR register. If I configured a 9 bit frame then I need to access TXDR register on u16. Each u16 access will consume 16bits in the FIFO. The FIFO will pop 16 bits into the shift register and then the shift register will shift out 9 bits on the wire.

Additionally I am not activating the IP packing feature as this is auto activate depends on my access of TXDR (asU32 or as U16) + the threshold + the frameSize. See the reference manual on it.


Regardless of all of this if I setup the SPI for 8bit transfer the EOT still doesn't work even in polling mode. Either criteria for EOT event is not solely based on TSIZE or the IP block has a serious bug when transmitting only.




"hmmmm", did you get it?

9bit word size configured, trying to reading 2x 16bit words from FIFO, but the other side sends just 3 words (27bits as 3 x 9bits) - the SPI is still waiting for the missing bits. You can read the FIFO anytime you want, but the SPI peripheral is still waiting for bits (or bits = words provided, you want to transmit).

There is nothing wrong in MCU, the SPI works for me on all STM MCUs I have ever used.
But what I know "for sure": if the SPI device is still waiting for an expected bit (to receive) or when transmitting not yet enough words provided with all the number of bits needed for N * words - it "hangs" (actually - "the SPI waits still for you").

My bet: you have a mismatch between "bits provided" and "bits configured". Am sure EOT will come when the correct number of bits were there. And the "confusion" about Word Size and Frame Size.

  • I am in transmit only mode, sending data to a slave. 
  • The SPI works for me as well in receive only mode with a DMA. As we have other drivers that utilize it in receiving mode.
  • I provide enough bits as TXDR is access as 16bit register. So for each access (6 in total) I write 16bit into it. The FIFO threshold is set to 1 data packet, so any data greater than 9 bits would cause it to offload to the shift register 
  • You are also missing the very obvious. When setup for 8bits frame and 1 data packet the EOT flag isn't set, even whenI use polling mode (HAL_SPI_Transmit())`. The EOT isn't even set when I try to transmit just 1 byte using 8 bit frame. 
    • Try debugging the STHAL driver in transmit only mode and check if the flag is ever EOT flag is ever set. If you use polling mode add some logs around `SPI_WaitOnFlagUntilTimeout(SPI_FLAG_EOT)`.

I appreciate the help but I would prefer a ST employee provide some advice.

The post below is the same observation I have made but I am not using the stm32h7. However I suspect the SPI IP would be the same