Forum: Mikrocontroller und Digitale Elektronik STM32MP1 und U-Boot standalone app: "Undefined instruction"


von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Ich versuche gerade, auf einem STM32MP157 die "hello_world" standalone 
App vom U-Boot zum Laufen zu bringen. Ich habe schon rausgefunden, dass 
die Standardumgebung auf eine völlig falsche Startadresse 
(CONFIG_STANDALONE_LOAD_ADDR) gelinkt hat (0xc100000), weil das einfach 
mal der Fallback für "irgendein ARM, der nirgends genannt worden ist" 
war. Das wurde korrigiert, die Adresse steht jetzt auf etwas, wo es auf 
jeden Fall RAM gibt.

Trotzdem jedoch, wenn ich die App starten will, bekomme ich ein 
"undefined instruction", und die Kiste rebootet.

Disassemble:
1
Disassembly of section .text:
2
3
c4600000 <hello_world>:
4
c4600000:       e92d 41f0       stmdb   sp!, {r4, r5, r6, r7, r8, lr}
5
c4600004:       4605            mov     r5, r0
6
c4600006:       4608            mov     r0, r1
7
c4600008:       460e            mov     r6, r1
8
c460000a:       f000 f8c3       bl      c4600194 <app_startup>
9

Aisschrift (Laden Binary via Kermit, dann starten):
1
CACHE: Misaligned operation at range [c4600000, c460023a]
2
## Total Size      = 0x0000023a = 570 Bytes
3
## Start Addr      = 0xC4600000
4
STM32MP> go $standalone_load_addr hi there
5
## Starting application at 0xC4600000 ...
6
undefined instruction
7
pc : [<c4600008>]          lr : [<d9f3c7a3>]
8
reloc pc : [<aa7ca008>]    lr : [<c01067a3>]
9
sp : d7df04c8  ip : 00000000     fp : 00000000
10
r10: 00000004  r9 : d7dffec0     r8 : d9fe35b4
11
r7 : d9f560b1  r6 : 00000004     r5 : c4600000  r4 : d7f34b74
12
r3 : c4600000  r2 : d7f34b74     r1 : d7f34b74  r0 : 00000003
13
Flags: nzCv  IRQs off  FIQs off  Mode SVC_32
14
Code: a7f4ebf7 5a4ffc5b 41f0e92d 46084605 (f000460e) 
15
Resetting CPU ...

Der geladene Code steht selbst nach dem Reboot noch da, also korrekt im 
RAM scheint er schon angekommen zu sein:
1
STM32MP> md $standalone_load_addr 10
2
c4600000: 41f0e92d 46084605 f000460e 2109f8c3    -..A.F.F.F.....!
3
c4600010: f0004817 f000f851 4601f83b f0004815    .H..Q...;..F.H..
4
c4600020: 4815f84b f848f000 48144629 f844f000    K..H..H.)F.H..D.
5
c4600030: 4f132400 8054f8df dd0e42ac f0004811    .$.O..T..B...H..

Die standalone app wird im Rahmen eines normalen U-Boot-Buildprozesses 
(in diesem Falle ein bitbake eines Yocto) angeschoben; die 
Compileroptionen für U-Boot selbst und für die standalone app sind die 
gleichen.

Hat jemand irgendeine Idee?

von Mw E. (Firma: fritzler-avr.de) (fritzler)


Lesenswert?

Könnts sein, dass der Cortex-A7 im ARM statt Thumb Modus läuft?
Leider zeigt dein uboot das CPSR nicht an.
Aber da der PC c4600008 ist undnicht c4600009 gehe ich vom ARM Modus aus 
(im Thumb Mode ist das LSB des PC immer 1).
Dann sieht er:
e92d41f0
46054608 <- rumms
460ef000 <- er zeigt hierhin, weil bei einer undef instr bereits der 
PC+4 ist (pipelining ;))

Eigentlich müsst dir auch schon das stmdb um die Ohren fliegen.
Der SP sieht komisch aus, is da RAM?

: Bearbeitet durch User
von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Mw E. schrieb:
> Könnts sein, dass der Cortex-A7 im ARM statt Thumb Modus läuft?

Da die standalone App ja im Kontext des U-Boots selbst läuft (und das 
Buildsystem sie genau so produziert hat), vermute ich mal, dass U-Boot 
intern auf Thumb schaltet. Aber wissen tu ich's nicht … Im Disassembly 
vom U-Boot selbst finde ich Vorkehrungen sowohl für ARM als auch Thumb.

Ich könnte natürlich mal gucken, ob ich die Makefiles so modifizieren 
kann, dass da ARM-Code generiert wird.

Andererseits: die Compiler-Optionen -mthumb -mthumb-interwork sehe ich 
auch im restlichen Compile-Aufruf von U-Boot an vielen Stellen.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Mw E. schrieb:
> Der SP sieht komisch aus, is da RAM?

Berechtigte Frage …

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Jörg W. schrieb:
> Mw E. schrieb:
>> Der SP sieht komisch aus, is da RAM?
>
> Berechtigte Frage …

