Hallo zusammen,
ich habe einen bootlaoder geschrieben, der eine Applikation zuerst
checkt und dann an der Adresse: 0x8060100 starten soll.
An der Adresse 0x8060000 sollen 256 Bytes Daten eines Headers reserviert
sein und danach soll das Applikationscode folgen.
Ich habe folgende bekannte codezeilen probiert. Leider ging es nicht
Es hängt und tut sich nichts mehr.
=================================================================
addr = (GetApplicationStartAddress() + sizeof(APP_HEADER)+4);
JumpAddress = *(__IO uint32_t*) addr;
Jump_To_Application = (pFunction) JumpAddress;
__set_MSP(*(__IO uint32_t*)(GetApplicationStartAddress() +
sizeof(APP_HEADER)) );
Jump_To_Application();
while(1)
{
LED_Blink();
}
wenn ich debugge finde ich:
addr: 0x8060104
JumpAddress: 0x80602F5
Jump_To_Application: 0x80602F5
Laut der Map-Datei der Applikation sollte eigentlich alles in Ordnung
sein:
========================================================================
==
__ARM_use_no_argv 0x00000000 Number 0
main.o ABSOLUTE
_cpp_initialize__aeabi - Undefined Weak Reference
__cxa_finalize - Undefined Weak Reference
__decompress - Undefined Weak Reference
_clock_init - Undefined Weak Reference
_microlib_exit - Undefined Weak Reference
__Vectors_Size 0x000001e0 Number
0 startup_stm32f722xx.o ABSOLUTE
__Vectors 0x08060100 Data
4 startup_stm32f722xx.o(RESET)
__Vectors_End 0x080602e0 Data
0 startup_stm32f722xx.o(RESET)
__main 0x080602e1 Thumb Code
0 entry.o(.ARM.Collect$$$$00000000)
_main_stk 0x080602e1 Thumb Code
0 entry2.o(.ARM.Collect$$$$00000001)
_main_scatterload 0x080602e5 Thumb Code
0 entry5.o(.ARM.Collect$$$$00000004)
__main_after_scatterload 0x080602e9 Thumb Code
0 entry5.o(.ARM.Collect$$$$00000004)
_main_clock 0x080602e9 Thumb Code
0 entry7b.o(.ARM.Collect$$$$00000008)
_main_cpp_init 0x080602e9 Thumb Code
0 entry8b.o(.ARM.Collect$$$$0000000A)
_main_init 0x080602e9 Thumb Code
0 entry9a.o(.ARM.Collect$$$$0000000B)
__rt_final_cpp 0x080602f1 Thumb Code
0 entry10a.o(.ARM.Collect$$$$0000000D)
__rt_final_exit 0x080602f1 Thumb Code
0 entry11a.o(.ARM.Collect$$$$0000000F)
Reset_Handler 0x080602f5 Thumb Code
8 startup_stm32f722xx.o(.text)
ADC_IRQHandler 0x0806030f Thumb Code
0 startup_stm32f722xx.o(.text)
CAN1_RX0_IRQHandler 0x0806030f Thumb Code
0 startup_stm32f722xx.o(.text)
CAN1_RX1_IRQHandler 0x0806030f Thumb Code
0 startup_stm32f722xx.o(.text)
CAN1_SCE_IRQHandler 0x0806030f Thumb Code
0 startup_stm32f722xx.o(.text)
CAN1_TX_IRQHandler 0x0806030f Thumb Code
0 startup_stm32f722xx.o(.text)
und Hier ist der Linker Skript für die Applikation:
===================================================
LR_IROM1 0x08060100 0x0001FF00 { ; load region size_region
ER_IROM1 0x08060100 0x0001FF00 { ; load address = execution address
*.o (RESET, +First)
*(InRoot$$Sections)
.ANY (+RO)
}
RW_IRAM1 0x20000000 0x00040000 { ; RW data
.ANY (+RW +ZI)
}
}
LR_ROM2 0x08060000 0x00000100
{
ER_ROM2 0x08060000 0x00000100
{
Header.o(.constdata)
}
}
liegt es jetzt an der Applikation oder an das Starten der Applikation
vom Bootloader.
Ich bedanke mich für jede Hilfe.
Gruß
Laspalmas
Wenn die Startadresse tatsächlich 0x8060100 sein soll, ist das '+4' doch
zuviel?
Es lohnt sich, den Assembler-Code mal zu kontrollieren. Denn die
Startadresse kann sicher nicht 0x8060100 lauten, sondern müsste wohl
0x8060101 lauten, wenn ein Sprung dahin ausgeführt wird. Das LSB muss
gleich '1' sein, da bei ARM das den Thumb-Mode anzeigt.
Vielleicht wird das vom Compiler hier nicht automatisch gemacht, da
vorher mit der Adresse herumgerechnet wird?
Und wie üblich: "Es hängt und tut sich nichts mehr." ist wenig
hilfreich. Schließlich kann man mit dem Debug-Interface doch gerade dann
in den Controller hineinsehen, Registerinhalte, PC etc. ...
Danke euch erstmal für die Antworten.
@STM32User:
nein. Interrupts habe ich nicht verwendet.
Sonst müssen sie abgeschaltet?
@A.B.
die +4 muss sein. Da +0 ist die Initialisierung des Stackpointers und
danach kommt der erste Befehl was ausgeführt werden soll.oder?
was mich verwirrt ist: JumpAddress: 0x80602F5
wie kommt der Compiler draut. Ist es überhaupt richtig?
Danke.
Laspalmas
Laspalmas schrieb:> die +4 muss sein. Da +0 ist die Initialisierung des Stackpointers und> danach kommt der erste Befehl was ausgeführt werden soll.oder?> was mich verwirrt ist: JumpAddress: 0x80602F5> wie kommt der Compiler draut. Ist es überhaupt richtig?
Moment mal, der Bootloader bringt doch seine eigene Vektor-Tabelle mit
(inkl. Stackpointer-Init.) und soll nur einen Sprung zur Applikation
machen?
Das würde heißen, nach JEDEM Reset startet zuerst der Booloader und
der wiederum ggf. die Applikation? Dann ist das '+4' aber in der Tat
zuviel, bzw. vielmehr die ganze Vektortabelle zuviel. Die
Stackpointer-Initialisierung wird duch nur bei einem Reset automatisch
durchgeführt.
Oder soll der Bootloader die Applikation "fest installieren"? Dann
müsste die Startadresse in den Option-Bytes entsprechend umgebogen
werden, die Vektortabelle der Applikation aktiv gemacht werden. Das ist
mit einem einfachen Sprung nicht getan.
Wie der Compiler auf die 0x080602f5 kommt ist aber klar, das ist nix
anderes als 'Reset_Handler'.
Ja so ist es gedacht. Nach jedem Reset checkt der Bootloader die
Integrität der Applikatoin und danach startet diese. Nach meinem
Verständnis, soll der Bootloader ganz zurückziehen und überlässt die
Hardware der Applikation.
D.h. Alle einstellungen was der Bootlaoder gemacht hat, sollen
überschrieben sein, so als hätte die Applikation von Anfang an selbst
gestartet ist.
Laut map-file denke ich dass der Linker die Verktor-Tabelle in der
richtigen Stelle abgelegt hat. oder?
Gruß
Hi,
Der Start Deines gebauten Codes sollte auf einem 512-bytes boundary
liegen, also lokiere den nach 0x08060200. Stichwort ISR vector table
Deiner Applikation, RTFM ;o).
__set_PRIMASK(1); // disable all isr's
JumpAddress = *(__IO uint32_t*) (0x08060200+4);
Jump_To_Application = (pFunction) JumpAddress;
__set_MSP(*(__IO uint32_t*)0x08060200;
Jump_To_Application();
Wenn Dein Linkerscript damit korrespondiert, sollte das mit arm-gcc tun.
Schau Dir im debugger an, ob die Werte für die Adressen richtig
übernommen werden. Ich habe da mit EmBitz 1.1 und dem built-in gcc schon
merkwürdiges gesehen...
Wie es mit Keil ist, keine Ahnung. Bei mir tut das mit CooCox 1.78 und
arm gcc 4.7 2012q4 problemlos.
Gutt Lack, Tom.
tom schrieb:> Hi,>> Der Start Deines gebauten Codes sollte auf einem 512-bytes boundary> liegen, also lokiere den nach 0x08060200. Stichwort ISR vector table> Deiner Applikation, RTFM ;o).
Genau, und wenn der Bootloader sozusagen dann 'tot' sein soll, muss man
manuell
0. Alle Interrupts abschalten (ggf. auch DMA)
1. Stackpointer neu laden (aus 0x08060200)
2. Vektortabelle verschieben (Vector Table Offset register auf
0x08060200)
3. Indirekten Sprung über Vektor-Tabelle+4
Das geht freilich nur in Assembler ...
Laspalmas schrieb:> danach kommt der erste Befehl was ausgeführt werden soll.oder?
Nö, da steht die Adresse des Reset Handlers.
Wenn du in der Applikation Interrupts haben willst musst du auch noch
das VTOR Register setzen. Ansonsten wird in der Applikation die Vektor
Tabelle des Bootloaders benutzt.
Du kannst auch mal hier rein schauen:
https://www.segger.com/downloads/application-notes/AN01005
A. B. schrieb:> Das geht freilich nur in Assembler ...
Nope. Geht auch problemlos in C.
Beispiel steht in der App Note bzw. bei Segger gibt es auch ein
Demoprojekt.
Laspalmas schrieb:> wenn ich debugge finde ich:> addr: 0x8060104> JumpAddress: 0x80602F5> Jump_To_Application: 0x80602F5
Wenn deine Interrupttabelle bei 0x8060100 liegt, wirst du möglicherweise
Probleme bekommen, wenn du die Flashtabelle nutzt (Alignment 0x200 oder
so, je nach Derivate).
Laspalmas schrieb:> was mich verwirrt ist: JumpAddress: 0x80602F5> wie kommt der Compiler draut. Ist es überhaupt richtig?
Passt. An der Stelle steht die Adresse, wo du hinspringen sollst. Auch
das Thumb bit ist bereits ordentlich gesetzt.
A. B. schrieb:> Das würde heißen, nach JEDEM Reset startet zuerst der Booloader und> der wiederum ggf. die Applikation? Dann ist das '+4' aber in der Tat> zuviel, bzw. vielmehr die ganze Vektortabelle zuviel.
Das ist die Vektortabelle der Applikation.
tom schrieb:> __set_PRIMASK(1); // disable all isr's> JumpAddress = *(__IO uint32_t*) (0x08060200+4);> Jump_To_Application = (pFunction) JumpAddress;> __set_MSP(*(__IO uint32_t*)0x08060200;> Jump_To_Application();
Nur der Vollständigkeit halber:
Da der Stack umgebogen wurde, muss Jump_To_Application im Register
liegen. Ist aber eigentlich immer der Fall. Aber wenn du am Verzweifeln
bist check einfach mal diese Stelle im Assembler.
A. B. schrieb:> 2. Vektortabelle verschieben (Vector Table Offset register auf> 0x08060200)
Das ist diskutabel. Ich bin auch dafür, dass im Bootloader zu machen.
Aber auf jedenfall gibt es regelmäßig derartige Einstellungen in der
Applikation, die das Register zurücksetzen. An diese Stelle muss man
genauso denken.
Laspalmas schrieb:> aber immer noch das gleiche Problem.
Ich vermute das Problem in der Applikation, nicht im Bootloader.
Die üblichen Verdächtigen wie Umstellen der Vektortabelle wurden
genannt.
Oft geht die Applikation auf davon aus, dass nach dem Reset die
Interrupte enabled sind und gern disabled man diese im Bootloader.
Einfach mal die Applikation per Bootloader flashen und dann ohne Flashen
die Applikation debuggen.
Ja ich denke auch dass die Applikation nicht In Ordnung ist.
Mal ein Veständnisfrage: kann ich die Applikation mit Keil debuggen
obwohl sie liegt an der Adresse 0x8060000 samt Verktortabelle & co und
nicht an Adresse 0x8000000?.
Der Bootloader befindet sich an 0x8000000.
D.h nach einem Reset ist erstmal Reset-Händer an 0x8000004 des
Bootloader gefragt?
wie kann ich das umgehen?
Danke
Laspalmas schrieb:> wie kann ich das umgehen?
Nicht umgehen...
Ziel ist es, dass alles so ist wie am Ende, d.h. Bootloader im Flash,
Applikation im Flash, ggf. Prüfdaten im Flash.
Aufpassen, dass man beim Debuggen nicht erased und flashed.
In diesem Zustand einfach die Applikation debuggen. Natürlich wird so
erst der Bootloader durchlaufen und erst dann die Applikation.
Ich setze meinen erstne Breakpoint in den Resetvektor der Applikation,
um zu sehen, dass alles wie erwartet anläuft.
Ab jetzt ganz normal debuggen.
Vieeeeeelen Danke an Alle.
Granz Großer Lob!
Es lag an der Applikation genauer gesagt an HAL_Delay() die nicht mehr
funktionniert (bis jetzt nicht. Ursache muss ich noch finden.
Vielleicht liegt es an __set_PRIMASK(1): alle Interrupts abschalten).
D.h. mit folgenden Code hat der Boot-Loader die Applikation gestartet:
__set_PRIMASK(1);
addr = GetApplicationStartAddress() + sizeof(APP_HEADER)+4;
JumpAddress = *(__IO uint32_t*) addr;
Jump_To_Application = (pFunction) JumpAddress;
__set_MSP(*(__IO uint32_t*)(GetApplicationStartAddress() +
sizeof(APP_HEADER)) );
Jump_To_Application();
Vielen Dank noch mal.
Laspalmas.
Laspalmas schrieb:> Vielleicht liegt es an __set_PRIMASK(1):
Ja klar, das ist das Problem. Einerseits möchtest du Interrupts im
Bootloader sperren aber andererseits muss die Applikation die CPU in dem
Zustand wie nach dem Reset vorfinden. Und das heißt Interrupts sind nach
dem Reset enabled (PRIMASK=0, BASEPRI=0). Der Ausweg aus dem Dilemma ist
die Interrupts in dem Applikation Startup Code einzuschalten.
Laspalmas schrieb:> Vieeeeeelen Danke an Alle.> Granz Großer Lob!>> Es lag an der Applikation genauer gesagt an HAL_Delay() die nicht mehr> funktionniert (bis jetzt nicht. Ursache muss ich noch finden.> Vielleicht liegt es an __set_PRIMASK(1): alle Interrupts abschalten).> D.h. mit folgenden Code hat der Boot-Loader die Applikation gestartet:>> __set_PRIMASK(1);> addr = GetApplicationStartAddress() + sizeof(APP_HEADER)+4;> JumpAddress = *(__IO uint32_t*) addr;> Jump_To_Application = (pFunction) JumpAddress;> __set_MSP(*(__IO uint32_t*)(GetApplicationStartAddress() +> sizeof(APP_HEADER)) );>> Jump_To_Application();>>> Vielen Dank noch mal.> Laspalmas.
An der Stelle möchte ich noch auf eine sehr sehr gerne gemachte
Denklücke hinweisen:
Da dein BL HAL_Delay() benutzt, aber über das Flash Layout jenseits
seines Bereiches keinen Einfluss hat, muss der Code für HAL_Delay() im
BL Bereich des Flashes sitzen.
So weit so gut. Interessant wird's nun aber, wenn deine App auch
HAL_Delay() benutzt. Hier gibt es mehrere Implementationsvarianten:
1. Der Bootloader ist nicht ersetzbar. Dann darf die App statisch
Informationen aus dem Linker Map file des BL nutzen, um absolut dort
hinzuspringen. Geht natürlich nicht in die Andere Richtung...
2. Die App dupliziert den Code für HAL_Delay(). Das geht prinzipiell,
ist aber mit grosser Vorsicht zu geniessen (manche HAL Funktionen
benutzen geteilte globale Variablen, die dann logischerweise für BL und
App an verschiedenen Stellen sitzen, was ein Anlass für sehr lange
Debugsessions und ein Grund zur Freude für die Kaffeeindustrie sein
kann). Ausserdem ist es nicht Sinn und Zweck der Sache, Code doppelt zu
halten.
3. Dynamische Sprungtabellen, also ein indirektes
Funktionsaufrufinterface zwischen BL und App. Im frei herunterladbaren
Beispielcode zum Buch Kapitel 9 hast Du ein Beispiel wie man so etwas
machen kann (nur falls Du das noch nicht in Betracht gezogen hast; es
hat mich ca. 5 BL gebraucht, bis ich das so mit Allen Fallstricken und
Randpoblemchen gerade gezogen habe). Funktioniert auch in beide
Richtungen (also Aufrufe vom BL in Applikationsocde, was auf der ersten
Blick schräg erscheint, aber zuweilen in Form von Callbacks sinnvoll
sein kann).
Guest schrieb:
> Laspalmas schrieb:>> Vielleicht liegt es an __set_PRIMASK(1):>> Ja klar, das ist das Problem. Einerseits möchtest du Interrupts im> Bootloader sperren
Warum möchte ich das? Es gibt doch nach einem Reset keine aktive
Interrupt-Quelle? Und wenn der Bootloader ein oder zwei Interrupts
braucht, kann er die auch wieder abschalten bzw. das Modul resetten.
Dafür gibt es doch extra die RCC_ Reset Register? Oder nicht?
eagle user schrieb:> Warum möchte ich das?
Weil du irgendwann vor dem Sprung in die Applikation die Interrupt
Vektor Tabelle umstellst (VTOR). D.h. es kann passieren, das im
Bootloader Interrupts auf der Interrupt Vektor Tabelle der Applikation
laufen. Und das kann ganz gewaltig schief gehen.
Ruediger A. schrieb:> 2. Die App dupliziert den Code für HAL_Delay(). Das geht prinzipiell,> ist aber mit grosser Vorsicht zu geniessen
Bei mir sind Bootloader und Applikation völlig getrennte Projekte. Da
sie nichts voneinander wissen, gibts auch keine Verwechslungen.
eagle user schrieb:> Und wenn der Bootloader ein oder zwei Interrupts> braucht, kann er die auch wieder abschalten bzw. das Modul resetten.
Prinzipiell hast du recht und wird wohl auch ST so sehen. Klassisch habe
ich aber gelernt all den Wenn und Abers aus dem Weg zu gehen und die
globalen Interrupte abzuschalten.
Und in diesem Fall auch erst wieder einzuschalten, wenn das Register für
die Vectortable richtig gesetzt ist.
Guest schrieb:> eagle user schrieb:>> Warum möchte ich das?>> Weil du irgendwann vor dem Sprung in die Applikation die Interrupt> Vektor Tabelle umstellst (VTOR). D.h. es kann passieren, das im> Bootloader Interrupts auf der Interrupt Vektor Tabelle der Applikation> laufen. Und das kann ganz gewaltig schief gehen.
Berücksichtige bitte die Aussage:
eagle user schrieb:> kann er die auch wieder abschalten bzw. das Modul resetten.
Beim Sprung in die Applikation initialisierte Peripherie zu hinterlassen
(die Interrupte auslöäsen könnte, wenn nicht abgeschaltet) ist
vielleicht nicht ganz so gut.
Anm:
Ich bin auch ein Verfechter des Abschaltens der globalen Interrupte.
Aber die Argumentation greift nicht.
Steffen R. schrieb:> Ruediger A. schrieb:>> 2. Die App dupliziert den Code für HAL_Delay(). Das geht prinzipiell,>> ist aber mit grosser Vorsicht zu geniessen>> Bei mir sind Bootloader und Applikation völlig getrennte Projekte. Da> sie nichts voneinander wissen, gibts auch keine Verwechslungen.>
Doch doch, die gibt es, und genau das ist mein Punkt:
Wenn Du zwei komplett voneinander getrennte Instanzen von der HAL hast,
können die nicht miteinander funktionieren, jedenfalls nicht solange Du
die Standardimplementation benutzt.
Die Defaultimplementation der HAL unter ST registriert einen
Timerinterruphandler, der eine globale Variable uwTick incrementiert,
und HAL_Delay() berechnet lediglich solange die Differenz zwischen
uwTick und dessen Stand bei Eintritt in HAL_Delay(), bis das gewünschte
Delta überschritten wird.
Hast Du zwei verschiedene Instanzen der HAL, dann hast Du auch zwei
voneinander unbhängige Instanzen von uwTick - aber vermutlich nur einen
ISR (HAL_InitTick() benutzt zumindestens in der Standardimplementation
nur einen Timer). Abhängig davon, "wessen" ISR mit dem Timer assoziiert
ist, wird der eine oder der Andere Timer funktionieren, die Andere
uwTick aber vermutlich niemals inkrementiert (was u.A. zu einem nie
wiederkehrenden HAL_Delay() führt).
Und das ist nur die Spitze des Eishügels (für einen Berg ist es nun doch
nicht komplex genug), denn die Prozessorfrequenz ist ebenfalls in einer
globalen Variable abgelegt, nämlich SystemCoreClock - von der es besser
keine zwei Instanzen geben sollte (weil nämlich die Clock in der Regel
nur einmal initialisiert wird, nämlich vom BL, und damit ist die Instanz
von SystemCoreClock von der Applikation undefiniert. Die Variable wird
aber zuweilen benutzt, u.A. um Ableitungsfaktoren für Baudraten u.ä. zu
berechnen).
Das sind zwei der Gründe, warum ich mit der HAL von ST nicht so
begeistert bin; erstensmal benutzt sie von mir ungefragt einen
Timerinterrupt für ein busy wait (dessen Priorität ich sowieso erst in
mein Schema unterbringen muss, also ganz transparent ist es sowieso
nicht, und vermutlich könnte ich applikationswaits besser durch
suspended waits realisieren), und zweitens sind diese
Bootloaderunverträglichkeiten sehr sehr gemeine Angelegenheiten zum
Debuggen.
Ruediger A. schrieb:> Wenn Du zwei komplett voneinander getrennte Instanzen von der HAL hast,> können die nicht miteinander funktionieren, jedenfalls nicht solange Du> die Standardimplementation benutzt.
Die funktionieren auch nicht miteinander, sondern nacheinander.
Ich mache das genauso wie Steffen, sowohl der Bootloader als auch die
Applikation benutzen die HAL-Lib. Aber beide wissen nichts voneinander
(außer die Startadresse der Application Vector Table und die CRC der
Appl.). Deshalb kann man auch nicht von 2 verschiedenen Instanzen
sprechen.
Gruß, Stefan
Stefan K. schrieb:> Ruediger A. schrieb:>> Wenn Du zwei komplett voneinander getrennte Instanzen von der HAL hast,>> können die nicht miteinander funktionieren, jedenfalls nicht solange Du>> die Standardimplementation benutzt.>> Die funktionieren auch nicht miteinander, sondern nacheinander.>> Ich mache das genauso wie Steffen, sowohl der Bootloader als auch die> Applikation benutzen die HAL-Lib. Aber beide wissen nichts voneinander> (außer die Startadresse der Application Vector Table und die CRC der> Appl.). Deshalb kann man auch nicht von 2 verschiedenen Instanzen> sprechen.>
Also sind die BL nach Starten der App komplett inaktiv? Dann kann das
funktionieren. In den BLs, die ich geschrieben habe, ist das aber nicht
der Fall. Da hängt z.B. der BL mit im Hostkommunikationsprotokoll drin,
filtert alle Softwaredownloadtelegramme heraus, baut das
Applikationsimage aus den Telegrammen und flasht es dann. Da es vor
Allem bei kleineren Controllern schwer möglich ist, so etwas potentiell
footprintreiches wie Hostkommunikationscode zu verdoppeln, wird bei
diesen Systemen kontrolliert zwischen BL und App hin- und her
aufgerufen, und da werden solche Themen relevant.
Man kann auf die Art und Weise sogar mit 32k RAM und 128k Flash einen
selbst und die Applikation upgradenden Bootloader mit minimalem eigenen
footprint schreiben.
> Gruß, Stefan
Zurück ;-)
Ruediger A. schrieb:> Hast Du zwei verschiedene Instanzen der HAL, dann hast Du auch zwei> voneinander unbhängige Instanzen von uwTick - aber vermutlich nur einen> ISR (HAL_InitTick() benutzt zumindestens in der Standardimplementation> nur einen Timer).
2 Programme
2 Vektortabellen, daher ist das Umstellen so wichtig
2 unabhängige Interrupthandler
=> Da die Applikation nichts von Interrupthandler des Bootloaders weiß,
kann sie diesen auch nicht nutzen. Der Preis der Unabhängigkeit.
Ruediger A. schrieb:> denn die Prozessorfrequenz ist ebenfalls in einer> globalen Variable abgelegt, nämlich SystemCoreClock
Den Prozessor interessiert diese Variable garnicht.
Aber davon abgesehen, wird diese von der clib des Bootloaders auf den
Initialwert des Bootloaders gesetzt und von der clib der Applikation auf
den Initialwert der Applikation.
Und natürlich kann diese Variable in jedem Fall an einer anderen Stelle
liegen.
Ich glaube du hast eher deinen Punkt 1 im Blick, bei der die HAL nur
einmal im Flash liegt. In dem Fall müssen alle Beteiligten die gleichen
Adressen nutzen. Und dann wird es aus meiner Sicht kompliziert.
Ich finde meinen Weg einfacher, weil man an fast nichts denken muss und
eine Applikation auch leicht ohne Bootloader testen kann. Aber natürlich
verbraucht dies zusätzlichen Flash.
Ruediger A. schrieb:> Da es vor> Allem bei kleineren Controllern schwer möglich ist, so etwas potentiell> footprintreiches wie Hostkommunikationscode zu verdoppeln, wird bei> diesen Systemen kontrolliert zwischen BL und App hin- und her> aufgerufen, und da werden solche Themen relevant.
Das verstehe ich, das ist natürlich ein ganz anderer Fall.
Bei uns ist glücklicherweise immer mehr als genug Flash übrig, so dass
solche Klimmzüge nicht nötig werden.
Viele Grüße, Stefan
Ruediger A. schrieb:> Man kann auf die Art und Weise sogar mit 32k RAM und 128k Flash
Wieviel Funktiionalität packt ihr in den Bootloader und wie komplex ist
Eure Hostkommunikation, dass du einen 128k Flash Prozessor als klein
bezeichnest?
Neugier ist ernst gemeint.
habe auch 2 komplett getrennte projekte draus gemacht
hatte das anfangs mit fester lib im flash und gelinkten aufrufen
aber sobald man was ändert hatte ich das problem das alles nchmal
durchkompiliert werden muss
daher BL ab adresse 0x8000000 und appl ab 0x8010000
ja der BL is recht groß
aber da sind nch mehr daten dahinter.
aber wichtg ist für den BL die vectortabelle zu setzen und für die
applikation
beides muss entsprechend vor dem JUMP in das VTOR register geladen
werden
also von APPL zu BL oder umgedreht
immer ISR aus ,
adresse laden ,
VTOR laden,
sprung zu adresse
Steffen R. schrieb:> Ruediger A. schrieb:>> Man kann auf die Art und Weise sogar mit 32k RAM und 128k Flash>> Wieviel Funktiionalität packt ihr in den Bootloader und wie komplex ist> Eure Hostkommunikation, dass du einen 128k Flash Prozessor als klein> bezeichnest?>> Neugier ist ernst gemeint.
Hast ne PM
Steffen R. schrieb:> dass du einen 128k Flash Prozessor als klein> bezeichnest?
ich habe einen F745 mit 1MB flash und 320k ram ...
Flash ist ca 50-60% voll
Ram je nach betriebsmodus bis zu 90% voll
@Laspalmas
Freue mich das Dir geholfen werden konnte.
Wenn Dein BL ein vollkommen eigenständiges Programm ist und die
Applikation auch (kein shared code der im BL-Bereich liegt), dann sollte
das alles so funktionieren. Und ja, bevor Du die ISR's in der
Applikation wieder freigibst, MUSST Du die VECT_TAB_BASE natürlich auf
die Basisadresse Deiner Applikation setzen, siehe Appnote(s). Da ich
Deinen zusätzlichen startup-code (SystemInit() bei arm-gcc) nicht kenne,
am besten erst nach diesem Aufruf in Deiner main() funktion. Und die
"komische" Adresse die Du da siehst ist in der tat die Adresse des
compiler startup-codes, wo der kontext des C-Programmes hergestellt
wird. Da kannst Du Dich belesen wieso warum weshalb bei Interesse.
Um die mit Offset lokierte Applikation zu debuggen, kannst Du Dir ein
Minimalprogramm bauen das unten im Flash sitzt und direkt in Deine
Applikation springt - Du weisst ja jetzt wie ;o). Beim download deiner
Applikation sollte natürlich der untere Flash Bereich nicht gelöscht
werden - debugger einstellungen checken.
Viel Erfolg, Tom.