Guten Morgen,
nach einiger Zeit habe ich wieder ein kleines Projekt mit einem ATmega,
doch es klappte nicht so gut wie „damals”.
Langes Probieren hat folgendes, seltsames Verhalten zu Tage gelegt:
Sobald das Programm eine Funktion außer main() enthält, führt der µC das
Programm nicht mehr aus.
Zur Verdeutlichung: Folgender Code lässt die LED an PB0 blinken.
1
#include<avr/io.h>
2
#include<util/delay.h>
3
4
// void test()
5
// {
6
// }
7
8
intmain(void)
9
{
10
DDRB|=(1<<PB0);
11
PORTB|=(1<<PB0);
12
13
while(1){
14
_delay_ms(1000);
15
PORTB^=(1<<PB0);
16
}
17
return0;
18
}
Kommentiert man Fkt. test() ein, so bleibt die LED nach übersetzten und
flashen dunkel.
Zielprozessor ist ein ATmega8 (ich weiss, deprecated, aber der lag rum),
fabrikneue Fuses. Programmer ist "STK-200" Kompatibel (Parallelport).
avrdude version 5.11.1
avr-gcc (GCC) 4.8.0
Folgende Befehle übersetzen und flashen das Programm:
Das muss etwas gaaaanz dummes sein, aber es ist fast unmöglich
Informationen zu diesen Symptomen zu finden.
Viele Grüße wünscht ein nun übernächtigter Gregor
Testweise hab ich die Funktion nun wurstbrot genannt, geht immer noch
nicht. War aber zu erwarten, da der Code nur ein Minimalbeispiel für das
Phänomen ist und es bei anderen Namen schon nicht ging.
Trotzdem schon mal Danke.
hp-freund schrieb:> Gibt es keinen Fehler/Warnungen?
Nein. Ich habe noch zusätzlich -Wall an den gcc und --fatal-warnings an
ld gefüttert.
Was genau meinst du mit *.lst Dateien? Im Assembler-Code war nichts
auffälliges zu sehen, allerdings bin ich kein Experte dieses GCC
outputs.
Funktionierend
1
.file "coffstat.c"
2
__SP_H__ = 0x3e
3
__SP_L__ = 0x3d
4
__SREG__ = 0x3f
5
__tmp_reg__ = 0
6
__zero_reg__ = 1
7
.section .text.startup,"ax",@progbits
8
.global main
9
.type main, @function
10
main:
11
/* prologue: function */
12
/* frame size = 0 */
13
/* stack size = 0 */
14
.L__stack_usage = 0
15
sbi 0x17,0
16
sbi 0x18,0
17
ldi r25,lo8(1)
18
.L2:
19
ldi r18,lo8(199999)
20
ldi r19,hi8(199999)
21
ldi r24,hlo8(199999)
22
1: subi r18,1
23
sbci r19,0
24
sbci r24,0
25
brne 1b
26
rjmp .
27
nop
28
in r24,0x18
29
eor r24,r25
30
out 0x18,r24
31
rjmp .L2
32
.size main, .-main
33
.ident "GCC: (GNU) 4.8.0"
Nicht funktionierend
1
.file "coffstat.c"
2
__SP_H__ = 0x3e
3
__SP_L__ = 0x3d
4
__SREG__ = 0x3f
5
__tmp_reg__ = 0
6
__zero_reg__ = 1
7
.text
8
.global wurstbrot
9
.type wurstbrot, @function
10
wurstbrot:
11
/* prologue: function */
12
/* frame size = 0 */
13
/* stack size = 0 */
14
.L__stack_usage = 0
15
ret
16
.size wurstbrot, .-wurstbrot
17
.section .text.startup,"ax",@progbits
18
.global main
19
.type main, @function
20
main:
21
/* prologue: function */
22
/* frame size = 0 */
23
/* stack size = 0 */
24
.L__stack_usage = 0
25
sbi 0x17,0
26
sbi 0x18,0
27
ldi r25,lo8(1)
28
.L3:
29
ldi r18,lo8(199999)
30
ldi r19,hi8(199999)
31
ldi r24,hlo8(199999)
32
1: subi r18,1
33
sbci r19,0
34
sbci r24,0
35
brne 1b
36
rjmp .
37
nop
38
in r24,0x18
39
eor r24,r25
40
out 0x18,r24
41
rjmp .L3
42
.size main, .-main
43
.ident "GCC: (GNU) 4.8.0"
Jonas schrieb:> Servus,> ich habe genau das gleiche Problem und weiß nicht woran es liegen> könnte.> Jonas
Hat es bei dir schon mal funktioniert? Könnte ja eine subtile Regression
sein.
Den Ort hab ich gefunden, bei mir
/usr/lib/ldscripts/
Evtl gibt es Probleme, weil sie nicht im Prefix mit den anderen
AVR-Headern und Libs liegen, hier
/usr/avr/
kratz
Danke auf jeden Fall schon mal, jetzt hab ich immerhin einen
Anhaltspunkt zum weiter suchen.
Ich hab ein altes Makefile von mir, wie gesagt etwa drei Jahre alt,
vermutlich ist da etwas mit den platformabhängigen Angaben
durcheinander. Diese Befehle reichten "damals" für lauffähige Programme.
Jörg Wunsch schrieb:> Ändere das mal in:
Habe ich nun getan, interessant! Jetzt geht es gar nicht mehr, egal ob
ich die wurstbrot() Funktion drinne habe oder nicht. Das passt zu dem
Verhalten des angepassten Makefiles aus den avr-gcc-Beispielen, dort
habe ich es auch in keinem Fall zum Laufen bekommen.
Ich versuche jetzt mit einem openSUSE Live System ob es mit deren
Toolchain geht, damals habe ich mit der gearbeitet. Außerdem habe ich
gemerkt, dass es in den archlinux-Foren einige mehr oder weniger
unbeantwortete Threads zu Problemen mit dem avr-gcc gibt, deren "Lösung"
die Atmel Toolchain war...
Gregor V. schrieb:> Jetzt geht es gar nicht mehr, egal ob> ich die wurstbrot() Funktion drinne habe oder nicht.
Zumindest konsistent. ;-)
Nun solltest du mal den disassemblierten Code ansehen. Ggf. auch
mal durch einen Simulator laufen lassen (simulavr + GDB).
Nach einer Freundin bedingten Pause geht das Basteln weiter.
Dank Jörgs Hinweis mit dem avr-ld enthält das Listing nun eine Interrupt
Tabelle, Wuza!
Hier der Anfang des Listings
1
coffstat.elf: file format elf32-avr
2
3
4
Disassembly of section .text:
5
6
00000024 <__vectors>:
7
24: 12 c0 rjmp .+36 ; 0x4a <__ctors_end>
8
26: 19 c0 rjmp .+50 ; 0x5a <__bad_interrupt>
9
28: 18 c0 rjmp .+48 ; 0x5a <__bad_interrupt>
10
2a: 17 c0 rjmp .+46 ; 0x5a <__bad_interrupt>
11
2c: 16 c0 rjmp .+44 ; 0x5a <__bad_interrupt>
12
2e: 15 c0 rjmp .+42 ; 0x5a <__bad_interrupt>
13
30: 14 c0 rjmp .+40 ; 0x5a <__bad_interrupt>
14
32: 13 c0 rjmp .+38 ; 0x5a <__bad_interrupt>
15
34: 12 c0 rjmp .+36 ; 0x5a <__bad_interrupt>
16
36: 11 c0 rjmp .+34 ; 0x5a <__bad_interrupt>
17
38: 10 c0 rjmp .+32 ; 0x5a <__bad_interrupt>
18
3a: 0f c0 rjmp .+30 ; 0x5a <__bad_interrupt>
19
3c: 0e c0 rjmp .+28 ; 0x5a <__bad_interrupt>
20
3e: 0d c0 rjmp .+26 ; 0x5a <__bad_interrupt>
21
40: 0c c0 rjmp .+24 ; 0x5a <__bad_interrupt>
22
42: 0b c0 rjmp .+22 ; 0x5a <__bad_interrupt>
23
44: 0a c0 rjmp .+20 ; 0x5a <__bad_interrupt>
24
46: 09 c0 rjmp .+18 ; 0x5a <__bad_interrupt>
25
48: 08 c0 rjmp .+16 ; 0x5a <__bad_interrupt>
26
27
0000004a <__ctors_end>:
28
4a: 11 24 eor r1, r1
29
4c: 1f be out 0x3f, r1 ; 63
30
4e: cf e5 ldi r28, 0x5F ; 95
31
50: d4 e0 ldi r29, 0x04 ; 4
32
52: de bf out 0x3e, r29 ; 62
33
54: cd bf out 0x3d, r28 ; 61
34
56: 04 d0 rcall .+8 ; 0x60 <main>
35
58: 01 c0 rjmp .+2 ; 0x5c <exit>
36
37
0000005a <__bad_interrupt>:
38
5a: e4 cf rjmp .-56 ; 0x24 <__vectors>
39
40
0000005c <exit>:
41
5c: f8 94 cli
42
5e: 10 c0 rjmp .+32 ; 0x80 <_exit>
43
44
00000060 <main>:
Es springt sofort ins Auge, dass die Int.tabelle bei 0x24 anfängt. WTF?
Die muss doch bei 0x0 anfangen…????
Gregor V. schrieb:> Nach einer Freundin bedingten Pause geht das Basteln weiter.
Deine Freundin hält aber lange durch. :-))
> Es springt sofort ins Auge, dass die Int.tabelle bei 0x24 anfängt. WTF?> Die muss doch bei 0x0 anfangen…????
Kannst du mal die exakten Kommandozeilen posten? Ggf. noch ein -v
hinzufügen, dann kann man mehr lesen.
Jörg Wunsch schrieb:> Gregor V. schrieb:>> Nach einer Freundin bedingten Pause geht das Basteln weiter.>> Deine Freundin hält aber lange durch. :-))
Hö? =)
>> Es springt sofort ins Auge, dass die Int.tabelle bei 0x24 anfängt. WTF?>> Die muss doch bei 0x0 anfangen…????>> Kannst du mal die exakten Kommandozeilen posten? Ggf. noch ein -v> hinzufügen, dann kann man mehr lesen.
Die genauen Befehle sind:
Ich weiss zwar nicht genau was ich jetzt gemacht habe (alle Dateien per
Hand und nicht per Makefile gelöscht) und nun … geht alles??
Danke Jörg, dein Hinweis war definitiv sehr wichtig. Warum die
Interrupttabelle schief lag, keine Ahnung.
Vlg,
Gregor
Kann es sein, dass Dein Compiler über Deine Funktionsbeschreibung
stolpert?
Eine Funktion wird üblicherweise:
Type FunktionsName ( Type )
{
}
und nicht mit
Type FunktionsName ()
{
}
beschrieben.
amateur schrieb:> Eine Funktion wird üblicherweise:>> Type FunktionsName ( Type )> {> }>> und nicht mit>> Type FunktionsName ()> {> }
Letzteres ist „historischer K&R-Stil“, den die Compiler durchaus
noch unterstützen. Bei hinreichend vielen eingeschalteten Warnungen
gibt's allerdings eine Warnung dafür (“function declaration is not
a prototype” oder so ähnlich), guter Stil ist es natürlich nicht.
Aber ein Fehler ist es eben auch nicht.