Step 7 Programming: FC vs FB and Instance Data Blocks Explained

David Krause14 min read
Best PracticesHMI ProgrammingSiemens
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 (TIA Portal and the legacy SIMATIC Manager) organizes application code into blocks. The two most common organizational blocks in SIMATIC S7-300/400 and S7-1200/1500 projects are Functions (FC) and Function Blocks (FB). Choosing between them dictates whether the runtime must allocate an Instance Data Block (IDB) for the call. This reference clarifies the variable types (TEMP, STAT, IN, OUT, IN_OUT, M, I, Q, DB), the scan-cycle behavior of each, the memory cost of IDBs versus global M memory, and the rules under which an FB call is invalid without an IDB. The goal is to give a first-time STEP 7 programmer a defensible engineering rationale for block selection rather than a rote rule.

Cross-vendor note: the concept of "instance data" is not unique to Siemens. As described in the general Wikipedia entry on aspect-oriented programming, advice-style functions wrap or modify behavior across invocations. In a PLC, the FB plus its IDB is the same idea expressed in deterministic, scan-cycle terms: the FB describes what to do, the IDB describes which set of working values the FB uses this time it is called.

Scope: This article targets the STEP 7 V5.x / SIMATIC Manager environment (S7-300/400). The same rules apply in TIA Portal for S7-1200/1500, where Instance DBs are called Instance data blocks and are generated automatically when an FB is dropped into a network.

Prerequisites

  1. STEP 7 V5.5 or higher installed, with at least one S7-300 (e.g. CPU 315-2 PN/DP, order number 6ES7315-2EH14-0AB0) or S7-400 (e.g. CPU 416-3, 6ES7416-3ES06-0AB0) station configured in the hardware catalog. Refer to the S7-300 Module Data manual and the S7-400 CPU 416-3 manual for hardware specifics.
  2. Working knowledge of OB1 (main cyclic organization block) and how the CPU scans inputs, executes OBs in priority order, and writes outputs.
  3. Familiarity with bit memory (Merker) addressing, e.g. M0.0, MW10, MD20. Memory size limits: 2048 bytes on the CPU 312, 8192 bytes on the CPU 315-2 PN/DP, and up to 16384 bytes on the CPU 416-3 (see S7-400 reference manual).
  4. STEP 7 help system installed locally; press F1 on any block to access the integrated reference (e.g. SFB4 "TON", SFB5 "TOF", SFC0 "SET_CLK").

Variable Types in STEP 7: A Reference Table

Every variable declared in an FC or FB has a defined storage class. The storage class determines where the value lives in CPU memory and how long it survives between scans.

Type Where it lives Retains across scans? Retains across OB restart? Visible from Typical use
INPUT (in FC/FB) L stack (L locals) during call No (snapshot at call start) No Call interface only Passing parameters into the block
OUTPUT L stack during call No No Call interface only Returning results to the caller
IN_OUT L stack during call No No Call interface only Bidirectional parameter passing
TEMP L stack (L stack is reinitialized on every block call) No No Inside the block only Intermediate calculations
STAT Associated IDB (persistent across scans for that instance) Yes Yes if IDB is non-volatile Inside the FB only State, accumulators, presets
M (Merker/flag) Global bit memory area in the system memory Yes Yes if defined as retentive in HW config All blocks Cross-block flags, handshakes
I / IB / IW / ID Process image input (PII) Yes (updated each scan) No All blocks Sensor wiring
Q / QB / QW / QD Process image output (PIO) Yes (written at end of OB1) No All blocks Coil / actuator wiring
DB global User data block (DB) Yes Yes if DB is non-volatile All blocks Recipes, setpoints, logs

The crucial rule for TEMP: the L stack area is overwritten at the start of every block call. A TEMP variable in an FC has no defined value before the first assignment in the current scan, and a TEMP in an FB behaves the same way because the L stack is shared with the block-call mechanism. This is a common source of intermittent faults in newly written code.

Field note: Reading an uninitialized TEMP BOOL in LAD/FBD sometimes returns 0 silently and sometimes latches a residual from a previous call. Always assign a value at the top of the network before any branch reads it.

Functions (FC) and Function Blocks (FB): The Hard Rule

