Exception Handling

Bei der Abarbeitung des aus MATLAB® oder Simulink® autogenerierten C++ Codes in TwinCAT, kann es zur Laufzeit zu Floating Point Exceptions kommen, wenn zum Beispiel ein bei der Programmierung unerwarteter Wert in eine Funktion übergeben wird. Die Behandlung von solchen Exceptions wird im Folgenden beschrieben.

Was ist eine Floating Point Exception?

Eine Floating Point Exception tritt dann auf, wenn eine arithmetisch nicht exakt ausführbare Rechenoperation in der Floating Point Unit der CPU beauftragt wird. IEEE 754 definiert diese Fälle: inexact, underflow, overflow, divide-by-zero, invalid-operation. Tritt einer dieser Fälle auf, wird ein Status Flag gesetzt, welches auf die nicht exakt ausführbare Rechenoperation hinweist. Es wird des Weiteren definiert, dass jede Rechenoperation ein Ergebnis liefern muss, und zwar ein solches, das in der Mehrzahl der Fälle dazu führt, dass man die Exception ignorieren kann.

Beispielsweise ergibt eine Division durch Null +inf oder -inf. Wird im weiteren Code ein Wert durch inf geteilt, ergibt dies Null, sodass keine Folgeprobleme zu erwarten sind. Wird inf allerdings multipliziert, oder werden andere Rechenoperationen mit inf ausgeführt, sind dies invalid operations, deren Ergebnis als Not-a-Number (NaN) dargestellt wird.

Wie reagiert die TwinCAT-Laufzeit bei Exceptions?

Exception Handling 1:

TwinCAT C++ Debugger nicht aktiv

Folgende Ausführungen gelten nur für den Fall, dass der C++ Debugger nicht auf dem TwinCAT-Laufzeitsystem aktiviert ist. Bei aktiviertem C++ Debugger werden Exceptions vom Debugger abgefangen und können behandelt werden, siehe Debugging.

Standard Verhalten

Default-Einstellung in TwinCAT ist, dass bei divide-by-zero und invalid-operation die Ausführung des Programms gestoppt wird und TwinCAT eine Fehlermeldung ausgibt.

Task-Einstellung: Floating Point Exceptions

Diese Default-Einstellung lässt sich auf Ebene einer jeden TwinCAT Task verändern. Wird die Checkbox „Floating Point Exception“ deaktiviert, führt eine Exception nicht zu einem TwinCAT-Stopp und es wird keine Fehlermeldung ausgegeben. Diese Einstellung ist dann gültig für alle Objekte, die durch eben diese Task aufgerufen werden. In der Folge ist in der Applikation darauf zu achten, dass NaN und inf-Werte entsprechend im Programmcode behandelt werden.

Prüfen auf NaN und Inf

Wird beispielsweise ein NaN per Mapping an ein TwinCAT-Objekt weitergegeben, welches Floating Point Exceptions aktiviert hat, führt eine Rechenoperation mit NaN natürlich in diesem Objekt zu einer Exception und in der Folge zu einem TwinCAT-Stopp. Daher muss direkt nach dem Mapping auf NaN bzw. inf geprüft werden. In der SPS stehen dazu entsprechende Funktionen in der Tc2_Utilities Bibliothek zur Verfügung, bspw. LrealIsNaN.

Try-Catch-Anweisung

Eine weitere Möglichkeit zum Umgang mit Exceptions ist die Einbettung in eine Try-Catch-Anweisung. In der SPS stehen dazu die Anweisungen __TRY, __CATCH, __FINALLY, __ENDTRY zur Verfügung. Sind auf der aufrufenden Task Floating Point Exceptions aktiviert und tritt innerhalb des Try-Catch eine Exception auf, so wird diese im Catch-Zweig gefangen und kann behandelt werden. Entsprechend werden bei dieser Vorgehensweise keine Variablen auf inf oder NaN gesetzt. Wichtig ist aber zu bemerken, dass der Code in Try-Zweig nur bis zu der Stelle der Exception durchlaufen wird und dann ein Sprung zum Catch-Zweig erfolgt. Im Applikationscode ist entsprechend zu beachten, dass interne Zustände im Try-Zweig ggf. nicht konsistent sind.

Dump Files

Ab TwinCAT 3.1.4024.22 (XAR) können zur Laufzeit Dump Files im Falle von Exceptions im TcCOM-Objekt erstellt werden.

Präzisierung des Verhaltens bei Exceptions auf Objekt-Ebene

Neben der Möglichkeit, das Verhalten bei Exceptions auf Task-Ebene zu beeinflussen, kann auch das Verhalten auf Ebene eines TwinCAT-Objekts, d. h. des generierten TcCOM oder des generierten SPS-Funktionsbausteins, präzisiert werden.

Auf Objektebene ist mit dem TwinCAT Target for Simulink® eine Fülle an Möglichkeiten realisierbar. Im Grunde basieren aber alle im Folgenden dargelegten Optionen auf oben genannten Prinzipien.

