Hallo zusammen, ich habe mir ein STM Nucleo Board für den STM32WB Microcontroller besorgt und möchte per CubeMX zunächst ein blankes Projekt in CubeIDE erstellen, auf den Controller laden und ausführen. Leider bekomme ich selbst mit dem unveränderten, in CubeMX speziell für das Board generierten Code einen HardFault. Ich muss dazu sagen, dass ich aus der PC-Software Ecke stamme und bei eingebetteten Systemen ziemlicher Einsteiger bin. Folgendes habe ich versucht: 1. CubeIDE starten und neues Projekt erstellen 2. Bei der Projekterstellung des Board auswählen (Nucleo WB55) 3. An der Konfig in CubeMX nichts verändern 4. Code aus CubeMX heraus generieren 5. Debuggen Sobald in startup_stm32wb55xx_cm4.s die Funktion "SystemInit" aufgerufen wird, tritt ein HardFault auf. Der Fault Analyzer zeigt einen IMPRECISERR und STKERR an, PC zeigt jedoch auf 0x0. Wenn ich im Einzelschritt debugge, sehe ich, dass nach der Anweisung zum Aufruf von "SystemInit" folgendes stattfindet, bevor der HardFault getriggert wird: 87 bl SystemInit 0800270a: bl 0x80024f0 <SystemInit> 080024f0: push {r7} 080024f2: add r7, sp, #0 <<<<<<<<<< HardFault 199 SCB->VTOR = VECT_TAB_OFFSET; Das passiert übrigens bei jedem beliebigen Funktionsaufruf aus dem Startup heraus, sobald das "add" ausgeführt wird. Hat jemand eine Ahnung, warum das so ist? Im Prinzip nutze ich ja ein Blanko-Projekt, was speziell für dieses Board vorkonfiguriert ist. Besten Dank im Voraus!
Das ist ja schoen das das so zeitig passiert. Damit hast du Gelegenheit dich intensiv mit dem Controller jenseits von HAL zu beschaeftigen. Lesestoff zu dem Thema 'Hardfault' gibt es u.a. bei TI: SPMA043.PDF Diagnosing Software Faults...
Da ist offenbar der Stack nicht richtig eingestellt. Schau Dir mal im resultierenden Hexfile die ersten vier Bytes der ersten Datenzeile an, da muß der Stackpointer bei Reset drinstehen.
Vielen Dank für die Anregungen! Prinzipiell stimme ich zu, dass das eine gute Übung für den Einstieg ist. Leider sitze ich aber schon eine ganze Weile davor und komme nicht weiter. Das Dokument von TI ist zwar hilfreich, allerdings sind bei mir alle ansonsten aufschlussreichen register einfach 0. Der Stackpointer wird mit 0x20040000 initialisiert und zwar mit der Anweisung ldr r0, =_estack mov sp, r0 /* set stack pointer */ im Startup (Reset Handler). Ich habe versucht, herauszufinden, ob das richtig ist. Mir scheint es aber so zu sein, dass der Wert im Controller fest hinterlegt ist. Stimmt das? EDIT: Hab gefunden, wo es definiert ist. Laut Kommentar sollte es das Ende des RAM sein. Versuche gerade herauszufinden, ob es das auch ist. EDIT2: Laut Referenz Endet der external RAM an Adresse 0x9FFFFFFF. Verstehe ich das richtig? Habe den Wert nun im Linker Script für den RAM auf diese Adresse angepasst und nun tritt der HardFault an anderer Stelle auf: Im Startup wird die Funktion "__libc_init_array" aufgerufen. Diese wiederum ruft "_init" auf. Im Disassembly von "_init" ist folgender Code zu sehen: 0800278c: push {r3, r4, r5, r6, r7, lr} 0800278e: nop 08002790: pop {r3, r4, r5, r6, r7} 08002792: pop {r3} 08002794: mov lr, r3 08002796: bx lr <<<<< lr = 0x0 lr hat zunächst die richtige Rücksprungadresse, wird dann aber mit r3 = 0x0 überschrieben (warum?). Mit lr = 0x0 wird dann versucht, an 0x0 zu springen, was dann wieder zum HardFault führt.
:
Bearbeitet durch User
Ich denke, ich habe das Problem gelöst: Der SRAM des Controllers ist 256 KB groß und beginnt bei 0x20000000, geht also nur bis 0x20010000. Per Default eingetragen ist aber 0x20040000, was offenbar zu dem Fehler führt. Ich habe den Wert im Linker Script entsprechend auf 0x20010000 angepasst und nun funktioniert alles. Nach wie vor bin ich etwas überrascht, dass die Standardeinstellungen so gar nicht zum Board zu passen scheinen... EDIT: Gerade noch mal nachgerechnet. Was ich oben geschrieben habe passt natürlich nicht, 0x20000000 + 256 KB = 0x20040000 ist schon richtig gewesen. Dennoch seltsam, warum die Änderung das Problem scheinbar behoben hat. Kann das jemand erklären?
:
Bearbeitet durch User
Rem V. schrieb: > Der Stackpointer wird mit 0x20040000 initialisiert und zwar mit der > Anweisung > > ldr r0, =_estack > mov sp, r0 /* set stack pointer */ > > im Startup (Reset Handler). Das sollte eigentlich bereits im Hexfile richtig gesetzt sein, manuell ist das schon eher ungewöhnlich. > EDIT2: Laut Referenz Endet der external RAM an Adresse 0x9FFFFFFF. Das dürfte der Adreßbereich sein, den externes RAM haben kann, sofern bestückt. Aber den Stack packt man normalerweise nicht ins externe RAM, sondern ins interne. Erstens ist das performanter, und zweitens müßte man im externen Fall die Chip-Konfig auch noch in Assembler machen, weil C-Funktionen einen bereits funktionierenden Stack erwarten. > 0800278c: push {r3, r4, r5, r6, r7, lr} > 0800278e: nop > 08002790: pop {r3, r4, r5, r6, r7} > 08002792: pop {r3} > 08002794: mov lr, r3 > 08002796: bx lr <<<<< lr = 0x0 Also da werden doch eigentlich nur alle Register einmal gepusht, dann gepopt, und am Ende wird das, was vorher als LR gepusht worden ist, in R3 gepopt, welches dann in LR kopiert wird. Sinnfrei, aber sieht nicht verkehrt aus. Es sei denn, da ist noch irgendwo die Nullungsschleife fürs RAM drin, und das nullt sich u.a. auch den Stack weg. Das ist doof, wenn man dann nämlich u.a. LR wieder vom Stack popt, dann kriegt man die beobachtete null raus. Step mal im Einzelschritt durchs Disassembly, da muß irgendwo eine Schleife sein, die grob so aussieht: - ein Register wird mit 0 geladen - ein anderes Register mit der Startadresse vom RAM - ein weiteres mit irgendeiner End-Adresse - und dann wird der Inhalt des genullten Registers in einer Schleife in das Register mit der Startadresse geladen. Das letztere wird dann typischerweise um 4 erhöht.
Es ist so, dass _estack im Linker Script standardmäßig von der IDE auf 0x20040000 gesetzt wird. Auf diese Weise bekomme ich aber immer diesen HardFault. Setze ich diesen Wert auf 0x20030000 funktioniert alles (ist auch in den mitgelieferten Beispielen so). Bei der scheinbar sinnlosen _init Funktion hatte ich noch eine nicht vorhandene Speicheradresse für den Stack im Linker Script hinterlegt, was beim Laden aus dem Stack dazu geführt hat, dass die Register alle 0 waren. Was ich nicht ganz verstehe ist nun, warum es mit einem initialen Stack Pointer von 0x20040000 (Ende SRAM) nicht funktioniert. Ich habe mal etwas rumprobiert und die letzte funktionierende Speicheradresse ist irgendwo in der Nähe von 0x2003df0, etwa 12 kB vor dem Ende des SRAM. Alles darüber hinaus führt zum HardFault.
Rem V. schrieb: > Was ich nicht ganz verstehe ist nun, warum es mit einem initialen Stack > Pointer von 0x20040000 (Ende SRAM) nicht funktioniert. Was für ein Chip ist überhaupt auf dem Board? Was sagt denn dessen Reference Manual zum Thema Speicherbereiche? > Ich habe mal > etwas rumprobiert und die letzte funktionierende Speicheradresse ist > irgendwo in der Nähe von 0x2003df0, etwa 12 kB vor dem Ende des SRAM. > Alles darüber hinaus führt zum HardFault. Kann natürlich sein, daß irgendwas in der IDE da noch irgendwas anderes hinlegt, was mit der Verwendung kollidiert. Zudem kennt jedenfalls der Cortex-M3/4 zwei verschiedene Stacks, die für Verwendung in einem RTOS gedacht sind: Thread Mode und Handler Mode. Wenn Du auch noch ein RTOS drin hast, was schon irgendwas einstellt, wäre es möglich, daß Du tatsächlich zwei Stacks hast, die da kollidieren. Siehe hier: http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dai0179b/ar01s02s06.html
Nop schrieb: > Was für ein Chip ist überhaupt auf dem Board? Was sagt denn dessen > Reference Manual zum Thema Speicherbereiche? Der Chip ist ein STM32WB55RG mit 256 kB SRAM beginnend bei 0x20000000 (lt. Reference Manual). Nop schrieb: > Wenn Du auch noch ein RTOS drin hast, was schon irgendwas einstellt, > wäre es möglich, daß Du tatsächlich zwei Stacks hast, die da > kollidieren. Das FreeRTOS ist in der Konfiguration deaktiviert. Mein Projekt ist ein blanko Projekt aus der Vorlage für genau dieses Board (STM Nucleo WB55), ohne jeglichen "Schnickschnack". Fast alle Peripheriekomponenten außer GPIO sind deaktiviert. EDIT: Bin gerade durch Zufall auf die Info gestoßen, dass es unterschiedliche Firmware Binaries für den Chip gibt, je nach dem, ob ein Wireless Stack benötigt wird. Da eine Wireless-Demo vorgeladen ist, ist wahrscheinlich eine entsprechende Wireless-Firmware drauf. Das könnte eventuell das Problem sein.
:
Bearbeitet durch User
> (lt. Reference Manual).
Ja, mit der falschen Literatur und stuemperhaften Herumprobieren
wird das noch bis zum Sankt Nimmerleinstag dauern.
Die "Memory Map" ist bei ST im allg. im Datasheet.
Und die verraet auch welche Peripherie dort auf dem Speicher
herumzaubert.
So wird das jedenfalls nuex.
Bei dem Bluetooth STM32 hier is das aber andersrum, also sei leise. The detailed memory map and the peripheral mapping of the STM32WB55xx devices can be found in the reference manual RM0434. @topic: Gibts denn eine Doku was die Wireless FW auf dem Cortex M0 macht? Ansonsten bleibt das hier wirklich ein stochern im dunkeln und der SRAM2b sollte nicht vom M4 genutzt werden. Ansonsten steht beim SRAM2 a/b, dass man den Zugriff durch den M0 (CPU2) durch das C2RFD Bit im SYSCFG Register sperren kann. Wenns dann geht ist klar worans liegt.
... schrieb: > Die "Memory Map" ist bei ST im allg. im Datasheet. Üblicherweise sowohl Kapitel 2 Refman als auch Kapitel 4 Datasheet. Mw E. schrieb: > Ansonsten steht beim SRAM2 a/b, dass man den Zugriff durch den M0 (CPU2) > durch das C2RFD Bit im SYSCFG Register sperren kann. Aber nur code execution aus dem SRAM, nicht jedweden Zugriff. Es gibt aber auch noch C2BOOT in PWR_CR4, was man auf 0 setzen kann, dann bootet CPU2 nicht und wird nicht dazwischenfunken.
Habe gerade nochmal in das Reference Manual geschaut. SRAM2 beginnt ja genau ab 0x20040000, während der (funktionierende) SRAM1 genau ab 0x20030000 beginnt. So wie ich das verstehe, gibt es zwar eine Möglichkeit, den SRAM2 gemeinsam zu nutzen, dafür muss aber scheinbar eine entsprechende arbitration Logik implementiert werden. So verstehe ich das jedenfalls mit meinem Halbwissen. Das reicht mir jedenfalls, um mich weiter einarbeiten zu können. Danke für eure Hilfe! :)
Ich habe auch schon häufig festgedtellt, dass die Standard Cube MX Projekte für die ST Boards nie recht funktionieren. HardFault etc.. Seither erstelle ich immer selbst ein Projekt mit Auswahl des Controllers und Config.. Da kann man schön Schritt für Schritt vorgehen.. Just my two cents..
Hallo Remo V. Wenn du jetzt weißt, was falsch ist, dann mach doch im STM Forum ein Bugrepo RT.... Danke und Grüße, Adib.
Giesser schrieb: > Seither erstelle ich immer selbst ein Projekt mit Auswahl des > Controllers und Config.. Da kann man schön Schritt für Schritt > vorgehen.. Kannst du das kurz genauer beschreiben, wie du da vorgehst bzw. was du verwendest? Falls du damit meinst, dass du in CubeMX anstatt des Boards nur den Controller auswählst: Hab ich schon versucht, funktioniert aber bei dem in CubeIDE integrieren MX nicht :-/ The A. schrieb: > Wenn du jetzt weißt, was falsch ist, dann mach doch im STM Forum ein > Bugrepo RT.... Mache ich!
Rem V. schrieb: > The A. schrieb: >> Wenn du jetzt weißt, was falsch ist, dann mach doch im STM Forum ein >> Bugrepo RT.... > > Mache ich! Kannst du dann den Link hier rein stellen? Hatte das gleiche Problem und würde gerne das Issue verfolgen.
Der Thread ist zwar alt, vielleicht hilft mein Kommentar aber anderen STM32WB Benutzern weiter. Der STM32WB hat 2 CPUs. CPU1 ist ein Cortex M4 und im allgemeinen läuft hier die Applikation. CPU2 ist eine Cortex M0+ und die ist für die BLE Kommunikation zuständig. Die beiden CPUs teilen sich Flash und RAM. Wenn ein BLE Stack installiert ist, ist ein Teil des RAMs für die CPU2 reserviert und vor Zugriffen der CPU1 geschützt. Sobald die CPU1 versucht auf dieses RAM zuzugreifen, gibt es ein Hardfault. Von den 256 KiB RAM sind 64 KiB (ab 0x20030000) für CPU2 reserviert oder mit CPU1 geshared. Das könnte man auch ändern, davon würde ich aber die Finger lassen. Wenn man schon eine BLE MCU einsetzt, nehme ich an, dass man den BLE Stack auch nutzen will. Wer sich für ein interaktives Forth System auf Basis STM32WB und CubeMX interessiert, kann ja mal hier reinschauen: https://spyr.ch/twiki/bin/view/MecrispCube/ Peter
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.