Re: TinyOS timer issue when building with mspgcc4.7 with large memory model

Peter Bigot <[email protected]>
Newsgroups gmane.comp.hardware.texas-instruments.msp430.gcc.user
Message-ID <CAPOJ94PkTf8dhPNJn-5PcwqbdBX74W3+hZreKDFdGtEoBdZqbA@mail.gmail.com>
For TinyOS specific issues it'd be best to start by going through TinyOS
support.  If  you can reduce the problem to a standalone C program and
report it at the SF mspgcc tracker, it'll be looked at during the normal
course of mspgcc maintenance.

Peter


On Fri, Apr 19, 2013 at 7:44 AM, Wim De Clercq <[email protected]> wrote:

> 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
> [email protected]
> https://lists.sourceforge.net/lists/listinfo/mspgcc-users
>
>

------------------------------------------------------------------------------
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
[email protected]
https://lists.sourceforge.net/lists/listinfo/mspgcc-users
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.