Supported platforms: CODESYS 3.5 SAFETY

 

How to transfer data between non-safety and safety related tasks

A safety project's application has a safety task and a non-safety task. Due to lower priority, the non-safety task may be interrupted at any time by the safety task.

Interruption can occur when the non-safety task is updating the non-safe related data. To prevent data corruption:

 

This section describes how a data interlock can be used between non-safety and safety related application parts. The data can consist of, for example,

 

CANopen and SAE J1939 protocols are all executed in non-safety code.

 

This topic does not apply to SRDO variables. SRDO variables are already interlocked in code template. See also, How to send and receive variables over SRDO

 

 

The following example uses two structures:

  1. data from non-safety related application to safety related application

  2. data from safety related application to non-safety related application

 

The main idea is that the non-safety related task sets the structure Interlock boolean to TRUE when the data is used (read/written). Non-safety related task resets the Interlock boolean to FALSE when reading/writing is done. The safety related task does not use the data when the Interlock boolean is TRUE.

 

NewData boolean is set to TRUE in that task which updates the data. The task which uses the data resets the NewData to FALSE.

 

Example

 

Declaration

// Safety task updates data and read by non-safety task

TYPE AppDataFromSafe :

STRUCT

    Interlock: BOOL; // Set TRUE by non-safety task when data read in progress

    NewData:BOOL; // Set TRUE by safety task when new data is available (copying complete)

 

    SafeInternalVar1: BYTE; // Internal variable from non-safety PRG to safety PRG

    TransmitData1: DWORD; // Data from safety PRG to non-safety TPDO

    SpeedRequest: WORD; // Variable from safety PRG to non-safety J1939 transmit PGN

END_STRUCT

END_TYPE

 

 

Declaration

 

// Non-safety task updates data and read by safety task

TYPE AppDataToSafe :

STRUCT

    Interlock: BOOL; // Set TRUE by non-safety task when data write in progress

    NewData:BOOL; // Set TRUE by non-safety task when new data is available (copying complete)

 

    NonSafeInternalVar1: BYTE; // Internal variable from non-safety PRG to safety PRG

    ReceivedData1: WORD; // RPDO variable to safety PRG

    ActualSpeed: WORD; // Received J1939 variable to safety PRG

END_STRUCT

END_TYPE

 

 

Declarations for GVL G_AppData

 

{attribute 'qualified_only'}

{attribute 'location' := '16#800'}

// Non-safety data to allow both tasks to write in data

VAR_GLOBAL

    DataToSafeTask: AppDataToSafe;

    DataFromSafeTask: AppDataFromSafe;

END_VAR

 

 

Non-safety related code

Declarations

VAR

    // to safety task

    non_safe_var1: BYTE;

    actual_speed: WORD;

 

    // from safety task

    var1_from_safe_task: BYTE;

    speed_request: WORD;

END_VAR

 

 

Update received non-safety related variables which are needed in safety related task.

The received data is updated for safety related task only when NewData is FALSE. This is needed to prevent lock being always on when the safety related task is executed.

 

Non-safe PRG

IF NOT G_AppData.DataToSafeTask.NewData THEN

    // non-safety task indicates that data copy in progress

    G_AppData.DataToSafeTask.Interlock := TRUE;

 

    // copy data

    G_AppData.DataToSafeTask.NonSafeInternalVar1 := non_safe_var1;

    G_AppData.DataToSafeTask.ReceivedData1 := G_CAN1_RPDO.ReceivedData;

    G_AppData.DataToSafeTask.ActualSpeed := actual_speed;

 

    // indicate new data available

    G_AppData.DataToSafeTask.NewData := TRUE;

    // Remove data lock

    G_AppData.DataToSafeTask.Interlock := FALSE;

END_IF

 

Application code:

 

Non-safe PRG

non_safe_var1 := non_safe_var1 + 1;

G_J1939.CAN2.Out.Engine.TSC1_EngRqedSpeed_SpeedLimit := speed_request * 8;

actual_speed := G_J1939.CAN2.In.Engine.EEC1_EngSpeed / WORD#8;

 

Reading data from the safety related task and update transmit variables, for example, TPDO messages.

The data is read only if NewData is TRUE. This prevents situation where Interlock would always be true during the safety related task.

 

Non-safe PRG

IF G_AppData.DataFromSafeTask.NewData THEN

    // non-safety task indicates that data copy in progress

    G_AppData.DataFromSafeTask.Interlock := TRUE;

 

    // copy data

    var1_from_safe_task := G_AppData.DataFromSafeTask.SafeInternalVar1;

    G_CAN1_TPDO.TransmitData1 := G_AppData.DataFromSafeTask.TransmitData1;

    speed_request := G_AppData.DataFromSafeTask.SpeedRequest;

 

    // non-safety task sets new data to false when data is read and removes lock

    G_AppData.DataFromSafeTask.NewData := FALSE;

    G_AppData.DataFromSafeTask.Interlock := FALSE;

END_IF

 

Safety related code

Declarations

VAR

    // fron non-safety task

    var1_from_nonsafe_task: BYTE;

    received_data1: WORD;

    actual_speed: WORD;

 

    // to non-safety task

    safetask_var1: BYTE;

    speed_request: WORD;

    transmit_data1: DWORD;

END_VAR

 

Read received non-safety variables which are needed in the safety related task.

The data is read only when NewData is TRUE and Interlock is FALSE.

 

Safe PRG:

IF G_AppData.DataToSafeTask.NewData AND NOT G_AppData.DataToSafeTask.Interlock THEN

    // copy data

    var1_from_nonsafe_task := G_AppData.DataToSafeTask.NonSafeInternalVar1;

    received_data1 := G_AppData.DataToSafeTask.ReceivedData1;

    actual_speed := G_AppData.DataToSafeTask.ActualSpeed;

 

    // Set new data to FALSE which allows non-safe task to update new data

    G_AppData.DataToSafeTask.NewData := FALSE;

END_IF

 

Application code:

 

Safe PRG:

safetask_var1 := safetask_var1 + 1;

speed_request := 1000;

transmit_data1 := transmit_data1 + 1;

 

Write safety related task variables for non-safety related task. The data is written only if Interlock is FALSE.

 

Safe PRG:

IF NOT G_AppData.DataFromSafeTask.Interlock THEN

 

    // copy data

    G_AppData.DataFromSafeTask.SafeInternalVar1 := safetask_var1;

    G_AppData.DataFromSafeTask.TransmitData1 := transmit_data1;

    G_AppData.DataFromSafeTask.SpeedRequest := speed_request;

 

    // safety task sets new data to TRUE when data has been written

    G_AppData.DataFromSafeTask.NewData := TRUE;

END_IF

 

See also

 

 

Source file topic100581.htm

Last updated 13-Jun-2024