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