News:

  • June 25, 2026, 11:00:26 AM

Login with username, password and session length

Author Topic: MEMCOPY to a Partial Structure  (Read 14135 times)

Bolt

  • Hero Member
  • *****
  • Posts: 598
MEMCOPY to a Partial Structure
« on: January 25, 2023, 12:15:15 PM »
Is there a way to copy a block of data into a partial structure? I have an MHR block with parameters, and I would like to copy it into a UDT that also contains status, etc towards the end of the structure, is there a way to copy words 0 -11 into the UDT and leave the last words 12 - 17 unaffected?

franji1

  • Bit Weenie
  • Host Moderator
  • Hero Member
  • *****
  • Posts: 3827
    • Host Engineering
Re: MEMCOPY to a Partial Structure
« Reply #1 on: January 25, 2023, 12:46:58 PM »
You can do individual field by field, OR

Create a new UDT called StatusStruct, then add those individual Status fields from the original UDT to the StatusStruct, THEN create a .Status field in the original struct that is a StatusStruct.  Then from MEMCOPY from MHR to Original.Status member.

The First attachment shows the MEMCOPY referencing a UDT w/a field called .Status that is a nested UDT.  I am copying MHRs into that sub-structure that is 2 DWORDS or 4 WORDs long (hence MHR10-MHR13 is copied on top of the .Status that itself is a UDT.  Note the Source, Destination and Number parameters in the MEMCOPY.

The Second attachment shows the main UDT definition that contains a field called .Status that is a StatusStruct.  The Third attachment shows the UDT definition of that subfield's structure StatusStruct.

Bolt

  • Hero Member
  • *****
  • Posts: 598
Re: MEMCOPY to a Partial Structure
« Reply #2 on: January 25, 2023, 01:36:42 PM »
Excellent idea. I had gotten as far as making a separate UDT for proof of concept, but the thought had not occurred to me to make that a nested structure inside the primary. The only issue there is that I have a string structure inside it, so I'll bump into the double nested structure limitation, but I can work around that by having Primary.String and Primary.Parameters, and just MEMCOPY twice to get both units filled. Much better than individually populating everything across the board.

Am I correct that to MEMCOPY a block to a string, the first DWord (Len, MaxLen?) needs to be 0x00080008? As far as I can test it populates each time when that's the case, and not when not the case.

franji1

  • Bit Weenie
  • Host Moderator
  • Hero Member
  • *****
  • Posts: 3827
    • Host Engineering
Re: MEMCOPY to a Partial Structure
« Reply #3 on: January 25, 2023, 02:13:39 PM »
Am I correct that to MEMCOPY a block to a string, the first DWord (Len, MaxLen?) needs to be 0x00080008? As far as I can test it populates each time when that's the case, and not when not the case.

Realize that the .Len could technically be anywhere from 0.. .MaxLen based on the specific string (e.g. "" 0 vs "a" 1 vs "ab" 2 vs "abcdefgh" 8).  Or is the Modbus Master actually always padding it with spaces to get to 8 character text length always?  The "safe" way is to just use STRPUTB (not MEMCOPY). that is "smart" regarding the character text only, and intelligently sets the .Len and maintains the .MaxLen (no way for Modbus Master to corrupt .MaxLen).  STRPUTB is also smart that if .Len the Modbus Master sent was 9 or more, STRPUTB would still only copy 8 (actual .MaxLen) and truncate it, not corrupt the memory (this is a SERIOUS problem with MEMCOPY).  MEMCOPY could work, but STRPUB is safer.

franji1

  • Bit Weenie
  • Host Moderator
  • Hero Member
  • *****
  • Posts: 3827
    • Host Engineering
Re: MEMCOPY to a Partial Structure
« Reply #4 on: January 25, 2023, 02:25:21 PM »
You have the "safest" idea of utilizing MEMCOPY for WRITING to Strings (make it fixed 0x00080008, just remember to pad).

I just tried to do MEMCOPY to a String and saw all the WARNINGS (see attachment - yes, 5 WARNINGS) - Caveat Emptor!

franji1

  • Bit Weenie
  • Host Moderator
  • Hero Member
  • *****
  • Posts: 3827
    • Host Engineering
Re: MEMCOPY to a Partial Structure
« Reply #5 on: January 25, 2023, 02:35:34 PM »
Realize that if you EVER change that string member length to be something other than 8 bytes (say to 16), the code that copies 0x00080008 would need to change to 0x0010010, along with better padding in your Modbus memory.  Even an UNDERFLOW would CORRUPT the memory (cuz .MaxLen would be 8, not the specified 16, making an inconsistency between what the UDT says (16) and what the actual memory says (.MaxLen member says 8) - creating confusion in some behaviors).

Moral to the story?  STRPUTB "just works".

Bolt

  • Hero Member
  • *****
  • Posts: 598
Re: MEMCOPY to a Partial Structure
« Reply #6 on: January 25, 2023, 03:17:29 PM »
Got it. Yes, my modbus source always pads with 0x00's so it's not a big issue there. And I would force the PLC to copy 0x08 (or MyStructure.String.MaxLen) to the first 2 registers pre-copy. But now that it's chunked up into 2 instructions anyways, one for .String, one for .Parameters, it won't be a big deal to just to STRPUTB, maybe an STRTRIM for good measure.

franji1

  • Bit Weenie
  • Host Moderator
  • Hero Member
  • *****
  • Posts: 3827
    • Host Engineering
Re: MEMCOPY to a Partial Structure
« Reply #7 on: January 25, 2023, 03:26:12 PM »
maybe an STRTRIM for good measure.

Good idea.  Just verified that STRTRIM in the Sim considers NUL characters (0x00) as "whitespace", so a STRTRIM to trim trailing whitespace worked with input "abc$00$00$00$00$00" in SS0 resulted in "abc" in SS0.