Siemens BLKMOV: Symbolic Copy of Partial BOOL Array in STEP 7

David Krause12 min read
HMI ProgrammingSiemensTechnical Reference
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

Siemens BLKMOV: Symbolic Copy of a Partial BOOL Array in STEP 7

1. Overview

Engineers moving alarm or status bitfields between data blocks frequently hit a hard constraint in STEP 7: BLKMOV (FC20/FC21/SFC20 BLKMOV and the SCL/STEP 7 V15+ instruction MOVE_BLK) operates on a byte-granular source/destination area, not on individual bits. When the source is a ARRAY[0..31] OF BOOL and the target requires only the first eight bits, neither a fully symbolic call nor a partial symbolic slice is accepted by the editor in the S7-300 toolchain. The classic work-around uses an absolute pointer such as P#DB1802.DBX44.0 BYTE 8, which couples the call to a fixed DB number and byte offset and breaks every time the upstream block is recompiled or restructured.

This reference documents the underlying mechanics, the S7-300 versus S7-1200/S7-1500 behavior delta, and five production-proven workarounds that keep the source fully symbolic:

  1. SCL AT-view overlay on a byte/word array
  2. STL ANY-pointer assembly with symbolic DB and runtime offset
  3. Wrapper FC/FB with IN_OUT of a byte-array slice
  4. SFC20 BLKMOV with pointer math from AR1 / AR2
  5. Bit-shifting into a WORD / DWORD staging buffer

2. BLKMOV Mechanics and the ANY-Pointer

Both the legacy STL BLKMOV in the S7-300 standard library and the S7-1500 MOVE_BLK instruction accept an ANY source and an ANY destination. The ANY pointer is 10 bytes laid out as follows:

Byte Content Meaning
0..3 10# 16# 00 00 (S7-300) or 10# 16# 00 00 (S7-1500) ID + type marker; 10 hex for S7-300 STL, sometimes 10 for TIA; 16 for full S7-1500 pointer
4..5 Length in bits or bytes (WORD) Repetition factor: byte count for non-BOOL types, bit count only for the legacy BLKMOV BOOL overload
6..7 DB number (WORD) 0 for non-DB areas; otherwise the DB number
8..9 Area code (BYTE) + byte offset high nibble 84h=DB, 81h=M, 82h=E (input), 83h=A (output), 80h=L (temp)
9..11 Byte offset (DWORD) Bit-addressable offset within the chosen area

The S7-1500 BLKMOV reference page states explicitly: "If a block of data type BOOL is moved, the tag must be addressed absolutely and the specified length of the area must be divisible by 8". This single rule is the root cause of the symbolic-failure symptom reported by the S7-315 user.

3. Why Symbolic Partial Copy of a BOOL Array Fails

STEP 7 enforces two independent rules that combine to make a symbolic slice of a ARRAY[..] OF BOOL unusable on every S7-CPU family:

  1. Byte alignment. The source length is interpreted in bytes. A request for "8 bits" is rounded up to 1 byte; the editor issues a compile error because the symbolic array slice does not carry a guaranteed byte boundary.
  2. Length divisibility. When the underlying area is declared BOOL, the length must be a multiple of 8 bits. The CALL line SRCBLK := "MyAlarm" BYTE 1 is therefore rejected even on a 1500; the length is 1 byte (= 8 bits), so the absolute form works but the symbolic short-form does not, because the compiler cannot prove that the next 7 bits after bit 0 are not allocated to a different BOOL tag in the same DB.

The compile error seen in the editor is typically 0800 0001 in S7-300 / STEP 7 V5.x ("type identification error") or LIC001 / LEN001 on TIA Portal ("length does not match the data type").

4. S7-300 vs S7-1200 / S7-1500 Behavior

Property S7-300 / S7-400 (STEP 7 V5.x) S7-1200 / S7-1500 (TIA Portal)
Instruction name FC20 BLKMOV / SFC20 BLKMOV MOVE_BLK (renamed) or legacy BLKMOV
Source/destination parameter type ANY VARIANT + length, plus ANY for STL compatibility
Symbolic BOOL slice Not allowed; absolute BYTE n only Same: "addressed absolutely" per the official S7-1500 BLKMOV manual
Length units Bytes for non-BOOL, bits only when source is BOOL array Always bytes; BOOL must be byte-aligned and multiple of 8
Symbolic full-array copy Yes (entire array passed as ANY) Yes
Symbolic partial slice (e.g. 8 of 32 bits) No No

