Reading Siemens S7 Module Information via SFC51 and SSL IDs

David Krause13 min read
PLC HardwareSiemensTechnical Reference
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

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:

  1. General
  2. Diagnostic Buffer
  3. Memory
  4. Performance Data
  5. Identification
  6. Time System
  7. Scan Cycle Time
  8. Stacks
  9. 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.
Critical rule: 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.
Field practice: For S7-400 CPUs of the 414-3 / 416-3 / 417-4 generation (e.g., 6ES7 414-3XJ04-0AB0), STEP 7 version compatibility matters. SZL 131/132 cannot be read with SFC51 on every firmware release; restrict those calls to PG-side diagnostics or to S7-1500 where the equivalent data is exposed through the system diagnostics block set.

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:

  1. Single-record mode: read entry n with SSL_ID = W#16#00Bn, INDEX = n, RD minimum 20 bytes.
  2. Multi-record mode: pass SSL_ID = W#16#00B1 and an INDEX = 1; the CPU fills the destination with as many full 20-byte entries as fit and returns DR with 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.

Compatibility note: ModuleStates exists in TIA Portal V14 SP1 onward on S7-1200 firmware V4.2 and on S7-1500 from firmware V1.7. Older firmware returns 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

  1. 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).
  2. Compile and download. Force the trigger bit, then monitor the destination DB online.
  3. 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.
  4. For diagnostic buffer, capture the first 20 entries by iterating W#16#00B1..W#16#00B4 four 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.
  5. For cycle time, verify against OB1_PREV_CYCLE. If values differ, suspect a CPU under scan-load that is masking the cycle counter.
  6. 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

1. SZL_ID is module-class sensitive. 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.
2. Communication status SZL 131/132 are not part of every CPU firmware. The 414-3XJ04 firmware 4.x exposes them through PG/PC only. Calling SFC51 with 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.
3. B Stack read-back has no practical use. The stacks are populated only when the CPU transitions to STOP due to a programming error. By the time a user program could read them, the program itself is not executing. For field debugging, prefer SFC6 / SFC13 + the diagnostic buffer (SZL 0xB1).
4. OB1_PREV_CYCLE is updated at the start of OB1. Values written by user code during the cycle are not visible until the next OB1 pass; do not compare OB1_MAX_CYCLE against an immediate computed figure inside the same OB1 run.
5. SFC51 must not be called from OB40 / OB82. Diagnostic OBs run with limited priority; nested SFC51 calls may exceed their runtime budget and trigger OB80 (time error). Move SFC51 calls to OB1 or to a low-priority cyclic OB (OB30-OB38).

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.

Back to blog