Optionaler ExecutionInfo Output

Werden auf Objektebene Exceptions behandelt, ist es sinnvoll, entsprechende Informationen über aufgetretene Exceptions am Objektausgang zugänglich zu machen. So kann an diesem Ausgang abgefragt werden, ob eine Exception aufgetreten ist, was für eine Exception es war, ob ein Dump-File geschrieben wurde etc.

Für das TcCOM-Objekt können Sie einen zusätzlichen Ausgang „ExecutionInfo“ aktivieren:

exportConfig.ClassExportCfg{nModuleCount}.TcCom.ExecutionInfoOutput = true;
Exception Handling 2:

ExecutionInfo Output für PLC-FB

Aktuell ist die ExecutionInfo nur für das TcCOM-Objekt verfügbar. Wenn Sie den Code aus der PLC heraus aufrufen möchte, nutzen Sie dazu den TcCOM-Wrapper-FB.

Der Ausgang ExecutionInfo ist eine Struktur mit folgenden Einträgen:

ExcecutionInfo Struktur

Eintrag

Datentyp

Bedeutung

CycleCount

ULINT

Aktueller Cycle Count (unabhängig von einer Exception)

ExceptionCount

ULINT

Anzahl der bislang aufgetretenen Exceptions

ActException

TcMgSdk.ExceptionInfo

Näherer Erläuterung zur aktuellen Exception (nur erste Exception im aktuellen Zyklus)

TcMgSdk.ExceptionInfo

ExceptionCode

DINT

Code der Exception, vgl. Microsoft Hilfe

TmxName

STRING(127)

Name des tmx-Treibers, der die Exception geworfen hat.

TmxVersion

ARRAY[0..3] OF UDINT

Version des tmx-Treibers, der die Exception geworfen hat.

InstructionAddr

UDINT

Relative Adresse im Speicher; Ort an dem die Exception aufgetreten ist.

ReturnAddr

ARRAY[0..3] OF UDINT

Rücksprungadressen

DumpCreated

BOOLEAN

TRUE, wenn ein Dump File zur Exception erstellt wurde.

Mit der InstructionAddr ist es möglich zu beurteilen, ob die Exception mit dem angegebenen ExceptionCode immer an der gleichen Stelle im Quellcode auftritt. Ist die InstructionAddr für wiederholende Exceptions gleich, tritt diese immer an der gleichen Stelle im Code auf. Über die ReturnAddr sehen Sie, woher die Aufrufe gekommen sind, die zur Stelle der Exception geführt haben. Sie können also beurteilen, ob der Aufruf, der zur Exception führt, immer denselben Aufrufweg nimmt. Wird der Code von außerhalb des Tmx-Treibers aufgerufen, steht in den ReturnAddr eine 0.

Definition des Objekt-Verhaltens bei auftretenden Exceptions

Das Verhalten eines TcCOM-Objekts bei auftretenden Exceptions können Sie für die Initialisierungsphase und für die UpdatePhase getrennt unter den Properties der Klasse TwinCAT.ModuleGenerator.ProjectExportConfig einstellen:

exportConfig.ClassExportCfg{ nModuleCount }.TcCom.UpdateExceptionHandling = 'CallerExceptions';
exportConfig.ClassExportCfg{ nModuleCount }.TcCom.InitExceptionHandling = 'CallerExceptions';

Optionen sind: CallerExceptions, ThrowExceptions, SuppressExceptions, LogExceptions, LogAndHold, LogAndCatch, LogAndDump, LogHoldAndDump, LogCatchAndDump.

Sollten Sie mit einem bereits kompilierten TcCOM in TwinCAT arbeiten, können Sie auch nachträglich die Einstellungen auf der Objekt-Instanz verändern. Nutzen Sie dazu den Reiter Parameter (Init) und wählen Sie Show hidden Parameters.

Exception Handling 3:

Die Einstellungen für den PLC-FB FB_<ModelName> in der SPS Bibliothek sind unabhängig von den Einstellungen zum TcCOM-Objekt.

exportConfig.ClassExportCfg{nModuleCount}.PlcFb.UpdateExceptionHandling

exportConfig.ClassExportCfg{nModuleCount}.PlcFb.InitExceptionHandling

Beachten Sie, dass der andere SPS-Funktionsbaustein (FB_<ModelName>_TcCOM) ein Wrapper für ein TcCOM-Objekt ist und somit bei dessen Verwendung die Exception Einstellungen aus dem Bereich TcCOM gültig sind.

Es stehen insgesamt 9 unterschiedliche Einstellungen zur Verfügung.

Es stehen insgesamt 9 unterschiedliche Einstellungen zur Verfügung.

Ausführungsstopp eines TwinCAT-Objekts behandeln

LogAndHold und LogHoldAndDump

