Problem mit CRC Berechnung

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

Problem mit CRC Berechnung

 · 
Posted: 15.03.2021 - 12:26  ·  #1
Hallo Leute,

ich habe bei einem XMEGA und der CalcCheckSum ein Problem, was ich irgendwie nicht eingrenzen kann.

Bei jeder Änderung der Einstellungen wird die CRC der Konfiguration im EEProm berechnet und im RTC-Ram (Batterie gepuffert) abgelegt und und die Einstellungen aus dem EEProm werden als Config-Datei auf die SD-Card gelegt.

Bei einem Neustart wird die CRC berechnet und mit dem CRC im RTC-Ram verglichen, ist es gleich läuft die Steuerung durch und fertig.

Ist diese unterschiedlich, werden die Einstellungen von der SDCard geladen, sollte die SDCard nicht verfügbar sein, werden die Werkseinstellungen aus dem Flash geladen, diese werden als Datei in den Flash eingelinkt:
Code
 const
  gLoadSTDCFG        : tLoadSTDCFG   = 'STDCFG.CFG';      // Std CFG mit flashen  


Auf der SDCard sind unter umständen verschiedene Konfigs, wenn ich die Konfig ausgewählt habe, lade ich diese in den EEProm Bereich und berechne die CRC:

Code
//---------------------------------------------------------------
// Load Config
procedure Load_Cfg( inFileName : Pointer to string; BBootCfg : boolean; BZKSCfgLoad : boolean);
var
 wXCopy           : Word;
 wResBlockWrite   : Word;
 wResBlockWriteAll: Word;
 CfgPointer       : pointer;
 CfgPointerWork   : pointer;
 strStrFileName   : string[12];
 BFileLoadOK      : boolean;
 BlockAnzahl64    : byte;
begin

if bMMCok then // SD Card vorhanden und aktiv
   BFileLoadOK:=false;

   if BBootCfg then // bootCfg StandardName
       DateiNameCfg := 'boot.cfg';
   else
    strStrFileName:= inFileName^;
     DateiNameCfg := strStrFileName;
   endif;

 if not F16_FileExist(sPathPara, DateiNameCfg,[faArchive]) then  // .CFG vorhanden?
         return;
 else
   if ListDirGetEntry( sPathPara, DateiNameCfg, [faArchive]) then  // TSearchRecord laden wegen Datum und Uhrzeit
      SDCfgDate := SR.Dir.WrAccDate;
       SDCfgTime := SR.Dir.WrAccTime;
   endif;

   if BZKSCfgLoad then BlockAnzahl64:=62; else BlockAnzahl64:= 58; endif;
    

 lock(self); // Lass Dich nicht stören

      if not F16_FileAssign(Cfg_Datei, sPathPara, DateiNameCfg) then // Handle mit FileNamen verknüpfen
       CheckFileHandle(Cfg_Datei);
         return;
      endif;

       if not F16_FileReset( Cfg_Datei ) then   // vorhandene Datei öffnen
        CheckFileHandle(Cfg_Datei);
          return;
        endif;

        // Init der Zähler
         wResBlockWrite:=0;
          wResBlockWriteAll:=0;

         CfgPointer:= @Cfg1; // ziehe Pointer für Start vom EEPROM

          for wXCopy:= 0 to BlockAnzahl64 do
            CfgPointerWork:= CfgPointer+(wXCopy * 64);

             BFileLoadOK:= F16_BlockRead (Cfg_Datei,  @SDBuf64, 64 ,wResBlockWrite );

              if not BFileLoadOK then
                F16_FileClose(Cfg_Datei); // schließe evtl offene Datei vor Break
                Break;
              endif;

            CopyBlock( @SDBuf64, EEPromPtr(CfgPointerWork), 64 ); // übertrage es in den EEProm Bereich
              wResBlockWriteAll:=wResBlockWriteAll+wResBlockWrite; // für geschriebene Daten berechnen!
          endfor;


      if not F16_FileClose(Cfg_Datei) then                         // File schließen
        SD_Error := 7; 
      endif; // CloseFile

unlock(self); // lass Dich wieder stören

 endif; // .CFG vorhanden?

 endif; // if bMMCok then
