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 --
#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();
	}
}
# 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();
 }
}

Attachment: signature.asc
Description: Digital signature

_______________________________________________
AVR-GCC-list mailing list
AVR-GCC-list@nongnu.org
https://lists.nongnu.org/mailman/listinfo/avr-gcc-list

Reply via email to