For an S7-315 (firmware V3.3 and later) and S7-1500 firmware V2.0 / V2.5 / V2.9, the partial-copy restriction is identical. Choosing a 1200/1500 does not unlock a symbolic slice; it just changes the error-message wording.

5. Workaround 1 — SCL AT-View Overlay

The cleanest answer is to keep the symbolic BOOL array and to declare a second view over the same memory region as a byte/word array. The two declarations are guaranteed by the compiler to occupy the same offsets inside the same DB. From V5.4 SP5 of STEP 7 onward the AT construction is supported in SCL; the Siemens knowledge contribution 21946854 demonstrates the technique in detail.

Declare inside DB1802 (or a wrapper DB that uses AT on the alarm symbol):

DATA_BLOCK "DB_AlarmShadow"
  STRUCT
    b1 AT "AlarmBlock".alarm[0]  : ARRAY[0..3] OF BYTE;   // overlaps bits 0..31
  END_STRUCT;
END_DATA_BLOCK

Alternative: local AT view inside the calling SCL block:

VAR
    abAlarms : ARRAY[0..31] OF BOOL;     // populated by upstream block
    abBytes  AT abAlarms : ARRAY[0..3] OF BYTE; // shared memory, byte-granular
END_VAR

// copy first byte (bits 0..7) into a 1-byte symbolic area in DB1803
"DB_AlarmShadow".firstByte := abBytes[0];   // purely symbolic

The AT view is fully symbolic, survives any upstream restructuring of the BOOL array, and lets the engineer use MOVE_BLK with a length of 1 (or 4 for the whole alarm word). On S7-300 firmware < V3.3 the AT keyword is parsed but the compiler issues warning W:": AT-construction in instance DB not yet supported"; upgrade to firmware V3.3 or move the data to a global DB before applying this technique on a 31x CPU.

6. Workaround 2 — STL ANY-Pointer Assembly with Symbolic DB

When the goal is to call SFC20 BLKMOV with the DB name symbolic but the offset computed at runtime (e.g. from a configurable alarm-base tag), build the ANY in two TAR/LAR steps inside an FC. The same Siemens FAQ 21946854 contains the STL example reproduced below.

FUNCTION FC 100 : VOID
VAR_TEMP
    sAnySrc  : ANY;
    sAnyDst  : ANY;
    wRet     : WORD;
    diBase   : DINT;
END_VAR
BEGIN
    // --- build source ANY for 8 bits (1 byte) starting at runtime offset ---
    LAR1  ;                          // AR1 holds instance-DB base (set by caller)
    L     DBB 0 ;                    // offset-low from a symbolic byte tag
    T     LW  20 ;
    L     B#16#10 ;                  // S7-300 ANY ID
    T     LB  20 ;
    L     B#16#04 ;                  // 4 = BOOL, length unit = bit
    T     LB  21 ;
    L     8 ;                        // 8 bits = 8 bools
    T     LW  22 ;
    L     W#16#0000 ;                // DB number placeholder
    T     LW  24 ;
    // Load DB number symbolically from a WORD tag in the same DB
    L     "DB_AlarmShadow".wDBno ;
    T     LW  24 ;
    L     B#16#84 ;                  // area code DB
    T     LB  26 ;
    L     W#16#0000 ;
    T     LW  27 ;

    // destination ANY built identically from the target DB
    CALL SFC 20 (
        SRCBLK := sAnySrc,
        RET_VAL:= wRet,
        DSTBLK := sAnyDst);
END_FUNCTION

This pattern keeps the DB number and the symbolic structure under engineering control. The only "absolute" element is the byte/bit area code, which is required by the SFC itself and never changes. Offset and length can be moved to instance data so the function is reusable across projects.

7. Workaround 3 — Wrapper FC/FB with IN_OUT Byte Slice

