cancel
Showing results for 
Search instead for 
Did you mean: 

SPI DMA Master to SPI DMA Slave works in 8-bit but hangs on 16-bit mode

ATzou.1
Associate II

Hardware/Firmware Setup

  • Nucleo-G474RB connected via SPI to a Nucleo-G431RB board
  • 3-Wires SCK, MOSI, MISO (and GND as well)
  • STM32Cube_FW_G4_V1.4.0 firmware package
  • Example code used
    • running on Nucleo-G474RE -> SPI_FullDuplex_ComDMA_Master
    • running on Nucelo-G431RB -> SPI_FullDuplex_ComDMA_Slave

In MX_SPI1_Init() in main.c

for 8-bit mode use the default of:

 hspi1.Init.DataSize = SPI_DATASIZE_8BIT;

for 16-bit mode use:

 hspi1.Init.DataSize = SPI_DATASIZE_16BIT;

The issue is

  • when just running the Slave application free running (reset before test)
  • and running the Master application in the debugger ...
  • in 8-bit mode works fine and code breaks at the buffer compare and finishes up the spi transaction successfully
  • in 16-bit mode the code hangs at while (wTransferState == TRANSFER_WAIT) {} which means that the application is never executing the callback HAL_SPI_TxRxCpltCallback

Notes

  • spi chip select is not required
  • modifying both firmware setups at the same time for either 8-bit or 16-bit modes
  • shortened up the data payload to 8 bytes for tx and rx (1-8 decimal bytes) for ease of verifying the results in the debugger
  • using an Logic Analyzer with an SPI analyzer/decoder
    • even in the 16-bit mode all 16-bit words from each board is transferred in full in both directions (the 16-bit spi transaction should also achieve TRANSFER_COMPLETE)
  • using the latest STM32CubeIDE and tools

Seems like I'm just missing some obscure configuration in order to make 16-bit mode to work. Perhaps someone has already resolved this issue ?

3 REPLIES 3
TDK
Guru

You're changing DMA transfer size from byte to half-word as well, correct?

If so, and if you wanted to debug further, you could put a breakpoint in the DMA stream interrupt and see why it never gets around to calling HAL_SPI_TxRxCpltCallback. You could also verify that the DMA stream NDTR register reaches 0. Sounds like a HAL issue based on your description, but hard to know.

If you feel a post has answered your question, please click "Accept as Solution".
ATzou.1
Associate II

I'm not dynamically switching from 8-bit to 16-bit (half-word). Just configuring the app to run either 8-bit or 16-bit transfers.

I will try your suggestion to set a breakpoint in the DMA Stream interrupt and verify that the NDTR register reaches 0.

ATzou.1
Associate II

Thanks for the hint. Changed the callback to the 'half word' callback and now I'm getting a successful 16-bit transfer with TRANSFER_COMPLETE. Now I just need to figure out why the second byte of the 16-bit received word is 0x00 instead of the desired value (the first byte is correct) ... even though the desired both byte values are correctly captured and decoded on the Logic Analyzer/Decoder.

I am manually driving the CSn active low and then high after the SPI transaction.

Additionally, the second time around that I try to do the same SPI transaction I get a HAL_BUSY from the HAL_SPI_TransmitReceive_DMA(). My first problem in the chain is not getting the second byte of the 16-bit received word.

Following is my SPI Configuration:

// SPI1 parameter configuration
  hspi1.Instance = SPI1;
  hspi1.Init.Mode = SPI_MODE_MASTER;
  hspi1.Init.Direction = SPI_DIRECTION_2LINES;
  hspi1.Init.DataSize = SPI_DATASIZE_16BIT;
  hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
  hspi1.Init.CLKPhase = SPI_PHASE_2EDGE;
  hspi1.Init.NSS = SPI_NSS_SOFT;
  hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_32;
  hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
  //hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
  //hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
  //hspi1.Init.CRCPolynomial = 7;
  //hspi1.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE;
  hspi1.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;