Resolving BLKMOV Compilation Warning with UDT in TIA Portal

David Krause11 min read
SiemensTIA PortalTroubleshooting
Licensed PE Working through this on a live machine? A Maine-licensed engineer can take it from here — included with IMD hardware, by the hour for everything else. Book an engineer

Resolving BLKMOV Compilation Warning with UDT Parameters in TIA Portal

This technical reference documents the root cause and resolution of the compiler warning emitted by the TIA Portal compiler when the BLKMOV (SFC20 / "Move block") instruction uses a parameter declared as a User Defined Type (UDT) as the destination area. The behavior is most often reported after migrating from STEP 7 V5.x to TIA Portal V13+ on S7-300 CPUs, but the underlying mechanism applies across the S7-300/S7-400 and S7-1200/S7-1500 families. The article consolidates Siemens documentation references, a concrete reproducer, four field-proven workarounds, runtime diagnostics for W#16#837F, and a migration checklist that resolves the warning without sacrificing the original block architecture.

Engineering scope. The discussion covers S7-300 (CPU 315-2 PN/DP), S7-400, S7-1200, and S7-1500 controllers. The S7-300/400 path uses SFC20 (BLKMOV) on a classic STEP 7 or TIA Portal firmware load. The S7-1500 path uses the native "Move block" instruction. Where the symptom is identical across families, the resolution has nuances detailed in Resolution Strategies.

1. Overview of the BLKMOV Compilation Warning

The BLKMOV instruction copies the contents of a source memory area to a destination memory area in a single call. Both source (SRCBLK) and destination (DSTBLK) are declared as ANY pointer parameters so the block can operate on different memory types, sizes, and addresses at runtime. Siemens describes the instruction formally in the entry BLKMOV: Move block - STEP 7 Professional V13.1 (ID: 109011420).

In TIA Portal V13 and later, the compiler emits an informational warning (level 1 in the TIA compiler pipeline) when a parameter that receives the result of BLKMOV is typed as a UDT rather than as a fully qualified ANY pointer or as an in-instance symbolic address with known storage location. The warning does not prevent download or runtime, but it flags a potential mismatch between the length encoded in the ANY pointer and the absolute memory footprint of the UDT. The reproducer follows.

FUNCTION_BLOCK FB100
VAR
    uParam  : ANY;          // source pointer, length auto
    Param   : UDT_PARAM_STRUCT; // destination typed as UDT
    bOK     : BOOL;
END_VAR

BEGIN
    // Source: P#DB20.DBX0.0 BYTE 80
    // Destination: a UDT instantiated in DB50
    bOK := BLKMOV(uParam, Param); // compiler emits 'Inconsistent ANY/UDT length' warning
END_FUNCTION_BLOCK

Switching the same call into a Function (FC) does not clear the warning. Inverting the situation so the compilation happens inside a separate Function Block that owns the temporary area, however, often silences the warning because the compiler can resolve the temporary to an absolute offset inside the FB's instance DB or local stack frame.

2. Technical Background: BLKMOV and ANY Pointer Mechanics

The ANY pointer format used by Siemens is ten bytes long and encodes the data type, length, and byte address of the referenced area:

Byte Meaning Typical value
0..3 ID + data type 10 00 00 00, B#16#02 = BYTE, B#16#04 = WORD, B#16#06 = DWORD, B#16#15 = BOOL, etc.
4..5 Length (repetition factor) Number of elements, max 65535
6..9 DB number + byte offset DB #, byte offset (negative offsets for inputs/outputs)

The destination ANY is re-encoded with the byte length of the destination parameter each call. When the destination parameter is a UDT, the length is the size of the UDT (header included). The TIA Portal compiler can only verify the ANY at compile time when both pointer operands can be statically resolved. UDTs that are not bound to a DB, FB-static, or FC-temp area lack a backing storage location during compile, so the warning is raised.

