#5 Find or create a Codesys solution for: FUNCTION MEMCPY

v1.0
closed
nobody
None
2020-05-01
2019-05-04
aliazzz
No

The function MEMCPY can be used to copy the values of PLC variables from one memory area to another.

https://infosys.beckhoff.com/english.php?content=../content/1033/tcplclib_tc2_system/36028797049921931.html&id=

The function MEMCPY can be used to copy the values of PLC variables from one memory area to another.
FUNCTION MEMCPY : UDINT

VAR_INPUT
    destAddr  : PVOID;
    srcAddr   : PVOID;
    n         : UDINT;
END_VAR

destAddr: Start address of the target memory area.
srcAddr: Start address of the source memory area.
n: Number of bytes to be copied.

The function copies n bytes from the memory area that starts at srcAddr to the memory area that starts at destAddr.
Return parameter

Meaning
0 : Incorrect parameter values. destAddr == 0 or srcAddr==0 or n == 0

0 If successful, the number of bytes copied (n)

Discussion

  • aliazzz

    aliazzz - 2019-05-08

    added CAA_Types_extern which contains the alias for PVOID (type __XWORD)

     
  • aliazzz

    aliazzz - 2019-05-12
    • status: open --> accepted
    • assigned_to: aliazzz
     
  • aliazzz

    aliazzz - 2019-05-12
    • assigned_to: aliazzz --> nobody
     
  • zer0g - 2019-05-12

    I tested your function with the following example but it didn't work:

    PROGRAM PRG2
    VAR
        arr1: ARRAY [0..23] OF REAL := [12.0, 25.0, 2.325, 87.0, 7.456, 128.0, 18(0.0)];
        arr2 : ARRAY [0..23] OF REAL;
        n : UDINT;
    END_VAR
    
    n := MEMCPY(srcAddr := ADR(arr1),destAddr := ADR(arr2),n := SIZEOF(arr2));
    

    The runtime crashed a couple of times.

    After some thinking I realized that we dont need the PVOID_TO_LWORD() conversion. The compiler will convert automatically to DWORD or LWORD depending on the runtime.

    I hope you don't mind, but I took the liberty to modify your version.

    FUNCTION MEMCPY : UDINT
    VAR_INPUT
        destAddr  : CAA.PVOID; //Start address of the destination
        srcAddr   : CAA.PVOID; //Start address of the source
        n         : UDINT;
    END_VAR
    VAR
        pSrc : POINTER TO BYTE;
        pDest : POINTER TO BYTE;
        i : UDINT;
    END_VAR
    
    // return 0 : Icorrect parameter values. 
    // destAddr == 0 or srcAddr==0 or n == 0
    IF (srcAddr = 0) OR (destAddr = 0) OR (n = 0) THEN
         MEMCPY := 0;
         RETURN;
    END_IF
    
    //lwSrc := CAA.PVOID_TO_LWORD(srcAddr);
    //pSrc := ADR(lwSrc); //This is not right. We are now pointing to the address of the lwSrc and not srcAddr.
    
    //lwDest := CAA.PVOID_TO_LWORD(destAddr);
    //pDest := ADR(lwDest); // Same as above
    
    //No need for the above conversions. The compiler will take care of everything.
    //Just pass the start address to the pointer.
    
    pSrc := srcAddr;
    pDest := destAddr;
    
    FOR i := 0 TO (n-1) DO
        pDest[i] := pSrc[i];    // copy contents from src to dest
    END_FOR
    
    //return n
    MEMCPY := n;
    

    As I don't have a 64 bit runtime maybe you can tell me if this runs okay on RPi.

     
  • aliazzz

    aliazzz - 2019-05-13

    Hi,

    Offcourse I dont mind.

    I had the same issue's with crashing on my RPi but I was tired so I stopped looking at it further. I allready suspected that "ADR()" was no good as the input references are allready pointing at the start adress of the datasourc and destination we want to copy.
    This caused my RPi also to crash which is not strange really.

    Plus you are right on the conversion, the compiler implicitly converts the PVOID to a (L)WORD according to the documentation, so it makes no sense to put an explicit conversion in (my bad!).

    I will test the code again on RPi soon.

    PS
    I tested another functionality from CAA Memory library, it has a function which returns if the systems is small, medium or large (16 bit, 32 bit, 64 bit) but at this moment my RPi3B+ returned medium size (32 bits).
    Maybe this has got something to do with the Codesys IDE itself as I installed 3.5.14.20 x86 (32bit) IDE version because RPi3B/3B+ is a 64 bits architecture.
    Maybe I did something wrong?

    To be continued very soon

    UPDATE
    I tested this function with succes on Control Win V3 32Bits. It will work on RPi, I am sure. So, for now I will park this Ticket as I think this Ticket is surely 99.9% resolved.

     
  • aliazzz

    aliazzz - 2019-05-13
    • status: accepted --> closed
     
  • zer0g - 2019-05-13

    I tested another functionality from CAA Memory library, it has a function which returns if the systems is small, medium or large (16 bit, 32 bit, 64 bit) but at this moment my RPi3B+ returned medium size (32 bits).
    Maybe this has got something to do with the Codesys IDE itself as I installed 3.5.14.20 x86 (32bit) IDE version because RPi3B/3B+ is a 64 bits architecture.
    Maybe I did something wrong?

    I don't think so.
    As for the runtime version I found out that __SYSTEM.Constants.nRegisterSize can be used to retrive the type of system.

    // Number of Bits per Register. Possible values: 16 (c16x, 186), 32 (x86, ARM, PPC ...), 64 (x86-64Bit)

     
  • aliazzz

    aliazzz - 2019-05-13

    For now we have a working implementation which accepts PVOID as input address which makes our solution more portable and universal.

    Maybe we can replace it with some x64 compatible CAA library which also implements PVOID when it is released.

     
  • aliazzz

    aliazzz - 2019-05-13

    latest version of MEMCPY with a small testprogram (contains a test for MEMCPY and MEM.MemMove)

     
  • zer0g - 2019-05-13

    It works okay.

     

Log in to post a comment.