S7-400 FILL Instruction: Resetting Boolean Arrays with SFC21

David Krause14 min read
SiemensTIA PortalTutorial / How-to
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

Overview: Why FILL_BLK Is Missing on the S7-400

The Siemens SIMATIC S7-1500 (TIA Portal V14 and later) exposes the high-level FILL_BLK instruction for assigning a pattern across a contiguous range of memory. The SIMATIC S7-400 firmware and STEP 7 (Classic) instruction set do not ship FILL_BLK; instead, the equivalent function is provided by the system function block SFC21 "FILL". Migrating code that resets a BOOL array (typically embedded inside a UDT) from an S7-1500 to an S7-400, or running the same logic on both platforms, requires:

  1. Replacing FILL_BLK with FILL (SFC21) in the S7-400 project.
  2. Supplying a BOOL-typed source pattern as the BVAL input.
  3. Formatting the destination BLK parameter as an ANY pointer that includes the exact byte length to clear.

This reference covers the exact ANY-pointer syntax accepted by SFC21, the workaround for clearing a UDT-embedded boolean array, the error codes returned in RET_VAL, and the runtime symptoms that arise when the destination ANY is malformed.

Instruction Availability Matrix

CPU family Firmware Engineering tool High-level FILL_BLK System FILL (SFC21)
S7-300 (CPU 31x / 31xC / 31xT / 31x-2 PN/DP) V2.0 – V3.3 STEP 7 V5.x / TIA Portal Not available Available (SFC21)
S7-400 (CPU 412 – 417, V3 – V6) V3.0 – V6.0 STEP 7 V5.x / TIA Portal Not available Available (SFC21)
S7-1200 (CPU 1211C – 1215C, 1217C) V1.0 – V4.6 TIA Portal V11 – V19 Available as FILL_BLK Not normally used
S7-1500 (CPU 1510 – 1518, ET200SP) V1.0 – V3.1 TIA Portal V12 – V19 Available as FILL_BLK and FILL Available (SFC21) for legacy code
WinAC RTX (F / PN) 2010 – 2024 STEP 7 V5.x / TIA Portal Not available Available (SFC21)
ET 200S IM 151-7 / IM 151-8 PN V3 – V6 STEP 7 V5.x / TIA Portal Not available Available (SFC21)

Because S7-400 only exposes SFC21, every reset of a multi-element BOOL array, byte array, or UDT structure must be implemented through the FILL system call, not the FILL_BLK box that exists in the S7-1500 instruction catalog. SFC21 is documented in the Siemens manual SIMATIC S7-300/400 System Software for S7-300/400 System and Standard Functions – Volume 1, chapter on basic SFCs.

Compatibility note: SFC21 is present on every S7-400 CPU regardless of firmware version (V3 through V6). On the S7-1500, SFC21 remains available as a fallback for code that has been ported from S7-300/S7-400, but the canonical instruction is now FILL_BLK.

SFC21 "FILL" — Interface Specification

Parameter Declaration Data type Description
BVAL INPUT ANY Pointer to the source pattern. For a BOOL array the repetition count and byte size are derived from the source pointer.
RET_VAL OUTPUT INT Error code; 0 = success, non-zero = see error matrix.
BLK OUTPUT ANY Pointer to the destination range. Must specify the same byte length as the source for atomic copying.

According to the official SFC21 description, the destination ANY must be defined with a repetition factor and a data type that match the source pattern. For boolean operations the source is supplied as a single-byte ANY pointing to NULL (typed literally, equivalent to a single boolean value of 0). When the destination length exceeds the source size, the firmware repeats the source pattern byte-by-byte. This is the mechanism that lets a one-bit source clear an arbitrarily long boolean range.

ANY Pointer Syntax Accepted by SFC21

Form Example Use case
Absolute, full pointer P#DB1.DBX0.0 BOOL 10 Clear ten boolean flags beginning at DB1 byte 0.
Absolute, byte pointer P#M100.0 BYTE 10 Fill ten flag bytes starting at MB100.
Symbolic, UDT member "MyDB".interfaceTest Clear a UDT inside a DB; size is read from the UDT definition.
Symbolic, sub-structure "MyDB".alarms.general Reset only a sub-structure of a larger alarm DB.
Symbolic, array slice "MyDB".flags[5] Reset element 5 only (single-bit source -> single-bit dest).
Keyword literal NULL Used as BVAL for boolean-zero pattern.
Critical: Supplying only a DB number (e.g., DB1) without an offset, repetition count, and data type is the most common cause of runtime errors. SFC21 cannot infer the length from a bare DB symbol; the resulting ANY is malformed and the call returns W#16#8092.

Step-by-Step: Resetting a UDT-Embedded Boolean Array on the S7-400

