Author Topic: uTasker Timer  (Read 5696 times)

Offline ctkian

  • Newbie
  • *
  • Posts: 20
    • View Profile
uTasker Timer
« on: April 16, 2014, 02:00:18 PM »
Hi Mark,

I saw the following code in uTasker function - fnStartNewTimer.

1        UTASK_TICK RemainingTime = TimeStamp + NextFire;                 // if our delay is longer than the present delay we calculate delay difference
2        if (RemainingTime >= uTaskerSystemTick) {
3            RemainingTime -= uTaskerSystemTick;
4        }
5        else {
6            RemainingTime = uTaskerSystemTick - RemainingTime;
7        }

Can you explain to me what is the function on line 6.

Thank you very much.

Offline mark

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3234
    • View Profile
    • uTasker
Re: uTasker Timer
« Reply #1 on: April 16, 2014, 02:24:10 PM »
Hi

Please check that you have the latest code for GlobalTimers.c since this looks like an old version (new version discussed below).

Since the global SW timers are based on a single task timer, each time a new timer is started and the task's monostable timer is already in use the new timer is either added to the timer queue (if its timeout will take place after the present timer's) or it replaces the present timer (since it needs to fire earlier). The code is calculating the difference between the two cases as a positive dalta value (either Remaining = (RemainingTime - uTaskerSystemTick) or Remaining = (uTaskerSystemTick - RemainingTime))

This is the present version:

        UTASK_TICK RemainingTime;                                        // {9}
        uDisable_Interrupt();                                            // ensure that the tick can not increment while doing the following
            RemainingTime = uTaskerRemainingTime(OWN_TASK);              // {8} get the time remaining before the timer fires - if this is 0 it means that it has fired and is waiting to be handled
            if (RemainingTime > ptrNewTimer->TimerDelay) {               // the new timer value is shorter that the next firing time
              //fnReduceSWTimers(ptrNewTimer, (unsigned char)(NextFire - (unsigned char)RemainingTime)); {6}
                fnReduceSWTimers(ptrNewTimer, (DELAY_LIMIT)(NextFire - RemainingTime)); // {6}
                uTaskerMonoTimer(OWN_TASK, (DELAY_LIMIT)ptrNewTimer->TimerDelay, E_TIMER_FIRED);
                NextFire = ptrNewTimer->TimerDelay;
            }
            else {                                                       // {6} the next timer needs to fire either at the same time as the next firing time or later
                ptrNewTimer->TimerDelay += (DELAY_LIMIT)(NextFire - RemainingTime); // {10} modify the delta
            }
        uEnable_Interrupt();                                             // leave critical code region


This now uses uTaskerRemainingTime() to obtain the time (in TICKs) before the task's monostable timer will fire and also protects the area from interrupts. This has proven reliable (there was a race-state that could cause a timer to fire too early) since 2010 when the fix was added.

Hopefully the new code is also clearer as to what it is doing.

Regards

Mark


Offline ctkian

  • Newbie
  • *
  • Posts: 20
    • View Profile
Re: uTasker Timer
« Reply #2 on: April 16, 2014, 04:20:59 PM »
Hi Mark,

Appreciated you reply. I am looking into this as I have stumble with a problem that causes incorrect value(rare case) being fed into function fnReduceSWTimer, causing some of the timer overflow and not fire in time.

The new version is more self explainable.

Below the the whole contents of fnStartNewTimer, please advise if the require changes involve is only as per your previous post.

static void fnStartNewTimer(TIMER_BLOCK *ptrNewTimer)
{
#ifdef GLOBAL_HARDWARE_TIMER
    if (ptrNewTimer->OwnerTask & HARDWARE_TIMER) {                       // start a new hardware timer
        fnSetNewHWTimer(ptrNewTimer);                                    // start hardware timer or queue the new timer
        return;
    }
#endif
    if (!fnGetNotTimer(ptrNewTimer)) {                                   // start new mono-stable timer
        uTaskerMonoTimer( OWN_TASK, (DELAY_LIMIT)ptrNewTimer->TimerDelay, E_TIMER_FIRED ); // if no other timer active, simply start ours
        TimeStamp = uTaskerSystemTick;
        NextFire = ptrNewTimer->TimerDelay;
    }
    else {
        UTASK_TICK RemainingTime = TimeStamp + NextFire;                 // if our delay is longer than the present delay we calculate delay difference
        if (RemainingTime >= uTaskerSystemTick) {
            RemainingTime -= uTaskerSystemTick;
        }
        else {
            RemainingTime = uTaskerSystemTick - RemainingTime;
        }

        if (RemainingTime > ptrNewTimer->TimerDelay) {
            fnReduceSWTimers(ptrNewTimer, (unsigned char)(NextFire - (unsigned char)RemainingTime));
            uTaskerMonoTimer( OWN_TASK, (DELAY_LIMIT)ptrNewTimer->TimerDelay, E_TIMER_FIRED );
            TimeStamp = uTaskerSystemTick;
            NextFire = ptrNewTimer->TimerDelay;
        }
    }
}

Thank you very much.
« Last Edit: April 16, 2014, 04:25:44 PM by ctkian »

Offline mark

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3234
    • View Profile
    • uTasker
Re: uTasker Timer
« Reply #3 on: April 16, 2014, 05:09:04 PM »
Hi

Attached is the latest version (24.06.2011) - it should be possible to use this one in place for the orignal but you can also download the latest release to check for defines etc. in case of problems.

Regards

Mark