Forum: Mikrocontroller und Digitale Elektronik STM32: Keine Interrupte nach Vector Table Relocation


von BrilleAuf (Gast)


Lesenswert?

Hallo Forum,

ich habe auf einem STM32F103 das Problem, dass nach einer Vector Table 
Relocation keine Interrupte mehr auslösen.

Um diesem Fehler zu ergründen, habe ich mit der aktuellen STM32CubeMX 
eine Testapplikation erstellt, die nur Systick und Timer2 bedient und 
einen IR auslösen kann.
Die ISR von Timer2 inkrementiert eine Variable je um eins.

Diese Applikation läuft ohne Probleme wenn...
...sie ohne VT Offset läuft,
...sie mit VT Offset läuft, die vorgannte Variante aber zuvor nicht aus 
dem Flash gelöscht wurde.

Wenn jedoch der Flash zuerst gelöscht und dann aufgespielt wird, lösen 
die IR nicht mehr aus.

Ich habe die betreffenden Register zwischen funktionierender und nicht 
funktionierender Applikation verglichen...SETENA, CLRENA sind gesetzt 
für Timer2.
PRIMASK, BASEPRI, FAULTMASK sind 0, das ist auch OK.
VTOR berücksichtigt den Offset 0x5000, also auch OK.

Allerdings habe ich bei Programmstop SCB->ICSR einen Unterschied 
feststellen. VECTACTIVE ist dort 0x3. Nach Doku wäre das IR 3-16=-13, 
der gerade aktiv ist. Was für ein Interrupt ist das? Wäre das Hardfault?

Mir fehlt da an der Stelle ein bisschen der Ansatz. Kann mir jemand vllt 
einen Hinweis geben...?

Gruß

von Jump (Gast)


Lesenswert?

Es reicht nicht den Code an anderer Stelle im Flash abzulegen und den 
Zeiger auf die Vektortabelle anzupassen. Am Anfang des Flash muss 
zusätzlich eigener Code (ein Jump oder eine geeignete VT) stehen, der 
die Code-Ausführung an das Programm weiter gibt.
(Habe lange keine STMs mehr programmiert. Hoffentlich verwechsel ich da 
nichts.)

von BrilleAuf (Gast)


Lesenswert?

Hallo,

ich tue drei Dinge, damit VTOR wirksam wird:

Linkerfile anpassen:
…
MEMORY
{
FLASH (rx)      : ORIGIN = 0x08005000, LENGTH = 108K   // <-hier
RAM (xrw)      : ORIGIN = 0x20000000, LENGTH = 20K
}
…

System_stm32f1xx.c anpassen:
…
#define VECT_TAB_OFFSET  0x5000 /*!< Vector Table base offset field.
                                  This value must be a multiple of 
0x200. */
…

Target Software Startup Script anpassen (Truestudio):
...
# Reconfig vector table offset reg to match pp location
set *0xe000ed08 = 0x5000

# Get app stackpointer
set $sp = *(unsigned int*)0x5000

# Get app entry point
set $pc = *(unsigned int*)0x5004
...


Habe ich etwas vergessen...?

Gruß

von Jump (Gast)


Lesenswert?

Ich meine schon. Der STM32 startet doch immer bei 0x08000000. Oder 
nicht?
Wenn das Programm bei 0x08005000 liegt, dann fehlt noch ein zweites 
Programm bei 0x08000000, welches den Sprung macht. In EMBlocks habe ich 
jedenfalls (aus welchen Gründen auch immer) so gemacht. Truestudio habe 
ich nie verwendet.

von Darth Moan (Gast)


Lesenswert?

BrilleAuf schrieb:
> # Reconfig vector table offset reg to match pp location
> set *0xe000ed08 = 0x5000
>
> # Get app stackpointer
> set $sp = *(unsigned int*)0x5000
>
> # Get app entry point
> set $pc = *(unsigned int*)0x5004

Ich kenne TreuStudio nicht, aber muesste es da nicht 0x08005000 und
0x08005004 heissen?

von Alex D. (daum)


Lesenswert?

Jump schrieb:
> Ich meine schon. Der STM32 startet doch immer bei 0x08000000. Oder
> nicht?

Glaube ich auch

Wo befindet sich der Code deines Startup scripts? du könntest im Linker 
Script noch eine section von 0x08000000 bis 0x08005000 definieren in die 
du den startup code legst, der dann entweder gleich alles dort macht 
oder einfach zum echten startup code auf 0x08005000 springt

