Hello,

I am building a TinyOS application using mspgcc 4.7.0 (20120911), with large 
memory model / 20bit support.
I have experienced severe timer issues (wrong timers being set, causing crashes 
in the end),  which I could trace back to TinyOS library file 
VirtualizeTimerC.nc. It looks to me like a mspgcc compiler bug.
I have no issues with my application when I build & run it with small memory 
model options, with the same tool chain.
Here is the original piece of code in VirtualizeTimerC.nc that causes the 
failure:

  task void updateFromTimer()
  {
    /* This code supports a maximum dt of MAXINT. If min_remaining and
       remaining were switched to uint32_t, and the logic changed a
       little, dt's up to 2^32-1 should work (but at a slightly higher
       runtime cost). */
    uint32_t now = call TimerFrom.getNow();
    int32_t min_remaining = (1UL << 31) - 1; /* max int32_t */
    bool min_remaining_isset = FALSE;
    uint16_t num;

    call TimerFrom.stop();

    for (num=0; num<NUM_TIMERS; num++)
      {
               Timer_t* timer = &m_timers[num];

               if (timer->isrunning)
                 {
                   uint32_t elapsed = now - timer->t0;
                   int32_t remaining = timer->dt - elapsed;

                   if (remaining < min_remaining)
                     {
                              min_remaining = remaining;
                              min_remaining_isset = TRUE;
                     }
                 }
      }

    if (min_remaining_isset)
      {
               if (min_remaining <= 0)
                 fireTimers(now);
               else
                 call TimerFrom.startOneShotAt(now, min_remaining);
      }
  }

The failure I saw is that the variable "now" got corrupted inside this function.
The produced assembler code of this function is as follows:

.L893:
               calla      #TransformCounterC__0__Counter__get
               mov       r14, r8
               mov       r15, r9
               and        #-17, &898
               mov       #13, r14
               mov.b   #0, r6
               mov       #llo(2147483647), r10
               mov       #lhi(2147483647), r11
               mov       #0, r15
.L959:
               mov       r15, r7
               rlam       #1, r7
               mov       r15, r13
               rlam       #3, r13
               add        r13, r7
               adda      #VirtualizeTimerC__0__m_timers, r7
               bit.b       #2, 8(r7)
               jeq         .L957
               mov       r8, r12
               mov       r9, r13
               sub         @r7, r12
               subc       2(r7), r13
               mov       4+2(r7), r8
               mov       4(r7), r7
               sub         r12, r7
               subc       r13, r8
               mov       r7, r12
               mov       r8, r13
               cmp       r11, r13
               jl             .L1173
               jne         .L957
               cmp       r10, r7
               jhs          .L957
.L1173:
               mov       r12, r10
               mov       r13, r11
               mov.b   #1, r6
.L957:
               add        #1, r15
               add        #-1, r14
               jne         .L959
               cmp.b    #0, r6
               jne         1f
               bra         #.L884
1:

               cmp       #0, r11
               jl             .L1208
               cmp       #1, r11
               jge         .L960
               cmp       #1, r10
               jhs          .L960
.L1208:
               mov       r8, r14
               mov       r9, r15
               calla      #VirtualizeTimerC__0__fireTimers
               bra         #.L884
.L960:
...more code...

At label L893, the value of variable "now" is stored in registers r8 and r9.
Later on, "now" is used as a parameter to call function fireTimers (label 
L1208), by moving r8 and r9 to r14 and r15 respectively.
However, from the code in between, you can see that register r8 is overwritten 
(and not restored afterwards), while "now" is nowhere changed in the C-code.

I managed to avoid the problem by changing statement:

    int32_t min_remaining = (1UL << 31) - 1; /* max int32_t */

to:

    volatile int32_t min_remaining = (1UL << 31) - 1; /* max int32_t */

so, just adding the "volatile" keyword.
Doing so, resulted in following assembler code:

.L893:
               calla      #TransformCounterC__0__Counter__get
               mov       r14, r10
               mov       r15, r11
               mov       #llo(2147483647), -102(r4)
               mov       #lhi(2147483647), -102+2(r4)
               and        #-17, &898
               mov       #13, r8
               mov.b   #0, r7
               mov       #0, r9
.L959:
               mov       r9, r14
               rlam       #1, r14
               mov       r9, r15
               rlam       #3, r15
               add        r14, r15
               adda      #VirtualizeTimerC__0__m_timers, r15
               bit.b       #2, 8(r15)
               jeq         .L957
               mov       r10, r12
               mov       r11, r13
               sub         @r15, r12
               subc       2(r15), r13
               mov       4(r15), r5
               mov       4+2(r15), r6
               sub         r12, r5
               subc       r13, r6
               mov       r5, r12
               mov       r6, r13
               mov       -102(r4), r14
               mov       -102+2(r4), r15
               cmp       r15, r13
               jl             .L1207
               cmp       r13, r15
               jl             .L957
               cmp       r14, r5
               jhs          .L957
.L1207:
               mov       r12, -102(r4)
               mov       r13, -102+2(r4)
               mov.b   #1, r7
.L957:
               add        #1, r9
               add        #-1, r8
               jne         .L959
               cmp.b    #0, r7
               jne         1f
               bra         #.L884
1:

               mov       -102(r4), r14
               mov       -102+2(r4), r15
               cmp       #0, r15
               jl             .L1208
               cmp       #1, r15
               jge         .L960
               cmp       #1, r14
               jhs          .L960
.L1208:
               mov       r10, r14
               mov       r11, r15
               calla      #VirtualizeTimerC__0__fireTimers
               bra         #.L884
.L960:
...more code...

This time, at L893, the value of variable "now" is stored in registers r10 and 
r11, and variable "min_remaining" is stored on the stack (previously also in 
registers).
r10 and r11 register contents are not modified this time, up to the point "now" 
is passed to function fireTimers.

With this modification my TinyOS application runs fine.
Needless to say I am worried... am I just lucky that compilation seems to be 
correct by adding this volatile keyword?
Is this a known issue? I cannot imagine that no one in the TinyOS community has 
faced this timer issue, even though it only occurs when building for large 
memory model.

Thanks for commenting.
Wim

------------------------------------------------------------------------------
Precog is a next-generation analytics platform capable of advanced
analytics on semi-structured data. The platform includes APIs for building
apps and a phenomenal toolset for data science. Developers can use
our toolset for easy data analysis & visualization. Get a free account!
http://www2.precog.com/precogplatform/slashdotnewsletter
_______________________________________________
Mspgcc-users mailing list
Mspgcc-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/mspgcc-users

Reply via email to