Supported platforms: CODESYS 3.5 SAFETY

 

Reviewing SRDO

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)

 

  1. 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)

 

  1. Verify that the program is generated

  2. Verify that generated S_ValidateSRDOSignatures_CANX programs are executed

  3. 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)

 

  1. Verify that the program is generated for each CAN where transmit SRDO messages are used

  2. 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)

 

  1. Verify that the program is generated for each CAN where receive SRDO messages are used

  2. Verify that each receive SRDO variable has S_ValidateSRDO_<type> function block in the program

  3. Verify that each validation instance is initialized and executed at runtime

  4. Verify that each validation instance affects o_SRDO_Data_Valid status

 

Application is responsible of using o_SRDO_Data_Valid.

See also How to send and receive variable over SRDO.

 

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();

 

Handle_CANopen_CANX (PRG)

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

);

 

Non-safety related

Additionally following can be checked, but not covered by this example:

 

See also

 

 

Source file topic100552.htm

Last updated 13-Jun-2024