von Alex D. (daum)


Lesenswert?

Darth Moan schrieb:
> Ich kenne TreuStudio nicht, aber muesste es da nicht 0x08005000 und
> 0x08005004 heissen?

Soweit ich weiß bootet der stm32 immer von 0x0, aber remapped 
unterschiedlichen speicher dorthin, je nach gesetzten boot pins, also 
ist bei normalem boot mode 0x8000000 und 0x0 der gleiche Speicher.

von Darth Moan (Gast)


Lesenswert?

Er verwendet aber ein start script im TrueStudio, das VTOR, SP und PC
explizit setzt. siehe oben.

Die SystemInit will doch auch die 'ganze' Adresse ins VTOR schreiben:
SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in 
Internal FLASH */

Er setzt da aber nur 0x5000 rein.

von Darth Moan (Gast)


Lesenswert?

Ich mutmasse jetzt natürlich, dass er später ab 0x08000000 eine 
Bootloader
einfügen möchte. Aber jetzt mit TrueStudion nur die Applikation testen
will.
Ist natürlich etwas viel gemutmasst.

von pegel (Gast)


Lesenswert?

Da CubeMX im Spiel ist, wird vermutlich HAL benutzt.

In der HAL Lib gibt es ein Beispiel IAP_Binary_Template das von 
IAP_Main(Bootloader) aufgerufen wird.

Brauchst davon nur den else Zweig:
1
/* Jump to user application */

Irgendwie muss er aber schon wissen wohin der Sprung gehen soll.

von Alex D. (daum)


Lesenswert?

Darth Moan schrieb:
> Ich mutmasse jetzt natürlich, dass er später ab 0x08000000 eine
> Bootloader
> einfügen möchte. Aber jetzt mit TrueStudion nur die Applikation testen
> will.

Dann wäre es am einfachsten schon jetzt eine bootloader section 
einzubauen und dort nur einen jump zur application machen. Sollte dann 
evtl funktionieren.

von Jump (Gast)


Lesenswert?

Ich entwickle meine Programme immer bei 0x08010000. Erst das Release 
wird für 0x08000000 kompiliert. Grund: Es kommt vor, dass ich zigtausend 
Flashvorgänge bis zum Release brauche. Auf diese Weise lässt selbst ein 
STMF030 (erlaubt wären dort nur 1000 Zyklen) mit gutem Gewissen 
debuggen.

Möglicherweise wusste ich nicht wie man eine "bootloader section" 
erstellt und habe mir deshalb mit einem zweiten Programm geholfen. Das 
zweite Programm müsste nur einmalig als Starterprogramm nach 0x08000000 
geflasht werden. Für "BrilleAuf" könnte es so aussehen:
1
int main(void)
2
{
3
  const void* ImgPtr = (void*)0x08005000;
4
  void (*pMainApp)(void) = *(void (**)(void))(ImgPtr+4);
5
  pMainApp();
6
  return 0;
7
}

von Darth Moan (Gast)


Lesenswert?

Alex D. schrieb:
> Dann wäre es am einfachsten schon jetzt eine bootloader section
> einzubauen und dort nur einen jump zur application machen. Sollte dann
> evtl funktionieren.

Auch wenn er explizit 0x5000 ins VTOR schreibt?

BrilleAuf schrieb:
> Target Software Startup Script anpassen (Truestudio):
> ...
> # Reconfig vector table offset reg to match pp location
> set *0xe000ed08 = 0x5000

Wie gesagt, TrueStudio hab ich nicht.
Also eigentlich bin ich ja auch der Meinung, es ist besser, sofort ein
Bootloader-Placebo zu benutzen.
Dann kann man auch gleich testen ob es ohne Debugger startet.
Man weiss ja nicht so genau, was die da sonst noch so alles
initialisieren.

von Alex D. (daum)


Lesenswert?

Darth Moan schrieb:
> Auch wenn er explizit 0x5000 ins VTOR schreibt?

Denke schon, habe auch mal schnell mit einem Debugger getestet: bei 
normalem boot (boot0 == 0 && boot1 == 0) wird 0x8000000 auf 0x0 
remapped, das heißt auf 0x5000 ist der gleiche speicher wie auf 
0x8005000. Ist vielleicht nicht der beste Stil und ziemlich verwirrend, 
aber sollte (denke ich) funktionieren.

