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
Hilfe! Ich komm nicht mehr weiter. hat jemand eine Idee? Gruß
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. ...
Hast du Interrupts im Bootloader verwendet ?
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
Ich hab es gerade probiert ohne +4. Hat nichts geholfen. addr = (GetApplicationStartAddress() + sizeof(APP_HEADER)); JumpAddress = *(__IO uint32_t*) addr; Jump_To_Application = (pFunction) JumpAddress; __set_MSP(*(__IO uint32_t*)(GetApplicationStartAddress() + sizeof(APP_HEADER)) ); Jump_To_Application();
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
Hatte das Problem schon vor einer ganzen Weile. Das Problem war der Vector Table der nicht umgestellt war. Vor dem Umschalten die Adresse ändern
1 | SCB->VTOR = ApplicationAddress; // Vector Table Relocation in Internal FLASH |
2 | |
3 | // Jump to user application
|
4 | JumpAddress = *(__IO uint32_t*) (ApplicationAddress + 4); |
5 | Jump_To_Application = (pFunction) JumpAddress; |
6 | // Initialize user application's Stack Pointer
|
7 | __set_MSP(*(__IO uint32_t*) ApplicationAddress); |
8 | Jump_To_Application(); |
So funktioniert es bei mir.
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.
Und das Thumb Bit nicht vergessen: #define THUMB_BIT 1 #define APP_START_ADDR 0x00100000 #define APP_STACK_PTR (*(volatile OS_U32*)(APP_START_ADDR + 0x00)) #define APP_RESET_PTR (*(volatile OS_U32*)(APP_START_ADDR + 0x04)) AppPtr = (void (*)(void))(APP_RESET_PTR | THUMB_BIT);
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.
Danke Tom: ich hab mittlerweile auf den Header verzichtet und die Applikation an der Adresse: 0x8060000 kompiliert. Der Bootlaoder auch angepasst: __set_PRIMASK(1); addr = 0x8060000+4; JumpAddress = *(__IO uint32_t*) addr; Jump_To_Application = (pFunction) JumpAddress; __set_MSP(*(__IO uint32_t*)(0x8060000) ); Jump_To_Application(); aber immer noch das gleiche Problem. Die Jump-Adresse die berechnet ist gleich: 0x80601F5 ??? (Siehe Anhang: Debug-Ausgabe) Map-File der Applikation (Ausschnitt): 0x08060000 0x000001e0 Data RO 1849 RESET startup_stm32f722xx.o 0x080601e0 0x00000000 Code RO 1854 * .ARM.Collect$$$$00000000 mc_w.l(entry.o) 0x080601e0 0x00000004 Code RO 1857 .ARM.Collect$$$$00000001 mc_w.l(entry2.o) 0x080601e4 0x00000004 Code RO 1860 .ARM.Collect$$$$00000004 mc_w.l(entry5.o) 0x080601e8 0x00000000 Code RO 1862 .ARM.Collect$$$$00000008 mc_w.l(entry7b.o) 0x080601e8 0x00000000 Code RO 1864 .ARM.Collect$$$$0000000A mc_w.l(entry8b.o) 0x080601e8 0x00000008 Code RO 1865 .ARM.Collect$$$$0000000B mc_w.l(entry9a.o) 0x080601f0 0x00000000 Code RO 1867 .ARM.Collect$$$$0000000D mc_w.l(entry10a.o) 0x080601f0 0x00000000 Code RO 1869 .ARM.Collect$$$$0000000F mc_w.l(entry11a.o) 0x080601f0 0x00000004 Code RO 1858 .ARM.Collect$$$$00002712 mc_w.l(entry2.o) 0x080601f4 0x00000024 Code RO 1850 .tex
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).
:
Bearbeitet durch User
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.
:
Bearbeitet durch User
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.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.