STM32F4xx-Bootloader und Interrupts

Ich versuche, einen Bootloader für einen STM32F4xx zu schreiben (derzeit für das STM32F429 Discovery Board). Meine Anwendung sollte bei Adresse 0x08020000 starten, während der Bootloader bei 0x08000000 (Start of Flash) startet.

Ich habe die Anwendung mit CubeMX erstellt, den FLASH ORIGIN in der Linker-Datei auf 0x08020000 und den VECT_TAB_OFFSET in der Datei system_stm32f4xx.c auf 0x20000 geändert (dies ändert den VTOR auf 0x08020000). Meine Anwendung blinkt nur eine LED und funktioniert wie erwartet an dieser neuen Adresse, wenn sie von der IDE gestartet wird.

while(true) {
    HAL_Delay(200);
    HAL_GPIO_TogglePin(GPIOG, GPIO_PIN_13);
}

Anstatt den Bootloader sofort zu schreiben (eigentlich habe ich das getan und es hat nicht funktioniert), habe ich das ST-Link-Dienstprogramm verwendet und ein paar Dinge getan: Ich habe überprüft, dass alles außer der Anwendung gelöscht ist (0xff). Ich setze die CPU zurück und setze den PC manuell auf 0x08021924 (dies ist der Reset_Handler laut Map-Datei aus der Anwendung). Wenn ich langsam durch die Anwendung gehe/laufe, kann ich Folgendes sehen: Der SP ist korrekt geschrieben (da dies Teil des Start-Assembler-Codes von CubeMX ist). Der VTOR ist korrekterweise auf 0x08020000 gesetzt (ich lese den SCB manuell bei Adresse 0xE000ED00 aus, der 3. Wert ist der VTOR) und nach einiger Zeit loopt die Anwendung innerhalb der HAL_GetTick & HAL_Delay Funktion (ich habe den PC ausgelesen und mit der Karte verglichen Datei). Ich sehe sogar, dass die Anwendung den uwTick liest (in meinem Fall an der Adresse 0x20000020), die niemals erhöht wird, und daher wird die HAL_Delay-Schleife für immer wiederholt. also mein Fazit ist:

Die Interrupts scheinen nicht richtig zu funktionieren

in diesem Fall der SysTick ... Trotz eines korrekten VTOR scheint auch die Anwendung einwandfrei zu laufen. Wenn ich HAL_Delay durch ein Busy_Delay ersetze (das nur aus einer Schleife von Millionen von NOP besteht), blinkt die LED. Wenn ich es manuell über die erwähnte Methode (oder einen manuell geschriebenen Bootloader mit Sprüngen zur richtigen Adresse) starte, läuft die Anwendung normal (weil in diesem kurzen Beispiel wahrscheinlich nichts von Interrupts abhängt).

Was fehlt mir, um einen funktionierenden Bootloader (mit funktionierenden Interrupts) zu schreiben?

Schon mal im STM32-Forum gesucht ? Ich bin mir nicht sicher, aber ich glaube, ähnliche Fragen wurden dort schon oft gestellt und beantwortet.
Du hast Recht, das Forum ist voll von solchen Fragen, aber viele davon unbeantwortet und konnte bisher keine Lösung für mein spezielles Problem finden, oder einige Leute haben ähnliche Probleme und umgehen es.

Antworten (1)

Ich glaube, ich habe selbst ein fehlendes Glied gefunden.

Anstatt zum Reset_Handler selbst zu springen, hilft der Sprung zum Reset_Handler + 1. Dies setzt das LSB auf 1 und zeigt an, dass es sich um einen Daumencode handelt. Für die IRQ-Handler ist es im ARM Information Center dokumentiert .

Die meisten (wenn nicht alle) Sprünge im generierten Code von C haben ein LSB 0 von Null (und Interrupts funktionieren immer noch), ich verstehe nicht ganz, warum es notwendig ist, das LSB in meinem Fall zu setzen. Vielleicht: Normalerweise sind die Sprünge relativ (aber im Debugger in Adressen mit einem LSB von 0 übersetzt), aber der Sprung zum Bootloader ist eine Adresse, die zuerst mit einem Register geladen und dann auch gesprungen wird.