Hi everyone,

We recently compiled and built a new AVR toolchain for use with the
motes, and encountered a small but nasty bug in all the existing TOS
releases.

TOS 4.3 defines a signal using code such as

RFM.c:SIGNAL(_output_compare1a_){

Or its NEST-release counterpart

RFM.c:TOS_SIGNAL_HANDLER(_output_compare1a_, ()){

Unfortunately this appears to be a bug.  It seems that the intended
API that is exported by the avr-libc is that you use the capitalized
symbolic signal name, e.g.

SIGNAL(SIG_OUTPUT_COMPARE1A)
or
TOS_SIGNAL_HANDLER(SIG_OUTPUT_COMPARE1A, ()){

With all previous releases of the avr-libc package, it didn't matter;
they all contained lines in include/sig-avr.h that looked something
like this:

#define SIG_OUTPUT_COMPARE1A _output_compare1a_

So, in the good old days, it didn't matter if you used the symbolic
name (SIG_OUTPUT_COMPARE1A) or the underlying, weakly-aliased function
name (_output_compare1a_).  Since they were defined equivalently,
either one would work.

On Nov 26, a new version of the avr-libc package was released.  This
version of the package reorganized the definitions of signals to make
it clearer which (logical) signals were in the different entries of
the interrupt vector table.  So, the old #defines disappeared,
replaced by new (per-platform) #defines of this form:

./avr-libc-20011126/include/io2313.h:#define SIG_OUTPUT_COMPARE1A _vector_4
./avr-libc-20011126/include/io4434.h:#define SIG_OUTPUT_COMPARE1A _vector_6

.... and so forth.  While the symbolic signal names have remained the
same (SIG_OUTPUT_COMPARE1A), the underlying functions have changed to a
more generic name that simply represents its position in the interrupt
vector table.

The nasty part about this bug is that it is not detected by the
toolchain.  Code compiled with the new avr-libc compiles and links
without complaint - but then inexplicably fails to work correctly.
This is because the installation of signal handlers works by
overriding a weakly aliased symbol.  The new version of avr-libc
changes the name of that symbol -- so using SIGNAL(_output_compare1a_)
will silently define a brand new function called _output_compare1a_,
without touching the new weakly aliased _vector_X function that now
represents the interrupt vector.  The result, as Vlad discovered, was
that the interrupt handler was being compiled into the image, but the
interrupt vector table was not being modified to point to the handler.

The fix, for TOS 4.3 and the NEST release, is to change all references
to functions such as _output_compare1a_ to their symbolic counterparts
such as SIG_OUTPUT_COMPARE1A.  Otherwise, code breaks in a somewhat
subtle and hard to track down way when you upgrade to the
avr-libc-2001/11/26 release.

Thanks very much to Vlad for helping me work up this bug!

Best,
Jer

Reply via email to