The runtime counterpart of this compile-time check is the return value RET_VAL. Per the Siemens KB entry 109011420, error code W#16#837F is the canonical "source/destination cannot be processed" error for BLKMOV. RET_VAL is W#16#0000 on success and an error word on failure. The CPU family influences which specific error codes can be issued; the table in Section 8 consolidates them.

3. Root Cause: UDT Templates vs. Absolute Memory Addresses

UDT (User Defined Type) is a type template, not an actual memory location. It is downloaded to the CPU only inside a Data Block, in the static area of an FB, or as the type of an IN_OUT parameter of an FB/FC. The UDT itself never holds runtime data. TIA Portal's compiler needs to know the actual address at which the destination bytes live so it can populate the ANY destination pointer at compile time. When the destination is a UDT but the compiler cannot resolve an absolute offset, it falls back to a "best-effort" ANY and emits the warning.

The mismatch has three common variations:

  1. FC with UDT IN_OUT: FCs do not own background memory. The UDT type is acceptable, but the compiler cannot fully verify the destination ANY because the FC's stack frame is volatile. The warning is raised.
  2. FB with UDT IN_OUT or static: The FB owns an instance DB. The compiler can resolve offsets to a specific address in the instance DB or to a temp local offset, and the warning is suppressed.
  3. FC/FB with UDT inside a passed DB: The destination is a UDT field in a referenced DB. The compiler resolves the offset, but only if the DB is symbolically known. Passing an ANY typed input shifts the validation back to runtime.
Why the warning appears in TIA but not in STEP 7 V5.5. TIA Portal performs additional pointer/length checks during compile because it builds a stricter type system for the SCL/ST editor. STEP 7 V5.x was more permissive and deferred most ANY validation to runtime. Migration to TIA exposes the structural ambiguity that V5.x hid.

4. Affected Platforms and CPU Behavior

Platform CPU sample FW range Warning visible in TIA? Runtime RET_VAL codes used
S7-300 CPU 315-2 PN/DP (6ES7315-2EH14) V3.3 Yes (when UDT destination is ambiguous) 0000, 8091, 8092, 837F
S7-400 CPU 416-3 PN/DP (6ES7416-3ES06) V6.x Yes 0000, 8091, 8092, 837F
S7-1200 CPU 1214C DC/DC/DC (6ES7214-1AG40) V4.2-V4.7 Yes Native "Move block" differs; see SCL doc.
S7-1500 CPU 1515-2 PN (6ES7515-2AM02) V2.5-V3.1 Yes (for legacy SFC20 calls) Native BLKMOV equivalent; SFC20 wrapper behaves as S7-300/400.

For S7-1500, Siemens recommends the native Move block instruction described in BLKMOV: Move block (S7-1500) - TIA Portal Help. The S7-1500 instruction honors the same SRCBLK/DSTBLK/RET_VAL interface, but its compiler checks are tighter; passing a UDT reference that lacks an absolute address raises the warning too.

5. Compiler Warning Reference

The TIA Portal compiler classifies this message as a "Length information cannot be derived" warning. It is similar in spirit to C4651 (Microsoft Learn) in that the compiler proceeds but signals a structural inconsistency that may surface as a runtime fault. The TIA warning text reads approximately:

[Warning] Block <name>: The length of an ANY pointer for parameter <Param> could not be statically determined.
           Verify that the destination area can fully contain the source bytes at runtime.

Three options are presented in the TIA "Information" pane after a build:

  1. Keep as warning. Acceptable if you have manually verified that the UDT size matches the source ANY length.
  2. Convert to error. Available via Project > Settings > Compiler > Warnings as errors. Forces a clean compile for CI/Gate processes.
  3. Refactor the call (recommended when migrating a large program).

6. Resolution Strategies

Four field-proven patterns resolve the warning. Pick the smallest one that fits your code topology.

6.1 Move the UDT into an FB's Static or Temp Area

