Exception handling
When processing the C++ code autogenerated from MATLAB® or Simulink® in TwinCAT, floating point exceptions can occur at runtime, for example if an unexpected value is passed into a function during programming. The handling of such exceptions is described below.
What is a floating point exception?
A floating point exception occurs when an arithmetically not exactly executable operation is instructed in the floating point unit of the CPU. IEEE 754 defines these cases: inexact, underflow, overflow, divide-by-zero, invalid-operation. If one of these cases occurs, a status flag is set, which indicates that the arithmetic operation cannot be executed exactly. It is further defined that each arithmetic operation must return a result – one that in the majority of cases leads to the possibility of ignoring the exception.
For example, a division by zero results in +inf or -inf. If a value is divided by inf in the further code, this results in zero, so that no consequential problems are to be expected. However, if inf is multiplied or other arithmetic operations are performed with inf, these are invalid operations, whose result is represented as a Not-a-Number (NaN).
How does the TwinCAT Runtime react in case of exceptions?
TwinCAT C++ Debugger not active The following explanations only apply if the C++ debugger is not activated on the TwinCAT runtime system. When the C++ debugger is enabled, exceptions are caught by the debugger and can be handled, see Debugging. |
Standard behavior
Default setting in TwinCAT is that at divide-by-zero and invalid-operation the execution of the program is stopped and TwinCAT issues an error message.
Task setting: Floating Point Exceptions
This default setting can be changed on the level of each TwinCAT task. If the checkbox "Floating Point Exception" is unchecked, an exception does not lead to a TwinCAT stop and no error message is issued. This setting is then valid for all objects that are called by this task. As a consequence, care must be taken in the application that NaN and inf values are handled accordingly in the program code.
Check for NaN and Inf
If, for example, a NaN is passed on via mapping to a TwinCAT object that has activated floating point exceptions, an arithmetic operation with NaN naturally leads to an exception in this object and subsequently to a TwinCAT stop. Therefore, NaN or inf must be checked directly after mapping. In the PLC, corresponding functions are available in the Tc2_Utilities library, e.g. LrealIsNaN.
Try-Catch statement
Another way to handle exceptions is to embed them in a try-catch statement. In the PLC the instructions __TRY, __CATCH, __FINALLY, __ENDTRY are available for this purpose. If floating point exceptions are enabled on the calling task and an exception occurs within the Try-Catch, it is caught in the Catch branch and can be handled. Accordingly, no variables are set to inf or NaN in this approach. However, it is also important to note that the code in the Try branch is run through only up to the point of the exception and then a jump is made to the Catch branch. In the application code, it should be noted that internal states in the Try branch may not be consistent.
Dump Files
From TwinCAT 3.1.4024.22 (XAR), dump files can be created at runtime in case of exceptions in the TcCOM object.
Specification of the behavior in case of exceptions on object level
In addition to the possibility of influencing the behavior in the event of exceptions at task level, the behavior can also be specified at the level of a TwinCAT object, i.e. the generated TcCOM or the generated PLC function block.
On the object level, a wealth of possibilities can be realized with the TwinCAT Target for Simulink®. Basically, however, all the options presented below are based on the above principles.
Optional ExecutionInfo Output
If exceptions are handled at object level, it makes sense to make corresponding information about occurred exceptions accessible at the object output. This output can be used to query whether an exception has occurred, what kind of exception it was, whether a dump file has been written, etc.
For the TcCOM object you can activate an additional output "ExecutionInfo":
exportConfig.ClassExportCfg{nModuleCount}.TcCom.ExecutionInfoOutput = true;
ExecutionInfo Output for PLC-FB Currently the ExecutionInfo is only available for the TcCOM object. If you want to call the code from the PLC, use the TcCOM-Wrapper-FB. |
The ExecutionInfo output is a structure with the following entries:
ExcecutionInfo structure
Entry | Data type | Meaning |
---|---|---|
CycleCount | ULINT | Current cycle count (independent of an exception) |
ExceptionCount | ULINT | Number of exceptions that have occurred so far |
ActException | TcMgSdk.ExceptionInfo | More detailed explanation of the current exception (only first exception in the current cycle) |
TcMgSdk.ExceptionInfo
ExceptionCode | DINT | Code of the exception, cf. Microsoft Help |
---|---|---|
TmxName | STRING(127) | Name of the tmx driver that threw the exception. |
TmxVersion | ARRAY[0..3] OF UDINT | Version of the tmx driver that threw the exception. |
InstructionAddr | UDINT | Relative address in memory; location where the exception occurred. |
ReturnAddr | ARRAY[0..3] OF UDINT | Return addresses |
DumpCreated | BOOLEAN | TRUE if a dump file was created for the exception. |
With the InstructionAddr it is possible to judge if the exception with the given ExceptionCode always occurs at the same place in the source code. If the InstructionAddr is the same for repeating exceptions, it always occurs at the same point in the code. Via ReturnAddr you can see where the calls came from that led to the location of the exception. So you can judge if the call that leads to the exception always takes the same call path. If the code is called from outside the Tmx driver, there is a 0 in the ReturnAddr.
Definition of the object behavior in case of occurring exceptions
The behavior of a TcCOM object in case of exceptions can be set separately for the initialization phase and for the update phase under the properties of the class TwinCAT.ModuleGenerator.ProjectExportConfig:
exportConfig.ClassExportCfg{ nModuleCount }.TcCom.UpdateExceptionHandling = 'CallerExceptions';
exportConfig.ClassExportCfg{ nModuleCount }.TcCom.InitExceptionHandling = 'CallerExceptions';
Options are: CallerExceptions, ThrowExceptions, SuppressExceptions, LogExceptions, LogAndHold, LogAndCatch, LogAndDump, LogHoldAndDump, LogCatchAndDump
.
If you are working with an already compiled TcCOM in TwinCAT, you can also change the settings on the object instance afterwards. To do this, use the tab Parameters (Init) and select Show hidden Parameters.
The settings for the PLC-FB FB_<ModelName> in the PLC library are independent of the settings for the TcCOM object.
exportConfig.ClassExportCfg{nModuleCount}.
PlcFb.UpdateExceptionHandling
exportConfig.ClassExportCfg{nModuleCount}.
PlcFb.InitExceptionHandling
Note that the other PLC function block (FB_<ModelName>_TcCOM) is a wrapper for a TcCOM object and therefore the exception settings from the TcCOM section are valid when it is used.
A total of 9 different settings are available.
A total of 9 different settings are available.
- CallerExceptions (default): Exceptions are thrown as configured at the calling task.
- ThrowExceptions: Exceptions in the TwinCAT object are thrown in any case, regardless of how the task is configured.
- An exception causes a TwinCAT error message and a TwinCAT stop
- SuppressExceptions: Exceptions are not thrown, regardless of how the task is configured.
- An exception does not cause a TwinCAT stop.
- Outputs or internal states can be NaN or inf.
- LogExceptions: Exceptions are thrown, but do not lead to a TwinCAT stop.
- An exception does not cause a TwinCAT stop.
- Outputs or internal states can be NaN or inf.
- The ExecutionInfo output is filled with information about an exception in the current cycle. If several exceptions occur in one cycle, only the first exception is displayed at the output. When the TwinCAT object is called again, the information is reset.
- LogAndHold: Exceptions are thrown. The execution of the TwinCAT object is stopped.
- An exception does not cause a TwinCAT stop.
- Outputs or internal states can be NaN or inf.
- The ExecutionInfo output is filled with information about an exception in the current cycle. If several exceptions occur in one cycle, only the first exception is displayed at the output. When the TwinCAT object is called again, the information is reset.
- The execution of the TwinCAT object is stopped after an exception occurs. TwinCAT itself remains in run mode. Restart execution: .
- LogAndCatch: Exceptions are caught with try-catch in the TwinCAT object. The execution of the TwinCAT object is stopped.
- An exception does not cause a TwinCAT stop.
- Outputs or internal states cannot contain NaN or inf.
- The ExecutionInfo output is filled with information about an exception in the current cycle.
- The execution of the code ends at the point of the exception. From there, the program jumps to the catch junction, i.e. internal states can be inconsistent.
- The execution of the TwinCAT object is stopped after an exception occurs. TwinCAT itself remains in run mode. Restart execution: .
- LogAndDump, LogHoldAndDump and LogCatchAndDump
- Behavior like LogExceptions
- Additionally a dump file is stored on the runtime system in the TwinCAT folder Boot. For more on dump files, see here.
Handle execution stop of a TwinCAT object
LogAndHold and LogHoldAndDump
In the event of an exception, execution of the code in the TcCOM object concerned is stopped by setting the Execute parameter to FALSE. The parameter can be read or written from the XAE and via ADS.
In the XAE, you can display and change the online values of the TcCOM object under Parameters (Init).
In the block diagram the parameter is offered to you under Module parameters.
If you move the mouse over the Execute name in the change dialog, you will be shown the ADS address of the parameter, as with all other parameters. This allows you to set the parameter also by ADS.
By right-clicking on the name Execute you can also save the ADS symbol information to the clipboard. This also applies to all other parameters.
LogAndCatch and LogCatchAndDump
In addition to the parameter Execute, the online parameter Initialized also changes to FALSE in the case of LogAndCatch and LogCatchAndDump. The module must be reinitialized before the module can perform a calculation again. This is necessary because internal states can no longer be consistent. Reinitialization can only be performed by returning the TcCOM object to the "Init" state and moving it to OP again.
At runtime, only TcCOM objects that have no mappings can be shut down, otherwise active mappings would block the shutdown. A new initialization is only possible by restarting the entire TwinCAT Runtime.
A more flexible alternative is to use the TcCOM-Wrapper-FB in the PLC. This can be used to call the TcCOM from the PLC and does not require any mappings to access its inputs and outputs. Accordingly, the TcCOM object can also be reinitialized during runtime.
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
Note that the ReInit method is executed synchronously, i.e. depending on the cycle time and the time required to reinitialize, cycle overruns may occur.
Dump files
Writing the dump file may take a few cycles. It is best to use a separate task for the TcCOM object or the PLC-FB in question that does not block any important tasks.
Dump files are only written with a TwinCAT XAR version >= 3.1.4024.22, otherwise you get a corresponding warning.
In the case of LogAndDump the execution of the code is continued cyclically after the occurrence of an exception, accordingly exceptions can occur cyclically which could lead to persistent cycle timeouts. Therefore, the online value of the parameter UpdateExceptionHandling is set to LogExceptions after the dump file has been written, i.e. the writing of dump files is deactivated, but can subsequently be switched on again, e.g. by ADS or intervention via the XAE under parameter (Init).
The created dump file is stored on the runtime PC in the boot folder and can be copied from there to another PC for analysis. If you use a TwinCAT version lower than 3.1.4024.x you can open the dump files with WinDbg and start your analysis.