The STEP 7 editor enforces a simple, non-negotiable rule:

  • An FC has no memory of its own. It receives INPUT, OUTPUT, and IN_OUT parameters and operates on TEMP locals. It may read/write global M, I, Q, and DB addresses. Calling an FC requires only the call site; no companion block is created.
  • An FB must be called with a companion block. The companion is the Instance Data Block (IDB). The IDB is a DB whose data structure is dictated by the FB's VAR_INPUT, VAR_OUTPUT, VAR_IN_OUT, and VAR_STAT declarations. Without an IDB, the FB cannot be downloaded and the call returns SF (system fault) with diagnostic buffer entry "FB call without instance DB".

From the STEP 7 Online Help (block help, F1 on any FB): "Every function block call requires an instance data block. The instance DB stores the static variables and the actual values of the input, output, and in/out parameters." See the STEP 7 Programming and Operating Manual for the formal definition.

Programming in LAD/FBD, when you place a system function block such as SFB4 (TON, on-delay timer) or SFB5 (TOF, off-delay timer) into a network, the editor shows a red ??? above the block. Clicking the ??? opens the Instance DB dialog. Enter an unused DB number (e.g. DB20). The CPU allocates that DB on the next download. The block is now linked to that IDB for as long as the program runs.

Instance Data Blocks (IDB) Explained

An IDB is a DB whose layout is auto-generated from the FB's variable declaration table. If the FB is later modified (a new STAT is added, an INPUT is renamed), STEP 7 prompts you to update the IDB on the next compile. The two update modes are:

  • Update only with instance consistency: matches block interface and IDB layout, retaining current values where types match.
  • Update with new structure: discards or initializes the IDB; values for newly added variables are 0 / FALSE.

Opening the IDB in the editor (DATA view) reveals entries such as:

DATA BLOCK DB20  // Instance of FB1 "Pump_Control"
BEGIN
  Preset_Time       : S5TIME  = S5T#5S;     // passed IN parameter
  Elapsed_Time      : S5TIME;                // STAT used by IEC timer
  Enable            : BOOL    = FALSE;      // passed IN parameter
  Running           : BOOL;                  // STAT, running flag
  Q_Output          : BOOL    = FALSE;      // passed OUT parameter
  HMI_ActualSpeed   : INT     = 0;           // STAT, accumulator
END_DATA_BLOCK

Every call to FB1 with a different IDB (e.g. DB20 for Pump_1, DB21 for Pump_2) creates a separate working dataset. This is the structural reason FBs exist: one piece of code, N independent state spaces. An FC cannot do this without writing its own "poor man's instance" by hand in M memory or a global DB, which is the path recommended in the field report when the programmer is not yet comfortable with FBs.

Memory Architecture: L Stack, Work Memory, Load Memory

STEP 7 partitions PLC memory into three logical tiers. Knowing which tier holds each variable clarifies scan behavior.

Tier Location Contents Volatile? Typical size (CPU 315-2 PN/DP)
Load memory Flash / MMC card Project, blocks, comments, symbols No (battery-free with MMC) up to 8 MB on MMC
Work memory (code) RAM Compiled logic, FC/FB/SFB/SFC code Yes (battery-backed) 384 KB
Work memory (data) RAM DBs, M flags, PII/PIO, timers, counters Yes (battery-backed) 256 KB
L stack RAM, per priority class TEMP, actual parameter copy during call Yes Configurable, 32 KB default

When OB1 calls FC10, the CPU pushes a new L stack frame sized to FC10's local-variable declarations. The frame is filled with indeterminate values for TEMP, and the actual parameters are copied into the INPUT area. On return, the L stack frame is discarded. This is why a TEMP DWORD declared at the top of FC10 is not the same memory location as the TEMP DWORD in the next scan's FC10 call.

When to Use IDBs, M Memory, and Global DBs

The choice is not stylistic; it is determined by the engineering problem. The decision matrix below summarizes the field-tested rules.

