Re: bug with timer0 interrupt?

Jonathan Geisler <[email protected]>
Newsgroups gmane.comp.hardware.avr.gcc
Message-ID <[email protected]>
On Fri, Feb 15, 2013 at 01:16:27AM +0100, Georg-Johann Lay wrote:
> Jonathan Geisler schrieb:
> > I'm encountering a strange error with avr-gcc 4.6.3 and 4.7.2 using
> > the timer interrupt.  The code I'm using is attached.  As you can see,
> > I was trying to tie in to the Arduino environment (with Eclipse) so
> > that I could help my students wean off that set of functions to being
> > able to use the hardware directly.
> > 
> > When I set up the library, I encountered a strange error and was able
> > to trace it back to this simple program that sets up the timer with a
> > prescalar of 1024 and then increments an unsigned long counter when
> > that timer overflows.  When the counter reaches a specific value, I
> > toggle the built-in LED on the Arduino board connected to PORTB.
> > 
> > The strange behavior is that if I initialize the counter to 0, the
> > code doesn't work--appearing to hang.  If I initialize the counter to
> > 1, everything works perfectly.  I have verified that if I make a
> > similar change to the Arduino libraries that the original code begins
> > to work properly.
> > 
> > I'm not sure what the exact error is since I can use the Arduino
> > environment on my machine without a problem, but when I try to compile
> > it through Eclipse it gives me this error.  I'll include the build log
> > as an attachment in case particular compiler/linker flags are triggering
> > the error.
> 
> When you change count in the ISR and read it in main, the read must be 
> atomic.  Otherwise, you may see glitches and phantom values.
> 
> It atomic access does not help, you can compare the code generated with 
> your Eclipse setup and with your Arduino setup.

The atomic accesses didn't help.  I didn't include that originally
because the Arduino doesn't include them.

For my C code, they appear to be identical.  I didn't compare the
extra code added by the linker.

> You cal also check the generated assembly whether or not it is as you 
> expect.  If so, your problem is somewhere else.

The asm code for my C code appears to be correct.  That is what is so
perplexing to me.  Note that the test code is a distillation of what
the Arduino environment does and it quite succinct, but displays the
error quite reliably.

> You could also supply a test case that can be compiled and reproduced.
> 
> To get a test case, add -v -save-temps to the compiler options and 
> recompile.  Then post the console output of the compiler and the .ii file.