von Jump (Gast)


Lesenswert?

Es kann doch VTOR nur per -Programm- beschrieben werden. Der Start ist 
dann aber schon geschehen. Die Startadresse in der Vektortabelle wird 
also nicht mehr berücksichtigt. Das heisst, es muss -vorher- für 
passende Daten bei 0x08000000 (eine VT evtl. mit Code) für den Sprung 
zum Programm gesorgt werden. Entweder per zweites Programm oder Einträge 
im Linkerskript evtl. automatisch generiert infolge eines 
Häkchens/Befehls in Truestudio.

"BrilleAuf" hat das Problem vermutlich schon gelöst.

von Bernd K. (prof7bit)


Lesenswert?

Du musst zunächst einen Dummy-Bootloader (oder auch schon den echten 
Bootloader) flashen der

* Sicherstellt dass jetzt kein Interrupt mehr kommt
* VTOR umbiegt
* Den Stackpointer mit dem Inhalt von 0x8005000 lädt
* Den Programcounter mit dem Inhalt von 0x8005004 lädt

Beispiel aus meinem CAN-Bootloader:

(APP_START ist bei mir ein makro das die Adresse der verschobenen 
Vektortabelle enthält und beispielhaft deinitialisiere ich hier eine im 
Bootloader benutzte Hardware die ansonsten weiter lustig Interrupts 
generiert hätte)
1
/**
2
 * Prepare everything for running the application and jump
3
 * to its entry point.
4
 */
5
void jump_app(void) {
6
    /*
7
     * de-initialize all interrupt using hardware
8
     * because we are going to relocate the vector
9
     * table now and MUST NOT cause any IRQ anymore
10
     */
11
    flexcan_deinit();
12
13
    // relocate the vector table and simulate reset
14
    SCB->VTOR = APP_START;
15
    asm(" ldr r1, [%0,#0]    \n\t"
16
        " ldr r2, [%0,#4]    \n\t"
17
        " mov sp, r1         \n\t"
18
        " mov pc, r2         \n\t"
19
        ::"r"(APP_START)
20
    );
21
}

Du machst also entweder nen Dummy-Bootloader oder nen echten Bootloader 
der nach einem Reset oder nach dem Einschalten zügig das obige macht und 
flasht den nach 0x8000000

Von dem Moment an kannst Du Deine für 0x8005000 gelinkte Anwendung ganz 
normal in der IDE laden und debuggen so oft Du willst, nur kein chip 
erase machen sonst ist der Bootloader wieder weg.

Deaktiviere falls vorhanden auch jegliche flash security in Deinem 
Bootloader (setze im Bootloader nicht die Lockbits wie sonst üblich bei 
kommerziellen Projekten) sonst schlägt der Bootloader beim ersten Start 
die Tür hinter sich zu und schließt zweimal ab und es wird nichts mit 
debuggen.

: Bearbeitet durch User
von Marvin M (Gast)


Lesenswert?

Man braucht kein komplettes Programm, man muss lediglich dafür sorgen, 
dass der Reset-Vektor an 0x0800004 die richtige Adresse (hier: 
0x08005000) beinhaltet. Stackpointer-Initialwert auch an 0x08000000 
eintragen. Dann klappts auch mit dem Starten eine Applikation an 
beliebiger Stelle im Speicher.

von pegel (Gast)


Lesenswert?

Marvin M schrieb:
> Man braucht kein komplettes Programm, man muss lediglich dafür sorgen,

Bist du sicher?

Ich habe das gerade mit einem BluePill Board probiert und es klappt 
nicht.

Mein vorgehen:
1
1. in CubeMX normales Projekt angelegt, PC13 ist LD1
2
2. SW4STM32 Projekt erzeugt
3
3. in der main.c LD1 Blinky eingebaut
4
3.1. in der system_stm32f1xx.c -> #define VECT_TAB_OFFSET  0x00005000U
5
3.2. in der STM32F103C8Tx_FLASH.ld -> 
6
     FLASH (rx) : ORIGIN = 0x8005000, LENGTH = 64K - 20k
