Forum: Mikrocontroller und Digitale Elektronik STM32 HAL Jump zur applikation


von Bootloader (Gast)


Lesenswert?

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.
1
void startApplikation(void)
2
{
3
  
4
  JumpAddress = *(__IO uint32_t*) (APPLICATION_ADDRESS + 4);
5
  JumpToApplication = (pFunction)JumpAddress;
6
  HAL_RCC_DeInit();
7
  HAL_DeInit();
8
  SysTick->CTRL = 0; 
9
  SysTick->LOAD = 0; 
10
  SysTick->VAL  = 0; 
11
  __HAL_SYSCFG_REMAPMEMORY_SYSTEMFLASH();
12
  __set_MSP(*(__IO uint32_t*) APPLICATION_ADDRESS);
13
  JumpToApplication();
14
}

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.

von Jim M. (turboj)


Lesenswert?

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.

von Bootloader (Gast)


Lesenswert?

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

von Christopher J. (christopher_j23)


Lesenswert?

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)

von pegel (Gast)


Lesenswert?

In der HAL Lib gibt es einige IAP Beispiele, damit sollte es gehen.

von Bootloader (Gast)


Lesenswert?

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.

von Rainer R. (Firma: Reusch Elektronik) (reusch)


Lesenswert?

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!

von switch the vectab (Gast)


Lesenswert?


von Jim M. (turboj)


Lesenswert?

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.

von Bootloader (Gast)


Lesenswert?

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!!

von Bootloader (Gast)


Lesenswert?

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!

von Bülent C. (mirki)


Lesenswert?

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.

von Bootloader (Gast)


Lesenswert?

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.

von Martin B. (ratazong)


Lesenswert?

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

von Jim M. (turboj)


Lesenswert?

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.

von Jim M. (turboj)


Lesenswert?

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.

von Martin B. (ratazong)


Lesenswert?

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.

von Bootloader (Gast)


Lesenswert?

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?

von Bülent C. (mirki)


Lesenswert?

Steht doch alles oben... Lesen bringt einen immer weiter

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.