For a clean ladder/FBD representation in the calling network, wrap the copy in a small FC whose input and output are IN_OUT ARRAY[*] OF BYTE variables typed over the same underlying memory. Inside the wrapper a single SCL MOVE_BLK call references the symbolic parameter and a constant length.

FUNCTION FC 101 : VOID
VAR_IN_OUT
    abSrc : ARRAY[0..3] OF BYTE;     // 32-bool area overlaid by AT in caller
    abDst : ARRAY[0..0] OF BYTE;     // 8-bool target area, pre-sized
END_VAR
BEGIN
    // Slice abSrc[0] into abDst. Compiler resolves abSrc[0] symbolically.
    abDst[0] := abSrc[0];
END_FUNCTION

The wrapper is fully symbolic, the call site becomes CALL FC 101 (abSrc := "DB_AlarmShadow".abBytes, abDst := "DB_AlarmTarget".abFirst). PLC code review, diffing and watch tables all read on the symbol rather than the absolute address.

8. Workaround 4 — SFC20 with AR1/AR2 Pointer Math

For high-performance applications where the call must remain in STL with multi-instance offsetting, pass the source pointer through AR1 and the destination pointer through AR2 using the "pointer to area-internal data" convention (area code 0x84 in the high byte of the low word). The Siemens AT-view contribution describes the same encoding for the ANY parameter of SFC20 and the BLKMOV legacy instruction.

