Resolving STEP 7 Local Variable Search and Cross-Reference Gaps

David Krause16 min read
SiemensTechnical ReferenceTIA Portal
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: STEP 7 V5.x Engineering Gaps That Slow Service Engineers

Engineers maintaining S7-300/S7-400 programs in STEP 7 V5.x (SIMATIC Manager) routinely hit limitations that do not exist in TIA Portal V13+. The classic IDE lacks first-class cross-reference for local FB/FC variables, offers no compiler warning when a local is read before assignment, accepts a program whose I/Q range exceeds the configured Process Image Partition without warning, and ships with a Monitor/Modify tab that only edits absolute addresses when the user types them in by hand. The Where-Used dialog also stops short of tracing indirect data flow through multi-instance DBs.

This reference catalogs the documented gaps, the TIA Portal V17/V18 behavior that closes them, and field-proven workarounds for STEP 7 V5.5 / V5.6 / V5.7 projects. All examples assume an S7-300 CPU 315-2 PN/DP (6ES7315-2EH14-0AB0, firmware V3.3) or S7-400 CPU 416-3 PN/DP (6ES7416-3ES07-0AB0) with default PIP sizes. Where CPU-specific defaults matter, the relevant catalog number is listed.

Verify Project Integrity Before Debugging

Before chasing any of the issues below, confirm the project opens with the same option packages that built it. When a STEP 7 project is opened, the option packages required are automatically checked. Missing option packages are displayed on your computer screen, and the project may compile with stub libraries that exhibit exactly the kind of "missing cross-reference" symptoms listed below. Refer to Siemens support entry ID 18631373 — Check the STEP 7 V5.x project for required option packages for the verification sequence.

  1. Open the project in SIMATIC Manager with the matching STEP 7 version (right-click the project node → Properties → Version). V5.5, V5.6, and V5.7 are not binary-compatible at the block container level; opening a V5.7 project in V5.6 prompts an upgrade that may fail.
  2. From the menu bar select Options → Option Packages; any package marked with a yellow exclamation is absent on the local machine.
  3. Install the missing packages from the SIMATIC DVD set or pull them from Siemens Industry Online Support with the entry ID referenced.
  4. Re-open the project and re-compile (Blocks → Check Block Consistency → Generate All).
A project that compiles with phantom FB/FC blocks where an option package is missing will exhibit exactly the kind of "missing cross-reference" symptoms listed below. Confirm package integrity before chasing tooling bugs.

Cross-Reference Gaps for Local Variables

The single biggest productivity drag is that STEP 7 V5.x cross-reference (View → Cross-References or shortcut Ctrl+Alt+F4) only resolves global symbols: I, Q, M, DB, PI/PQ, timers, and counters. Local TEMP, STAT, and IN/OUT/IN_OUT variables of an FB/FC are not indexed. Service engineers who must follow data flow inside a vendor-supplied FB cannot jump from a local to its caller or from the FB interface into the calling network. The right-click → "Go To" menu on a local symbol returns "No cross-reference information".

Variable Class STEP 7 V5.7 Where-Used TIA Portal V17/V18 Where-Used
Global symbols (I/Q/M/DB) Full Where-Used list with R/W sites and network number Same
FB IN / OUT / IN_OUT / STAT / TEMP Not indexed Indexed via "Go to usage" in PLC tags and program editor
FC IN / OUT / IN_OUT / TEMP Not indexed Indexed
Multi-instance DB STAT Resolves to DB, not to instance path Resolves to full instance path
SCL local in FB/FC Not indexed Indexed

Workaround 1 — interface mirror DB. Declare a dedicated DB (e.g., DB900) that carries one global symbol per local variable of interest. Copy each local to/from the mirror at the start and end of the FB. The mirror variables are global, are indexed, and can be Where-Used. Trade-off: copy code adds 10-50 µs per call on an S7-300 and a maintenance burden on the developer's side. Reserve this pattern for FBs where you must expose internals to a third-party integrator.