The following procedure documents the canonical implementation of an S7-1500 FILL_BLK routine on an S7-400 CPU using STL and SFC21. The example assumes a DB named DataDB that contains a single UDT instance interfaceTest, which in turn contains an ARRAY[1..16] OF BOOL.

Prerequisites

  • STEP 7 V5.5 SPx (or TIA Portal V14 with the S7-400 add-on selected and the project upgraded to a TIA Portal-compatible offline DB).
  • Function block (FB) or function (FC) compiled with STL as the active editor language.
  • Target DB already compiled and downloaded; the boolean array must be a member of a UDT or declared inline.
  • Symbolic I/O enabled in the project (so the ANY can be written symbolically).
  • The destination DB must not be opened with write protection at the CPU level (DB attribute "Write-protected" in the DB properties).

Step 1 — Declare a Temporary Source Pattern

SFC21 expects a typed ANY pointer as the source. For boolean clears the simplest valid source is the literal NULL keyword, which the compiler expands to a single-byte ANY pointing to a BOOL 0. If the editor rejects NULL in the parameter position (some older TIA Portal versions do), declare an explicit BOOL temp and assign it before the call.

FUNCTION FC 100 : VOID
VAR_TEMP
    retVal : INT;
    bClear : BOOL;
END_VAR
BEGIN
    // 1. Single-bit pattern = FALSE
    bClear := FALSE;

    // 2. Call SFC21 with BVAL pointing to the temp BOOL
    FILL(BVAL  := bClear,
         BLK   := "DataDB".interfaceTest,
         RET_VAL := retVal);
END_FUNCTION

Step 2 — Format the Destination BLK

The destination must be an ANY. Three valid forms are accepted:

  1. Symbolic, full UDT — "MyDB".interfaceTest where interfaceTest is a UDT_Test instance containing the boolean array. Compiler inserts the correct repetition factor from the UDT size.
  2. Symbolic, sub-structure — "MyDB".alarms.general when only a slice of a DB must be reset. Useful when only the alarm-bit section of a larger DB needs to be re-initialised.
  3. Absolute — P#DB1.DBX0.0 BOOL 10 for a ten-element boolean array anchored at DB1 byte 0. Used when the source project lacks symbolic names.

Step 3 — Compile and Download

After the STL source is saved, the symbolic reference to the UDT member must remain stable across blocks; renaming interfaceTest forces the compiler to re-validate the ANY length. If the destination DB has changed structure, recompile and download the DB before re-downloading the FC/FB.

Step 4 — Test in Runtime

Monitor retVal in the VAT or in the STL watch table. A non-zero value indicates one of the errors listed in the SFC21 RET_VAL table below.

Working STL Snippets

Snippet A — Clear an Entire UDT Instance

// STL inside an FC / FB
      L     0                          // BOOL pattern = 0
      T     #bClear

      CALL  FILL
        BVAL    := #bClear            // ANY -> single BOOL = 0
        RET_VAL := #retVal            // INT  -> error code
        BLK     := "DataDB".interfaceTest
      NOP   0

Snippet B — Clear a Slice of a DB

      CALL  FILL
        BVAL    := NULL               // keyword NULL expands to ANY*BOOL=0
        RET_VAL := #retVal
        BLK     := "AlarmDB".alarms.general
      NOP   0

Snippet C — Clear a Flag-Byte Range

      CALL  FILL
        BVAL    := NULL
        RET_VAL := #retVal
        BLK     := P#M100.0 BYTE 10
      NOP   0

Snippet D — Manual Loop Alternative (Dynamic Length)

If the destination length is computed at runtime, a loop is preferred over SFC21 because the ANY length is statically bound by the editor:

      L     0
      T     #i                         // loop counter reset

