Hi
Ich habe ein kleines ARM-Problem, von dem ich als ARM-Neuling leider
nicht sagen kann woran es liegt. Ich habe mir ein Evaluationsboard von
Olimex mit AT91SAM7S64 und passendem Wiggler-kompatiblen-JTAG gekauft.
Das funktioniert auch mit dem passenden Beispiel ganz hervorragend, nur
mein erstes eigenes Programm will nicht so ganz.
Ich verwende die YATARGO-IDE und lade meine Programme per OpenOCD auf
den ARM.
Symptome:
Das einfache Programm, das eigentlich 2 LEDs zum leuchten bringen soll,
wird scheints gar nicht ausgeführt, sprich die LEDs leuchten nicht.
Komisch: Wenn vorher ein Beispielprogramm auf dem ARM war, funktioniert
es.
Ich vermute entweder, dass ich Mist beim Programmieren gebaut habe, oder
das was im Makefile nicht stimmt (-> Linkerscript?!).
(Davon habe ich erst seit ich mit den ARMs beschäftige Kontakt, beim AVR
macht das ja das Studio).
Ich habe hier mal das gesamte Projekt auf meinen Webspace geladen:
http://www.tobias-schlegel.de/PublicData/test2.zip
Leider finde ich keine Tutorials, die die Sache mit dem Tiefgang
beleuchten, den ich gerne hätte.
Deshalb bitte auch nicht erschrecken: Ich versuche die ARM-CPU zu
verstehen, und nicht Bibliotheken einzubinden.
Für Hilfe wäre ich wirklich sehr dankbar.
Viele Grüße, Tobi
Hallo,
irgendwie scheint OpenOCD mit dem Wiggler murks zu sein. Bei mir wurde
das Programm zwar geladen und ausgeführt, aber wenn ich die Spannung
wegnahm, war auch das Programm weg.
Dann habe ich H-JTAG verwendet und dann ging es problemlos:
http://www.hjtag.com/
Hi,
Ok, ich habe das gerade mit dem Beispiel getestet, und das bleibt im
Speicher, selbst wenn keine Betriebsspannung dran ist.
Es fängt ja auch garnicht mit Ausführen an, wenn ich es hochlade.
Was vielleicht noch zu erwähnen ist: Beim Compilieren gibt es keinerlei
Warnungen o.ä..
Das HJTAG sieht sehr gut aus, ich werd das mal genauer unter die Lupe
nehmen...
VLG Tobi
Hallo Tobias,
das Projekt sieht ziemlich verstümmelt aus. Dein main.out (und damit
auch main.bin) enthält nur die main() Funktion, der Startup Code aus
crt.S fehlt.
Hat es einen Grund, dass du das Linker Skript im Makefile auskommentiert
hast?
@Steven:
Sorry, aber das ist ein Piloten-Fehler... Wenn das Programm nach
Wegnehmen der Spannung nicht mehr im Speicher ist hattest du es nie im
Flash, sondern nur im RAM.
Der OpenOCD funktioniert wunderbar mit einem Wiggler, allerdings
verlangt eine GNU Toolchain mit dem OpenOCD mehr Einarbeitungszeit als
eine Lösung mit IAR/Keil/... und H-JTAG.
Gruß,
Dominic
Hi
Oooops. Ja, das war auskommentiert weil ich erst einen anderen
Linkerscript hatte... der dann nicht funktioniert hat etc. Jetzt sollte
es stimmen...
http://www.tobias-schlegel.de/PublicData/test2.zip
Der Startup-code. Das sollte eigentlich meine main() machen, weil die ja
die Clocks etc. initialisiert. Die crt.s ist eigentlich auch nur zu
Testzwecken da...
Oder liege ich dahingehend total falsch und man braucht immer einen
Startup-Code?
Wenn ja: Wie kann man ihn einbinden, und wozu braucht man das überhaupt?
Der AVR braucht das ja auch nicht...??
Oder?
Danke!
VLG Tobi
HI
Ja, ich habe diese Beispiele gesehen, ich bin gerade dabei das Beispiel
fürs PIO nachzuprogrammieren, aber ich hab den Ehrgeiz das ohne
fertig-Funktionen zu schaffen. Theoretisch sollte es jea eigentlich
funktionieren. Ich hoffe auf den Startupcode... ;)
VLG Tobi
Hallo Tobi,
irgend eine Form von Startup-Code brauchst du immer. Ich habe nie mit
einem AVR gearbeitet, weiss also nicht, wie dort der Startup realisiert
wird, ein ARM sieht nach einem Reset allerdings wie folgt aus:
- R14_SVC (die Return Addresse) ist unpredictable
- SPSR_SVC (das Saved Program Status Register) ist unpredictable
- CPSR[4:0] = b10011 (Supervisor Mode)
- CPSR[5] = 0 (ARM State, nicht Thumb State)
- CPSR[6] = 1 (FIQ disabled)
- CPSR[7] = 1 (IRQ disabled)
- PC = 0x0 (oder 0xffff0000 bei high-vectors, der SAM7 verwendet
allerdings low-vectors)
Alle anderen Register dürften wohl ihren vorherigen Zustand beibehalten,
allerdings ist der bei einem Poweron-Reset natürlich auch undefiniert.
Der Startup Code muss jetzt zumindest die Stack Pointer (R13) der
verschiedenen Modi initialisieren und den Einsprung in die Main-Routine
machen. Dazu müssen die Register entsprechend der Calling-Convention
initialisiert werden:
int main(int argc, char *argv[]);
die Parameter werden von links nach rechts in r0-r3, alle Weiteren auf
dem Stack übergeben. Ausserdem sollte der Framepointer (r11) auf NULL
initalisiert werden, damit der Debugger nicht bei der Suche nach
weiteren Stackframes auf ungültige Speicheraddressen zugreift.
Bei Ausführung aus dem Flash muss ausserdem der Startup Code das BSS
Segment auf Null initialisieren und das DATA Segment vom Flash in's RAM
kopieren.
(ohne Anspruch auf Vollständigkeit)
Gruß,
Dominic
Hi
ähh... Okay.
Gut, dann ist das ETWAS komplizierter als ich gedacht habe ;) .
-> Jetzt verstehe ich auch, warum der Startup-Code in ASM geschrieben
wird...!
Hm. Wo kann ich so einen Code herbekommen, der nichts anderes macht, als
für mich den ARM zu "resetten" und in die main-Routine zu springen? Ich
werd mich damit noch auseinandersetzen (müssen) aber für den Anfang
dürfte das etwas zu komplex sein oder?
Also ich habe ja diese crt.s. Da ist ja Startup-Code drin?
Wenn ja, was hat das da zu suchen:
1
/* Turn on LED3 (write 0x0008 to PIOA_CODR at 0xFFFFF434) */
2
ldr r12, =AT91C_PIOA_CODR
3
mov r11, #0x04
4
str r11, [r12]
Line 115-118
Jetzt ist also "nur" noch die Frage, wie ich dem Linker sage, dass der
das dazu linken soll...
Sagts mir, wenn ich euch auf die Nerven geh... :)
Danke auf jeden Fall!!
VLG Tobi
Es ist wohl eine Stil-Frage, was im Startup-Code gemacht wird. Bei
komplexeren Boards signalisiert man z.B. mit LEDs den Fortschritt des
Bootens, also PLL initialisiert, PLL locked, SDRAM initialisiert, etc.
Schau dir nochmal das Original des Makefiles an, das du verwendet hast.
Dort sollte crt.S in ein crt.o assembliert werden, das dann mit main.o
und den Libraries zu main.out gelinkt wird (wohl via $OBJECTS).
Gruß,
Dominic
>Hm. Wo kann ich so einen Code herbekommen, der nichts anderes macht, als>für mich den ARM zu "resetten" und in die main-Routine zu springen? Ich>werd mich damit noch auseinandersetzen (müssen) aber für den Anfang>dürfte das etwas zu komplex sein oder?
JA!
ich kann dir nur empfehlen dich an fertige beispiele zu halten (die von
martin thomas sind für den anfang schion mal sehr gut) und zuertst zu
versuchen, die einzelnen peripherie-böcke kennenzulernen. dazu findest
du auch gute beispiele auf www.atmel.com bzw. www.at91.com.
wenn du die peripherie mittels c programmierung durch hast dann kannst
du dir ja mal ansehen wie der assembler befehlssatz aussieht. auch dazu
gibt es einige gute tutorials.
und wenn du das alles durch hast dann machst du dich übe den startup
code
her.
gruss
gerhard
Hi
Ok, der Startup-Code wird eingebunden, aber es treten lustige Fehler
auf.
Aber das gefällt mich schonmal. Wenn man Fehler hat, kann man wenigstens
was machen... ;P
Ich werde mich mit der Peripherie beschäftigen - nachdem ein
Standard-Projekt funktioniert. Ich denke, dass ich nicht lernen kann,
wenn das Beispiel schon alles fix und fertig mitbringt.
Bin da vielleicht ein bisschen Dickköpfig in der Richtung. Aber ich
möchte mir das selber ein bisschen erschließen, und naja.
OK, morgen Abend gehts weiter, morgen ist HAM RADIO ;)
Bis dann, VLG, Tobi
Hi
So ganz hat mich die Sache jetzt doch nicht in Frieden gelassen, deshlab
habe ich gestern Abend noch ein bisschen Rumgebastelt.
Die Struktur des Startup-Codes ist mir soweit klar, es werden
verschiedene Vektoren an Funktionen übergeben, auch _vec_reset, in dem
der Prozessor initialisiert wird.
So weit so gut, ich habe den projektspezifischen (?) Code entfernt, und
so müsste es jetzt eigentlich funktionieren, aber der Linker kann
verschiedene Symbole nicht finden:
Linker-Script und Startup-Code müssen zusammen passen. Das ist hier
nicht der Fall. Beispiel: Das Linker-Script definiert __bss_start, der
Startup-Code benötigt _bss_start. Ich kann mir kaum vorstellen, dass die
beiden aus dem gleichen Projekt stammen.
Wo immer dein crt.s herkommt, aus dem SAM7 GPIO Beispiel jedenfalls
nicht.
> MAKE Version 5.2 Copyright (c) 1987, 2000 Borland
Und daran solltest du erkennen, dass du das falsche MAKE Tool erwischst.
> @Steven:> Sorry, aber das ist ein Piloten-Fehler... Wenn das Programm nach> Wegnehmen der Spannung nicht mehr im Speicher ist hattest du es nie im> Flash, sondern nur im RAM.> Der OpenOCD funktioniert wunderbar mit einem Wiggler, allerdings> verlangt eine GNU Toolchain mit dem OpenOCD mehr Einarbeitungszeit als> eine Lösung mit IAR/Keil/... und H-JTAG.
Ich interessiere mich da weniger für den ARM, als für die Programmer.
Für den Test habe ich mir ein kleines ARM-Board gekauft und mit der
Kickstartversion den Progranmmer mit OCD getestet. Warum der Code ins
RAM geladen wurde, ist unverständlich. Mit dem H-JTAG hat es wenigstens
ohne Probleme geklappt.
Aber irgendwie ist es leider typisch, dass eine Gnu-Toolchain viel
Einarbeitungszeit benötigt. Das muss nicht sein. Nicht der Mensch soll
sich an die Software anpassen, sondern diese sollte so geschrieben
werden, dass sie einfach zu bedienen ist. Aus diesem Grund empfehle ich
hier immer H-JTAG.
> Aber irgendwie ist es leider typisch, dass eine Gnu-Toolchain viel> Einarbeitungszeit benötigt. Das muss nicht sein. Nicht der Mensch soll> sich an die Software anpassen, sondern diese sollte so geschrieben> werden, dass sie einfach zu bedienen ist. Aus diesem Grund empfehle ich> hier immer H-JTAG.
Das sind schlichtweg unterschiedliche Philosophien. Der Großteil der GNU
Software wurde (zumindest ursprünglich) von Entwicklern für Entwickler
geschrieben, und diese Entwickler wollen möglichst direkte Kontrolle
haben. Daher darf bzw. muss bei einer GNU Toolchain der User alles
selbst machen.
Wer die GNU Toolchain nur benutzt weil diese umsonst ist, ist vermutlich
schlecht beraten. Wer aber zu schätzen weiss, dass die selbe Toolchain
von 16-bit Micros bis hinauf zu Server Architekturen skaliert, ist dann
wohl auch gerne bereit, die längere Einarbeitungszeit darin zu
investieren.
Dass dir H-JTAG und IAR EWARM einfacher zu bedienen erscheinen liegt
doch nur daran, dass du dich an diese Art Software angepasst hast. Ich
hatte verschiedene IDEs ausprobiert, inkl. IAR, Keil und Crossworks, und
während jede einzelne sicher ihre Vorzüge hat komme ich persönlich mit
den GNU Tools und einem simplen VIM als Editor deutlich schneller zu
meinem Ziel.
Gruß,
Dominic
> Daher darf bzw. muss bei einer GNU Toolchain der User alles> selbst machen.
Kommt eben drauf an, wie man die Prioritäten setzt. Ob nun die Bedienung
der Tools, die Konfiguration derselben oder das Schreiben von
irgendwelchen Skripten für die Steuerung dieser Tools hoher bewertet,
als die Programmierung des Controllers und damit die Lösung des
Problems, muss jeder selber wissen.
Ich bevorzuge Tools, die so geschrieben wurden, dass sie meine Oma
bedienen kann.
Hi
Also ich habe jetzt soweit die Dateien von (s. Link) übernommen.
Gute Nachricht: Es Funktioniert.
Ich weis nicht, es stört mich irgendwie, dass das so kompliziert ist.
Andererseits ist es ein Vorteil, wenn man die Startup-Geschichte einfach
in C ändern kann.
Frage: Bin ich mit diesem Paket jetzt All-Round abgedeckt, oder muss ich
da bei jeder Gelegenheit dran herumschrauben?
VLG Tobi