> 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.
The watchdogs, by design, ask for a single tick delay. Here it is: https://github.com/apache/nuttx/blob/master/sched/wdog/wd_start.c#L406 When the wdog->lag is 0, then the delay is set to 1 tick. On Wed, Jun 7, 2023 at 11:25 PM Fotis Panagiotopoulos <f.j.pa...@gmail.com> wrote: > > 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. >> >> >>