Showing results for 
Search instead for 
Did you mean: 

STM32U575 timer triggered DMA for autonomous SPI transfers

Associate II


I have a STM32U575 connected to an external HW watchdog which needs to be periodically fed (with a 100 ms timeout) with an SPI command from the MCU (2 bytes), and i would like to achieve this without CPU intervention (or as little as possible).

Here's what I achieved so far:

  • I set up TIM6 to generate an update event every 50ms
  • I linked TIM6 update event to GPDMA1 channel 0 
  • DMA source address points to a 2 byte array containing the data to be sent over SPI (to feed the watchdog)
  • DMA destination address points to SPI1->TXDR register.
  • DMA is configured in Linked List Circular Mode to trigger the transfer each time the TIM6 update event triggers

Here's the DMA configuration


To start the procedure i simply to the following:

  • __HAL_SPI_ENABLE(&handleSPI1); //enable the SPI
  • SET_BIT(handleSPI1.Instance->CR1, SPI_CR1_CSTART); //set the transmission start BIT
  • HAL_DMAEx_List_Start_IT(&handleWDTimerUpDMA); //Start the DMA
  • HAL_TIM_Base_Start_IT(&handleWDTimer); //Start the TIMER

The problem is that the TIMER and the DMA work nicely (DMA transfer happens periodically as exepcted), but the SPI data is actually sent out only the first time. My understanding is that the SPI peripheral needs to be re-armed for the next transmissions. To do that I added the following lines to the SPI configuration to enable the autonomous mode:

HAL_SPI_AutonomousMode_Cfg_Struct.TriggerState = SPI_AUTO_MODE_ENABLE;
HAL_SPI_AutonomousMode_Cfg_Struct.TriggerSelection = SPI_GRP1_GPDMA_CH0_TCF_TRG;
HAL_SPI_AutonomousMode_Cfg_Struct.TriggerPolarity = SPI_TRIG_POLARITY_RISING;
HAL_SPIEx_SetConfigAutonomousMode(&handleSPI1, &HAL_SPI_AutonomousMode_Cfg_Struct);

This resulted in having the SPI_CR1_CSTART bit to be autonomously set by the DMA upon the transmission complete event (correct me if my understanding is wrong).

Unfortunately, this wasn't enough to retrigger the transmission, i had to add the following lines on the Transmission Completed interrupt of the SPI:

SET_BIT(handleSPI1.Instance->IFCR, SPI_IFCR_EOTC);

This works but it still needs CPU intervention to trigger the SPI interrupt and clear the registers.

Do you have any suggestion to completely automate the process without having the CPU to intervene?



I have the same question. Do you solve the problem about clearing the SPI interrupt flags?

Thank you very much.

You are like the support of some big companies: you give a perfectly accurate, but totally useless answer...

How do you achieve what you specify?