Irgendwie schon. ;-)
1
STM32MP> md d7df04c8
2
d7df04c8: d9fe0150 d9fe016c d9fe0188 d9fe01a4    P...l...........
3
d7df04d8: d7f31760 d9f7d7b5 d9f5557b d7f32058    `.......{U..X ..
4
d7df04e8: d9fe91d4 d9f51b77 00000004 00000038    ....w.......8...
5
d7df04f8: 00000004 00000010 00000004 d9fa76ed    .............v..
6
d7df0508: d9fc137c 00000008 00000008 d9fc30bd    |............0..
7
d7df0518: d7df0518 d7df0518 00000008 00000009    ................
8
d7df0528: d9fe040c d9fe040c d9fe040c d9fe040c    ................
9
d7df0538: 2e2e2e2e d9fa6d00 00000006 00000000    .....m..........
10
d7df0548: 00000002 d9fa871d d9fb5272 00000000    ........rR......
11
d7df0558: 00000000 00000001 00000080 d9fb5272    ............rR..
12
d7df0568: 00000000 d9fa9841 00000004 d7df04c8    ....A...........
13
d7df0578: 00000000 00000040 d9fd7f38 00000002    ....@...8.......
14
d7df0588: d7f34b80 d9f409cf 00000004 00000000    .K..............
15
d7df0598: d7f34b80 d9fdff90 00000000 d9f560b1    .K...........`..
16
d7df05a8: d9fe359c 00000002 00000000 d9f56163    .5..........ca..
17
d7df05b8: d7df05c4 00000002 d7f34b80 00000001    .........K......

Ah ja. Zwischen 0xC0000000 und (maximal) 0xE0000000 ist der SDRAM.

: Bearbeitet durch Moderator
von Mw E. (Firma: fritzler-avr.de) (fritzler)


Lesenswert?

Du musst unterscheiden womit uboot gebaut wird und in welchem Modus die 
geladene Software gestartet wird.
Aber der PC sagt ARM Modus wegen dem LSB = 0.

Was heißt im Kontext des Uboots selbst läuft?
Uboot läd Images ins RAM, das muss/sollte mit einem Tool packen und per 
Header versehen.
Der Header sgat dann zB obs zipepd ist oder ARM/Thumb.
-> https://linux.die.net/man/1/mkimage

Gut, dann ist da schonmal RAM.

: Bearbeitet durch User
von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Mw E. schrieb:
> Du musst unterscheiden womit uboot gebaut wird und in welchem Modus die
> geladene Software gestartet wird.

Naja, die Software gehört ja (als Beispielcode) zu U-Boot und wird 
automatisch von deren Buildsystem mit gebaut. Daher gehe ich 
grundsätzlich davon aus, dass sie da wissen, was sie tun.

> Aber der PC sagt ARM Modus wegen dem LSB = 0.

Ja, das ist komisch, in der Tat.

> Was heißt im Kontext des Uboots selbst läuft?

