STM32 HAL Jump zur applikation

Gast #5275533
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.
Gast #5275574
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.
(Firma: Reusch Elektronik) #5275578
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!
#5275598
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.
Gast #5275692
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.
#5275737
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
#5275809
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.
#5275810
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.
#5276027
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.
Gast #5276580
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?

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren