Welcome to our new forum
All users of the legacy CODESYS Forums, please create a new account at account.codesys.com. But make sure to use the same E-Mail address as in the old Forum. Then your posts will be matched. Close

Wago 750-841: Retain Daten blähen Bootprogramm auf

Wühlmaus
2012-08-03
2012-11-14
  • Wühlmaus - 2012-08-03

    Hallo,

    gar Seltsames tut sich bei mir:

    Wenn ich den Umfang meiner Retain-Daten (konkret: VARIABLE RETAIN PERSISTENT) vergrößere, wächst die mit "Bootprojekt erzeugen" generierte und auf die Wago transferierte Datei um ca. das 36fache der Retain-Vergrößerung. Da ich Retain-Daten jetzt im größeren Stile nutzen wollte, um alle Benutzereingaben und Regler-Variablen auch nach Programm-Neustart weiter nutzen zu können, passt das Bootprogramm nicht mehr in den Speicher. Das geht gar nicht.

    Außerdem: Wenn ich alle Retain-Deklarationen entferne, sagt der Compiler, dass 77 bytes Retain-Daten verwendet werden. Sind das die Bytes, die schon kaputtgeschrieben wurden ? Das wäre aber enttäuschend, die Wago ist drei Jahre alt und ich ändere die Retain-Daten bisher alle paar Wochen mal. Wenn's 100 Schreibvorgänge gewesen sein sollen, ist das schon hochgegriffen.

    Was verstehe ich mal wieder falsch ?

     
  • Anonymous - 2012-08-06

    Originally created by: thomas_nienstaedt

    Ich finde Retain / Persistent sind nicht das Mittel der Wahl...
    ich benutze für solche Fälle gerne Syslibfile!

    ich lese am Anfang in einem Init die Daten ein und fülle die Datenstrukturen!
    Die ganze Struktur überwache ich auf Änderung und schreibe dann wieder!

    ... du hast einen 841?
    wenn du auf einen 880 umsteigen würdest könntest du die Retain-datei
    auf die SD legen und hättest deinen Controller etwas entlastet!?
    Schwierig wird es bei dieser Methode mit vielen Schreib/Lese-Zyklen auf die SD!

    Aber es ist halt wie immer:
    Wo Licht ist,
    ist auch Schatten!

    VG
    thomas

     
  • Wühlmaus - 2012-08-06

    thomas_nienstaedt hat geschrieben:
    Ich finde Retain / Persistent sind nicht das Mittel der Wahl...
    Warum nicht ? Sind meine geschilderten Beobachtungen also zutreffend ?

    thomas_nienstaedt hat geschrieben:
    ich benutze für solche Fälle gerne Syslibfile!
    Wenn's bei mir denn funktionieren würde - siehe den Parallelthread eins vorher ...

    thomas_nienstaedt hat geschrieben:
    ich lese am Anfang in einem Init die Daten ein und fülle die Datenstrukturen!
    Gibt es eigentlich irgendeine Möglichkeit, beim Neustart des Programms Änderungen in der DatenStruktur automatisch zu erkennen und zu behandeln ? Da mein Projekt anscheinend nie fertig wird, sind Softwareänderungen mit immer neuen Bedienparametern für 99% der Neustarts verantwortlich. Ich habe mir jetzt mit einiger Mühe eine dynamische Speicherverwaltung gebastelt, bei der ich für willkürlich zu definierende Teilmengen der gesamten Retain-Daten jeweils eigene Versionsnummern vergeben kann, die dann überwacht werden. Wenn sich eine solche Teilmenge in der Struktur ändert, können alle anderen Daten unversehrt übernommen werden. Wenn ich bestimmte Konventionen einhalte (z.B. einen zusätzlichen Parameter nicht mitten in die vorhandene Teilmenge reinquetschen, sondern ausschließlich hintendran hängen), werden sogar alle gespeicherten Parameter der geänderten Teilmenge gerettet. War etwas mühsam, da alles mit Pointern implementiert, macht sich jetzt aber eigentlich ganz gut.

    thomas_nienstaedt hat geschrieben:
    ... du hast einen 841? wenn du auf einen 880 umsteigen würdest könntest du die Retain-datei
    auf die SD legen und hättest deinen Controller etwas entlastet!?
    Ich erwäge den Umstieg, da der Speicherplatz für die Visus immer knapper wird, fürchte aber, dass der Umstieg im Detail dann doch nicht so reibungslos vonstatten geht. Ist diese Furcht unbegründet ?

    thomas_nienstaedt hat geschrieben:
    Schwierig wird es bei dieser Methode mit vielen Schreib/Lese-Zyklen auf die SD!
    Ich habe Regel/Adaptionsprozesse, die sich über Monate hinweg ziehen. Diese werden im Moment einmal täglich aktualisiert. Für andere Regelgrößen wäre stündliches Aktualisieren wünschenswert - ich kann aber auch mit drei oder 6 Stunden leben, wenn's der Lebenserwartung des FLASH dienlich ist. Bedienparameter schreibe ich, wenn sie sich ändern (dann aber immer immer die ganze Teilmenge, siehe oben).

     
  • WAGO - 2012-08-22

    Hallo Christoph,

    bei den 77 Bytes handelt es sich schon mal definitiv nicht um "kaputte" Sektoren. Wenn der Compiler 77 Bytes an Retain-Daten ausweist, dann wirst Du diese irgendwo auch benutzt haben. Vielleicht in einem Funktionsbaustein aus einer "fremden" Bibliothek, den Du einsetzt?

    Es ist in der Tat so, dass sich die Größe des Bootprojekt bei der Verwendung von Retain-Daten erheblich erhöht. Vielleicht solltest Du noch einmal prüfen, ob wirklich alle Variablen ihren Wert bei Programmänderung beibehalten müssen. Ggfs. kannst Du hier bei kritischer Betrachtung einiges an Speicherplatz gewinnen.

    Hinweis: Die Größe der Retaindaten, die der Compiler nach vollzogener Arbeit meldet, beinhaltet alle Variablen außer den Merkern. Merker, die als retain deklariert worden sind, werden im "Memory"-Bereich verwaltet.

    Bei weiteren Fragen kannst Du uns auch gerne unter den unten genannten Adressdaten direkt kontaktieren.

     
  • Wühlmaus - 2012-08-22

    Hallo WAGO Support Team,

    danke für die Antwort.

    WAGO hat geschrieben:
    bei den 77 Bytes handelt es sich schon mal definitiv nicht um "kaputte" Sektoren. Wenn der Compiler 77 Bytes an Retain-Daten ausweist, dann wirst Du diese irgendwo auch benutzt haben. Vielleicht in einem Funktionsbaustein aus einer "fremden" Bibliothek, den Du einsetzt?
    Es wird immer merkwürdiger. Habe im aktuellen Stand des Projekts die mittlerweile verwendeten 280 Bytes VAR RETAIN PERSISTENT umgewandelt in simple VAR und alle PRGs und FBs nochmal nach "retain" abgesucht, aber nichts Überraschendes mehr gefunden. "Fremde" Bibliotheken setze ich nicht ein, nur CoDeSys und Wago Libs. Und nun sagt der Compiler, dass 312 Bytes Retain-Daten verwendet seien. Zählt der alles, was jemals verwendet WURDE, auch wenn es aktuell gar nicht verwendet wird ? Hmpffff ...

    WAGO hat geschrieben:
    Es ist in der Tat so, dass sich die Größe des Bootprojekt bei der Verwendung von Retain-Daten erheblich erhöht.
    Dass an sich, leuchtet ja ein. Aber warum um 36 Bytes für jedes zusätzliche Retain-Byte ?

    WAGO hat geschrieben:
    Die Größe der Retaindaten, die der Compiler nach vollzogener Arbeit meldet, beinhaltet alle Variablen außer den Merkern. Merker, die als retain deklariert worden sind, werden im "Memory"-Bereich verwaltet.

    Meines Wissens verwende ich keine Merker, jedenfalls nicht mit Absicht. Weiß ehrlich gesagt gar nicht, was das ist.

     
  • ggauf - 2012-09-24

    Hallo,

    bei mir ist's das Gleiche...

    Ich wollte ein Array (0..199) von einer struct mit 13Byte, also insgesamt 2600Byte, mit Parametern auf retain persistent setzen...

    Der Unterschied zwischen normaler Variablen Deklaration und als retain beträgt:
    Daten: -3200 Byte
    Retaindaten: +3200 Byte
    Code: +104440 Byte

    Das erste verwunderliche ist, dass meine struct aus 7 Byte-, 2 Word- und 1 Int-Variablen besteht, macht für mich 13 Byte, es werden aber ganz offensichtlich 16 Byte / struct verwendet (egal ob retain oder nicht).
    Dies wäre nicht schlimm wenn sich der Code eben nicht um das 32-fache der Daten aufblähen würde, dies ist komplett unakzeptabel, da ich ansonsten bald an die Codegrenze stoße...

    Meine Lösung ist, da diese Paramter nicht so häufig verwendet werden, das gesamte array in einen File zu schreiben und beim starten wieder einzulesen.

    file_ok:= FALSE;
    handle := SysFileOpen(filename,zugriff);                (* Datei öffnen bzw. generieren *)
    SysFileWrite(handle, ADR(Automatik_Parameter_Array[0]),Automatik_FileSize);
    file_ok := SysFileClose(handle);                 (* Datei schließen *)
    

    wobei Automatik_FileSize 2600 ist...
    Das Einlesen erfolgt identisch mit SysFileRead.

    Meine Frage: besteht ein Risiko bei diesem verfahren ? - kann ich sicher sein, dass das Array an einem Stück im Speicher liegt und ich nicht beim Einlesen irgendwelche Variablen überschreibe ?

    Viele Grüße
    Gode

     
  • ggauf - 2012-10-23

    Hallo,

    wollte noch mal fragen, ob jemand zu meinem Vorgehen etwas sagen kann...

    Noch mal kurz zusammengefasst:
    - um das Bootprogramm nicht aufzublähen werden die Variablen nicht als retain deklariert
    - das Array wird wie unten im Codebeispiel bei Änderungen am Stück (Zeiger auf das erste Element + ANzahl Elemente) weggeschrieben und nach reset genauso auch wieder eingelesen (sehr wenig Quellcode nötig)

    • Spricht etwas dagegen ?

    Viele Grüße
    Gode

     
  • Anonymous - 2012-11-14

    Originally created by: Eckhard

    Hallo ggauf
    Das Phänomen mit dem größeren Code ist mir auch schon aufgefallen. In meinem Programm benutze ich viele ARRAYs (mit je 365 Worten) und habe die Arrays als RETAIN PERSISTENT deklariert. Dadurch wurde der Code zum Laden in den Controller 330 KByte groß. Angeregt durch Deine Beobachtung habe ich etwas herum experimentiert und herausgefunden das PERSISTENT für die Größenänderung verantwortlich ist. So habe ich mein Programm modifiziert und die Array nur noch RETAIN deklariert. Damit überleben sie einen Stromausfall. Und siehe da, der Code ist nur noch 190 KByte groß und läßt sich deutlich schneller runterladen.
    Damit ich die Inhalte der Arrays bei Programmänderungen nicht verliere schreibe ich sie vor dem Einloggen einer neuen Version mit der Bibliothek SysLibFile.lib in das Dateisystem. Sehr ähnlich Deinem Codebeispiel. Vor der Lebensdauer des FLASH-Bereiches habe ich keine Angst. Im Handbuch steht was von 1 Million Schreibzyklen. Angst habe ich eher davor das ich irgendwann mal vergesse auf den extra programmierten Knopf in der Visu zu drücken, den ich mir zu dem Zweck dort hingelegt habe (ich habe ihn "Array_jetzt_schreiben" genannt).
    Das Zurücklesen der Arrays erfolgt automatisch. Dazu habe ich eine Hilfsvariable "Download_erkannt" als RETAIN deklariert. Nach dem Wiedereinlesen der Arrays wird sie auf TRUE gesetzt. Ein Reset oder Stromausfall ändert das TRUE nicht, nur ein Programmupdate bewirkt das die Variable wieder auf FALSE steht.
    Ganz aufgegeben habe ich die PERSISTENT Variablen nicht. Ein paar Betriebsstundenzähler bewahre ich da noch auf. Aber durch den Wegfall der großen Arrays ist der Code deutlich schlanker geworden und ich habe 140 KByte für hübsche Bildchen in der Visu gewonnen.

    Um Deine letzte Frage zu beantworten: Nein, es spricht nichts dagegen. Meine geflashten Arrays sind auch genau 730 Bytes groß. Ich könnte sie sogar mit einem FTP Client sichern. (Hmm, vielleicht gar keine so schlechte Idee.)

    Viel Spaß beim Programmieren, Eckhard

     

Log in to post a comment.