Die Library-Aufrufe sind nur Stubs. Benutzt werden die Lib-Funktionen 
des U-Boots selbst; die Verbindung erfolgt über r9, welches offenbar als 
eine Art context pointer fungiert.
1
c4600098 <getc>:
2
c4600098:       f8d9 c078       ldr.w   ip, [r9, #120]  ; 0x78
3
c460009c:       f8dc f004       ldr.w   pc, [ip, #4]
4
5
c46000a0 <tstc>:
6
c46000a0:       f8d9 c078       ldr.w   ip, [r9, #120]  ; 0x78
7
c46000a4:       f8dc f008       ldr.w   pc, [ip, #8]
8
9
c46000a8 <putc>:
10
c46000a8:       f8d9 c078       ldr.w   ip, [r9, #120]  ; 0x78
11
c46000ac:       f8dc f00c       ldr.w   pc, [ip, #12]
12
13
c46000b0 <puts>:
14
c46000b0:       f8d9 c078       ldr.w   ip, [r9, #120]  ; 0x78
15
c46000b4:       f8dc f010       ldr.w   pc, [ip, #16]

> Uboot läd Images ins RAM, das muss/sollte mit einem Tool packen und per
> Header versehen.

Kann man, muss man für eine standalone app aber nicht unbedingt - sagt 
die Doku. Mit Header kann man dann das bootm-Kommando benutzen, welches 
sich automatisch um die Caches kümmert.

Der Crash passiert allerdings auch, wenn ich die Caches ausschalte.

Doku:

https://www.denx.de/wiki/view/DULG/UBootStandalone

von Frank K. (fchk)


Lesenswert?

Jörg W. schrieb:
>
1
> Disassembly of section .text:
2
> 
3
> c4600000 <hello_world>:
4
> c4600000:       e92d 41f0       stmdb   sp!, {r4, r5, r6, r7, r8, lr}
5
> c4600004:       4605            mov     r5, r0
6
> c4600006:       4608            mov     r0, r1
7
> c4600008:       460e            mov     r6, r1
8
> c460000a:       f000 f8c3       bl      c4600194 <app_startup>
9
> …
10
>

Das muss Thumb Code sein, weil die mov Operationen als 16 Bit Opcodes 
codiert sind. Im ARM Modus wären das alles 32 Bit Opcodes. Also müsste 
bei der Startadresse Bit 0 gesetzt sein.

> ## Starting application at 0xC4600000 ...
> undefined instruction

Auch das ist dann logisch, wenn Thumb/Thumb2 Code im ARM-Modus 
ausgeführt werden soll.

fchk

von Mw E. (Firma: fritzler-avr.de) (fritzler)


Lesenswert?

Soweit sind wir ja schon, dass Thumb im ARM Modus ausgeführt wird ;)

Ich hab nochmal geguckt: auch mkimage kennt nur "-A arm" und nicht 
thumb.
Mysteriös!
Bisher hab ich uboot auch nur dazu genutzt Images per TFTP auf ARM Kerne 
zu laden und das im ARM Modus, aber da nen thumb mitzugeben muss doch 
möglich sein.
Auch wenns einkompiliert ist.

Jörg W. schrieb:
> Der Crash passiert allerdings auch, wenn ich die Caches ausschalte.

Es ist ja auch kein Cache Problem, aber trotzdem erstmal deaktiviert 
lassen bis alles läuft.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Frank K. schrieb:
> Also müsste bei der Startadresse Bit 0 gesetzt sein.

Ah, mir dämmert da was …

Kann es sein, dass ich "go 0xC4600001" schreiben müsste?

von Mw E. (Firma: fritzler-avr.de) (fritzler)


Lesenswert?

Kannste ja mal probieren, das LSB ist aber eher ein Merkbit für BLX.
Es ist also die Frage mit welchem Befehl der uboot den Code anspringt.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Jörg W. schrieb:
> Frank K. schrieb:
>> Also müsste bei der Startadresse Bit 0 gesetzt sein.
>
> Ah, mir dämmert da was …
>
> Kann es sein, dass ich "go 0xC4600001" schreiben müsste?
1
STM32MP> go 0xC4600001 ah be ce
2
## Starting application at 0xC4600001 ...
3
Example expects ABI version 9
4
Actual U-Boot ABI version 9
5
Hello World
6
argc = 4
7
argv[0] = "0xC4600001"
8
argv[1] = "ah"
9
argv[2] = "be"
10
argv[3] = "ce"
11
argv[4] = "<NULL>"
12
Hit any key to exit ...

:-)

Danke fürs Mit-der-Nase-drauf-Stoßen. :-)

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Nachtrag:

Was ich nicht verstehe, ARM überschreibt extra dafür eigentlich das 
"go"-Kommando:
1
/*
2
 * ARMv7M does not support ARM instruction mode. However, the
3
 * interworking BLX and BX instructions do encode the ARM/Thumb
4
 * field in bit 0. This means that when executing any Branch
5
 * and eXchange instruction we must set bit 0 to one to guarantee
6
 * that we keep the processor in Thumb instruction mode. From The
7
 * ARMv7-M Instruction Set A4.1.1:
8
 *   "ARMv7-M only supports the Thumb instruction execution state,
9
 *    therefore the value of address bit [0] must be 1 in interworking
10
 *    instructions, otherwise a fault occurs."
11
 */
12
unsigned long do_go_exec(ulong (*entry)(int, char * const []),
13
                         int argc, char * const argv[])
14
{
15
        ulong addr = (ulong)entry | 1;
16
        entry = (void *)addr;
17
18
        return entry(argc, argv);
19
}

Aus irgendeinem Grund scheint das hier aber nicht gegriffen zu haben …

von Μαtthias W. (matthias) Benutzerseite


Lesenswert?

arch/arm/lib/Makefile:
1
obj-$(CONFIG_CPU_V7M) += cmd_boot.o

CONFIG_CPU_V7M ist für die STM32MP1 ziemlich sicher nicht gesetzt da die 
eher ARMV7 (ohne M) sind. Ich würde einfach deine standalone nicht für 
Thumb übersetzen.

Matthias

: Bearbeitet durch User
von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Μαtthias W. schrieb:
> ch würde einfach deine standalone nicht für Thumb übersetzen.

Wäre auch 'ne Option.

Muss mir jetzt sowieso mal ansehen, wie ich daraus dann custom commands 
innerhalb der Yocto-Bitbäckerei zusammen genagelt bekomme.

von Μαtthias W. (matthias) Benutzerseite


Lesenswert?

Jörg W. schrieb:
> Muss mir jetzt sowieso mal ansehen, wie ich daraus dann custom commands
> innerhalb der Yocto-Bitbäckerei zusammen genagelt bekomme.

Wer Yocto kennt nimmt Buildroot ;-)

Matthias

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Μαtthias W. schrieb:
> Wer Yocto kennt nimmt Buildroot ;-)

Mag sein – ist nicht meine Entscheidung. Auftragsarbeit.

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.