Hallo zusammen,
auf einem STM32F4 habe ich auf der 0x8000000 einen Bootloader. Dieser
prüft einen Flag ab. Je nachdem was vorliegt startet er entweder die
Applikation oder warten auf Instruktionen um per IAP die Firmware zu
aktualisieren.
Im Grunde genommen läuft ja "fast" alles, nur funktionieren die
Interrupts in der Applikation nicht mehr.
Sowohl der Bootloader als auch die Applikation wurden auf Basis von
CubeMx/HAL entwickelt.
Das in die Applikation richtig gesprungen sehe ich darin, das aus der
Applikation heraus, nachdem dorthin gesprungen wurde, eine Uart
Nachricht mit HAL_UART_TRANSMIT verschickt wird.
Es funktioneren aber nicht die Interrupt Callback Funktionen.
Woran könnte dies liegen.
Für jede Unterstützung bin ich sehr dankbar.
Bootloader schrieb:> Es funktioneren aber nicht die Interrupt Callback Funktionen.> Woran könnte dies liegen.
Ich sehe kein Setzen von VTOR, das könnte man auch manuell in der
Applikation erledigen. Vorher sind aber alle Interrupts auf dem
Bootloader gemappt.
Jim M. schrieb:> Ich sehe kein Setzen von VTOR, das könnte man auch manuell in der> Applikation erledigen. Vorher sind aber alle Interrupts auf dem> Bootloader gemappt.
Sorry, aber ich verstehe nicht ganz was Du meinst
Bootloader schrieb:> habe ich auf der 0x8000000 einen Bootloader
Genauer gesagt hast du "auf der 0x8000000" die Vektortabelle des
Bootloaders. Woher soll denn dein Controller wissen wo die Vektortabelle
deiner Applikation liegt, welche der Bootloader geladen hat?
Dafür gibt es das VTOR (Vector Table Offset Register)
Christopher J. schrieb:> Genauer gesagt hast du "auf der 0x8000000" die Vektortabelle des> Bootloaders. Woher soll denn dein Controller wissen wo die Vektortabelle> deiner Applikation liegt, welche der Bootloader geladen hat?>> Dafür gibt es das VTOR (Vector Table Offset Register)
Ich benutze Keil. In den Projekteinstellungen ist die Startadresse
hinterlegt.
Wie ich oben schon bereits schrieb, startet die Applikation auch.
Aber die Interrupts funktionieren nicht. Das ist mein Problem.
Bootloader schrieb:> Das in die Applikation richtig gesprungen sehe ich darin, das aus der> Applikation heraus, nachdem dorthin gesprungen wurde, eine Uart> Nachricht mit HAL_UART_TRANSMIT verschickt wird.> Es funktioneren aber nicht die Interrupt Callback Funktionen.> Woran könnte dies liegen.
Die Lösung ist recht einfach. In der Datei system_stm32xxxx.c gibt es
die Definition VECT_TAB_OFFSET, die den Wert Null hat, und weiter unten
die Zeile
SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in
Internal FLASH */
Liegt die Applikations-Firmware beispielsweise auf der Adresse
0x08020000, setzt man für VECT_TAB_OFFSET einfach den Wert 0x20000.
Schon klappt es auch mit den Interrupts!
Bootloader schrieb:> Ich benutze Keil. In den Projekteinstellungen ist die Startadresse> hinterlegt.
Das interressiert den µC aber nicht die Bohne. Für den ist nur der Wert
in SCB->VTOR relevant.
Ansonsten siehe Beitrag von Rainer Reusch, falls Du das korrekte File im
Projekt mit drin hast.
Christopher J. schrieb:> Dafür gibt es das VTOR (Vector Table Offset Register)Rainer R. schrieb:> Liegt die Applikations-Firmware beispielsweise auf der Adresse> 0x08020000, setzt man für VECT_TAB_OFFSET einfach den Wert 0x20000.> Schon klappt es auch mit den Interrupts!
VIELEN DANK JUNGS!!
Jim M. schrieb:> Das interressiert den µC aber nicht die Bohne. Für den ist nur der Wert> in SCB->VTOR relevant.>> Ansonsten siehe Beitrag von Rainer Reusch, falls Du das korrekte File im> Projekt mit drin hast.
Jupp, Danke auch an Dich!
Willst Du denn nicht wissen, was Dein Problem war?
Bei einen Jump aus einem Interrupt Kontext heraus kommst Du direkt in
den Reset Handler Deiner Applikation. Daher können Deine Interrupts in
der Applikation auch nicht funktionieren, weil Du aus dem ursprünglichen
Interrupt nie rauskommst.
Bülent C. schrieb:> Bei einen Jump aus einem Interrupt Kontext heraus kommst Du direkt in> den Reset Handler Deiner Applikation. Daher können Deine Interrupts in> der Applikation auch nicht funktionieren, weil Du aus dem ursprünglichen> Interrupt nie rauskommst.
Ich komme doch nicht aus einem Interrupt Kontext raus. Wie kommst Du auf
diesen murgs? Die Funktion von oben rufe ich ganz normal aus der main()
auf.
Rainer R. schrieb:> Die Lösung ist recht einfach. In der Datei system_stm32xxxx.c gibt es> die Definition VECT_TAB_OFFSET, die den Wert Null hat, und weiter unten> die Zeile>> SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in> Internal FLASH */>> Liegt die Applikations-Firmware beispielsweise auf der Adresse> 0x08020000, setzt man für VECT_TAB_OFFSET einfach den Wert 0x20000.> Schon klappt es auch mit den Interrupts!
Bin über diesen Fehler (?) auch schon gestolpert.
Eigentlich müsste der bootloader den VTOR setzen. Hat TO nicht gemacht.
Das applikations Programm überschreibt den VTOR mit einer Adresse, die
er aus einem source (!) file (system_stm32xxxxx.c) des Applikations
Programms holt (der dämliche OFFSET)
(Hätte TO mit VTOR machen können, wie es ihm beliebt.)
eigentlich sollte das Applikations programm mit dem linker file schon
bedient sein sollen. Wenn bootloader VTOR setzt, wäre alles schön. Aber
sytem_stm32xxxxx.c überschreibt den ja.
keine Ahnung, welche Strategie STM da verfolgt.
Anpassung im Linker file + Anpassung im Source code, um die Startadresse
der applikation zu ändern. Thats bullshit
---
hatte GCC nicht keil. Generiert über Stm32CubeMX.
system32xxxxx.c wurde autogeneriert über CubeMX
Martin B. schrieb:> Eigentlich müsste der bootloader den VTOR setzen.
Da wäre ich mir nicht sooo sicher. Wenn da ein flacshes Programm
geflasht wurde, könnte der Bootloader das u.U via HardFault Handler
mitbekommen - aber nur wenn VTOR später in der Applikation geladen wird.
Und bevor das Datensegment vollständig initialisiert ist will man im
Hauptprogramm normalerweise auch keine Interrupts haben.
Kann man aber natürlich anders sehen, YMMV.
Martin B. schrieb:> keine Ahnung, welche Strategie STM da verfolgt.
Wenn das nach der Initialiserung des Datensegments aufgerufen wird, dann
könnte man die Interrupt Tabelle komplett ins RAM legen.
Das ist mitunter praktisch weil man die Einträge als Function Pointer
einfach dynamisch ändern kann.
Oder man umgeht so mandatory wait states beim Schreiben/Löschen von
Flash Pages und kann derweil zeitkritische Interrups (aus dem RAM)
ausführen.
Jim M. schrieb:> Martin B. schrieb:>> keine Ahnung, welche Strategie STM da verfolgt.>> Wenn das nach der Initialiserung des Datensegments aufgerufen wird, dann> könnte man die Interrupt Tabelle komplett ins RAM legen.>> Das ist mitunter praktisch weil man die Einträge als Function Pointer> einfach dynamisch ändern kann.>> Oder man umgeht so mandatory wait states beim Schreiben/Löschen von> Flash Pages und kann derweil zeitkritische Interrups (aus dem RAM)> ausführen.
Das stimmt! Wäre mal ein Argument, das so zu machen.
Man lernt nie aus.
Bootloader schrieb:> Bülent C. schrieb:>> Bei einen Jump aus einem Interrupt Kontext heraus kommst Du direkt in>> den Reset Handler Deiner Applikation. Daher können Deine Interrupts in>> der Applikation auch nicht funktionieren, weil Du aus dem ursprünglichen>> Interrupt nie rauskommst.>> Ich komme doch nicht aus einem Interrupt Kontext raus. Wie kommst Du auf> diesen murgs? Die Funktion von oben rufe ich ganz normal aus der main()> auf.
Bekomme ich hierzu noch eine Antwort oder nicht?