end Load_Cfg;


Danach ruf ich die folgende Funktion auf:
Code
//---------------------------------------------------------------
// Errechne Config CRC und lege diese im RTCRAM ab 
//
procedure CalcCfgCRC;
var 
 wCRC_Buffer : word;
 
begin
 wCRC_Buffer:= CalcCheckSum (@Cfg1, @BInvalidateBoot); // Berechne CRC
  wCRC_Config_RTC:= wCRC_Buffer;  // Lege den Wert im RTC-Ram ab Userdevice
  DebugOut('Eprom CRC: '+IntToHex(wCRC_Buffer));
end CalcCfgCRC;


Da der RTC-RAM über ein I2C Bus erreichbar ist, habe ich das über ein USERDEVICE angelegt:
Code
{ functions }
UserDevice UsrDevIni;
begin
// Prüfe ob Speicher init benötigt wird:
  if TWIoutE(RTC_MCP_ID, $20+38) then // set the read address
    TWIinpE(RTC_MCP_ID, inWordCheck);           // read the word
   if inWordCheck <> $1A2B then
    TWIoutE(RTC_MCP_ID, $20); // Setze Start Adresse
    for xInit:= 0 to 63 do
     // fülle SRAM mit $00 auf
      TWIoutE(RTC_MCP_ID, $20+xInit, $00);
    endfor;
    // usrW38_CheckSram
     TWIoutE(RTC_MCP_ID, $20+38, $1A2B);  // Wenn Init dann steht hier 1A2B
   endif;
    return;
  endif;

end;

//-----------------------------------------------------------------------------
UserDevice UsrDevInp(adr : word) : byte;
var ok  : boolean;
    inp : byte;
begin
  lock(self);
 ok:= TWIoutE(RTC_MCP_ID, $20+lo(adr));              // set the read address
  if ok then
    TWIinpE(RTC_MCP_ID, inp);                                // read the byte
    unlock(self);
    return(inp);
  endif;

 unlock(self);
  return($ff);
end;

//-----------------------------------------------------------------------------
UserDevice UsrDevOut(adr : word; outp : byte);
var ok  : boolean;
begin
   lock(self);
    ok:= TWIoutE(RTC_MCP_ID, $20+lo(adr), outp);
      unlock(self);
end;

Und jetzt kommt das merkwürdige, wenn ich dann später den Test mit der Funktion:
Code
//-----------------------------------------------------------------------------
// Prüfe CRC cfg
function CheckCfgCRC : boolean;  
var 
 wCRC_Buffer : word;

begin
 wCRC_Buffer:= CalcCheckSum (@Cfg1, @BInvalidateBoot); // Berechne CRC
  DebugOut('Eprom CRC: '+IntToHex(wCRC_Buffer)+ ' / RTC RAM CRC: '+IntToHex(wCRC_Config_RTC) );

  if wCRC_Config_RTC <> wCRC_Buffer then
     return(false);
    else
     return(true);  
    endif;
end CheckCfgCRC; // CheckCfgCRC


Beim überprüfen erhalte ich ab und an ein FAIL. Also einen Unterschied zwischen dem errechneten CRC und dem Wert im RTC-RAM. Der Wert im RTC-Ram entspricht dem Wert den der XMEGA aber nach dem Schreiben errechnet hat. Nur wenn ich dann erneut berechnet (ohne Änderung) erhalte ich eine leichte Abweichung.

Jetzt wird es noch merkwürdiger, gehe ich jetzt in die Einstellungen der Steuerung und ändere nur einen Wert, danach wird wieder der CRC berechnet und abgelegt, dann stimmt der Wert. Mache ich jetzt die Änderung in den Einstellungen der Steuerung Rückgängig, stimmen die CRCs wieder.

Ich habe fast das Gefühl, das nach der Übernahme der Datei Einstellungen auf der SCCard, diese noch nicht richtig fertig sind um eine CRC Berechnung zu machen. Als ob der Treiber / XMEGA im Hintergrund erst noch im EEProm speichert. Ein MDELAY(100) bringt leider keinen Unterschied und eigentlich nutze ich mit dem Process und Tasksystem NIE Delays.