Workaround 2 — promote TEMP to STAT. When designing new code, declare all signals as STAT in an instance DB rather than as TEMP. STAT variables live in the instance DB and are indexed because the DB itself is global. TEMP is reserved for scratch values that you genuinely do not need to inspect.

Workaround 3 — source-level search. Open the generated STL source (File → Generate Source → STL Source Files) and use Ctrl+F on the local variable name. The compiler emits the local as #Name in STL, so the search hits every read/write in that single FB/FC, including nested calls. This works because STEP 7 stores generated STL sources in the S7 program source files container and they are plain ASCII.

Ctrl+F operates only on the active editor. To search across every block in the project, generate the entire program as STL source (right-click S7 Program → Generate Source → "Generate source for all blocks"), open the source, and run a single Find All. Expect a 1-3 second delay for a 4,000-block program on a current Windows 10 workstation.

Absolute Address Lookup via Hover and Monitor/Modify

Hovering the mouse over any operand in a network exposes the symbolic name and the absolute address in a tooltip — for example, "Motor_On" resolves to Q 4.0. STEP 7 also lets you type that absolute address directly into the Monitor/Modify tab (Monitor/Modify → Modify) and force the value online, provided the CPU is in RUN-P and the operand is not write-protected by the CPU's protection level (1-3: write-protection password required).

For a non-instanced variable inside an FB/FC, however, the tooltip shows only the local name; there is no way to surface the absolute instance-DB offset. To reach it:

  1. Open the instance DB in Declaration View (right-click the DB → Declaration View). The Offset column gives Byte n Bit m for each STAT.
  2. Build the absolute address DB<inst_no>.DBX<byte>.<bit> or DBW/DBD.
  3. Paste into the Modify tab. The CPU accepts the access regardless of whether the FB happens to be active at scan time.

This is also the only practical way to drive a TEMP variable from the outside, because TEMP has no absolute address and cannot appear in Monitor/Modify at all — it is only visible in the active block's online view during a single scan.

Modifying Locals Online: Scope Matrix

Unlike TIA Portal, STEP 7 V5.x does not allow you to force a value into a local IN/OUT/IN_OUT/STAT/TEMP directly from the block monitoring view. The Modify column in the program editor is greyed for locals, and the LAD/FBD "modify selected address" context-menu action returns "Operand not permitted" for any local. To change a local online you must modify the absolute instance DB address (for STAT) or change the value upstream before the block is called (for IN/OUT/IN_OUT) or trigger a re-entry with new TEMP state by re-executing the block call.

Scope Online Force Available? STEP 7 Workaround TIA Portal V17 Behavior
Global M / I / Q / DB Yes (Modify tab) Yes
FB STAT in instance DB Indirect via DB address Type DB<n>.DBB<offset> in Modify Yes, direct
FB IN / OUT / IN_OUT No Modify the calling network's source operand Yes, direct
FC TEMP No Re-call FC; rely on a VAT for the next-cycle value Yes, direct
SCL static inside FB Indirect via DB Same as FB STAT Yes, direct

Process Image Partition vs. Highest Used I/Q Address

STEP 7 V5.x will silently accept a program that writes to Q 256.0 even when the CPU's default Process Image Partition 1 (PIP 1) covers only Q 0.0 .. Q 127.7. The compiler performs no check between declared OB1 process-image range and the highest I/Q operand referenced. The result: outputs above the PIP are written into the PA area only if an explicit L PQB / T PQB is used, but the OB1 end-of-cycle copy never touches them — they appear "dead" without any wiring fault and without any SF diagnostic on the CPU diagnostic buffer.

Recommended diagnostic procedure:

  1. Right-click the CPU in HW Config → Object Properties → Cycle/Clock Memory; note the PIP sizes (default 128 bytes for S7-300, 256 bytes for S7-400).
  2. Open View → Cross-References; filter on operand class "I" and "Q" (View → Filter).
  3. Sort the highest byte address used; compare against PIP-1 end address.
  4. Any operand above PIP-1 is a candidate for OB1 "lost write/read" — extend the PIP, or move the operand into OB35 with explicit L PQB / T PQB.