Situation Recommended Reason
One-shot control logic, single device, no state to remember FC with M flags or no memory No persistent state needed; IDB adds overhead
Reusable logic called N times (e.g. N pumps, N valves, N PID loops) FB + N IDBs Each call gets its own dataset; renaming or restructuring changes one source
IEC timers (SFB4 TON, SFB5 TOF, SFB3 TP pulse) FB + IDB (mandatory) These SFBs are FBs; an IDB is required by definition
IEC counters (SFB0 CTU, SFB1 CTD, SFB2 CTUD) FB + IDB (mandatory) Same as above
Cross-block handshakes, mode flags, global alarms M memory or global DB Shared state; no need for per-call isolation
Recipes, setpoints, machine parameters, HMI-mapped data Global DB with structured types (UDT) Symbolic access, easy HMI binding, possible to mark non-volatile
Sequential state machines (gearing, batching, multi-step processes) FB + IDB with STAT Step Encapsulation: the step lives with the logic, not in a global tag
First-time programmer, simple "pump on / pump off" task FC + M memory Lower cognitive load; matches the field report's pragmatic advice

Working with TON and TOF: A Concrete Example

The system function blocks SFB4 (TON, on-delay) and SFB5 (TOF, off-delay) are pre-compiled FBs that live in the CPU's firmware. Each call to SFB4 still requires its own IDB because the call is structurally a call to a user-side FB wrapper that binds the system SFB to a DB.

Declaration table of the wrapper FB (call it FB100 "MyOnDelay"):

VAR_INPUT
  Start        : BOOL;       // start edge input
  PresetTime   : S5TIME;     // time preset (e.g. S5T#5s500ms)
END_VAR
VAR_OUTPUT
  Q            : BOOL;       // timer done
END_VAR
VAR
  TON_Inst     : SFB4;       // system FB, needs its own IDB
END_VAR

Calling the wrapper in OB1:

CALL "MyOnDelay" , DB100
  Start     := I 0.0
  PresetTime:= S5T#5s500ms
  Q         := Q 4.0

Inside FB100, the network that uses the embedded SFB4 is itself a call with its own IDB. STEP 7 (from V5.5 SP2 onward) will auto-generate a multi-instance DB, so the embedded TON_Inst lives in DB100 alongside the wrapper's VAR and parameter area. The single-instance approach (one IDB per SFB) is the legacy alternative and is still supported.

Common SF diagnostic buffer entries in this area:

  • "Area length error reading" on a S5TIME parameter — the caller's value is malformed (e.g. negative or > 9h59m59.999s).
  • "Function block not loaded" on SFB4 — the SFB has been deleted from the offline project but the IDB still references it.
  • "DB not loaded" — the IDB is referenced but missing from the loaded configuration; re-download the program.

Programming Workflow: From "I Avoid IDBs" to "I Use FBs Comfortably"

  1. Phase 1 — FCs and M memory only. Declare the equivalent of a "preserved timer" by hand. In an FC, write the preset into MW100, the elapsed counter into MW102, the running flag into M104.0. Update MW102 against MW100 every scan using OB35 cyclic interrupt. This is workable for a single device but becomes a maintenance burden at N = 5 devices.
  2. Phase 2 — Introduce a single FB. Pick the most repeated function in the project (e.g. Pump_Control). Right-click BlocksInsert New ObjectFunction Block. Name it, accept the default DB-number dialog, declare parameters, fill in the logic. Download.
  3. Phase 3 — Multi-instance FBs. Once comfortable, embed SFB4 (TON), SFB5 (TOF), and IEC counters as multi-instances of one IDB. This consolidates the data layout and avoids DB-number pollution (DB20, DB21, DB22... for every timer). The option is in the FB declaration: set the SFB instance column from Single instance to Multi-instance and assign a name under the VAR section.
  4. Phase 4 — Structured types (UDT). When the FB's interface becomes large, factor repeated parameter clusters (e.g. Axis_Inputs, Axis_Outputs) into a User-Defined Type and reference it as a VAR_INPUT or STAT. This is the path that scales to large programs (S7-400 with hundreds of FBs).

Common Pitfalls and Field-Proven Diagnostics

