Forum: Mikrocontroller und Digitale Elektronik Hilfe beim Einsatz von OpenOCD benötigt


von Olli Z. (z80freak)


Lesenswert?

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:
1
source [find ../scripts/interface/ftdi/olimex-arm-usb-ocd-h.cfg]

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:
1
source [find ../scripts/interface/ftdi/olimex-arm-usb-ocd-h.cfg]
2
source [find ../scripts/target/omap5948.cfg]

Das "omap5948.cfg" script enthält bislang lediglich "newtap" Befehle für 
die einzelnen Komponenten des Ziels, sowie den Targetnamen:
1
jtag newtap omap5948 dsp -irlen 34 -expected-id 0x031f3d81
2
jtag newtap omap5948 arm -irlen 4  -expected-id 0x0692602F
3
# Hier bin ich mir unsicher:
4
#jtag newtap omap5948 ice -irlen 12 -expected-id 0x00000001
5
jtag newtap omap5948 ice -irlen 12 -expected-id 0x2008f02f
6
7
set _TARGETNAME omap5948.arm
8
target create $_TARGETNAME arm926ejs -chain-position $_TARGETNAME

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?

von Jim M. (turboj)


Lesenswert?

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.

von Olli Z. (z80freak)


Angehängte Dateien:

Lesenswert?

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:
1
# Adapter Skript für den Olimex laden
2
source [find scripts/interface/ftdi/olimex-arm-usb-ocd-h.cfg]
3
4
# 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
8
jtag newtap omap5948 dsp -irlen 34 -expected-id 0x031f3d81
9
jtag newtap omap5948 arm -irlen 4  -expected-id 0x0692602F
10
jtag newtap omap5948 ice -irlen 12 -expected-id 0x2008f02f
11
12
# 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>'.
8
Warn : omap5948.dsp: huge IR length 34
9
Warn : Transport "jtag" was already selected
10
RCLK - adaptive
11
Info : RCLK (adaptive clock speed)
12
Info : JTAG tap: omap5948.dsp tap/device found: 0x031f3d81 (mfg: 0x6c0 (<unknown>), part: 0x31f3, ver: 0x0)
13
Info : JTAG tap: omap5948.arm tap/device found: 0x0692602f (mfg: 0x017 (Texas Instruments), part: 0x6926, ver: 0x0)
14
Info : TAP omap5948.ice does not have IDCODE
15
Info : Embedded ICE version 0
16
Error: unknown EmbeddedICE version (comms ctrl: 0x018e9ec0)
17
Info : omap5948.arm: hardware has 2 breakpoint/watchpoint units
18
trst_only separate trst_push_pull
19
Info : JTAG tap: omap5948.dsp tap/device found: 0x031f3d81 (mfg: 0x6c0 (<unknown>), part: 0x31f3, ver: 0x0)
20
Info : JTAG tap: omap5948.arm tap/device found: 0x0692602f (mfg: 0x017 (Texas Instruments), part: 0x6926, ver: 0x0)
21
Info : JTAG tap: omap5948.ice tap/device found: 0x2008f02f (mfg: 0x017 (Texas Instruments), part: 0x008f, ver: 0x2)
22
Error: omap5948.arm: how to reset?
23
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?

von Olli Z. (z80freak)


Lesenswert?

+ + + Nachtrag + + +

