Bug with clock nanoseconds
Joel Sherrill
joel.sherrill at OARcorp.com
Mon Mar 30 16:49:10 UTC 2009
Manuel Coutinho wrote:
>
> Hi
>
>
>
> We have discovered a bug of RTEMS relating to the clock. Even though
> we only tested it for the ERC32 board (for now), we believe it is
> common throughout all the targets.
>
No you have discovered a bug in the ERC32's get nanoseconds since last
tick handler.
Apparently it doesn't recognize that is has been longer than a tick
since the last clock
tick. It should determine that is has overflowed and return 1 clock
tick + partial clock
tick.
It is returning the wrong answer.
>
>
> The test consists in checking if the time given by rtems_clock_get is
> always increasing. The code is as follows:
>
>
>
> .....
....
>
> As you can see, the problem is raised when a clock tick occurs: the
> time read in “new” is older than “old”. This cannot happen since “new”
> is updated AFTER “old”! This problem occurs if a clock interrupt is
> triggered after the number of clock ticks have been read but BEFORE
> the nanosecond field has been read. The resulting number of clock
> ticks is “small” (should be plus one).
>
>
>
> We can use the interrupt pending CPU registers info to determine if,
> while we are reading the number of clock ticks that occurred and the
> nanoseconds, a clock interrupt could be pending.
>
>
>
> We do not have enough knowledge to say that this solution can be used
> for all boards (determining if an interrupt is pending). In the SPARC
> architecture, at least, it is possible. If it is possible in all
> architectures, then a solution to RTEMS would be to change the code of
> the _TOD_Get_uptime function to:
>
>
>
>
>
> void _TOD_Get_uptime(struct timespec *uptime) {
>
> ISR_Level level;
>
> struct timespec offset;
>
> volatile uint32_t pending;
>
>
>
> /* assume uptime checked by caller */
>
>
>
> offset.tv_sec = 0;
>
> offset.tv_nsec = 0;
>
>
>
> _ISR_Disable(level);
>
> *uptime = _TOD_Uptime;
>
> if (_Watchdog_Nanoseconds_since_tick_handler)
>
> offset.tv_nsec = (*_Watchdog_Nanoseconds_since_tick_handler)();
>
>
>
> /* code added: */
>
> pending = isClockInterruptPending();
>
>
>
> _ISR_Enable(level);
>
>
>
> /* code added */
>
> /* if an interrupt occurred while interrupts were disabled and the
> nanoseconds is too little */
>
> /* means that a clock interrupt occurred BEFORE the nanoseconds
> were read */
>
> if (pending && offset.tv_nsec <
> rtems_configuration_get_microseconds_per_tick() / 2) {
>
> struct timespec clockTick = {0,
> rtems_configuration_get_microseconds_per_tick()*1000};
>
> _Timespec_Add_to(&offset, &clockTick); /* so add one clock
> tick to the offset */
>
> }
>
>
>
> /* else, the clock tick occurred AFTER the nanoseconds were read,
> so no problem */
>
>
>
> _Timespec_Add_to(uptime, &offset);
>
> }
>
>
>
>
>
> At least, with these modifications, the test passes :)!
>
>
>
> Kind regards
>
> Manuel Coutinho
>
--
Joel Sherrill, Ph.D. Director of Research & Development
joel.sherrill at OARcorp.com On-Line Applications Research
Ask me about RTEMS: a free RTOS Huntsville AL 35805
Support Available (256) 722-9985
More information about the users
mailing list