Author Topic: Problem with GlobalMonoTimers ?  (Read 10188 times)

Offline m_mikula

  • Newbie
  • *
  • Posts: 14
    • View Profile
Problem with GlobalMonoTimers ?
« on: January 21, 2008, 08:06:58 PM »
Hi,

I have problem with GlobalMonoTimers, maybe i't my mistake... We use some complicated timers usage, so we need about 30 timers at same time and there is some strange...

I write some example:
Code: [Select]
#define E_RDR2_PING_TIMEOUT 21
#define E_RDR2_DO_PING 23
#define E_RDR_3SEC 24

void fnApplication(TTASKTABLE *ptrTaskTable)
{
....
if (!iAppState) {
uTaskerGlobalMonoTimer( OWN_TASK, (DELAY_LIMIT)(5*SEC), E_RDR2_DO_PING);
uTaskerGlobalMonoTimer( OWN_TASK, (DELAY_LIMIT)(1*SEC), E_RDR2_PING_TIMEOUT);
uTaskerGlobalMonoTimer( OWN_TASK, (DELAY_LIMIT)(0.5*SEC), E_RDR_3SEC);
iAppState = 1;
    } // END OF INIT

// check input queue
while ( fnRead( PortIDInternal, ucInputMessage, HEADER_LENGTH )) {
    // switch depending on message source
        switch ( ucInputMessage[ MSG_SOURCE_TASK ] ) {
        case TIMER_EVENT:
        if (E_RDR2_DO_PING == ucInputMessage[ MSG_TIMER_EVENT ]) {
        fnDebugMsg("RDR2 do ping\r\n");
        uTaskerGlobalMonoTimer( OWN_TASK, (DELAY_LIMIT)(5*SEC), E_RDR2_DO_PING);
        uTaskerGlobalMonoTimer( OWN_TASK, (DELAY_LIMIT)(1*SEC), E_RDR2_PING_TIMEOUT);
        uTaskerGlobalMonoTimer( OWN_TASK, (DELAY_LIMIT)(0.5*SEC), E_RDR_3SEC);
        }
        else if (E_RDR2_PING_TIMEOUT == ucInputMessage[ MSG_TIMER_EVENT ]) {
        fnDebugMsg("Ping timeout\r\n");
        LED_2_OFF();
        }
        else if (E_RDR_3SEC == ucInputMessage[ MSG_TIMER_EVENT ]) {
        fnDebugMsg("3SEC timeout\r\n");
      uTaskerGlobalMonoTimer( OWN_TASK, (DELAY_LIMIT)(5*SEC), E_RDR2_DO_PING);
        uTaskerGlobalStopTimer( OWN_TASK, E_RDR2_PING_TIMEOUT );
        }
    break;   
        default:
        // flush any unexpected messages (assuming they arrived from another task)
            fnRead( PortIDInternal, ucInputMessage, ucInputMessage[MSG_CONTENT_LENGTH]);
            break;
        }
    }
}
Right behaviour:
After uTasker boot set up three timers: E_RDR2_DO_PING, E_RDR2_PING_TIMEOUT, E_RDR_3SEC. After 0.5 sec, the first timer E_RDR_3SEC may elapse. So timer E_RDR2_DO_PING shoud be relaunch to 5 sec interval, and timer E_RDR2_PING_TIMEOUT should be stopped.
Real behaviour:
After 0.5 sec, the first timer E_RDR_3SEC elapsed. After approx next 0.5 timer E_RDR2_DO_PING elapsed. I can't find reason why!?

When I replace code:
Code: [Select]
uTaskerGlobalMonoTimer( OWN_TASK, (DELAY_LIMIT)(5*SEC), E_RDR2_DO_PING);
uTaskerGlobalStopTimer( OWN_TASK, E_RDR2_PING_TIMEOUT );
with
Code: [Select]
uTaskerGlobalStopTimer( OWN_TASK, E_RDR2_DO_PING);
uTaskerGlobalStopTimer( OWN_TASK, E_RDR2_PING_TIMEOUT );
uTaskerGlobalMonoTimer( OWN_TASK, (DELAY_LIMIT)(5*SEC), E_RDR2_DO_PING);
everithing works fine....

As I mentioned before we use many timers at same time and this undefined/undocumented behaviour is very bad for us... Please help...

