Go Down

Topic: Arduino Mega 1280 delay() turbocharged (Read 13 times) previous topic - next topic

stimmer

I'm baffled by this one. I tried to compile GCC 4.5.2 on Ubuntu but just got too many errors. I also tried to install Arch Linux but Virtualbox was not cooperating, so gave up on that too.

Are either of you able to disassemble the object file and see what the compiler is doing to the delay function?

I wonder if the compiler is misconfigured or picking up a delay function from some other header somewhere... Does Arch set any environment variables that might interfere with GCC, like CFLAGS, CXXFLAGS, C_INCLUDE_PATH, CPLUS_INCLUDE_PATH and LIBRARY_PATH ?

igor86

Hi stimmer,

None of those environment variables seem to be set:

Code: [Select]

??[igor]??[X201]
??[~]$ echo $PATH
/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin:/opt/java/bin:/opt/java/db/bin:/opt/java/jre/bin:/usr/bin/core_perl:/usr/local/bin:/usr/local/bin
??[igor]??[X201]
??[~]$ echo $CFLAGS

??[igor]??[X201]
??[~]$ echo $C_INCLUDE_PATH

??[igor]??[X201]
??[~]$ echo $C_PLUS_INCLUDE_PATH

??[igor]??[X201]
??[~]$ echo $LIBRARY_PATH

??[igor]??[X201]
??[~]$


I'll dive into the issue in more detail as soon as I get some free time. I just updated Arch linux and saw it pulled a new gcc in, so I will recompile the sketches and see if anything changes. If I can't figure anything out, I'll get in touch with the Arch linux arduino package maintainer and let him know about this issue, since it seems to be Arch specific.

Cheers,
-Igor

stimmer

#17
Feb 02, 2011, 09:45 pm Last Edit: Feb 02, 2011, 09:47 pm by stimmer Reason: 1
Could you try doing a disassembly of the delay function?

Load up the Blink sketch, then hold down shift as you click Verify, then look in the box at the bottom for the temporary directory it uses.

In a terminal, type cd /tmp/buildnnnnnnnnnnn.tmp (where buildnnnnnnnnnnnn.tmp is the temporary directory as above)

Then type avr-objdump -S Blink.cpp.elf

Then find the <delay> symbol  and cut and paste it from there up to the next symbol and post it here, it should look like this:

Code: [Select]
000004c4 <delay>:

void delay(unsigned long ms)
{
4c4: ef 92        push r14
4c6: ff 92        push r15
4c8: 0f 93        push r16
4ca: 1f 93        push r17
4cc: cf 93        push r28
4ce: df 93        push r29
4d0: 7b 01        movw r14, r22
4d2: 8c 01        movw r16, r24
uint16_t start = (uint16_t)micros();
4d4: 0e 94 3c 02 call 0x478 ; 0x478 <micros>
4d8: eb 01        movw r28, r22
4da: 0e c0        rjmp .+28      ; 0x4f8 <delay+0x34>

while (ms > 0) {
if (((uint16_t)micros() - start) >= 1000) {
4dc: 0e 94 3c 02 call 0x478 ; 0x478 <micros>
4e0: 6c 1b        sub r22, r28
4e2: 7d 0b        sbc r23, r29
4e4: 68 5e        subi r22, 0xE8 ; 232
4e6: 73 40        sbci r23, 0x03 ; 3
4e8: c8 f3        brcs .-14      ; 0x4dc <delay+0x18>
ms--;
4ea: 08 94        sec
4ec: e1 08        sbc r14, r1
4ee: f1 08        sbc r15, r1
4f0: 01 09        sbc r16, r1
4f2: 11 09        sbc r17, r1
start += 1000;
4f4: c8 51        subi r28, 0x18 ; 24
4f6: dc 4f        sbci r29, 0xFC ; 252

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

while (ms > 0) {
4f8: e1 14        cp r14, r1
4fa: f1 04        cpc r15, r1
4fc: 01 05        cpc r16, r1
4fe: 11 05        cpc r17, r1
500: 69 f7        brne .-38      ; 0x4dc <delay+0x18>
if (((uint16_t)micros() - start) >= 1000) {
ms--;
start += 1000;
}
}
}
502: df 91        pop r29
504: cf 91        pop r28
506: 1f 91        pop r17
508: 0f 91        pop r16
50a: ff 90        pop r15
50c: ef 90        pop r14
50e: 08 95        ret

00000510 <init>:


ccfreak2k

None of those environment variables seem to be set:
None of those variables should be set normally; the makefile sets them, and they basically are only set while make is running (i.e. during the build process).

mkpetch

Hi, I'm having the same problem Igor86 describes... Arduino Uno, Arch Linux 64-bit, avr-gcc version 4.5.2.

Here's my disassembly of the standard example Blink sketch as Stimmer requested

Code: [Select]

00000210 <delay>:

void delay(unsigned long ms)
{
210: ef 92        push r14
212: ff 92        push r15
214: 0f 93        push r16
216: 1f 93        push r17
218: cf 93        push r28
21a: df 93        push r29
21c: 7b 01        movw r14, r22
21e: 8c 01        movw r16, r24
uint16_t start = (uint16_t)micros();
220: 0e 94 e2 00 call 0x1c4 ; 0x1c4 <micros>
224: eb 01        movw r28, r22

while (ms > 0) {
226: 0f c0        rjmp .+30      ; 0x246 <delay+0x36>
if (((uint16_t)micros() - start) >= 1000) {
228: 0e 94 e2 00 call 0x1c4 ; 0x1c4 <micros>
22c: 6c 1b        sub r22, r28
22e: 7d 0b        sbc r23, r29
230: 83 e0        ldi r24, 0x03 ; 3
232: 68 3e        cpi r22, 0xE8 ; 232
234: 78 07        cpc r23, r24
236: 38 f0        brcs .+14      ; 0x246 <delay+0x36>
ms--;
238: 08 94        sec
23a: e1 08        sbc r14, r1
23c: f1 08        sbc r15, r1
23e: 01 09        sbc r16, r1
240: 11 09        sbc r17, r1
start += 1000;
242: c8 51        subi r28, 0x18 ; 24
244: dc 4f        sbci r29, 0xFC ; 252

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

while (ms > 0) {
246: e1 14        cp r14, r1
248: f1 04        cpc r15, r1
24a: 01 05        cpc r16, r1
24c: 11 05        cpc r17, r1
24e: 61 f7        brne .-40      ; 0x228 <delay+0x18>
if (((uint16_t)micros() - start) >= 1000) {
ms--;
start += 1000;
}
}
}
250: df 91        pop r29
252: cf 91        pop r28
254: 1f 91        pop r17
256: 0f 91        pop r16
258: ff 90        pop r15
25a: ef 90        pop r14
25c: 08 95        ret

0000025e <init>:


I notice at offset 226 above the rjmp looks like it's inside the while (ms > 0) { }

and at offsets 230-234 things are handled slightly differently, but my reading of the assembly language isn't good enough to tell me what that means  :)

Hope this is helpful as I'd really like to be programming my new Arduino Uno from my Arch system too!

Thanks to Stimmer for looking into this problem.

Go Up