cancel
Showing results for 
Search instead for 
Did you mean: 

Syncronous Timers

DetlefS
Associate III

Hi,

I'm running two timers on STM32F303 which do square wave output on two hardware pins. They are clocked by the 72MHz internal clock. They count down to 0 and reload from ARR register, which sets the output frequency. The two timers run perfectly syncronous, i.e the CNT registers of the timers have a constant offset.

Then I permanently have to switch the frequency for both timers by modifying the ARR registers.  As a result the CNT registers of the two timers begin to slip, i.e. the offset is changing.

I suspect the following: I modify the two ARR registers consecutively. I check for CNT counters to be high enough so no reload takes place while modifying the ARR registers.  Maybe an interrupt happens in between ARR update for the first counter and ARR update for the second counter. So one CNT register is updated from the old ARR value, the other from the new one. So the two counter values begin to slip.

 

I use the eval board for STM32F303 and initialize all to the default values with CubeIDE12. I hope and I'm quite sure I killed all interrupt sources, but there are hidden corners in CubeIDE. When I check the runtime of an arbitrary set of code I get changing numbers of systicks for that code. I'm running the board over the USB debug setup from the host, so the debug may kick in with interrupts.

 

How can I switch off all interrupt, especially with regard to CubeIDE and debug mode from host?

 

Thank you.

Cheers

Detlef

 

1 ACCEPTED SOLUTION

Accepted Solutions
TDK
Guru

__disable_irq() will globally disable all interrupts. It would be fine to call this while you update the registers.

__disable_irq();
TIM1->ARR = xxx;
TIM2->ARR = xxx;
__enable_irq();

You should re-check to ensure TIM1->CNT is in the appropriate range after you disable interrupts and before you set ARR.

Using systick to time events isn't the most precise thing. And it will be invalid if you have interrupts disabled. It would be better to use DWT->CYCCNT or a 32-bit timer.

Your method for resetting the timers should work. If they're upcounting, which is typical, you would wait for them to overflow (i.e. have a low CNT), then update. If you know which one is behind the other, and they're only off by a few counts, this should be straightforward.

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

View solution in original post

4 REPLIES 4
MasterT
Lead

If I need two timers in sync, than configure both of them in slave mode and add one more Master timer. Than to do PWM reconfig,  I stopped master timer, change two slaves configuration, and than start master.

TDK
Guru

__disable_irq() will globally disable all interrupts. It would be fine to call this while you update the registers.

__disable_irq();
TIM1->ARR = xxx;
TIM2->ARR = xxx;
__enable_irq();

You should re-check to ensure TIM1->CNT is in the appropriate range after you disable interrupts and before you set ARR.

Using systick to time events isn't the most precise thing. And it will be invalid if you have interrupts disabled. It would be better to use DWT->CYCCNT or a 32-bit timer.

Your method for resetting the timers should work. If they're upcounting, which is typical, you would wait for them to overflow (i.e. have a low CNT), then update. If you know which one is behind the other, and they're only off by a few counts, this should be straightforward.

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

Hi,

I tried to guard the ARR modifications with the disable/enable interrupt setup. I still get a slight slip, I miss some of the 72MHz pulses. It is not many, I miss 450 ticks within a minute or so. There is no slip if I keep ARR untouched. The timers are counting down. So I check for both counters being high and then I change ARR. Maybe there is a flaw in this part of the code. Anyway, the problem is hunt down and will be solved after a long weekend.

THX, stay tuned.

Cheers

Detlef

 

DetlefS
Associate III

So, weekend is over and I solved it, more or less. 

What I did: I have timer1 and timer2. timer1, slow one, ist counting down from 4*max to 0, fast one is counting down from max to 0. CNT registers of both timers are in sync, they share the same input clock. Then I change max, i.e. I modify ARR registers of both timers. If one CNT register reloads from the new ARR, the other from the old one you are out of sync. So you have to doublecheck the CNT register to be high enough. Then there is enough time to change both registers. And, as TDK lined out, no IRQ may kick in.

I check sync for both timers by waiting for a specific CNT value of the fast one, then I read out the slow one, IRQ always disabled. If I replace max with the same value all is working fine. If I replace max with another value, I get a higher jitter for the sync check and a very slight slip, some ticks over minutes.

So I conclude there is another interrupt still alive which brings the timers out of sync.

I decided to reset both CNT registers after ARR modification.

This is not nice, but it works for me.

Cheers

Detlef