Supported platforms: CODESYS 3.5 SAFETY

 

Reviewing Safety Parameters

This section describes how to review generated code for safety parameters.

Safety parameter implementation consists of non-safety related code (CANopen OD) and safety related code.

 

This guide focuses mainly on safety related implementation.

 

 

Init_CANopen_ODX (PRG)

 

  1. Verify that the access type G_CANOPEN_OD_ACCESS_SAFEPARAMINDEX is used in each safety parameter OD index initialization. This will prevent write access to the safety parameters from CAN bus, until authentication is done.

 

Code:

 

i_ObjectAccess := G_CANOPEN_OD_ACCESS_READWRITE OR G_CANOPEN_OD_ACCESS_SUB0NOWRITE OR G_CANOPEN_OD_ACCESS_SAVE OR G_CANOPEN_OD_ACCESS_SAFEPARAMINDEX,

 

 

 

S_ValidateParameters_CANX (PRG)

 

This program validates safety parameter CRC for each safety parameter OD index.

 

  1. Verify that the S_ValidateSafetyParameterIndex function is executed for each safety parameter OD index

  2. Verify that the validation datatype corresponds to the OD index datatype (see ParameterDataType for supported types)

  3. Verify that number of subindex matches with the parameter count in the safety parameter OD index

  4. Verify that the parameter given in the i_pData input is the first parameter of the safety parameter OD index (same parameter as used in corresponding OD initialization at Init_CANopen_ODX)

  5. Verify that the used CRC array index matches the safety parameter index list (see below)

 

The following example definition has 6 safety parameter indexes.

SafetyParameterIndexList has a list of safety parameter OD indexes. The order of CRCs in SafetyParameterIndexCRCs shall match with the SafetyParameterIndexList.

 

Definition:

 

/// 16#21FB Table of safety parameter index numbers

