habe ein Paar grundsätzliche Fragen zum Schreiben/Flashen einer Firmware über einen Mikrocontroller in einen anderen (i.d.F. einen Nordic)
Derzeit schreibe ich per SWD-Protokoll mit DAP (Debug Access Port) in den Flash-Speicher des NRF52180 das Image der Firmware folgendermaßen rein:
Erste bis vorletzte Memory Page werden seitenweise geschrieben
Letzte Memory Page wird word-/byte-weise geschrieben
Gibt es technische Möglichkeiten den Prozess des Flash-Vorgangs zu beschleunigen? Aktuell verzichte ich probeweise auch auf das Auslesen des READY-Flags und benutze stattdessen ein us-Delay. Das angepeilte Ziel wären <4s für 0x3000 Flash-Speicher des N52180.
Welche Verifizierungsmöglichkeiten bestehen bei so einem Flashvorgang? Ich benutze derzeit einen Prüfsummenabgleich für das Gesamtimage. Außerdem lese ich das Image einmal komplett aus und vergleiche es mit der Referenz. Was gäbe es außerdem für Möglichkeiten?
Hat jemand Erfahrungen mit dem im Referenzdokument erwähnten Flashloader gemacht? Ich komme mit dem EFM32-Beispiel auf keine bessere zeit als mit dem direkten Flashzugriff.
Du könntest einen flash loader in's RAM laden. Danach lädst Du den Inhalt einer Seite in einen von 2 Puffern und startest den flash loader. Während der flash loader die Seite in den flash Speicher schreibt (und auch korrekt auf das READY event wartet), kann eine 2. Seite im RAM schon via SWD mit dem Inhalt der nächsten Seite gefüllt werden.
So erreichst Du minimale (und korrekte) Wartezeiten und kannst die Wartezeit bereits zum Transport der nächsten Daten verwenden.
Zum Verifizieren fällt mir auch nichts besseres ein, als eine CRC über den gesamten Speicher zu bilden (das kann z.B. auch der im RAM liegende flash loader machen).
Keine Ahnung, welches Referenzdokument Du referenzierst.
Da würde ich mal in die Eingeweide von OpenOCD z.B. für STM32xxx schauen: Da wird eine einfache Schleife ins RAM geladen, die sich aus einem Ringpuffer bedient und ins Flash schreibt, der Ringpuffer wird seinerseits parallel über SWD (oder JTAG) nachgefüllt. Der Engpass ist da eher die SWD-Taktfrequenz.
Verify macht man sinnvollerweise über CRC, das läuft komplett intern und es ist damit kein Datentransport über SWD nötig.
Da würde ich mal in die Eingeweide von OpenOCD z.B. für STM32xxx
schauen: Da wird eine einfache Schleife ins RAM geladen, die sich aus
einem Ringpuffer bedient und ins Flash schreibt, der Ringpuffer wird
seinerseits parallel über SWD (oder JTAG) nachgefüllt. Der Engpass ist
da eher die SWD-Taktfrequenz.
Diese "einfache Schleife" nenne andere halt flash loader ;-) Der Aufwand besteht im wesentlich darin, seine Toolchain dazu zu bekommen, einem so einfachen code zu generieren (ohne vector table, ohne runtime etc.).
Naja, "Flash Loader" klingt nach wer weiß was ... Das sind nur ein (je nach Komplexität des Flash Interfaces) zwei bis drei Dutzend Zeilen Assembler (ja Assembler, das spart halt den ganzen Aufwand mit Stack, Vektor-Tabelle, Lib und sonstigem Gerümpel).
Naja, "Flash Loader" klingt nach wer weiß was ... Das sind nur ein (je
nach Komplexität des Flash Interfaces) zwei bis drei Dutzend Zeilen
Assembler (ja Assembler, das spart halt den ganzen Aufwand mit Stack,
Vektor-Tabelle, Lib und sonstigem Gerümpel).
Anbei der Code meines flash loaders. Im linker script muss SUPPORT_LIB_RAM_BASE und SUPPORT_LIB_RAM_SIZE entsprechend ersetzt werden. Der ganze loader muss nicht in Assembler geschrieben werden.
Du könntest einen flash loader in's RAM laden. Danach lädst Du den
Inhalt einer Seite in einen von 2 Puffern und startest den flash loader.
Während der flash loader die Seite in den flash Speicher schreibt (und
auch korrekt auf das READY event wartet), kann eine 2. Seite im RAM
schon via SWD mit dem Inhalt der nächsten Seite gefüllt werden.
Obwohl ich keine Probleme mit dem delay_us habe (im schlimmsten Fall bekomme ich beim Schreiben in das Register einen WAIT und warte auf das READY), ist der flashloader natürlich eleganter. Welche Werte beim Flashen erreichst du damit erfahrungsgemäß, mal nachgemessen gehabt? Mit meinem aktuellen Konstrukt erreiche ich "nur" 8,2s für den gesamten Flashspeicher (0x3000)
Erstmal vielen lieben Dank für eure Antworten! Schade, dass nur das
Radio-Modul einen automatischen CRC Checker bieten :)
Ja, mir würde auch nicht einfallen, wie man den für seine Zwecke nutzen könnte, zumal DMA in der Regel auch nur im RAM funktioniert. Du könntest aber z.B. die Checksumme über den Inhalt der RAM-Puffer machen. Z.B: nach dem Du das flashen gestartet hast, dann muss Du nicht auf das READY-Flag pollen, sondern rechnest die CRC und vergleichst danach das RAM mit dem geschriebenen Flash.
Welche Werte beim
Flashen erreichst du damit erfahrungsgemäß, mal nachgemessen gehabt? Mit
meinem aktuellen Konstrukt erreiche ich "nur" 8,2s für den gesamten
Flashspeicher (0x3000)
Das Projekt ist schon etwas länger her (ein Bluetooth LE SWD Debugger). Ich meine mich aber zu erinnern, dass der Flaschenhals Bluetooth war und damit sollte es bestimmt mit mindestens 40kByte/s geschrieben haben (in einem sehr alten Protokoll finde ich auf jeden Fall 7kBytes/s).
Du must mal gucken, was bei Dir im System der Flaschenhals ist. "Time to Write one word" ist mit maximal 338µs angegeben (nRF53832). Damit müssten also mindestens 11,5kBytes/s möglich sein. Als Minimum ist 67,5µs angegeben, was dann ein Maximum von ~58kBytes/s.
Wenn Du für jedes Wort mindestens 338µs wartest und mit jedem Wort die Latenz zum Abfragen und Schreiben mehrere Register via SWD hast (Wort Schreiben, Flashen Starten, Wort zurück lesen), dann kommst Du natürlich sehr schnell auf Zeiten im Millisekunden-Bereich pro Wort.
Gibt es technische Möglichkeiten den Prozess des Flash-Vorgangs zu
beschleunigen? Aktuell verzichte ich probeweise auch auf das Auslesen
des READY-Flags und benutze stattdessen ein us-Delay. Das angepeilte
Ziel wären <4s für 0x3000 Flash-Speicher des N52180.
Gibt es einen technischen Grund für die Zeitvorgabe? Beim interaktiven Flashen sind auch 10s so kurz, dass das An- und abklemmen schon deutlich länger dauert.
Im MCU boot gibt es sogar eine option das erase verhalten umzustellen
von erase befor programming auf erase on demand.
Zahlen hab ich jetzt nicht im kopf, aber das waren fuer die 512kb ein
paar sekunden, und keine minuten.
nRF hat zum Glück eine ERASEALL-Funktionalität, welche deutlich unter page-wise erasing liegt. Wenn die Anforderungen es sonst erlauben, kann ich jedes mal einen kompletten Löschvorgang ausführen. Habe mal nachgemessen:
erase page: 83ms (von insgesamt 0x30 pages) → 3984ms für alle
erase all: 165ms
Gibt es einen technischen Grund für die Zeitvorgabe? Beim interaktiven
Flashen sind auch 10s so kurz, dass das An- und abklemmen schon deutlich
länger dauert.
Es ist eine Anforderung, hängt mit einem Initial-Flashvorgang während der Gerätemontage zusammen. Wenn sich die Manager dadurch effektiver fühlen, sei es drum ;) Für mich an der Stelle eine interessante technische Herausforderung.
und wieso nimmt man nichts von der stange?
Wir verwenden z.B. Segger JFLASH in der Produktion. Der kann auch den NRF programmieren ueber SWD. Inital programmiert wird im ICT.
und bei einer Inital programmierung gehe ich davon aus, das der flash lehr ist, bzw das ich einen erase all vorneweg absetzen kann.
Zeitlich haengt das ganze ggf auch noch von der SWD geschwindigeit hab. Was kann der Programmer, und was hat man eingestellt.
Alles anderes ist dann fuer mich updating mit einem selber geschriebenen (oder uebernommenen) flasching rotine.
Da funktioniert dann nur noch page erase. da kann man dann ggf zeit sparen wenn man waerend des programmerens von page 1 page 2 loescht.
aber vermutlich geht irgend wo ganz anders die zeit drauf. Wenn du schnell sein willst, muss empfang der daten, loeschen und programieren, crc berechnen quasie parallel laufen. und nicht sequenziell.
"habe ein Paar grundsätzliche Fragen zum Schreiben/Flashen einer Firmware
über einen Mikrocontroller in einen anderen"
Weil man z.B. Firmware-Updates über eine Schnittstelle bekommt, die an dem einen, aber nicht an dem anderen µC angeschlossen ist. Auf dem µC, der die Updates bekommen soll, könnte man auch einen Bootloader installieren, der kostet dann aber extra Flash und auf der client Seite braucht es auch einen bootloader client, da kann dann SWD machmal einfacher sein.