2024-08-13 06:39 PM - edited 2024-08-13 09:27 PM
NUCLEO-G474RE
My design uses two timers, one in master mode(TIM20) and one in slave mode(TIM1).
To have the master timer generate an update signal in the trigger output, I set its TRGO event selection as "Update Event". the CR2 value 0x200020 confirms MMS is set to 2. I confirm TIM20 is running by probing its PWM output channel routed to an GPIO.
The trigger source for the slave-mode TIM1 is ITR9, which comes from TIM20(my master-mode TIM).
TIM1 is in "Combined reset + trigger mode". The design goal is to have a UEV(update settings from pre-loaded registers) and trigger(my understanding on the concept of trigger here is that the CEN bit is set by hardware automatically).
I want the TIM1 to produce one PWM output per UEV from TIM20, therefore OPM is enabled in TIM1(Given my Repetition setting is 1, by the end of the TIM period, CEN will be 0 automatically, waiting for next trigger from master TIM20).
The TIM1 PWM parameter is a sequence of known values, therefore I enabled a DMA channel to transfer these known data from memory to TIM1 preload register. I expect the DMA request flow is 1) TIM20 sends UEV to TIM1, 2) TIM1 update its PWM settings from preload registers, 3) in the meantime, TIM1 also makes a DMA request and populates the preload register for next PWM period.
After using __HAL_TIM_ENABLE_DMA on TIM1(DMA in TIM1 is waiting for trigger), I start running master TIM20.
I must have made some fundamental mistake here, because the TIM1 doesn't produce any PWM waveform. If I don't use the master-slave setup, the PWM waveform in TIM1 looks good(just to confirm I am probing the right pins). Since I am using circular mode DMA transfer, I created some CB functions for HT and FT, and they are not called, which seems to be indicating trigger has NOT been received from TIM20. In TIM1's SR, I do see TIF being 1, which seems to be indicating trigger has been received from TIM20.
I didn't find any HAL/LL TIM related API that can be used to configure such operation(master-TIM syncs the slave-TIM's DMA data transfer of its setting). Did I miss anything related in the HAL/LL?
While I am digging into the details in RM, can I get any suggestions/hints? Even how to properly describe such a problem means a lot to me.
In case I failed to describe any details, I dump the TIM1 register info into files:
Solved! Go to Solution.
2024-08-15 12:17 AM
TIM20 is an Advanced Timer and as such, it has the Repetition Counter. That can be used to generate a preset number N of timer cycles when it's set to OPM. However, the mechanism to achieve that also means, so Update is generated only once per N cycles (at the end of Nth cycle), so you then can't use Update as source of TRGO. You could still use one of the TIM20 channels as TRGO source.
Another option to generate N cycles (and then stop) may involve TIM20-DMA which loads TIM20's ARR N-times with a "normal" value and the N+1th being zero, which stops the timer.
The third option is, as you've said, involving a third timer. You don't necessarily
There may be other ways to achieve what you want.
Details do matter. Triggering one timer from the other means, that there are delays - sometimes full cycle long - between them. Preloading of ARR/CCRx means, that there are further cycle-length delays. Draw yourself timing diagrams. Experiment a lot - for some experiments you don't need even to write program, you can experiment by directly manipulating registers in debugger.
JW
2024-08-13 07:23 PM
Presentation of registers is horrible, how can you make out what happened? Don't you have some means to restrict it only to the relevant registers?
TIM1 SR indicates it has run at least once, if you haven't seen any output pulse, the problem may be GPIO setting so check that. Start with TIM1 running freely (i.e. no slave setting and no OPM), does that produce output PWM signal?
JW
2024-08-13 07:42 PM
Hi, JW, thanks a lot for your comment, I put some screenshot of the TIM1 register values, hopefully useful.
The GPIO settings and probing point are confirmed. If I disable TIM1's current setting of slave mode, I can observe the numerically correct PWM waveform as is specified by ARR and CCx settings.
2024-08-13 10:12 PM
TIM20 is set to OPM. Is that an intention? What happens if you start it repeatedly?
JW
2024-08-14 12:26 AM
Hi, JW, you pointed me to the right direction, thanks. I intentionally put TIM20 in OPM, which is a mistake. My design goal is for TIM20 to produce a finite number N of PWM output, and N update to TIM1. The number N is also the length of uint32_t array for the TIM1's DMA channel to transfer from memory to TIM1. In OPM, the TIM20 will generate only one UEV in the end instead of N UEV's. Switch TIM20 to continuous running allows TIM1 with DMA working correctly.
If I may, I have a follow-up question. Now TIM20 runs continuously. I get the first N period for both TIM20(master) and TIM1(slave), which is the desired portion. After the desired first N period, both TIM20 and TIM1 continue output PWM. (TIM1 DMA in linear mode won't stop the PWM output.) However my design requires exactly N PWM periods produced by TIM20 and TIM1.
I can think of have DMA TC interrupt ISR to clear TIM20 CEN. Ideally I hope to avoid such SW solution and its associated latency/safety risk. That's why I made the mistake of OPM in TIM20.
I am stuck at the point now that TIM doesn't seem to be able to produce N UEV while output N PWM waveform. The only other approach I can think of is to use a GPIO pin to output the OPM signal using a third TIM, and electrically wire the signal to TIM20 and TIM1's ETR or ti1fp1. But this is obviously not optimal.
Could you share with me your insight please?
2024-08-15 12:17 AM
TIM20 is an Advanced Timer and as such, it has the Repetition Counter. That can be used to generate a preset number N of timer cycles when it's set to OPM. However, the mechanism to achieve that also means, so Update is generated only once per N cycles (at the end of Nth cycle), so you then can't use Update as source of TRGO. You could still use one of the TIM20 channels as TRGO source.
Another option to generate N cycles (and then stop) may involve TIM20-DMA which loads TIM20's ARR N-times with a "normal" value and the N+1th being zero, which stops the timer.
The third option is, as you've said, involving a third timer. You don't necessarily
There may be other ways to achieve what you want.
Details do matter. Triggering one timer from the other means, that there are delays - sometimes full cycle long - between them. Preloading of ARR/CCRx means, that there are further cycle-length delays. Draw yourself timing diagrams. Experiment a lot - for some experiments you don't need even to write program, you can experiment by directly manipulating registers in debugger.
JW
2024-08-15 07:43 PM
Hi, JW, please accept my most sincere appreciation. Your help is not only THE SOLUTION, but also a guideline to more systematical design approaches :)