7
4. Projekt bauen
8
5. mit STM32CubeProg GUI kontrolliert, Programm liegt an 0x08005000
9
6. bei disconnet startet STM32CubeProg das Programm, es blinkt
10
7. noch einmal CubeMX aufgerufen, verändert, Projekt erzeugt, 
11
die system_stm32f1xx.c und die STM32F103C8Tx_FLASH.ld behalten die Änderungen und werden nicht überschrieben!
12
8. mit dem CubeProgrammer CLI ab Adresse 0x08005000 gestartet, blinkt
13
Aufruf: ./STM32_Programmer.sh -c port=SWD -g 0x08005000
14
15
Ein schreiben von 20005000 und 08005000 an Adresse 0x08000000 funktioniert allerdings nicht. Das Programm startet nicht nach Reset oder PON.
16
17
Startet mit Punkt 8 aber sofort wieder.

von pegel (Gast)


Lesenswert?

Aha, an die 0x08000004 muss nicht 08005000 sondern die wirkliche Start 
Adresse die auch auf 0x08005004 steht, dann läufts.

von pegel (Gast)


Lesenswert?

Dann braucht man wirklich keinen Bootlader oder Sonstiges.

von BrilleAuf (Gast)


Lesenswert?

Darth Moan schrieb:
> Er verwendet aber ein start script im TrueStudio, das VTOR, SP und PC
> explizit setzt. siehe oben.
>
> Die SystemInit will doch auch die 'ganze' Adresse ins VTOR schreiben:
> SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in
> Internal FLASH */
>
> Er setzt da aber nur 0x5000 rein.

Ja, aber im VTOR steht dann 0x8005000. Es geht ja hier nur um vereiste 
ISR. Die App würde sonst nicht laufen.

von BrilleAuf (Gast)


Lesenswert?

Darth Moan schrieb:
> Ich mutmasse jetzt natürlich, dass er später ab 0x08000000 eine
> Bootloader
> einfügen möchte. Aber jetzt mit TrueStudion nur die Applikation testen
> will.
> Ist natürlich etwas viel gemutmasst.

Liegst aber schon ganz richtig. Deshalb eine 
Grüne-Wiese-Testapplikation.

von Joerg W. (joergwolfram)


Lesenswert?

Ein ähnliches Problem habe ich auch, wenn ich Applikationen testweise 
ins RAM lade und dort starte. Auch wenn ich VTOR setze, werden 
(scheinbar) keine INTs ausgelöst. Woran es wirklich liegt, habe ich aber 
nicht herausgefunden.

Jörg

von BrilleAuf (Gast)


Lesenswert?

pegel schrieb:
> Dann braucht man wirklich keinen Bootlader oder Sonstiges.

Ja, das war auch so mein Verständnis...nach dieser Literatur:

http://info.atollic.com/hubfs/Whitepapers/Atollic_Develop_Debug_BootloaderApps_ARMCortex.pdf


