Supported platforms: CODESYS 3.5 SAFETY
This section describes how to review generated code for Safety-Related Data Objects (SRDO).
SRDO message implementation consists of non-safety related code and safety related code.
This guide focuses mainly on safety related implementation.
S_ValidateSRDOSignatures_CANX (PRG)
Verify that the program is generated for each CAN which has SRDO message(s)
Error code is added to application log only when device description includes SafeErrorLog library. In SC52 device description 3.5.10.6 or later is required. See also How to use application error log. |
The following code is generated in a program which will validate all SRDO message signatures in a single CAN bus. The following example is for CAN1 bus.
Values to the SRDO_Signatures array are generated by MultiTool Creator.
Code: |
o_InitSafeSRDOValidationReady := TRUE; S_o_Valid := TRUE; /// CAN 1 SRDOs FOR i := UINT#1 TO SIZEOF(G_CANopen_CAN1.SRDOS)/SIZEOF(G_CANopen_CAN1.SRDOS[1]) DO S_o_Valid := S_o_Valid AND EPEC_SDV.S_ValidateSRDOSignature ( i_pSRDOSignature := ADR(G_CANopen_CAN1_VAR.SRDO_Signatures[i]), i_InfoDirection := G_CANopen_CAN1.SRDOS[i].i_SRDOType, i_SCTime := G_CANopen_CAN1.SRDOS[i].i_SCTime, i_SRVTime := G_CANopen_CAN1.SRDOS[i].i_SRVTime, i_COBID1 := G_CANopen_CAN1.SRDOS[i].i_COB_ID1, i_COBID2 := G_CANopen_CAN1.SRDOS[i].i_COB_ID2, i_Mappings := G_CANopen_CAN1.SRDOS[i].i_Mappings, i_pMappingParameter := ADR(G_CANopen_CAN1.SRDOS[i].i_Mapping), i_pEventCode := ADR(G_CANopen_CAN1_VAR.SRDO_EventCodes[i]), o_ParameterError => srdoerror, o_OutputValid => srdovalid );
IF NOT S_o_Valid THEN EPEC_SERRLOG.S_AddError_DWORD( i_ErrorCode := ApplicationErrors.VALIDATE_SRDO_SIGNATURE, i_LibraryErrorCode := G_CANopen_CAN1_VAR.SRDO_EventCodes[i].EventID, i_Info1 := G_CANopen_CAN1.SRDOS[i].i_SRDONumber, // SRDO number i_Info2 := 1 // CAN bus ); END_IF
o_InitSafeSRDOValidationReady := o_InitSafeSRDOValidationReady AND srdovalid; END_FOR |
S_ValidateConfigurations (PRG)
Verify that the program is generated
Verify that generated S_ValidateSRDOSignatures_CANX programs are executed
Verify that the S_o_Valid flag of each S_ValidateSRDOSignatures_CANX program affects o_SRDOSignaturesValid output
The following is an example where CAN1 bus has SRDO messages and safety parameters. See also Reviewing Safety Parameters.
Code: |
// If initializing, or configuration valid status is in progress IF G_CAN1_VAR.ConfigurationValidStatus=EPEC_CANopen.CANopenGCL.G_CANOPEN_SRD_CONF_IN_PROGRESS OR i_Init THEN // Validate parameters and SRDO signatures S_ValidateParameters_CAN1(); S_ValidateSRDOSignatures_CAN1(); // If both passed, set configuration valid status to valid, otherwise set it to invalid IF S_ValidateParameters_CAN1.S_o_Valid AND S_ValidateSRDOSignatures_CAN1.S_o_Valid THEN G_CAN1_VAR.ConfigurationValidStatus:=EPEC_CANopen.CANopenGCL.G_CANOPEN_SRD_CONF_VALID; G_Common.ParhandlerEnableChanges:=TRUE; ELSE G_CAN1_VAR.ConfigurationValidStatus:=EPEC_CANopen.CANopenGCL.G_CANOPEN_SRD_CONF_INVALID; END_IF // Output statuses o_Ready:=TRUE; o_ParametersValid:=S_ValidateParameters_CAN1.S_o_Valid; o_SRDOSignaturesValid:=S_ValidateSRDOSignatures_CAN1.S_o_Valid; END_IF |
S_Create_SRDOs_CANX (PRG)
Verify that the program is generated for each CAN where transmit SRDO messages are used
Verify that each transmit SRDO variable has a CreateSRDO_<type> function call in the program
The following is an example code for two variables in the same SRDO message.
Array index of CANopen SRDO variables shall be same for each variable which is mapped to same SRDO message.
Code: |
IF NOT G_CANopen_CAN1_VAR.SRDO_Interlock[1] THEN EPEC_SRDO.CreateSRDO_Int( S_i_Input:= S_i_Joystick_X_Control, S_i_TransmitTimeout:= G_CANopen_CAN1.SRDOS[1].i_SCTime, o_PlainMsgData => G_CAN1_TSRDO.Joystick_X_Control, o_InvertMsgData => G_CAN1_TSRDO.Joystick_X_Control_i, o_PlainMsgTime => G_CAN1_TSRDO.Joystick_X_Control_TIME, o_InvertMsgTime => G_CAN1_TSRDO.Joystick_X_Control_i_TIME ); END_IF
IF NOT G_CANopen_CAN1_VAR.SRDO_Interlock[1] THEN EPEC_SRDO.CreateSRDO_Int( S_i_Input:= S_i_Joystick_Y_Control, S_i_TransmitTimeout:= G_CANopen_CAN1.SRDOS[1].i_SCTime, o_PlainMsgData => G_CAN1_TSRDO.Joystick_Y_Control, o_InvertMsgData => G_CAN1_TSRDO.Joystick_Y_Control_i, o_PlainMsgTime => G_CAN1_TSRDO.Joystick_Y_Control_TIME, o_InvertMsgTime => G_CAN1_TSRDO.Joystick_Y_Control_i_TIME ); END_IF |
S_Validate_SRDOs_CANX (PRG)
Verify that the program is generated for each CAN where receive SRDO messages are used
Verify that each receive SRDO variable has S_ValidateSRDO_<type> function block in the program
Verify that each validation instance is initialized and executed at runtime
Verify that each validation instance affects o_SRDO_Data_Valid status
Application is responsible of using o_SRDO_Data_Valid. |
Error code is added to application log only when device description includes SafeErrorLog library. In SC52 device description 3.5.10.6 or later is required. See also How to use application error log. |
Following is initialization example of two variables mapped to same receive SRDO.
Array index of CANopen SRDO variables shall be same for each variable which is mapped to same SRDO message.
Code: |
IF (i_Initialize) THEN (* SRDO 1, receive SRDOs*) init_ok := S_Validate_Cabin_Joystick_X_Control.Init( S_i_SCTime := G_CANopen_CAN1.SRDOS[1].i_SCTime, (* Safeguard cycle time *) S_i_SRVTime := G_CANopen_CAN1.SRDOS[1].i_SRVTime, (* SR Validation time *) i_SRDOIndex := BYTE#1, (* SRDO number -> EventCode.DeviceID *) i_VarIndex := BYTE#1, (* variable number -> EventCode.ChannelID *) i_pEventCode := ADR(G_CANopen_CAN1_VAR.SRDO_EventCodes[1]), (* Event code pointer for FB *) i_pTrigger := ADR(G_CANopen_CAN1_VAR.SRDO_Triggers[1]), (* Trigger status *) i_pInterlock := ADR(G_CANopen_CAN1_VAR.SRDO_Interlock[1]) (* CANopen interlock *) ); init_ok := init_ok AND S_Validate_Cabin_Joystick_Y_Control.Init( S_i_SCTime := G_CANopen_CAN1.SRDOS[1].i_SCTime, (* Safeguard cycle time *) S_i_SRVTime := G_CANopen_CAN1.SRDOS[1].i_SRVTime, (* SR Validation time *) i_SRDOIndex := BYTE#1, (* SRDO number -> EventCode.DeviceID *) i_VarIndex := BYTE#2, (* variable number -> EventCode.ChannelID *) i_pEventCode := ADR(G_CANopen_CAN1_VAR.SRDO_EventCodes[1]), (* Event code pointer for FB *) i_pTrigger := ADR(G_CANopen_CAN1_VAR.SRDO_Triggers[1]), (* Trigger status *) i_pInterlock := ADR(G_CANopen_CAN1_VAR.SRDO_Interlock[1]) (* CANopen interlock *) ); o_InitError:= NOT init_ok; o_InitReady:= TRUE; ELSE (* Validate RX SRDO data *) S_Validate_Cabin_Joystick_X_Control( i_Enable := i_Enable, i_PlainMsgData := G_CAN1_RSRDO.Cabin_Joystick_X_Control, i_InvertMsgData := G_CAN1_RSRDO.Cabin_Joystick_X_Control_i, i_PlainMsgTime := G_CAN1_RSRDO.Cabin_Joystick_X_Control_TIME, i_InvertMsgTime := G_CAN1_RSRDO.Cabin_Joystick_X_Control_i_TIME, o_Status => o_Status_Cabin_Joystick_X_Control, S_o_Output => S_o_Cabin_Joystick_X_Control ); S_Validate_Cabin_Joystick_Y_Control( i_Enable := i_Enable, i_PlainMsgData := G_CAN1_RSRDO.Cabin_Joystick_Y_Control, i_InvertMsgData := G_CAN1_RSRDO.Cabin_Joystick_Y_Control_i, i_PlainMsgTime := G_CAN1_RSRDO.Cabin_Joystick_Y_Control_TIME, i_InvertMsgTime := G_CAN1_RSRDO.Cabin_Joystick_Y_Control_i_TIME, o_Status => o_Status_Cabin_Joystick_Y_Control, S_o_Output => S_o_Cabin_Joystick_Y_Control );
G_CANopen_CAN1_VAR.SRDO_Triggers[1]:=FALSE;
o_SRDO_Data_Valid:= o_Status_Cabin_Joystick_X_Control.OutputValid AND o_Status_Cabin_Joystick_Y_Control.OutputValid;
IF (i_Enable AND NOT o_SRDO_Data_Valid) OR o_InitError THEN EPEC_SERRLOG.S_AddError_BYTE( i_ErrorCode := ApplicationErrors.VALIDATE_SRDO, i_LibraryErrorCode := G_CANopen_CAN1_VAR.SRDO_EventCodes[1].EventID, i_Info1 := G_CANopen_CAN1_VAR.SRDO_EventCodes[1].FunctionID, i_Info2 := G_CANopen_CAN1_VAR.SRDO_EventCodes[1].DeviceID, i_Info3 := G_CANopen_CAN1_VAR.SRDO_EventCodes[1].ChannelID, i_Info4 := 0, i_Info5 := 0, i_Info6 := 0, i_Info7 := 0, i_Info8 := 1 // CAN bus ); END_IF END_IF |
S_PLC_PRG
1. Verify that S_Validate_SRDOs_CANX is executed at initialization phase (if generated)
2. Verify that S_ValidateConfigurations is executed at initialization phase
Code: |
ELSIF NOT S_Validate_SRDOs_CAN1.o_InitReady THEN S_Validate_SRDOs_CAN1(i_Initialize:=TRUE); ELSIF NOT S_ValidateConfigurations.o_Ready THEN S_ValidateConfigurations(i_Init:=TRUE); |
3. Verify that S_Validate_SRDOs_CANX is executed at run phase (if generated)
4. Verify that S_ValidateConfigurations is executed at run phase
Code: |
ELSIF PLC_PRG.o_Initdone THEN (*...*) S_Validate_SRDOs_CAN2(i_Initialize:=FALSE); S_ValidateConfigurations(i_Init:=FALSE); |
5. Verify that S_ValidateConfigurations.o_SRDOSignaturesValid affects S_Safety_Status program's input:
Code: |
S_Safety_Status(i_Safe_InitDone:= o_InitDone, i_Nonsafe_InitDone:= PLC_PRG.o_InitDone, S_i_SafetySignaturesValid:= S_ValidateConfigurations.o_SRDOSignaturesValid, S_i_SafetyParametersValid:= S_ValidateConfigurations.o_ParametersValid, S_o_SafeOperationEnable => G_StatusFlags_Safe.S_SafeOperationEnable); |
6. Verify that S_Create_SRDOs_CANX is executed at run phase (if generated)
Code: |
(* User safe main program *) S_Main(); (* Safe actions to execute after safe main program *) S_Create_SRDOs_CAN1(); |
Following executes SRDO protocol in run phase.
Verify that S_SafeOperationEnable status affects SRDO protocol's i_Enable.
Code: |
|
G_CANopen_CAN1.SRDO_Handler.Update( i_Enable := G_StatusFlags_Safe.S_SafeOperationEnable, o_Error => G_CANopen_CAN1_VAR.SRDO_Error ); |
Additionally following can be checked, but not covered by this example:
G_CANopen_CANX / G_CANopen_CANX_VAR: All SRDO arrays need to be same size (amount of rx+tx SRDO messages)
G_CANopen_CANX_Mappings: Mapping array is generated for each SRDO message
G_CAN1_TSRDO: Plain & invert data + timestamp variables are generated for each transmit variable mapped to SRDO
G_CAN1_RSRDO: Plain & invert data + timestamp variables are generated for each receive variable mapped to SRDO
Init_CANopen_CANX (PRG): All SRDO messages need to be initialized for CANopen
Init_CANopen_ODX (PRG): All OD indexes used in SRDO mappings need to be initialized
Source file topic100552.htm
Last updated 19-Dec-2024