Bug with clock nanoseconds

Manuel Coutinho manuel.coutinho at edisoft.pt
Tue Mar 31 11:30:20 UTC 2009


Here are the functions for ERC32 and Leon2 - ERC32 and Leon2 already have
the is_interrupt_pending functions :D :



ERC32:

uint32_t bsp_clock_nanoseconds_since_last_tick(void) {
    uint32_t clicks;

    clicks = ERC32_MEC.Real_Time_Clock_Counter;

    /* Down counter */
    clicks = (uint32_t) (BSP_Configuration.microseconds_per_tick - clicks) *
1000;

    /* 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 (ERC32_Is_interrupt_pending(ERC32_INTERRUPT_REAL_TIME_CLOCK) &&
clicks < BSP_Configuration.microseconds_per_tick / 2)
        clicks += BSP_Configuration.microseconds_per_tick * 1000;

    return clicks;
}




LEON2:

uint32_t bsp_clock_nanoseconds_since_last_tick(void) {
    uint32_t clicks;

    clicks = LEON_REG.Timer_Counter_1;

    /* Down counter */
    clicks = (uint32_t) (BSP_Configuration.microseconds_per_tick - clicks) *
1000;

    /* 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 (LEON_Is_interrupt_pending(LEON_INTERRUPT_TIMER1) && clicks <
BSP_Configuration.microseconds_per_tick / 2)
        clicks += BSP_Configuration.microseconds_per_tick * 1000;

    return clicks;
}


I've tested and the result seams ok :)
Kind regards
Manuel Coutinho



> -----Original Message-----
> From: rtems-users-bounces at rtems.org [mailto:rtems-users-bounces at rtems.org]
> On Behalf Of Manuel Coutinho
> Sent: Tuesday, March 31, 2009 11:59 AM
> To: 'Joel Sherrill'; 'Aitor Viana'
> Cc: rtems-users at rtems.com
> Subject: RE: Bug with clock nanoseconds
> 
> Yes, I agree :)
> 
> > -----Original Message-----
> > From: Joel Sherrill [mailto:joel.sherrill at oarcorp.com]
> > Sent: Tuesday, March 31, 2009 11:40 AM
> > To: Aitor Viana
> > Cc: Manuel Coutinho; rtems-users at rtems.com
> > Subject: Re: Bug with clock nanoseconds
> >
> > Aitor Viana wrote:
> > > Yep,
> > >
> > > crystal clear. BTW, isClockInterruptPending() is not present in the
> > > RTEMS distribution, it should be implemented for all BSPs I guess.
> > >
> > I repeat.  It is the responsibility of the clock tick device driver
> > to reliably and correctly report the number of nanoseconds since
> > the last time rtems_clock_tick was called.  If that was slightly
> > greater than 1 tick ago, then it needs to return a number of nanoseconds
> > slightly greater than 1 tick.
> >
> > Any code modifications outside the device driver are not correct and
> > will not address all cases of using this extension.
> >
> > This might be a common issue with get nanoseconds handlers but it will
> > NOT be addressed in this way.  Check the is pending bit or that the
> > counter overflowed in the get nanoseconds handler and return the correct
> > number.
> >
> > --joel
> > > Best regards,
> > >
> > > Aitor
> > >
> > >
> > > On Tue, Mar 31, 2009 at 10:30 AM, Manuel Coutinho
> > > <manuel.coutinho at edisoft.pt <mailto:manuel.coutinho at edisoft.pt>>
> wrote:
> > >
> > >     Hi. Thanks for testing in leon2.was just about to do that :)!
> > >
> > >
> > >
> > >     Basically, the test aims to see that the clock is always
> > >     increasing. But the result is that, sometimes, it decreases.
> > >
> > >     This happens when a clock tick occurs.
> > >
> > >
> > >
> > >     The RTEMS algorithm to read the time consists of:
> > >
> > >
> > >
> > >     1. Disabling interrupts
> > >
> > >     2. Read how many clock interrupts occurred
> > >
> > >     3. Read nanoseconds elapsed
> > >
> > >     4. Enable interrupts
> > >
> > >
> > >
> > >     The problem occurs if an interrupt occurs between the 1 and 3
> > >     steps: -> the number of clock ticks is NOT updated (because
> > >     interrupts are disabled) and the nanoseconds field (which is read
> > >     directly from the CPU registers) is restarted.
> > >
> > >
> > >
> > >     For example, the clock is 2 clock ticks and 99999 us (a clock tick
> > >     is just about to occur). Suppose you disable interrupts, read 2
> > >     clock ticks, then the CPU clock counter overflows and the
> > >     nanoseconds is reset to 0 and you read 0 nanoseconds.
> > >
> > >     You end up reading 2 clock ticks and 0 nanoseconds when in fact
> > >     you should read 3 clock ticks and 0 nanoseconds - you cannot stop
> > >     the clock counter (nor do you wish to!).
> > >
> > >
> > >
> > >     Hope this explains the problem a little bit better :)
> > >
> > >
> > >
> > >     By the way, by glancing at the code of the remaining BSPs,
> > >     specifically at the Clock_driver_nanoseconds_since_last_tick
> > >     macro, I don't believe this is a problem just with SPARC. I don't
> > >     see this problem address in any board. But, of course, I might be
> > >     wrong since it was just a very brief look.
> > >
> > >
> > >
> > >     Kind regards
> > >
> > >     Manuel Coutinho
> > >
> > >
> > >
> > >     ------------------------------------------------------------------
> --
> > ----
> > >
> > >     *From:* aitorvs at googlemail.com <mailto:aitorvs at googlemail.com>
> > >     [mailto:aitorvs at googlemail.com <mailto:aitorvs at googlemail.com>]
> > >     *On Behalf Of *Aitor Viana
> > >     *Sent:* Tuesday, March 31, 2009 8:31 AM
> > >     *To:* Joel Sherrill
> > >     *Cc:* Manuel Coutinho; rtems-users at rtems.com
> > >     <mailto:rtems-users at rtems.com>
> > >     *Subject:* Re: Bug with clock nanoseconds
> > >
> > >
> > >
> > >     Just tried in tsim-leon and happens the same.
> > >
> > >
> > >
> > >     I didn't completely understand what's the problem Manuel could you
> > >     explain to me again? is early in the morning :D
> > >
> > >
> > >
> > >     Best regards,
> > >
> > >
> > >
> > >     Aitor
> > >
> > >
> > >
> > >     On Mon, Mar 30, 2009 at 6:49 PM, Joel Sherrill
> > >     <joel.sherrill at oarcorp.com <mailto:joel.sherrill at oarcorp.com>>
> > wrote:
> > >
> > >     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
> > >
> > >
> > >     _______________________________________________
> > >     rtems-users mailing list
> > >     rtems-users at rtems.com <mailto:rtems-users at rtems.com>
> > >     http://rtems.rtems.org/mailman/listinfo/rtems-users
> > >
> > >
> > >
> > >
> 
> 
> _______________________________________________
> rtems-users mailing list
> rtems-users at rtems.com
> http://rtems.rtems.org/mailman/listinfo/rtems-users




More information about the users mailing list