cancel
Showing results for 
Search instead for 
Did you mean: 

STM32U5xx: QSPI and SPI3 in DMA mode - callback comes too early - for you

tjaekel
Senior III

I have my OCTOSPI1 as QSPI working - in "indirect mode", now using DMA: it generates a very clean waveform (no gaps between words or bytes as in "polling mode", a smooth waveform).

I use also OCTOSPI1 as a "regular SPI transmitter" (acting as SPI Tx). But due to fact that OCTOSPI is NOT a "regular SPI" (it is NOT "full-duplex"): I use SPI3 as a SPI Slave RX:

I connect QSPI SCLK with SPI3 SCLK and SPI3 MOSI is QSPI DIO1 (as MISO). Now I have shared pins for QSPI and a regular SPI on the same QSPI pins. I works.

I use also SPI3 Rx DMA. It makes the SPI waveform way better (no gaps).

The project is here (if you want to see how to use DMA for OCTOSPI as QSPI and SPI3 as Slave Rx for regular SPI):

https://github.com/tjaekel/NUCLEO-U5A5JZ-Q_QSPI 

What I have realized:

Callback comes way to early

But it is obvious for me.

The

void HAL_OSPI_TxHalfCpltCallback(OSPI_HandleTypeDef *hospi)

comes when the DMA has finished to push Tx words into QSPI FIFO.
But it does not mean the transaction has really finished!

I use the nCS signal(s) in SW mode: I need two nCS signals for two QSPI slaves connected. Therefore, I toggle the nCS signals pins as GPIOs.

But this callback comes "early": if I use it, assuming the QSPI Tx has finished - it comes way before the real Tx has shifted out all bytes and words. It is obvious: there is a FIFO in OCTOSPI and DMA has finished to fill it. But with a slow QSPI clock speed - it takes still time that the FIFO content was sent out.

Therefore, I use this "trick" to realize all was done (before I proceed on my FW):

#ifdef QSPI_DMA
  /* this is too early! DMA has finished but OSPI shifts still out! */
  ////while ( ! GQSPI_DMA_TxComplete ) {;}
  while ( hospi->State != HAL_OSPI_STATE_READY) { /*tx_thread_sleep(1)*/; }
  /* with sleep it is too long */
#endif

Now all works fine.

BTW:
If you do not have a circular buffer (I do not have and do not use/need) - the TxHalfCpltCallback is the right indication (and the only one which is called). I was thinking that TxCpltCallback would do - but it is never called (if not a circular DMA is configured).

 

1 ACCEPTED SOLUTION

Accepted Solutions
tjaekel
Senior III

OK, OCTOSPI can also use DMA in "indirect mode" and SPI3 with DMA works as SPI Rx where OCTOSPI is the Tx part (because OCTOSPI does not support "full-duplex" mode, pretty "frustrating").
Now I have my "pin sharing" on QSPI (which is not supported by OCTOSPI, also pretty "frustrating").

https://github.com/tjaekel/NUCLEO-U5A5JZ-Q_QSPI 

View solution in original post

1 REPLY 1
tjaekel
Senior III

OK, OCTOSPI can also use DMA in "indirect mode" and SPI3 with DMA works as SPI Rx where OCTOSPI is the Tx part (because OCTOSPI does not support "full-duplex" mode, pretty "frustrating").
Now I have my "pin sharing" on QSPI (which is not supported by OCTOSPI, also pretty "frustrating").

https://github.com/tjaekel/NUCLEO-U5A5JZ-Q_QSPI