TIA Portal V17 raises a warning at compile time if a process image exceeds CPU PIP bounds. In STEP 7 V5.x this check is entirely manual. There is no menu item, no error code, and no SF LED — the value simply never reaches the module.

CPU-Specific Process Image Defaults

CPU Catalog Number Default PIP Size (bytes) Max PIP Configurable Number of PIPs
6ES7315-2EH14-0AB0 (CPU 315-2 PN/DP, FW V3.3) 128 2048 1
6ES7317-2EK14-0AB0 (CPU 317-2 PN/DP, FW V3.3) 128 2048 1
6ES7319-3EL00-0AB0 (CPU 319-3 PN/DP, FW V3.3) 128 2048 1
6ES7414-3EM07-0AB0 (CPU 414-3 PN/DP) 256 8192 Up to 4
6ES7416-3ES07-0AB0 (CPU 416-3 PN/DP) 256 8192 Up to 4
6ES7417-4XT05-0AB0 (CPU 417-4) 512 16384 Up to 8

S7-400 PIPs are tied to OB priorities (OB40 → PIP2, OB35 → PIP3, etc.) via HW Config. An S7-300 has a single PIP that is updated synchronously with OB1; outputs above the PIP will never be copied regardless of OB.

Compiler Warnings for Uninitialized Local Reads

STEP 7 V5.x does not warn when an FC TEMP is read before being assigned. A common defect pattern is:

FUNCTION FC 17 : VOID
VAR_TEMP
   tSum : INT;       // uninitialized
   tIndex : INT;
END_VAR
BEGIN
   tIndex := tIndex + 1;   // reads garbage from previous scan
   tSum := tSum + tIndex;  // propagates junk downstream
END_FUNCTION

The compiler passes this and the CPU cycles the local register with whatever value was left in the accumulator's low word from the previous scan. Defects surface as "random" -32768 wrap-around events that are nearly impossible to trace because they correlate with the call order of preceding FCs, not with the FC itself.

Manual defensive pattern:

  • Initialize every TEMP at the first network of the FC/FB with an explicit L 0; T #Name block, or with L W#16#0; T #WordName for word-sized temps.
  • Adopt a coding standard that bans local accumulator reuse across calls in the same OB1 priority class.
  • Run Options → Check Block Consistency → Generate All after every edit; this surfaces structural errors but does not catch uninit reads.
  • Validate with a SCL stub that scans the local-data area at the start of OB1 — a diagnostic FB that walks the L stack and asserts all-zero will catch uninit in commissioning.
TIA Portal V17 emits warning C0197: Local variable 'x' may be used before being assigned. STEP 7 V5.x has no equivalent. Project coders must enforce init manually through code review.

Naming Convention Enforcement

A long-standing request is for STEP 7 to enforce a project-wide naming standard so that engineers can distinguish physical I/Q from block-local I/Q at a glance. The de-facto convention used by most plants is:

Object Suggested Prefix STEP 7 Sample
Physical input (symbol table) I_ "I_Motor_Start" → I 0.0
Physical output Q_ "Q_Conveyor_Run" → Q 4.0
FB/FC input i iEnable : BOOL
FB/FC output q qRunning : BOOL
FB/FC in/out iq iqSpeed : INT
FB STAT s or PascalCase sFaultWord : WORD
FB/FC TEMP t or camelCase tIndex : INT

STEP 7 does not enforce this; TIA Portal V17 allows project templates with prefix-based naming rules that surface violations at compile time. Until you migrate, store the convention as a Word/PDF alongside the project and apply it manually via Symbol Table → Export → Edit in Excel → Import. Block-local names in STEP 7 are emitted in STL source prefixed with #, which is the only automatic visual separator. Configure the STL editor font to a monospaced face (Consolas, Courier New) so that the # prefix is visually distinct from the absolute address column.

Search Dialog "Next / Previous" Bug

