Forum: Mikrocontroller und Digitale Elektronik Probleme/Fragen mit Stellaris 3S8962, OpenOCD, Debugger


von Johannes E. (cpt_nemo)


Lesenswert?

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?

von Johannes E. (cpt_nemo)


Angehängte Dateien:

Lesenswert?

Hier ist noch mein Test-Projekt als Zip-File.

von Roland H. (batchman)


Lesenswert?

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?

von Johannes E. (cpt_nemo)


Lesenswert?

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...

von Johannes E. (cpt_nemo)


Lesenswert?

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?

von Roland H. (batchman)


Lesenswert?

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.

von Johannes E. (cpt_nemo)


Angehängte Dateien:

Lesenswert?

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:
1
cs-make all 
2
Building file: ../main.c
3
Invoking: ARM Sourcery Windows GCC C Compiler
4
arm-none-eabi-gcc -I"D:\Arm\StellarisWare" -O0 -Wall -Wa,-adhlns="main.o.lst" -c -fmessage-length=0 -MMD -MP -MF"main.d" -MT"main.d" -mcpu=cortex-m3 -mthumb -g3 -gdwarf-2 -o "main.o" "../main.c"
5
Finished building: ../main.c
6
 
7
Building file: ../startup_gcc.c
8
Invoking: ARM Sourcery Windows GCC C Compiler
9
arm-none-eabi-gcc -I"D:\Arm\StellarisWare" -O0 -Wall -Wa,-adhlns="startup_gcc.o.lst" -c -fmessage-length=0 -MMD -MP -MF"startup_gcc.d" -MT"startup_gcc.d" -mcpu=cortex-m3 -mthumb -g3 -gdwarf-2 -o "startup_gcc.o" "../startup_gcc.c"
10
Finished building: ../startup_gcc.c
11
 
12
Building target: Hello1.elf
13
Invoking: ARM Sourcery Windows GCC C Linker
14
arm-none-eabi-gcc -T"E:\ARM_Indigo\Hello1\Hello.ld" -nostartfiles -Wl,-Map,Hello1.map -mcpu=cortex-m3 -mthumb -g3 -gdwarf-2 -o "Hello1.elf"  ./main.o ./startup_gcc.o   
15
Finished building target: Hello1.elf

> - 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.

von Roland H. (batchman)


Lesenswert?

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:
1
arm-none-eabi-gdb
2
3
(gdb) target remote localhost:3333
4
Remote debugging using localhost:3333

Nur um zu erkennen, ob die Problem bei Eclipse oder zwischen gdb und 
OpenOCD liegen.

Vermutlich liegt das Problem eher daran: 
http://old.nabble.com/RMT-ERROR-:-failed-to-get-remote-thread-list-td12776709.html
Zitat:
1
If you are using a JTAG device to talk to your target, it probably
2
does not support threads.  However, it looks like it is not correctly
3
reporting that it does not support threads.
4
5
Compare the remote protocol manual with what OpenOCD is doing, and
6
change OpenOCD's behavior to correctly report unsupported commands.
7
8
-- 
9
Daniel Jacobowitz
10
CodeSourcery

Aber da habe ich keine Aktien mehr ;-)

von Johannes E. (cpt_nemo)


Angehängte Dateien:

Lesenswert?

> 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?

von schrumpfkopf (Gast)


Lesenswert?

> target remote localhost:3333

Was kommt, wenn Du

stattdessen

>target extended localhost:3333


benutzt?

von Johannes E. (cpt_nemo)


Lesenswert?

> 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

von Roland H. (batchman)


Lesenswert?

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
1
_stack = ORIGIN(SRAM) + LENGTH(SRAM);

von Johannes E. (cpt_nemo)


Lesenswert?

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...

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.