Forum: Mikrocontroller und Digitale Elektronik ATSAMD51 Flash Bank Swap


von Firmwareupdater (Gast)


Lesenswert?

Hallo zusammen,
ich versuche gerade die Funktion eines Firmwareupdates auf einem 
ATSAMD51J19 zu implementieren. Hierzu werden per UART Daten vom PC 
übertragen und auf die Bank B des Flash (Adresse 0x40000) geschrieben. 
Nach CRC-Prüfung der Daten wird final mit
1
/* wait until it is ready to accept a new command */
2
while (!NVMCTRL->STATUS.bit.READY);
3
            
4
/* execute the command BKSWRST (Bank swap and system reset) */
5
NVMCTRL->CTRLB.reg = NVMCTRL_CTRLB_CMD_BKSWRST | NVMCTRL_CTRLB_CMDEX_KEY;
6
            
7
/* wait until command done */
8
while (NVMCTRL->INTFLAG.bit.DONE);
9
/* At the end of this command, code starts running from 0x00000 upon reset*/
der Bank Swap sowie Reset durchgeführt.

Leider funktioniert das nur selten, bzw eigentlich nur dann, wenn ich 
z.B. in der Zeile
1
(NVMCTRL->INTFLAG.bit.DONE);

einen Breakpoint setze. Sonst funktioniert der Bank Swap und Reset 
nicht. Nach einem manuellen Reset (z.B. neu einstecken) und auslesen des 
NVMCTRL.Status.AFIRST bits ist dann auch keine Änderung zu sehen. Wird 
kein manueller Reset durchgeführt, startet der µC auch nicht 
selbstständig neu hängt wohl irgendwo?!

Interrupts sind global aktiviert, wobei aber während des Updates aber 
nur der Peripheral-Interrupt für den UART freigegeben ist. Alle anderen 
sind währenddessen deaktiviert.

Gibt es hier spontan weitere Vorschläge, was man noch beachten muss?
Falls nicht, werde ich versuchen ein Minimalbeispiel zu erzeugen.

Beste Grüße,
Firmwareupdater

von Stephan (Gast)


Lesenswert?

Wir machen das beim ATSAM4DSxx so (ggf ist es beim ATSAMD51xx ähnlich), 
dass alles, inkl des Bank-Switches im RAM läuft.

Also:
{
<...>
Interrupts abschalten();
ramfunc Bank umschalten();
ramfunc Reset();
<NEVER REACH THIS>
}

Denn, nachdem die Bank umgeschaltet ist, ist es beim ATSAM4DSxx so, dass 
das Flash bereits auf die neue Bank zeigt. Jeder Code der im Flash 
läuft, läuft dann wahlweise aus Zufall (weil im Flash der "anderen" Bank 
der Code zufällig passt) oder eben nicht.

Wie Du RAM-Funktionen machst, hängt von Deiner 
Entwicklungs/Buildumgebung ab.

von Stephan (Gast)


Lesenswert?

gerade nochmal nachgeschaut. Das Vorgehen war nicht genau genug:
1
{
2
  <...>
3
  Interrupts abschalten();
4
  ramfunc finale_umschaltung_UND_reset(bank);
5
  <NEVER REACH THIS>
6
}
7
8
ramfunc finale_umschaltung_UND_reset(bank){
9
  ramfunc Bank umschalten(bank);
10
  ramfunc Reset();
11
}

:)

von Firmwareupdater (Gast)


Lesenswert?

Hallo Stefan,

vielen Dank für den Hinweis. Ich schätze allerdings dass dies bei dem 
ATSAMD51 nicht nötig ist. Hier gibt es im Non-Volatile-Memory-Controler 
einen Befehl, der den Bank-Swap und Reset durchführt. Im prinzip würde 
das von mir beschriebene Verhalten allerdings zu deinem Hinweis passen.

Wenn ich im Disassembly per debugger durchgehe funktioniert der Reset 
und Bankswap auch. Nur eben ohne Debugger nicht:-P Der Optimizer ist 
inzwischen auch mal deaktiviert, ändert aber leider auch nichts.

Sonst noch jemand ideen? Ich bau hier nebenbei mal das 
Minimalbeispiel...

Grüße Firmwareupdater

von Stephan (Gast)


Lesenswert?

Hi FWU,

Hast Du vorher alle INT disabled?
Ansonsten: im Datenblatt des ATSAM4SD steht auch, das die 
Bankumschaltung (dort geht das nur über die EFC, nicht  direkt über den 
NVMCtrl wie bei Dir) erst NACH dem Reset wirkt und eben nicht SOFORT… 
hat mich auch ein paar Kaffee gekostet…;)
VG Stephan

von Firmwareupdater (Gast)


Angehängte Dateien:

Lesenswert?

Hallo Stefan,

ja, die IRQ sollten abgeschalten sein. Im Anhang jetzt mal die main.c 
als Minimalbeispiel.


