STM32H562 HAL_SPI_Transmit_DMA erroneously reporting transmit is still busy
I am using SPI6 on an STM32H562 to write data to a WS2812 LED strip.
The following code is called once per second to write the data:
LOGIF ("bytes left=%d", GPDMA1_Channel2->CBR1);
LOGIF ("TXC %d", (WS2812_SPI.Instance->SR & SPI_SR_TXC) != 0);
LOGIF ("ready=%d", HAL_SPI_GetState(&WS2812_SPI)== HAL_SPI_STATE_READY);
if (HAL_SPI_GetState(&WS2812_SPI) != HAL_SPI_STATE_READY) {
LOGIF ("error=%d", HAL_SPI_GetError(&WS2812_SPI));
HAL_SPI_Abort (&WS2812_SPI);
}
HAL_SPI_Transmit_DMA (&WS2812_SPI, spi_bytes, RESET_BYTES + nvalues * BYTES_PER_FRAME);
Here is the log output for the first two calls:
[101] ws2812 75: bytes left=0
[101] ws2812 76: TXC 1
[101] ws2812 77: ready=1
[201] ws2812 75: bytes left=0
[201] ws2812 76: TXC 1
[201] ws2812 77: ready=0
[201] ws2812 79: error=0
The first time, GetState reports READY, but the second time it does not, even though bytes_left is zero and TXC is 1, so an Abort is required before the next transmit. Unfortunately, this produces a nasty glitch on the MOSI line and, as the WS2812 protocol does not use the clock line, the glitch upsets the WS2812 LED strip.

This is the SPI setup:
hspi6.Instance = SPI6;
hspi6.Init.Mode = SPI_MODE_MASTER;
hspi6.Init.Direction = SPI_DIRECTION_2LINES_TXONLY;
hspi6.Init.DataSize = SPI_DATASIZE_8BIT;
hspi6.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi6.Init.CLKPhase = SPI_PHASE_1EDGE;
hspi6.Init.NSS = SPI_NSS_SOFT;
hspi6.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16;
hspi6.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi6.Init.TIMode = SPI_TIMODE_DISABLE;
hspi6.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi6.Init.CRCPolynomial = 0x7;
hspi6.Init.NSSPMode = SPI_NSS_PULSE_ENABLE;
hspi6.Init.NSSPolarity = SPI_NSS_POLARITY_LOW;
hspi6.Init.FifoThreshold = SPI_FIFO_THRESHOLD_01DATA;
hspi6.Init.MasterSSIdleness = SPI_MASTER_SS_IDLENESS_00CYCLE;
hspi6.Init.MasterInterDataIdleness = SPI_MASTER_INTERDATA_IDLENESS_00CYCLE;
hspi6.Init.MasterReceiverAutoSusp = SPI_MASTER_RX_AUTOSUSP_DISABLE;
hspi6.Init.MasterKeepIOState = SPI_MASTER_KEEP_IO_STATE_DISABLE;
hspi6.Init.IOSwap = SPI_IO_SWAP_DISABLE;
hspi6.Init.ReadyMasterManagement = SPI_RDY_MASTER_MANAGEMENT_INTERNALLY;
hspi6.Init.ReadyPolarity = SPI_RDY_POLARITY_HIGH;
This is the DMA setup:
handle_GPDMA1_Channel2.Instance = GPDMA1_Channel2;
handle_GPDMA1_Channel2.Init.Request = GPDMA1_REQUEST_SPI6_TX;
handle_GPDMA1_Channel2.Init.BlkHWRequest = DMA_BREQ_SINGLE_BURST;
handle_GPDMA1_Channel2.Init.Direction = DMA_MEMORY_TO_PERIPH;
handle_GPDMA1_Channel2.Init.SrcInc = DMA_SINC_INCREMENTED;
handle_GPDMA1_Channel2.Init.DestInc = DMA_DINC_FIXED;
handle_GPDMA1_Channel2.Init.SrcDataWidth = DMA_SRC_DATAWIDTH_BYTE;
handle_GPDMA1_Channel2.Init.DestDataWidth = DMA_DEST_DATAWIDTH_BYTE;
handle_GPDMA1_Channel2.Init.Priority = DMA_LOW_PRIORITY_LOW_WEIGHT;
handle_GPDMA1_Channel2.Init.SrcBurstLength = 1;
handle_GPDMA1_Channel2.Init.DestBurstLength = 1;
handle_GPDMA1_Channel2.Init.TransferAllocatedPort = DMA_SRC_ALLOCATED_PORT0|DMA_DEST_ALLOCATED_PORT0;
handle_GPDMA1_Channel2.Init.TransferEventMode = DMA_TCEM_BLOCK_TRANSFER;
handle_GPDMA1_Channel2.Init.Mode = DMA_NORMAL;
The DMA interrupt is enabled but enabling the SPI interrupt causes a lockup of some kind.
Is there some way to convince the SPI driver that the previous transmit completed successfully, without causing a glitch on the MOSI line?
