Dauertest und Bootloadereinsprung

  • 1
  • 2
  • Page 1 of 2
pvs-deck
PowerUser
Avatar
Gender:
Age: 53
Homepage: pvs-deck.de
Posts: 1341
Registered: 02 / 2009
Subject:

Dauertest und Bootloadereinsprung

 · 
Posted: 26.03.2020 - 16:09  ·  #1
Hallo Leute,

ich habe da ein Problem mit einer Steuerung beim Dauertest (TÜV)
Die Steuerung wurde in ihrer Funktion über 200.000 x getestet ohne auch nur einen Fehler.
Jetzt habe ich wahrscheinlich ein Fehler gemacht und alle Kontakte und Meldungen wurden auf der SD-Card geloggt. Und wahrscheinlich habe ich damit die max. Anzahl der Schreibzyklen durch den Dauertest erreicht.

Danach wurde die Steuerung in die Klimakammer gesteckt -20 C bis +50 C und rlt. Luftfeuchte 95%.

Aus irgendeinen Grund ist die Steuerung dabei in den FirmwareFlash Modus gegangen, das erledige ich mit dieser Funktion
Code
//---------------------------------------------------------------
// Flash einleiten
procedure StartFlash;
begin
  mDelay(300);
   F16_FlushBufSec;  // Sichere offene Dateien
    //F16_SDIO_Idle;    // Schalte die MicroSD auf IDLE
     USB_Detach;       // USB Abmelden
      EEprom[EEpromEnd]:= $FF;   // invalidate application for Boot usage
       mDelay(800);
        WDoff;  // Watchdog abschalten
         HardWareReset;    // Reset ausführen und Sprung in den BOOTBEREICH
end StartFlash;



Mein Bootloader Ausschnitt:
Code

procedure CheckError;
begin
      if    BootErr = bootNoErr           then OutStr:= '00 no Error';         // Keine Fehler alles OK
      elsif BootErr = bootInvCardType     then OutStr:= '01 inv.Card Type';    // Falscher SD-Card Typ
      elsif BootErr = bootInvBootType     then OutStr:= '02 inv. Boot Type';
      elsif BootErr = bootReadFail        then OutStr:= '03 read Fail';        // Lesefehler
      elsif BootErr = bootClusterNotfound then OutStr:= '04 Cluster not Found';// Cluster Fehler evtl. defekte Firmwaredatei oder SDCard
      elsif BootErr = bootFalseID         then OutStr:= '05 wrong ID';         // Falsche LoaderID
      elsif BootErr = bootFalseCPU        then OutStr:= '06 wrong CPU';        // Firmware nicht für diese CPU geeignet
      elsif BootErr = bootAESerr          then OutStr:= '07 AES Error';        // AES entschlüsselungsfehler
      endif;
      PrintString('ERR:'+OutStr,4,1); // LCD-Ausgabe Fehler
    loop
      // gehe in Wartestellung und mache nichts weiter
    endloop;
end CheckError;


{--------------------------------------------------------------}
{ Main Program }
{$IDATA}
begin
  // Optional a port pin can be checked for a forced download
  // If Pin.x = false then skip the EEprom checks
  //  ...
Debug_Break;
  if EEprom[EEpromEnd] = $00 then
    // If a Download failed or the app was never programmed then there is no $00
    // If the main app forces a download then the last byte in the EEprom must be $FF
    Application_Startup;
  endif;
Debug_Break;
// Nur Init, wenn der Flash gemacht werden soll..
// InitPort
  WDOff; // Schalte WD OFF !!!
//HxDispData
  DDRE.2:= 1;  // 0=EINGANG  1=Ausgang
   I2CInit;

// Ziehe Pointer für CHARS
 ptrLoadChars := @gLoadChars;

// LCD aktivieren
 LCDInit;


//Start-Meldung
PrintString('Bootloader V1.01',1,1);
// mDelay(10000);

  // at first check the Card detect switch, if present!
  // if ...

  // Initialize the MMC and check for a valid FAT16 file system
  if not FATInit then
    // big problem !!
     CheckError;
  endif;

{$IfDef FAT_bootModeAES}
  AES_Init(@DecryptKey);  // necessary if AES encryption is used
{$endif}

     PrintString('Flash Firmware...',3,1);  // Ausgabe LCD-Display

  if not UpdateFirmware($xxxx) then          // BootLoader ID
  // es gab einen Fehler
    CheckError;
  endif;
  
  loop
    // Downloader does an exit to the main app if
    // a valid main has been downloaded
    // so normally it will not enter here
  endloop;