SafetyParameterIndexList: ARRAY[0..5] OF WORD := [WORD#16#2201, WORD#16#2202, WORD#16#2203, WORD#16#2204, WORD#16#2205, WORD#16#2206];

/// 16#21FC Table of safety parameter index CRCs

SafetyParameterIndexCRCs: ARRAY[0..5] OF WORD := [6(WORD#0)];

 

The following is an initialization of 2201h safety parameter index.

Note that G_CAN1_PAR.Joystick_X_Deadband is given as a pointer to the OD index (first parameter in safety parameter index).

Code:

 

(* 16#2201  *)

IF G_CANopen_CAN1_VAR.OD_Error = EPEC_CANopen.Errors.NoError THEN

G_CANopen_CAN1_VAR.OD_Error := CANopenODAddLine(

i_pOD := ADR(G_CANopen_CAN1.OD),(*Address of Object dictionary where index will be added*)

i_Index := 16#2201,

i_ObjectCode := EPEC_CANopen.ObjectCode.OD_ARRAY,(*Type of index*)

i_NumOfSubids := USINT#7,(*Number of subindexes*)

i_TypeSpec := EPEC_CANopen.DataType.Deftype_INTEGER32,(*Index datatype, either user defined or standard CiA 301*)

i_ObjectAccess := G_CANOPEN_OD_ACCESS_READWRITE OR G_CANOPEN_OD_ACCESS_SUB0NOWRITE OR G_CANOPEN_OD_ACCESS_SAVE OR G_CANOPEN_OD_ACCESS_SAFEPARAMINDEX,

i_Sub0data := USINT#7,(*Value of subindex0 in array or (def)struct*)

i_pIndexData := ADR(G_CAN1_PAR.Joystick_X_Deadband),

i_itfSDOHandler := DWORD#0

);

END_IF

 

The following example validates two of the safety parameter indexes (in S_ValidateParameters_CANX).

Note that the first validation uses a pointer to G_CAN1_PAR.Joystick_X_Deadband (first safety parameter in 2201h).

The array index of SafetyParameterIndexCRCs is 0 which corresponds to 2201h position in SafetyParameterIndexList.

Code:

failed_index := WORD#0;

 

S_o_Valid :=

EPEC_SDV.S_ValidateSafetyParameterIndex(

i_pData := ADR(G_CAN1_PAR.Joystick_X_Deadband),

i_NumberOfIndices := USINT#7,

i_DataType := EPEC_SDV.ParameterDataType.Deftype_INTEGER32,

i_pCRC := ADR(G_CAN1_VAR.SafetyParameterIndexCRCs[0]),

i_pEventCode := ADR(EC_ParameterValidation),

o_ParameterError => sparerror,

o_OutputValid => sparvalid

);

 

IF NOT S_o_Valid THEN

failed_index := G_CAN1_VAR.SafetyParameterIndexList[0];

END_IF

 

IF S_o_Valid THEN

S_o_Valid :=

EPEC_SDV.S_ValidateSafetyParameterIndex(

i_pData := ADR(G_CAN1_PAR.Joystick_X_DirSwitchDiagDelay),

i_NumberOfIndices := USINT#1,

i_DataType := EPEC_SDV.ParameterDataType.Deftype_UNSIGNED16,

i_pCRC := ADR(G_CAN1_VAR.SafetyParameterIndexCRCs[1]),

i_pEventCode := ADR(EC_ParameterValidation),

o_ParameterError => sparerror,

o_OutputValid => sparvalid

);

IF NOT S_o_Valid THEN

failed_index := G_CAN1_VAR.SafetyParameterIndexList[1];

END_IF

END_IF

 

 

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.

 

Safety parameter OD index which fails validation is added to output o_ErrorInIndex when MultiTool 6.4 or later, or MultiTool Creator is used.

 

The following adds validation error to application log.

Code:

EPEC_SERRLOG.S_AddError_DWORD(

i_ErrorCode := ApplicationErrors.VALIDATE_SAFE_PAR,

i_LibraryErrorCode := EC_ParameterValidation.EventID,

i_Info1 := WORD_TO_DWORD(failed_index), // Safety parameter OD index

i_Info2 := 1 // CAN bus

);

o_ErrorInIndex := failed_index;

 

 

 

S_ValidateConfigurations (PRG)

 

  1. Verify that the program is generated

  2. Verify that the generated S_ValidateParameters_CANX program is executed

  3. Verify that the S_o_Valid flag of S_ValidateParameters_CANX program affects o_ParametersValid output

 

The following is an example where CAN1 bus has safety parameters and SRDO messages. See also Reviewing SRDO.

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_CopyValidatedParameters (PRG)

 

  1. Verify that the program copies parameter values only when the valid flag is TRUE

  2. Verify that each safety parameter defined in MultiTool Creator is copied from G_CANX_PAR variable to G_CANX_SPAR variable

 

An example of safety parameter value initialization:

Code:

IF i_ParametersValid THEN

G_CAN1_SPAR.S_Boom_X_PVGPosMaxPWM:=G_CAN1_PAR.Boom_X_PVGPosMaxPWM;

G_CAN1_SPAR.S_Boom_X_PVGPosMinPWM:=G_CAN1_PAR.Boom_X_PVGPosMinPWM;

 

 

S_ValidateAccessCode_CANX (PRG)

 

The purpose of this program is to verify safety parameter authentication and set a flag which is used to enable safety parameter write access.

 

  1. Verify that the program is generated to the CAN bus containing safety parameters

  2. Verify that the OD variables used in the program corresponds to the CAN bus number in the program name

 

The following is an example of access code validation when safety parameters are defined to CAN1.

Code:

S_o_ValidationOk:=S_ValidateAccessCode(i_ChallengeCode:=G_CAN1_VAR.ChallengeCode,

i_ResponseCode:=G_CAN1_VAR.ResponseCode,

i_ProjectKey:=G_Common.ProjectKey,

i_pEventCode:=ADR(o_EC_ValidateAccessCode),

o_ParameterError => o_ParameterError,

o_OutputValid => o_OutputValid);

                        

IF G_CANOPEN_GFC_VALID=G_CANopen_CAN1_VAR.GFC_Status AND S_o_ValidationOk AND NOT S_ValidationOk_Old THEN

G_Common.CAN1SSDOHandlerGrantAccess:=TRUE;

G_CAN1_VAR.ConfigurationValidStatus:=EPEC_CANopen.CANopenGCL.G_CANOPEN_SRD_CONF_INVALID;

G_CAN1_VAR.AuthenticationStatus:=G_CONSTANTS.G_SAFE_PARAMETERS_AUTHENTICATED;

G_Common.ParhandlerDisableChanges:=TRUE;

S_ValidationOk_Old:=S_o_ValidationOk;

END_IF

 

 

S_PLC_PRG

 

  1. Verify that S_ValidateConfigurations is executed at the initialization phase

 

Code:

ELSIF NOT S_ValidateConfigurations.o_Ready THEN

S_ValidateConfigurations(i_Init:=TRUE);

 

  1. Verify that S_CopyValidatedParameters is executed at the initialization phase

 

Code:

ELSIF NOT S_CopyValidatedParameters.o_Ready THEN

S_CopyValidatedParameters(i_ParametersValid:=S_ValidateConfigurations.o_ParametersValid);

 

  1. Verify that S_ValidateConfigurations is executed at the run phase

 

Code:

ELSIF PLC_PRG.o_Initdone THEN

(*...*)

S_ValidateConfigurations(i_Init:=FALSE);

 

  1. Verify that S_ValidateConfigurations.o_ParametersValid affects the 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);

 

  1. Verify that S_ValidateAccessCode_CANX is executed at the run phase

 

Code:

S_Main();

(*...*)

S_ValidateAccessCode_CAN1();

 

 

PLC_PRG

 

  1. Verify that the following code is generated to PLC_PRG, which is related to S_ValidateAccessCode_CANX and S_ValidateConfigurations.

 

Code:

 

(* Call non-safe blocks that have been flagged from the safe program *)

IF G_Common.ParhandlerDisableChanges THEN

    G_Common.ParhandlerDisableChanges:=FALSE;

    G_Common.ParHandler.DisableChanges(TRUE);

END_IF

IF G_Common.ParhandlerEnableChanges THEN

    G_Common.ParhandlerEnableChanges:=FALSE;

    G_Common.ParHandler.DisableChanges(FALSE);

END_IF

IF G_Common.CAN1SSDOHandlerGrantAccess THEN

G_Common.CAN1SSDOHandlerGrantAccess:= FALSE;

G_CANopen_CAN1.SSDO_Handler.GrantAccessToSafetyParameters(TRUE);

G_CANopen_CAN1.NMT.NmtState:= EPEC_CANopen.NMTState.Preoperational;

END_IF

 

See also

 

 

Source file topic100553.htm

Last updated 13-Jun-2024