A reproducible defect: when the Find and Replace dialog (Ctrl+F) is open in any LAD/FBD/STL editor and the user right-clicks a symbol in the program to invoke the context-menu Go To → Next / Previous occurrence, the navigation is hijacked: it executes against the term currently in the Find dialog, not against the symbol under the cursor. The expectation is that the symbol under the cursor should win, or at minimum that the Find dialog should auto-close on context-menu invocation.

Workaround sequence:

  1. Close the Find dialog (Esc) before invoking right-click → Next / Previous.
  2. Or use View → Cross-References as the canonical navigator; it never collides with the Find dialog.
  3. If the cross-reference is empty for a local symbol, fall back to source-level Ctrl+F on the generated STL file as described in the previous section.

This bug is present in V5.5, V5.6, and V5.7 and was not fixed by any service pack. The dialog-focus race condition is documented internally by Siemens but has no public KB article.

Indirect Addressing and Global Constants

STEP 7 V5.x has no native CONST keyword — every project defines "constants" as initial values in a global DB, which are technically read/write. Service engineers can corrupt them either through online modify or through a program bug. Workaround: declare a DB whose attributes are set to read-only by typing it under Blocks → System Data → CPU Properties → Protection with the "Know-how protect" + "Write protection" pair, or move genuine constants into the symbol table as REAL/INT with comments. TIA Portal V17 supports block-level read-only attributes on global constants.

Indirect addressing limits worth noting:

  • AUF DB[AR1] is illegal in classic STL; STEP 7 does not allow an indexed DB number. Workaround: pre-compute the DB number in a jump ladder using a sequence of AUF DB<constant> calls.
  • L P#M[AR1, P#0.0] works for memory but cannot resolve through a multi-instance DB to a STAT of an inner FB without manual offset arithmetic against the instance DB layout.
  • SCL gives bounded loops (FOR i := 1 TO 16 DO); pure STL requires a manual LOOP label or counter ladder.
  • Any indirect access through AR1/AR2 registers cannot be cross-referenced because the address is not resolved at compile time. Build a SCL helper to surface resolved addresses into a VAT for inspection.

Library Blocks and Option Package Resolution

Standard library blocks (IEC timers, IEC counters, USS/Modbus/PN IO libraries) ship as compiled FBs and require the matching option package on the development station. Per Siemens entry ID 18631373, when a STEP 7 project is opened, the option packages required are automatically checked. Missing option packages are displayed on your computer screen. The project will still open and the library FBs will appear in the program editor with "Unknown interface" until the package is installed. Once installed, regenerate the block consistency.

Library Required Option Package Typical Symptom When Missing
IEC 61131-3 timers/counters Base STEP 7 (always present)
Modbus TCP/RTU (FB 7 / FB 8 / FB 100) MODBUS library package FB shows no inputs, error "Library not found"
PN IO PNIO_Send / PNIO_Recv SIMATIC NET OPC Compile fails with FB 100 not defined
S7 Communication (PUT/GET) Base STEP 7
SFB 35 / SFB 36 / SFB 37 (alarm) Base STEP 7

Where-Used Resolution Flow

Symbol under cursor class? I/Q/M/DB/T/C View → Cross-References FB STAT in instance DB Indexed via DB number FB/FC LOCAL (IN/OUT/ STAT/TEMP) Not indexed Workaround: Generate STL source Ctrl+F on #Name Indirect access via AR1/AR2/DBW[AR1] Address resolved at runtime — not cross-referenceable. Instrument with SCL helper or VAT, or set breakpoint in STL.

Process Image Topology

S7-300 PIP1 default (CPU 315-2 PN/DP) PIP1: I 0.0 .. I 127.7 / Q 0.0 .. Q 127.7 (128 B) Q 128.0 .. Q 255.7 — NOT in PIP1 OB1 end-of-cycle copy: PAE (read PIP → inputs) PAA (write outputs → PIP) Anything written to Q ≥ 128.0 in OB1 is held in PA but NEVER copied to the module. S7-400 PIPs (CPU 416-3): PIP1: OB1 (256 B) PIP2: OB40 PIP3: OB35 PIP4: OB82

