hw timers

Hi,

I am porting RIOT to a new platform and I have been having lots of problems with getting the timers working. I have gone through all the timer code and I think I understand how RIOT uses timers and found a few problems/limitations.

Limitations Am I correct in thinking:

  • RIOT only supports 32 bit timers?
  • RIOT uses multiple timers but they all must run at the same speed and be synchronised. So effectively there must be only one timer but multiple channels/compares.

Problems

  1. If I set a hwtimer for longer than the maximum period of the timer it will interrupt too soon. e.g. Timer overflows every 1000s. If I set a hwtimer to delay for 1001s it will interrupt in 1s time.

  2. vtimers fail if the maximum timer period is less than 4096s (SECONDS_PER_TICK).

  3. Currently vtimers do not check if they request a hwtimer and there is not one available.

Regards

Simon

Hey,

- RIOT only supports 32 bit timers?

You should implement the periph/timer interface. Using defines in periph_conf.h, you can set a "max value", e.g., 0xffff for 16 bit timers. Don't bother with hwtimer, that will be phased out soon, and also there's a wrapper for hwtimer on top of periph/timer.

- RIOT uses multiple timers but they all must run at the same speed and be synchronised. So effectively there must be only one timer but multiple channels/compares.

Using the periph/timer interface, there can be multiple timers with multiple channels. The "channels" are supposed to map multiple capture/compare registers og one actual timer. It is perfectly fine to only have one "channel" per timer. Different "timers" can run at different speeds.

In order to harmonize platforms, if possible make one timer, preferably timer 0, run at 1MHz.

*Problems* 1) If I set a hwtimer for longer than the maximum period of the timer it will interrupt too soon. e.g. Timer overflows every 1000s. If I set a hwtimer to delay for 1001s it will interrupt in 1s time.

Seems like a bug. But we are aware that hwtimer + vtimer are, lets say, not optimal, and are working on a new timer subsystem. Check PR #2926 to see where we're headed.

2) vtimers fail if the maximum timer period is less than 4096s (SECONDS_PER_TICK).

Yeah, vtimer has problems with an overflow of the underlying timer...

3) Currently vtimers do not check if they request a hwtimer and there is not one available.

Unfortunately also true...

May I ask which platform you are porting to?

Kaspar

Hi Kaspar,

Hey,

- RIOT only supports 32 bit timers?

You should implement the periph/timer interface. Using defines in periph_conf.h, you can set a "max value", e.g., 0xffff for 16 bit timers. Don't bother with hwtimer, that will be phased out soon, and also there's a wrapper for hwtimer on top of periph/timer.

I have seen the max value but I can't see anything using it.

- RIOT uses multiple timers but they all must run at the same speed and be synchronised. So effectively there must be only one timer but multiple channels/compares.

Using the periph/timer interface, there can be multiple timers with multiple channels. The "channels" are supposed to map multiple capture/compare registers og one actual timer. It is perfectly fine to only have one "channel" per timer. Different "timers" can run at different speeds.

Currently the issue I get with multiple timers is that calls to hwtimer_arch_now do not specify a timer. So you call hwtimer_arch_now and get a value. If you then use this to set a delay there are problems as when you request this delay it could use a different hwtimer. This currently occurs in vtimers.

In order to harmonize platforms, if possible make one timer, preferably timer 0, run at 1MHz.

What if my platform does not have a 1MHz timer? Is there going to be problems?

*Problems* 1) If I set a hwtimer for longer than the maximum period of the timer it will interrupt too soon. e.g. Timer overflows every 1000s. If I set a hwtimer to delay for 1001s it will interrupt in 1s time.

Seems like a bug. But we are aware that hwtimer + vtimer are, lets say, not optimal, and are working on a new timer subsystem. Check PR #2926 to see where we're headed.

Ok I will have a look. When do you think it will ready?

2) vtimers fail if the maximum timer period is less than 4096s (SECONDS_PER_TICK).

Yeah, vtimer has problems with an overflow of the underlying timer...

3) Currently vtimers do not check if they request a hwtimer and there is not one available.

Unfortunately also true...

May I ask which platform you are porting to?

Currently I am porting to the Zynq 7000 which contains a Arm Cortex A9. I know this is not a typical processor for RIOT. This is a development platform for us and eventually we will move to a smaller microprocessor such as a Arm M3.

I am having problems with the timers as the Zynq timers are too fast. I have three options: - one 32-bit timer running at 50MHz-333MHz but only a single channel. - one 64-bit timer running at 50MHz-333MHz but only a single channel. - three 16-bit timers running at 1KHz-100MHz each with three channels.

Currently I have implemented as the periph/timer the three 16-bit timers running at 0.78MHz (closest I can get to 1MHz). This works well using hwtimers for short delays but vtimer does not work at all as the timers overflow too quickly.

Simon

Hey,

Currently the issue I get with multiple timers is that calls to hwtimer_arch_now do not specify a timer. So you call hwtimer_arch_now and get a value. If you then use this to set a delay there are problems as when you request this delay it could use a different hwtimer. This currently occurs in vtimers.

hm, did you implement hwtimer for your architecture? The implementation should use only timers that run at the same speed.

In order to harmonize platforms, if possible make one timer, preferably timer 0, run at 1MHz.

What if my platform does not have a 1MHz timer? Is there going to be problems?

No. Right now, wtimer is just missing support for that.

Check PR #2926 to see where we're headed.

Ok I will have a look. When do you think it will ready?

I'd say, until it is the default timer in master, a couple of weeks. I hope to have it ready as experimental drop-in-replacement before the IETF (next week).

May I ask which platform you are porting to?

Currently I am porting to the Zynq 7000 which contains a Arm Cortex A9.

Very interesting! If possible, please let as see the code. :wink:

Currently I have implemented as the periph/timer the three 16-bit timers running at 0.78MHz (closest I can get to 1MHz). This works well using hwtimers for short delays but vtimer does not work at all as the timers overflow too quickly.

You could try to fake 32bit timers (in software or by combining two timers).

If you only need the timer for your application, take a look at #2926. wtimer has support for 16bit timers and handles overflows a lot better.

Kaspar

Ok maybe I will leave timers alone for a couple of weeks and redo them once the new timers hit master.

I hope to make all the Zynq port code available in a few weeks.

Simon

Hi Simon,

You can also use a 32-bit timer lets say running at 50MHz and use pre-scale of 50 so that you get tick at every 1us.

Thanks and Regards, Rakendra

Ah yes I forgot you could prescale the 32bit private timer!

Simon