Arduino Mega 1280 delay() turbocharged

Hi,

Here is my dissassmebled code as requested:

000002fc <delay>:

void delay(unsigned long ms)
{
 2fc:   ef 92           push    r14
 2fe:   ff 92           push    r15
 300:   0f 93           push    r16
 302:   1f 93           push    r17
 304:   cf 93           push    r28
 306:   df 93           push    r29
 308:   7b 01           movw    r14, r22
 30a:   8c 01           movw    r16, r24
        uint16_t start = (uint16_t)micros();
 30c:   0e 94 58 01     call    0x2b0   ; 0x2b0 <micros>
 310:   eb 01           movw    r28, r22

        while (ms > 0) {
 312:   0f c0           rjmp    .+30            ; 0x332 <delay+0x36>
                if (((uint16_t)micros() - start) >= 1000) {
 314:   0e 94 58 01     call    0x2b0   ; 0x2b0 <micros>
 318:   6c 1b           sub     r22, r28
 31a:   7d 0b           sbc     r23, r29
 31c:   83 e0           ldi     r24, 0x03       ; 3
 31e:   68 3e           cpi     r22, 0xE8       ; 232
 320:   78 07           cpc     r23, r24
 322:   38 f0           brcs    .+14            ; 0x332 <delay+0x36>
                        ms--;
 324:   08 94           sec
 326:   e1 08           sbc     r14, r1
 328:   f1 08           sbc     r15, r1
 32a:   01 09           sbc     r16, r1
 32c:   11 09           sbc     r17, r1
                        start += 1000;
 32e:   c8 51           subi    r28, 0x18       ; 24
 330:   dc 4f           sbci    r29, 0xFC       ; 252

void delay(unsigned long ms)
{
        uint16_t start = (uint16_t)micros();

        while (ms > 0) {
 332:   e1 14           cp      r14, r1
 334:   f1 04           cpc     r15, r1
 336:   01 05           cpc     r16, r1
 338:   11 05           cpc     r17, r1
 33a:   61 f7           brne    .-40            ; 0x314 <delay+0x18>
                if (((uint16_t)micros() - start) >= 1000) {
                        ms--;
                        start += 1000;
                }
        }
}
 33c:   df 91           pop     r29
 33e:   cf 91           pop     r28
 340:   1f 91           pop     r17
 342:   0f 91           pop     r16
 344:   ff 90           pop     r15
 346:   ef 90           pop     r14
 348:   08 95           ret

0000034a <init>:

Thanks heaps for looking into this stimmer! Helping others like you have is certainly good karma! :wink:

Cheers,
-Igor

Well, that disassembly looks correct, it's slightly different to mine but not significantly.

Could you disassemble it again and post the entire disassembly? I am wondering if something is clobbering r1 (which should usually be zero) or if an ISR is clobbering something else, the only way to find out is to look through the whole lot :cold_sweat:

OK... I finally managed to install Arch linux on Virtualbox and I think I'm getting to the bottom of this. It appears that the Arch compiler sometimes generates code that writes to addresses before the start of memory. RAM starts at address 0x200 on the mega, but the Blink code has the delay() timer variables located at 0x100-0x10b. This only seems to happen when the code contains no initialised global variables (.data segment in asm-speak) - the linker is told that the data segment starts at 0x200, but if there's nothing to go in it it generates an incorrect start address for the uninitialised global variables (.bss segment). Since the timer variables are uninitialised globals (or globals initialised to zero) they end up at an illegal address.

Here's my blink code that worked, with an initialised global. Could you test this and tell me if it is at the correct speed?

char dummyvariablecuzmaintainerborkedthecompiler = 123; // force something into the .data segment with non-zero initializer
/*
  Blink
  Turns on an LED on for one second, then off for one second, repeatedly.

  This example code is in the public domain.
 */

void setup() {  
  dummyvariablecuzmaintainerborkedthecompiler++;  // stops the linker from removing the global variable
  
  // initialize the digital pin as an output.
  // Pin 13 has an LED connected on most Arduino boards:
  pinMode(13, OUTPUT);     
}

void loop() {
  digitalWrite(13, HIGH);   // set the LED on
  delay(1000);              // wait for a second
  digitalWrite(13, LOW);    // set the LED off
  delay(1000);              // wait for a second
}

Any code that uses the Serial class won't be affected by this, as Serial contains an initialised global.

Wow, well the Blink sketch with global var inserted functions correctly for me! Compiles and uploads fine and the led blinks on and off at the correct rate on the Uno.

Will be interesting to know how this tests out for Igor's Mega 1280 as well as Uno board and Aleks' various boards on 32 bit Arch...

As an arduino newbie I'm not sure where to go next with this but it seems it is an Arch specific problem?

char dummyvariablecuzmaintainerborkedthecompiler = 123;

LOL

Seriously the Arch maintainers are doing a great job, from what I can tell there's still issues with the Arduino IDE distribution containing 32bit rxtx but there is rxtx replacement in AUR (Arch User Repos)

But this problem sounds like it will be with gcc-avr, gcc-binutils or something?

I strongly agree with Igor's statement that:

Open source hardware should have a good IDE implementation for open source software, no?

and the kind of help Stimmer, Dafid et al are providing on this forum will no doubt be invaluable for getting Arduino stable on Arch's rolling releases insofar as that's possible ]:)

I'm following with interest and I guess this will filter over to the Arch forums or bug reports as it develops...?

Yes, it sounds like an Arch specific problem at the moment. Maintaining a cross compiler is probably one of the harder jobs, they are a pain to compile and bug reports are hard to replicate.

A potential solution has been posted in another thread by dsh1. This involves downgrading to GCC 4.3.5 and applying Debian patches:

http://arduino.cc/forum/index.php/topic,51000.msg363998.html#msg363998

Can people try this and see if it works?

stimmer:
Yes, it sounds like an Arch specific problem at the moment. Maintaining a cross compiler is probably one of the harder jobs, they are a pain to compile and bug reports are hard to replicate.

A potential solution has been posted in another thread by dsh1. This involves downgrading to GCC 4.3.5 and applying Debian patches:

http://arduino.cc/forum/index.php/topic,51000.msg363998.html#msg363998

Can people try this and see if it works?

I just thought I would mention that I’m having this problem with Gentoo as well. I’m using:

$ avr-gcc -v
Using built-in specs.
Target: avr
Configured with: /var/tmp/portage/cross-avr/gcc-4.3.3-r2/work/gcc-4.3.3/configure --prefix=/usr --bindir=/usr/i686-pc-linux-gnu/avr/gcc-bin/4.3.3 --includedir=/usr/lib/gcc/avr/4.3.3/include --datadir=/usr/share/gcc-data/avr/4.3.3 --mandir=/usr/share/gcc-data/avr/4.3.3/man --infodir=/usr/share/gcc-data/avr/4.3.3/info --with-gxx-include-dir=/usr/lib/gcc/avr/4.3.3/include/g++-v4 --host=i686-pc-linux-gnu --target=avr --build=i686-pc-linux-gnu --disable-altivec --disable-fixed-point --enable-nls --without-included-gettext --with-system-zlib --disable-werror --enable-secureplt --disable-libmudflap --disable-libssp --enable-cld --enable-checking=release --disable-libgcj --enable-languages=c,c++ --enable-shared --disable-threads --disable-bootstrap --with-bugurl=http://bugs.gentoo.org/ --with-pkgversion='Gentoo 4.3.3-r2 p1.2, pie-10.1.5'
Thread model: single
gcc version 4.3.3 (Gentoo 4.3.3-r2 p1.2, pie-10.1.5)

I’ve been discussing this in #arduino, and we’re working around this issue so far like this: (with a 0022 ide)

$ diff -u5 hardware/arduino/cores/arduino/wiring.{c_orig,c}
--- hardware/arduino/cores/arduino/wiring.c_orig	2011-02-05 18:17:40.058000066 -0600
+++ hardware/arduino/cores/arduino/wiring.c	2011-02-05 18:19:32.907000066 -0600
@@ -21,10 +21,11 @@
 
   $Id$
 */
 
 #include "wiring_private.h"
+#include <avr/delay.h>
 
 // the prescaler is set so that timer0 ticks every 64 clock cycles, and the
 // the overflow handler is called every 256 ticks.
 #define MICROSECONDS_PER_TIMER0_OVERFLOW (clockCyclesToMicroseconds(64 * 256))
 
@@ -102,18 +103,21 @@
 	return ((m << 8) + t) * (64 / clockCyclesPerMicrosecond());
 }
 
 void delay(unsigned long ms)
 {
+/*	
 	uint16_t start = (uint16_t)micros();
 
 	while (ms > 0) {
 		if (((uint16_t)micros() - start) >= 1000) {
 			ms--;
 			start += 1000;
 		}
 	}
+*/
+	_delay_ms(ms);
 }
 
 /* Delay for the given number of microseconds.  Assumes a 8 or 16 MHz clock. */
 void delayMicroseconds(unsigned int us)
 {

I have also found that using the 0018 IDE, the delay() works properly.

I’ll have a look at the Debian patches you listed, and report back when I know more.

On further investigation, it seems that using binutils-2.20.1-r1 instead of binutils-2.21 solves this for me on Gentoo.

I have this issue with the Uno and Fedora14 i686. The software is avr-gcc-4.5.1 and avr-binutils 2.21.

Same here with Fedora 14. (using a Duemilanove)

avr-gcc -v result.

Using built-in specs. COLLECT_GCC=avr-gcc COLLECT_LTO_WRAPPER=/usr/libexec/gcc/avr/4.5.1/lto-wrapper Target: avr Configured with: ../gcc-4.5.1/configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --target=avr --enable-languages=c,c++ --disable-nls --disable-libssp --with-system-zlib --enable-version-specific-runtime-libs --with-pkgversion='Fedora 4.5.1-2.fc14.1' --with-bugurl=https://bugzilla.redhat.com/ Thread model: single gcc version 4.5.1 (Fedora 4.5.1-2.fc14.1)

Hadn't used it for a while on my Fedora box. Works fine so far on Mint though, so not completely duinoless. I also get an error when uploading

"avrdude: stk500_recv(): programmer is not responding"

But none with the blink without delay sketch.

Using avrdude 5.10

Ditto for Fedora 14, with Arduino Duemilanove. See topic http://arduino.cc/forum/index.php/topic,68512.0.html

However the 'blink' example that comes with the arduino v22 software, initializes a LEDPin global variable and that, as has been said fixes the problem.

I am a newbe to using the arduino, and the fact that it fails like this with a very basic example has been a worry for me. Any idea when the real problem will be fixed?