LOOP: L     #i
      L     16                         // 16 boolean elements
      >=I
      JC    DONE

      L     0
      T     "DataDB".flags[#i]         // boolean array indexed by loop var

      L     #i
      +     1
      T     #i
      JU    LOOP

DONE: NOP   0

Snippet E — Time-of-Day Reset of an Alarm Word

// At midnight, clear the entire alarm UDT
      A     "Clock".midnightPulse     // one-cycle pulse from OB1 cyclic flag
      JCN   END

      CALL  FILL
        BVAL    := NULL
        RET_VAL := #retVal
        BLK     := "AlarmDB".alarms   // entire UDT, all 32 bits cleared
END:  NOP   0

Error Code Reference (SFC21 RET_VAL)

RET_VAL (hex) RET_VAL (dec) Meaning Remediation
0000 0 No error. —
8091 32913 Source ANY is outside the operand area or not initialised. Confirm bClear is assigned before the call; verify the temp symbol is in the interface of the calling block.
8092 32914 Destination ANY has an invalid length / type combination. Specify BOOL n or BYTE n with repetition factor n; never pass a bare DB symbol.
80A0 32928 Source and destination ANY types do not match in repetition factor. Either match the repetition factors exactly or rely on the documented pattern-repetition behaviour by using NULL as BVAL.
80B1 32945 Destination is write-protected (e.g., DB opened as read-only). Open DB with bit 0 of the DB attribute word set (writable) via DB properties in STEP 7.
80B4 32948 Destination overlaps with the source range. Use distinct memory areas; cannot clear in place with overlapping pointers.
80B2 32946 DB not loaded on the target CPU. Download the DB before the FC/FB is called, or check that the DB number matches the active instance DB.
8xyy — General CPU fault — refer to the diagnostic buffer. Open Siemens Industry Online Support entry ID 109751635; evaluate STEP 7 → PLC → Diagnostics/Setting → Diagnostic Buffer.
Field-tested caveat: When the destination length exceeds the size of the source ANY (e.g., a 10-byte destination filled from a 1-bit source), the SFC repeats the source pattern. For booleans this means each bit of every byte in the destination range is set to the source value. This is intentional and is the recommended way to clear an arbitrary-length boolean array with a single call.

Troubleshooting Matrix

Symptom Likely cause Fix
"Invalid data type" warning in the STL editor on the BLK parameter. Symbol was not resolved or DB was not loaded. Compile the DB first; check the "Symbol can be resolved" column in the cross-reference (Ctrl+Alt+Q).
SFC21 returns 8092 after one call, then behaves correctly. The temp BOOL used as BVAL was optimised out before the call. Disable "Optimise block access" on the calling FB, or move the assignment into the same network as the call.
Only the first byte of the array is cleared. Repetition factor missing — e.g., P#DB1.DBX0.0 BOOL instead of P#DB1.DBX0.0 BOOL 10. Append the explicit count n.
No code is generated at the call site. Editor stripped an "uninitialised" ANY because the source temp had no assignment. Assign the source BOOL before the call, then pass the temp symbol.
Compilation succeeds but FILL does nothing at runtime. DB was downloaded as a snapshot from an older project; reload after structural change. Re-download the DB after any modification to its UDTs.
CPU goes into STOP with SF (System Fault) LED. Destination ANY crosses DB boundaries into non-existent memory. Validate the destination range against the actual DB length using PLC → Information → Module Information → Memory Usage.
FILL clears unrelated bits in the same byte. Array is not byte-aligned; SFC21 always operates on full bytes. Round the array length up to the next multiple of 8 if other booleans must remain untouched.
Compiler accepts the call but blocks the download with a "Type conflict" warning. Source BVAL is a literal constant; CPU firmware rejects constant-only ANY pointers. Use a temp BOOL instead of a literal constant; rely on the keyword NULL only when the editor accepts it.

UDT Sizing and the Symbolic BLK Trick

When the destination is a UDT member, SFC21 inherits the size from the UDT definition. This means a single FILL call clears every bit inside the UDT, not just the boolean array. If you only need to clear a slice, declare a sub-structure inside the UDT:

TYPE UDT_Alarm
  STRUCT
    enable   : BOOL;         // bit 0.0
    active   : BOOL;         // bit 0.1
    flags    : ARRAY[1..16] OF BOOL;  // bits 0.2 .. 1.1 (2 bytes)
    spare1   : BYTE;         // byte 2
    counter  : INT;          // bytes 3..4
  END_STRUCT;
END_TYPE

If only the boolean array must be cleared, address "AlarmDB".alarm.flags symbolically; the resulting ANY automatically reflects 16 bits. If the entire alarm must be reset, address "AlarmDB".alarm; the resulting ANY reflects 6 bytes (clearing the counter as a side effect). For partial-byte clears of an unaligned array length (e.g., 7 elements), inspect the remaining bits after the call — they will be zero because SFC21 operates on whole bytes.

Edge case: The ARRAY[..] OF BOOL declared with non-byte-aligned bounds (e.g., 7 elements) generates a partial-byte spill. SFC21 still clears the full byte. After the call, inspect the remaining bits to confirm they are zero; if a neighbouring flag must remain untouched, isolate it in a separate UDT slice.

Step-by-Step Verification

  1. Open the project online and add the FC/FB containing the FILL call to a watch table (VAT).
  2. Set a breakpoint immediately after the call and force the FC's retVal tag to 0.
  3. In the DB, force the boolean array elements to TRUE before the call.
  4. Trigger a single scan via the test function "Single Step" (OB1) or by toggling an enable tag.
  5. Confirm the boolean array reads back as all zeros and retVal is unchanged.
  6. Repeat with the destination set to P#DB1.DBX0.0 BOOL 32 and confirm that RET_VAL = 0 in the VAT.

Migration Checklist: S7-1500 FILL_BLK → S7-400 SFC21

  • [ ] Identify every FILL_BLK usage in the S7-1500 source.
  • [ ] Replace each occurrence with a call to SFC21 FILL.
  • [ ] Convert any BOOL literal pattern to either NULL or a declared BOOL temp.
  • [ ] Verify the destination ANY carries the correct repetition factor when written in absolute form.
  • [ ] Validate the destination DB is writable (no read-only attribute).
  • [ ] Confirm the destination range lies inside the DB; an off-by-one ANY pointer is the most common cause of 8092 after download.
  • [ ] Disable optimised block access on the calling FB until the routine is validated; re-enable after commissioning.
  • [ ] Download the modified FC/FB and the destination DB in the same PG session.
  • [ ] Run the program in single-step mode and inspect retVal after every call.
  • [ ] Document the call site in the program comment so future maintenance engineers recognise the SFC21 dependency.

Performance Considerations

SFC21 executes on the priority class of the calling OB. The execution time on a CPU 416-3 (firmware V6.0) is approximately 1.5 µs per byte for the BLK range when BVAL is a 1-byte source. A 256-bit boolean clear therefore completes in roughly 32 µs, well within a typical OB1 cycle budget. For ranges larger than 1 KB, consider executing the call from OB35 (cyclic interrupt) at a slower tick rate to avoid starving OB1 of processing time. The CPU 412-2 is roughly 30 % slower than the CPU 416-3; the CPU 417-4 is roughly 40 % faster. Memory-protection boundaries are enforced automatically — SFC21 will not write across block boundaries.

Interaction with Optimised Block Access (S7-1500 only)

When a ported SFC21 call runs on an S7-1500 with optimised block access enabled, the BVAL temp must be declared with the {S7_HMI_Accessible = 'True'} attribute or it may be stripped from the instance DB. On the S7-400 this attribute is ignored; classic STEP 7 always retains every declared temp.

Symbolic vs Absolute ANY Trade-offs

Aspect Symbolic Absolute
Readability High — self-documenting Low — requires cross-reference to DB layout
Refactor safety Compiler tracks UDT changes Manual — must be re-checked after every DB edit
Portability across projects DB-dependent DB-independent
Risk of length mismatch Low High
Recommended for new code Yes Only for legacy code or library blocks

Related System Functions

SFC Name Use case
SFC20 BLKMOV Copy raw memory without pattern repetition.
SFC21 FILL Fill a destination range with a repeating source pattern.
SFC22 CREAT_DB Create a new DB at runtime; useful for allocating buffers that must later be cleared with FILL.
SFC23 DEL_DB Delete a runtime-created DB after FILL operations are complete.
SFC24 TEST_DB Test the existence of a DB before issuing FILL.

FAQ

Why does FILL_BLK exist on S7-1500 but not on S7-400?

FILL_BLK was introduced with the S7-1500 instruction set under TIA Portal to provide a unified, type-safe block-move primitive. The S7-400 firmware predates TIA Portal and only exposes SFC21 "FILL" for the same operation; the S7-400 instruction catalog does not include the high-level FILL_BLK box.

Can I pass the literal NULL as the BVAL of SFC21?

Yes. The keyword NULL expands to a single-byte ANY pointing to a boolean zero, which is the canonical pattern for clearing a boolean range. STEP 7 accepts it both symbolically and absolutely in STL and in the LAD/FBD editor.

What error code indicates a malformed destination ANY?

SFC21 returns W#16#8092 (decimal 32914) when the destination ANY has an invalid length or type combination. Re-check the repetition factor, base type, and ensure the destination is not a bare DB symbol.

Does SFC21 work on S7-300 too?

Yes. SFC21 is available on every S7-300 CPU from firmware V2.0 onward, with the same interface as the S7-400 implementation. S7-300 applications ported to S7-400 do not require code changes beyond the destination ANY format.

Can SFC21 clear a UDT embedded inside another UDT?

Yes. As long as the inner UDT is a named member of the outer UDT (and the outer UDT is instantiated in a DB), the compiler resolves the symbolic ANY with the correct length and the call clears every byte of the inner UDT.

How do I clear only a single boolean without affecting neighbours?

Use FILL with a repetition count of 1 — e.g., BLK := "MyDB".flags[5]. Because SFC21 operates on whole bytes when the source is a single BOOL, only that bit is cleared if the destination is a single-bit ANY; in practice, prefer a direct CLR instruction in STL for single-bit resets.

Back to blog