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:
- Replacing
FILL_BLKwithFILL(SFC21) in the S7-400 project. - Supplying a
BOOL-typed source pattern as theBVALinput. - Formatting the destination
BLKparameter 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.
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. |
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:
-
Symbolic, full UDT —
"MyDB".interfaceTestwhereinterfaceTestis aUDT_Testinstance containing the boolean array. Compiler inserts the correct repetition factor from the UDT size. -
Symbolic, sub-structure —
"MyDB".alarms.generalwhen 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. -
Absolute —
P#DB1.DBX0.0 BOOL 10for 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. |
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.
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
- Open the project online and add the FC/FB containing the FILL call to a watch table (VAT).
- Set a breakpoint immediately after the call and force the FC's
retValtag to0. - In the DB, force the boolean array elements to
TRUEbefore the call. - Trigger a single scan via the test function "Single Step" (OB1) or by toggling an enable tag.
- Confirm the boolean array reads back as all zeros and
retValis unchanged. - Repeat with the destination set to
P#DB1.DBX0.0 BOOL 32and confirm thatRET_VAL = 0in the VAT.
Migration Checklist: S7-1500 FILL_BLK → S7-400 SFC21
- [ ] Identify every
FILL_BLKusage in the S7-1500 source. - [ ] Replace each occurrence with a call to SFC21
FILL. - [ ] Convert any
BOOLliteral pattern to eitherNULLor a declaredBOOLtemp. - [ ] 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
8092after 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
retValafter 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.