Hat Jemand evtl. eine Idee, wo das Problem liegen könnte?

Thorsten
Merlin
Administrator
Avatar
Gender:
Age: 24
Posts: 1409
Registered: 03 / 2005
Subject:

Re: Problem mit CRC Berechnung

 · 
Posted: 15.03.2021 - 17:35  ·  #2
Is it possible that an interrupt is occurring at just the wrong time? Maybe one that does not save and restore all of its registers?

Might be worth looking at the ASM for this routine to see which registers are used.

Another possibility is of course stack or frame overflow but I imagine that you have already eliminated this possibility.

At any event the intermittent nature of it suggests something of this nature.
pvs-deck
PowerUser
Avatar
Gender:
Age: 53
Homepage: pvs-deck.de
Posts: 1341
Registered: 02 / 2009
Subject:

Re: Problem mit CRC Berechnung

 · 
Posted: 15.03.2021 - 18:33  ·  #3
Hallo Merlin,

danke für die Ideen. Stacks und Frames sind beide OK.
Es gab auch keinen Überlauf, ich überwache alle meine Tasks und Processe auf Überlauf.

Für mich sieht es eher danach aus, als ob der XMEGA im Hintergrund noch die Werte im EEProm speichert. Frage ich etwas später die CRC ab, erhalte ich den richtigen Wert.

Ich werde ich mal eine Verzögerung programmieren.

Thorsten

-------------------
Hello Merlin,

thanks for the ideas. Stacks and frames are both OK.
There was also no overflow, i monitor all of my tasks and processes for overflow.

For me it looks more like the XMEGA is still saving the values ​​in the EEProm in the background. If I query the CRC a little later, I get the correct value.

I'll program a delay.
pvs-deck
PowerUser
Avatar
Gender:
Age: 53
Homepage: pvs-deck.de
Posts: 1341
Registered: 02 / 2009
Subject:

Re: Problem mit CRC Berechnung

 · 
Posted: 16.03.2021 - 11:26  ·  #4
Hallo Leute,

es hat wohl wirklich etwas mit dem Delay nach dem EEProm schreiben zu tun.

Ich habe nun eine verzögerte CRC-Berechnung gemacht und damit funktioniert es perfekt.

Einer meiner Prozesse refresht ca. 3x pro Sekunde die Statuszeile im Display. für eine ca. 3 Sekunden Verzögerung lasse ich hier einfach einen Zähler bis 10 hochzählen und errechne dann erst den CRC-Wert.
Code
var
// Flash EEProm Check-System
// 16.03.2021 10:25:22 TD
//
  BLoadFlashAktiv  :  boolean;   // Merker für verzögerte CRC Berechnung
  bLoadFlashWarte : byte;      // Wartezähler


Ich schalte nach dem "Load_Cfg()" einfach einen Bool auf True:
Code
            Load_Cfg(@ListEntry[bReturnIndex].sFileName, false, BCfgZksLoad); 
            BLoadFlashAktiv:=true;


Im Prozess rufe ich dann durch den Zähler verzögert den CRC ab:

Code
...
// Workaround für Flash-CRC Problem
// Erst flashen lassen und dann CRC berechnen
// 16.03.2021 10:20:09 TD 
//   
  if BLoadFlashAktiv then
   inc(bLoadFlashWarte);
     if bLoadFlashWarte >= 10 then
          BLoadFlashAktiv:=false;
           bLoadFlashWarte:=0;
           CalcCfgCRC; // Errechne Config CRC             
    endif;
  endif;
  
  Schedule;       // Rechenzeit freigeben 
...


Es sieht fast so aus, als ob der XMEGA im Hintergrund erst noch das EEPROM-Flasht, bei kleinen Änderungen ist das kein Problem. Aber wenn ich den Ganzen EEPROM Bereich übernehme scheint dies ein Problem zu sein.

Thorsten
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: 15 · Cache Hits: 14   80   94 · Page-Gen-Time: 0.025954s · Memory Usage: 2 MB · GZIP: on · Viewport: SMXL-HiDPI