ERROR (ENUM)¶
TYPE ERROR :
Every function block in this document has a boolean output xError
to indicate that there is an error condition reached.
In this case a more detailed information will be signaled with the value of the output iErrorID
of the functionblock BehaviourModel. The iErrorID
represents an
Integer value, indicating the reason for the error.
It is neccecary to map the integer value of iErrorID
to an domain specific enum data type ERROR
.
Error Domains and Error Codes (ERROR
(Enum) and eErrorID
(output)) and their organisation in different domains:
In many cases this integer value of eErrorID
is used as input for an additional FB which converts the number to a related localized string in an applicable language.
The set of values for a specific eErrorID
is are application dependent.
In case several libraries are combined (several domains), there can be an overlap in the numbers of the eErrorID
,
meaning that the same number identify a different error condition in a different domain.
For this reason an value range definition for eErrorID
per library must be done.
The error handling of a function block should be designed in a way that only error codes are returned, which are documented in the affected library. It is very convenient but not recommended simply to return untreated error codes from sub libraries. This would result in a bad user experience. It is recommended to map foreign error codes to the error range of the affected library.
In the following example we take a closer look to the relationship between two libraries. Each with a specific domain of error codes.
The first library may be called the “Memory Block Manager library” and is build in the namespace MBM
.
The second library my be called the “Function Block Factory” and is build in the namespace FBF
.
Each library defines its own ERROR
Enum data type.
The ERROR Enum of the library “Memory Block Manager” (MBM)
1{attribute 'qualified_only'}
2TYPE ERROR : (
3 NO_ERROR := 0, // The defined operation was executed successfully
4 NO_MEMORY := 10 // The memory pool has no further capacity
5 HANDLE_INVALID := 20, // The object was not created properly or has been already released
6 WRONG_ALIGNMENT := 30, // The structure description aligns not properly to the block specification
7 (*...*)
8END_TYPE
The ERROR Enum of the library “Function Block Factory” (FBF)
1{attribute 'qualified_only'}
2TYPE ERROR : (
3 NO_ERROR := 0, // The defined operation was executed successfully
4 TIMEOUT := 1, // The specified operation time was exceeded
5 INVALID_PARAM := 10, // One or more function parameters have no valid value
6 NO_MEMORY := 20, // The extension of memory pool is not possible
7 (*...*)
8END_TYPE
Two libraries are isolated with a namespace (in this example
FBF
andMBM
).Each
ERROR
Enum declaration should respect two predefined error codes.NO_ERROR
⇒ 0 (Zero)TIME_OUT
⇒ 1 (One)
If the
TIME_OUT
error code has no usage in a specific domain the value should not reused for an other error code.Any error code need a short description about the background of its error condition.
A Enum data types should be isolated from other Enum data types with its own namespace (
{attribute 'qualified_only'}
).FBF.ERROR.NO_MEMORY
has a completely different meaning asMBM.ERROR.NO_MEMORY
.
Working together with sub libraries brings up the need for mapping the different error domains to the one local domain.
The next example demonstrates the possible design of an error code mapping function.
It handles the error codes (from CS.ERROR
and CO.ERROR
) of two sub libraries and tries to map these to
the one local Error Enum (CANOPEN_KERNEL_ERROR
) (All enum data types in this example have the base type INT
).
Example of an error code mapping function “MapError”
1FUNCTION MapError : CANOPEN_KERNEL_ERROR
2VAR_INPUT
3 iErrorID : INT;
4END_VAR
5
6MapError := CANOPEN_KERNEL_ERROR.CANOPEN_KERNEL_UNKNOWN_ERROR;
7IF iErrorID = CS.ERROR.NO_ERROR THEN
8 MapError := CANOPEN_KERNEL_ERROR.CANOPEN_KERNEL_NO_ERROR;
9ELSIF iErrorID > CS.ERROR.FIRST_ERROR AND iErrorID < CS.ERROR.LAST_ERROR THEN
10 CASE iErrorID OF
11 CS.ERROR.TIME_OUT : MapError := CANOPEN_KERNEL_ERROR.CANOPEN_KERNEL_TIMEOUT;
12 CS.ERROR.REQUEST_ERROR : MapError := CANOPEN_KERNEL_ERROR.CANOPEN_REQUEST_ERROR;
13 CS.ERROR.WRONG_PARAMETER : MapError := CANOPEN_KERNEL_ERROR.CANOPEN_WRONG_PARAMETER;
14 CS.ERROR.NODEID_UNKNOWN : MapError := CANOPEN_KERNEL_ERROR.CANOPEN_NODEID_UNKNOWN;
15 CS.ERROR.SDOCHANNEL_UNKNOWN : MapError := CANOPEN_KERNEL_ERROR.CANOPEN_SDOCHANNEL_UNKNOWN;
16 ELSE
17 MapError := CANOPEN_KERNEL_ERROR.CANOPEN_KERNEL_OTHER_ERROR;
18 END_CASE
19ELSIF iErrorID > CO.ERROR.FIRST_ERROR AND iErrorID < CO.ERROR.LAST_ERROR THEN
20 CASE iErrorID OF
21 CO.ERROR.TIME_OUT : MapError := CANOPEN_KERNEL_ERROR.CANOPEN_KERNEL_TIMEOUT;
22 CO.ERROR.NO_MORE_MEMORY : MapError := CANOPEN_KERNEL_ERROR.CANOPEN_NO_MORE_MEMORY;
23 CO.ERROR.WRONG_PARAMETER: MapError := CANOPEN_KERNEL_ERROR.CANOPEN_WRONG_PARAMETER;
24 CO.ERROR.NODEID_UNKNOWN : MapError := CANOPEN_KERNEL_ERROR.CANOPEN_NODEID_UNKNOWN;
25 CO.ERROR.NETID_UNKNOWN : MapError := CANOPEN_KERNEL_ERROR.CANOPEN_NETID_UNKNOWN;
26 ELSE
27 MapError := CANOPEN_KERNEL_ERROR.CANOPEN_KERNEL_OTHER_ERROR;
28 END_CASE
29END_IF
This design assumes CS.ERROR.NO_ERROR
has the same value as CO.ERROR.NO_ERROR
and the rest of the value range of CS.ERROR
and CO.ERROR
is disjunct.
- Attributes:
qualified_only
- InOut:
Name
Initial
NO_ERROR
0
TIME_OUT
1
WRONG_TRANSITION
-1
WRONG_CONFIGURATION
-2