Problem Description
When compiling STL, FBD, or LAD logic in TIA Portal V13 / STEP 7 V13 against an S7-300 (or compatible S7-400) CPU, the compiler emits the diagnostic "The address is not occupied by a tag". The message is treated as a warning, not an error, so the program still loads, runs, and exchanges I/O — but the message pollutes the compile output, blocks clean builds in CI pipelines, and frequently indicates that the FB/FC is touching local stack (L-stack) memory that was never explicitly declared in the block interface.
Typical triggers observed in the field:
- Direct
L 0.0,L 20.0operand references inside an FC or FB without a matchingTempdeclaration. - Migrated legacy STEP 7 V5.x code that used absolute L-stack addresses for scratch storage.
- Code pasted from a third-party library where the original block interface was stripped.
- Use of the old
OPN %DB10/DBW0pair without an explicitL %DB10.DBW0prefix in the network.
Symptom signature in the inspector window:
[Warning] Block FC100 / Network 7
The address is not occupied by a tag.
Operand: L0.0
Block: FC100 - "Calc_Phase"
Why the Warning Exists
The TIA Portal V13 compiler enforces IEC 61131-3 symbolic consistency on the S7-300/400 platform. Every memory operand in a code block should resolve to a declared symbol in one of three interface sections:
| Section | Scope | Persisted? | Indexed? |
|---|---|---|---|
Input |
Caller-supplied | No | By name only |
Output |
Caller-visible | No | By name only |
InOut |
Caller-supplied & visible | No | By name only |
Static (FB only) |
Instance DB-backed | Yes (in instance DB) | Yes, via multi-instance or ARRAY |
Temp |
Local stack (L-stack) | No — cleared each call | Yes, via temporary variables |
Constant |
Read-only literal | No | No |
When the compiler encounters an operand such as L0.0, it has no symbol to map to, so it raises the warning. The address is technically valid on the CPU — the L-stack is always present and addressable from 0.0 through the configured local data size (default 256 bytes on S7-300 CPUs) — but the absence of a declaration means the compiler cannot type-check, optimize, or warn about overlap with neighboring temporary variables. This is the exact failure mode the warning is designed to catch.
L0.0 without coordination, runtime data corruption occurs. The warning is your only static-analysis hint that this risk exists.Affected Versions and Platforms
| Controller | Effect | AT overlay support | Slicing support |
|---|---|---|---|
| S7-300 (all MLFBs) | Warning present, no IEC 61131-3 check bypass for L-stack | SCL only, local-scope only | Not available |
| S7-400 | Warning present, IEC check is configurable per block | SCL only, local-scope only | Not available |
| S7-1200 / S7-1500 | Warning is normally absent because absolute L addressing is disallowed at the editor level | Full SCL scope | Full slice support ("Tag".%X0) |
| ET 200SP / ET 200MP CPUs | Same as S7-1500 line | Full SCL scope | Full slice support |
Confirmed in TIA Portal V13.0, V13.1, and the V13.1.4 service pack — the warning is generated even when the project option IEC checks is deselected at the block properties. It is not a per-block toggle.
Root Cause Analysis Flow
- Open the Inspector > Compile tab and double-click the warning line. TIA Portal highlights the offending network and operand.
- Right-click the block in the project tree and select "Go to > Block interface".
- Switch to the Temp row. Confirm whether any
Tempvariable is defined. - If empty, the absolute operand is the cause. If a temp exists, verify the symbol is used (not the absolute address) in the code.
- For migrated V5.x code, compare the V5.5 AWL source against the TIA import. The importer does not generate
Tempdeclarations for raw L-stack references.
Solution 1 — Declare a Temp Variable (Recommended)
The cleanest fix is to give every L-stack operand a symbolic home. Open the block interface, scroll to Temp, add a new row, and select a type that matches the operand width.
- Open the FC/FB editor in TIA Portal V13.
- In the interface pane, click the Temp section header.
- Insert a new row, e.g.
Name: PhaseFlag,Data type: Bool. - Compile the block. The compiler assigns the variable to offset 0.0 by default.
- Replace every literal
L 0.0reference in the code with the symbol#PhaseFlag. - Recompile — the warning disappears.
// Before (raises warning)
A L 0.0
= L 0.0
// After (clean compile)
A #PhaseFlag
= #PhaseFlag
WORD temp may not overlay the bits the legacy code expected.Solution 2 — Use the AT Construct in SCL
For blocks authored in SCL, the AT overlay lets a derived view reinterpret the byte layout of an existing variable. This is the only way on S7-300/400 to obtain a sliced view, and the overlay is local to the block — it cannot be exported.
FUNCTION_BLOCK "FB_TempOverlay"
VAR
RawWord : WORD; // Static, persisted in instance DB
END_VAR
VAR_TEMP
AT_View : AT %DB."FB_TempOverlay".RawWord : ARRAY[0..1] OF BOOL;
END_VAR
BEGIN
// AT_View[0] corresponds to bit 0 of RawWord
AT_View[0] := TRUE;
END_FUNCTION_BLOCK
Reference documentation for the AT construct and the S7-300/400 limitations is the Siemens FAQ "How do you program the overlapping of tags with the keyword AT in the TIA Portal?" (entry ID 57132240).
Solution 3 — Apply the Global Message Filter
If the warning is deemed acceptable (e.g. during migration cleanup), it can be suppressed globally through the message filter. TIA Portal V13 does not expose a per-message toggle, so this silences every warning of the same category.
- Compile the block.
- In the Inspector > Compile tab, right-click the warning row.
- Select "Filter messages of this type" — or click the yellow exclamation mark icon in the toolbar to open the full filter dialog.
- Uncheck "Warning" to hide all warnings, or expand the category and deselect the specific Address rule.
- Confirm with OK and recompile.
Solution 4 — Restructure Absolute L-Stack Usage
For long-standing legacy blocks where the original programmer intended raw scratch memory, restructure into a typed temp block:
FUNCTION "FC_Scratch" : VOID
VAR_TEMP
tByte0 : BYTE; // offset 0.0 - 0.7
tByte1 : BYTE; // offset 1.0 - 1.7
tWord0 : WORD; // offset 2.0 - 3.7
tBool0 : BOOL; // bit inside tByte0 if needed
bFlag AT %LW2 : BOOL; // overlay view in SCL only
END_VAR
BEGIN
// tByte0, tByte1, tWord0 are now symbolic
END_FUNCTION
This pattern is the recommended migration path for AWL code imported from STEP 7 V5.5. After the restructure, no L-stack address is referenced literally, and the IEC check can be re-enabled.
Solution 5 — Replace OPN DB / DBW0 Pairs
A second common warning in migrated code is the use of OPN %DB10 followed by L DBW0. Replace with a fully-qualified operand:
// Legacy pattern (raises warnings in TIA V13)
OPN %DB10
L DBW0
T %MW100
// TIA-clean replacement
L %DB10.DBW0
T %MW100
The fully-qualified form is the only one the V13 STL editor accepts without warning. The DB must be present in the project, compiled without error, and not in "Unlinked" state.
Verification
- Right-click the program blocks folder → Compile > Software (rebuild all).
- Open Inspector > Compile. The warning list should show 0 entries for the affected block.
- Download the project to the S7-300 CPU (or PLCSIM) and perform an online → Compare to confirm block consistency.
- Force the affected tag in a watch table and toggle the value. The CPU should accept the write without SF / BF diagnostic LEDs.
- Open Online & Diagnostics > Diagnostic buffer and verify no OB121 (programming error) or OB122 (I/O access error) entries appeared during the test cycle.
Edge Cases and Field Caveats
Multi-instance FBs. Inside a multi-instance FB, the compiler reserves static memory in the parent instance DB. Absolute L-stack addressing inside such a block almost always indicates a bug — the developer likely intended a Static member. Replace with #Instance.MyVar where MyVar is declared under Static.
Library blocks compiled against a different firmware. If a library FC was compiled on TIA V15 and is being used in a V13 project, the warning may be persistent in V13 even though V15 suppresses it. Compile the library from source in V13 to regenerate the block with a V13-compatible symbol table.
Know-how-protected blocks. If you cannot edit the block interface, the message filter is the only static option. Alternatively, replace the protected block with a copy whose interface you can edit.
Optimized vs. standard block access. The S7-300/400 platform uses standard access only. There is no optimized bit/byte/word overlay in the same sense as S7-1200/1500, so the AT construct is the sole method to project a typed view onto the same memory.
Local data size overflow. If the S7-300 CPU is configured with a local data size smaller than the temp footprint of a deeply nested call chain, the CPU will enter STOP with OB121 (length error when reading/writing local data). The compiler warning is the pre-emptive indicator — address it before deployment, not after the first STOP.
Troubleshooting Matrix
| Symptom | Likely Cause | Fix |
|---|---|---|
| Warning persists after adding a Temp row | Block was not recompiled (incremental compile) | Right-click block → Compile → Software (rebuild all) |
| Warning reappears after every project save | Auto-generated code from a library or HMI tag is using L-stack | Open the referenced library, restructure per Solution 4 |
| Warning only on FB, not FC | Compiler treats Static differently from Temp
|
Move the L-stack operand into the Static section (instance DB-backed) |
| Warning disappears in V14+ but remains in V13 | Compiler rule was relaxed in V14 | Upgrade project or accept the warning in V13 |
| IEC check is disabled but warning still shows | This rule is not gated by the IEC check flag | Use Solution 1 or Solution 3 |
| OB121 / OB122 in diagnostic buffer | Local data size exceeded or undeclared L-stack overflow | Increase Local data size in CPU properties → Cycle |
Best Practices Going Forward
- Author new logic in SCL where possible. The editor blocks absolute L-stack addressing at source level.
- For STL blocks, set the project option "Warn when address is not occupied by a tag" to Error via the project properties if your engineering rules require clean builds.
- When importing V5.x projects, run the "Migration cleanup" pass that converts absolute temporaries to typed symbols. This is part of the standard TIA migration wizard.
- Reserve AT overlays for the rare cases where byte-level reinterpretation is genuinely required (e.g. status word packing). Never use them as a substitute for a typed interface.
Can the "address is not occupied by a tag" warning be turned off for a single block in TIA Portal V13?
No. TIA Portal V13 does not expose a per-block or per-message filter for this rule. The only static options are declaring a matching Temp variable (Solution 1) or using the global message filter, which silences every warning of the same category across the project.
Does the AT construct work on S7-300 CPUs in TIA Portal V13?
Yes, but only inside an SCL block and only for locally-scoped overlays. The AT view cannot be exported to the block interface or to OPC, and the underlying variable must reside in the instance DB (Static) or in the L-stack (Temp). See Siemens FAQ 57132240 for the full matrix.
Why does the warning persist even with IEC checks disabled on the block?
The "address is not occupied by a tag" rule is enforced at the compiler core, not the IEC 61131-3 check layer. Toggling IEC checks in the block properties relaxes type-compatibility rules but does not change the operand-to-symbol mapping requirement. The only way to suppress it is a Temp declaration or the global filter.
Is the warning related to an OB121 programming error at runtime?
Not directly. The warning is a compile-time signal that the operand is undeclared; the CPU will still execute the absolute L-stack read/write. However, if the call chain's temp footprint exceeds the CPU's configured local data size, the runtime will enter STOP with OB121, and this warning is the pre-emptive hint that the footprint is too large.
Can migrated STEP 7 V5.x AWL code be cleaned up automatically?
Partially. The TIA migration wizard imports AWL source verbatim and does not generate Temp declarations for raw L-stack references. Use the restructure pattern in Solution 4 to convert each absolute operand to a typed Temp row, then recompile. There is no bulk "auto-declare" tool, so the cleanup is manual but straightforward for blocks with fewer than ~20 L-stack references.