..und nein, BrilleAuf hat das Problem noch nicht gelöst :-(

von pegel (Gast)


Lesenswert?

Hänge mal deine fertige hex an, dann versuche ich zu vergleichen.

von BrilleAuf (Gast)


Angehängte Dateien:

Lesenswert?

pegel schrieb:
> Hänge mal deine fertige hex an, dann versuche ich zu vergleichen.

Ich habe das Gefühl, dass Pegel hier schon auf dem richtigen Weg ist.

Das sind jetzt zwei Varianten. eine ohne VT Offset und ein mit VT Offset 
0x5000.

von pegel (Gast)


Lesenswert?

Auf den ersten Blick sieht das gut aus.

Alle Int. Vectoren sind um 0x00005000 versetzt, so wie es sein muss.

Der Tim2 Interrupt an 0x080050B0 ist vermutlich auch richtig belegt.

Es ist nicht ein fehlendes volatile oder so etwas in der Art, oder?

von pegel (Gast)


Lesenswert?

Lass doch deinen Timer2 ein Pin toggeln, am Besten PC13.

Mit Oszi sieht man dann leicht was sich tut.

von BrilleAuf (Gast)


Lesenswert?

Man kann in der Hauptschleife mit dem Debugger stoppen. Dann sehe 
ich,dass Systick und Timerwerte erhöht wurden. Die funktionieren, denke 
ich.

Was ich wirklich nicht sicher klären kann ist, warum der aktuelle IR 0x3 
sein soll und was das bedeutet. Man kann das z.B. aus xPSR lesen...Man 
muss dort noch 16 abziehen, also 3-16=-13 :-\

Scheint vllt so zu sein, dass dieser IR alles blockiert...

von Jump (Gast)


Lesenswert?

BrilleAuf schrieb:
> Liegst aber schon ganz richtig. Deshalb eine
> Grüne-Wiese-Testapplikation.

Es soll also einen Bootloader geben. Gibt es den?

In "TestISR.VTOR_5k.hex" ist nichts für den Startbereich (ersten 8 Bytes 
von 0x0800000) definiert. Solange Du diesen nicht definierst (Bootloader 
oder Linkerskript), wird das Laufverhalten definitiv undefiniert sein! 
Es ist daher fraglich was du da debuggst.

von BrilleAuf (Gast)


Lesenswert?

OK.

für diesen Test gibt es aktuell keinen BL. Ich probiere hier alles ohne.

Im Linkerfile gibt es genau eine Anpassung:

…
MEMORY
{
FLASH (rx)      : ORIGIN = 0x08005000, LENGTH = 108K   // <-HIER 
angepasst
RAM (xrw)      : ORIGIN = 0x20000000, LENGTH = 20K
}
…

Kann es sein, dass der MSP hier noch her muss? :-|

von Darth Moan (Gast)


Lesenswert?

Moin,

BrilleAuf schrieb:
> Was ich wirklich nicht sicher klären kann ist, warum der aktuelle IR 0x3
> sein soll und was das bedeutet. Man kann das z.B. aus xPSR lesen...Man
> muss dort noch 16 abziehen, also 3-16=-13 :-\

Na wenn ich mich nicht verzähle müsste das ja dann der Hard Fault sein.
Wenn also aus irgendeinem Grund der Debugger an Adresse 0x5000 nicht das
selbe liest, wie an 0x08005000 dann könnte er ziemlich bald in den Hard
Fault wollen.
Wenn der Vector, den er zu lesen glaubt aber illegal ist, was dann?
Hattest du mal versucht die set Anweisungen mit 0x08005000 und 
0x08005004
auszuführen?
Kannst du dann den Startup code single steppen?

So ein Verhalten hatte ich nur mal als der Hard Fault versehentlich 
mitten
ins Programm gezeigt hatte. Der wurde angesprungen, und alles unterhalb
war damit blockiert. Ich lief dann irgendwann auf meinen BP, aber eben
nur zufällig.

von Jump (Gast)


Lesenswert?

Darth Moan schrieb:
> Na wenn ich mich nicht verzähle müsste das ja dann der Hard Fault sein.
Ohne Bootloader wäre das eigentlich nicht unerwartet.

BrilleAuf schrieb:
> Kann es sein, dass der MSP hier noch her muss? :-|

Zur Zeit wird zwar der neue Code geflasht, der aktive ist aber 
irgendwas. Dein Linkerskript hat zur Zeit keine oder keine passenden 
Einträge, da im  Hex-File nichts für 0x08000000 definiert ist.

Das Anpassen des Linkerskripts (etwas Code ist auch nötig) wäre zwar 
weniger Arbeit, ist aber deutlich schwerer (viele Fehlerquellen -> 
dauert länger). Da du sowieso einen Bootloader verwenden willst, würde 
ich an deiner Stelle eher das tun. Du bräuchtes dann ein zweites 
Projekt. Beispiel für main.c vom Bootloader:
1
int main(void)
2
{
3
  const void* ImgPtr = (void*)0x08005000;
4
5
  // Set VectorTable
6
  SCB->VTOR = (uint32_t)ImgPtr;
7
8
  // Set Stack Pointer
9
  __set_MSP((*(uint32_t*)ImgPtr));
10
11
  // Set Program Pointer
12
  void (*pMainApp)(void) = *(void (**)(void))(ImgPtr+4);
13
  pMainApp(); // ist eigentlich ein Call statt Jump, aber egal
14
  return 0;
15
}


Da evtl. nach dem Bootloader noch irgendwo falsche Werte für VTOR 
gesetzt werden, füge bitte zu Testzwecken in deiner main.c vom 
Hauptprogramm eine erneute Zuweisung der Vektortabelle durch:
1
SCB->VTOR = 0x08005000;

von BrilleAuf (Gast)


Lesenswert?

Ich hatte mich auch schon gefragt, ob ich mich verzählt habe. Scheint 
theoretisch wirklich der Hardfault zu sein. Schön, das es einer 
verifiziert hat.

Die Zusammenhänge erscheinen mir aber komisch. Das fehlt irgendwas :-(

Muss ich mal am WE drüber nachdenken...

Danke an alle für die bisherigen Infos!

Beitrag #5728653 wurde von einem Moderator gelöscht.
von Jump (Gast)


Lesenswert?

BrilleAuf schrieb:
> Die Zusammenhänge erscheinen mir aber komisch. Das fehlt irgendwas :-(

Warum "komisch"???

Da wird irgendwas ausgeführt, da der Bootloader fehlt. Erstelle erst 
einen Bootloader!

von Darth Moan (Gast)


Lesenswert?

Äh, mal ne doofe Frage, muss das Start Script SP setzen oder MSP?
Macht TrueStudio da einen Unterschied?

> set $pc = *(unsigned int*)0x5004

Jump schrieb:
> __set_MSP

von Darth Moan (Gast)


Lesenswert?

Jump schrieb:
> Warum "komisch"???
>
> Da wird irgendwas ausgeführt, da der Bootloader fehlt. Erstelle erst
> einen Bootloader!

Er setzt im Debugger explizit den PC auf seinen Applikations-Einstieg 
und
lässt dann den Core loslaufen. Wenn der Debugger richtig funktioniert,
wovon ich ausgehe, sollte er nicht erst den Core durch den Reset 
schicken.
Aber wer weiss.
Daher die Frage nach dem Steppen.

von Jump (Gast)


Lesenswert?

Darth Moan schrieb:
> Er setzt im Debugger explizit den PC auf seinen Applikations-Einstieg
> und

Wirklich? Hat er das geschrieben?

von Darth Moan (Gast)


Lesenswert?

Jump schrieb:
>> Er setzt im Debugger explizit den PC auf seinen Applikations-Einstieg
>> und
> Wirklich? Hat er das geschrieben?

BrilleAuf schrieb:
> Target Software Startup Script anpassen (Truestudio):
> ...
> # Get app entry point
> set $pc = *(unsigned int*)0x5004

Also ich interpretiere das TrueStudio Start Script genau so.
Aber ich habe TrueStudio nicht, also erstmal nur Vermutung.
Vielleicht sollte ich TrueStudio mal ausprobieren.

von Jump (Gast)


Lesenswert?

Ok, er hat es wirklich geschrieben. Das "Startup Script" betrifft also 
den Debugger und nicht wie ich glaubte den Compiler/Linker. Es sollte 
dann eigentlich ohne Bootloader laufen.

Im "Startup Script" setzt er VTOR, Stackpointer und Entry point. Das 
sieht alles richtig aus. Aber - möglicherweise wird VTOR beim Startup 
seines Programms (EntryPoint bis main.c) unbewusst verändert (bei 
"EmBlocks" würde das nämlich in  SystemInit() passieren). Man könnte 
einen Breakpoint in der main.c setzen und prüfen, ob VTOR (*0xe000ed08) 
tatsächlich noch 0x08005000 ist.

von Bernd K. (prof7bit)


Lesenswert?

Jump schrieb:
> (bei
> "EmBlocks" würde das nämlich in  SystemInit() passieren)

EmBlocks ist eine IDE, was hat die damit zu tun was der OP in seiner 
SystemInit macht?

von Bernd K. (prof7bit)


Lesenswert?

Ich verstehe nicht was der Zirkus soll. Flash doch einfach schonmal den 
Bootloader drauf, danach wird sich die verschoben gelinkte Firmware ganz 
normal debuggen lassen. Der Bootloader wird dafür sorgen daß alles 
richtig ist bevor er sie anspringt.

von Jump (Gast)


Lesenswert?

Bernd K. schrieb:
> EmBlocks ist eine IDE, was hat die damit zu tun was der OP in seiner
> SystemInit macht?

Bei EmBlocks wird beim Anlegen eines Standardprojekts Code 
zusammengestellt. Die SystemInit() steht in der Datei 
"system_stm32f10x.c". Als Autor wird "MCD Application Team" genannt. Der 
Code kann bei allen IDE's laufen, muss aber nicht (z.B. geht auch reines 
ASM).

Bernd K. schrieb:
> Ich verstehe nicht was der Zirkus soll. Flash doch einfach schonmal den
> Bootloader drauf, danach...

Nein. Wenn über Debugger (richtig) gestartet, dann braucht man den 
Bootloader nicht. Dort liegt nicht das Problem. (Ich selber würde es 
aber auch über den Bootloader machen.)

von Bernd K. (prof7bit)


Lesenswert?

Jump schrieb:
> Nein. Wenn über Debugger (richtig) gestartet, dann braucht man den
> Bootloader nicht.

Der Debugger müsste dann aber auch VTOR umstellen bevor er es startet. 
Oder das Programm muss irgendwo beim Start selbst das VTOR für sich 
umbiegen was aber ebenfalls unelegant ist.

Und warum ist es mit Bootloader eleganter? Ganz einfach: Wenn man das 
alles den Bootloader machen lässt und selber die VTOR unangetastet lässt 
dann ist der einzige Unterschied zwischen Standalone-Anwendung und 
verschobener Anwendung die Angabe eines anderen Linkerscripts im 
Makefile. Man muß weder in der IDE noch in den Debuggereinstellungen 
irgendwelche Einstellungen ändern um es mal in der einen und mal in der 
anderen Form zu debuggen, das halte ich für eleganter und in der Praxis 
auch einfacher zu handhaben wenn weder irgendwelcher Code in der 
Anwendung noch die Debuggereinstellungen irgendwas davon wissen müssen 
mit welchem Linkerscript zufällig gerade gelinkt wurde und an welcher 
Stelle im Flash die Anwendung zu liegen kommt.

Einzige Voraussetzung: Wenn die bootloaderfähgige Konfiguration debuggt 
werden soll muss auch ein Bootloader drauf sein, was auch einen 
ziemlichen Sinn ergibt denn man will ja auch mal das Gesamtgebilde 
debuggen wie es später mal laufen soll.

: Bearbeitet durch User
von Joe J. (j_955)


Lesenswert?

Alles durchlesen ist mir jetzt zu aufwendig - auf die Gefahr hin, dass 
die ANtwort  überflüssig ist: guck mal im Manual nach dem Alignement für 
die Vector Interrupt Tabelle. Kann sonst sein, dass hier was 
abgschnitten wird. Typisch für STMs.

No Risk No FUN;-)

von Jump (Gast)


Lesenswert?

Joe J. schrieb:
> ...Alignement...

Gefordert sind 0x200 Alignment und "BrilleAuf" verwendet 0x5000. -> 
passt

Bernd K. schrieb:
> Der Debugger müsste dann aber auch VTOR umstellen bevor er es startet.
> Oder das Programm muss irgendwo beim Start selbst das ...

Unterstreiche ich alles.

Ich habe da noch einen Speziallfall...
Ich verwende den STMF030 sehr häufig. Da der Flash nur 1000 Zyklen 
verträgt, verschiebe ich das Programm beim Debuggen in den oberen 
Flash-Bereich. Ein separater Bootloader ist für diesen speziellen Fall 
ziemlich umständlich. Deshalb pfusche ich den Bootloader direkt mit in 
das Projekt hinein. (Das Ganze macht natürlich nur dann Sinn, wenn der 
Flasher nicht grundsätzlich den gesamten Flash neu beschreibt, sondern 
unveränderte Flash-Seiten erkennt und überspringt.)


Ergänzung bzw. Änderung im Linkerskript:
1
MEMORY
2
{
3
    ROMB (rx) : ORIGIN = 0x08000000, LENGTH = 64   /* neue Zeile */
4
    ROM  (rx) : ORIGIN = 0x0801ac00, LENGTH = 4K   /* bestehende Zeile geändert */
5
    ...
6
}


Ergänzung im Linkerskript:
1
SECTIONS
2
{
3
    .myboot :
4
    {
5
        KEEP(*(.myboot.vtable));
6
        KEEP(*(.myboot.loader));
7
    } > ROMB
8
    ...
9
}



Ergänzung im Quellcode:
1
// Bootloader-Source
2
void __attribute__((naked, optimize("-Os"), section(".myboot.loader"))) MyBoot_Loader()
3
{
4
  extern uint32_t __isr_vector;
5
  SCB->VTOR = (uint32_t)&__isr_vector;
6
  goto *(void*)((&__isr_vector)[1]);
7
}
8
// Bootloader-vtable
9
extern uint32_t __StackTop;
10
__attribute__((section(".myboot.vtable"))) void* MyBoot_VectorTable[2] =
11
{
12
  &__StackTop,
13
  MyBoot_Loader
14
};

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.