Eigener Bootloader stm32f103

OP #7944694
Lesenswert?

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.

: Bearbeitet durch Moderator
#7944710
Lesenswert?

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

#7944717
Lesenswert?

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.

#7944843
Lesenswert?

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.

#7944847
Lesenswert?

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.

#7944931
Lesenswert?

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.

OP #7944973
Lesenswert?

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

#7944983
Lesenswert?

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.

#7944986
Lesenswert?

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.

#7944988
Lesenswert?

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.

: Bearbeitet durch User
OP #7944993
Lesenswert?

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?

#7945007
Lesenswert?

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.

: Bearbeitet durch User
#7945009
Lesenswert?

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.

#7945105
Lesenswert?

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.

: Bearbeitet durch User
#7945114
Lesenswert?

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.

Persönliche Seite #7945128
Lesenswert?

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.pdf

Flunder 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.

: Bearbeitet durch User
#7945139
Lesenswert?

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.

Persönliche Seite #7945144
Lesenswert?

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.

: Bearbeitet durch User
#7945152
Lesenswert?

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.

#7945159
Lesenswert?

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.

Persönliche Seite #7945166
Lesenswert?

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.

Persönliche Seite #7945174
Lesenswert?

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

Persönliche Seite #7945193
Lesenswert?

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

Persönliche Seite #7945203
Lesenswert?

Μα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.

#7945212
Lesenswert?

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

Persönliche Seite #7945244
Lesenswert?

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

Persönliche Seite #7945250
Lesenswert?

Μα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?

: Bearbeitet durch User
Persönliche Seite #7945263
Lesenswert?

Niklas G. schrieb:

Μαtthias W. schrieb im Beitrag #7945244: 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?)

Persönliche Seite #7945265
Lesenswert?

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...

Persönliche Seite #7945266
Lesenswert?

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

Persönliche Seite #7945276
Lesenswert?

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.

: Bearbeitet durch User
Persönliche Seite #7945285
Lesenswert?

Μα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.

OP #7946982
Lesenswert?

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.

Persönliche Seite #7946992
Lesenswert?

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.

1
void runApp (uint32_t appAddr) {
2
  WRITE_REG(SCB->VTOR, appAddr);
3
  __asm__ volatile (
4
    "mov r4, sp\n"
5
    "ldrd r0, r1, [%[appAddr]]\n"
6
    "mov sp, r0\n"
7
    "dsb\n"
8
    "isb\n"
9
    "cpsie i\n"
10
    "blx r1\n"
11
    "mov sp, r4\n"
12
    : : [appAddr] "r" (appAddr) : "r0", "r1", "r2", "r3", "r4", "r12", "lr", "cc", "memory"
13
  );
14
}
: Bearbeitet durch User
#7947015
Lesenswert?

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

#7947429
Lesenswert?

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 ?

#7947457
Lesenswert?

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

#7947494
Lesenswert?

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.

#7947495
Lesenswert?

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.

#7947510
Lesenswert?

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 ;-)

#7947522
Lesenswert?

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:

1
SCB->VTOR = 0x08000000;

die Lösung war.

Grüße, Werner

#7947537
Lesenswert?

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 */
7
  uint32_t vtor = SCB->VTOR;
8
  SCB->VTOR = 0x08000000;
9
  /* USER CODE END 1 */
10

11
  /* MCU Configuration--------------------------------------------------------*/
12

13
  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
14
  HAL_Init();
15

16
  /* USER CODE BEGIN Init */
17

18
  /* USER CODE END Init */
19

20
  /* Configure the system clock */
21
  SystemClock_Config();

vtor = 0x00000000, danach 0x08000000

Grüße

OP #7947582
Lesenswert?

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.

#7947854
Lesenswert?

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

OP #7948596
Lesenswert?

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?

OP #7949170
Lesenswert?

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

: Bearbeitet durch User

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren