periph/rtt intent

Dear developers, The intent of the RTT API seem to be rather unclear. My interpretation was that the RTT API is used for long time, low precision timers that can be used to sleep the system for minutes, hours or days. The precision is expected to be 1 second, the same as for the RTC API, but without the calendar struct representation. The reason for using the RTT API is to let it represent the current wall clock time, for tagging collected data etc, while the xtimer (and periph timer) is used for delays and internal precision timing of events. The RTT alarm is used to schedule wake ups or events which should happen at a specific time of day, for example taking a measurement every day at 2:00. There seem to be a different interpretation as well: the RTT API is used for any hardware timers which keep running in low power modes. This split is seen in the board configurations, where some boards list the RTT as a 32768 Hz timer, others list it as a 1 Hz timer. This has already begun causing problems among the API users, see the lwmac implementation for example, which only works if the RTT is 32768 Hz. My interpretation was initially based on a limitation in the RTT (called RTC in NXP documents) on Kinetis hardware which only allow integer seconds for the alarm, while a different hardware module can be used for 1/32768 second precision, but that timer wraps around after 2 seconds (2**16 ticks). We need to clarify the documentation and align the implementations to match each other, or the RTT API will be useless as an abstraction layer, since its interpretation will be platform dependent.

What are your opinions on the RTT API, or the timer APIs in general?

Best regards, Joakim Nohlgård RIOT developer


For the motivation of creating the RTT interface it is needed to once more recap the main motivation of the peripheral drivers: the idea is/was to introduce unified APIs that give direct access to selected MCU peripherals with the least possible overhead, mapping each type of peripheral to exactly one API. So it was never intended for the periph interfaces to care of multiplexing between different hardware units of the same/simliar type, but this was always intended to be done by higher layer modules (as e.g. the xtimer, stdio, etc).

So the original reason for creating the RTT interface was actually historically driven by the stm32’s and the sam3, where especially the stm32 have three different hardware units (timer, rtt, rtc), all with some different characteristics. So we decided back then, to create different periph APIs for each of these units.

Now from todays point of view (and we have learned a lot in the last 3 years…), I think what is nagging is most conceptionally is that the periph API and the way its used does not allow us to concurrently map different devices into the same API (e.g. timer vs lptimer, uart vs. lpuart, rtt vs tim, etc). The only way this is currently possible is to use (very) ugly if-else constructs in the periph drivers imlementation, that switch between two (or more?) completely different code paths. This is not only ugly, hard to maintain, and imposes run-time penalties, but this also breaks with the original intention of the periph API to provide slim and direct access to a single selected type of peripheral.

So back to the RTT topic: considering what one would expect from the API, there is indeed no good reason for having a separation between periph/timer and periph/rtt. Both provide the same type of functionality and the periph/timer interface could simply also be implemented for rtt hardware units. But to do this cleanly, we would need to solve the (internal) multiplexing issue for using different typed peripherals under the same API. There was some prior work done by some people in the community (kaspar, johann, …) to play around with function pointer based approaches which would solve this issue natively, but so far no solution yielded satisfying results and could compete in terms of efficiency.

So bottom line: functional the RTT interface does only make limited sense, but structurally given by the motivation of the periph interfaces there is a reason for having it. I guess the problem we need to solve is more about internally multiplexing peripheral types to the same API…

Cheers and thanks for bringing this up, Hauke

A brief aside, as far as I recall I had to make the timer interface also integrate the RTT to get xtimer to use the RTT on SAMR21. It was very ugly, which is why I did not upstream it.