Hallo liebe µC-Gemeinde,
ich habe ein kleines Problem mit der _delay_ms() Funktion. Ich hab das
Problem schon etwas nachverfolgt, stehe aber mittlerweile nurnoch mit
einem großen Fragezeichen über dem Kopf da. Wenn ich nach dem Fehler
suche finde ich leider nur antworten in denen die Funktion falsch
verwendet wird oder F_CPU nicht definiert ist.
Mein Problem ist, das mein Compiler scheinbar die _delay_ms() funktion
nicht richtig behandelt. So kommt exakt die gleiche elf und somit auch
die gleiche (i)hex datei heraus, egal ob ich z.B. _delay_ms(500) oder
_delay_ms(1000) schreibe.
Aber erstmal ein paar infos zur Umgebung:
OS: Linux Mint (Auf Arch Linux und/oder anderen PCs ist das gleiche
Problem)
IDE: Codeblocks 13.12-3
Compiler: avr-gcc 1:4.8-2.1
libc: avr-libc 1:1.8.0-4.1
binutils: binutils-avr 2.23.1-2.1
avr: attiny2313 (ist aber egal welcher)
Ich hab ein Programm mal auf das nötigste heruntergebrochen damit der
Fehler schneller sehbar ist:
1
#define F_CPU 4000000UL
2
3
#include<avr/io.h>
4
#include<util/delay.h>
5
6
intmain(void)
7
{
8
while(1)
9
{
10
asm("nop");
11
asm("nop");
12
asm("nop");
13
_delay_ms(1000);
14
asm("nop");
15
asm("nop");
16
asm("nop");
17
}
18
19
return0;
20
}
Dieses Programm hab ich mit verschiedenen Werten in _delay_ms(x)
compiliert. 500, 1000, 10000. Alle Werte ergeben folgendes, wenn ich mit
avr-objdump -d die elf-datei ansehe die compiliert wird.
Die jeweils 3x NOP sollen nur bewirken das man die stelle einfach im
objdump findet.
1
delay_ms_test.elf: Dateiformat elf32-avr
2
3
4
Disassembly of section .text:
5
6
00000000 <__vectors>:
7
0: 12 c0 rjmp .+36 ; 0x26 <__ctors_end>
8
2: 17 c0 rjmp .+46 ; 0x32 <__bad_interrupt>
9
4: 16 c0 rjmp .+44 ; 0x32 <__bad_interrupt>
10
6: 15 c0 rjmp .+42 ; 0x32 <__bad_interrupt>
11
8: 14 c0 rjmp .+40 ; 0x32 <__bad_interrupt>
12
a: 13 c0 rjmp .+38 ; 0x32 <__bad_interrupt>
13
c: 12 c0 rjmp .+36 ; 0x32 <__bad_interrupt>
14
e: 11 c0 rjmp .+34 ; 0x32 <__bad_interrupt>
15
10: 10 c0 rjmp .+32 ; 0x32 <__bad_interrupt>
16
12: 0f c0 rjmp .+30 ; 0x32 <__bad_interrupt>
17
14: 0e c0 rjmp .+28 ; 0x32 <__bad_interrupt>
18
16: 0d c0 rjmp .+26 ; 0x32 <__bad_interrupt>
19
18: 0c c0 rjmp .+24 ; 0x32 <__bad_interrupt>
20
1a: 0b c0 rjmp .+22 ; 0x32 <__bad_interrupt>
21
1c: 0a c0 rjmp .+20 ; 0x32 <__bad_interrupt>
22
1e: 09 c0 rjmp .+18 ; 0x32 <__bad_interrupt>
23
20: 08 c0 rjmp .+16 ; 0x32 <__bad_interrupt>
24
22: 07 c0 rjmp .+14 ; 0x32 <__bad_interrupt>
25
24: 06 c0 rjmp .+12 ; 0x32 <__bad_interrupt>
26
27
00000026 <__ctors_end>:
28
26: 11 24 eor r1, r1
29
28: 1f be out 0x3f, r1 ; 63
30
2a: cf ed ldi r28, 0xDF ; 223
31
2c: cd bf out 0x3d, r28 ; 61
32
2e: 02 d0 rcall .+4 ; 0x34 <main>
33
30: 0d c0 rjmp .+26 ; 0x4c <_exit>
34
35
00000032 <__bad_interrupt>:
36
32: e6 cf rjmp .-52 ; 0x0 <__vectors>
37
38
00000034 <main>:
39
34: 00 00 nop
40
36: 00 00 nop
41
38: 00 00 nop
42
3a: 8f ef ldi r24, 0xFF ; 255
43
3c: 9f e3 ldi r25, 0x3F ; 63
44
3e: 01 97 sbiw r24, 0x01 ; 1
45
40: f1 f7 brne .-4 ; 0x3e <__SP_L__+0x1>
46
42: 00 c0 rjmp .+0 ; 0x44 <__SREG__+0x5>
47
44: 00 00 nop
48
46: 00 00 nop
49
48: 00 00 nop
50
4a: f4 cf rjmp .-24 ; 0x34 <main>
51
52
0000004c <_exit>:
53
4c: f8 94 cli
54
55
0000004e <__stop_program>:
56
4e: ff cf rjmp .-2 ; 0x4e <__stop_program>
Um zu verhindern das ich irgendwas übersehe habe ich auch schon
avr-objdump mit -d -x ausgeführt und für die jeweils verschiedenen Werte
in _delay_ms in dateien geschrieben und mit diff verglichen. KEIN
Unterschied. Und um zu verhindern das ich die falsche Datei untersuche
habe ich versucht andere kleine Variablenmanipulationen ins Programm zu
bringen. Hierbei entstehen durchaus änderungen in der elf-Datei.
Ich will _delay_ms eigentlich gar nicht verwenden, aber um schnell etwas
zu testen ist es eben nützlich. Nur wenn einem so ein kleines Problem
einen ganzen Abend aufhält ist das schon lästig.
Letzendlich ist es egal was ich eingebe, das delay ändert sich nicht,
und so kann natürlich niemand arbeiten.
Was mich besonders stutzig macht ist das _delay_ms() vor wenigen
Wochen/Monaten von mir ohne Probleme benutzt werden konnte. Also zu doof
scheine ich auch nicht zu sein.
Ich hoffe das irgendjemand eine Lösung hat.
Danke für Eure Zeit und Lösungen!
Benedikt W. schrieb:> der _delay_ms() Funktion
Es ist ein Makro - keine Funktion.
Und es wird durch die Compiler-Optimierungseinstellung gerne
wegoptimiert.
STK500-Besitzer schrieb:> Benedikt W. schrieb:>> der _delay_ms() Funktion>> Es ist ein Makro - keine Funktion.> Und es wird durch die Compiler-Optimierungseinstellung gerne> wegoptimiert.
Hatte ich zuerst auchgedacht, dass es wegoptimiert wurde.
Ist hier aber nicht der Fall, wie der Assembler Output zeigt.
Bitflüsterer schrieb:> Du hast vergessen, nachträglich zu editieren, Karl Heinz. Ich weiss zwar> nicht, was Du noch ändern solltest, aber Du solltest es. :-)
Hmm. Zwischen 'auch' und 'gedacht' fehlt ein Leerzeichen.
Könnte ich jetzt noch reineditieren, bin aber im Moment zu faul dazu :-)
Jim Meba schrieb:> Versuche mal einen Wert kleiner als 60. Da war was mit Integer Überlauf> in dem _delay_ms Makro.
Da müsste er schon eine sehr alte Version haben.
Seit einigen Jahren ist das kein Problem mehr.
Karl Heinz schrieb:> Jim Meba schrieb:>> Versuche mal einen Wert kleiner als 60. Da war was mit Integer Überlauf>> in dem _delay_ms Makro.>> Da müsste er schon eine sehr alte Version haben.> Seit einigen Jahren ist das kein Problem mehr.
Aber irgendwas stimmt da nicht
Denn das
1
3a: 8f ef ldi r24, 0xFF ; 255
2
3c: 9f e3 ldi r25, 0x3F ; 63
3
3e: 01 97 sbiw r24, 0x01 ; 1
4
40: f1 f7 brne .-4 ; 0x3e <__SP_L__+0x1>
ergibt bei aller Liebe niemals 1 Sekunde Laufzeit. Da brauch ich gar
nicht nachrechnen, das geht sich nie aus.
Benedikt W. schrieb:> Ich hoffe das irgendjemand eine Lösung hat.
So sieht es bei mir aus:
1
00000034<main>:
2
millisecondscanbeachieved.
3
*/
4
void
5
_delay_loop_2(uint16_t__count)
6
{
7
__asm__volatile(
8
34:24e6ldir18,0x64;100
9
36:30e0ldir19,0x00;0
10
11
intmain(void)
12
{
13
while(1)
14
{
15
asm("nop");
16
38:0000nop
17
asm("nop");
18
3a:0000nop
19
asm("nop");
20
3c:0000nop
21
3e:80e1ldir24,0x10;16
22
40:97e2ldir25,0x27;39
23
42:f901movwr30,r18
24
44:3197sbiwr30,0x01;1
25
46:f1f7brne.-4;0x44<__SREG__+0x5>
26
__ticks=(uint16_t)(__ms*10.0);
27
while(__ticks)
28
{
29
// wait 1/10 ms
30
_delay_loop_2(((F_CPU)/4e3)/10);
31
__ticks--;
32
48:0197sbiwr24,0x01;1
33
__ticks=1;
34
elseif(__tmp>65535)
35
{
36
// __ticks = requested delay in 1/10 ms
37
__ticks=(uint16_t)(__ms*10.0);
38
while(__ticks)
39
4a:d9f7brne.-10;0x42<__SREG__+0x3>
40
_delay_ms(1000);
41
asm("nop");
42
4c:0000nop
43
asm("nop");
44
4e:0000nop
45
asm("nop");
46
50:0000nop
47
52:f2cfrjmp.-28;0x38<main+0x4>
48
49
00000054<_exit>:
50
54:f894cli
51
52
00000056<__stop_program>:
53
56:ffcfrjmp.-2;0x56<__stop_program>
Bei dir ist _delay irgendwie verschwunden, auch ist Wert fur _delay
nicht as volatile deklariert, aber so schlau kann doch eigentlich kein
Compiler sein - oder doch ?
Versuchs mal mit irgendeiner Variable dahinter.
Marc Vesely schrieb:> So sieht es bei mir aus:
Ist zwar OT, aber trotzdem eine Frage an den Moderator:
Du hast mein Beitrag moderiert, ich meine das mit Unterstrich und so,
machst du das zu Fuss oder kann man autoedit irgendwie abstellen ?
Marc Vesely schrieb:> Marc Vesely schrieb:>> So sieht es bei mir aus:>> Ist zwar OT, aber trotzdem eine Frage an den Moderator:> Du hast mein Beitrag moderiert, ich meine das mit Unterstrich und so,> machst du das zu Fuss oder kann man autoedit irgendwie abstellen ?
Wenn du dir angewöhnen würdest, bei Code gleich die Formatierzeichen
einzufügen ....
Für C-Code am Beginn des Codes [ C ], am Ende des Codes [ /C ] (jeweils
ohne die Leerzeichen.
Für Assembler Code am Beginn des Codes [ avrasm ], am Ende des Codes [
/avrasm ] (wieder ohne die Leerzeichen
... dann bräuchte ich deinen Post nicht editieren.
Mahr als diese Formatierzeichen ergänzen hab ich in deinem Posting nicht
gemacht.
Marc Vesely schrieb:> nicht as volatile deklariert, aber so schlau kann doch eigentlich kein> Compiler sein - oder doch ?> Versuchs mal mit irgendeiner Variable dahinter.
Vor etwa 10 Jahren zeigte mir jemand ein Schnipsel aus den 60-er
in FORTRAN. War fur IBMetwas geschrieben. Und zwar wollten die wissen
wie schnell der IBM eigentlich rechnen kann.
Also, Variable XYZ durch PI, in eine Schleife, 1000 Durchläufe, Zeit
gemessen - nicht messbar.
5000, 100000, 10000000, 1E12 - dasselbe.
Na, so schnell kann der IBM doch gar nicht sein, dachten die
Schlaumeier. Bis irgendeiner dahinter kam, dass die Variable ja
nirgendwo ausgegeben oder benutzt wurde, also hat der compiler das
Ganze einfach wegoptimiert...
Karl Heinz schrieb:> ... dann bräuchte ich deinen Post nicht editieren.> Mahr als diese Formatierzeichen ergänzen hab ich in deinem Posting nicht> gemacht.
Hab mich auch nicht beschwert, nur gefragt. Sorry.
Wichtige Regeln - erst lesen, dann posten.
Hurra, ich kann das !!!