1. Problem Definition
On SIMATIC S7-400 / S7-400H controllers, the diagnostic organization block OB86 (Rack Failure / DP Slave Failure) is invoked only when a rack failure or a distributed I/O station loss is detected as a live transition during RUN. If a PROFIBUS DP slave (for example, an ET200M station with a redundant IM 153-2 link module) is removed while the CPU is de-energized and remains missing at the moment the controller returns to RUN, OB86 is not called at power-up. The user program therefore sees the system as healthy even though physical modules are absent, leaving the diagnostic database silent until the next live event.
This behavior creates a diagnostic gap for any plant whose control cabinet may be powered down for transport, maintenance, or customer-driven shutdown. OB82, OB83, OB85, OB86, and OB87 are all event-driven — they fire on transitions, not on static conditions. Without an explicit status scan during startup, the program cannot distinguish "everything is OK" from "the rack was already missing when we woke up."
Observable symptom signatures:
- No OB86 call at the OB100 (warm restart) or OB102 (cold restart) boundary
- No OB82 diagnostic interrupt at startup for faults already present
- Fault-tracking DB shows "all stations OK" even though a link module or ET200M is physically absent
- OB86 fires correctly for live events once the CPU is fully RUN
- Removing and reinserting the link during RUN triggers OB86 as expected
- Slot-level I/O faults appear in the diagnostic buffer but no station-level alarm is raised
2. System Architecture Context
The fault pattern described above most commonly appears on S7-400H redundant systems with distributed I/O connected over PROFIBUS DP using redundant IM 153-2 link modules. Typical hardware in scope:
| Component | Typical Siemens Part Number | Role in Diagnostic Chain |
|---|---|---|
| SIMATIC S7-417-5H | 6ES7 417-5HT06-0AB0 (or later H-CPU) | Master, runs OB100 / OB102 / OB86 |
| ET200M station | 6ES7 153-2BA10-0XB0 / 6ES7 153-2BA70 (redundant link) | DP slave, reports diagnostics upstream |
| PROFIBUS DP cable | 6XV1 830-0EH10 / 6XV1 830-3EH10 | Physical link for cyclic I/O exchange |
| PS 405 / PS 407 | 6ES7 405-0KA02-0AA0 / 6ES7 407-0KA02-0AA0 | Power supply for rack and DP interface |
| Sync module / fiber | 6ES7 960-1AA04-0XA0 / 6ES7 960-1AB04-0XA0 | H-specific — not directly involved, but supports H diagnostics |
For S7-400H systems, additional redundant-aware OBs exist and may also need to be considered:
- OB70 — I/O redundancy error (loss of redundancy on a redundant I/O)
- OB72 — CPU redundancy error (loss of master / standby or sync failure)
- OB73 — Communication redundancy error
The same edge-triggered limitation applies to OB70-OB73 — they too will not fire for faults already present at startup. See the SIMATIC S7-400H System Manual for the complete list of redundant-specific OBs and their startup information templates.
3. Diagnostic OB Execution Model in S7-400
Understanding why OB86 is silent at startup requires a precise view of the S7-400 event model. The following table summarizes the diagnostic OBs and their triggering conditions:
| OB | Name | Trigger | Startup Behavior |
|---|---|---|---|
| OB82 | Diagnostic interrupt | Module reports diagnostic event (incoming/outgoing) | Only fires on edge after RUN |
| OB83 | Insert/remove module | Module insertion or removal during RUN | Only fires on edge after RUN |
| OB85 | Priority class error | I/O access error during process image update | Only fires on edge after RUN |
| OB86 | Rack failure / DP slave failure | DP station present → absent or absent → present | Only fires on edge after RUN |
| OB87 | Communication failure | Communication error (e.g., GD packet failure) | Only fires on edge after RUN |
| OB100 | Warm restart | CPU completes restart | Called once at startup — does not call OB82-87 |
| OB101 | Hot restart | CPU completes hot restart (S7-400 only) | Called once at startup |
| OB102 | Cold restart | CPU completes cold restart | Called once at startup |
The Startup Information of OB86 (and OB82) contains two flags:
-
OB86_FLT_ID— fault identifier (e.g., B#16#C3 / B#16#C4 / B#16#C7) - For OB86, the
OB86_EV_CLASSbyte distinguishes incoming (B#16#38 / B#16#39) from outgoing (B#16#3A / B#16#3B) events
Refer to the Siemens TIA documentation for the diagnostic interrupt OB to confirm startup information layout for OB82: Diagnostic interrupt OB (OB 82) — STEP 7 / TIA Portal V21. The same structure applies on the S7-400, where OB82 startup info contains module start address, channel, and event-in / event-out flags.
4. Root Cause Analysis
The diagnostic gap is not a bug — it is a deliberate consequence of the S7-400 event model:
- The CPU boots and enters OB100 (warm restart) or OB102 (cold restart).
- During the restart phase, the CPU performs PROFIBUS DP initialization: it calls each slave, parametrizes it, and configures it.
- After parametrization, the DP master takes each missing slave into its "not available" state.
- Because the CPU never observed the slave as present, no OB86 "incoming failure" event can be generated — there is no edge from "present" to "absent."
- OB82, OB83, OB85, OB86, and OB87 remain silent until the next runtime transition.
The only place where the current physical state is authoritatively known is the System State List (SSL). The SSL is a snapshot maintained by the operating system that reflects the actual current condition of every configured module, DP slave, and slot.
Reading the SSL requires the standard function SFC51 "RDSYSST" (Read System State). SFC51 is the only sanctioned interface for the user program to query the SSL. The relevant SSL partial lists for distributed I/O diagnosis are:
| SZL_ID | Description | Index Meaning | Typical Use |
|---|---|---|---|
| W#16#0A91 | DP slave diagnostic status | 0 = extract (all slaves), or DP address | Identify which slaves are faulty |
| W#16#0094 | Status of all DP slaves | DP master / DP slave system ID | Per-system station list |
| W#16#00B4 | Module diagnostic data of a DP slave | DP station address | Get detailed diagnostic buffer |
| W#16#00B1 | Diagnostic data of a module | Logical base address | Central / expansion rack slots |
| W#16#00B3 | Module diagnostic data records DS0/DS1 | Logical base address | Detailed diagnostic record |
| W#16#0118 | H system diagnostic information | 1 | S7-400H redundant-specific |
| W#16#0131 | Diagnostic buffer of the CPU | 1 | Recent fault history |
For the use case described in this article, the most useful SSL is W#16#0A91 — the DP slave diagnostic status list. Each entry is a two-word record:
| Byte | Field | Meaning |
|---|---|---|
| 0 | Status byte (SZL.STATUS) | B#16#00 = OK, B#16#11 = faulty, B#16#33 = not configured |
| 1 | Reserved | — |
| 2-3 | DP station address | PROFIBUS address of slave |
5. Solution Strategy: Active Status Polling in OB100 / OB102
The robust solution is a hybrid architecture:
- Mark the fault-tracking DB as non-retentive. This clears any stale flags from before power-down.
- In OB100 (warm restart) and OB102 (cold restart), call SFC51 with SZL_ID = W#16#0A91 to read the actual DP slave diagnostic status of every configured station.
- Populate the fault-tracking DB based on the SFC51 result. A status byte <> B#16#00 means the station is currently faulty.
- After startup, rely on OB86 events for real-time updates.
This hybrid model restores correctness without sacrificing the runtime efficiency of event-driven OB handling. The startup scan adds a few milliseconds to OB100 — negligible on S7-400 — and ensures the diagnostic DB is fully synchronized with the actual physical state before OB1 begins cyclic execution.
6. Prerequisites for Implementation
- STEP 7 V5.5 / V5.6 (or TIA Portal V16+ for S7-400 with compatibility mode)
- SFC51 from the standard library (CEIL / IEC library)
- Pre-allocated DB (e.g., DB2000 "Diag_DB") with at least N+2 words, where N is the number of configured DP slaves
- Configured OB100 and OB102 (download empty OBs if not yet present, otherwise the CPU will remain in STOP if the default startup routine is rejected)
- Access to the hardware configuration (HW Config) to confirm DP station addresses
7. Implementation in STL
The following STL block can be inserted at the top of OB100 (and duplicated into OB102). It reads SSL W#16#0A91 with INDEX = 0 (extract of all DP slaves) and writes the result into a pre-allocated data area. After the call, the application scans the returned list and marks the fault DB accordingly.
// OB100 — initial SSL scan to populate fault DB
// Scratch flags: M 100.0 = busy, MW102 = retval
// Target data area: P#DB2000.DBX 0.0 BYTE 256 (32 stations max)
CALL SFC 51
REQ := TRUE
SZL_ID := W#16#0A91 // DP slave diagnostic status
INDEX := W#16#0000 // 0 = full extract
RET_VAL := MW 102 // 0 = OK, Fxxx = error
BUSY := M 100.0
SZL_HEADER := DB2000.SSL_HEADER // STRUCT (length, n_records)
DR := P#DB2000.DBX 16.0 BYTE 240
A M 100.0
JC end // SFC51 still running
// Evaluate SZL_HEADER: DBW0 = record length, DBW2 = number of records
L DBW 0 // record length (bytes per record)
L 4
==I
JC eval_4 // each record = 4 bytes (status + addr)
end: BE
eval_4:
L DBW 2 // number of records returned
T MW 104 // loop counter
L 0
T MW 106 // pointer offset
next:
L MW 104
L 0
==I
JC finished
// Each record: byte 0 = status, byte 1 = reserved, bytes 2-3 = DP address
L DBB [MW 106 + 16] // status byte
L B#16#00
==I
JC ok_station
// Faulty station: write address + status into fault DB
L DBW [MW 106 + 18] // DP address
T DBW [MW 110] // fault_db[i].addr
L DBB [MW 106 + 16] // status
T DBB [MW 112] // fault_db[i].status
SET
S DBX [MW 114] // fault_db[i].fault_flag
JU cont
ok_station:
L DBW [MW 106 + 18] // DP address
T DBW [MW 110]
L 0
T DBB [MW 112]
CLR
S DBX [MW 114] // fault_db[i].fault_flag = 0
R DBX [MW 115] // fault_db[i].new_fault = 0
cont: L MW 106
L 4
+I
T MW 106
L MW 110
L 8
+I
T MW 110
L MW 104
DEC 1
T MW 104
JU next
finished:
BE
8. Implementation in SCL
For engineers using SCL (Structured Control Language) the same logic is more compact:
// SCL — call inside OB100 / OB102
FUNCTION_BLOCK FB_DiagScan
VAR
busy : BOOL;
ret_val : INT;
header : STRUCT
length_w : WORD;
n_records : WORD;
END_STRUCT;
record : ARRAY[1..32] OF STRUCT
status : BYTE;
rsvd : BYTE;
addr : WORD;
END_STRUCT;
i : INT;
END_VAR
BEGIN
RDSYSST(REQ := TRUE,
SZL_ID := W#16#0A91,
INDEX := W#16#0000,
RET_VAL := ret_val,
BUSY := busy,
SZL_HEADER := header,
DR := record);
// Wait until SFC51 completes
WHILE busy DO
RDSYSST(REQ := FALSE,
SZL_ID := W#16#0A91,
INDEX := W#16#0000,
RET_VAL := ret_val,
BUSY := busy,
SZL_HEADER := header,
DR := record);
END_WHILE;
// Iterate over returned records
IF ret_val = 0 THEN
FOR i := 1 TO WORD_TO_INT(header.n_records) DO
// fault_db[i].fault_flag := record[i].status <> B#16#00;
"Diag_DB".fault[i] := record[i].status <> B#16#00;
"Diag_DB".addr[i] := record[i].addr;
"Diag_DB".status[i] := record[i].status;
"Diag_DB".new_fault[i] := 0; // suppress new-fault latching on startup
END_FOR;
END_IF;
END_FUNCTION_BLOCK
9. OB86 Runtime Logic — Do Not Remove
The startup scan complements but does not replace the runtime OB86. Once the CPU is in RUN, OB86 remains the authoritative source for live transitions. The combined fault DB write logic should look like this:
- OB100 / OB102: populate fault DB from SSL (handles pre-existing faults)
- OB86 (incoming event): set fault flag for the affected station; optionally raise an HMI alarm
- OB86 (outgoing event): clear fault flag when station returns
- OB82: handle module-level diagnostic interrupts; update channel-level diagnostic bits
- OB70 (H only): handle I/O redundancy loss; do not flag the station as failed, only as "no longer redundant"
- OB72 (H only): handle CPU redundancy error (master/standby swap, sync loss)
The SSL partial-list extractions and their semantics are documented in the STEP 7 Online Help for SFC51 and in the S7-300/400 System Software System and Standard Functions reference manual.
10. Retentive Strategy Combined with SSL Scan
There are three viable retention strategies. Pick one based on the diagnostic semantics required:
| Strategy | DB Property | Startup Action | Risk |
|---|---|---|---|
| A — Pure non-retentive | Non-retentive | OB100 SSL scan populates DB | None if SSL scan is implemented |
| B — Pure retentive | Retentive | None | Stale flags reflect pre-power-down state |
| C — Retentive with reset bit | Retentive | OB100 clears DB then SSL scan repopulates | Slightly more code; safe |
Strategy A is the most elegant and is recommended for new projects. Strategy C is recommended when an existing fault DB has retentive dependencies that cannot easily be removed. In both cases, the OB100 / OB102 SSL scan is mandatory.
11. Verification and Commissioning
Validate the implementation with the following test sequence:
- Healthy power-up: With all DP stations connected, power down the cabinet and power back up. Confirm that the fault DB contains no fault flags after OB100 completes (verify in online watch table).
- Faulted power-up: Power down, remove one IM 153-2 from the redundant pair on a configured ET200M station, then power back up. Confirm that the fault DB contains a fault flag for that station's address within the first OB1 cycle.
- Live transition: With the CPU in RUN and healthy, remove the IM 153-2. Confirm OB86 fires (event class B#16#39 / B#16#3A). Confirm the fault DB flag transitions correctly.
- Recovery transition: Reinsert the IM 153-2. Confirm OB86 fires with event class B#16#38 (incoming / station recovered) or B#16#3B (outgoing). Confirm the fault DB flag clears.
- Diagnostic buffer cross-check: Read SSL W#16#0131 (diagnostic buffer) after each step and confirm consistent timestamps.
- Watchdog on OB100: Confirm OB100 completes in < 100 ms (typical) — add a temporary "OB100 done" timestamp if needed.
Place a breakpoint or status indicator on the OB100 / OB102 block to verify it executes during restart. In STEP 7 / TIA Portal, use the online "Monitor / Modify" function on the fault DB after power-up to confirm the SSL result was applied correctly.
12. Troubleshooting Matrix
| Observed Symptom | Likely Cause | Fix |
|---|---|---|
| OB100 SSL scan returns RET_VAL = W#16#80A1 | SZL_ID / INDEX combination invalid | Verify SZL_ID = W#16#0A91 and INDEX in valid range |
| RET_VAL = W#16#8080 | SFC51 already active | Use single instance, wait for BUSY = FALSE |
| Header.n_records = 0 | No DP master / no configured slaves | Verify HW Config and DP master system ID |
| All status bytes = B#16#33 | Slaves not configured in HW Config | Re-import GSD / re-run HW Config |
| OB100 never called | CPU is in run-mode only (not restarted) | Force restart via PG or mode selector |
| Fault DB cleared on power-up but never repopulates | OB100 not downloaded, OB102 not downloaded | Download empty OB100 / OB102; place call inside |
| Fault flag set but not on HMI | HMI polling period longer than transient | Use event-driven HMI tags or shorter poll period |
| OB86 fires twice for same station | Two DP master systems / H system addressing duplicate | Check DP master system IDs in HW Config |
| OB70 not firing on H redundancy loss | OB70 not present in program | Download OB70 with at least BE at the end |
| S7-400H reports "solo" after restart unexpectedly | Sync-up not yet completed at OB100 execution | Delay SSL scan until after first link-up check (e.g., 1 s) |
For deeper information on diagnostic error interrupt semantics across S7-300/400, see Diagnostic interrupt OB (OB 82) (S7-300, S7-400) — TIA Portal V21 and the S7-1200 equivalent for context on the diagnostic event model in TIA Portal S7-1200 Manual Collection — Diagnostic error interrupt OB. Although the S7-1200 differs in detail, the underlying "edge-triggered vs. status-based" distinction is identical and explains the philosophy behind OB82's startup information. For CPU-specific manuals, consult SIMATIC S7 S7-1200 Programmable controller — ID 91696622, which contains the same diagnostic-event model description applicable to the S7-1200 family.
13. Edge Cases and Field-Proven Caveats
- OB100 timing on H systems: On S7-400H, OB100 may execute before the sync link is fully established. Avoid making sync-dependent decisions inside OB100. Instead, set a "first scan" flag and act on it from OB1.
- SSL extract limits: SZL_ID W#16#0A91 with INDEX = 0 returns an extract. The maximum number of records depends on the CPU; S7-417 supports 64 DP slaves per master system, multiple master systems. Plan the data area accordingly (4 bytes × max stations + 4-byte header).
- DP/PA couplers: For PROFIBUS-PA segments behind a coupler, use SZL_ID W#16#0A92 in addition to W#16#0A91 — PA devices are not visible in the DP slave list.
- Subsequent re-parameterization: If a slave was disconnected at power-up, the CPU still parametrizes it after a configurable timeout. The SSL status byte then transitions from B#16#11 to B#16#00 if the slave returns. To avoid false "station OK" flags, do not read the SSL too early in OB100.
- Faults cleared during OB100: OB100 must complete before OB1 starts. If the diagnostic DB is non-retentive and OB100 fails to populate it, OB1 will read zeros. Wrap the SFC51 call in a status check and refuse to leave OB100 if the read failed (BU/Be for monitoring only — do not block startup unless absolutely required).
- CPU 410 (newer H family): The same pattern applies. Use SZL_ID W#16#0A91 with INDEX = 0 in OB100. S7-400H-specific SSL W#16#0118 is unchanged.
- Time stamping: When logging fault timestamps, use SFC1 (READ_CLK) inside OB86 — not SFC51. The SSL itself does not carry timestamps; it carries current status only.
14. Frequently Asked Questions
Why does OB86 not fire at power-up when a DP slave is missing?
OB86 is edge-triggered. The CPU only generates OB86 when a station transitions between present and absent during RUN. If the slave is already absent when the CPU first scans it during restart, no edge occurs and OB86 is never called. Use SFC51 with SZL_ID W#16#0A91 in OB100 or OB102 to query the current SSL status directly.
Which SZL_ID should I use to read the DP slave diagnostic status?
Use W#16#0A91 (DP slave diagnostic status). Call SFC51 with INDEX = 0 to get a full extract of all configured DP slaves. Each record is 4 bytes: status byte, reserved byte, and the 2-byte DP station address. A status byte of B#16#00 indicates the slave is OK; B#16#11 indicates a faulty slave; B#16#33 indicates an unconfigured address.
Should the diagnostic DB be retentive or non-retentive?
For a clean implementation, mark the diagnostic DB as non-retentive and use the OB100 / OB102 SSL scan to repopulate it at every restart. This prevents stale flags from before power-down. If retention is required, use OB100 to clear the DB and then repopulate from the SSL — never rely on OB86 alone for the initial state.
Does the same issue affect OB82 diagnostic interrupts?
Yes. OB82 (module diagnostic interrupt) is also edge-triggered. Diagnostic events that exist at the moment of power-up will not trigger OB82. The SZL_IDs W#16#00B1 (diagnostic data of a module) and W#16#00B3 (DS0/DS1 diagnostic records) can be polled in OB100 to detect existing module faults. Index with the logical base address of the slot.
How does this change for S7-400H redundant systems?
The principle is identical, but additional SSLs apply. Use SZL_ID W#16#0118 in OB100 to read H-system redundancy status, and populate H-specific fault tracking for OB70 (I/O redundancy loss) and OB72 (CPU redundancy error) the same way. On H systems, ensure the OB100 SSL scan runs after the sync link is established, or delay the H-state evaluation to the first OB1 cycle.
What is the maximum number of DP slaves supported by SZL_ID W#16#0A91?
The partial list extract length depends on the CPU. S7-416 and S7-417 support up to 64 DP slaves per master system and multiple master systems. Allocate the destination area generously (e.g., 32 × 4 bytes for one DP master system, 64 × 4 bytes for two) and check the SZL_HEADER.n_records field to determine the actual count returned.