Ankündigung

Einklappen
Keine Ankündigung bisher.

persistent Variable

Einklappen
X
 
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

    [Featurewunsch] persistent Variable

    Nachdem es mit der v.3 jetzt die mtimechart() gibt, braucht man sich über das Speichern von langen Datenaufzeichnungen im Flash Memory keine großen Gedanken mehr machen. Das ist wunderbar!

    Aber es fehlt noch eine einfache Möglichkeit, den Status einzelner Variablen, und damit dann auch den Status des EibPC über den systemstart() hinweg zu retten.
    Die 999 Slots im Flash Memory sollten dafür reichen, auch wenn man so verschwenderisch ist, und pro Slot nur eine Variable speichert.

    Ideal ware eine Function die jeweils für eine Variable:
    - Bei systemstart() je nach Wunsch, der Variable aus dem Flash den Wert zuweist, oder das Flash mit einem initial Wert beschreibt.
    - Bei Änderung der Variablen nach einem Time-Delay den Wert ins Flash schreibt.
    - Auf Komando den Wert der Variablen ins Flash-Memory schreibt.
    - Für alle Daten-Typen funktioniert.

    Ich habe mit Hausmitteln ein einfaches Macro dafür geschrieben. Das funktioniert auch, ist aber ein wenig umständlich.
    Vielleicht geht das aber auch einfacher, ich bin Anfänger.
    Eine Function istaber sicher die beste Lösung.

    Das Macro zur Ansicht:
    Code:
    // $Id: RemMem.lib 64 2014-04-08 15:24:45Z asc $
    
    ////////////////////////////////////////////////////////////////////////
    // To observe:
    // - macro does not give any information about read/write success/failure.
    // - macro does not pass information about pending write operations.
    ///////////////////////////////////////////////////////////////////
    //
    :begin RemMemControl3(Pos,Var,remVar,forceWrite)
    :info $ Saves the state of any scalar variable Var to the flash memory.\\
    if forceWrite is set to OFF on systemstart() Var receives its value from the flash memory.\\
    if forceWrite is set to ON on  systemstart(), the value of Var during systemstart() is written to the flash memory.\\
    When Var changes, after a delay of changeDelay@ the new value of Val is written to the flash memory.\\
    ATTENTION: Two variables of the same type must be passed to the macro: \\
    Var is the variable the macro persists the state for,\\
    remVar must be passed for internal use of the macro and must not be changed from outside the macro!$\\
    $slot on the flash memory u16$\\
    $any scalar variable to safe the state $\\
    $for internal use only. Must be ame type as Var$\\
    $If set to EIN, writes the value of Val to the flash memory. During systemstart(),\\
    if set to EIN, prevents a readflash( ) and writes the initial value of Val to the flash memory$
    
    
    :var readSuccess@
    :var readComplete@
    :var readFault@
    :var writeFault@
    :var readDelay@
    :var changeDelay@
    :var readTimeout@
    :var writeTimeout@
    :var readPending@
    :var writePending@
    :var writeReq@
    
    
    readSuccess@   = EIN
    readComplete@  = AUS
    readFault@     = ON
    writeFault@    = ON
    readDelay@     = 2000u64      /* delay after systemstart() for reading RemMem */
    changeDelay@   = 60000u64     /* wait that time before writing to RemMem */
    writeTimeout@  = 120000u64
    readTimeout@   = 120000u64
    readPending@   = AUS
    writePending@  = AUS
    writeReq@      = AUS
    
    //////////////
    // reading
    /////////////
    // read from flash if forceWrite is EIN
    if after(systemstart(),readDelay@)  then{
       readSuccess@   = EIN;
       write( "DebugOut-10/4/0",$Init RemMem()$c14 );
       write( "DebugOut-10/4/0",$forceWrite: $c14+convert(forceWrite,$$c14)  );
       if( forceWrite) then{
          write( "DebugOut-10/4/0",$skip reading$c14 );
          readPending@   = AUS;
          readFault@     = OFF;
          writeReq@      = ON;
          }else{
          readPending@   = EIN;
          readFault@     = ON;
          write( "DebugOut-10/4/0",$readflash()$c14 );
          readFault@ = readflash( remVar,Pos ); 
          }endif ;
          forceWrite     = AUS;
       }endif
    
    // readflash() timeout handling
    if( delay(readPending@, readTimeout@ ) and readPending@) then{
       write( "DebugOut-10/4/0",$TimeoutR$c14 );
       readSuccess@   = AUS;
       readFault@     = OFF;
       }endif
    
    // after readflash() handling
    if( after(!readFault@,1u64 )) then{
          write( "DebugOut-10/4/0",$read comlete$c14 );
          write( "DebugOut-10/4/0",$rem: $c14+convert(remVar,$$c14)  );
          write( "DebugOut-10/4/0",$Suc: $c14+convert(readSuccess@,$$c14)  );
       if( readSuccess@ ) then{
          Var = remVar;
          }else{
          writeReq@ = EIN;
          }endif;
       readComplete@  = EIN;
       readPending@   = AUS;
       }endif
    ///////////////
    // writing
    //////////////
    // check if a write is needed
    if( delay(change(Var),changeDelay@ )) then{
       write( "DebugOut-10/4/0",$check$c14+convert(Var,$$c14)+$!=$c14+convert(remVar,$$c14)   );
       if Var != remVar then{
          writeReq@ = EIN;
          write( "DebugOut-10/4/0",$write req$c14 );
          }endif
       }endif
    // write to flash
    if (after((writeReq@ and readComplete@ and !writePending@ ), 1u64 )) then{
       writePending@  = EIN;
       writeReq@      = AUS;
       writeFault@   = ON;
       write( "DebugOut-10/4/0",$writeflash()$c14 );
       writeFault@   = writeflash( Var,Pos );
       }endif
    // write timeout
    if( delay(writePending@,writeTimeout@) and writePending@ ) then{
       write( "DebugOut-10/4/0",$TimeoutW$c14 );
       writeFault@   = OFF;
       }endif
    // after write handling
    if after(!writeFault@,1u64  ) then{
       write( "DebugOut-10/4/0",$write reset$c14 );
       remVar         = Var;
       writeFault@    = ON;
       writePending@  = AUS; 
       }endif
    // handle outside trigger for write
    if( after(forceWrite and readComplete@,1u64) and forceWrite) then{
       writeReq@   = EIN;
       forceWrite  = AUS;
       }endif         
    :end
    ////////////////////////////////////////////////////////////////////////
    alexander

    #2
    in diesem Zusammenhang:
    beeinflusst das häufige Schreiben eigentlich die Lebensdauer des Speichers?

    Wenn die neuen SHUTDOWN-Funktion implementiert ist, dann kann man auf häufiges Schreiben ja eigentlich verzichten - zumindest bei uns sind Stromausfälle seeeehr selten
    EPIX
    ...und möge der Saft mit euch sein...
    Getippt von meinen Zeigefingern auf einer QWERTZ Tastatur

    Kommentar


      #3
      Zitat von EPIX Beitrag anzeigen
      in diesem Zusammenhang:
      beeinflusst das häufige Schreiben eigentlich die Lebensdauer des Speichers?
      Ja... da gabs mal ne Zahl, der max. Schreibzyklen... die liegt zwar recht hoch, kann aber bei übermäßigem Gebrauch durchaus schnell erreicht werden.

      Bei den Timecharts wurde ich auch belehrt, nicht stündlich meine 20 Chartbuffers zu sichern. Also ich wäre da vorsichtig.

      auch ich würde die neue SHUTDOWN-Funktion abwarten... sicher ist sicher..

      Gruß Martin
      Die Selbsthilfegruppe "UTF-8-Probleme" trifft sich diesmal abweichend im groüen Saal.

      Kommentar


        #4
        Zitat von asc570 Beitrag anzeigen
        Das Macro zur Ansicht:
        Vielen Dank für Dein Makro.
        Hier ein grundsätzliche Anmerkung:
        Code:
           write( "DebugOut-10/4/0",$Init RemMem()$c14 );
           write( "DebugOut-10/4/0",$forceWrite: $c14+convert(forceWrite,$$c14)
        Zum Onlinedebuggen ist das gut und so mach ich das auch immer. Ich würde aber bei einem Makro, welches dann mal ausgereift ist, diese Debugmeldungen rausschmeißen. Am besten über ein define
        Code:
        #define MYMACRODEBUG
        ....
        #ifdef MYMACRODEBUG
           write( "DebugOut-10/4/0",$Init RemMem()$c14 );
           write( "DebugOut-10/4/0",$forceWrite: $c14+convert(forceWrite,$$c14) 
        #endif
        Nun kannst Du am Ende der Entwicklung das MYMACRODEBUG kommentieren und das Programm wird schlanker.
        offizielles Supportforum für den Enertex® EibPC: https://knx-user-forum.de/eibpc/
        Enertex Produkte kaufen

        Kommentar


          #5
          Danke @enertegus, für das Durchschauen des Macros und den Hinweis zu #ifdef.
          Zitat von EPIX Beitrag anzeigen
          Wenn die neuen SHUTDOWN-Funktion implementiert ist, dann kann man auf häufiges Schreiben ja eigentlich verzichten - zumindest bei uns sind Stromausfälle seeeehr selten
          EPIX hat sicher Recht, das mit der angeküdigten SHUTDOWN() Funktion, in den meisten Fällen die persistent Variablen nur noch vor dem Shutdown ins Flash geschrieben werden müssen.

          Gerade dann aber ist es sinnvoll, neben einer Funktion shutdown(), ähnlich systemstart() , auch eine mit den Shutdown verbundene Funktionalität für persistent Variable bereitzustellen.
          Die einfachste Form ist sicher so etwas wie:

          persist(Variable,FlashSlot,WriteFlag)
          Funktionalität:
          - if(systemstart() and !WriteFlag) then readflash(Variable,FlashSlot) endif
          - if shutdown() then writeflash(Variable,FlashSlot) endif
          - if WriteFlag than ( writeflash(Variable,FlashSlot); WriteFlag = OFF) endif
          - return den Rückgabewert von readflash()

          Die Funktionalität benötigt kein über readflash/writflash hinausgehendes Management des Flash und ist auch mir readflash/writeflash kompatible.

          Ich denke das sollte reichen.

          alexander

          Kommentar

          Lädt...
          X