Troubleshooting Matrix

Symptom Likely Root Cause First Check Workaround
Cross-reference empty for local FB/FC variable Tool gap, not a defect Confirm variable class (TEMP/STAT) Generate STL source → Ctrl+F on #Name
Output bit never energizes, no SF LED, no diagnostic buffer entry Address above PIP1 range View → Cross-References → filter I/Q Extend PIP1 in HW Config or move output into OB35 with PQB
TEMP value is junk on first scan No init warning First network of FC/FB Force L 0; T #var defensively
Modify tab grey for block-local Tool limitation Class of variable Modify instance DB or caller operand
Search dialog "Next" jumps to wrong text Dialog-focus bug Close Find first (Esc) Use Cross-References or close+retry
Library blocks show as "stub" with no interface Option package missing Options → Option Packages Install per Siemens ID 18631373
Indirect DB[AR1] gives compile error SF021 Classic STL constraint Pre-compute DB number Use AUF ladder or SCL
Constants in DB corrupted by online modify DB is read/write by default DB attributes in CPU properties Apply Know-how protect + write-protection
Multi-instance STAT jumps to wrong DB Cross-reference returns DB number only Open instance DB → Declaration view Hand-trace byte offset

Verification Checklist

  1. Open project; confirm Options → Option Packages shows no yellow exclamation marks (per Siemens ID 18631373).
  2. Run Blocks → Check Block Consistency → Generate All; resolve every warning, especially W: address above process image-class messages.
  3. Cross-reference every global I/Q in OB1 against HW Config PIP sizes; record any mismatch in a project README.
  4. Generate STL source for every FB/FC; spot-check uninitialized TEMP usage by searching for # prefix on the LHS of a network.
  5. Open a VAT (Blocks → Variable Table → New); force a STAT via its instance-DB absolute address; observe behavior in a real process.
  6. Export the symbol table to Excel; audit prefix compliance with project naming standard; import back if corrections are needed.
  7. For every indirect access, document the address-formation sequence in a comment above the call — indirect addresses are invisible to the tool.
  8. Run an uninit-TEMP audit by adding a diagnostic FB at OB1 priority that walks the L stack and asserts zero; observe over 24 h.

Why does STEP 7 V5.x cross-reference show nothing for my local FB variable?

The classic Where-Used index only resolves global symbols (I, Q, M, DB, timers, counters). FB/FC IN/OUT/IN_OUT/STAT/TEMP variables are not indexed. Open File → Generate Source → STL Source Files, open the compiled source, and use Ctrl+F on the local variable name (preceded by #) to find every read/write inside that block.

How do I modify a local FB variable online in STEP 7 V5.x?

You cannot force a local directly from the block editor. For STAT variables, type the instance-DB absolute address (e.g., DB20.DBX2.0) into the Monitor/Modify tab. For IN/OUT/IN_OUT, change the value at the caller operand. For TEMP, re-trigger the block call or use a VAT to read the next-cycle value.

Why does an output never turn on even though the bit is set in the program and there is no SF LED?

The address may lie above the configured Process Image Partition. View → Cross-References filtered on operand class "Q" lists the highest byte in use; if it exceeds the CPU PIP range (128 B on S7-300, 256 B on S7-400), OB1 will not copy it to the module. Extend the PIP or move the output into OB35 with an explicit T PQB.

Does STEP 7 V5.x warn when a TEMP is read before assignment?

No. The compiler accepts uninitialized TEMP reads and the value is whatever the local-data stack happens to hold from the previous scan. Defensively initialize every TEMP at the first network of the FC/FB with L 0; T #var. TIA Portal V17 emits warning C0197 for the same defect.

Why does the search dialog's Next/Previous jump to the wrong text?

When the Find dialog is open, right-click → Go To → Next/Previous executes against the term currently in the Find box, not the symbol under the cursor. Close the dialog with Esc first, or use View → Cross-References as a reliable navigator instead.

Back to blog