RTEMS - rtems_clock_get_uptime() fails during timer tick
Rolf Schroedter
rolf.schroedter at dlr.de
Thu Feb 24 09:53:51 UTC 2011
Hello Sebastion,
your analysis sounds reasonable.
It sounds similar to a problem I once had when reading two cascaded
hardware timer registers:
- Two 32-bit Leon3 timer registers can be cascaded: When the LO register
overruns to 0, the HI register is incremented by hardware
Polling these registers to a single 64-bit time value creates the
problem, that the LO timer could overrun between the two register read
instructions.
The solution was to read both registers twice HI_1, LO_1, HI_2, LO_2 and
check them to extract the correct time:
if ( HI_1 == HI_2 )
return (HI_1 << 32) + LO_1;
else
return (HI_2 << 32) + LO_2;
Rolf.
Sebastian Huber wrote, On 24.02.2011 09:47:
> Hello Rolf,
>
> this looks like a general problem with the
> _Watchdog_Nanoseconds_since_tick_handler() mechanic. Lets suppose we have a
> hardware timer with an automatic reload capability. It counts from 0 to N,
> then goes back to 0, and so on. It triggers an interrupt during the N to 0
> transition. The _Watchdog_Nanoseconds_since_tick_handler() returns the current
> hardware timer ticks mapped to nanoseconds. Lets have a look at this function.
>
> void _TOD_Get_uptime(
> Timestamp_Control *uptime
> )
> {
> ISR_Level level;
> Timestamp_Control offset;
> Timestamp_Control up;
> long nanoseconds;
>
> /* assume time checked for NULL by caller */
>
> /* _TOD_Uptime is in native timestamp format */
> _ISR_Disable( level );
> up = _TOD_Uptime;
> nanoseconds = (*_Watchdog_Nanoseconds_since_tick_handler)();
> _ISR_Enable( level );
>
> _Timestamp_Set( &offset, 0, nanoseconds );
> _Timestamp_Add_to( &up, &offset );
> *uptime = up;
> }
>
> Now consider the following sequence. We are right before the hardware timer N
> to 0 transition. We disable the interrupts in the above function. The
> hardware timer goes to 0. Since interrupts are disabled, the _TOD_Uptime is
> not up to date. We call _Watchdog_Nanoseconds_since_tick_handler() and get the
> time since the last hardware (!) timer tick. Now we use the out of date uptime
> with the new nanoseconds.
>
> A solution may be to not disable interrupts in _TOD_Get_uptime() (and all
> calling contexts) and use something like this:
>
> do {
> up0
> nanoseconds
> up1
> } while (up0 != up1)
>
> Have a nice day!
>
--
------------------------------------
Rolf Schroedter
German Aerospace Center
Institute of Planetary Research
D-12489 Berlin, Rutherfordstrasse 2
Tel/Fax: (+49) (30) 67055-416/384
Email: Rolf.Schroedter at dlr.de
More information about the users
mailing list