cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F4 SPI with DMA is not working, Transmit only used. stuck at HAL_SPI_STATE_BUSY_TX

JohnsAby
Associate II

I have done the implementation of 3 wire SPI using DMA and when I do SPI transfer using

HAL_SPI_Transmit_DMA(&SPIx_handle, (uint8_t *)TxBuffer, 8u); the HAL_SPI_GetState(&SPIx_handle) is stuck at HAL_SPI_STATE_BUSY_TX.

Not changing the state.

My configuration of SPI and DMA is similar to this query : STM32F405 SPI Transmit using DMA not working

Thanks in advance

Edit: First time posting query here, if anything needed additionally please comment

Edit 2: Earlier mentioned HAL_SPI_STATE_BUSY, updated to HAL_SPI_STATE_BUSY_TX

24 REPLIES 24

Hi JW,

Thanks for your response.

Hi TDK,

I checked with high priority, still the behavior is same

_inline_ static void spi5_dataTransfer(uint16_t *TxBuffer)
{
  HAL_GPIO_WritePin(SPIx_NSS_Port, SPIx_NSS_Pin, GPIO_PIN_RESET);
  HAL_SPI_Transmit_DMA(&SPIx_handle, (uint8_t *)TxBuffer, 8u);
  HAL_GPIO_WritePin(SPIx_NSS_Port, SPIx_NSS_Pin, GPIO_PIN_SET);
  while (HAL_SPI_GetState(&SPIx_handle) != HAL_SPI_STATE_READY);
}

the control is not stopping at while(mentioned above).

And SPI state remains in "HAL_SPI_STATE_BUSY_TX" state.

But if I disable the "while" as shown below

_inline_ static void spi5_dataTransfer(uint16_t *TxBuffer)
{
  HAL_GPIO_WritePin(SPIx_NSS_Port, SPIx_NSS_Pin, GPIO_PIN_RESET);
  HAL_SPI_Transmit_DMA(&SPIx_handle, (uint8_t *)TxBuffer, 8u);
  HAL_GPIO_WritePin(SPIx_NSS_Port, SPIx_NSS_Pin, GPIO_PIN_SET);
 // while (HAL_SPI_GetState(&SPIx_handle) != HAL_SPI_STATE_READY);
}

the ISR (DMA2_Stream4) is getting called at fixed interval(as I call spi5_dataTransfer() in a repeated task), so interrupt is enabled and working right?

Please correct me if am wrong.

NVIC set priority and enabled are done for both DMA stream and SPI

Kindly reply, as your replies are helping

> in a repeated task

RTOS?

Where do you call spi5_dataTransfer from? Aren't interrupts disabled globally at that point, or isn't it from an interrupt context with priority equal or higher than DMA2_Stream4 interrupt priority?

JW

Hi JW,

Thanks for the response

Not RTOS, a repeated task is created using a timer interrupt.

spi5_dataTransfer is called from this task.(No global interrupts are disabled)

I will look for issue from interrupt context and will update here.

TDK
Guru

> a repeated task is created using a timer interrupt.

> spi5_dataTransfer is called from this task

If spi5_dataTransfer is called from an interrupt, probably the DMA2_Stream4 IRQ has the same or lower priority than it. If you don't know what it's in, set a breakpoint and look at VECTACTIVE bits to determine which interrupt it's in.

> HAL_GPIO_WritePin(SPIx_NSS_Port, SPIx_NSS_Pin, GPIO_PIN_RESET);

> HAL_SPI_Transmit_DMA(&SPIx_handle, (uint8_t *)TxBuffer, 8u);

> HAL_GPIO_WritePin(SPIx_NSS_Port, SPIx_NSS_Pin, GPIO_PIN_SET);

If your intention is to hold NSS low until the transmission completes, you need to wait for it to complete. As written, the code will only set NSS low briefly, perhaps for a single bit or less, as the transmission will continue in the background. You can instead set NSS high in the receive complete callback function.

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

Hi TDK,

Thanks for the response.

You were correct about the interrupt,

For testing purpose, I changed to flow and called HAL_SPI_Transmit_DMA from main().

It worked fine for single byte transfer.

0693W00000GY18XQAT.png 

But when I pass multiple bytes( like 8, 25 etc) for last byte in the sequence is getting identified

 Please see below, Here data send are "12345678", but only 8 is identified(Data from 1-7 also present in transfer but during the ChipSelect high clock is present)

another example if "ABCDEFGH" is send means H will be identified.

0693W00000GY18mQAD.png 

Note: HAL_GPIO_WritePin(SPIx_NSS_Port, SPIx_NSS_Pin, GPIO_PIN_SET); is called inside HAL_SPI_TxCpltCallback() and is fine.

> But when I pass multiple bytes

How?

Post relevant portion of code.

JW

Hi JW

Thanks for the quick response

I pass

uint8_t aTxBuffer[] = "ABCDEFGH";

to this

void spi5_dataTransfer(uint8_t *TxBuffer)
{
  HAL_GPIO_WritePin(SPIx_NSS_Port, SPIx_NSS_Pin, GPIO_PIN_RESET);
  HAL_SPI_Transmit_DMA(&SPIx_handle, TxBuffer, 8u); //8u //1u
  while (HAL_SPI_GetState(&SPIx_handle) != HAL_SPI_STATE_READY);
}

> //8u //1u

Was the lower waveform (with red circles) taken with 8u or 1u?

And channel 3 displays the SPIx_NSS_Pin?

JW

Hi JW,

Thanks for your response

Lower waveform is taken with 8u.(Correct)

Channel 3 is NSS output.(Correct)

Issue is when the NSS is high, Clock also present. This is what I tried to showcase in image.