In dem Code prüfe ich auf "EEprom[EEpromEnd] = $00" und wenn das 00 ist, startet er die MainApp.
Hier scheint es aber so zu sein, als ob aus irgendeinen Grund die Steuerung von alleine kein 00 mehr dort stehen hat. Denn nach einem Neustart hat er nicht mehr die "Application_Startup;" durchgeführt.

Er wollte nun ein Firmware-Flash durchführen, da aber die SD-Card wahrscheinlich den Geist aufgegeben hat,
wurde die Routine:
Code
  // Initialize the MMC and check for a valid FAT16 file system
  if not FATInit then
    // big problem !!
     CheckError;
  endif;


ausgeführt und es gab einen Initfehler. Nun hängt die Steuerung da fest, was nun leider sehr ärgerlich ist, die Steuerung muß nun erneut in die Klimakammer :-(

Im Checkerror
Code
procedure CheckError;
begin
      if    BootErr = bootNoErr           then OutStr:= '00 no Error';         // Keine Fehler alles OK
      elsif BootErr = bootInvCardType     then OutStr:= '01 inv.Card Type';    // Falscher SD-Card Typ
      elsif BootErr = bootInvBootType     then OutStr:= '02 inv. Boot Type';
      elsif BootErr = bootReadFail        then OutStr:= '03 read Fail';        // Lesefehler
      elsif BootErr = bootClusterNotfound then OutStr:= '04 Cluster not Found';// Cluster Fehler evtl. defekte Firmwaredatei oder SDCard
      elsif BootErr = bootFalseID         then OutStr:= '05 wrong ID';         // Falsche LoaderID
      elsif BootErr = bootFalseCPU        then OutStr:= '06 wrong CPU';        // Firmware nicht für diese CPU geeignet
      elsif BootErr = bootAESerr          then OutStr:= '07 AES Error';        // AES entschlüsselungsfehler
      endif;
      PrintString('ERR:'+OutStr,4,1); // LCD-Ausgabe Fehler
    loop
      // gehe in Wartestellung und mache nichts weiter
    endloop;
end CheckError;


Zeigt das Display nun "00 no Error" an,da es ja keinen BootErr gab, das werde ich nun etwas anpassen. Kurze Anzeige, das es einen InitFehler gab und dann automatisch "Application_Startup;" ausführen. Damit er dabei nicht mehr hängen bleibt.

Weiterhin werde ich das ganze ändern, es muss eine bestimmte Zahl im EEPROM stehen, damit der Flash Ausgeführt wird.

Hat Jemand von euch eine Idee, warum sich dieser EEPROM Bereich von alleine geändert hat?
Der Temperaturbereich kann es doch nicht sein oder?

Thorsten
Harry
Moderator
Avatar
Gender:
Location: zwischen Augsburg und Ulm
Age: 59
Posts: 2134
Registered: 03 / 2003
Subject:

Re: Dauertest und Bootloadereinsprung

 · 
Posted: 26.03.2020 - 16:19  ·  #2
Hallo Thorsten,

über sich selbst verändernde EEPROM wurde schon viel geschrieben und auch ich hatte schon meine Probleme damit. Was ich weiß ist, daß sich ein EEPROM anscheinend ändern kann, wenn eine niedrige Spannung anliegt. Damit meine ich eine Spannung, bei der der µC selber gar nicht arbeitet. Gehört habe ich, daß Elkos bei Temperatursprüngen durch chemische Reaktionen Spannungen erzeugen können, die dann zu EEPROM-Veränderungen führen können. Deshalb: FRAM ..... ja das wolltest du nicht hören.

Gruss
Harry
pvs-deck
PowerUser
Avatar
Gender:
Age: 53
Homepage: pvs-deck.de
Posts: 1341
Registered: 02 / 2009
Subject:

Re: Dauertest und Bootloadereinsprung

 · 
Posted: 26.03.2020 - 19:14  ·  #3
Hallo Harry,

notfalls habe ich noch einen Bereich in meiner RTC MCP79410, mit:
- 64-Byte Battery-Backed SRAM
- 128 Byte EEPROM mit Software write-protect
- 8 Byte Protected EEPROM Area

Der Rest vom EEProm-Bereich liegt als Backup-Config auf der SD-Card, ich werde das Konzept mal etwas überarbeiten, so das bei einem fehlerhaften Inhalt vom EEPROM (CRC-Check) nach einem Neustart über dem Bootloader diese von der SD-Card übernommen wird.

Weiterhin grenze ich die Schreibzugriffe noch etwas ein und speicher nicht mehr jedes Ereignis auf der SD-Card ab. Im Moment nehme ich meine Logs aus der Pipe von den anderen Prozessen/ Tasks und öffne und schreibe die die Einträge auf die SD-Card.

Und es muss im SRAM und im EEPROM eine spezielle Zahl stehen oder beim booten die Servicetaste gedrückt werden, damit er in den Bootloadermodus springt. Dies sollte ausreichen um so ein Fehlerbild zu vermeiden :-(

Im Moment ist er immer in den Bootloadermodus gesprungen, wenn es nicht mehr 0 war.

Thorsten
pvs-deck
PowerUser
Avatar
Gender:
Age: 53
Homepage: pvs-deck.de
Posts: 1341
Registered: 02 / 2009
Subject:

Re: Dauertest und Bootloadereinsprung

 · 
Posted: 26.03.2020 - 22:04  ·  #4
Hallo rolf,

ich habe das Problem und den BUG gefunden, die SDCard ist nicht defekt, der Hänger ist hier scheinbar in der Funktion "UpdateFirmware()".
Hier müsstest Du mal etwas nachbessern.

Angenommen ich nutze wie im Standard Bootloader:

Code
  if not EEprom[EEpromEnd] = $00 then 
    // If a Download failed or the app was never programmed then there is no $00
    // If the main app forces a download then the last byte in the EEprom must be $FF
    Application_Startup;
  endif;


Und aus irgendeinem Grund (gewünscht oder nicht) ist im "EEprom[EEpromEnd]" ein anderer Wert anstelle des $00 (für Main APP ok) oder $FF (FirmwareUpdate).

Dann passiert in Deiner Funktion "UpdateFirmware(id)" zwar scheinbar das Update, aber die Funktion kehrt mit einem "FALSE" und BootErr = 00 zurück. (siehe Bild)
Und hängt dann im loop beim CheckError fest:
Code
procedure CheckError;
begin
      if    BootErr = bootNoErr           then OutStr:= '0 NO ERROR';         // Keine Fehler alles OK
      elsif BootErr = bootInvCardType     then OutStr:= '1 INV.CARD';    // Falscher SD-Card Typ
      elsif BootErr = bootInvBootType     then OutStr:= '2 INV. BOOT';
      elsif BootErr = bootReadFail        then OutStr:= '3 READ FAIL';        // Lesefehler
      elsif BootErr = bootClusterNotfound then OutStr:= '4 CLUSTER NOT FOUND';// Cluster Fehler evtl. defekte Firmwaredatei oder SDCard
      elsif BootErr = bootFalseID         then OutStr:= '5 WRONG ID';         // Falsche LoaderID
      elsif BootErr = bootFalseCPU        then OutStr:= '6 WRONG CPU';        // Firmware nicht für diese CPU geeignet
      elsif BootErr = bootAESerr          then OutStr:= '7 AES ERROR';        // AES entschlüsselungsfehler
      endif;
      PrintString('ERR:'+OutStr,4,1); // LCD-Ausgabe Fehler
    loop
      // gehe in Wartestellung und mache nichts weiter
    endloop;
end CheckError;


Das selbe ist mir gerade aufgefallen im Test mit $AA, das UpdateFirmware() darf da nicht mehr $FF verlangen, denn das wird ja bereits beim booten von der BootApp geprüft, wenn kein $00 dann mache das UpdateFirmware.

Zum Test (Workaround) habe ich nun mal den Code in der BootApp erweitert:

Code
// BUG AVRCO hier muss vor UpdateFirmware auf $FF gesetzt werde
  EEprom[EEpromEnd]:= $FF; // setze auf FF
   mDelay(200);


{$IfDef FAT_bootModeAES}
  AES_Init(@DecryptKey);  // necessary if AES encryption is used
{$endif}

     PrintString('FLASH FIRMWARE...',3,1);  // Ausgabe LCD-Display


  // This reads the UpdateFile and flashes it into the application area.
  // If selected then also EEprom and UserRow are reprogrammed.
  // The filename can have upto 8 chars, the extension must be ".dld"!
  // The extension must not be included and is always ".dld"
  if not UpdateFirmware($A9F0) then          // BootLoader ID
  // es gab einen Fehler
    CheckError;
  endif;


Wenn ich vor dem AES_Init die "EEprom[EEpromEnd]" wieder auf $FF setze funktion alles einwandfrei.

Ich arbeite jetzt erstmal mit dem Workaround, sollte aus irgendeinem Grund mal wieder was anderes im EEprom[EEpromEnd] als $00 oder jetzt bei mir $AA beim starten der MainApp stehen, habe ich in meinem Code vor dem MainLoop einen Check auf Ungleichheit $00 ergänzt:

Somit passiert nun folgendes:
1. Es steht kein $00 und kein $AA in der Speicherstelle dann bootet er in der bootapp beim neustart/reset
Code
  if not EEprom[EEpromEnd] = $AA then // alt war $00
    // If a Download failed or the app was never programmed then there is no $00
    // If the main app forces a download then the last byte in the EEprom must be $AA
    Application_Startup;
  endif;


Da kein $AA vorhanden ist, springt er in die MAINAPP, prüft beim booten
Code
// prüfe ob EEPROMEND Schrott im Bootloader-Start enthält und setze hier wieder  00
//
if (EEprom[EEpromEnd] <>  $00) then
  if (EEprom[EEpromEnd] <>  $AA) then
   EEprom[EEpromEnd]:= $00; // setze auf 00  
  endif;
endif;

Und es steht wieder $00 im EEPROM

2. ich fordere ein FirmwareUpdate an (mit $AA), nach dem reset/neustart steht in der Speicherstelle $AA, die MainApp wird nicht gestartet, sondern der FirmwareUpdate wird durchgeführt.

Sollte es einen InitSD Fehler geben, zeige ich dies kurz an, und starte die MainApp:
Code
  if not FATInit then
     PrintString('ERR:INIT SD',4,1); // LCD-Ausgabe Fehler
      mDelay(800);
       Application_Startup;
  endif;

In der MainApp setze wieder "EEprom[EEpromEnd]:= $00;"

Wenn es keinen Fehler gibt, setzte ich vor dem AES_Init und UpdateFirmware(), die Speicherstelle auf $FF, damit sich die Funktion UpdateFirmware nicht im loop aufhängt:

Code
// BUG AVRCO hier muss vor UpdateFirmware auf $FF gesetzt werde
  EEprom[EEpromEnd]:= $FF; // setze auf FF
   mDelay(200);


Thorsten
Attachments
UpdateFirmware
Filename: 20200326_Boot.jpeg
Filesize: 85.15 KB
Title: UpdateFirmware
Information: UpdateFirmware
Download counter: 139
rh
Administrator
Avatar
Gender:
Location: Germany
Age: 24
Homepage: e-lab.de
Posts: 5558
Registered: 03 / 2002
Subject:

Re: Dauertest und Bootloadereinsprung

 · 
Posted: 01.04.2020 - 20:50  ·  #5
Hallo Thorsten,
Code

  if not EEprom[EEpromEnd] = $00 then 
    // If a Download failed or the app was never programmed then there is no $00
    // If the main app forces a download then the last byte in the EEprom must be $FF
    Application_Startup;
  endif;

Kann ja nicht sein. Bei <> $00 springt das System in das MainApp. Falsch !!!
Bei einem $FF muss ein Download angefordert werden.
Ansonsten (<> $FF) kann davon ausgegangen dass das Main ok ist.

Seit Jahren arbeiten unsere Programmer mit dieser Mimik.
Bei x-tausend Geräten noch kein Problem. Sorry.

rolf
Thomas.AC
Benutzer
Avatar
Gender: n/a
Age: 43
Posts: 308
Registered: 07 / 2013
Subject:

Re: Dauertest und Bootloadereinsprung

 · 
Posted: 02.04.2020 - 21:51  ·  #6
Hallo Thorsten,
da bin ich aber froh, dass mein Bootloader es wie folgt handhabt.
Code

  if EEprom[EEpromEnd] <> $FF then
    Application_Startup;
  endif;


Mein Mitleid
Attachments
||| v7: (12.08.2019) AVRco 5.10.01 Optimizer 3.6.5.0
||| Changed bootloaderId and version
||| Deleted FlashCheck_A, because it overwrites the app's checksum in hex file
||| Changed BOD level to 2.8V
program boot;

Device = xmega128A4U, VCC = 3.3;
{$BootApplication}


Define_Fuses
Override_Fuses; // update ispe file
//COMport = USB;
//ProgMode = PDI;
//LockBits0 = [BLBB0, BLBB1, LB0, LB1]; // protect boot and app against read back
FuseBits0 = [];
FuseBits1 = [WDPER0, WDPER2]; // watchdog = 8s
FuseBits2 = [BOOTRST]; // mandatory for bootloader
FuseBits4 = [WDLOCK];
FuseBits5 = [BODACT0, BODLEVEL1, BODLEVEL2]; // BOD = 2.8V
progFuses = true;
progEEPROM = true;
AddApp = '..\app\udac'; // use batch file if addApp does not work
// addApp fails without a message

Import FlashWrite, FAT_BootX, SerPortE0;

From System Import LongWord, Traps;

Define
OSCtype = int32MHz; // default
StackSize = $100, iData;
FrameSize = $200, iData;
SerPortE0 = 115200, Stop1; // debug connection
FAT_BootPort = SPI_D, PortD.4;
FAT_BootMode = plain; // plain or AES
FAT_BootFile = 'UDAC';

uses uFAT_BootX;

Implementation

{$EEPROM}
structconst
EE_bootMe[eepromEnd] : byte = $00; // jump to app after programming the pac file to
// prevent downgrade if an old udac.dld exist on card
// after flashing pac file

{$IDATA}

const
BootLoaderVersion : word = 7;
BootLoaderID : word = 8323; // must be equal to Application's ID

{--------------------------------------------------------------}
{$VALIDATE $} // no optimise
function trap_getBootLoaderID : word; Trap;
begin
return (BootLoaderID);
end;

{$VALIDATE $} // no optimise
function trap_getBootVersion : word; Trap;
begin
return (BootLoaderVersion);
end;

{--------------------------------------------------------------}
{ Main Program }
begin
Writeln(SeroutE0, 'Boot loader v' + IntToStr(BootLoaderVersion)
Filename: udac_boot.pas
Filesize: 3.17 KB
Title:
Download counter: 94
pvs-deck
PowerUser
Avatar
Gender:
Age: 53
Homepage: pvs-deck.de
Posts: 1341
Registered: 02 / 2009
Subject:

Re: Dauertest und Bootloadereinsprung

 · 
Posted: 05.04.2020 - 15:15  ·  #7
Quote by rh

Hallo Thorsten,
Code

  if not EEprom[EEpromEnd] = $00 then 
    // If a Download failed or the app was never programmed then there is no $00
    // If the main app forces a download then the last byte in the EEprom must be $FF
    Application_Startup;
  endif;

Kann ja nicht sein. Bei <> $00 springt das System in das MainApp. Falsch !!!
Bei einem $FF muss ein Download angefordert werden.
Ansonsten (<> $FF) kann davon ausgegangen dass das Main ok ist.

Seit Jahren arbeiten unsere Programmer mit dieser Mimik.
Bei x-tausend Geräten noch kein Problem. Sorry.

rolf


Hallo rolf,

Du kannst es ja mal testen schreibe vor dem UpdateFirmware an die Speicherstelle was anderes
als EEprom[EEpromEnd] = $FF, dann geht die Routine nach dem Flash mit FALSE raus und hat aber keinen FehlerCode, deswegen Error:NoError.

Dieses Fehlverhalten kann ich reproduzieren, oder ist das irgendwie gewollt? Lt. Anleitung startet der UpdateFirmware nach einem erfolgreichen Flash die Appl.! Macht er aber nur, wenn $FF in dieser Speicherstelle steht ;-)

Wäre dieses Problem nicht, hätte der XMEGA ein Flash gemacht und die MainApp gestartet und fertig.

Wie gesagt, wenn es gewollt ist, sollte man dies in der Doku anpassen. Aber wenn er flasht und es kein Error gab, dann sollte er doch lt. aktueller Anleitung die MainApp starten oder?

Ich kann jetzt erstmal mit dem Workaround leben, aber vielleicht doch mal nachschauen, warum er mit FALSE und keinen FehlerCode aus der Routine geht und dann nicht startet.

Thorsten
Thomas.AC
Benutzer
Avatar
Gender: n/a
Age: 43
Posts: 308
Registered: 07 / 2013
Subject:

Re: Dauertest und Bootloadereinsprung

 · 
Posted: 05.04.2020 - 22:52  ·  #8
Hallo Thorsten

Code

if not EEprom[EEpromEnd] = $00 then
    Application_Startup;


Das ist nicht der Standard Bootloader Code und irritiert, da dein Problem nicht auftreten kann.
  • 1
  • 2
  • Page 1 of 2
Selected quotes for multi-quoting:   0

Registered users in this topic

Currently no registered users in this section

The statistic shows who was online during the last 5 minutes. Updated every 90 seconds.
MySQL Queries: 17 · Cache Hits: 15   143   158 · Page-Gen-Time: 0.056076s · Memory Usage: 2 MB · GZIP: on · Viewport: SMXL-HiDPI