Hallo an alle,
ich habe folgendes Problem. Ich habe einen funktionierenden
MIDI-Controller auf Basis eines AtMega2560 gebaut. Im Netz habe ich
einen Bootloader gefunden der ein Update der Firmware über eine SD-Karte
erlaubt (https://github.com/FleetProbe/MicroBridge-Arduino-ATMega2560).
Das habe ich benutzt um im Menü des Controllers ein Update zu starten
(also User gesteuert).
Nun bin ich mit meinem MIDI Controller auf einen STM32F103 umgestiegen
und es funktioniert alles wie beim AtMega2560. Ich finde sehr viel über
Bootloader für den STM aber ich kapiers einfach nicht.
Ich bräuchte einen Bootloader der von der Mechanik her wie der für den
AtMega2560 ist.
1
The bootloader looks for byte in eeprom at address 0x1FF:
2
-if it is set to 0xF0 bootloader will look for a bin file on the sdcard named
3
firmware.bin and use it to flash the firmware then reset the byte to 0xFF so it
4
does this only once
5
6
-otherwise no action is taken and bootloader works as a arduino bootloader except
7
some of the debugging functions are missing
Leider finde ich nicht wirklich etwas verständliches im Netz. Ich habe
einige Custom Bootloader gefunden, weiss aber nicht wirklich wie ich die
so modifizieren kann das es so funktioniert wie ich das gerne hätte.
Kann mir jemand ein paar Tipps zu Custom Bootloadern geben.
Vielen Dank schon mal.
Beim STM32 ist ein eigener Bootloader nichts anderes als eine Firmware.
Der Factory Bootloader von STM kann nicht geändert werden und startet
immer zuerst. Die Jump Adresse für den Start der Firmware ist daher
immer 0x0800000000. Den eigenen Bootloader kann man daher dann wie eine
ganz normale Firmware aufspielen. Diese kann dann schauen ob eine
valide, zweite Firmware auf einer SD Karte liegt, diese in den Flash
kopieren, zb Address ab 0x082000000 und dann diese von dort ausführen.
Damit das funktioniert muss die zweite Firmware mit einem Offset
erstellt und kompiliert werden. Aber dazu gibt es jede Menge Anleitungen
im Netz
Stefan M. schrieb:> The bootloader looks for byte in eeprom at address 0x1FF:> -if it is set to 0xF0 bootloader will look for a bin file
Den Mechanismus würde ich mir komplett sparen z.B. indem du das File
nach dem Update löschst/umbenennst oder einen nicht initialisieren RAM
Bereich nutzt (in vielen Bootlaodern nehmen sie ein Register in der
RTC). Der STM hat kein EEPROM an Board und man müsste dann deshalb
unnötig im Flash rum schreiben.
Allgemein: Bei MIDI bist du doch 100 pro über USB verbunden. Warum dann
überhaupt der Umweg über SD? Auf GitHub findest du zig fertige USB
Bootloader. Teilweise sogar mit Massenspeicher und UF2 File.
Komfortabler geht's ja nicht mehr für den Kunden.
Bootloader sind auch ein Stück Software. Allerdings derart dicht an der
Hardware unterwegs, dass der Umug von einer µC - Architektur auf eine
andere auf ein so gut wie komplettes Neuschreiben heraus läuft.
Es gibt STM32 mit einem eingebauten ROM, in dem ein Bootloader steht. Da
wird die neue Software allerdings über ein ganz eigenes Protokoll auf
USB oder Seriellport (RS232 3,3V) erwartet. Immerhin, schauen die
STM32, die ich bisher benutzt habe, am Ende des Reset auf I/O-Pins und
beginnen die Abarbeitung der Firmware an unterschiedlichen Adressen, je
nach Pegel. Eine davon zeigt auf den Programmstart im ROM.
Wenn Du die SD-Karte zu nichts anderes benutzt kannst Du natürlich das
Card-Detect vom Kartenslot dafür nutzen.
Andererseits kannst Du auch immer zuerst Deinen Bootloader starten. Nach
einer SD-Karte suchen und dann auf der SD-Karte nach einer Datei mit
neuer Applikation. Dann nur noch Prüfsumme und Versionsnummer der
Applikation im Flash checken und wenn die fehlerhaft oder älter als die
auf der Karte ist updaten. Das dauert halt. Ich habe ja auch keine
Ahnung, ob das Gerät zu spontanen Jam-Sessions benutzt werden soll oder
ob die Röhrenendstufe sowieso noch ein wenig zum Vorheizen braucht.
Es soll nämlich auch unterbrochene oder fehlerhafte Updateversuche
geben, die dann dazu führen, dass das Starten der Applikation das Gerät
zuverlässig ins Land der Träume schickt. Wenn man davor nicht zum
Aufspielen neuer Software abzweigen kann, hat man einen Briefbeschwerer
mehr, bis jemand, der sich auskennt, per SWD oder JTAG was neues
einspielt.
Natürlich kann man zusätzlich einen Einsprungpunkt im Bootloader
einbauen, so dass die Applikation, wenn sie merkt, dass da ein Benutzer
mit neuer Firmware um die Kurve kommt, diese einspielen lassen kann.
Ob es da vielleicht in diesem Universum schon was fertiges gibt, weiss
ich nicht.
N. M. schrieb:> Allgemein: Bei MIDI bist du doch 100 pro über USB verbunden. Warum dann
MIDI ist eher ein RS232 Signal. Wobei allerdings die logischen Pegel als
Strom codiert sind, per Optokoppler potentialfrei gemacht werden und
eine eher exotische Baudrate haben.
Und ja : es gibt unter dem Stichwort SysEx bestimmt auch die
Möglichkeit, Firmwareupdates über MIDI zu verschieben.
Flunder schrieb:> Allerdings derart dicht an der Hardware unterwegs, dass der Umug von> einer µC - Architektur auf eine andere auf ein so gut wie komplettes> Neuschreiben heraus läuft.
Du sagst ja selbst, es ist ein Stück Software wie jede andere. Warum
sollte das dann so sein? Musst du halt richtig abstrahieren und bei
einem neuen Device die HAL austauschen.
Flunder schrieb:> Es gibt STM32 mit einem eingebauten ROM, in dem ein Bootloader steht. Da> wird die neue Software allerdings über ein ganz eigenes Protokoll auf> USB oder Seriellport (RS232 3,3V) erwartet.
Beim F103 aber nicht über USB. UART geht, bräuchte man aber einen
externen USB/Seriell Wandler. Oder eben einen eigenen Bootloader.
Flunder schrieb:> Das dauert halt.
Der Check geht verdammt schnell wenn man die interne CRC Engine mit dem
DMA füttert. Das Flashen dann wenige Sekunden. Auf jeden Fall nicht so
lange um eine Röhrenendstufe vorheizen zu können 😄
Flunder schrieb:> Es soll nämlich auch unterbrochene oder fehlerhafte Updateversuche> geben, die dann dazu führen, dass das Starten der Applikation das Gerät> zuverlässig ins Land der Träume schickt.
Einfach im Bootloader die im Flash stehende Applikation checken bevor
man sie anspringt. Wenn sie kaputt ist kann man sowieso nichts mit
anfangen und man bleibt im Bootloader für ein Update. Dann kannst du
jederzeit ein neues Update einspielen.
Flunder schrieb:> MIDI ist eher ein RS232 Signal.
Heute auch noch?
Die MIDI-Controler die ich im Internet finde haben alle USB. Aber
tatsächlich kenne ich mich da nicht sonderlich aus.
Flunder schrieb:> gibt unter dem Stichwort SysEx bestimmt auch die Möglichkeit,> Firmwareupdates über MIDI zu verschieben.
Der Gedanke war eher der, dass der Bootloader bei einem Update Request
über USB z.B. einen Massenspeicher o.ä. zur Verfügung stellt über den
ein neues Update geladen werden kann.
Die eigentliche Applikation nutz den gleichen USB für MIDI.
Hallo,
danke für die vielen Antworten.
Ja, mein MIDI-Controller hat einen 5pol-Din sowie auch USB. Allerdings
habe ich noch einen Atmega 90USB162 für die MIDI Komunikation auf meinem
Board, da ich auf diesem die LUFA USB Midi Firmware darauf habe.
Wenn ich Johannes richtig verstanden habe dann könnte ich ja den STm
Bootloader darauf lassen, dann einen eigenen "Bootloader" ab der
normalen Startadresse flashen. Der eigenen pseudo Bootloader schaut dann
einfach ob eine Update Datei auf der SD Karte ist und flashed diese ab
Adresse xxxx. Falls keine Update Datei vorhanden ist springt mein pseudo
Bootloader einfach an die Adresse xxxx.
Das wäre ja eigentlich ganz cool da könnte ich ja mein Display auch zur
Anzeige, Abfrage ob man wirkich updaten möchte, etc. nutzen.
Wird das dann getrennt geflashed also eigener Bootloader und dann
eigentliche Firmware oder sind beide Programmcodes in einer Datei mit
Adresszuweisungen?
Vielen Dank
Stefan M. schrieb:> Wird das dann getrennt geflashed also eigener Bootloader und dann> eigentliche Firmware oder sind beide Programmcodes in einer Datei mit> Adresszuweisungen?
Ich würde es der Übersicht halber in 2 getrennten Projekten entwickeln.
Beide mit unterschiedlichen Linker-Scripts, so dass der Code woanders im
Flashspeicher landet.
Für den Fall, dass man mehrere davon aufbauen will, würde ich die .hex
Dateien der beiden Projekte vereinen und die Mikrocontroller damit schon
mal befüllen. So dass die Applikation nicht erst im 2. Schritt
aufgespielt werden muss.
Bedenke auch, dass bei jedem hochfahren mit Update Datei auf gesteckter
SD-Karte, der Bootloader wieder ansetzt, den Flash des Mikrocontrollers
zu überschreiben. Daher wohl der Vorschlag mit dem Vergleich der
Versionsnummern.
N. M. schrieb:> Du sagst ja selbst, es ist ein Stück Software wie jede andere. Warum> sollte das dann so sein? Musst du halt richtig abstrahieren und bei> einem neuen Device die HAL austauschen.
Nunja, das Verhältnis Applikation zu HAL ist bei einem Bootloader halt
ein anderes als bei einer Adressverwaltung. Sprich der wiederverwertbare
Teil des Bootloaders ist das, was im 1. Werner Film mit den Worten "sehr
übersichtlich" beschrieben wurde.
Nur mal so als Anregung:
Bei Objektiven von Viltrox (mit USB-Port) läuft das so:
Wenn man die anstöpselt, melden die sich wie ein USB-Speicher-Stick.
(egal welches Betriebssystem)
Auf diesem Speicher findet man eine Textdatei mit Informationen zur
aktuellen Hardware- und Firmware-Version.
Man kopiert dann das neue Firmware-File (eine simple bin-Datei) auf
diesen Speicher, und sobald der Schreibvorgang abgeschlossen ist,
beginnt der Update Vorgang, die Textdatei wird aktualisiert, und die
.bin-Datei wird im Anschluss gelöscht.
Natürlich wird vorher geprüft, ob das Update zur Hardware passt.
Ich hab einige Objektive dieses Herstellers, hab da schon Zig Updates
eingespielt, und Probleme gab es nie.
Frank O. schrieb:
> Ich würde es der Übersicht halber in 2 getrennten Projekten entwickeln.> Beide mit unterschiedlichen Linker-Scripts, so dass der Code woanders im> Flashspeicher landet.
Aktuell nutze ich Platformio, da ich es sehr übersichtlich finde. Soweit
ich weiss kann man da auch eigene Linker-Scripts benutzen.
Frank O. schrieb:
> Für den Fall, dass man mehrere davon aufbauen will, würde ich die .hex> Dateien der beiden Projekte vereinen und die Mikrocontroller damit schon> mal befüllen. So dass die Applikation nicht erst im 2. Schritt> aufgespielt werden muss.
Ziel ist es mehrere davon zu bauen und zu vermarkten.
Frank O. schrieb:
> Bedenke auch, dass bei jedem hochfahren mit Update Datei auf gesteckter> SD-Karte, der Bootloader wieder ansetzt, den Flash des Mikrocontrollers> zu überschreiben. Daher wohl der Vorschlag mit dem Vergleich der> Versionsnummern.
Das könnte man ja lösen indem die Update Datei nach dem flashen auf der
SD-Karte gelöscht wird.
Ich muss ja dan in meinen eigenen Bootloader auch die SD-Library und die
OLEDLibrary mit einbinden um auf die SD Karte zugreifen zu können und
den fortschritt bzw. Fehler auf dem Display anzeigen zu lassen.
Wenn z.B. meine Firmware ab Adresse 0x082000000 liegt, kopiert mein
Bootloader die Updatedatei von der SD Karte dann einfach direkt an diese
Adresse oder erst woanders hin und dann an die eigentliche Adresse?
Stefan M. schrieb:> Ich muss ja dan in meinen eigenen Bootloader auch die SD-Library und die> OLEDLibrary mit einbinden um auf die SD Karte zugreifen zu können und> den fortschritt bzw. Fehler auf dem Display anzeigen zu lassen.
Wenn ich sowas lese, enstehen bei mir Zweifel, ob du in der Lage bist,
einen Bootloader zu schreiben, und ob es nicht eventuell sinnvoller
wäre, sich erstmal mit der Architektur der STM32-Familie intensiver zu
beschäftigen.
Stefan M. schrieb:> Wenn z.B. meine Firmware ab Adresse 0x082000000 liegt, kopiert mein> Bootloader die Updatedatei von der SD Karte dann einfach direkt an diese> Adresse oder erst woanders hin und dann an die eigentliche Adresse?
Das bestätigt meine obige Aussage.
Hättest du auch nur eine ungefähre Vorstellung davon, wie ein Bootloader
funktioniert und ein STM32 aufgebaut ist, hättest du diese Frage nicht
stellen müssen.
Mein Rat: lern erstmal die Basics.
Bootloader sind bereits mindestens Level 2.
Stefan M. schrieb:> Ziel ist es mehrere davon zu bauen und zu vermarkten.
Vergiss es!
Du bist ein "Heimwerker" der von einem "Produkt" meilenweit entfernt
ist.
Wenn du ganz, ganz fleißig bisst, und am Ball bleibst, können wir in nem
Jahr vielleicht nochmal drüber reden.
Man kann für die Versionskontrolle auch einen Header in die Binary
Implementieren. Mache ich auch bei jeder Firmware so, zumindest bei den
kommerziellen. Dafür eine Structure anlegen, diese mit einer dedizierten
Adresse versehen, bei STM32 glaube ich 0x400 Offset von der
Startadresse, da der erste Bereich für die Vector-Tables reserviert ist.
Müsste man im Datwnblatt nachlesen um sicherzugehen. Diesen Header kann
man jedenfalls easy abfragen, bevor man die file in den Flash schreibt.
Stefan M. schrieb:> Das könnte man ja lösen indem die Update Datei nach dem flashen auf der> SD-Karte gelöscht wird.
Dann muss jemand, der mehrere updaten will, die Datei immer wieder auf
die SD-Karte kopieren. Funktioniert aber erstmal...
Stefan M. schrieb:> Aktuell nutze ich Platformio, da ich es sehr übersichtlich finde. Soweit
Also mehr so Arduino - naja damit bleibt Dir zumindest die Klippe
erspart, dass CubeMX nicht lauffähigen Code für SD-Karten-Zugriffe
erzeugt.
Stefan M. schrieb:> Wenn z.B. meine Firmware ab Adresse 0x082000000 liegt, kopiert mein> Bootloader die Updatedatei von der SD Karte dann einfach direkt an diese> Adresse oder erst woanders hin und dann an die eigentliche Adresse?
Genau deshalb sollen Bootloader und Applikation an verschiedenen
Adressen liegen. Du kannst die Applikation direkt platt machen, ohne
erst hierhin und dann dorthin zu kopieren. Schlimmstenfalls hast Du nur
ein Flash, das auch nur entweder oder beherrscht. Das bedeutet,
während Du neu flashst, kann kein Code aus dem Flash ausgeführt werden.
Dann muss die (kurze) Überschreibroutine ins RAM kopiert werden und von
dort ausgeführt werden (mit gesperrten Interrupts). Aber in so Fragen
sind Datenblatt und Referenzmanual Deine Freunde.
A propos Versionen und kontrollieren : Was Du Dir angewöhnen solltest,
ist ein Vesionsverwaltung für Deine Quellcodes zu verwenden. git ist da
momentan ganz hipp, aber auch Subversion sollte für Dich mehr als
ausreichend sein. Mit Tortoise(git|svn) gibt es nette Einbindungen in
den Explorer. Visual Studio Code hat dafür auch Extensions.
Das hilft extrem bei der Frage, seit wann und warum geht das nicht mehr.
Stefan M. schrieb:> Ja, mein MIDI-Controller hat einen 5pol-Din sowie auch USB. Allerdings> habe ich noch einen Atmega 90USB162 für die MIDI Komunikation auf meinem> Board, da ich auf diesem die LUFA USB Midi Firmware darauf habe.
Wenn du den ATmega weglässt, und statt des STM32F103, der ja der
allererste Ur-STM32 ist, einen aktuelleren STM32 nutzt (z.B. STM32G4),
hat dieser einen fest integrierten USB-Bootloader. Dann kannst du den
wunderbar komfortabel über die STM32CubeProgrammer Software über USB
programmieren, ohne dass du irgendwas auf der Firmware-Seite dafür tun
müsstest. Dann kannst du das USB-MIDI Protokoll auch direkt auf diesem
Controller implementieren und hast dann alles in einem und brauchst gar
kein Update per SD-Karte. Das kann man sogar wenig technisch versierten
Kunden zumuten, die brauchen halt einen PC dafür. Hardwareseitig sollte
man aber 2 Buttons haben - für Reset und BOOT0 Pin, letzterer löst das
Update aus.
Siehe AN2602:
https://www.st.com/resource/en/application_note/an2606-introduction-to-system-memory-boot-mode-on-stm32-mcus-stmicroelectronics.pdfFlunder schrieb:> Das bedeutet,> während Du neu flashst, kann kein Code aus dem Flash ausgeführt werden.
Doch, die CPU bleibt einfach stehen während des Flash-Vorgangs, sofern
man also während des Flashens nicht noch etwas parallel steuern muss,
kann der Flasher-Code schon selbst im Flash stehen.
Stefan M. schrieb:> Ich muss ja dan in meinen eigenen Bootloader auch die SD-Library und die> OLEDLibrary mit einbinden um auf die SD Karte zugreifen zu können und> den fortschritt bzw. Fehler auf dem Display anzeigen zu lassen.
Das würde bedeuten der Bootloader wird riesig, und dann bleibt nicht
mehr viel Platz für die Haupt-Anwendung. Die Hauptanwendung müsste dann
entweder den Code für die SD-Karte und das Display nochmals mitbringen
(verschwendet viel Platz) oder den Code des Bootloaders dafür aufrufen
(möglich aber kompliziert).
Außerdem musst du entscheiden ob der Bootloader sich selbst
überschreiben können soll - wenn ja, bedeutet ein fehlgeschlagenes
Update dass gar nichts mehr geht, wenn nein kann der Bootloader nie
aktualisiert werden. Im zweiten Fall sollte der Bootloader daher so
klein wie möglich sein, weil man es später nicht mehr optimieren kann.
Außerdem ist dann der Flash-Verbrauch des Bootloaders immer
"aufgerundet" auf die Page-Größe des Flashs, also 1KB / 2KB je nachdem
welcher STM32F103 es genau ist. Selbst wenn der Bootloader nur 1.5 Pages
ist, kannst du die letzte halbe Page nicht für die Anwendung nutzen,
denn um diese zu aktualisieren müsstest du die ganze Page löschen,
sodass dann der Bootloader halb mitgelöscht würde.
Als Referenz: Ein "vollwertiger" STM32-Bootloader der aus einem
seriellen NOR-Flash liest lässt sich in exakt 2048 Bytes, also eine
2kB-Page, quetschen, aber nur unter Verzicht auf Libraries (stattdessen
direkter Hardware-Zugriff und teilweise handoptimiertem Assembler).
SD-Karte und LCD sind deutlich komplexer.
Frank O. schrieb:> Ich würde es der Übersicht halber in 2 getrennten Projekten entwickeln.> Beide mit unterschiedlichen Linker-Scripts, so dass der Code woanders im> Flashspeicher landet.
Geht eh kaum anders. Man kann sogar auch die ELF-Datei des Bootloaders
mit der ELF-Datei des Hauptprogramms zu einer kombinierten Datei
vereinigen, sodass man nicht nur alles auf einmal flashen, sondern auch
auf einmal Debuggen kann. So kann auch das Hauptprogramm auf Funktionen
im Bootloader zugreifen (wie bei einer Library). Das ist aber recht
umständlich umzusetzen.
N. M. schrieb:> Der Check geht verdammt schnell wenn man die interne CRC Engine mit dem> DMA füttert. Das Flashen dann wenige Sekunden.
Geht das wirklich per DMA? Die CRC-Engine hat ja keine DMA-Request
Leitung - benutzt du dann den MEM2MEM-Mode? Aber auch ohne DMA geht der
CRC-Check in deutlich unter einer Sekunde. Das kann man durchaus bei
jedem Bootvorgang machen.
Btw, ein wichtiges Zauberwort in diesem Zusammenhang ist das "Vector
Table Offset Register, VTOR". Dort kann man ab ARMv7M (d.h.
Cortex-M3/4/7, aber nicht Cortex-M0) die Basisadresse des
Interruptvektors einstellen. Das ist erforderlich, wenn die
Hauptanwendung nicht bei 0x08000000 beginnt, sondern erst "hinter" dem
Bootloader. Beim Umschalten von Bootloader auf Hauptanwendung muss man
das VTOR setzen.
Niklas G. schrieb:> Außerdem musst du entscheiden ob der Bootloader sich selbst> überschreiben können soll - wenn ja, bedeutet ein fehlgeschlagenes> Update dass gar nichts mehr geht, wenn nein kann der Bootloader nie> aktualisiert werden. Im zweiten Fall sollte der Bootloader daher so> klein wie möglich sein, weil man es später nicht mehr optimieren kann.
Man kann schon Pseudo-Applikationen erstellen und verteilen, die sich
vom Bootloader als Applikation aufspielen lassen und sobald sie
loslaufen nix anderes machen, als den Bootloader mit einem neuen zu
überschreiben. Danach muss man halt über den neuen Bootloader wieder
eine echte Applikation einspielen.
PS:
Für die CRC-Prüfung muss man natürlich auch erstmal die CRC initial nach
dem Kompilieren berechnen. Idealerweise schreibt man diese in einem
Post-Built-Step direkt in die ELF-Datei, sodass man die Datei direkt im
Debugger verwenden kann ohne dass der Bootloader sich beschwert. Das
geht z.B. mit Python und der LIEF-Library. Geschickterweise konfiguriert
man die Hardware-CRC-Einheit so, dass der Algorithmus kompatibel ist zur
"Standard-CRC", wie sie Python, zlib und auch Java verwendet.
Flunder schrieb:> Man kann schon Pseudo-Applikationen erstellen und verteilen, die sich> vom Bootloader als Applikation aufspielen lassen und sobald sie> loslaufen nix anderes machen, als den Bootloader mit einem neuen zu> überschreiben.
Klar, aber wenn diese Anwendung mitten drin abstürzt (z.B. Einbruch der
Versorgungsspannung), ist der Bootloader ggf. nur halb geschrieben und
dann ist das Gerät "gebrickt". Der Bootloader könnte sich auch ohne
diesen Umweg mit der Pseudo-Applikation direkt selbst überschreiben
indem er sich zuvor in den RAM kopiert, aber mit dem gleichen
"Brick"-Problem.
Also ich finde der STM32CubeProgrammer ist kein für Endkunden gemachtes
Update Tool. Nunja, das Protokoll ist irgendwo beschrieben und man
könnte etwas eigenes Klicki-Bunti entwickeln, dass nur das macht, was
gebraucht wird.
Da der ROM-Bootloader sämtliche Peripherie im Reset-Zustand erwartet,
ist es gar nicht so einfach, aus der Applikation rein zu springen. Ich
habe dann eine Verzweigung an den Anfang des Startup-Codes gesetzt und
löse in der Applikation einen Reset aus.
Ja, das versagt, sobald ein Update schief gegangen ist, aber leider war
das Gehäuse schneller fertig als die Software und man kam nicht mehr an
das BOOT0 Signal.
Niklas G. schrieb:> Klar, aber wenn diese Anwendung mitten drin abstürzt (z.B. Einbruch der> Versorgungsspannung), ist der Bootloader ggf. nur halb geschrieben und> dann ist das Gerät "gebrickt". Der Bootloader könnte sich auch ohne> diesen Umweg mit der Pseudo-Applikation direkt selbst überschreiben> indem er sich zuvor in den RAM kopiert, aber mit dem gleichen> "Brick"-Problem.
Das kann man nur mit "KISS" etwas abmildern. Der Bootloader muss so
klein und überschaubar wie möglich sein, so dass er so gut wie nie
upgedatet werden muss. Bootloader mit OLED-Display-Benutzerführung :
uijuijui !!!
Spätestens wenn irgendwelche OLED-Displays abgkündigt werden und es 3
verschiedene Bootloader je nach Hardware braucht, ist Party angesagt.
Flunder schrieb:> Also ich finde der STM32CubeProgrammer ist kein für Endkunden gemachtes> Update Tool.
Ja, aber für jemanden der mit MIDI umgehen kann ist es vermutlich
zumutbar, und spart hier sehr viel Aufwand.
Flunder schrieb:> Da der ROM-Bootloader sämtliche Peripherie im Reset-Zustand erwartet,> ist es gar nicht so einfach, aus der Applikation rein zu springen.
Stimmt, man könnte auch in den Option-Bytes permanent nSWBOOT0=0 setzen,
und dann für den Bootloader-Start auch nBOOT0=0 setzen und einen
Software-Reset auslösen. Dann muss man allerdings im STM32CubeProgrammer
nach dem Update wieder nBOOT0=1 setzen um die Anwendung wieder starten
zu können...
Flunder schrieb:> aber leider war> das Gehäuse schneller fertig als die Software und man kam nicht mehr an> das BOOT0 Signal.
Ggf. ist es auch akzeptabel wenn der Button nur bei offenem Gehäuse
zugänglich ist.
Flunder schrieb:> Das kann man nur mit "KISS" etwas abmildern. Der Bootloader muss so> klein und überschaubar wie möglich sein, so dass er so gut wie nie> upgedatet werden muss.
Wenn er klein und simpel ist, nimmt er auch wenig Platz weg, weshalb man
ihn auch nicht später nach-optimieren muss, um Platz für die Anwendung
zu machen; so spart man sich jedenfalls diverse Probleme. Wenn man
tricksen muss um den Bootloader in eine Flash-Page zu quetschen ist der
Code allerdings nicht mehr so überschaubar.
Wenns um Kleinserie geht nimmt man einfach einen µC mit genug Flash um
auch im Bootloader mehr zu ermöglichen. 2MB Flash gibts in
Einzelstückzahlen schon unter 6€.
Wenns "unbrickbar" werden soll kann man auch einen mehrstufigen Ansatz
fahren. Stufe 1 Bootloader (wird nie ausgetauscht) prüft nur die
Integrität von einem Stufe 2 Bootloader (es gibt zwei davon) und startet
dann diesen. Der kann das auch für die Applikation (A/B) machen oder
wenn nur Platz für eine Applikation vorhanden dann im Bootloader stehen
bleiben.
Es gibt da unendlich viele Konzepte wie man sowas realisieren kann. Die
Anforderungen vorher zu klären ist immer hilfreich.
Bei einem ordentlichen Konzept sind dann auch solche Themen wie
verschlüsselte und signierte Firmware zu klären.
Matthias
Μαtthias W. schrieb:> einem Stufe 2 Bootloader (es gibt zwei davon)
Wenn aber der Stufe-2-Bootloader groß ist, was ja auch der Grund dafür
ist ihn aktualisieren können zu wollen, hat man diese Speichermenge dann
gleich doppelt belegt...
Niklas G. schrieb:> Μαtthias W. schrieb:>> einem Stufe 2 Bootloader (es gibt zwei davon)>> Wenn aber der Stufe-2-Bootloader groß ist, was ja auch der Grund dafür> ist ihn aktualisieren können zu wollen, hat man diese Speichermenge dann> gleich doppelt belegt...
Ja, das ist so. Um das etwas abzumildern könnte Stufe 2 (z.B. GZ)
komprimiert abgelegt werden und dann ins RAM entpackt werden. Kurzer
Test zeigt eine um 25% reduzierte Größe für ein gerade hier rumliegendes
Cortex-M0 Binary.
Wie immer YMMV
Μαtthias W. schrieb:> Kurzer Test zeigt eine um 25% reduzierte Größe für ein gerade hier> rumliegendes Cortex-M0 Binary.
Mit GCC erstellte Cortex-M Binaries enthalten eine Menge Null-Bytes,
d.h. relativ wenig Entropie. Wäre eigentlich mal interessant zu testen
ob man durch clevere manuelle Assembler-Optimierung Null-Bytes und
Redundanzen so reduzieren kann, dass die Entropie steigt und der Code so
klein wie möglich wird und dann auch kaum noch per GZ o.ä. konprimierbar
ist. Das wird man sich aber durch reduzierte Ausführungsgeschwindigkeit
erkaufen müssen.
Bei einem STM32 ist oftmals auch der Flash in Dual Banks implementiert.
Dann kann man auch den Bootloader direkt in die Firmware implementieren
und muss nicht mit zwei Projekten arbeiten. Man kann die Version auf der
SD Karte prüfen, wenn diese größer ist die Firmware auf die zweite Flash
Bank schreiben und aus dem Code raus die Option Bytes setzen, um einen
Bank Swap auszuführen. Der STM Bootloader wird dann beim nächsten
Bootvorgang zu der zweiten Flash Bank springen. Der Vorteil ist hier,
dass die ursprüngliche Firmware als Backup immer noch im Flash verweilt
und auch durch setzen der Option Bytes wieder auf Flash Bank 1
gewechselt werden kann. Der Nachteil ist, dass die Firmware maximal die
halbe Gesamtgröße des Flashs haben darf. Was bei 2MB selten ein Problem
sein sollte. Das funktioniert super, habe ich bei einem Projekt mit
Firmware Updates über Ethernet am laufen
Niklas G. schrieb:> Geht das wirklich per DMA?
OK, da hatte ich die neueren CRC Units im Kopf der neueren STMs. Da geht
es definitiv.
Einziges Problem ist da nur dass man mit dem DMA maximal über 4x2^16
Byte kommt. Man muss also je nach dem den DMA mehrmals konfigurieren.
Aber Geschwindigkeits technisch ist das schon ziemlich gut.
Niklas G. schrieb:> Μαtthias W. schrieb:>> Kurzer Test zeigt eine um 25% reduzierte Größe für ein gerade hier>> rumliegendes Cortex-M0 Binary.>> Mit GCC erstellte Cortex-M Binaries enthalten eine Menge Null-Bytes,> d.h. relativ wenig Entropie. Wäre eigentlich mal interessant zu testen
Ich denk nicht dass das am GCC liegt sondern einfach an der Verwendung
von 0x00 in vielen Opcodes. Ganz grob haben 13% von allen Instruktionen
in meinem Binary (16k groß) mindestens ein Nullbyte. Hier mal ein paar
Beispiele:
1
00c9 lsls r1, r1, #3
2
4b18 ldr r3, [pc, #96]
3
9b00 ldr r3, [sp, #0]
4
e000 b.n 3452 <__divsi3+0x42>
5
b200 sxth r0, r0
6
0031 movs r1, r6
7
001e movs r6, r3
8
003c movs r4, r7
9
2300 movs r3, #0
10
00d2 lsls r2, r2, #3
11
009e lsls r6, r3, #2
12
d000 beq.n 11c6
13
0056 lsls r6, r2, #1
14
001a movs r2, r3
15
00bf lsls r7, r7, #2
16
2500 movs r5, #0
17
d000 beq.n 2358
18
00a2 lsls r2, r4, #2
19
0027 movs r7, r4
20
008b lsls r3, r1, #2
21
d100 bne.n 32b8
22
0052 lsls r2, r2, #1
23
0010 movs r0, r2
24
0011 movs r1, r2
25
d200 bcs.n 350e <__divsi3+0xfe>
> ob man durch clevere manuelle Assembler-Optimierung Null-Bytes und> Redundanzen so reduzieren kann, dass die Entropie steigt und der Code so
Denke nicht das da viel zu holen ist. Vor allem wird man sich einen
Bootloader mit den angesprochenen Features in diesen Anforderungen nicht
geben wollen.
Matthias
Μαtthias W. schrieb:> Ich denk nicht dass das am GCC liegt sondern einfach an der Verwendung> von 0x00 in vielen Opcodes.
Könnte auch am Cortex-M0 Code liegen, der Cortex-M4 Code ist da deutlich
"dichter". Aber gerade auch die vielen Peripherie-Adressen in den
Literal-Pools haben viele Nullen, und wiederholen sich auch ziemlich oft
(jede Funktion die auf SPI1 zugreift enthält die SPI1-Adresse als
Literal etc). Ähnlich bei Adressen von globalen Variablen, die erst vom
Linker eingesetzt werden, sodass die Adresse immer als kompletter
32bit-Wert im literal-Pool stehen muss für die Relocation.
Außerdem kann der GCC Peripheriezugriffe nicht gut optimieren; nach
jedem Schreibzugriff entwickelt er eine gewisse Paranoia und lädt dann
manche Register neu aus dem Literal-Pool. Das scheint eine übereifrige
Interpretation der Strict-Aliasing-Rules zu sein.
Μαtthias W. schrieb:> Denke nicht das da viel zu holen ist.
In Assembler kann man gerade auch die Adressen in den Literal-Pools
zusammenfassen, also sodass mehrere Funktionen auf den selben
Literal-Pool zugreifen. "Simple" Adressen à la 0x20000000 lassen sich
beim Cortex-M4 auch in einer 32bit-MOV Instruktion ablegen, was aber das
Gespann aus GCC+LD nicht kann.
Grundsätzlich könnte man das alles im Compiler umsetzen (ggf. als Teil
vom LTO?) - machen kommerzielle Compiler das vielleicht schon?
Niklas G. schrieb:> Μαtthias W. schrieb:> Außerdem kann der GCC Peripheriezugriffe nicht gut optimieren; nach> jedem Schreibzugriff entwickelt er eine gewisse Paranoia und lädt dann> manche Register neu aus dem Literal-Pool. Das scheint eine übereifrige> Interpretation der Strict-Aliasing-Rules zu sein.
Das wäre m.E. ein "Problem Report" wert. (Es geht wohl nicht um Register
sondern um Registeradressen?)
Johann L. schrieb:> Das wäre m.E. ein "Problem Report" wert. (Es geht wohl nicht um Register> sondern um Registeradressen?)
Gute Frage, ich habe es bei Registeradressen beobachtet, aber würde
vermuten dass auch andere Literals betroffen sind. Das Ganze ist
letztlich Teil eines größeren Problems, nämlich dass C/C++ keine
wirkliche Möglichkeit bietet um auf memory-mapped IO-Register
zuzugreifen, und keine Möglichkeit um Pointer als "kann nicht aliasen"
zu deklarieren ("restrict" hilft nur begrenzt und ist in C++ nur als
GCC-Erweiterung vorhanden). Die Zugriffe per Inline-Assembly zu machen
hilft auch nicht, weil dann die Offset-Adressierung nicht gut optimiert
werden kann. Das Ergebnis ist, dass der Compiler nach jedem
Schreibzugriff auf IO-Register alle Speicherstellen als "potenziell
verändert" betrachtet.
Wenn ich mal die Muße habe stell ich ein paar Testcases zusammen und
versuche einen Report zu erstellen...
Johann L. schrieb:> Niklas G. schrieb:>> Außerdem kann der GCC Peripheriezugriffe nicht gut optimieren; nach>> jedem Schreibzugriff entwickelt er eine gewisse Paranoia und lädt dann>> manche Register neu aus dem Literal-Pool. Das scheint eine übereifrige>> Interpretation der Strict-Aliasing-Rules zu sein.>> Das wäre m.E. ein "Problem Report" wert. (Es geht wohl nicht um Register> sondern um Registeradressen?)
Ich würde da gerne mal ein Beispiel sehen wie das aussieht. Am Besten
mit dem passenden C Code hier: https://godbolt.org/ Ich konnte sowas
noch nicht beobachten.
Matthias
Niklas G. schrieb:> Gute Frage, ich habe es bei Registeradressen beobachtet, aber würde> vermuten dass auch andere Literals betroffen sind. [...]>> Wenn ich mal die Muße habe stell ich ein paar Testcases zusammen und> versuche einen Report zu erstellen...
Oder bevor ein neuer PR erstellt wird mal die Entwickler fragen in
gcc-help@gcc.gnu.org. Vielleicht gibt es ja schon nen PR dazu.
Die Internals sagen nicht viel zu MEM_ALIAS_SET und wie die für arm
umgesetzt sind.
https://gcc.gnu.org/onlinedocs/gccint/Special-Accessors.html
Evtl. liegts auch am volatile der Registerzugriffe. volatile bewirkt
gerne mal nen Optimization Fence auch dann, wenn bestimmte Optimierungen
über den Zaun hinweg eigentlich unproblematisch sind.
Evtl. wird das Alias Set sogar angezeigt, z.B. mit -save-temps -dP.
Μαtthias W. schrieb:> Ich würde da gerne mal ein Beispiel sehen wie das aussieht.
Hier ein kleines Beispiel:
https://godbolt.org/z/d8hWqPxcz
In 3 Varianten:
- Zugriff auf Peripherieregister mittels Integer-To-Pointer cast und
volatile, also genau wie das bei den STM32-Libraries in Massen gemacht
wird
- Zugriff auf gewöhnliche globale Variable
- Zugriff auf "extern" Variable, Adresse per Linker-Argument definiert
Variante 1 ist um 4 bytes länger als die anderen beiden, weil der
Compiler das Register "r3" zweimal mit der Peripherieadresse lädt,
obwohl "r3" niemals verändert wird.
Johann L. schrieb:> Evtl. liegts auch am volatile der Registerzugriffe.
Gut möglich, aber ohne volatile ist's schwierig! Und volatile sollte ja
eigentlich auch nicht dafür sorgen, dass der Compiler denkt, dass sich
CPU-Register einfach so ändern können...
Den volatile-Schreibzugriff durch Inline-Asm zu ersetzen ändert
interessanterweise auch nichts, selbst ohne "volatile".
Es ist hier zwar nur eine Instruktion die nutzlos ist, aber über ein
komplexes Programm mit vielen Registerzugriffen kann sich das ganz schön
aufsummieren.
Hallo Leute,
danke für die vielen Antworten. Komme gerade nicht mehr mit :).
Vielleicht habe ich mich auch falsch ausgedrückt mit dem Bootloader. Ich
lasse natürlich den Originalen Bootloader auf dem Chip.
Johannes schrieb:> Beim STM32 ist ein eigener Bootloader nichts anderes als eine Firmware.> Der Factory Bootloader von STM kann nicht geändert werden und startet> immer zuerst. Die Jump Adresse für den Start der Firmware ist daher> immer 0x0800000000. Den eigenen Bootloader kann man daher dann wie eine> ganz normale Firmware aufspielen. Diese kann dann schauen ob eine> valide, zweite Firmware auf einer SD Karte liegt, diese in den Flash> kopieren, zb Address ab 0x082000000 und dann diese von dort ausführen.> Damit das funktioniert muss die zweite Firmware mit einem Offset> erstellt und kompiliert werden. Aber dazu gibt es jede Menge Anleitungen> im Netz
Also es soll dann so aussehen: STM Bootloader starten meine Firmware1,
die schaut ob es eine Update-Datei gibt, falls nicht startet Firmware2
also das Hauptprogramm meiner Hardware. Gibt es eine neue Datei und alle
Parameter stimmen( Datei vorhanden, Version neuer als die aktuelle)
ersetzt die Datei die Firmware2 im STM. Nach erfolgreichem kopieren
startet Firmware2.
Gibt es einen Befehl um Adressen im Speicher des STM anzuspringen (Kenne
es nur noch vom Amiga Assembler (JSR,JMP)). Benutze aktuell halt noch
die Arduino Umgebung auf Platformio.
Stefan M. schrieb:> Gibt es einen Befehl um Adressen im Speicher des STM anzuspringen
In Assembler "blx", vorher Stack-Pointer initialisieren (1. Eintrag im
ISR-Vektor) mittels "ldr" oder "mov", und SCB->VTOR auf die Adresse des
ISR-Vektors setzen.
Johannes schrieb:> Bei einem STM32 ist oftmals auch der Flash in Dual Banks implementiert.> Dann kann man auch den Bootloader direkt in die Firmware implementieren> und muss nicht mit zwei Projekten arbeiten. Man kann die Version auf der> SD Karte prüfen, wenn diese größer ist die Firmware auf die zweite Flash> Bank schreiben und aus dem Code raus die Option Bytes setzen, um einen> Bank Swap auszuführen. Der STM Bootloader wird dann beim nächsten> Bootvorgang zu der zweiten Flash Bank springen. Der Vorteil ist hier,> dass die ursprüngliche Firmware als Backup immer noch im Flash verweilt> und auch durch setzen der Option Bytes wieder auf Flash Bank 1> gewechselt werden kann. Der Nachteil ist, dass die Firmware maximal die> halbe Gesamtgröße des Flashs haben darf. Was bei 2MB selten ein Problem> sein sollte. Das funktioniert super, habe ich bei einem Projekt mit> Firmware Updates über Ethernet am laufen
Dazu eine Frage:
ich habe einen STM32L082 mit 192KB Flash.
Aktuell liegt mein Programm (ca. 62KB) auf Bank1 0x08000000 und
funktioniert.
Jetzt flashe ich mein Programm auf Adresse: 0x08018000 (Bank 2) und
setze danach BFB2 auf 1. Nach einem Reset wird das Programm auf Bank 2
nicht ausgeführt.
Setze ich BFB2 auf 0 dann läuft mein Programm von Bank 1.
Habe schon gegoogelt und dabei gelesen, dass das nur funktionieren würde
wenn der interne Bootloader aktiviert ist. Also Pin BOOT0 auf HIGH.
Stimmt das? Wenn ja, muss dann BOOT0 immer auf HIGH liegen?
Grüße, Werner
Werner P. schrieb:> Jetzt flashe ich mein Programm auf Adresse: 0x08018000 (Bank 2) und> setze danach BFB2 auf 1. Nach einem Reset wird das Programm auf Bank 2> nicht ausgeführt.
Dazu eine Frage : Linkst Du das Programm erneut für den Adressbereich in
Bank 2 oder schreibst Du einfach eine .bin-Datei, die der Linker für
Bank 1 angefertigt hat woanders hin ?
Frank O. schrieb:> Werner P. schrieb:>> Jetzt flashe ich mein Programm auf Adresse: 0x08018000 (Bank 2) und>> setze danach BFB2 auf 1. Nach einem Reset wird das Programm auf Bank 2>> nicht ausgeführt.>> Dazu eine Frage : Linkst Du das Programm erneut für den Adressbereich in> Bank 2 oder schreibst Du einfach eine .bin-Datei, die der Linker für> Bank 1 angefertigt hat woanders hin ?
Ich compile für Bank 1 0x08000000. Das flashe ich in die Bank 1
(0x08000000) und in die Bank 2 (0x08018000).
Habe das hier in Google gefunden:
https://community.st.com/t5/stm32-mcus-products/stm32l082-dual-nvm-banks-how-to-boot-from-bank2/td-p/65520
Now when I understand correctly this time -> the following should work
for the stm32L082:
Exact same code for bank1 can be written in bank2.
Flash bank1 and bank2 at the addresses as mentioned earlier.
Set BFB2 flag (1)
Reset the processor
Bank2 code will be running
Werner P. schrieb:> Ich compile für Bank 1 0x08000000. Das flashe ich in die Bank 1> (0x08000000) und in die Bank 2 (0x08018000).
das ist natürlich totaler Unsinn. Ein Programm was für Bank 1 kompiliert
ist wird niemals in Bank2 laufen.
Es gibt da wohl in einigen STM32 ein Feature, dass Johannes (zuberjo) am
02.10.2025 11:48 schonmal erwähnt hat. Da wechseln 2 Flash Banks ihre
Adressen. Im Forum ging es um einen stm32L082, der mit einem Config-Bit
diesen Trick vollbringt, dass für die Firmware alle Bits ab 0x08000000
mit denen ab 0x08018000 die Plätze tauschen. Aber kann das auch der
stm32f103 ?
Da wird anhand der Startup-Konfiguration (Pegel an Pins) einfach nur der
Startwert des Programmcounters gesetzt. Ganz andere (primitivere)
Technik.
Thomas Z. schrieb:> Werner P. schrieb:>> Ich compile für Bank 1 0x08000000. Das flashe ich in die Bank 1>> (0x08000000) und in die Bank 2 (0x08018000).>> das ist natürlich totaler Unsinn. Ein Programm was für Bank 1 kompiliert> ist wird niemals in Bank2 laufen.
hm. hab den code auch mal für BANK2 (0x08018000) compiled. Läuft aber
auch nicht. Irgendwie komme ich da grad nicht weiter.
Aktuell mach ich Firmware Update wie folgt:
Programm holt sich via Ethernet die Firmware und schreibt diese in BANK
2. Danach reset und somit Start meines Bootloaders (0x08000000) welcher
die Firmware von BANK 2 nach 0x08008000 kopiert. Dann wieder Reset und
das wars.
Wäre halt schön gewesen wenn ich mir meinen Bootloader sparen könnte.
Werner P. schrieb:> Läuft aber auch nicht. Irgendwie komme ich da grad nicht weiter.
Einfach mal per SWD debuggen...? Da siehst du sofort wo es stehen
bleibt...
so. Jetzt bin ich etwas weiter gekommen.
In main.c habe ich gleich am Anfang folgende Zeile eingefügt.
1
SCB->VTOR = 0x08000000;
Dann den Code für Bank 1 und für Bank 2 compiled und entsprechend
geflashed.
Je nachdem wie ich Option Byte BFB2 setze startet das Programm von Bank
1 oder Bank 2.
Somit schon mal einen Schritt weiter ;-)
Niklas G. schrieb:> Werner P. schrieb:>> SCB->VTOR = 0x08000000;>> Das ist doch der Default und sollte keinen Unterschied machen...
Dachte ich auch. Hab dann aber einen Foren Beitrag bei ST gefunden. War
selbes Problem.
Grüße
Hab jetzt noch mal weiter getestet.
code mit UART Ausgabe "boot from bank 1" für BANK 1 compiled.
selbigen code mit UART Ausgabe "boot from bank 2" für BANK 1 compiled.
Also gleiches programm nur mit unterschiedlichen UART Ausgaben.
Dann in BANK 1 und in BANK 2 geflasht.
Je nach Status von BFB2 läuft das Programm von BANK1 oder BANK2.
Sieht so aus als wenn:
Werner P. schrieb:> Sieht so aus als wenn:>> SCB->VTOR = 0x08000000;>> die Lösung war.
Skurril, dann ist es ein seltsamer Hardware-Bug - ein Feature zu viel!
Sicher dass du das VTOR nicht doch irgendwo vorher auf was anderes
setzt? Hast du mal den vorigen Wert von VTOR ausgeben lassen?
Niklas G. schrieb:> Werner P. schrieb:>> Sieht so aus als wenn:>>>> SCB->VTOR = 0x08000000;>>>> die Lösung war.>> Skurril, dann ist es ein seltsamer Hardware-Bug - ein Feature zu viel!> Sicher dass du das VTOR nicht doch irgendwo vorher auf was anderes> setzt? Hast du mal den vorigen Wert von VTOR ausgeben lassen?
Hier der Code in main.c
1
int main(void)
2
{
3
/* USER CODE BEGIN 1 */
4
5
6
/* here we check for which artifical bank in SRAM2 is the code in active Flash bank intended */
Werner P. schrieb:> vtor = 0x00000000
Interessant, vermutlich wirkt da normalerweise das Remap von 0x00 auf
0x08000000, aber nicht wenn die Bänke getauscht sind. Steht da was im
Errata Sheet dazu?
Werner P. schrieb:> 2.1.8 und 2.1.9 haben was mit dual-bank boot zu tun.
Hm, 2.1.8 ist bei aktuellen Chips repariert und 2.1.9 sollte sich nicht
auf VTOR auswirken...
Niklas G. schrieb:> Werner P. schrieb:>> 2.1.8 und 2.1.9 haben was mit dual-bank boot zu tun.>> Hm, 2.1.8 ist bei aktuellen Chips repariert und 2.1.9 sollte sich nicht> auf VTOR auswirken...
ok.
Mein STM32L082: Device ID: 0x447, Revision ID: Rev V
Die habe ich vor ca. 3-4 Jahren gekauft.
2.1.9 habe ich vorsichtshalber mal im Code eingefügt ;-)
Grüße, Werner
Hallo,
so ich bin auch weiter gekommen. Firmware1 habe ich in 0x08000000
geflashed und Firmware2 habe ich in 0x0800D000 geflashed. In
Platformio.ini habe ich in mein environment die option
board_build.flash_offset = 0xD000 eingefügt, somit muss ich das
linker-script nicht ändern sondern wird für die Adresse 0x0800D000
compiliert und geflashed.
Es startet zuerst Firmware1 danach läuft Firmware2. Jetzt kommt die
Update-Datei Abfrage, das kopieren der Datei von SD-Karte in den
Speicher 0x0800D000.
Bei dem Projekt, das ich damit am laufen habe, verwende ich einen
STM32H7. Die Binary File wird ganz normal compiliert, ohne Flash Offset.
Bei einem Bank Swap wird die zweite Bank mit 0x8000000 adressiert und
die erste nach hinten geschoben. Das macht es ziemlich einfach und man
muss nicht bei einem Update die Sorge haben, etwas mit den Adressen zu
verwechseln.
Bei läuft das aber auch alles aus der Firmware raus. Neue Binary in den
Flash schreiben (0x8100000), die Option Bytes abfragen ob Bank Swap
aktiv ist, wenn ja deaktivieren, wenn nein aktivieren und dann einen
Reboot initialisieren. Und so funktioniert es bei mir auch mit dem
Programmer. Die selbe Firmware kann ein mal auf 0x8000000 und 0x8100000
geschrieben werden. Je nach Option Bytes wird die eine oder andere
gestartet. Ausgeben kann man dies über eine Abfrage im Code selbst über
serielle Ausgabe. Option Bytes abfragen, wenn gesetzt, dann läuft Bank
2, wenn nicht dann Bank 1. Funktioniert alles problemlos. Aber ob es
irgendwelche Bugs oder Fallstricke bei anderen STM32 MCUs gibt kann ich
natürlich nicht sagen ohne jemals damit was gemacht zu haben
Hallo,
so hab es jetzt soweit am laufen. User kann über das Menü ein Update
auslösen, Stm resetet sich Firmware1 checkt die SD-Karte und schaut ob
eine Update Datei vorhanden ist. Falls ja kopiert er Firmware2 in den
Flash Speicher, führt einen CRC check durch, setzt ein checkbyte zurück
und resetet sich. Firmware1 erkennt Update durchgeführt und startet die
aktualisierte Firmware2. Jetzt fehlt noch ein Datei Check, also ob es
auch eine Datei für dieses System ist, Header im File und nicht
irgendeine firmware.bin). Nur einen würde mich noch interessieren, ich
kopiere ja die neue Firmware2 direkt von SD-Karte in den Speicher, was
ist wenn beim kopieren schief geht? Dann stimmt natürlich der CRC Check
nicht. In diesem Fall macht er 3 Versuche es erfolgreich zu kopieren.
Wenn nun aber auch nach dem 3. Versuch es nicht erfolgreich kopiert ist
dann ist ja keine lauffähige Firmware2 mehr im Flash oder sehe ich das
falsch?
Stefan M. schrieb:> so hab es jetzt soweit am laufen.
Cool, wie groß ist Firmware1 letztendlich? Hast du meinen Code für den
Sprung in Firmware2 genutzt?
Niklas G. schrieb:> Stefan M. schrieb:>> so hab es jetzt soweit am laufen.>> Cool, wie groß ist Firmware1 letztendlich? Hast du meinen Code für den> Sprung in Firmware2 genutzt?
Die ist 35Kb gross.
Ja, ich hab deinen Code benutzt, wenn ich darf.
Harry L. schrieb:> Ich nehme meine -voreilige- Meinung voll-umfänglich zurück!> Beitrag "Re: Eigener Bootloader stm32f103">> Gut gemacht!
Danke, hatte ja auch Hilfe von allen. Habe mich vielleicht auch nicht
richtig ausgedrückt mit Bootloader.
Stefan M. schrieb:> Die ist 35Kb gross.> Ja, ich hab deinen Code benutzt, wenn ich darf.
Happig, hoffentlich bleibt genug für die Anwendung übrig... Ja kannst du
nutzen, hatte mich nur gefragt ob du meine Antwort gesehen hattest
Niklas G. schrieb:> Stefan M. schrieb:>> Die ist 35Kb gross.>> Ja, ich hab deinen Code benutzt, wenn ich darf.>> Happig, hoffentlich bleibt genug für die Anwendung übrig... Ja kannst du> nutzen, hatte mich nur gefragt ob du meine Antwort gesehen hattest
Ja, bleibt genug übrig. Der stm32f103RGT6 hat ja 1MB Flash Speicher.
Klar hab ich deine Antwort gelesen. Danke