Overview
The Siemens SIMATIC S7-300/400 CPUs expose a large set of internal diagnostic and runtime data through partial System State Lists (SSL / SZL). The standard function block SFC51 "RDSYSST" (Read System State) is the PLC-side mechanism for retrieving these partial lists at runtime, while STEP 7 / TIA Portal use them implicitly when the user opens Ctrl+D > Module Information from a PG/PC.
The Module Information dialog (online > target system > module information) shows nine categories:
- General
- Diagnostic Buffer
- Memory
- Performance Data
- Identification
- Time System
- Scan Cycle Time
- Stacks
- Communication
Items 1-5 are documented partial lists accessible through SFC51. Items 6-9 either require a different SFC, are only available via OB1 temporary variables, are only meaningful in STOP/HOLD, or can only be read by the engineering tool (PG) over MPI/PROFINET — not from user program code.
SFC51 RDSYSST Interface
SFC51 is part of the IEC standard block library on every S7-300/400 CPU (and on S7-1500 as "RDSYSST" inside the legacy SFC compatibility set). The full call signature is:
// STL call example
CALL SFC 51
SSL_ID := W#16#xy11 // partial list selector (see below)
INDEX := W#16#0001 // sub-index / object ID
RET_VAL := MW100 // return value (error code)
BUSY := M101.0 // 1 = read in progress
RD := P#M 200.0 BYTE 200 // destination area
DR := MW104 // length of data returned (bytes)
Parameters:
| Parameter | Type | Description |
|---|---|---|
SSL_ID |
WORD | Partial-list identifier. The high byte is the list ID, the low byte encodes module class (0x11 = CPU, 0x12 = IM, 0x14 = CP, 0x15 = FM, 0x16 = DI, 0x17 = DO, 0x18 = AI, 0x19 = AO, 0x1B = F-CPU, 0x1C = F-DI, 0x1D = F-DO, 0x84 = CP-200, 0x87 = DP slave, 0xA0 = OB, etc.). |
INDEX |
WORD | Object index: rack/slot, OB number, DP station, etc. Pass 0x0000 if not used. |
RET_VAL |
INT | Status; 0 = OK, <0 = error, >0 = warning. |
BUSY |
BOOL | TRUE while asynchronous read is active. Always FALSE for single-word partial lists, TRUE for multi-record reads (e.g., diagnostic buffer scan). |
RD |
ANY | Destination pointer; must be large enough for the partial-list record. |
DR |
WORD | Number of bytes actually written by the CPU. |
SSL_ID with the low byte set to a specific module class (e.g., 0x14 = CP) addresses that module class only. Set the low byte to 0x00 to query all modules of the requested list. For example, W#16#0011 requests module identification of every module, W#16#1111 requests identification of the CPU only.SSL ID Reference Table
The table below lists the documented partial lists relevant to each Module Information tab. xx denotes the module-class byte described above. All values are in hexadecimal.
| SSL_ID | Module Info Tab | Purpose | INDEX | Typical Record Size |
|---|---|---|---|---|
| W#16#0011 | General / Identification | Module identification (order number, hardware/firmware version, serial number, plant identifier) | Rack/slot or 0 | 34 bytes / module |
| W#16#0012 | Identification | CPU characteristics (MMC present, operating mode capability, redundancy role) | 0 | 34 bytes |
| W#16#0013 | Memory | User memory areas (work, load, retentive) in bytes | 0 | 28 bytes |
| W#16#0014 | Performance Data | System memory areas (PI, PII, bit memories, counters, timers) | 0 | 28 bytes |
| W#16#0015 | Performance Data | Bit memory, counter, timer ranges | 0 | 26 bytes |
| W#16#0019 | Communication | CP-300/400 status (SZL 0x131 - transmission rate, link status, resources) | Slot of CP | 34 bytes |
| W#16#001C | Time System | Time-of-day interrupt status (OB10-OB17 active flags) | 0 | 8 bytes |
| W#16#0021 | Diagnostic Buffer | Cause of STOP (startup, error OB, OB not loaded) | 0 | 4 bytes |
| W#16#0022 | Scan Cycle Time | Cycle, shortest, longest cycle (SZL 0x222) - 32-bit ms values | 0 | 16 bytes |
| W#16#0024 | Time System | Current time-of-day (SZL 0x224) - 8 bytes BCD | 0 | 8 bytes |
| W#16#0025 | Time System | Time-sync status (last sync source, drift) | 0 | 24 bytes |
| W#16#0031 | Communication | Communication status data SZL 0x131 (CPU-300/400) | 0 | 32 bytes |
| W#16#0032 | Communication | Communication status data SZL 0x132 (CPU-300/400 connection resources) | 0 | 34 bytes |
| W#16#0071 | Identification | H-CPU redundancy status (only S7-400H) | 0 | 10 bytes |
| W#16#0091 | General | Module status information (station/DP slave error bitmap) | Rack | 32 bytes |
| W#16#0092 | General | Rack / station status | 0 | 34 bytes |
| W#16#00A0 | Diagnostic Buffer | Diagnostic buffer header (number of entries, newest/oldest) | 0 | 12 bytes |
| W#16#00B1 | Diagnostic Buffer | Diagnostic buffer entry (event) 1 (newest) | 1 | 20 bytes |
| W#16#00B2 | Diagnostic Buffer | Diagnostic buffer entry 2 | 2 | 20 bytes |
| W#16#00B3 | Diagnostic Buffer | Diagnostic buffer entry 3 | 3 | 20 bytes |
| W#16#00B4 | Diagnostic Buffer | Diagnostic buffer entry 4 (oldest of four accessible) | 4 | 20 bytes |
| W#16#00D0 | General | LED status (SF, BF, RUN, STOP) | 0 | 2 bytes |
| W#16#00E0 | General | Last warm/cold restart startup information | 0 | 20 bytes |
| W#16#00F1 | Stacks | I-Stack / B-Stack (only available in STOP / HOLD) | 0 | variable |
SSL_ID W#16#0000 returns the catalog of all supported partial lists for the addressed module class. Query this first to discover which lists the target CPU actually exposes — older CPUs (e.g., CPU 314, CPU 412-1) implement a strict subset of the full catalog.
Module Information Tabs Not Readable Through SFC51
Three of the nine categories shown in Ctrl+D > Module Information are not reachable by SFC51 in RUN. Substitute mechanisms are listed:
| Category | Mechanism | Notes |
|---|---|---|
| Time system — current time | SFC1 READ_CLK | Returns DATE_AND_TIME (8-byte BCD). Replaces SZL 0x224 from user code. |
| Time system — runtime meter | SFC4 / SFC101 | SFC4 reads the 16-bit hour counter; SFC101 reads 32-bit counters on newer CPUs. |
| Time system — sync info | Not user-readable | Modifies only on hardware reload (SFC82 / SFC84 / MMC write). |
| Scan cycle time | OB1 temporary variables |
OB1_PREV_CYCLE, OB1_MIN_CYCLE, OB1_MAX_CYCLE in milliseconds. |
| Stacks | Not available in RUN | Stacks (I, B, L) are valid only in STOP / HOLD; program is not running so the diagnostic only helps during STOP. |
| Communication — transmission rate | Not user-readable | Configured at hardware-config time; only PG/PC online tools can read it. |
| Communication — connection count | PG/PC tools only | STEP7 / WinCC reads SZL 131 and 132. Some CPUs block SFC51 access to these lists. |
Working Example: Scan Cycle Time
The cleanest runtime read of scan-cycle time uses the OB1 temporary interface, declared automatically when OB1 is opened:
// OB1 temp declarations
VAR_TEMP
OB1_EV_CLASS : BYTE; // Bits 0-3 = 1, bits 4-7 = 1
OB1_STRT_INF : BYTE;
OB1_PRIORITY : BYTE;
OB1_OB_NUMBR : BYTE;
OB1_RESERVED_1 : BYTE;
OB1_RESERVED_2 : BYTE;
OB1_PREV_CYCLE : DWORD; // ms - last cycle
OB1_MIN_CYCLE : DWORD; // ms - shortest cycle
OB1_MAX_CYCLE : DWORD; // ms - longest cycle
OB1_DATE_TIME : DATE_AND_TIME;
END_VAR
Move the values into process data or a DB on every OB1 cycle to make them visible to HMI / OPC:
L OB1_PREV_CYCLE
T DB100.DBD0 // last cycle [ms]
L OB1_MIN_CYCLE
T DB100.DBD4 // min cycle [ms]
L OB1_MAX_CYCLE
T DB100.DBD8 // max cycle [ms]
For CPUs without OB1 temps (older S7-300 types), fall back to SFC51 with SSL_ID = W#16#0022; the returned 16 bytes contain the same three counters in the order last, shortest, longest, current OB1 priority.
Working Example: Diagnostic Buffer Scan
The diagnostic buffer keeps the last 200 events on a CPU 414-3. SFC51 supports two modes:
-
Single-record mode: read entry n with
SSL_ID = W#16#00Bn,INDEX = n,RDminimum 20 bytes. -
Multi-record mode: pass
SSL_ID = W#16#00B1and anINDEX = 1; the CPU fills the destination with as many full 20-byte entries as fit and returnsDRwith the byte count.
// Ladder / FBD equivalent
A M 100.0 // Trigger: rising edge once per minute
JCN END1
CALL SFC 51
SSL_ID := W#16#00A0 // Buffer header
INDEX := W#16#0000
RET_VAL:= MW110
BUSY := M111.0
RD := P#DB110.DBX0.0 BYTE 12
DR := MW112
END1: NOP 0
Decode DB110.DBD0 for number-of-entries and DB110.DBD4 for newest-event index, then read each event with the matching W#16#00Bn list.
Working Example: Current Time of Day
CALL SFC 1 // READ_CLK
RET_VAL := MW200
CDT := DB120.DBD0 // DATE_AND_TIME (8 bytes BCD)
The 8 bytes are coded YYYY-MM-DD hh:mm:ss weekday in BCD, allowing direct forward to an HMI time field without conversion. SZL 0x224 returns the identical bytes; SFC1 is preferred because it is one call rather than two-stage (catalog lookup + data read).
ModuleStates Instruction (S7-1200 / S7-1500)
On S7-1200 / S7-1500, SFC51 is replaced by the ModuleStates extended instruction. It returns a bit list of the operational states of distributed I/O modules on PROFINET or PROFIBUS without the partial-list indirection. See the SIMATIC S7-1200 manual collection for the full reference: ModuleStates — Read module status information of a module.
// SCL example, S7-1500
"DB_ModStates"(REQ := TRUE,
LADDR := 0,
STATE := "dbModBitList",
RETVAL := "iwRet");
Each bit of STATE represents one module. A 0 bit means the module is error-free; a 1 means it is in fault / not accessible. The bit position follows the configured slot order, so users can build HMI error lists directly without parsing SZL records.
STATUS = W#16#80C3 (instruction not supported). Program code written for S7-300/400 with SFC51 must be ported, not re-linked.Error Codes (SFC51 RET_VAL)
| RET_VAL | Meaning | Action |
|---|---|---|
| 0000 | OK, data copied | Proceed. |
| 7000 | Job accepted, BUSY = TRUE | Wait; re-call on next cycle. |
| 8090 | SSL_ID invalid or not supported on this CPU | Read SSL_ID 0x0000 catalog first. |
| 8092 | RD length too small | Increase the ANY pointer length. |
| 8093 | INDEX invalid for the requested list | Check INDEX semantics per table above. |
| 80A1 | Partial list not available on the requested module | Re-query with module-class byte = 0x00. |
| 80B1 | Module does not exist at this address | Verify rack/slot in HW Config. |
| 80C1 | Buffer overflow — read more entries than available | Reduce RD size; query header first. |
| 80C3 | Resource exhausted / not available in current operating mode | Check RUN mode; verify firmware level. |
| 80D0 | Stacks / B stack — CPU not in STOP | Only valid in STOP/HOLD. |
| 8xyy | General error — see SFC51 help in STEP 7 | Refer to the block help inside STEP 7 F1. |
Verification & Commissioning Steps
- In STEP 7, place SFC51 on a cyclic OB (OB1 or OB35). Wire the desired SSL_ID and a destination DB sized large enough for the longest record (use 200 bytes to cover the diagnostic buffer header).
- Compile and download. Force the trigger bit, then monitor the destination DB online.
- Open Ctrl+D > Module Information on the same PG/PC and compare each tab to the data placed in the DB; values must match to the byte.
- For diagnostic buffer, capture the first 20 entries by iterating
W#16#00B1..W#16#00B4four times with INDEX = 1, 2, 3, 4 — four is the maximum number of single-record reads per SFC51 invocation on S7-400. For deeper scans, run multiple OB1 passes. - For cycle time, verify against
OB1_PREV_CYCLE. If values differ, suspect a CPU under scan-load that is masking the cycle counter. - Disconnect PG online and run a control panel test that polls the DB to prove the values are visible without engineering tools.
Troubleshooting Matrix
| Symptom | Likely Cause | Countermeasure |
|---|---|---|
| RET_VAL = 8090, BUSY = 0 | SSL_ID high byte unsupported | Read catalog W#16#0000 and pick a listed list. |
| RET_VAL = 8092 | RD too small | Increase ANY length to documented record size; for diagnostic buffer use 200 bytes. |
| RD zeroed but RET_VAL = 0 | INDEX = 0 for a list that needs slot index | Set INDEX to rack/slot per the table. |
| Cycle time = 0 | Reading OB1 temp before OB1 first pass | Place reads inside OB1, not OB100. |
| Stack data empty | CPU in RUN, not STOP | Stacks only meaningful in STOP; trigger from startup OB if STOP is acceptable. |
| Time-of-day zeroed | Clock not set | Use SFC0 SET_CLK or NTP via SFC82 / SFC84. |
| SZL 131/132 returns 80A1 | CPU firmware blocks SFC51 access | Use PG-side online view only; alternative: read CP status via SZL 0x131 (CP class) and parse locally. |
| Connection count off by 1 | Diagnostic connection not counted | Exclude slot 0.0; the diagnostic connection is internal. |
| Different values in PG vs. user program | PG reads live, program reads cached | Re-call SFC51 each scan; do not latch older results across many cycles. |
Field-Proven Caveats
W#16#0011 returns a list that includes the CPU itself plus every addressable module. W#16#1111 returns the same list filtered to CPUs only. Mixing the bytes incorrectly is the single most common source of RET_VAL = 80A1.W#16#0031/0032 returns 0 bytes or RET_VAL = 8090. Treat the partial-list catalog (W#16#0000) as the authoritative reference, not the manual.Related Function Blocks
| Block | Purpose | When to Use Instead of SFC51 |
|---|---|---|
| SFC1 READ_CLK | Current time-of-day | Always, for time of day. |
| SFC2 SET_RTM / SFC3 CTRL_RTM / SFC4 READ_RTM | Runtime meter | Hours since last reset; not in Module Information but adjacent topic. |
| SFC6 RD_SINFO | Start info of OB that triggered OB1 | Detect which OB interrupted. |
| SFC13 DPNRM_DG | PROFIBUS diagnostic of a DP slave | Per-slave diagnostics beyond SZL. |
| SFC51 RDSYSST | The block itself | Anything SSL/SZL based. |
| SFC59 RD_REC | Read record from an I/O module | DS0/DS1 records; identifier-related diagnostics. |
| SFC87 C_DIAG | Receive complete diagnostics from module | S7-1500 replacement for SFC51 with structured events. |
Which SSL_ID do I use to read the scan cycle time from SFC51?
Use SSL_ID = W#16#0022 with INDEX = W#16#0000. The destination receives 16 bytes containing the last, shortest, and longest OB1 cycle time in milliseconds. On CPUs without SFC51 support for this list, read the OB1 temporary variables OB1_PREV_CYCLE, OB1_MIN_CYCLE, and OB1_MAX_CYCLE instead.
Can the diagnostic buffer be read through SFC51, and how many entries?
Yes. Use SSL_ID W#16#00A0 for the header (number of entries, newest/oldest index) and W#16#00B1..W#16#00B4 for the four newest event records, 20 bytes each. The diagnostic buffer holds 200 entries on a CPU 414-3, but SFC51 only returns four per call; scan the buffer with repeated invocations.
Why does SFC51 fail with RET_VAL = 8090 when I call W#16#0031 / W#16#0032?
SSL_ID W#16#0031 and W#16#0032 (communication status, SZL 131/132) are reserved for PG/PC access on many S7-400 firmware versions and are blocked for user-program calls. Run the partial-list catalog W#16#0000 first; if 0x31/0x32 are not listed, read the connection data with PG-side tools or use SFC62 / SFC63 for connection status.
How do I read the B stack in RUN, or do I have to stop the CPU?
You cannot meaningfully read the B stack in RUN. The B stack is populated only when the CPU goes to STOP due to a programming error, and once the CPU is in STOP the user program does not execute. For runtime fault diagnostics, use the diagnostic buffer (SZL 0xB1) and SFC6 RD_SINFO instead.
Is there a S7-1200 / S7-1500 replacement for SFC51?
Yes. On S7-1200 firmware V4.2+ and S7-1500 firmware V1.7+, use the ModuleStates extended instruction for module status bits, and the system diagnostics blocks (SFC87 C_DIAG, RDREC, GET_DIAG) for full event records. SFC51 itself remains available as a legacy block on S7-1500 but its SSL catalog is a strict subset of the S7-400 set.