Here is the console output.  I'm attaching the .ii file and the .cpp
file used for the compilation.

    [227] jgeisler:~/classes/enp341 % avr-g++ -Wall -Os -ffunction-sections -fdata-sections -fno-exceptions -mmcu=atmega328p -DF_CPU=16000000UL -MMD -MP -MF"main.d" -MT"main.d" -c -o test.o test.cpp -v -save-temps
    Using built-in specs.
    COLLECT_GCC=/usr/x86_64-pc-linux-gnu/avr/gcc-bin/4.7.2/avr-g++
    Target: avr
    Configured with: /var/tmp/portage/cross-avr/gcc-4.7.2/work/gcc-4.7.2/configure --prefix=/usr --bindir=/usr/x86_64-pc-linux-gnu/avr/gcc-bin/4.7.2 --includedir=/usr/lib/gcc/avr/4.7.2/include --datadir=/usr/share/gcc-data/avr/4.7.2 --mandir=/usr/share/gcc-data/avr/4.7.2/man --infodir=/usr/share/gcc-data/avr/4.7.2/info --with-gxx-include-dir=/usr/lib/gcc/avr/4.7.2/include/g++-v4 --host=x86_64-pc-linux-gnu --target=avr --build=x86_64-pc-linux-gnu --disable-altivec --disable-fixed-point --without-ppl --without-cloog --enable-lto --enable-nls --without-included-gettext --with-system-zlib --enable-obsolete --disable-werror --enable-secureplt --disable-multilib --disable-libmudflap --disable-libssp --disable-libgomp --with-python-dir=/share/gcc-data/avr/4.7.2/python --enable-poison-system-directories --enable-checking=release --disable-libgcj --disable-libquadmath --enable-languages=c,c++ --enable-shared --disable-threads --disable-bootstrap --with-bugurl=http://bugs.gentoo.org/ --with-pkgversion='Gentoo 4.7.2 p1.0, pie-0.5.3'
    Thread model: single
    gcc version 4.7.2 (Gentoo 4.7.2 p1.0, pie-0.5.3) 
    COLLECT_GCC_OPTIONS='-Wall' '-Os' '-ffunction-sections' '-fdata-sections' '-fno-exceptions' '-mmcu=atmega328p' '-D' 'F_CPU=16000000UL' '-MMD' '-MP' '-MF' 'main.d' '-MT' 'main.d' '-c' '-o' 'test.o' '-v' '-save-temps'
     /usr/libexec/gcc/avr/4.7.2/cc1plus -E -quiet -v -MMD test.d -MF main.d -MP -MT main.d -D F_CPU=16000000UL test.cpp -mmcu=atmega328p -Wall -ffunction-sections -fdata-sections -fno-exceptions -Os -fpch-preprocess -fno-rtti -fno-enforce-eh-specs -fno-exceptions -o test.ii
    ignoring nonexistent directory "/usr/lib/gcc/avr/4.7.2/include/g++-v4"
    ignoring nonexistent directory "/usr/lib/gcc/avr/4.7.2/include/g++-v4/avr"
    ignoring nonexistent directory "/usr/lib/gcc/avr/4.7.2/include/g++-v4/backward"
    ignoring nonexistent directory "/usr/lib/gcc/avr/4.7.2/../../../../avr/sys-include"
    #include "..." search starts here:
    #include <...> search starts here:
     /usr/lib/gcc/avr/4.7.2/include
     /usr/lib/gcc/avr/4.7.2/include-fixed
     /usr/lib/gcc/avr/4.7.2/../../../../avr/include
    End of search list.
    COLLECT_GCC_OPTIONS='-Wall' '-Os' '-ffunction-sections' '-fdata-sections' '-fno-exceptions' '-mmcu=atmega328p' '-D' 'F_CPU=16000000UL' '-MMD' '-MP' '-MF' 'main.d' '-MT' 'main.d' '-c' '-o' 'test.o' '-v' '-save-temps'
     /usr/libexec/gcc/avr/4.7.2/cc1plus -fpreprocessed test.ii -quiet -dumpbase test.cpp -mmcu=atmega328p -auxbase-strip test.o -Os -Wall -version -ffunction-sections -fdata-sections -fno-exceptions -fno-rtti -fno-enforce-eh-specs -fno-exceptions -o test.s
    GNU C++ (Gentoo 4.7.2 p1.0, pie-0.5.3) version 4.7.2 (avr)
            compiled by GNU C version 4.5.4, GMP version 5.0.2, MPFR version 3.0.1-p4, MPC version 0.8.2
    warning: MPFR header version 3.0.1-p4 differs from library version 3.1.1.
    GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
    GNU C++ (Gentoo 4.7.2 p1.0, pie-0.5.3) version 4.7.2 (avr)
            compiled by GNU C version 4.5.4, GMP version 5.0.2, MPFR version 3.0.1-p4, MPC version 0.8.2
    warning: MPFR header version 3.0.1-p4 differs from library version 3.1.1.
    GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
    Compiler executable checksum: 5e7b521416cf40df37e35c64e8937dd8
    COLLECT_GCC_OPTIONS='-Wall' '-Os' '-ffunction-sections' '-fdata-sections' '-fno-exceptions' '-mmcu=atmega328p' '-D' 'F_CPU=16000000UL' '-MMD' '-MP' '-MF' 'main.d' '-MT' 'main.d' '-c' '-o' 'test.o' '-v' '-save-temps'
     /usr/libexec/gcc/avr/as -mmcu=atmega328p -mno-skip-bug -o test.o test.s
    COMPILER_PATH=/usr/libexec/gcc/avr/4.7.2/:/usr/libexec/gcc/avr/4.7.2/:/usr/libexec/gcc/avr/:/usr/lib/gcc/avr/4.7.2/:/usr/lib/gcc/avr/
    LIBRARY_PATH=/usr/lib/gcc/avr/4.7.2/:/usr/lib/gcc/avr/4.7.2/../../../../avr/lib/
    COLLECT_GCC_OPTIONS='-Wall' '-Os' '-ffunction-sections' '-fdata-sections' '-fno-exceptions' '-mmcu=atmega328p' '-D' 'F_CPU=16000000UL' '-MMD' '-MP' '-MF' 'main.d' '-MT' 'main.d' '-c' '-o' 'test.o' '-v' '-save-temps'
    [228] jgeisler:~/classes/enp341 % 

						-- Jonathan Geisler --

_______________________________________________
AVR-GCC-list mailing list
[email protected]
https://lists.nongnu.org/mailman/listinfo/avr-gcc-list
test.cpp (text/x-c, 409 B)
#include <avr/interrupt.h>
#include <util/atomic.h>

void setup() {
	TCCR0A = 0;
	TCCR0B = 5;
	TIMSK0 = 1;
	sei();

	DDRB |= 0x20;
}

volatile unsigned long count = 0;  // bad executable if initialized to 0!!!

void loop() {
    ATOMIC_BLOCK(ATOMIC_FORCEON) {
	if (count > 50) {
		PORTB ^= 0x20;
		count = 0;
	}
    }
}

