2022-06-13 03:14 PM
I've got a STM32L053 (on a Nucleo-Lo53R8). I'd like to drive TIM21 from the 32KHz clock, and gang it with TIM22 to form a 32 bit counter. But I'm confused on a few points.
First question: how to drive TIM21 from 32KHz? The documents (RCC chapter, 7.2.16) says:
In a number of applications using the 32.768 kHz clock as RTC timebase, timebases completely independently from the system clock are useful. ... For this purpose, the LSE clock is internally redirected to the 3 timers’ ETR inputs,
Looking at Figure 18, available clock inputs for TIM21 are MSI, LSI, HSE_RTC and LSE. And in the TIM21 Clock Selection description (22.3.3), it says that in "External clock mode2: external trigger input (ETR connected internally to LSE)".
Question 1: must I do anything special to connect ETR to LSE? Or is it sufficient to select External clock mode 2?
Question 2: Is it possible to use the STM32CubIDE Device Configuration Tool to configure TIM21 this way? (I don't mind writing the code myself; I have a somewhat academic curiosity to see how far I can push the design tool...)
2022-06-13 03:20 PM
> Question 1: must I do anything special to connect ETR to LSE?
> Question 2: Is it possible to use the STM32CubIDE Device Configuration Tool to configure TIM21 this way?
Who cares?
Btw., you can also remap LSE to TIM21_CH1 in TIM21_OR.TI1_RMP, and then use it in the Slave-mode controller set to External clock mode 1; but the result is the same.
The real challenge is to read out the two chained timers in a coherent way.
JW
2022-06-13 03:28 PM
@Community member
That's very helpful, but you've just earned yourself a follow-on question! :)
> you can also remap LSE to TIM21_CH1 in TIM21_OR.TI1_RMP, and then
> use it in the Slave-mode controller set to External clock mode 1
My real goal is to drive TIM21 at 32KHz and gang TIM21 and TIM22 to form a 32bit counter. If I run TIM21 in slave mode, can I still use its output to clock TIM22 (also in slave mode)?
(If you didn't notice, this is my first encounter with ST32 timers...)
TIA.
2022-06-13 04:08 PM
> The real challenge is to read out the two chained timers in a coherent way
This is the pattern I've used on other platforms -- I don't see why it wouldn't work here:
uint16_t ms16, ls16;
do {
ms16 = TIM22->CNT; // capture high 16 bits
ls16 = TIM21->CNT; // capture low 16 bits
} while (ms16 != TIM21->CNT); // retry ms16 changed
return (ms16 << 16) | ls16; // compose into 32 bit value
2022-06-13 11:46 PM
> If I run TIM21 in slave mode, can I still use its output to clock TIM22 (also in slave mode)?
Yes. But using ETR and External clock mode 2 is equally good.
> This is the pattern
You read TIM22 counter into ms16 and then compare it to TIM21 counter. I don't think this is what you wanted.
Details matter. Note, that it takes a couple of system clock (or APB clock? ST does not document this) cycles until the TIM21 overflow propagates into TIM22 and increments it.
JW
2022-06-14 05:14 AM
> You read TIM22 counter into ms16 and then compare it to TIM21 counter.
> I don't think this is what you wanted.
Thanks for catching the typo. Amended and annotated:
do {
A: ms16 = TIM22->CNT; // capture high 16 bits
B: ls16 = TIM21->CNT; // capture low 16 bits
C: } while (ms16 != TIM22->CNT); // retry if ms16 changed
> it takes a couple of system clock cycles until the TIM21 overflow
> propagates into TIM22 and increments it.
That does pose a challenge -- thank you for the warning. I'm sure you already understand the issue, but for others reading this: At step B, assume TIM21->CNT has just overflowed, but at step C, due to propagation delays, TIM22->CNT has not yet incremented. Then (ms16 != TIM22->CNT) will be false and the loop will terminate before capturing the updated value for TIM22->CNT.
In other words, the do loop pattern does not protect against the race condition it was designed to handle.
@Community member : it appears you've had experience with this sort of thing before. How would you handle it?
2022-06-14 06:15 AM
> it appears you've had experience with this sort of thing
Not with this particular one, there was no concrete requirement for it. I have chalked it up to the "maybe try one day" list, but that one is very long.
I would try to characterize the problem first. It may be less severe than it appears at the first sight, if only processor reads the values, as there's an inherent APB-clock-related delay in each such read (I was thinking about simultaneous capture upon an external signal, and that's timing-wise a slightly different problem).
Sorry for scaring you off, while can't provide more help.
JW
2022-07-03 10:38 AM
@Community member Having stepped away from the problem for a few weeks, I've revisited the issue, but this time describing what I'm really trying to accomplish without assuming how I'm supposed to do it:
This is likely to be a more fruitful approach! :)