EFM32 timers, PWM and xtimer

Hello RIOT developers,

working with the EFM32 port trying to use some PWM pins, I found that of the four TIMER peripherals (each of which is tied to particular sets of PWM pins it can drive), two adjacent[1] ones are in use for a combined RIOT timer peripheral that them forms also the XTIMER_DEV. This means that two timers (1 and 2 of 0, 1, 2 and 3) are practically unusable for any PWM.

Before I go head-first into hacking something together with a timer implementation based on the RTC or the systick peripheral, was there a particular rationale behind making this the default timer on EFM32?

AFAICS, the design does make sense when it comes to creating arbitrary timers (where the lower timer gets its fine-grained top value output a precise frequency), but that isn't really required when it comes to providing a timer for XTIMER which has its own XTIMER_HZ value which "just" needs to set to an adaequate value. How is the trade-off between having PWM devices vs. having a fine-grained-fixed-frequency capable timer usually handled?

Thanks chrysn

[1]: That's a limitation of the chips, where TIMEROUF only works between adjacent timers.

Hi Chrysn,

The two timers are needed, because they run in cascade mode. Only that way, I can generate values for XTIMER_HZ that have sufficient resolution. I don’t recall the details, but I haven’t found another way. The recommended MCU oscillators are typically 38.4 or 40 MHz, and the prescaler is always a power of two, so I cannot get 1us precision with only one timer.

The newer chips have an additional 32-bit timer with the same problem, but this frees up timers for PWM. I have a PR that I still need to fix though :wink:

Hi Bas,

thanks for your quick response!

The newer chips have an additional 32-bit timer with the same problem, but this frees up timers for PWM.

That unfortunately won't help with the hardware I have here right now :-/

The two timers are needed, because they run in cascade mode. Only that way, I can generate values for XTIMER_HZ that have sufficient resolution.

As I understand, the timer that serves XTIMER needs to be precise 1MHz, and may be up to 6 shifts away from it -- but there is also the option of running it from a 32768Hz clock available as internal and often external clock. That seems to be sufficient xtimer resolution for some applications (it certainly is for mine).

Options are a bit limited as to how to implement such a clock without moving the whole device on the low frequency clock (HFPERCLK TIMERn can only be clocked from LFxO if all HF stuff actually uses that in HFCLKSEL), but the LETIMER0 (or RTC, but LETIMER is unused) would be an option here (provided LFACLK comes from an LFxO).

If LETIMER support were to be added, it could probably look similar to the changes in [1] -- but would need to branch out in timer_init, and (when it's a LETIMER) err out if the desired frequency is not 32768.

Christian

[1]: cpu: efm32: add support for 32-bit timers by basilfx · Pull Request #9878 · RIOT-OS/RIOT · GitHub

Hi Christian, If you want some inspiration for a timer driver you could take a look at the Kinetis periph/timer driver which wraps two different timer hardware modules underneath, one for high frequency and precise control (PIT, always clocked by the CPU bus clock), and the other for low power consumption and lower frequency (LPTMR, usually clocked by the RTC oscillator, but there are other options as well). Additionally, PR#7897 adds pm_layered management inside the timer driver for the PIT to prevent low power modes from disrupting a timer when there is a target set.

https://github.com/RIOT-OS/RIOT/blob/master/cpu/kinetis/periph/timer.c https://github.com/RIOT-OS/RIOT/pull/7897/files

/Joakim