Hallo,
ich versuche gerade auf dem LM3S8962 Entwicklungs-Kit ein einfaches
Projekt (Hello World) zu erstellen und zum Laufen zu bringen. Ich habe
vorher noch nicht mit einem Cortex M3 gearbeitet, für mich ist das also
alles Neuland.
Diese Programme habe ich installiert:
- Eclipse Indigo SR1
- GNU ARM C/C++ Plugin 0.5.4.201201250003
- OpenOCD 0.5.0
- yagarto-bu-2.21_gcc-4.6.2-c-c++_nl-1.19.0_gdb-7.3.1_eabi_20111119
- StellarisWare SW-LM3S-8264
- CodeSourcery arm-2011.09-69-arm-none-eabi.exe
Ich hab von diesen Tools jeweils die aktuelle Version installiert, hoffe
ich zumindest. Zuerst hab ich es mit Yagarto getestet, den
CodeSourcery-Compiler habe erst später installiert.
OpenOCD funktioniert, die passenden USB-Treiber habe ich installiert.
Ich habe dann in Eclipse ein komplett neues Projekt erstellt und nur ein
C-File main.c erzeugt mit dem Ziel, eine LED leuchten zu lassen (s.
Anhang).
Folgende Punkte sind mir nicht klar bzw. dazu habe ich nichts gefunden:
1. Startup-Code + Linker-Script:
Es gibt beim Linker die Option -nostartfiles. Ist sinnvoll, das zu
aktivieren und einen eigenen Startup-Code zu verwenden?
Gibt es für ein Linker-Script eine Vorlage, die für das Board passt?
Ich hab zum testen aus den Beispiel-Programmen in StellarisWare die
Files "startup_gcc.c" und "hello.ld" übernommen; ist das so OK?
Das Projekt wird damit Fehlerfrei kompiliert, der Maschinencode sieht
auch plausibel aus.
2. Config-File für OpenOCD
Was muss ich da reinschreiben? Mein Config-File enthält im Moment nur
die Zeile "source [find board/ek-lm3s8962.cfg]", die Datei
ek-lm3s8962.cfg habe ich erstellt, indem ich aus OpenOCD die Datei
ek-lm3s6965.cfg kopiert habe und die Zeile "set CHIPNAME lm3s6965"
angepasst habe.
Damit kann ich immerhin den Debugger starten und das Programm im
Einzelschritt-Modus duchsteppen.
Allerdings geht die LED an PORTF.0 nicht an, irgendwie hab ich das
Gefühl, dass gar nichts in die entsprechenden Register geschrieben wird.
3. Zugriff aus Debugger direkt auf GPIO-Register
Die Register für PORTF liegen bei 0x4002500, wenn ich im Debugger mit
Memory-View diesen Bereich anschau, dann steht da überall 0 drin, obwohl
das Programm dort etwas reinschreiben müsste.
Wenn ich versuche, von Hand dort etwas reinzuschreiben, kommt eine
Fehlermeldung ("Error writing memory block").
Mit OpenOCD direkt kann ich auf diesen Speicherbereich auch nicht
zugreifen (z.B. mit "MDW"), vermutlich liegt das am Config-File. Muss
man da für den Bereich oberhalb von 0x40000000 etwas eintragen?
4. Unterschiede Yagarto / CodeSourcery Compiler
Nachdem es mit Yagarto nicht so richtig funktioniert hatte, hab ich den
CodeSourcery-Compiler installiert. Damit konnte ich mein Projekt auch
kompilieren und debuggen.
Dabei ist mir aufgefallen, dass beim Debuggen mit CodeSourcery alles
deutlich schneller geht.
Im "Console"-Fenster kommt dabei aber laufend diese Fehlermeldung:
"warning: RMT ERROR : failed to get remote thread list."
Welche Toolchain ist denn nach euren Erfahrungen besser geignet?
Johannes E. schrieb:> Es gibt beim Linker die Option -nostartfiles. Ist sinnvoll, das zu> aktivieren und einen eigenen Startup-Code zu verwenden?
Im allgemeinen ja, insbesondere dann, wenn der HW-Lieferant welche zu
seinen Beispielen beilegt.
Johannes E. schrieb:> Ich hab zum testen aus den Beispiel-Programmen in StellarisWare die> Files "startup_gcc.c" und "hello.ld" übernommen; ist das so OK?
Knapp, aber sollten ausreichen. Für C++ reicht es nicht.
Johannes E. schrieb:> Allerdings geht die LED an PORTF.0 nicht an, irgendwie hab ich das> Gefühl, dass gar nichts in die entsprechenden Register geschrieben wird.
Ich kenne die TI CM3s nicht.
Aber: Im Hauptprogramm gibt es keine Verzögerung zwischen der
Umschalterei, so es denn überhaupt eine ist.
- Was sollen die drei Zuweisungen vor while machen?
- Einfach mal eine "busy loop" einbauen: eine "for loop" mit "volatile"
Variable oder einem asm("nop") im Körper.
- Muss man irgendwelche Clocks für die Peripherie aktivieren?
Hallo Roland,
danke für deine schnelle Antwort.
Roland H. schrieb:> ber: Im Hauptprogramm gibt es keine Verzögerung zwischen der> Umschalterei, so es denn überhaupt eine ist.
Ich hab versucht, das Programm im Einzelschrittmodus durchzusteppen. Da
sollten die Delays eigentlich nicht notwendig sein.
> - Was sollen die drei Zuweisungen vor while machen?
GPIO_PORTF_DIR_R = 1; -> Direction auf Output schalten
GPIO_PORTF_DEN_R = 1; -> Digital Enable
GPIO_PORTF_DATA_R = 1; -> Ausgang setzen
> - Einfach mal eine "busy loop" einbauen: eine "for loop" mit "volatile"> Variable oder einem asm("nop") im Körper.
werde ich mal testen.
> - Muss man irgendwelche Clocks für die Peripherie aktivieren?
Das habe ich mir auch schon überlegt, hab dazu aber nichts im Datenblatt
des Controllers gefunden...
Die LED blinkt jetzt, es war tatsächlich ein Takt. Im Register RCGC2
muss dazu das passende Bit für PortF gesetzt werden:
SYSCTL_RCGC2_R = SYSCTL_RCGC2_GPIOF;
Ich habe aber trotzdem noch das Problem, dass debuggen mit der
Yagarto-Toolchain sehr langsam ist; mit CodeSourcery kommen ständig die
Fehlermeldungen.
Außerdem hängt sich der gdb beim Beenden des Debuggers ("Run" ->
"Terminate") immer auf; ich muss dann jedesmal den GDB und OpenOCD im
Tastkamanger noch extra beenden.
Tritt dieses Problem nur bei mir auf oder ist das bei anderen auch so?
Johannes E. schrieb:> Die LED blinkt jetzt, es war tatsächlich ein Takt.
Das ist doch schon einmal etwas. Könntest Du bitte die korrigierte
Version (mit busy loop), die auch ohne Debugger richtig funktioniert,
bitte anhängen?
Bitte ggf. auch die Optionen für Compiler/Linker.
Johannes E. schrieb:> Ich habe aber trotzdem noch das Problem, dass debuggen mit der> Yagarto-Toolchain sehr langsam ist; mit CodeSourcery kommen ständig die> Fehlermeldungen.>> Außerdem hängt sich der gdb beim Beenden des Debuggers ("Run" ->> "Terminate") immer auf; ich muss dann jedesmal den GDB und OpenOCD im> Tastkamanger noch extra beenden.
Ich verwende OpenOCD nur zusammen mit einem lpc2103 und dort auch nur
ohne Eclipse. Insofern nur ein paar Ideen:
- Funktioniert das Debuggeon ohne Eclipse?
- Kommen sich die beiden Tool chains ins Gehege? Beide im Pfad? Haben
die verschiedene Namen oder hören beide auf den Namen
"arm-none-eabi-gdb"?
- Welche Versionen spucken die beiden GDBs aus?
Ich würde mal eine der beiden "tool chains" deinstallieren.
Roland H. schrieb:> Könntest Du bitte die korrigierte Version (mit busy loop), die auch> ohne Debugger richtig funktioniert, bitte anhängen?> Bitte ggf. auch die Optionen für Compiler/Linker.
Ich hab vom kompleten Projekt ein Zip-File gemacht.
Hier ist der Output vom Build-Prozess, da sieht man die
Compiler-/Linker-Optionen:
> - Funktioniert das Debuggeon ohne Eclipse?
Hab ich noch nicht getestet; weiß auch nicht so richtig, wie das
funktioniert.
> - Kommen sich die beiden Tool chains ins Gehege? Beide im Pfad? Haben> die verschiedene Namen oder hören beide auf den Namen> "arm-none-eabi-gdb"?
Ich habe jeweils nur eine Toolchain (wechselweise) im Pfad, beiden hören
auf "arm-none-eabi-...".
> - Welche Versionen spucken die beiden GDBs aus?
CodeSourcery:
GNU gdb (Sourcery CodeBench Lite 2011.09-69) 7.2.50.20100908-cvs
Yagarto:
GNU gdb (GDB) 7.3.1
> Ich würde mal eine der beiden "tool chains" deinstallieren.
Am Anfang hatte ich nur Yagarto alleine installiert, da war es genau
gleich. Ich bin mir schon relativ sicher, dass sich da nichts
gegenseitig stört.
Danke für das neue Projekt.
> Ich habe jeweils nur eine Toolchain (wechselweise) im Pfad, beiden hören> auf "arm-none-eabi-...".
Irgendwie würde mir das nicht behagen. Nicht dass sich da in den
Untiefen von Eclipse irgendetwas verheddert.
Warum hat es eigentlich mit Yagarto nicht richtig funktioniert?
>> - Funktioniert das Debuggeon ohne Eclipse?> Hab ich noch nicht getestet; weiß auch nicht so richtig, wie das> funktioniert.
Je nach Backend etwas verschieden, z. B. so:
> Warum hat es eigentlich mit Yagarto nicht richtig funktioniert?
Es hat schon funktioniert, allerdings war debuggen mit Yagarto extrem
langsam.
>>> - Funktioniert das Debuggeon ohne Eclipse?
...
Ich hab das mittlerweile getestet:
Mit CodeSourcery-GDB aus der Kommandozeile funktioninert das debuggen
ganz gut.
Beim Yagarto-GDB kommt nach dem Kommando
1
target remote localhost:3333
folgende Fehlermeldung:
1
Remote 'g' packet reply is too long: 1f3038ec0100000046c6ce00a66969eb40089bb40090001846014f8978ff0020e4002c44605956b9920140b0020247990101010178ff0020750c0000310b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000061
Aus Eclipse heraus funktioniert es mit beiden GDB-Varianten, nur kommen
mit dem CodeSourcery-GDB ständig die Fehlermeldungen mit der thread
list.
Wenn ich direkt im GDB das Kommando "info threads" eintippe, kommt die
gleiche Fehlermeldung.
> Vermutlich liegt das Problem eher daran:> http://old.nabble.com/RMT-ERROR-:-failed-to-get-remote-thread-list-td12776709.html> Zitat:> [code]> If you are using a JTAG device to talk to your target, it probably> does not support threads. However, it looks like it is not correctly> reporting that it does not support threads.
Danke, der Hinweis trifft es ganz gut. Ist das also ein Fehler in
OpenOCD? Komisch ist allerdings, dass mit dem Yagarto-GDB die
Fehlermeldung nicht kommt.
In meinem Testprojekt hab ich als nächstes Versucht, eine
sprintf-Anweisung zu verwenden. Dabei kam dann die Fehlermeldung:
"undefined reference to `_sbrk'"
Mit etwas googeln und Studium der Linker-Script-Doku hab ich dafür eine
Lösung gefunden. Ich hab dazu die Funktion _sbrk in meinen Startup-Code
eingebaut, außerdem hab ich Änderungen am Linker-Script gemacht.
@Roland:
Kannst Du dir mal das Linker-Script (Print.ld) und startup_gcc.c
anschauen? Hab ich die Stackpointer-Initialisierung und Definition des
Heaps so richtig gemacht? Ist das die übliche Vorgehensweise oder wird
das normalerweise irgendwie anders gemacht?
> Was kommt, wenn Du> stattdessen>>target extended localhost:3333> benutzt?
Damit kommt:
1
(gdb) target extended localhost:3333
2
Remote debugging using localhost:3333
3
Remote 'g' packet reply is too long: 62144800370000000000000000000000000899b40890009846014f89bcff0020e4002c60205b56b9120140b0020247d901010101bcff0020a9100000f50900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000061
Johannes E. schrieb:> In meinem Testprojekt hab ich als nächstes Versucht, eine> sprintf-Anweisung zu verwenden.
Wenn schon, dann besser snprintf.
Johannes E. schrieb:> Dabei kam dann die Fehlermeldung:> "undefined reference to `_sbrk'"
Ich setze weder newlib noch Heap ein. Deine Implementierung für _sbrk
erscheint plausibel.
Ich würde mir dennoch überlegen, ob das Sinn macht. Es erscheint mir
etwas übertrieben, für ein snprintf eine Heap-Verwaltung zu
implementieren. Es wird alles etwas weniger deterministisch.
Zum "linker script": Warum ziehst Du von _stack 4 Byte ab? Was ist in
diesen 4 Byte?
Probier doch mal
Hallo Roland,
danke dafür, dass du dir meinen Code angeschaut hast.
> Ich würde mir dennoch überlegen, ob das Sinn macht. Es erscheint mir> etwas übertrieben, für ein snprintf eine Heap-Verwaltung zu> implementieren. Es wird alles etwas weniger deterministisch.
Ob ich printf später in meinem Projekt verwende, weiß ich noch nicht.
Aber es sollte schon funktionieren, falls man es mal braucht. Außerdem
hab ich einiges dabei dazu gelernt.
> Zum "linker script": Warum ziehst Du von _stack 4 Byte ab? Was ist in> diesen 4 Byte?
Stimmt eigentlich, der Stackpointer zeigt ja nicht auf eine freie
Speicherstelle sondern auf das letzte gespeicherte Datenwort; neue Daten
werden also an die nächste Speicherstelle darunter "gepusht".
Ich hab das in irgend einem Beispiel-Linker-Script so gesehen und
übernommen; für mich hat es plausibel ausgesehen...