> Yes, it is a free-running timer and represents the current time. It is
> read whenever anything asks for the current time.  It is read frequently
> during the interval timer interrupt processing to avoid/minimize
> situations like you describe.
> > Should the timer be stopped?
>
> You can't stop it or it no longer represents the current time.

Understood. Also just got verified experimentally.
The timer must run, by design.

> It is possible if you make an assumption like "the maximum delay cannot
> be larger than half the range of clock".  Then if the implied delay is
> larger than half the range of the clock, then you can assume that we
> tried to schedule something in the past.
>
> A better check would be to calculate the number of ticks until the
> match.  This should be the same as the delay +/-  a few ticks.

I am afraid that this check will not help.
For this specific problem, you cannot perform any checks.
Because between the time the check is performed, and the match register is
loaded,
the timer may have advanced.

Here is the failure scenario:
1. Assume that the timer counter is currently at 100 ticks.
2. The scheduler requests a timeout in 1 tick.
3. The counter is read (100).
4. The match value is calculated (100 + 1 = 101).
5. It just so happens that the timer advanced to 101.
6. The match register is loaded with the value 101. Now it is too late.

You will have to wait a full timer roll-over for the next match.

No matter where you put the check, the timer will always have the chance to
"slip" to the next value
before you had the chance to set the match register (and re-enable the
interrupt).

> This is, ultimately, the problem.  You can't wait for one tick. There is
> something wrong with the delay that is asking for the single tick delay.

This is surely happening though!
I added the following within up_timer_start():

ASSERT(period > 1);

The assertion fails immediately!

I checked at least one occurence, and this is the fault:

sched_unlock() -> nxsched_reassess_timer() -> nxsched_cancel_timer()
-> nxsched_timer_process()
-> wd_timer()

There, there is the watchdog lp_work_timer_expiry that requests a delay of
1 tick.

But I am pretty sure there will be other cases of 1 tick wait, though...




On Wed, Jun 7, 2023 at 10:58 PM Gregory Nutt <spudan...@gmail.com> wrote:

>
> > Later on, up_timer_start() will try to schedule the timer expiration 1
> tick
> > in the future.
>
> This is, ultimately, the problem.  You can't wait for one tick. There is
> something wrong with the delay that is asking for the single tick delay.
>
> If the single tick delay is valid for some reason, then there is no
> clean work-around:  Increase the delay? Ignore the delay?
>
> I don't think this should happen.  I think it is a bug of some kind.
> For example, if interrupts are disabled for a long time so that interval
> timer processing is delayed.  Then the delay value can be small or even
> negative, I suppose.
>
> > At least in STM32 there is no protection about scheduling things to the
> > past.
> > As far as I can tell, it would be impossible with the current
> > implementation.
>
> It is possible if you make an assumption like "the maximum delay cannot
> be larger than half the range of clock".  Then if the implied delay is
> larger than half the range of the clock, then you can assume that we
> tried to schedule something in the past.
>
> A better check would be to calculate the number of ticks until the
> match.  This should be the same as the delay +/-  a few ticks.
>
> > During all these calculations, and setting of the match register, the
> timer
> > is left running.
> > Thus it can run beyond our intended target while we set it.
> Yes, it is a free-running timer and represents the current time. It is
> read whenever anything asks for the current time.  It is read frequently
> during the interval timer interrupt processing to avoid/minimize
> situations like you describe.
> > Should the timer be stopped?
>
> You can't stop it or it no longer represents the current time.
>
>
>

Reply via email to