This is the canonical fix. Promoting the UDT from a free variable to a static variable of an FB (or to the temporary area of an FB/FC) gives the compiler a deterministic address.

FUNCTION_BLOCK FB200
VAR
    stData   : UDT_PARAM_STRUCT;   // static instance > absolute address known
END_VAR
VAR_TEMP
    tBuf     : ARRAY[0..79] OF BYTE; // temp > DBB offset known per FB call
END_VAR

BEGIN
    // No warning; static and temp are part of instance/stack frame
    BLKMOV(uParam, stData);
END_FUNCTION_BLOCK

6.2 Declare the Destination as an Explicit ANY Pointer

If you cannot change the FB static layout, force the destination to be ANY:

VAR_IN_OUT
    Param : ANY;  // explicit pointer > compiler assumes caller matches length
END_VAR

Length validation is then performed by the caller (typically a DB instance whose first bytes are the UDT). The compiler no longer emits the warning because it has a fully resolvable ANY at compile time.

6.3 Use a Wrapper DB that Holds the UDT as a Field

DATA_BLOCK dbParam
VAR
    stParam : UDT_PARAM_STRUCT;
END_VAR
BEGIN
    // source > dbParam.stParam size matches source length
    BLKMOV(uParam, dbParam.stParam); // no warning; absolute offset resolvable
END_DATA_BLOCK

This is the pattern that most cleanly preserves the FC interface while keeping data persistence.

6.4 Replace BLKMOV with Serialized Field Copies (Last Resort)

For UDTs whose size is dynamic (e.g., ARRAY[*] or STRING with ANY-like boundaries), consider per-field assigns or a loop with MOVE_BLK_VARIANT on S7-1500:

MOVE_BLK_VARIANT(SRC := uSrcAny, DST := stDst, COUNT := uCount, RET_VAL := iRet);

7. Implementation Examples in SCL, LAD, and FBD

7.1 SCL (Structured Control Language) Pattern

// SCL in TIA Portal V18
FUNCTION "fcCopyToUdt" : Void
{ S7_Optimized_Access := 'TRUE' }
VAR_INPUT
    iSrcAny : ANY;
END_VAR
VAR_IN_OUT
    ioDst   : ANY; // length matches UDT, address must reference UDT
END_VAR
VAR_TEMP
    tDiag   : WORD;
END_VAR
BEGIN
    BLKMOV(srcblk := iSrcAny, dstblk := ioDst, ret_val := tDiag);
    IF tDiag <> W#16#0 THEN
        // raise diagnostic, do not trip CPU
    END_IF;
END_FUNCTION

7.2 LAD/FBD Wiring with SFC20

Place SFC20 on a network and assign:

Pin Source example Destination (FB static)
SRCBLK P#DB20.DBX0.0 BYTE 80 n/a
DSTBLK n/a P#DB100.DBX0.0 BYTE 80 (must equal UDT size)
RET_VAL n/a MW200 (WORD)

7.3 S7-1500 Native Move Block

Drag the Move block instruction onto the network, configure SRCBLK and DSTBLK as Variant tags, and the instruction will accept symbolic UDT references without warning as long as the destination is a typed variable in a known DB, FB static, or tag.

8. Error Code W#16#837F and Runtime Diagnostics

When the destination ANY is later truncated at runtime (for example because the UDT was renamed and the offsets changed in TIA Portal), BLKMOV writes W#16#837F into RET_VAL. Other relevant codes:

Code Meaning Diagnostic action
W#16#0000 No error None.
W#16#8091 Source area exceeds the assigned area Check SRCBLK length vs DB size.
W#16#8092 Destination area exceeds the assigned area Check DSTBLK length vs UDT/DB size.
W#16#837F Source/destination pointer invalid or inconsistent Re-pass both ANY pointers; verify DB exists.
W#16#80A1 DB not loaded (cross-DB access) Verify DBNUM in ANY against current runtime DB list.

