Skip to main content
Associate
July 29, 2026
Question

STM32F777: DMA race condition between TIM8 CH1 and TIM8_UP triggering SPI

  • July 29, 2026
  • 7 replies
  • 83 views

Hello community,

I am currently working on an STM32F777 project where I encounter a race condition between two DMA-triggered SPI transfers originating from the same timer (TIM8).

Setup:

  • MCU: STM32F777

  • Mechanism 1 (Input Capture): TIM8 CH1 is configured for Input Capture. Upon an active edge, a DMA request transfers a 14-bit data packet to SPI->DR.

  • Mechanism 2 (Periodic Update): TIM8_UP (Update Event) triggers a chained DMA transfer that writes 2 consecutive packets to SPI->DR.

The Problem:

When both events (TIM8 CH1 Input Capture and TIM8_UP) trigger simultaneously, a collision occurs on the SPI bus:

  1. Only 2 packets appear on the SPI MOSI line instead of the expected sequence.

  2. The transmitted sequence consists of the packet from the CH1 Capture event followed directly by the second packet of the TIM8_UP chained DMA transfer.

  3. The first packet of the TIM8_UP DMA transfer is lost/overwritten.

  4. Following this race condition, the entire transfer mechanism halts, and no further packets are transmitted.

Question / Expected Hardware Behavior: 

Is there a hardware-level way (e.g., via DMA stream priority, timer gating, request masking, or trigger configuration) to give TIM8_UP strict priority over TIM8 CH1, so that a periodic TIM8_UP event completely overrides/suppresses the CH1 capture transfer if both occur at the same time?

Handling this in software via an ISR is too slow for my timing constraints, so I require a pure hardware or register-level solution.


Update:
I managed to catch the error in the IRQ. After restarting the timer, the packets are triggering on the periodic TIM event again. However, the two packets are now swapped – the first one is sent last, and the last one comes first.
Does anyone know why this might be happening and how I can fix it?
 

Thanks in advance for your insights!

7 replies

waclawek.jan
Super User
July 29, 2026

What is “chained DMA transfer”?

JW

FelixFTZAuthor
Associate
July 29, 2026

A single TIM8_UP event triggers DMA_A, which enables DMA_B by writing to its control register (DMA_B->CR).
Once activated, DMA_B performs the actual 2-package transfer driven by standard SPI_TX (buffer empty) requests.

MasterT
Lead II
July 29, 2026

A single TIM8_UP event triggers DMA_A, which enables DMA_B by writing to its control register (DMA_B->CR).
Once activated, DMA_B performs the actual 2-package transfer driven by standard SPI_TX (buffer empty) requests.

I interfaced MCP3562 to F4/F7/G4 ( or any uCPU with limited 16-bits SPI). The problem is ADC requires data read command sequence on 32-bits data frame. Here is clean “hardware” solution:

  1. Timer-3 getting input capture events directly from DR (data ready) ADC pin;
  2. Time-3 ch-2 drives OC pin to activate CS line, indicating readiness to SPI transaction; 
  3. Tim-3 also chains to Tim-1 configured in One Pulse repeat 4 times mode;
  4. Tim-1 ch-1 drives DMA->SPI_DR 4 times 8-bits each in MEM-2-PER, sending comman.
  5. Tim-1 ch-2 drives DMA-:SPI_DR for PER-2-MEM direction, reading ADC data 

Doing so, I have full control over timing  SPI each packet simply changing Tim-1 period, so I can expand 32-bits transfer for longer, nulling out parasitic coupling in between SPI clock to ADC sampling frequency. 

 

TDK
July 29, 2026

You can write 2 packets to SPI->DR, but not 3. The first immediately goes into the shift register. Don’t think there is a way to solve this apart from moving to a chip with a TXFIFO for SPI, which is most of the newer ones, including STM32H7.

"If you feel a post has answered your question, please click ""Accept as Solution""."
FelixFTZAuthor
Associate
July 30, 2026

Thanks for your reply!

Moving to another chip isn't an option for this project, but I'll definitely keep that in mind for future designs.

Currently, I push a new 14-bit package into SPI->DR every time the SPI TX empty flag triggers. This should allow me to send continuous, back-to-back packages indefinitely, correct?