LAR1  P#DBX 0.0       ; // AR1 = pointer to bit 0 of instance-DB root
+AR1  P#4.0           ; // offset to the alarm array base
LAR2  P#DBX 100.0     ; // AR2 = target area base
CALL SFC 20(
    SRCBLK := P#M 0.0 BYTE 8,  // length 8 bits must be 1 byte here
    RET_VAL:= MW 200,
    DSTBLK := P#M 10.0 BYTE 1);

Note: SFC20 does not accept a bit-length; convert the "8 BOOLs" to "1 byte" and ensure the 8 bits are byte-aligned in the source DB. This is the byte-length restriction noted on the S7-1500 BLKMOV page.

9. Workaround 5 — Bit-Shift into a WORD/DWORD Staging Buffer

If the engineer cannot change the source DB layout and is forbidden from using AT overlays (for example, on a legacy S7-300 with V5.3 SP1 or earlier where the compiler issues an error rather than a warning), serialize the eight bits into a temporary WORD by reading each bit with a U/L pattern, shifting and OR-ing into the staging word.

FUNCTION FC 102 : VOID
VAR_TEMP
    i        : INT;
    wStage   : WORD;
END_VAR
BEGIN
    wStage := 0;
    FOR i := 0 TO 7 DO
        IF "DB_Alarm".abAlarms[i] THEN
            wStage := wStage OR SHL(WORD#1, i);
        END_IF;
    END_FOR;
    "DB_AlarmTarget".wFirstEight := wStage;
END_FUNCTION

The staging WORD can then be moved with one MOVE_BLK or MOVE instruction into a WORD tag in the target DB, where the receiving ladder logic decodes the eight bits individually. This is the slowest method (eight bit reads plus a loop) but the only one that works on every CPU firmware without overlay support.

10. Workaround Comparison Matrix

Method CPU families Required firmware Fully symbolic Reusable Performance (cycle cost) Maintenance risk
SCL AT overlay S7-300 (315 V3.3+), S7-400, S7-1200, S7-1500 V3.3 / V4.0 / V1.0 Yes High 1 byte copy, ~5 µs Low — compiler tracks offsets
STL ANY assembly S7-300 / S7-400 / S7-1500 (STL) Any Yes (DB + offset tag) High ~20 µs + SFC20 Medium — manual pointer math
Wrapper FC/FB All Any Yes High ~5 µs Low — single call site
AR1/AR2 + SFC20 S7-300 / S7-400 STL Any No (P# literal) Medium ~15 µs High — multi-instance fragile
Bit-shift staging All Any Yes Medium ~50 µs (8 iterations) Low — explicit code

11. Verification and Commissioning

After applying any of the five workarounds, run the following verification sequence on the target CPU. The steps reference S7-300 firmware V3.3 / STEP 7 V5.6 and S7-1500 firmware V2.9 / TIA Portal V18; adapt the menu paths to the local engineering tool.

  1. Compile check. Trigger a full rebuild of the program. The SCL compiler must report 0 errors / 0 warnings. A residual warning such as "AT-view: identical offset not guaranteed" indicates the BOOL array is in a different DB than the overlay; resolve by moving the AT declaration into the source DB or a dedicated shadow DB with the same STRUCT address.
  2. Symbol resolution. Open the compiled program in the online view, right-click the SRCBLK operand, and confirm the displayed symbolic name matches the project symbol table. If the view shows an absolute address, the offline project is out of sync — re-download the program.
  3. Length check. Place a watch table on the source byte "DB_Alarm".abBytes[0] and on the destination byte "DB_AlarmTarget".abFirst. Force eight bits in the source and verify that the destination byte reflects them bit-for-bit.
  4. Bit-isolation regression. Force the remaining 24 bits of the source array (abAlarms[8..31]) to 1 and re-check the destination: it must still hold only the first eight bits. A failure here means the AT overlay is pointing at the wrong byte offset and is leaking into the next area.
  5. Cycle-time impact. On a 315-2 PN/DP measure OB1 cycle time with and without the BLKMOV block. A properly implemented AT-view copy should add < 0.1 ms; a misconfigured bit-shift loop can add 0.3–0.5 ms per call.
  6. Cross-DB consistency. Open the cross-reference (Ctrl+Shift+F in STEP 7) on the source symbol. Every usage must resolve to the same DB number/offset. If the cross-reference shows two different offsets, the source block was modified after the AT view was generated — re-run the compile and re-download.
  7. Retain / restart test. Cycle power to the PLC and confirm the destination byte is identical to the source. The AT view does not alter retain behavior; both sides must be in a retain-enabled DB if the data must survive a warm restart.
Safety note. BOOL arrays that drive safety logic (F-CPU F-runtime groups) are not permitted to be copied via the standard BLKMOV path. Use the F-library certified F_BLKMOV or F_I_DB move blocks from the Siemens Industry Online Support safety package and keep the F-runtime group time budget under the value listed in the F-CPU manual (typically 30 ms for S7-300F, 15 ms for S7-1500F).

12. Frequently Asked Questions

Can I move 8 bits of a 32-bit BOOL array with a fully symbolic BLKMOV call on an S7-315?

No. STEP 7 forces the BOOL source of BLKMOV to be addressed absolutely with a length that is a multiple of 8 bits. Use an SCL AT overlay, a wrapper FC/FB, or a bit-shift staging word to keep the call site symbolic.

Does upgrading from an S7-300 to an S7-1500 lift the partial-BOOL-array restriction?

No. The S7-1500 MOVE_BLK / BLKMOV instruction carries the same byte-alignment rule — "the tag must be addressed absolutely and the specified length of the area must be divisible by 8". The compiler messages differ, but the underlying requirement is identical.

What is the minimum firmware for the SCL AT overlay on an S7-300?

Firmware V3.3 on the S7-31x CPUs and STEP 7 V5.4 SP5 (or later) is required. Earlier firmware issues warning W: AT-construction in instance DB not yet supported and refuses the AT view in an FB's static area. Move the data to a global DB or upgrade the CPU firmware.

Is SFC20 BLKMOV faster than SCL MOVE_BLK for an 8-bit copy?

On an S7-315 the two are equivalent (~5 µs) because the bulk of the time is the call overhead, not the data transfer. The performance gap only matters for arrays above ~32 bytes. Pick SCL MOVE_BLK with an AT view for readability and pick SFC20 with explicit ANY assembly only when you need to compute the offset at runtime.

Where is the official Siemens documentation for the BLKMOV byte-alignment rule?

The S7-1500 BLKMOV reference page and the SCL Knowledge Contribution 21946854 together state the rule and the AT overlay pattern. For S7-300 STL behavior, the SFC20 entry in the "System and Standard Functions for S7-300/400" manual is the primary reference.

Back to blog