cancel
Showing results for 
Search instead for 
Did you mean: 

Restart SPI DMA Transmission

cgallardo
Associate II

Hello,

I am working on a sensor device acting as a SPI slave with transmit only and without chip select signal. I am using a STM32G070 microcontroller.

I configured 4 bytes transmissions using DMA. The problem I have is that the external master can perform incomplete reads of any number of bits under the maximum of 32, so the next transmissions will be shifted.

I am using a timer to restart the SPI transmission so that the transmitted buffer is restarted after some time since the beginning of the first clock, but the SPI data is still shifted after incomplete reads.

 

What is the way to restart the transmission from the beggining of the buffer?

 

My current flow is:

1. Start 4 bytes transmission by DMA SPI

2. When the first clock is detected by EXTI, start the timer.

3. An incomplete read is performed by the external serial master (21 bits, for example).

4. The timer timeout is triggered.

5. The SPI transmission is aborted and started again. (HAL_SPI_Abort(), HAL_SPI_Transmit_DMA())

 

Thank you.

1 ACCEPTED SOLUTION

Accepted Solutions

It is solved!

What I was doing wrong was the reset sequence.

On the 5th step, the functions sequence that works for a good reset is:

HAL_SPI_DMAStop();

__HAL_RCC_SPIx_FORCE_RESET();

__HAL_RCC_SPIx_RELEASE_RESET();

HAL_SPI_Init();

HAL_SPI_Transmit_DMA();

 

Once I found the RCC macros, it worked.

View solution in original post

4 REPLIES 4
cgallardo
Associate II

I changed the 5th step to stop DMA and start transmisison again (HAL_DMAStop(), HAL_SPI_Transmit_DMA()) and now it is still shifted after incomplete reads but it seems to restart after completing the remaining bits of the incomplete byte.

Before the change, it restarted after completing the 32bits, so it wasn't really restarted.

 

Can it be restarted at any number of bits or must it complete the byte in progress?

TDK
Guru

> Can it be restarted at any number of bits or must it complete the byte in progress?

SPI works with bytes (words, technically I suppose). It can't be paused, or resumed mid-byte. It CAN be stopped mid-byte if you disable/reset the peripheral and DMA stream and then reinitialize/restart them.

 

A common synchronization approach is to reset on the rising edge of the CS line, if your protocol allows for it.

 

Without a CS line, monitoring DMA for progress and implementing a timeout seems fine, provided your protocol is idle for long enough.

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

Thank you for your answer.

I tried performing a reinitialization of the SPI peripheral and the DMA stream but it doesn't work.

What I am trying to do is the implementation of SSI communication. I did it by bit-banging but it is not fast enough for high frequencies, so I decided to use the SPI peripheral. I will normally have 25 bits on communication, but it is possible to have incomplete frames.

 

I changed the SPI communication from DMA to Interrupt and now it works OK, restarting the communication when I need it. The problem is that other interrupts are not triggered at the designed time if the are coincident with the SPI frame.

That's why I wanted to use DMA.

It is solved!

What I was doing wrong was the reset sequence.

On the 5th step, the functions sequence that works for a good reset is:

HAL_SPI_DMAStop();

__HAL_RCC_SPIx_FORCE_RESET();

__HAL_RCC_SPIx_RELEASE_RESET();

HAL_SPI_Init();

HAL_SPI_Transmit_DMA();

 

Once I found the RCC macros, it worked.