ISR(TIMER0_OVF_vect) {
	++count;
}

int main() {
	setup();

	while (1) {
		loop();
	}
}
test.ii (text/plain, 5.3 KB)
# 1 "test.cpp"
# 1 "<command-line>"
# 1 "test.cpp"
# 1 "/usr/lib/gcc/avr/4.7.2/../../../../avr/include/avr/interrupt.h" 1 3
# 38 "/usr/lib/gcc/avr/4.7.2/../../../../avr/include/avr/interrupt.h" 3
# 1 "/usr/lib/gcc/avr/4.7.2/../../../../avr/include/avr/io.h" 1 3
# 99 "/usr/lib/gcc/avr/4.7.2/../../../../avr/include/avr/io.h" 3
# 1 "/usr/lib/gcc/avr/4.7.2/../../../../avr/include/avr/sfr_defs.h" 1 3
# 126 "/usr/lib/gcc/avr/4.7.2/../../../../avr/include/avr/sfr_defs.h" 3
# 1 "/usr/lib/gcc/avr/4.7.2/../../../../avr/include/inttypes.h" 1 3
# 37 "/usr/lib/gcc/avr/4.7.2/../../../../avr/include/inttypes.h" 3
# 1 "/usr/lib/gcc/avr/4.7.2/include/stdint.h" 1 3 4


# 1 "/usr/lib/gcc/avr/4.7.2/../../../../avr/include/stdint.h" 1 3 4
# 121 "/usr/lib/gcc/avr/4.7.2/../../../../avr/include/stdint.h" 3 4
typedef signed int int8_t __attribute__((__mode__(__QI__)));
typedef unsigned int uint8_t __attribute__((__mode__(__QI__)));
typedef signed int int16_t __attribute__ ((__mode__ (__HI__)));
typedef unsigned int uint16_t __attribute__ ((__mode__ (__HI__)));
typedef signed int int32_t __attribute__ ((__mode__ (__SI__)));
typedef unsigned int uint32_t __attribute__ ((__mode__ (__SI__)));

typedef signed int int64_t __attribute__((__mode__(__DI__)));
typedef unsigned int uint64_t __attribute__((__mode__(__DI__)));
# 142 "/usr/lib/gcc/avr/4.7.2/../../../../avr/include/stdint.h" 3 4
typedef int16_t intptr_t;




typedef uint16_t uintptr_t;
# 159 "/usr/lib/gcc/avr/4.7.2/../../../../avr/include/stdint.h" 3 4
typedef int8_t int_least8_t;




typedef uint8_t uint_least8_t;




typedef int16_t int_least16_t;




typedef uint16_t uint_least16_t;




typedef int32_t int_least32_t;




typedef uint32_t uint_least32_t;







typedef int64_t int_least64_t;






typedef uint64_t uint_least64_t;
# 213 "/usr/lib/gcc/avr/4.7.2/../../../../avr/include/stdint.h" 3 4
typedef int8_t int_fast8_t;




typedef uint8_t uint_fast8_t;




typedef int16_t int_fast16_t;




typedef uint16_t uint_fast16_t;




typedef int32_t int_fast32_t;




typedef uint32_t uint_fast32_t;







typedef int64_t int_fast64_t;






typedef uint64_t uint_fast64_t;
# 273 "/usr/lib/gcc/avr/4.7.2/../../../../avr/include/stdint.h" 3 4
typedef int64_t intmax_t;




typedef uint64_t uintmax_t;
# 4 "/usr/lib/gcc/avr/4.7.2/include/stdint.h" 2 3 4
# 38 "/usr/lib/gcc/avr/4.7.2/../../../../avr/include/inttypes.h" 2 3
# 77 "/usr/lib/gcc/avr/4.7.2/../../../../avr/include/inttypes.h" 3
typedef int32_t int_farptr_t;



typedef uint32_t uint_farptr_t;
# 127 "/usr/lib/gcc/avr/4.7.2/../../../../avr/include/avr/sfr_defs.h" 2 3
# 100 "/usr/lib/gcc/avr/4.7.2/../../../../avr/include/avr/io.h" 2 3
# 222 "/usr/lib/gcc/avr/4.7.2/../../../../avr/include/avr/io.h" 3
# 1 "/usr/lib/gcc/avr/4.7.2/../../../../avr/include/avr/iom328p.h" 1 3
# 223 "/usr/lib/gcc/avr/4.7.2/../../../../avr/include/avr/io.h" 2 3
# 432 "/usr/lib/gcc/avr/4.7.2/../../../../avr/include/avr/io.h" 3
# 1 "/usr/lib/gcc/avr/4.7.2/../../../../avr/include/avr/portpins.h" 1 3
# 433 "/usr/lib/gcc/avr/4.7.2/../../../../avr/include/avr/io.h" 2 3