Thanks...
Best Regards...

Offline mark

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3236
    • View Profile
    • uTasker
Re: Problem with GlobalMonoTimers ?
« Reply #1 on: January 21, 2008, 08:47:49 PM »
Hi

This sounds like a bug which we have recently discovered. It is possible that when a timer is stopped, the next timer can fire too quickly. This correction has been prepared ready for subsequent service packs (it is already in the SAM7X SP3 and in the new LPC23XX package).

Please try the following change in GlobalTimer.c.

   03.01.2008 Correct deleted software timer firing early                {3}

Code: [Select]
static void fnSWTimerFired(void)
{
    TIMER_BLOCK dead_timer;                                              // {3}
    unsigned char ucMessage[ HEADER_LENGTH];
    TIMER_BLOCK *ptrTimer;
    TIMER_BLOCK *ptrRef = 0;
    CLOCK_LIMIT FiredTime = (CLOCK_LIMIT)(0-1);
#ifdef USE_TIMER_FUNCTION_EVENT
    unsigned char ucEvents[TIMER_QUANTITY];
    int iEvents = 0;
#endif

    ucMessage[ MSG_DESTINATION_NODE ] = INTERNAL_ROUTE;                  // internal message
    ucMessage[ MSG_SOURCE_NODE ] = INTERNAL_ROUTE;
    ucMessage[ MSG_SOURCE_TASK ] = TIMER_EVENT;                          // a timer event

    while ((ptrTimer = fnGetSWFired(FiredTime)) != 0) {                  // handle multiple timers which may have fired at the same time
        if (NextFire < ptrTimer->TimerDelay) {                           // {3} if the timer fired before expected it is due to a deleted timer whose monostable timer could not be stopped. In this case we must not generate an event.
            dead_timer.TimerDelay = NextFire;                            // set the killed timer time
            ptrRef = &dead_timer;
            break;
        }
#ifdef USE_TIMER_FUNCTION_EVENT
        if (FUNCTION_EVENT == (unsigned char)ptrTimer->OwnerTask) {      // if defined as function event
            ucEvents[iEvents++] = ptrTimer->ucEvent;                     // collect function events
            FiredTime = ptrTimer->TimerDelay;
            ptrTimer->OwnerTask = 0;                                     // clear timer block since event has been sent
            ptrRef = ptrTimer;
            continue;
        }
#endif
...

In the correction marked {3} dead_timer has been added and the new conditional block
if (NextFire < ptrTimer->TimerDelay) {

This cleans up from left-overs from a deleted timer which could cause a problem.

Please tell me if this corrects the problem.

Also ensure that you allocate adequate timer space for the amount that you require to be operating in parallel.
    #define TIMER_QUANTITY 30 // in config.h

Good luck

Regards

Mark

Offline m_mikula

  • Newbie
  • *
  • Posts: 14
    • View Profile
Re: Problem with GlobalMonoTimers ?
« Reply #2 on: January 21, 2008, 11:22:45 PM »
Thanks!!!

It's seems that you are right. Now when I looks to your patch, I can't beleve that i dont see it... However this looks like my problem, now I must add this patch to base source and do some additional tests for timers... Is anywhere list of hnown bugs? Maybe It could help in some cases to know about known bugs between service packs... Before I send this topic I read the SP5 patch list for MCF5223X at:
http://www.utasker.com/forum/index.php?topic=40.0
but there  is nothing about this problem, so if such page doesn't exists do you consider about something like that?

Offline mark

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3236
    • View Profile
    • uTasker
Re: Problem with GlobalMonoTimers ?
« Reply #3 on: January 22, 2008, 12:19:04 AM »
Martin

Since you are using the coldfire, the SP5 patch list is the one to use.

There are in fact 2 'known' bugs (I don't know how many unknown ones...;-)  ) which are not on the list.

The one with the global monostable timers, which was discovered and corrected at the beginning of January, plus one which was identified only yesterday (this one doesn't affect SW operation though, but possibly long term FLASH reliability [Thanks again to Leon for identifying it!]).

A new SP6 should be available soon (although it is proving more difficult to get this ready than expected [time problems...]) and so it was expected that the release would be ready before it was noticed.

I will therefore try to update the SP5 patch list tomorrow so that it is up to date.

Regards

Mark