Forum: Mikrocontroller und Digitale Elektronik mein erstes STM32F4 .asm/ .s Program stürzt ab im gdb


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Christoph K. (chriskuku)


Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Das angehängte Program stürzt im gdb ab, wenn ich durchsteppe.
Ich habe line-numbers mitgeneriert (-g Schalter im gnu as).
(gdb) load
`/Users/kuku/myfirst/firmware.elf' has changed; re-reading symbols.
Loading section .text, size 0x478 lma 0x0
Start address 0x400, load size 1144
Transfer rate: 9152 bits in <1 sec, 1144 bytes/write.
(gdb) si
halted: PC: 0x00000402
85    mov r0, HSEON
(gdb) 
halted: PC: 0x00000404
0x00000404  85    mov r0, HSEON
(gdb) 
halted: PC: 0x00000406
86    str r0, [r1]            @ turn on the external clock
(gdb) 
halted: PC: 0x00000408
awaitHSE () at myfirst.s:89
89    ldr r0, [r1]
(gdb) 
halted: PC: 0x0000040a
90    ands r0, #HSERDY
(gdb) 
halted: PC: 0x0000040c
0x0000040c  90    ands r0, #HSERDY
(gdb) 
halted: PC: 0x0000040e
91    beq.n awaitHSE  @ hang here until external clock is stable
(gdb) 
halted: PC: 0x00000410
95    ldr r1, = RCC_CFGR
(gdb) 
halted: PC: 0x00000412
97    mov r0, # 1
(gdb) 
halted: PC: 0xfffffffe
0xfffffffe in ?? ()
(gdb) 


von Johannes S. (jojos)


Bewertung
0 lesenswert
nicht lesenswert
Ich denke da fehlen einige LDR und OR Operationen, mit deinen STR setzt 
du ein Bit und machst alle anderen platt.
Und die Clock Berechnung ist auch nicht gut, normalerweise schaltet man 
die PLL ein und bekommt einen höheren APB Takt, damit wird die Bitrate 
deutlich genauer. Die UART hängen an verschiedenen APB und haben 
wiederum Vorteiler, das kann man sich in CubeMX  ansehen wo es schön 
grafisch dargestellt wird.
Und gdb in VSCode mit Cortex-debug Extension ist Grafisch auch schöner. 
Forth Extensions gibt auch dafür.

von Christoph K. (chriskuku)


Bewertung
0 lesenswert
nicht lesenswert
Johannes S. schrieb:
> Ich denke da fehlen einige LDR und OR Operationen, mit deinen STR setzt
> du ein Bit und machst alle anderen platt.
> Und die Clock Berechnung ist auch nicht gut, normalerweise schaltet man
> die PLL ein und bekommt einen höheren APB Takt, damit wird die Bitrate
> deutlich genauer. Die UART hängen an verschiedenen APB und haben
> wiederum Vorteiler, das kann man sich in CubeMX  ansehen wo es schön
> grafisch dargestellt wird.
> Und gdb in VSCode mit Cortex-debug Extension ist Grafisch auch schöner.
> Forth Extensions gibt auch dafür.

Ad 1) es kommt mir nicht auf den Inhalt an. Es könnte irgendwelcher 
Kokolores im Programm stehen. Denn, meine Frage war:

Ad 2) warum stürzt das Programm ab,

Ad 3) Forth Extensions und gar VS sind das Entfernteste, an das ich hier 
denken würde.

Insofern ist vielleicht der Titel etwas irreführend, daß es "mein 
erstes" Programm ist. Es ist ein Code snippet, das ich aus einem anderen 
Programm isoliert habe und von dem ich wissen will, warum es im GDB 
abstürzt.

Kommt der gdb mit der mov r0, #1 Instruktion nicht klar? Fehlt eine 
Assembler-Direktive?
77                    @  Initialize STM32 Clocks
  78
  79                    @ Ideally, we would just take the defaults to begin with and
  80                    @ do nothing.  Because it is possible that HSI is not
  81                    @ accurate enough for the serial communication (USART2), we
  82                    @ will switch from the internal 8 MHz clock (HSI) to the
  83                    @ external 8 MHz clock (HSE).
  84 0400 1449                  ldr r1, =RCC_CR
  85 0402 4FF48030              mov r0, HSEON
  86 0406 0860                  str r0, [r1]            @ turn on the external clock
  87
  88                    awaitHSE:
  89 0408 0868                  ldr r0, [r1]
  90 040a 10F40030              ands r0, #HSERDY
  91 040e FBD0                  beq.n awaitHSE  @ hang here until external clock is stable
  92                                            @ at this point, the HSE is running and
  93                                            @ stable but I suppose we have not yet
  94                                            @ switched Sysclk to use it.
  95 0410 1149                  ldr r1, = RCC_CFGR
  96
  97 0412 4FF00100              mov r0, # 1

: Bearbeitet durch User
von Johannes S. (jojos)


Bewertung
0 lesenswert
nicht lesenswert
Beim Clock versteht der STM32 aber keinen Spass, und du überschreibst im 
RCC_CR alle Bits, auch solche die man lt. Doku auf Initialwert stehen 
lassen soll. Und bei den Periphieclocks genauso, da geht eben gar nix 
mehr und auch das SWD kann sich da verabschieden.

: Bearbeitet durch User
von Christoph K. (chriskuku)


Bewertung
0 lesenswert
nicht lesenswert
Es kommt mir so vor, als sei das, was im memory steht, nicht der code, 
den gdb dazu anzeigt.
xPSR: 0x01000000 pc: 0x00003a56 msp: 0x20000330
Loading section .text, size 0x478 lma 0x0
Start address 0x400, load size 1144
Transfer rate: 9152 bits in <1 sec, 1144 bytes/write.
(gdb) x/20x 0x0400
0x400 <Reset>:  0x04124152  0x040a18b6  0x18800c09  0x3f04414e
0x410 <awaitHSE+8>:  0x47706038  0x000004a6  0x75040044  0x002a6d64
0x420 <awaitHSE+24>:  0x2400b510  0x6d04f847  0xf847687e  0x693e6d04
0x430 <awaitHSE+40>:  0xffc2f7ff  0xcf400031  0xcf400030  0x6d04f847
0x440 <awaitHSE+56>:  0xf847683e  0x68fe6d04  0xf7ffb403  0xbc03ffb5
(gdb) x/20i 0x0400
=> 0x400 <Reset>:  adcs  r2, r2
   0x402 <Reset+2>:  lsls  r2, r2, #16
   0x404 <Reset+4>:  adds  r6, r6, r2
   0x406 <Reset+6>:  lsls  r2, r1, #16
   0x408 <awaitHSE>:  lsrs  r1, r1, #16
   0x40a <awaitHSE+2>:  adds  r0, r0, r2
   0x40c <awaitHSE+4>:  adcs  r6, r1
   0x40e <awaitHSE+6>:  subs  r7, #4
   0x410 <awaitHSE+8>:  str  r0, [r7, #0]
   0x412 <awaitHSE+10>:  bx  lr
   0x414 <awaitHSE+12>:  lsls  r6, r4, #18
   0x416 <awaitHSE+14>:  movs  r0, r0
   0x418 <awaitHSE+16>:  lsls  r4, r0, #1
   0x41a <awaitHSE+18>:  strb  r4, [r0, #20]
   0x41c <awaitHSE+20>:  ldr  r4, [r4, #84]  ; 0x54
   0x41e <awaitHSE+22>:  movs  r2, r5
   0x420 <awaitHSE+24>:  push  {r4, lr}
   0x422 <awaitHSE+26>:  movs  r4, #0
   0x424 <awaitHSE+28>:  str.w  r6, [r7, #-4]!
   0x428 <awaitHSE+32>:  ldr  r6, [r7, #4]

von Christoph K. (chriskuku)


Bewertung
0 lesenswert
nicht lesenswert
Johannes S. schrieb:
> Beim Clock versteht der STM32 aber keinen Spass, und du überschreibst im
> RCC_CR alle Bits, auch solche die man lt. Doku auf Initialwert stehen
> lassen soll. Und bei den Periphieclocks genauso, da geht eben gar nix
> mehr und auch das SWD kann sich da verabschieden.

Danke für die Interpretation. Werde das mal mit dem Autor diskutieren.

P.S. ich glaube, ich habe in meinem Source code den vector-Bereich 
vergessen, zu initialisieren. Da stehen im Moment noch die Adressen 
eines älteren Programms drin. Hatte ja meinen Source file gepostet.

: Bearbeitet durch User
von Christoph K. (chriskuku)


Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Irgendwas mache ich noch falsch. Ich bekomme nicht das ins flash, was 
ich programmiert habe. Ich lade mal alles hoch. Es geht jetzt um 
simple.s. Weder die Plätze 0 und 4 werden programmiert noch der 
Codebereich
Reset: 0x400:
        .global Reset
        .syntax unified
        .cpu cortex-m4
        .thumb
        .equ TOS, 0x40000000

        .data
        .org 0

        .word TOS        @ 00: Stack top address
        .word Reset+1    @ 01: Reset Vector +1 wegen des Thumb-Einsprunges

        .text
        .org 0x400

Reset:
        bal Reset
        .end
Starte ich dazu den gdb, so bekomme ich dieses:
$ ./GDB
GNU gdb (GNU Tools for Arm Embedded Processors 8-2018-q4-major) 8.2.50.20181213-git
Copyright (C) 2018 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "--host=x86_64-apple-darwin10 --target=arm-none-eabi".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
    <http://www.gnu.org/software/gdb/documentation/>.

For help, type "help".
Type "apropos word" to search for commands related to "word".
0x00010100 in ?? ()
Unable to match requested speed 2000 kHz, using 1800 kHz
Unable to match requested speed 2000 kHz, using 1800 kHz
target halted due to debug-request, current mode: Thread 
xPSR: 0x01000000 pc: 0x00010100 msp: 0x464c457c
Loading section .text, size 0x404 lma 0x0
Loading section .data, size 0x8 lma 0x404
Start address 0x400, load size 1036
Transfer rate: 91 KB/sec, 518 bytes/write.
(gdb) x/20x 0
0x0:  0x464c457f  0x00010101  0x00000000  0x00000000
0x10:  0x00280002  0x00000001  0x00000400  0x00000034
0x20:  0x00010d24  0x05000200  0x00200034  0x00280001
0x30:  0x000a000b  0x00000001  0x00010000  0x00000000
0x40:  0x00000000  0x00000478  0x00000478  0x00000005
(gdb) x/10x 0x400
0x400 <Reset>:  0x00000000  0x00000000  0x00000000  0x00000000
0x410:  0x00000000  0x00000000  0x00000000  0x00000000
0x420:  0x00000000  0x00000000

Vielleicht ist memmap falsch? Habe ich so übernommen aus dem 
ursprünglichen Projekt.
MEMORY
{
   rom(RX)   : ORIGIN = 0x00000000, LENGTH = 0x4000
   ram(WAIL) : ORIGIN = 0x20000000, LENGTH = 0x4000
}

SECTIONS
{
   .text : { *(.text*) } > rom
   .bss  : { *(.bss*) } > ram
}

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


Bewertung
1 lesenswert
nicht lesenswert
Warum packst du denn die Vektortabelle nach .data (welches du noch dazu 
im Linkerscript nicht einmal erwähnst)?

Die Vektortabelle gehört natürlich an den Anfang des Flashs. 
Üblicherweise reserviert man dafür eine eigene section und platziert 
diese dann im Linkerscript noch vor .text.

.org hat in verschieblichem Assemblercode schon seit CP/M nichts mehr 
verloren …

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


Bewertung
1 lesenswert
nicht lesenswert
Vielleicht solltest du erstmal ein simples C-Blinky-Beispiel durchgehen 
und dir anschauen, was der Compiler als Assemblercode generiert?

Bevor du den ganzen Spaß mit dem GDB in den Flash pumpst, kannst du 
übrigens ruhig mal einen Blick in die ELF-Datei werfern 
(arm-none-eabi-objdump, vor allem -h und -d sind interessant als 
Optionen).

: Bearbeitet durch Moderator
von Christoph K. (chriskuku)


Bewertung
0 lesenswert
nicht lesenswert
Jörg W. schrieb:
> Vielleicht solltest du erstmal ein simples C-Blinky-Beispiel durchgehen
> und dir anschauen, was der Compiler als Assemblercode generiert?
>
> Bevor du den ganzen Spaß mit dem GDB in den Flash pumpst, kannst du
> übrigens ruhig mal einen Blick in die ELF-Datei werfern
> (arm-none-eabi-objdump, vor allem -h und -d sind interessant als
> Optionen).

Gut, werde ich machen.

Was da geladen wurde mit "load" nach 0x00000000, ist übrigens der .ELF 
file selbst:

(gdb) x/20c 0
0x0:  127 '\177'  69 'E'  76 'L'  70 'F'  1 '\001'  1 '\001'  1 '\001' 
0 '\000'
0x8:  0 '\000'  0 '\000'  0 '\000'  0 '\000'  0 '\000'  0 '\000'  0 
'\0000 '\000'
0x10:  2 '\002'  0 '\000'  40 '('  0 '\000'
(gdb)

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


Bewertung
1 lesenswert
nicht lesenswert
Christoph K. schrieb:
> Was da geladen wurde mit "load" nach 0x00000000, ist übrigens der .ELF
> file selbst:

grmpf

Dann ist irgendwas grundlegend flasch gelaufen und der GDB hat das Ding 
als Binärdatei genommen.

Ich denke, es ist wirklich zielführender, ein C-Minimalprogramm 
(möglichst ohne all den Kladderadatsch wie HAL oder dergleichen) mal zu 
analysieren, sowohl hinsichtlich des Aufbaus von Startup-Code und 
Linkerscript als auch hinsichtlich einiger ARM-typischer 
Programmierstrategien (wie eben bspw. das Ablegen von Konstanten 
innerhalb des Codes, die zu groß sind, um als Direktoperanden geladen zu 
werden).

von Niklas G. (erlkoenig) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Das "Reset+1" im Interrupt Vector ist unnötig, wenn man "Reset" korrekt 
als Funktion definiert:
  .word TOS           @ 00: Stack top address
  .word Reset            @ 01: Reset Vector  +1 wegen des Thumb-Einsprunges

  .text
        .org 0x400

.type Reset, %function
Reset:
        bal Reset
  .end

Und der Vektor gehört natürlich wie schon gesagt an den Anfang des 
Flash. Wie wäre es mit meinem ARM-ASM-Tutorial?

von Christoph K. (chriskuku)


Bewertung
0 lesenswert
nicht lesenswert
zum .org:

Ich bin ja zunächst von der source des mecrisp-stellaris-forth 
ausgegangen und der Autor hat das Projekt nicht auf .elf basiert, 
sondern .bin Files erzeugt und es sind etliche .org in seiner Source. Da 
habe ich mir jetzt erst mal nichts bei gedacht. Die .data und .text 
statements in meinem Beispiel waren verzweifelte Versuche. Es geht auch 
darum, diese Source noch auf dem discovery-Board unter einem anderen 
UART zum laufen zu kriegen.

Deshalb die .orgs

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


Bewertung
1 lesenswert
nicht lesenswert
Christoph K. schrieb:
> der Autor hat das Projekt nicht auf .elf basiert, sondern .bin Files
> erzeugt

Das glaube ich nicht ernsthaft. Seit mehr als 20 Jahren können die 
entsprechenden Linker (zumindest im hier benutzten Opensource-Umfeld) 
eigentlich nichts anderes als ELF mehr direkt erzeugen. Die .bin-Files 
werden anschließend daraus extrahiert. Es muss also davor schon mal ein 
sinnvoll aufgebautes ELF-File gegeben haben.

Ich glaube, AVRDUDE war damals wohl das letzte derartige Tool, das ich 
darauf umgestellt habe, ELF-Files direkt zu lesen. Das ist nun auch 
schon 8 Jahre her.

Wie ich aber schrieb: .org hatte schon unter CP/M keinen Sinn mehr, wo 
man ähnlich wie hier vorgegangen ist und mit dem Assembler relocatable 
object files (.rel) erzeugt hat, die dann erst der Linker auf absolute 
Adressen mappt.

: Bearbeitet durch Moderator
von Christoph K. (chriskuku)


Bewertung
0 lesenswert
nicht lesenswert
Niklas G. schrieb:
> Das "Reset+1" im Interrupt Vector ist unnötig, wenn man "Reset" korrekt
> als Funktion definiert:
>
>
  .word TOS           @ 00: Stack top address
>   .word Reset            @ 01: Reset Vector  +1 wegen des 
> Thumb-Einsprunges
> 
>   .text
>         .org 0x400
> 
> .type Reset, %function
> Reset:
>         bal Reset
>   .end
> 
>
> Und der Vektor gehört natürlich wie schon gesagt an den Anfang des
> Flash. Wie wäre es mit meinem ARM-ASM-Tutorial?

Hatte ich doch auch an den Anfang gesetzt.

ARM-ASM-Tutorial, ja, werde ich mir ansehen.
Danke.

von Niklas G. (erlkoenig) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Christoph K. schrieb:
> Hatte ich doch auch an den Anfang gesetzt.

Aber .data ist halt nicht im Flash...

Christoph K. schrieb:
> ARM-ASM-Tutorial, ja, werde ich mir ansehen.

Da sind auch vollständig funktionierende Beispiele und ein 
Projekt-Template drin:

https://github.com/Erlkoenig90/ArmAsmTutorial/tree/master/ProjectTemplate-STM32F103RB

von Johannes S. (jojos)


Bewertung
0 lesenswert
nicht lesenswert
Die gcc toolchain enthält in share/gcc-arm-none-eabi/examples auch 
Beispiele. Aber ein bisschen CMSIS für   die headerfiles und Systeminit 
sollte man auch mitnehmen.

von Uwe B. (Firma: TU Darmstadt) (uwebonnes)


Bewertung
2 lesenswert
nicht lesenswert
Warum man die Systeminitialisierung bei einem F4 in Assembler schreibt, 
erschliesst sich mir auch nicht...

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


Bewertung
1 lesenswert
nicht lesenswert
Uwe B. schrieb:
> Warum man die Systeminitialisierung bei einem F4 in Assembler schreibt

Christoph hatte seine Motivation doch an anderen Stellen schon 
dargelegt: er hat von einem Verstorbenen einen FORTH-Interpreter 
übernommen und möchte den weiter pflegen.

von Christoph K. (chriskuku)


Bewertung
0 lesenswert
nicht lesenswert
Uwe B. schrieb:
> Warum man die Systeminitialisierung bei einem F4 in Assembler schreibt,
> erschliesst sich mir auch nicht...

Wie schon erwähnt, geht es um ein bereits bestehendes FORTH System, das 
in Assembler geschrieben ist. Warum soll ich da jetzt noch eine weitere 
"Hoch"sprache (C) mit hineinbringen? Die FORTH-Primitiven und der 
FORTH-Inner Interpreter basieren auf Assembler. Da wäre alles andere 
ineffizient.

Das ganze System ist 15KB groß.

: Bearbeitet durch User
von Niklas G. (erlkoenig) Benutzerseite


Bewertung
1 lesenswert
nicht lesenswert
Christoph K. schrieb:
> Warum soll ich da jetzt noch eine weitere
> "Hoch"sprache (C) mit hineinbringen? Die FORTH-Primitiven und der
> FORTH-Inner Interpreter basieren auf Assembler. Da wäre alles andere
> ineffizient.

C++ und C werden für ARM schon ziemlich effizient übersetzt. Da holst du 
mit Assembler (sehr) wenig raus.

von Christoph K. (chriskuku)


Bewertung
0 lesenswert
nicht lesenswert
Niklas G. schrieb:
> Christoph K. schrieb:
>> Warum soll ich da jetzt noch eine weitere
>> "Hoch"sprache (C) mit hineinbringen? Die FORTH-Primitiven und der
>> FORTH-Inner Interpreter basieren auf Assembler. Da wäre alles andere
>> ineffizient.
>
> C++ und C werden für ARM schon ziemlich effizient übersetzt. Da holst du
> mit Assembler (sehr) wenig raus.

Der „Inner Interpreter“, der den Threaded Code verarbeitet, sah damals 
auf der PDP-11 so aus:

     .MACRO NEXT
     MOV (IP)+,W
     JMP @(W)+
     .ENDM

Für 68k waren es drei Instruktionen.

IP und W sind CPU-Register.
+ ist postincrement des jew. Registers.

Bilde das in C bzw. ASM ab.

von Niklas G. (erlkoenig) Benutzerseite


Bewertung
1 lesenswert
nicht lesenswert
Christoph K. schrieb:
> Bilde das in C bzw. ASM ab.

Ich kann keinen PDP-11-Assembler, keine Ahnung was da passiert. Aber es 
ging überhaupt nicht um den Interpreter, sondern die Initialisierung, 
denn rein zufällig sind sowohl die Cortex-M-Architektur als auch die 
STM32-Peripherie-Register extra auf die Verwendung mit C optimiert.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.