Endianness Problem in TCP Communication

necati
2022-08-12
2022-09-11
  • necati - 2022-08-12

    Hello,

    I have two devices to be communicate by TCP/IP Server/Client. The devices has different endianness. Server device has PowerPC processor (big endian) and client device has Intel processor (little endian).

    When I sent a STRUCT that includes BOOLs, WORDs and DWORDs from server device, client device get the struct elements as byte swapped except for BOOLs. I tried so many way to overcome this problem but I could not solve. Is there any way to get elements of STRUCTS? Is there anybody here to help me?
    BR

    Necati.

     

    Last edit: necati 2022-08-18
  • necati - 2022-08-18

    Updated.

     
  • dFx

    dFx - 2022-08-18

    Both device are codesys plcs ?
    How are you transfering/recovering data from communication buffers to structures ?

     
  • necati - 2022-08-19

    Codesys is running on two devices. I have transferred data but WORD and DWORD data is being swapped on destination device.

     
  • dFx

    dFx - 2022-08-19

    How about using a simple ROL on send buffer ?

    (* Assuming this is a word array buffer *)
    (* And that you only process it once *)
    FOR i:=0 TO LastWordIndexInBuffer DO
        SendBuffer[i] := ROL(SendBuffer[i],8);
    END_FOR;
    
     

    Last edit: dFx 2022-08-19
  • necati - 2022-08-20

    ROL functions does not solve the problem. Because sent data is a STRUCT as below and BYTE swapping occurs.

    TYPE DUT:
    STRUCT
        Var_BOOL01: BOOL:= 1;
        Var_BOOL02: BOOL:= 1;
        Var_BYTE01: BYTE:= 45;
        Var_BYTE02: BYTE:= 188;
        Var_WORD01: WORD:= 110;
        Var_WORD02: WORD:= 35000;
    END_STRUCT
    END_TYPE
    

    BOOLs are stored in memory as BYTE. So, when I inspect Codesys memory bytes for this struct of two devices, it seen as below mapping.

    Device Var_BOOL01 Var_BOOL02 Var_BYTE01 Var_BYTE02 Var_WORD01 Var_WORD02
    Source 01 01 2D BC 00-63 88-B8
    Destination 01 01 2D BC 6E-00 B8-88

    I think if I access type of struct elements and iterating struct by element type, I can swap WORD values, but I don't know if it is possible. And I will be pleased to get your suggestions.
    BR.

     
  • fajean - 2022-08-20

    Reading the following, please note I am not an expert and have not used TCP communication between PLCs, and there may be simpler ways to deal with this that I do not know about.

    It is a bit tricky to diagnose byte swapping issues without access to the full system, but I will hazard a guess as to what may be happening:

    • One of your CPU is little endian, the other is big endian.
    • No byte swapping is actually occurring during TCP communication.
    • You are seeing different values because when the receiving CPU processes the (otherwise entirely identical) multi-byte variables, its endianness makes it see values as swapped.

    You would need to observe your structure as an array of bytes to confirm this (i.e. seeing each byte individually). If your two CPUs have the same endianness, then it could be your I/O subsystem performing byte swapping on one end but not the other, and maybe this is configurable and your problem could go away.

    If two CPUs have different endianness, there is no way they can both work on the same data without conversion if the structure contains multi-byte numeric data. On at least one side (or both if you want a generic solution that adapts to any possible combination of endianness), you must perform a copy to/from I/O memory, from/to normal memory on a variable-by-variable basis, while byte-swapping those variables that are multi-byte. In theory there could, I guess, be a special CODESYS operator that is aware of the layout of structures that could byte-swap the multi-byte variables, but I do not know of one.

    The general solution to allow full independence is to work with three byte orders : one for each host, and one for communication. Decide which byte order you use for communication. On each end, read and write each multi-byte value while performing byte swapping between the host order and the communication order (if they differ). This way, you can switch either end to a new byte order while not affecting the other host.

    For my use, I have created dedicated byte-swapping functions. They receive the data and the communication byte order as arguments, they adapt to the host byte order using conditional compilation, and they return a value that is byte swapped only if the orders differ. The same function works for reading and writing. Perform a web search for "CODESYS defined(IsLittleEndian)" for a starting point in how to do that.

    If you can live with the fact that a change in endianness on either end is going to require re-coding, you can also simply perform byte-swapping on one end only by copying the "main" structure to/from the "I/O" structure in an ad-hoc way.

    Please note that the "pack mode" pragma and the BIT type are also relevant to ensure end-to-end alignment, because two systems may well have the same variables defined in the same order, but have them packed in a different way in their respective structures (causing these structures to be of different sizes). Pack mode 0 is probably what you will need most of the time when structures are used for communication.

    I am not sure this makes you problem any simpler, but this is how I deal with it. If there is a simpler way, I will be happy to find out about it...

     
  • shaunvdm - 2022-09-11

    Hi,

    We are doing this successfully between different IPC.
    Use the MEM.PackBytesToWord function example MEM.PackBytesToWord(byHighByte:=My_data[1],byLowByte:=My_data[0]) function to swap the data at the other end after receiving the data from the TCP buffer.

    Hope this helps...

     

    Related

    Talk.ru: 1


Log in to post a comment.