Hi zusammen
Viele hier nerven sich ja bestimmt auch über die unmotivierten Reinits von TIA wenn man das Programm in die Steuerung läd.
ich dachte mir, vielleicht besteht ja interesse gemeinsam an einem guten Baustein zu schreiben der uns einen ArbeitsspeicherDB in einen LadespeicherDB auf der Memorycard sichert und automatisch wiederherstellt.
Ich hab da mal was angefangen das grundsätzlich auch schon funktioniert. Aber er hat noch keine richtige Fehlerbehandlung und bestimmt einiges an Verbesserungspotential. Besteht interesse darin diesen Baustein offen weiterzuentwickeln und zu verbessern. Er soll aber weiterhin frei zugänglich bleiben (ggf erlauben das ja nicht alle Arbeitgeber mit Werksentwicklungslizenzen)
Hier was ich schon habe:
Ich hab ihn schon auf CPUs mit diversen 1.8er Firmwares und 2.0er Firmware ausprobiert.
Der DB der Gesichert werden soll muss an erster Speicherstelle ein Bool haben das nicht verwendet wird. Dieses wird durch den Baustein auf FALSE überprüft. Wenn es FALSE (z.B. durch einen Reinit von TIA) ist, wird falls vorhanden der Inhalt des LadespeicherDBs zurückgelesen.
mfG René
Viele hier nerven sich ja bestimmt auch über die unmotivierten Reinits von TIA wenn man das Programm in die Steuerung läd.
ich dachte mir, vielleicht besteht ja interesse gemeinsam an einem guten Baustein zu schreiben der uns einen ArbeitsspeicherDB in einen LadespeicherDB auf der Memorycard sichert und automatisch wiederherstellt.
Ich hab da mal was angefangen das grundsätzlich auch schon funktioniert. Aber er hat noch keine richtige Fehlerbehandlung und bestimmt einiges an Verbesserungspotential. Besteht interesse darin diesen Baustein offen weiterzuentwickeln und zu verbessern. Er soll aber weiterhin frei zugänglich bleiben (ggf erlauben das ja nicht alle Arbeitgeber mit Werksentwicklungslizenzen)
Hier was ich schon habe:
Code:
FUNCTION_BLOCK "SaveDatablock"
{ S7_Optimized_Access := 'FALSE' }
AUTHOR : VoR
VERSION : 0.1
//Baustein soll einen kompletten DB im Ladespeicher sichern. Um TIA Reinitialisationen zu begrenzen.
//Der zu sichernde DB darf nicht optimiert sein.
//Die Sicherung muss durch SaveDB getriggert. SaveDB wird vom Baustein zurückgesetzt.
VAR_INPUT
DB_TO_SAVE : Any; // Welcher DB soll gesichert werden
DB_NR_Loadmem { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : UInt := 60000; // DBNR_Ab 60000 im Ladespeicher
END_VAR
VAR_IN_OUT
SaveDB : Bool;
RecoverDB : Bool;
END_VAR
VAR
DeleteDB : Bool;
CreateDB : Bool;
DelBusy : Bool;
Attrib : Byte;
Attr_DB_Lenght : UDInt;
Create_DB_Busy : Bool;
Create_DB_Num : UInt;
Busy_Write : Bool;
Busy_Read : Bool;
Status_BLKMOV_Save_1 : Int;
Status_BLKMOV_Recover_1 : Int;
speicherbereich : Word;
testpointer : "ANY_POINTER";
trueval { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Bool := true;
FN_Busy {OriginalPartName := 'F_TRIG_1500'; LibVersion := '1.0'} : F_TRIG;
END_VAR
VAR_TEMP
pSourceDB : Any;
ptSourceDB AT pSourceDB : "ANY_POINTER";
pSaveDB : Any;
ptSaveDB AT pSaveDB : "ANY_POINTER";
Status : Int;
Status_attr : Int;
Status_crea : Int;
Status_Attr_DB : Int;
Status_BLKMOV_Save : Int;
Status_BLKMOV_Recover : Int;
DB_Lenght : UDInt;
Attrib_RCV : UDInt;
Anzahl_Werte : Word;
InitBool : Bool;
DB_save_Length : UDInt;
DB_save_Attrib : Byte;
Attr_status : Int;
Attr_status_st : Struct
Ladespeicher : Bool;
writeprotect : Bool;
remanent : Bool;
ladeundarbeitspeicher : Bool;
END_STRUCT;
END_VAR
BEGIN
#pSourceDB := #DB_TO_SAVE;
#speicherbereich := DWORD_TO_WORD(ROR(IN := #ptSourceDB.Startadresse, N := 24));
(*Pointer aufbereiten für kompletten DB*)
#ptSourceDB.SyntaxID := B#16#10;
#ptSourceDB.Bereichstyp := 2;
#Status_Attr_DB := ATTR_DB(REQ := True,
DB_NUMBER := #ptSourceDB.DB_Nr,
DB_LENGTH => #DB_Lenght,
ATTRIB => #Attrib_RCV);
#Anzahl_Werte := UDINT_TO_WORD(#DB_Lenght);
#ptSourceDB.Anzahl_Werte := UDINT_TO_UINT(#Anzahl_Werte);
#ptSourceDB.Startadresse := DW#16#84000000;
#ptSaveDB := #ptSourceDB; //Source/Save Pointer abgleichen
#ptSaveDB.DB_Nr := #DB_NR_Loadmem;
#Attr_status := ATTR_DB(REQ:=True, DB_NUMBER:=#ptSaveDB.DB_Nr, DB_LENGTH=>#DB_save_Length, ATTRIB=>#DB_save_Attrib);
#Attr_status_st.Ladespeicher := #DB_save_Attrib.%X0; // Nachsehen ob DB zur Sicherung existiert.
#Attr_status_st.writeprotect := #DB_save_Attrib.%X1;
#Attr_status_st.remanent := #DB_save_Attrib.%X2;
#Attr_status_st.ladeundarbeitspeicher := #DB_save_Attrib.%X3;
// Vielleicht will man den DB mal aus dem Programm gesteuert löschen.
#Status := DELETE_DB(REQ := #DeleteDB, DB_NUMBER := LINT_TO_UINT(60000), BUSY => #DelBusy);
#DeleteDB := false;
(* Wenn DB nicht im Ladespeicher und auch keine DB Generierung im Gang
Dann Einen DB auf der Karte erstellen um ihn als Sicherung zu nutzen *)
IF NOT #Attr_status_st.Ladespeicher AND NOT #Create_DB_Busy THEN
#CreateDB := true;
ELSIF #Create_DB_Busy THEN // Generierung im Gang Init Bool setzen da dieser DB nicht zurückgesichert werden soll
#CreateDB := false;
POKE_BOOL(area := 16#84,
dbNumber := #ptSourceDB.DB_Nr,
byteOffset := 0,
bitOffset := 0,
value := TRUE);
END_IF;
// Erstes Bit im zu sichernden DB überprüfen, wenn 0 dann soll DB restored werden.
#InitBool := PEEK_BOOL(area := 16#84, dbNumber := #ptSourceDB.DB_Nr, byteOffset := 0, bitOffset := 0);
#Status_crea := CREATE_DB(REQ := #CreateDB,
LOW_LIMIT := #ptSaveDB.DB_Nr,
UP_LIMIT := #ptSaveDB.DB_Nr,
COUNT := 65534, // DB in maximaler Grösse. SD Karten kosten nix und es muss nicht neu generiert werden bei Grössenänderung
ATTRIB := b#8#1,
SRCBLK:=#pSourceDB, BUSY => #Create_DB_Busy,
DB_NUM => #Create_DB_Num);
#testpointer := #ptSaveDB; // Nur für Testzwecke. Kann am Schluss gelöscht werden.
#Status_BLKMOV_Save := WRIT_DBL(REQ := #SaveDB AND NOT #Create_DB_Busy, // DB inhalt sichern
SRCBLK := #pSourceDB,
BUSY => #Busy_Write,
DSTBLK => #pSaveDB);
IF #Status_BLKMOV_Save <> w#16#7000 THEN
#Status_BLKMOV_Save_1 := #Status_BLKMOV_Save;
END_IF;
IF NOT (#Busy_Write OR #Create_DB_Busy) THEN
#SaveDB := FALSE;
END_IF;
// DB wurde initialisiert Daten aus Sicherungsdb wiederherstellen.
IF NOT #InitBool THEN
#RecoverDB := true;
END_IF;
#Status_BLKMOV_Recover := READ_DBL(REQ := #RecoverDB AND NOT #Create_DB_Busy,
SRCBLK := #pSaveDB,
BUSY => #Busy_Read,
DSTBLK =>#pSourceDB);
IF #Status_BLKMOV_Recover <> w#16#7000 THEN
#Status_BLKMOV_Recover_1 := #Status_BLKMOV_Recover;
END_IF;
#FN_Busy(CLK:=#Busy_Read);
IF #FN_Busy.Q THEN
#RecoverDB := FALSE;
POKE_BOOL(area := 16#84,
dbNumber := #ptSourceDB.DB_Nr,
byteOffset := 0,
bitOffset := 0,
value:=TRUE);
END_IF;
END_FUNCTION_BLOCK
Der DB der Gesichert werden soll muss an erster Speicherstelle ein Bool haben das nicht verwendet wird. Dieses wird durch den Baustein auf FALSE überprüft. Wenn es FALSE (z.B. durch einen Reinit von TIA) ist, wird falls vorhanden der Inhalt des LadespeicherDBs zurückgelesen.
mfG René