Ich habe mir für OpenOCD einen "Olimex ARM-USB-OCD-H" JTAG-Adapter
zugelegt und brauche für die ersten Schritte etwas Hilfe.
Die für Windows compilierte Version 0.10.0 von OpenOCD habe ich mir hier
besorgt: http://www.freddiechopin.info/en/download/category/4-openocd
Als Treiber nutze ich den ZADIG Universal USB. Ging unter Windows 10
problemlos (was bei Windows 10 ja schon echt was bedeutet ;-))
Liegt eine Datei namens "openocd.cfg" im gleichen Ordner in dem man die
EXE startet, wird diese standardmäßig eingelesen und abgearbeitet. Die
Syntax ist "abgespecktes" TCL. Hier habe ich zunächst das
Interface-Script für den Olimex-Adapter geladen:
Als nächstes geht es an das zu untersuchende Ziel. In meinem Fall soll
es ein OMAP5948 sein (vom Aufbau her wohl ähnlich wie ein OMAP5912). Das
ist ja ein SOC, also nicht bloß eine CPU. Daher stellt sich mir hier
schon die Frage ob ich dafür nun ein "board-script" oder ein
"target-script" erstellen sollte?
Das Board an das ich mich per JTAG verbinde hat an dem JTAG-Port nur
diesen OMAP, sonst nichts. Aus meiner sicht ist das eher ein Target.
Unterm Strich sollte es für die Funktion egal sein, geht mir mehr darum
das Prinzip zu verinnerlichen. Jedenfalls habe ich für den OMAP ein
Script erstellt und in die openocd.cfg eingefügt:
Ob das alles so stimmt weiss ich nicht... das habe ich mir aufgrund
anderer Beispielskripte zusammengereimt. "Arbeiten" will ich ja
eigentlich nur mit der CPU, sprich diese anhalten, Watchdogs stoppen und
auf Register bzw. das externe RAM/Flash zugreifen. Daher dachte ich ist
es ausreichend nur die CPU als Target zu erstellen.
Nun muss ich wohl auch noch irgendwie sagen mit welcher Taktfrequenz
über JTAG kommuniziert werden kann und wie OpenOCD die Statemachine des
TAP resettet. Bei dem Teil komm ich grad nicht mehr klar... wo und wie
mache ich das? Woher weiss ich wie schnell es der TAP mag?
Welche Fehlermeldung spuckt denn OpenOCD aus? OpenOCD ist zu Anfang mit
einigem Trail&Error verbunden.
Hint: "-d3" Parameter beim Start übergeben. Dann erschlägt es einen zwar
mit Log Meldungen, aber man findet so Fehler schneller. Per Default
teilt OpenOCD nicht wirklich mit was schief ging.
Hier mal mein aktuelles openocd.cfg Skript. Ich habe zunächst die
Targetspezifischen Befehle einfach mit dort reingepackt. Wenn das mal
alles läuft würde ich das dann in ein Target-Scriptfile überführen.
Ich kommentiere mal über der jeweiligen Codezeile was ich denke was es
tun soll. Einige Daten die ich verwende habe ich "geklaut" bzw. geraten.
Sicher gibt es bei OpenOCD, ähnlich wie beim J-Link von Segger, auch
eine Möglichkeit des Autodetect. Die habe ich aber noch nicht
gefunden...
openocd.cfg:
# Ob es das braucht weiss ich nicht, hab ich so aus anderen Skripten übernommen
5
adapter_nsrst_delay 100
6
7
# Laut TAP-Detect vom Segger (siehe unten) so hoffentlich richtig übernommen. Hier wird jeweils ein TAP definiert, mit Namen ("omap5948"), Typ ("arm"), länge des IR-Registers in der Scanchain und erwartetem ID-Code bei Abfrage. Die Reihenfolge muss der Reihenfolge der TAPs in der Scanchain entsprechen
# Nun definiere ich eine Variable namens _TARGETNAME die bestimmt womit der OpenOCD arbeiten soll, wenn mehrere TAPs vorhanden sind. Ich entscheide mich für die ARM9-CPU
13
set _TARGETNAME omap5948.arm
14
15
# Das Target wird erstellt und ist vom Typ "arm926ejs". Little-Endian muss man wohl nicht angeben, mache ich nur sicherheitshalber. Die Position in der Chain wird ebenfalls angegeben
16
target create $_TARGETNAME arm926ejs -endian little -chain-position $_TARGETNAME
17
# Theoretisch müsste man das auch so schreiben können, ohne Variable:
18
# target create omap5948.arm arm926ejs -endian little -chain-position omap5948.arm
19
20
# Hier wähle ich explizit das JTAG-Protokoll für die Schnittstelle des Adapters, denn er kennt auch SWD
21
transport select jtag
22
23
# Ich weiss das das RTCK-Signal vom OMAP unterstützt wird, daher habe ich es angegeben. Die "4" (steht für 4 MHz Takt) wird wohl nur verwendet, wenn RTCK doch nicht funktioniert und ein statischer Takt benötigt wird
24
jtag_rclk 4
25
26
# Das muss ich wohl so machen, keine Ahnung warum
27
init
28
reset_config trst_only
29
reset
So, dabei kommt zunächst mal dieses Ergebnis beim Aufruf von openocd.exe
ohne weitere Parameter:
1
C:\Program Files (x86)\openocd>openocd
2
Open On-Chip Debugger 0.10.0-rc2
3
Licensed under GNU GPL v2
4
For bug reports, read
5
http://openocd.org/doc/doxygen/bugs.html
6
adapter_nsrst_delay: 100
7
Info : auto-selecting first available session transport "jtag". To override use 'transport select <transport>'.
in procedure 'reset' called at file "openocd.cfg", line 17
24
in procedure 'ocd_bouncer'
Das ausführliche Log (-d3) habe ich angehangen, damit es nicht zu lang
wird im Text.
Sieht ja anfänglich nicht sooo schlecht aus, oder? Warum er die 34 Bit
IR-Länge vom DSP anmostert ist mir etwas unklar, scheint aber nur ein
Hinweis zu sein.
JTAG und Adaptive Taktung hat er wohl soweit erkannt. Dann findet er
auch den DSP (C55x) und die CPU (ARM9).
Beim ICE (Debug-Controller?!) tut er sich etwas schwer, keine Ahnung
warum. Für mich sieht es so aus als würde er von diesem TAP keinen
IDCODE erhalten, so wie er es für den DSP und die CPU konnte. Woran
könnte das liegen? Stimmt evtl. die IR-Len nicht? Oder muss der ICE
durch irgendein Hardware-Wunder (Pin) erst aktiviert werden?
Warum er dann etwas später den ICE scheinbar doch noch erkennt ist mir
ein Rätsel! Womöglich erfolgt diese Ausgabe auch nur aufgrund meiner
Vorgabe beim definieren des TAP-Device?
"trst_only separate trst_push_pull" bedeutet doch wohl, das ich durch
das Kommando "reset_config trst_only" dafür sorge, das der
TAP-Controller-RESET rein über das Pin-Signal /TRST erfolgt und nicht
über "Software" (die berühmte 5 '1'en Folge), richtig?
Und "push_pull" das er sowohl das HIGH als auch das LOW-Signal aktiv
treibt. Manche TAPs benötigen einen externen Pullup auf dem Pin. Beim
OMAP glaube ich, ist der intern. Kann aber wohl auch nicht schaden?
So und dann kommt das große Problem "Error: omap5948.arm: how to
reset?". Tja, wie soll er das denn machen? Und warum überhaupt? Er soll
die CPU doch garnicht resetten, höchstens initialisieren und später dann
auch mal anhalten oder sowas.
Hmm... wer weiß Rat?
jtag newtap $_CHIPNAME arm -irlen 4 -expected-id $_CPUTAPID
6
jtag newtap $_CHIPNAME unknown -irlen 8
Der OMAP5948 soll nahezu identisch mit dem OMAP5912 sein, also habe ich
einfach mal diese IR-Len Werte übernommen und siehe da, plötzlich findet
er auch den ICE:
1
C:\Program Files (x86)\openocd>openocd
2
Open On-Chip Debugger 0.10.0-rc2
3
Licensed under GNU GPL v2
4
For bug reports, read
5
http://openocd.org/doc/doxygen/bugs.html
6
adapter_nsrst_delay: 100
7
Info : auto-selecting first available session transport "jtag". To override use 'transport select <transport>'.
+ + + NACHTRAG 2 + + +
Wenn ich es richtig verstanden hab, funktioniert das Autoprobing so, das
man eben nur ein Interface-Script aber kein Target/Board-Script angibt.
Dann versucht OpenOCD die TAPs selbst zu identifizieren. Das habe ich
mit folgendem Inhalt des openocd.cfg ausprobiert:
1
# load the interface script for the Olimex ARM-USB-OCD-H probe, connected to USB
Warn : AUTO auto0.tap - use "jtag newtap auto0 tap -irlen 7 -expected-id 0x031f3d81"
15
Warn : AUTO auto1.tap - use "jtag newtap auto1 tap -irlen 2 -expected-id 0x0692602f"
16
Error: auto1.tap: IR capture error; saw 0x0003 not 0x0001
17
Warn : Bypassing JTAG setup events due to errors
18
Warn : gdb services need one or more targets defined
Die gefundenen TAPs entsprechen denen die ich einen Post zuvor auch
ermittelt hab. Lediglich die IR-Lens kann er nicht richtig bestimmen,
wodurch auch der nachfolgende Error produziert wird.
Aber anscheinend liege ich mit den ID-Codes und IR-Lens oben doch schon
ziehmlich richtig.
Als nächstes müsste ich dann einen Weg finden dieses INIT und RESET
richtig hin zu bekommen...
Jim M. schrieb:> RCLK würde ich auch erstmal weglassen und so> 100kHz Frequenz zwecks Test einstellen. Kann man später hochdrehen.
Also anstelle "jtag_rclk 8" dann "adapter_khz 100". Kann ich ja anfangs
so machen.
> Mach mal aus dem "reset" ein "reset init".
Ich glaube hier gibt es folgende Optionen: "reset", "reset halt", "reset
init". Diese beeinflussen das Verhalten und die Verwendung der Signale
SRST und TRST.
Das SRST-Signal soll doch, sofern verfügbar, das ganze Board resetten.
Somit könnte ich dann via OpenOCD für einen definierten Ausgangszustand
sorgen. Verstehe ich das so richtig?
Das JTAG-Resetsignal TRST setzt ja via Hardware (Pin) den Zustand des
JTAG-TAP zurück.
Wenn ich "reset init" richtig verstanden habe, dann würde OpenOCD
zunächst SRST auf low halten um die CPU oder das Board in einem
RESET-Zustand zu halten und dann kurz mit TRST den JTAG-TAP
initialisieren und nachfolgend alles tun um eine "saubere und schnelle"
Kommunikation mit z.B. einem Debugger vorzubereiten. Nachdem er dann
SRST wieder hochnimmt könnte man quasi vor dem ersten Reset-Vector
bereits debuggen.
So gesehen hatte ich meinen "reset" und kein "reset init" oder "reset
halt" genommen. Probiere es aber gern mal aus. Auch würde ich schauen ob
ich SRST nutzen kann, wär schon eine sinnvolle Sache.
Das Timing und die Dauer der Reset-Signale ist wohl ebenfalls von
Bedeutung. Dies wird wohl über "adapter_nsrst_*" und "jtag_ntrst_*"
Befehle gesteuert.
>
1
> reset_config trst_only
2
>
> Hast Du das TRST Signal verbunden?
Ja, wie ich schrieb ist das Signal am OMAP-TAP vorhanden und verbunden.
> Ansonsten nehme ich gerne zum Testen:>
1
> reset_config none
2
>
Probiere ich mal. Das bedeutet dann ja, das weder SRST noch TRST per
Hardware genutzt werden, richtig?