For S7-400 V4 CPUs, W#16#837F may be raised if a forced or unlinked DB is referenced. The exact message catalog lives in the Siemens support entry 109011420.

9. Migration Considerations from STEP 7 V5.x to TIA Portal

  1. Convert all FCs containing BLKMOV with UDT destinations to FB wrappers. The simplest migration path is to wrap the FC call inside a new FB that owns the UDT as static data.
  2. Re-verify ANY lengths. TIA Portal enforces byte alignment and may flag P#DB20.DBX0.0 BYTE N cases where N differs from the UDT size.
  3. Update HMI references. If the UDT was renamed or its fields reordered, refresh HMI tag DBs after the migration.
  4. Audit cross-references. Use Project tree > Cross-references to find every call site of the migrated block and confirm no legacy FCs still pass raw UDTs.
  5. Run an online/offline compare on a test CPU before production rollout.

10. Best Practices and Field-Proven Patterns

  • Prefer FB static or DB-typed destinations. They give the compiler an address to encode in ANY at call time.
  • Document the ANY length rule. Add a comment block on every wrapper FC stating the expected source bytes per UDT.
  • Use symbolic names. Pass P#"DB_Param"."stParam" instead of P#DB100.DBX0.0 BYTE 80 so renames do not break the link.
  • Validate RET_VAL on every call until the program is signed off; remove the check only after a project-wide review.
  • Centralize BLKMOV calls in one FB per logical subsystem to make future refactors easier.
  • For S7-1500, use the native Move block / MOVE_BLK_VARIANT instructions rather than legacy SFC20 unless you have a documented S7-300 compatibility reason.

11. Verification and Commissioning Checklist

  1. Compile the project and confirm there are no entries with text "length of an ANY pointer".
  2. Open the block online; observe RET_VAL after one scan cycle. It must be W#16#0000.
  3. Inspect the destination DB with Monitor/Modify; the first byte of the UDT field should reflect the first source byte copied.
  4. Introduce a deliberately oversized source ANY in a test instance; verify that the CPU returns W#16#8091 or W#16#837F rather than crashing OB121.
  5. Document the ANY/UDT length contract in the program comments and the Functional Specification.
Safety-relevant code. SIL-rated F-CPU programs may not use BLKMOV to copy data between fail-safe and standard DBs without an explicit fault-tolerant wrapper. Verify against the latest F-CPU Safety Manual before deploying.

FAQ

Why does TIA Portal raise a warning when BLKMOV uses a UDT destination?

The compiler cannot determine the absolute byte offset of a UDT that is not bound to a Data Block, FB static, or temporary area, so it cannot statically validate the destination ANY pointer length. Wrap the UDT in an FB static or a DB field, or declare the parameter as ANY.

Does the warning mean the program will malfunction at runtime?

No. The block executes, but RET_VAL may surface a runtime error such as W#16#837F if the source and destination lengths are not equal. Always evaluate RET_VAL during commissioning and consider promoting warnings to errors for production compiles.

What is the difference between BLKMOV on S7-300/400 and S7-1500?

S7-300/400 use SFC20 with explicit ANY pointers. S7-1500 uses a native Move block that accepts Variant tags. Both share the error codes W#16#837F, 8091, and 8092; see Siemens TIA Portal V20 Help for the S7-1500 behavior.

Can I suppress the warning without refactoring the block?

Yes. In Project > Settings > Compiler, you can demote specific warnings to informational or turn off the relevant class. The warning stays out of the build log but is documented in the compiler log; this is acceptable for legacy blocks you do not intend to maintain.

Why does the warning disappear when I compile in an FB instead of an FC?

FBs own an instance DB and a static layout, so the compiler can resolve the destination ANY to a concrete byte offset. FCs lack persistent memory, which leaves the UDT address unresolvable at compile time. Promoting the destination to an FB static is the recommended fix.

Back to blog