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-----