2025-11-17 12:53 PM - edited 2025-11-17 12:53 PM
Hey!
I will explain my setup and then paste the code. I have three different timers (TIM1, TIM2, TIM3) sending out PWMs to different parts of my board. All timers are set up the same way; the only difference is that TIM1 is an advanced timer.
What I do is initialize all my timers and start everything up. Then, much later, I switch my pins from GPIO output low to pin alternate mode to enable the PWM outputs. This works great 999 times out of 1000, but sometimes TIM1 (and it’s always TIM1) randomly decides to put the PWM high for a very long time and then, after about 20 ms, goes down to 0 and never starts again. Resetting the MCU fixes this, and everything works as expected.
(Using STM32G051)
Here is the initialization code for TIM1:
TIM1.CR1.CMS = 0x1; //Set TIM1 center aligned mode, trigger interrupt flags on compares in downcount
TIM1.CR2.MMS = 0x7; //OC4REFC signal is used as trigger output (TRGO)
TIM1.ARR = PERIOD_SIXTH * 3; //Auto-reload register
TIM1.CCMR1.OC1M = 0x6; //PWM mode 1 on channel 1; in upcounting PWM active below compare
TIM1.CCMR1.OC1PE = 1; //Enable preload
TIM1.CCMR1.OC2M = 0x7; //PWM mode 2 on channel 2; in upcounting PWM active above compare
TIM1.CCMR1.OC2PE = 1; //Enable preload
TIM1.CCMR2.OC4M = 0x6; //Set Channel Active on match
TIM1.CCMR2.OC4PE = 1; //Enable preload
TIM1.CCR4 = PERIOD_SIXTH * 2; //Sync pulse to TIM2
TIM1.CCER.CC1E = 1; //Enable output on channel 1
TIM1.CCER.CC2E = 1; //Enable output on channel 2
TIM1.CCER.CC4E = 1; //Enable output on channel 4
TIM1.BDTR.MOE = 1; //Enable MOE (main output enable)
TIM1.EGR.UG = 1; //Generate update event on TIM1
2025-11-17 1:55 PM
The TIM does what it's told. Debugging and examining the TIM1 registers after it "goes down to 0 and never starts again" may shed a clue as to what's happening. Perhaps a write out of bounds or stack overflow happens.
2025-11-19 2:27 AM
hello @morris
can you provide more details about this step:
"Then, much later, I switch my pins from GPIO output low to pin alternate mode to enable the PWM outputs."
what are the steps that you followed to do it?
also did you try to track the counter, prescaler and ARR registers when this strange behavior happens?
BR
Gyessine
To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.
2025-11-19 3:26 AM
You seem to use some non-standard definitions of timer control registers with bit fields. You may encounter strange problems if the bit fields are defined with the base type other than uint32_t. Also, the problems may arise if you attempt to modify timer control registers in the event loop and in ISRs.
2025-11-25 1:53 AM
When I read the registers when its in the "fault mode" I can see that everyting is fine, all clocks is running but the TIM1.CCR2 keeps switching between 34830 and 8837. This is extremly strange because I clamp the value to 459 before writing to these registers. Also I tried (in debug mode) writing to this register manually, but it gets directly overwritten to 34830 or 8837.
2025-11-25 1:53 AM
When I read the registers when its in the "fault mode" I can see that everyting is fine, all clocks is running but the TIM1.CCR2 keeps switching between 34830 and 8837. This is extremly strange because I clamp the value to 459 before writing to these registers. Also I tried (in debug mode) writing to this register manually, but it gets directly overwritten to 34830 or 8837.
2025-11-25 2:59 AM
> TIM1.CCR2 keeps switching between 34830 and 8837. This is extremly strange because I clamp the value to 459 before writing to these registers
That means, that TIM1_CCR2 gets written in some part of your program you are not aware of.
> Also I tried (in debug mode) writing to this register manually, but it gets directly overwritten to 34830 or 8837.
Was that while a) the processor was stopped (e.g. at a breakpoint, or manually by pressing something like "stop" button in IDE), or b) while processor running?
If a), it's some of the DMAs, so read out all DMA's registers and check their address registers' content, whether they point to TIM1_CCR2 or to TIM1_DMAR.
If b), it may be either DMA or interrupts or some other part in the program (and note, that RTOS is nothing but interrupts), so try first with the processor stopped. If the register won't change while processor is stopped, it's in the program; use data breakpoint (a.k.a. watchpoint) at the TIM1_CCR2 register to find out where does it get overwritten.
JW