This time something more advanced, memory manipulation.

Each PLC manufacturer has its own library for doing direct memory manipulation. The functions ignore the data type matching and simply copy n characters from one memory area to another.

Most used functions are:

  • memcpy (copies src. memory into dest. memory)

  • memset (sets wanted value to the dest. memory)

  • memcmp (compares two memory areas and returns)

As most of IDEs are built on top of C, these functions are carbon copies of their C equivalents.

Here are a few examples on how to use MemSet, MemCpy in a PLC environment with some examples of the common faults and risk involved. These examples are using Codesys and their MemUtils library.

Memset

Memset allows the program to set the whole memory area provided to a certain value. I find this extremely useful when resetting structs to zero. It requires no additional memory to set a struct and arrays to a value.

//------------RESET STRUCT WITH A EMPTY STRUCT -------------------
vResultStruct1 := cEmptyStruct;

//------------RESET STRUCT WITH MEM SET -------------------
SysMemSet(ADR(vResultStruct2), 16#0 , SIZEOF(vResultStruct2));

Memcpy

Memcpy allows the program to copy the whole memory area provided to another memory area. This has many uses, but one useful use would be parsing arrays into smaller blocks

//------------COPY STRUCT TO ANOTHER STRUCT -------------------
vResultStruct3 := cEmptyStruct;

//------------COPY STRUCT TO ANOTHER STRUCT MEMCPY -------------------
SysMemCpy(ADR(vResultStruct4), ADR(cEmptyStruct) , SIZEOF(cEmptyStruct));

Memcmp

Memcmp allows the program to compare memory areas. The function returns 0 if same, <> if not same. Compared to struct comparison the MemCmp wins on complexity. The function call will work even if the datatype changes.

//------------COMPARE STRUCT TO ANOTHER STRUCT -------------------
//NOTE: Codesys doesn't support complex struct comparing with = <>
vResult5 := vResultStruct3.dummy1 = cEmptyStruct.dummy1
            AND vResultStruct3.dummy2[0] = cEmptyStruct.dummy2[0]
            AND vResultStruct3.dummy2[1] = cEmptyStruct.dummy2[1]
            AND vResultStruct3.dummy2[2] = cEmptyStruct.dummy2[2]
            AND vResultStruct3.dummy2[3] = cEmptyStruct.dummy2[3]
            AND vResultStruct3.dummy2[4] = cEmptyStruct.dummy2[4]
            AND vResultStruct3.dummy2[5] = cEmptyStruct.dummy2[5]
            AND vResultStruct3.dummy2[6] = cEmptyStruct.dummy2[6]
            AND vResultStruct3.dummy2[7] = cEmptyStruct.dummy2[7]
            AND vResultStruct3.dummy2[8] = cEmptyStruct.dummy2[8]
            AND vResultStruct3.dummy2[9] = cEmptyStruct.dummy2[9]
            AND vResultStruct3.dummy2[10] = cEmptyStruct.dummy2[10]
            AND vResultStruct3.dummy2[11] = cEmptyStruct.dummy2[11]
            AND vResultStruct3.dummy4 = cEmptyStruct.dummy4
            AND vResultStruct3.dummy5 = cEmptyStruct.dummy5
            AND vResultStruct3.dummy6 = cEmptyStruct.dummy6
            AND vResultStruct3.Elem1 = cEmptyStruct.Elem1
            AND vResultStruct3.Id = cEmptyStruct.Id
            AND vResultStruct3.IdText = cEmptyStruct.IdText;

//------------COMPARE STRUCT TO ANOTHER STRUCT MEMCMP -------------------
vResult6 := SysMemCmp(ADR(vResultStruct4), ADR(cEmptyStruct),SIZEOF(cEmptyStruct)) = 0;

Speed measurements

While the speed of execution is roughly the same, SysMemLib wins in many cases, especially with comparing structs and arrays as Codesys doesn’t support this out of the box.

In some cases, manual struct compare is faster if your application has predictable data. With predictable data you can check the data that is more often changing for comparison. This does require the data type to never change or function updated if it does.

Results

Measur. Time took (ms) Note
Reset struct with a empty struct First index 29.6 Loses as we have to have more memory allocation
Reset struct with MemSet 27.801 Roughly same speed as empty struct
Copy a struct to another struct 29.3  
Copy a struct to another struct (MemCpy) 31.09 Roughly same speed as struct assignment
Compare a struct to another struct 37.4 Loses on lines of code and flexibility
Compare a struct to another struct (MemCmp) 38.4 Same call even if modifed data type

As always, the complete source code is on my github repository dedicated to speed testing.

Speedtest: Converting BOOL[1..32] to BYTE[1..4]

Speedtest: Calculations inside loop declarations

Speedtest: ST vs LADDER vs FBD vs CFC

Speedtest: IF-ELSIF vs CASE

Speedtest: Integer vs Floating point math