Wenn ich mit dem Debugger im Disassembly die letzten Schritte 
durchsteppe führt er den Bank-Swap sowie den Reset durch. Sonst bleiben 
die LEDs Rot an und es folgt auch nach manuellem Reset (PWR OFF-ON) kein 
Bank-Swap.

Gruß Firmwareupdater

von Stephan (Gast)


Lesenswert?

Ich kann es leider mangels D51 nicht testen…
Was mich (analog zu den Erfahrungen beim SAM4) stutzig macht, ist das 
while() nach dem baswrst:

 /* wait until command done */
            while (NVMCTRL->INTFLAG.bit.DONE);
            /* At the end of this command, code starts running fro


Also entweder macht der NVMCtrl einen Reset: dann kommt er nie beim 
folgenden while() an!
Oder, das while wird erreicht- wer macht dann den reset?
Und wenn die bank umgeschaltet hat, bist Du bei meinem Beispiel: da 
steht dann im flash nämlich möglicherweise kein while…

Was passiert denn, wenn du die SELBE firmware schreibst (bit-gleich)? 
Geht‘s dann? Dann würde nach dem bank switch nämlich das while() da 
stehen…

Ansonsten würde ich das mal mit der ramfunc probieren… (die ganze 
umschaltlogik inkl dem abschliessenden while()).

Ob der Debugger das alles weiss, ist eh fraglich; unsere IAR workbench 
weiss auch nichts von Bank-Switches…

Vg Stephan

von Firmwareupdater (Gast)


Lesenswert?

Stephan schrieb:
> Ich kann es leider mangels D51 nicht testen…

Kein Problem, vllt findet sich ja noch jemand der das auf nem D51 nutzt. 
Hatte irgendwie erwartet, das wäre ein verbreitetes Verfahren. Aber auch 
im internet gibt es jetzt nicht sonderlich viele Berichte hierzu.


Das warten hier
1
while (NVMCTRL->INTFLAG.bit.DONE);
 hatte ich in meiner ursprünglichen Version auch nicht drin. Habe es 
dann aber in dem Microchip-Support-Artikel hier gefunden:

https://microchipsupport.force.com/s/article/SAM-D5x-E5x---NVM-Bank-Swapping

Hat aber auch nichts weiter gebracht...

Ich werde jetzt die Sache mit der ramfunc noch testen, habe aber eher 
weniger Hoffnung auf Erfolg. Werde berichten...

Gruß Firmwareupdater

von Stephan (Gast)


Lesenswert?

Und was ist das Ergebnis, wenn Du die bitgleiche FW umschaltest? Das 
Ergebnis wäre nicht unerheblich für die Lösungssuche…

von Firmwareupdater (Gast)


Lesenswert?

hatte ich vergessen, sry... Leider genau das selbe, d.h. kein Reset und 
kein Bank-Swap wenn man es ohne Einzelschritt im Debugger durchlaufen 
lässt.

von Stephan (Gast)


Lesenswert?

Ok! Wenn das stimmt (und Du Dich bei den BankADR nicht verrechnet 
hast;)!), dann bin ich wenig optimistisch, das es mit der Ramfunc 
klappt; trotzdem probieren! Was für eine IDE hast Du?

Das nächste wäre ein lowlevel debug ohne IDE: aka LED setzen. Wir müssen 
dann genau verstehen bis wohin er kommt/wo genau er stehen bleibt. 
Gibt‘s einen Hardfault oder wie genau bleibt er hängen?

von Firmwareupdater (Gast)


Lesenswert?

es scheint so als würde es mit der RAMFUNC funktionieren...melde mich 
nochmal

von Stephan (Gast)


Lesenswert?

Nachtrag:
>und Du Dich bei den BankADR nicht verrechnet hast;)!)

Du bist wirklich sicher, dass eine Bitgleiche FW auch wirklich an der 
selben Stelle in beiden Flash-Bänken  landet?
Also z.B. 0x4004711 enthält das selbe wie 0x5004711?
Und das ist auch NACH einem Reset noch so?
Du kannst auf die jeweils inaktive Flashbank auch lesend zugreifen- das 
ist übrigens unser letzter Check: eine CRC über den gesamten, gerade 
geschriebenen Flashbereich und Vergleich mit einer referenzCRC.

von Stephan (Gast)


Lesenswert?

Firmwareupdater schrieb:
> es scheint so als würde es mit der RAMFUNC funktionieren...melde
> mich nochmal

Okay….;)

Und: <kleine Kritik> der code ist ein kleines bisschen unübersichtlich 
;)

von Stephan (Gast)


Lesenswert?

Und: Hat es einen Grund warum Du die CRC (crc_ccitt_update) Berechnung 
selbst machst? Die ATSAMx haben fast alle eine sauschnelle CRC32C 
Einheit…
(Oder brauchst Du die CCITT Variante?)

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.