Symptom Likely cause Diagnostic step Fix
SF LED on, diagnostic buffer "FB call without instance DB" FB called but IDB number blank or missing PLC → Diagnose Hardware; open the buffer Open the call site, click red ???, assign an unused DB
Timer output stuck ON after one shot TEMP BOOL used as a latch flag; survives by chance Cross-reference the address; check declaration Move the flag to STAT (in FB) or M (in FC)
Pump 1 stops when Pump 2 starts Shared M bits used as "instance" data for two pumps Symbol table → filter by M area Convert to FB + per-pump IDB
Count value resets on every scan Counter accumulated value stored in a TEMP Watch table; observe value over 5 scans Use SFB0/1/2 with IDB, or store in STAT / M
CPU goes STOP on download of new FB version IDB structure mismatch; CPU in update with new structure mode Online → Download to Target Device, check option dialog Choose consistent update if current values matter
L stack overflow in deep FC calls FC nests 8+ levels; L stack frame too small Diagnostic buffer "L stack overflow" Convert bottom-level FCs to FBs with IDB, reducing nesting
IEC timer ET shows 0 even when input is TRUE IDB deleted or replaced with a different DB Open FB call; verify IDB number Reassign IDB; recompile and download

Verification Checklist

  1. Compile the project (menu ProgramCompile All). Resolve every warning; do not ship a build with "no error found on offline check" if warnings remain.
  2. Cross-reference (Ctrl+Alt+F7) every global M, I, Q, and DB address. Any M that is written in more than one block is a candidate for refactoring into an IDB-based structure.
  3. Download to the target PLC in STOP mode for the first cut. After download, perform a CPU restart (warm restart) to clear the L stack and reinitialize IDBs from the new structure.
  4. Open Monitor/Modify on the IDB in online mode. Cycle the inputs and confirm STAT values change as expected.
  5. Force a power-cycle of the PLC (if battery-backed) and re-check STAT values for non-volatile IDBs.
  6. Watch the diagnostic buffer for SF entries during a 1-hour burn-in.
Memory budget: Each IDB reserves its full size in work memory, even if most STAT cells are unused. A FB with 2 kB of declarations, called 50 times, costs 100 kB of work memory. On a CPU 315-2 PN/DP with 256 kB of work-memory data area, the budget closes fast. Use multi-instance FBs to consolidate IDBs and reclaim work memory.

Notes on TIA Portal and S7-1200/1500

Although the field report is framed in STEP 7 V5.x terms, the same engineering rule applies in TIA Portal V15 and later for S7-1200/1500. The S7-1500 CPU family (e.g. CPU 1515-2 PN, 6ES7515-2AM02-0AB0) introduces optimized block access, which means the IDB is no longer a flat byte-image DB but a structured data view managed by the compiler. The IDB is still required; what changes is the on-the-wire layout. The S7-1500 also allows instance-aware know-how protection, an attribute on the FB that hides the IDB contents in read-protected projects — useful when shipping machine code to OEMs.

FAQ

What is the difference between TEMP and STAT variables in STEP 7?

TEMP variables live in the L stack and are reinitialized to indeterminate values at every block call, making them suitable only for intermediate calculations. STAT variables live in the associated IDB of an FB and retain their values across scans, making them the correct choice for state, accumulators, and presets. Reading a TEMP before assignment is a common source of intermittent faults.

Can I call a Siemens FB without an Instance Data Block?

No. Every FB call requires an IDB. In the editor, the red ??? above the FB box is a prompt to assign a DB number. If the IDB is missing at runtime, the CPU enters STOP with diagnostic buffer entry "FB call without instance DB". The only way to avoid the IDB requirement is to use an FC instead, which has no associated instance memory.

How do I call an SFB4 (TON) timer without writing a wrapper FB?

Place SFB4 directly in a network, click the red ???, and assign an unused DB number (e.g. DB50). The CPU treats that DB as the SFB4's instance. This is the "single instance" approach. For larger programs, wrap SFB4 in a user FB and use multi-instance mode so all timers share one consolidated IDB.

When should I use M memory instead of an IDB?

Use M memory for cross-block handshakes, mode flags, and any value that is logically global (one copy shared by all logic). Use an IDB for per-call state, such as the running flag, accumulated time, and presets of a specific pump or valve. The decision is structural: M memory has one copy, an IDB has one copy per FB call.

What happens to IDB values on a CPU restart?

It depends on the IDB's retentive setting. A non-retentive IDB is reinitialized from its initial declaration values on every warm restart and on every STOP→RUN transition. A retentive IDB preserves its current values across power cycles (with battery backup on S7-300/400, or via the SIMATIC Memory Card on S7-1500). Configure retention in HW Config → CPU properties → Retentive Memory, listing the DB numbers to retain.

Back to blog