Ich habe mir mal das beim openocd beiligende Skript "omap5912.cfg" 
angeschaut. Dort werden die TAPs wie folgt definiert:
1
# NOTE: presumes irlen 38 is the C55x DSP, matching BSDL for
2
# its standalone siblings (like TMS320VC5502) of the same era
3
4
jtag newtap $_CHIPNAME dsp -irlen 38 -expected-id 0x03df1d81
5
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>'.
8
Warn : omap5948.dsp: huge IR length 38
9
Warn : Transport "jtag" was already selected
10
RCLK - adaptive
11
Info : RCLK (adaptive clock speed)
12
Info : JTAG tap: omap5948.dsp tap/device found: 0x031f3d81 (mfg: 0x6c0 (<unknown>), part: 0x31f3, ver: 0x0)
13
Info : JTAG tap: omap5948.arm tap/device found: 0x0692602f (mfg: 0x017 (Texas Instruments), part: 0x6926, ver: 0x0)
14
Info : JTAG tap: omap5948.ice tap/device found: 0x2008f02f (mfg: 0x017 (Texas Instruments), part: 0x008f, ver: 0x2)
15
Info : Embedded ICE version 6
16
Info : omap5948.arm: hardware has 2 breakpoint/watchpoint units
17
trst_only separate trst_push_pull
18
Info : JTAG tap: omap5948.dsp tap/device found: 0x031f3d81 (mfg: 0x6c0 (<unknown>), part: 0x31f3, ver: 0x0)
19
Info : JTAG tap: omap5948.arm tap/device found: 0x0692602f (mfg: 0x017 (Texas Instruments), part: 0x6926, ver: 0x0)
20
Info : JTAG tap: omap5948.ice tap/device found: 0x2008f02f (mfg: 0x017 (Texas Instruments), part: 0x008f, ver: 0x2)
21
Error: omap5948.arm: how to reset?
22
in procedure 'reset' called at file "openocd.cfg", line 22
23
in procedure 'ocd_bouncer'

Was mich wundert ist, das der Segger J-Link über seine 
Autodetect-Funktion folgendes erkannt hat:
1
TotalIRLen = 50, IRPrint = 0x001444031F3D81
2
JTAG chain detection found 3 devices:
3
 #0 Id: 0x031F3D81, IRLen: 34, Unknown device
4
 #1 Id: 0x0692602F, IRLen: 04, ARM9TDMI Core
5
 #2 Id: 0x00000001, IRLen: 12, Unknown device
Dann liegt der Segger hier wohl einfach falsch, nicht wahr? Und ich habe 
diesen Fehler einfach übernommen ("geklaut") und jetzt stimmt es wohl.

von Olli Z. (z80freak)


Lesenswert?

+ + + 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
2
source [find scripts/interface/ftdi/olimex-arm-usb-ocd-h.cfg]
3
4
reset_config trst_and_srst
5
jtag_rclk 8

Heraus kam dies hier:
1
C:\Program Files (x86)\openocd>openocd -f openocd_autoprobe.cfg
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
trst_and_srst separate srst_gates_jtag trst_push_pull srst_open_drain connect_deassert_srst
7
Info : auto-selecting first available session transport "jtag". To override use 'transport select <transport>'.
8
RCLK - adaptive
9
Info : RCLK (adaptive clock speed)
10
Warn : There are no enabled taps.  AUTO PROBING MIGHT NOT WORK!!
11
Info : JTAG tap: auto0.tap tap/device found: 0x031f3d81 (mfg: 0x6c0 (<unknown>), part: 0x31f3, ver: 0x0)
12
Info : JTAG tap: auto1.tap tap/device found: 0x0692602f (mfg: 0x017 (Texas Instruments), part: 0x6926, ver: 0x0)
13
Info : JTAG tap: auto2.tap tap/device found: 0x2008f02f (mfg: 0x017 (Texas Instruments), part: 0x008f, ver: 0x2)
14
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...

von Jim M. (turboj)


Lesenswert?

Mach mal aus dem "reset" ein "reset init".


Außerdem:
1
reset_config trst_only

Hast Du das TRST Signal verbunden? Ansonsten nehme ich gerne zum Testen:
1
reset_config none


.. allerdings auf Cortex-M. RCLK würde ich auch erstmal weglassen und so 
100kHz Frequenz zwecks Test einstellen. Kann man später hochdrehen.

von Olli Z. (z80freak)


Lesenswert?

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?

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.