2023-08-12 04:59 AM - edited 2023-08-12 05:20 AM
Hello, hope this message finds you well.
So, I'm on a project that requires multiple timers to generate 7 variable pulse waveforms in master/slave mode and I'm hoping to get parallel synchronization at startup, I'm using timer 1 as master, and timer 2 as a slave.
I have done things as per Reference Manual and ST knowledge base videos and articles, so can't see any extra detail that might cause this issue described below.
The device is STM32F103C8T6, and I am using HAL libraries.
The issue:
Tim2 does not align with Tim1, seems to me their alignment is code dependent, so sometimes they align perfectly, and when you change the code even in non-timer-related sections they get out of alignment.
more useful info for you:
TIMER 1 (Master) settings:
CH1,2,3 are "PWM Generation" and CH4 is either "PWM Generation NO Output" or "Output Compare NO output" have tried both, does not make a difference.
No Prescaler is used so Clock is 72Mhz, only using ARR for Frequency adjustments. RCR => 50.
Trigger Event Selection => Output Compare(OC4REF)
TIMER 2(Slave) settings:
Slave Mode => Trigger mode, Trigger Source = > ITR0, Clock Source for both timers => internal Clock, CH1,2,3,4 => PWM Generation.
just to note that timer2 is using DMA in DMA-Burst-Multi-write mode and it changes the ARR value as well as all the channel's CCR value 5 times in every TIM 1 period(TIM1 ARR = TIM2_ARR1 + TIM2_ARR2 + ....+ ARR5), and also all the values related to TIM1/TIM2 registers might change on the fly.
See Attachment section.
Long story short, It's been a long time since I'm tackling this, and have tried many things along the way but can not reliably synch both timers, At first TIM1 used a 9Mhz clock, and TIM2 72Mhz (8 times more) but now I changed TIM1 to use 72Mhz clock, however, no progress has been observed.
tried starting TIM2 channels first and TIM1 second and vice versa, it changed the delays but was not aligned to the required delay.
There is a visual scheme for you in the attachment section.
if you need any specific information or detail, please let me know.
Solved! Go to Solution.
2023-08-13 10:06 AM
JW, thank you for the hint on "Slave mode= Trigger mode" in your first post.
it made me think about the Triggering once more and by reading the RM section 15.3.14 more carefully I found the solution(hope it lasts as I go further).
I solved it.
simply by changing slave mode to "Reset mode" AND using the Max value(65536-1) for both timer ARRs in the initialization code in CubeMX, I could manage to solve this conundrum.
so A, B, and C are all good now.
just one more thing.
there is one strange behavior happening with my CubeIDE:
when I upload the code to the target MCU, during the build and upload, it automatically opens up different system files like "startup_stm32f103c8tx.s" and "stm32f1xx_hal.c" and goes to a specific line of code or functions like it's trying to say something and those functions are mostly about systick, interrupts, and timers.
I'm not sure what it's all about!
2023-08-12 05:52 PM - edited 2023-08-12 06:10 PM
Has this video been seen?
Hands-On with STM32 Timers: Internal Triggering System
I don't know if it can help in your case, but I found these videos about advanced debugging:
STM32CubeIDE Advanced Debug Features
(Note: The video shows the dual core MCU, but uses only one core. If anyone needs to debug this type of MCU in the future: Dual Core Debugging on STM32H7 with STM32CubeIDE)
2023-08-13 12:13 AM
> timer2 is using DMA in DMA-Burst-Multi-write mode and it changes the ARR value
> and also all the values related to TIM1/TIM2 registers might change on the fly.
So, what exactly do you expect, how would TIM2 stay in sync with TIM1, if it's period changes? What do you mean by "sync" in that context?
> TIMER 2(Slave) settings:
> Slave Mode => Trigger mode
This probably does not do what you expect. Trigger arriving in trigger mode only sets TIMx_CR1.CEN, nothing more. So, if TIMx_CR1.CEN is already set, it does nothing.
Read the TIM chapter in RM. Perform simple experiments first.
JW
2023-08-13 12:43 AM
Thank you for the suggestion.
I have watched that video along with many others, and now I'm watching the second one about debugging features to learn new tricks, thank you again.
2023-08-13 01:34 AM
Now after further investigations and by isolating the problem, I have a rough idea of where the problem lays, but before going through that, I'm going to clear your mind from any confusion about the setup first.
>So, what exactly do you expect, how would TIM2 stay in sync with TIM1, if it's period changes? What do you mean by "sync" in that context?
The changes are not arbitrary, they are calculated so that the TIM2 ARR(s) will always at all times equal that of TIM1, so they have the same period, and same Frequency every time.
so take this as a simple example:
TIM1 -> ARR = 1000;
TIM1->CCR(s) = does not matter;
TIM2->ARR = This is done by the DMA_Burst_Multiwrite feature and it uses an array let's call it "Pulse_Buffer" that changes the TIM2 ARR and CCR values throughout one TIM1 ARR(period), BUT when you add all those TIM2 ARRs they will sum up to be equal to TIM1_ARR, like this:
TIM1_ARR = 1000
TIM2_ARR(s) = 100 + 200 + 500 + 50 + 150 = 1000
so they align perfectly, however, TIM2 getting out of alignment is coming from another place:
if the initialization values for the timers in cubeMX are equal to that of the array "Pulse_Buffer" in my code then everything will be aligned perfectly and they never get out of alignment(only ARRs have to be the same), now the issue is right here:
I have 3 user input latching switches, let's call them A, B, C:
they are pushed at the start of the program or sometimes when the application is running, but only one can be pushed at a time and every one of them is associated with a set of ARR and CCR values for TIM1 and TIM2, so basically they are different time settings for these timers.
now let's say we have CubeMX initialization values set to be the same as 'A' timer settings, then the 'A' timer settings will work perfectly, however, if we change the A to B or C it will not synch anymore.
that's interesting, I'm not sure where that comes from, I have tried disabling the PWM channels and time base and re-Enabling them after I set the timing values but it didn't yield any positive results.
I'm reading the Manual now for the dezilion's time as per your suggestion waclawek.jan, hope I get a snap in my mind.
2023-08-13 02:54 AM
Do you make sure a "program" changes only when the complete previous "program"? How exactly do you accomplish that?
Do you have TIM2 ARR preload set (i.e. TIM2_CR1.ARPE=1)? Note, that that at one hand ensures you don't inadvertently change ARR to a value lower than CNT, but at the second hand it makes timing trickier as the written value is not used immediately - draw yourself a timing diagram such as this (in that example only CCR changes, but the principle is the same).
JW
2023-08-13 10:06 AM
JW, thank you for the hint on "Slave mode= Trigger mode" in your first post.
it made me think about the Triggering once more and by reading the RM section 15.3.14 more carefully I found the solution(hope it lasts as I go further).
I solved it.
simply by changing slave mode to "Reset mode" AND using the Max value(65536-1) for both timer ARRs in the initialization code in CubeMX, I could manage to solve this conundrum.
so A, B, and C are all good now.
just one more thing.
there is one strange behavior happening with my CubeIDE:
when I upload the code to the target MCU, during the build and upload, it automatically opens up different system files like "startup_stm32f103c8tx.s" and "stm32f1xx_hal.c" and goes to a specific line of code or functions like it's trying to say something and those functions are mostly about systick, interrupts, and timers.
I'm not sure what it's all about!
2023-08-13 10:25 AM
>Do you make sure a "program" changes only when the complete previous "program"? How exactly do you accomplish that?
I'm not exactly sure what you mean by "program" If you meant to say how do I change time settings without them getting out of hand:
I use UEV of TIM1 to call upon a function and that function will change the ARR and CCR of timers values(mostly TIM2) but not too fast as I need the slow changes.
>Do you have TIM2 ARR preload set?
100%, and I notice the consequences of doing so.