cancel
Showing results for 
Search instead for 
Did you mean: 

Generate a pulse in the STM32H7 SPI's SS line every 64 bits

DGast.1
Associate III

I want to communicate with an SPI slave whose high level protocol states that each command is 64 bits, and that the SS line must be de-asserted and asserted in between commands. I want to send to it 2 commands as quick as possible, so I need to assert SS, send 64 bits, de-assert SS, assert it again, send the other 64 and de-assert again to finish the communication.

To do this fast, I want to load 64 bits into the SPI's FIFO, wait for the FIFO to be empty, de-assert/assert SS, and load the remaining 64.

To achieve this, I have configured the master SPI's frame size as 32 bits, and the FIFO threshold as 4 data.

As per this explanation about the TXP bit in the SPI2S_SR register, in the STM32H7xx reference manual:

0693W00000aHRfYQAW.png 

My understanding is that, since I have configured the FIFO threshold as 4 data, that means that whenever there is a frame in the FIFO (which will be at least 32 bits) TXP will be 0, because as soon as 1 frame enters the FIFO there is no room for an entire packet, since each packet is 4 data, in other words 4 * 32 bits frame size = 128, which is the maximum capacity of the SPI1 FIFO (16 * 8 bits).

Apart from the above, I have tried to modify the STM32CubeMX generated code to wait for the TxFIFO to be empty every 64 bits. The modification is as following:

In `HAL_SPI_Transmit`, in the loop that writes words to the SPI Tx register:

  int j = 0;
  /* Transmit data in 32 Bit mode */
  if (hspi->Init.DataSize > SPI_DATASIZE_16BIT)
  {
    /* Transmit data in 32 Bit mode */
    while (hspi->TxXferCount > 0UL)
    {
      /* Wait until TXP flag is set to send data */
      if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXP))
      {
        *((__IO uint32_t *)&hspi->Instance->TXDR) = *((const uint32_t *)hspi->pTxBuffPtr);
        hspi->pTxBuffPtr += sizeof(uint32_t);
        hspi->TxXferCount--;
        j++;
        if (j > 0 && j % 2 == 0)
        {
            extern void __pulse(void);
            while (LL_SPI_IsActiveFlag_TXP(hspi->Instance) == 0) {}
            __pulse();
        }
      }
[...]
}
[...]

The function `__pulse()` just de-asserts and asserts the GPIO I'm using as SS line. The above doesn't work, it generates the following waveform:

0693W00000aHRglQAG.png

I don't understand why the pulses are generated in those instants. Shouldn't the first one be generated after the TxFIFO has become empty, after loading it with the first 64 bits?

How can I achieve what I'm trying?

1 REPLY 1

TxFIFO becomes empty when the last frame is transferred from FIFO to the shift register, ie. at that moment, the whole frame remains to be transmitted.... Plus latencies in software.

SPI in STM32 is less flexible than desirable. One trick to pull out required SCK+NSS timing is to generate the required waveforms using interconnected timers, and then feed them back externally (interconnecting pins) to SPI set as slave.

JW