cancel
Showing results for 
Search instead for 
Did you mean: 

Timer synchronization offset STM32G431RB

IBeck.1
Associate

I am trying to configure two timers (TIM3 & TIM4) to start at the same time, following the procedure in RM0440 pg. 1304. However, when I scope the output pins of my timers, there is a ~25us delay between the edges of the pulses. Is there any way to eliminate this delay to make them synchronized near-perfectly? I have attached setup functions for the timers, using a system clock of 170MHz.

    RCC->APB1ENR1 |= RCC_APB1ENR1_TIM3EN;
    RCC->APB1ENR1 |= RCC_APB1ENR1_TIM4EN;
 
    /*****************************************************************************/
    /* Configure Master Timer TIM3 */
 /*****************************************************************************/
    
    TIM3->PSC = 170 - 1;        // 1 MHz CLK
    TIM3->ARR = 5000;           // 200 Hz
    TIM3->CCR1 = 50;            // 50us pulse to be synchronized
    TIM3->CCER = TIM_CCER_CC1E; // Enable TIM3CH1 output
    TIM3->CCMR1 |=  (6 << 4);   // Set to PWM mode
 
    // Set MMS bits to "Enable as trgo"
    TIM3->CR2 |= (1 << 4); 
    
    // Set TS bits to 00100
    TIM3->SMCR |= (4 << 4);
    
    // Set MSM bit to 1 for master
    TIM3->SMCR |= TIM_SMCR_MSM;
    
    // Set SMS bits to Trigger mode (110)
    TIM3->SMCR |= (6 << 0);
 
    /*****************************************************************************/
    /* Configure Slave Timer TIM4 */
    /*****************************************************************************/
    TIM4->PSC = 170 - 1;        // 1 MHz CLK
    TIM4->ARR = 5000;           // 200 Hz
    TIM4->CCR1 = 50;            // 50us pulse to be synchronized
    TIM4->CCER = TIM_CCER_CC1E; //Enable TIM4CH1 output
    TIM4->CCMR1 |=  (6 << 4);   // Set to PWM mode
 
    // Set TS bits to 0
    TIM4->SMCR |= (0 << 4);
 
    // Set SMS bits to Trigger mode (110)
    TIM4->SMCR |= (6 << 0);
 
    // Turn on Timers
    TIM4->CR1 |= (1 << 0);
    while(!(TIM4->SR & (1<<0)));
    TIM3->CR1 |= (1 << 0);
    while(!(TIM3->SR & (1<<0)));

3 REPLIES 3
TDK
Guru

Set one of them in gated slave mode and use the other as the master. This will sync them perfectly.

Or just do TIM4->CR1 |= 1; immediately after TIM4->CR1 |= 1; to reduce the delay. Pre-cache the value beforehand so it's two single writes instead of two read-modify-writes.

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

> TIM4->CR1 |= (1 << 0);

No, this defeats the whole point of Trigger mode in Slave-mode controller/ In Trigger mode, it is the Slave-mode controller which sets TIMx_CR1.CEN, when the trigger arrives.

So, start with removing line 42 (plus the test after it on line 43, which is simply not needed at all, so you can remove also line 45).

There still will be some delay imposed by the trgi-trgo mechanism, which ST does not care to specify, experimentally it appears to be around 2 system clocks if there's no other external influence (e.g. timers on differently clocked APB buses, the MSM mechanism described below, maybe others - as I've said, ST does not care to be meticulous in details). The simplest approach to mitigate this is to set the slave's clock (i.e. TIM4_CNT) to the value equivalent to the delay, i.e. around 2, before the enable sequence.

You appear to have attempted to mitigate by using the MSM bit. However, that works only if you in turn trigger TIM3 from the slave-mode controller i.e. again, you would avoid setting TIM3_CR1.CEN explicitly, rather, you would trigger it using the trigger selected by TIM3_SMCR.TS. You've selected TIM3_CH1 edge there; however, for that to work you then could not use TIM3_CH1 as PWM output, but you would need to set TIM3_CH1 as Input Capture in TIM3_CCMR1.CC1S, and then of course bring in some signal tom TIM3_CH1. I personally don't use MSM, though, as in my experiments, while it did impose a delay shortening the effect of inter-timer connection, it did not suffice to eliminate it entirely as promised. This may again be dependent on more factors.

One more thing: note, that TIMx_PSC is unconditionally prescaled. You want to get it "active" by forcing Update by setting TIMx_EGR.UG before any sort of enable; however, note that Update is also the signal which serves as TRGO from the master.

JW

> TIM4->CR1 |= 1; immediately after TIM4->CR1 |= 1;

You probably meant

TIM3->CR1 |= 1; immediately after TIM4->CR1 |= 1;

or the other way round.

JW