# 1 "/usr/lib/gcc/avr/4.7.2/../../../../avr/include/avr/common.h" 1 3
# 435 "/usr/lib/gcc/avr/4.7.2/../../../../avr/include/avr/io.h" 2 3

# 1 "/usr/lib/gcc/avr/4.7.2/../../../../avr/include/avr/version.h" 1 3
# 437 "/usr/lib/gcc/avr/4.7.2/../../../../avr/include/avr/io.h" 2 3


# 1 "/usr/lib/gcc/avr/4.7.2/../../../../avr/include/avr/fuse.h" 1 3
# 239 "/usr/lib/gcc/avr/4.7.2/../../../../avr/include/avr/fuse.h" 3
typedef struct
{
    unsigned char low;
    unsigned char high;
    unsigned char extended;
} __fuse_t;
# 440 "/usr/lib/gcc/avr/4.7.2/../../../../avr/include/avr/io.h" 2 3


# 1 "/usr/lib/gcc/avr/4.7.2/../../../../avr/include/avr/lock.h" 1 3
# 443 "/usr/lib/gcc/avr/4.7.2/../../../../avr/include/avr/io.h" 2 3
# 39 "/usr/lib/gcc/avr/4.7.2/../../../../avr/include/avr/interrupt.h" 2 3
# 2 "test.cpp" 2
# 1 "/usr/lib/gcc/avr/4.7.2/../../../../avr/include/util/atomic.h" 1 3
# 42 "/usr/lib/gcc/avr/4.7.2/../../../../avr/include/util/atomic.h" 3
static __inline__ uint8_t __iSeiRetVal(void)
{
    __asm__ __volatile__ ("sei" ::: "memory");
    return 1;
}

static __inline__ uint8_t __iCliRetVal(void)
{
    __asm__ __volatile__ ("cli" ::: "memory");
    return 1;
}

static __inline__ void __iSeiParam(const uint8_t *__s)
{
    __asm__ __volatile__ ("sei" ::: "memory");
    __asm__ volatile ("" ::: "memory");
    (void)__s;
}

static __inline__ void __iCliParam(const uint8_t *__s)
{
    __asm__ __volatile__ ("cli" ::: "memory");
    __asm__ volatile ("" ::: "memory");
    (void)__s;
}

static __inline__ void __iRestore(const uint8_t *__s)
{
    (*(volatile uint8_t *)((0x3F) + 0x20)) = *__s;
    __asm__ volatile ("" ::: "memory");
}
# 3 "test.cpp" 2

void setup() {
 (*(volatile uint8_t *)((0x24) + 0x20)) = 0;
 (*(volatile uint8_t *)((0x25) + 0x20)) = 5;
 (*(volatile uint8_t *)(0x6E)) = 1;
 __asm__ __volatile__ ("sei" ::: "memory");

 (*(volatile uint8_t *)((0x04) + 0x20)) |= 0x20;
}

volatile unsigned long count = 0;

void loop() {
    for ( uint8_t sreg_save __attribute__((__cleanup__(__iSeiParam))) = 0, __ToDo = __iCliRetVal(); __ToDo ; __ToDo = 0 ) {
 if (count > 50) {
  (*(volatile uint8_t *)((0x05) + 0x20)) ^= 0x20;
  count = 0;
 }
    }
}

extern "C" void __vector_16 (void) __attribute__ ((signal,used, externally_visible)) ; void __vector_16 (void) {
 ++count;
}

int main() {
 setup();

 while (1) {
  loop();
 }
}
signature.asc (application/pgp-signature, 490 B)
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.19 (GNU/Linux)

iQEcBAEBCAAGBQJRHqpiAAoJEOwSkIyhEMwr3KgH/0i9lB/G36B3oUOf+Aw+bzrc
0IrLzvHoo/8KXUGvTfwnGBAYWgRscAoP2SKgu7zLP5w3PkzXbaNczkSJdkZoK8No
mjj7kVNhmlgLh3QnFW+9SXdyGyusjNoU851Ty6RoKYEUN73fRxMFFaHpMmVp2ZTw
2qtdsMIkaupQ7xqK+MHmb6qsU5oz1JPjN39JHAI9mvptoj9qkFDoY9OrAY9x12Hw
HSF3lliGxCuzq6p5jB4PL0T36Rh4Ez8Lb4pxMLBlIZW0b3XXN3PIg2HNPVSWSrRm
HKZ+uTRi8oiCUmwUDx9D0sbLD9dLi49JfzFYSImIoIs6IikfmzUomfiqZH/8tM0=
=vi9i
-----END PGP SIGNATURE-----
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.