Im Falle einer Exception wird die Ausführung des Codes im betreffenden TcCOM-Objekt durch Setzen des Parameters Execute auf FALSE gestoppt. Der Paramater kann aus dem XAE und per ADS gelesen bzw. geschrieben werden.

Im XAE können Sie auf dem TcCOM-Objekt unter Parameter (Init) dessen Online-Werte anzeigen lassen und verändern.

Exception Handling 4:
Exception Handling 5:

Im Blockdiagramm wird Ihnen der Parameter unter Module parameters angeboten.

Exception Handling 6:

Wenn Sie die Maus über den Namen Execute im Änderungsdialog führen, wird Ihnen, wie bei allen anderen Parametern auch, die ADS-Adresse des Parameters gezeigt. Damit können Sie den Parameter auch per ADS setzen.

Exception Handling 7:

Durch Rechtsklick auf den Namen Execute können Sie die ADS-Symbolinformationen auch in der Zwischenablage speichern. Auch dies gilt für alle anderen Parameter.

Exception Handling 8:

LogAndCatch und LogCatchAndDump

Zusätzlich zum Parameter Execute wechselt, im Fall von LogAndCatch und LogCatchAndDump, auch der Online-Parameter Initialized nach FALSE. Das Modul muss neu initialisiert werden, bevor das Modul wieder eine Berechnung durchführen kann. Dies ist notwendig, da interne Zustände nicht mehr konsistent sein können. Eine Reinitialisierung kann nur erfolgen, indem das TcCOM-Objekt in den Zustand „Init“ zurückgefahren und erneut nach OP gefahren wird.

Zur Laufzeit können nur TcCOM-Objekte runtergefahren werden, welche keine Mappings haben, sonst würden aktive Mappings das Herunterfahren blockieren. Eine neue Initialisierung ist nur möglich, indem die gesamte TwinCAT-Laufzeit neu gestartet wird.

Eine flexiblere Alternative ist die Nutzung des TcCOM-Wrapper-FB in der SPS. Dieser kann genutzt werden, um das TcCOM aus des SPS aufzurufen und benötigt keine Mappings um auf dessen Eingänge und Ausgänge zuzugreifen. Entsprechend kann das TcCOM-Objekt auch während der Laufzeit neu initialisiert werden.

PROGRAM MAIN
VAR
   stInitTemp : ST_FB_SimpleTempCtrl_TcCOM_InitStruct := (nOid := 16#01010010);
   fbTempCtr  : FB_SimpleTempCtrl_TcCOM_InitStruct(stInitTemp);
   Inputs     : ST_ExtU_SimpleTempCtrl_T;
   Outputs    : ST_ExtY_SimpleTempCtrl_T;
   ExecutionOut : ST_ExecutionInfo2;
END_VAR
// check if TcCOM is in OP mode and all set 
IF fbTempCtr.bExecute = TRUE AND fbTempCtr.bInitialized = TRUE AND fbTempCtr.nObjectState = TCOM_STATE.TCOM_STATE_OP THEN
    
    // call the module
    fbTempCtr(stSimpleTempCtrl_U := Inputs, stSimpleTempCtrl_Y => Outputs, stExecutionInfo => ExecutionOut);
    
    // handle exceptions
    IF ExecutionOut.ActException.ExceptionCode <> 0 THEN
       // collect exception information
       (* ...... *)
       
       // reinit TcCOM
       fbTempCtr.Reinit(stReInit := stInitTemp); 
    END_IF
    
 END_IF

Beachten Sie, dass die ReInit-Methode synchron ausgeführt wird, d. h. je nach Zykluszeit und benötigter Zeit zum neu initialisieren, kann es zu Zyklusüberschreitungen kommen.

Dump-Files

Das Schreiben des Dump-Files kann einige Zyklen in Anspruch nehmen. Am besten sollte für das betreffende TcCOM-Objekt oder den PLC-FB eine separate Task verwendet werden, die keine wichtigen Tasks blockiert.

Dump-Files werden nur mit einer TwinCAT XAR Version >= 3.1.4024.22 geschrieben, ansonsten erhält man eine entsprechende Warnung.

Im Fall von LogAndDump wird die Ausführung des Codes nach Auftreten einer Exception zyklisch fortgeführt, es können entsprechend zyklisch Exceptions auftreten, die zu andauernden Zykluszeitüberschreitungen führen könnten. Daher wird der Online-Wert des Parameters UpdateExceptionHandling nach dem Schreiben des Dump-Files auf LogExceptions gesetzt, d. h. das Schreiben von Dump-Files wird deaktiviert, kann anschließend aber z. B. per ADS oder Eingriff über das XAE unter Parameter (Init) wieder eingeschaltet werden.

Das erstellte Dump-File wird auf dem Laufzeit-PC im Boot-Ordner abgelegt und kann von dort zur Analyse auf einen anderen PC kopiert werden. Bei Verwendung einer TwinCAT Version kleiner 3.1.4024.x können Sie die Dump-Files mit WinDbg öffnen und Ihre Analyse starten.