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