S7-400 SFC 51 SSL W#16#0174 CPU LED Status: Fixing Error 8081

David Krause11 min read
S7-400SiemensTroubleshooting
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

1. Overview

On Siemens S7-400 / S7-400H controllers the SFC 51 "RDSYSST" (Read System Status List) is the canonical mechanism to read diagnostics data such as module identification, diagnostic buffer excerpts, and the live CPU front-panel LED status. The relevant partial list is SZL ID W#16#0174 (decimal 372), which reports the current state of every LED exposed by the CPU or an interface (IF) module.

On a CPU 412-5HK06 (6ES7 412-5HK06-0AB0) – an S7-400H high-availability CPU – users frequently hit RET_VAL = W#16#8081 the first time they call SFC 51 with this SSL ID. The error is almost always a buffer-length / DR-struct mismatch, not a hardware defect or a missing SZL. This article documents the SZL layout, the error-code root cause, and the exact struct expansion that resolves the issue.

2. SFC 51 / RDSYSST Fundamentals

SFC 51 reads one partial list extract of the System Status List (SSL). The block is declared as follows in the S7-300/400 system library:

// CALL SFC 51 (RDSYSST)
//   REQ      := TRUE
//   SZL_ID   := W#16#0174      // LED status partial list
//   INDEX    := W#16#000D      // LED identifier (e.g. REDF)
//   SZL_LEN  := 0               // 0 = use implicit max length
//   DR       := P#DBX0.0 BYTE 30 // destination buffer
//   BUSY     := M10.0
//   RET_VAL  := MW12

When SZL_LEN = 0 the CPU writes the maximum number of records for the requested ID/index combination. The DR pointer must reference an ANY pointer that is large enough to hold the entire SZL header plus the full set of records; otherwise SFC 51 returns 8081h. The official Siemens reference for the block is the RDSYSST — Read system status list (S7-300, S7-400) documentation page in the TIA Portal help system.

3. SZL W#16#0174 Data-Record Layout

Each call to SFC 51 with SZL_ID = W#16#0174 returns the following binary structure inside the destination area pointed to by DR:

Offset Bytes Meaning
+0 2 SZL_ID (echo) – W#16#0174
+2 2 SZL_INDEX (echo) of first record
+4 2 Length of one SZL record (bytes)
+6 2 Number of records (n)
+8 2 × n Record[n].INDEX – LED identifier
+10 + 2n 1 Record[n].STATUS_1
+11 + 2n 1 Record[n].STATUS_2
+12 + 2n 2 Record[n].LED_STATUS – bit-coded state

Each record is therefore 8 bytes wide. The H-CPU returns more records than a standard S7-400 CPU because it must also publish the redundancy LEDs (REDF, MSTR, LINK) that the simplex CPUs do not have.

4. LED Index Mapping on CPU 412-5HK06

The SZL W#16#0174 exposes the following LED indices on a 6ES7 412-5HK06-0AB0 S7-400H CPU. The "Index (hex)" column is the value to pass to the SFC 51 INDEX input when a single LED is queried:

Index (hex) Index (dec) LED Meaning H-CPU only?
W#16#0001 1 INT Internal fault No
W#16#0002 2 EXT External fault No
W#16#0003 3 BUS1F Bus 1 fault (PROFIBUS DP1) No
W#16#0004 4 BUS2F Bus 2 fault (PROFIBUS DP2 / MPI) No
W#16#0005 5 IFM1F Interface module 1 fault No
W#16#0006 6 IFM2F Interface module 2 fault No
W#16#0007 7 LINK PROFINET / sync link status H-CPU
W#16#0008 8 RX/TX Optical sync cable activity H-CPU
W#16#0009 9 MSTR Master role indicator H-CPU
W#16#000A 10 (reserved) – –
W#16#000B 11 (reserved) – –
W#16#000C 12 RUN RUN state LED No
W#16#000D 13 REDF Redundancy fault LED H-CPU
W#16#000E 14 STOP STOP state LED No
Note: The RUN and STOP LEDs are not read with INDEX 4 – INDEX 4 is the BUS2F LED. Reading the RUN LED requires INDEX W#16#000C. Reading the redundancy-fault LED (REDF) on a 412-5HK06 requires INDEX W#16#000D, the value the discussion thread eventually settled on.

5. RET_VAL 8081h – Root Cause

The SFC 51 RET_VAL codes reported in the STEP 7 System and Standard Functions manual are reproduced below. Only the codes relevant to SZL W#16#0174 are shown:

RET_VAL Meaning (SZL read) Likely cause with W#16#0174
W#16#0000 No error –
W#16#8081 Result length is larger than the destination area (DR) that was passed DR struct is too small – the SZL contains more records than the buffer can hold
W#16#8082 SZL header is wrong DB / area no longer matches the ANY pointer; check LEN byte
W#16#8083 SZL_ID/INDEX is wrong Did you pass the ID/INDEX combination that the CPU supports?
W#16#8090 Module does not support this SZL SSL W#16#0174 not implemented in the firmware of the queried module
W#16#8091 SZL_ID is not supported Typo – e.g. 17A instead of 174
W#16#8092 INDEX is not supported Index 4 is BUS2F, not RUN; use 0C for RUN, 0D for REDF
W#16#80C1 SZL is currently being processed by another job Two OB1 calls to SFC 51 racing on the same SZL
W#16#80C3 Internal error CPU firmware bug; update to ≥ V6.0.7 on 412-5HK06

For the symptom "RET_VAL = 8081 on a 412-5HK06, always, with every INDEX" the dominant root cause is the DR buffer is undersized. The H-CPU publishes 14 LED records (8 bytes each) plus an 8-byte SZL header – a total of 120 bytes – but the example struct in the question only contained 1 WORD + 2 BYTE = 4 bytes. SFC 51 detects the overflow and returns 8081h.

6. Prerequisites

  • STEP 7 V5.5 SP2 or later (TIA Portal V13+ for the documentation link above), with the optional S7-400H package installed.
  • S7-400 / S7-400H CPU with firmware ≥ V6.0 (6ES7 412-5HK06-0AB0 ships with V6.0.6 from the factory; 6.0.7 fixes the 80C3 path).
  • Knowledge of the SZL index you actually need (RUN = 0C, REDF = 0D on a 412-5HK06).
  • A free DB (preferably instance DB) of at least 120 bytes in the work-memory area accessible to the call (the S7-400H allows DB 0 – DB 65535).

7. Step-by-Step: Resolving RET_VAL 8081 on the 412-5HK06

  1. Create the destination DB. Open the S7 program in STEP 7 and add a new DB (e.g. "DB_LED") with a length of 120 bytes. The block must be set as a non-optimised access block (classic DB) for the ANY pointer to work correctly.
  2. Declare a STRUCT that mirrors the SZL header plus the 14 records. The declaration must start at byte 0 of the DB:
DATA_BLOCK "DB_LED"
{ S7_Optimized_Access := 'FALSE' }
VERSION : 0.1
  STRUCT
    SZL_ID       : WORD;    // +0   echoed SSL ID
    SZL_INDEX    : WORD;    // +2   echoed first INDEX
    SZL_LEN      : WORD;    // +4   length per record (bytes)
    SZL_NREC     : WORD;    // +6   number of records returned
    LED_INDEX    : ARRAY[1..14] OF WORD;    // +8   record INDEX
    LED_STATUS1  : ARRAY[1..14] OF BYTE;    // +36  record STATUS_1
    LED_STATUS2  : ARRAY[1..14] OF BYTE;    // +50  record STATUS_2
    LED_STATE    : ARRAY[1..14] OF WORD;    // +64  bit-coded LED state
  END_STRUCT;
END_DATA_BLOCK
  1. Call SFC 51 with the corrected ANY pointer. The ANY must span all 120 bytes:
CALL "RDSYSST" (
       REQ     := TRUE,
       SZL_ID  := W#16#0174,
       INDEX   := W#16#0000,            // 0 = all LEDs in the SZL
       SZL_LEN := 0,                    // let CPU choose max length
       DR      := P#DB_LED.DBX0.0 BYTE 120,
       BUSY    := M 10.0,
       RET_VAL := MW 12);
  1. Poll BUSY / RET_VAL. With REQ = TRUE, evaluate RET_VAL: any non-zero value means the call failed – see the table in §5.
  2. Decode the LED you need. After a successful call, the field DB_LED.LED_STATE[i] holds the bit-coded state of the i-th LED. The bit pattern for S7-400 / S7-400H is:
LED_STATE value Visual state
W#16#0000 LED off
W#16#0001 Green, steady
W#16#0002 Green, flashing
W#16#0003 Red, steady
W#16#0004 Red, flashing
W#16#0005 Yellow, steady
W#16#0006 Yellow, flashing
  1. Read a single LED by index. If you only need the REDF LED, narrow the call down with INDEX = W#16#000D. SFC 51 then returns exactly one record (8 bytes) so the buffer can be much smaller:
DATA_BLOCK "DB_REDF"
{ S7_Optimized_Access := 'FALSE' }
VERSION : 0.1
  STRUCT
    SZL_ID    : WORD;
    SZL_INDEX : WORD;
    SZL_LEN   : WORD;
    SZL_NREC  : WORD;
    REDF_IDX  : WORD;
    REDF_ST1  : BYTE;
    REDF_ST2  : BYTE;
    REDF_LED  : WORD;     // 0=off, 1=green, 3=red, 4=red-flashing
  END_STRUCT;
END_DATA_BLOCK

8. Sample Structured-Text (SCL) Implementation

FUNCTION_BLOCK FB_LED_Read
VAR
    dbLed     : INT := 100;        // DB_LED number
    retVal    : INT;
    busy      : BOOL;
    i         : INT;
END_VAR
BEGIN
    IF NOT busy THEN
        RDSYSST(REQ    := TRUE,
                SZL_ID := 16#0174,
                INDEX  := 16#0000,
                SZL_LEN:= 0,
                DR     := P#"DB_LED".DBX0.0 BYTE 120,
                BUSY   := busy,
                RET_VAL:= retVal);
    END_IF;

    IF retVal <> 0 THEN
        // Error path – see error table in §5
        RETURN;
    END_IF;

    // Iterate through the records returned
    FOR i := 1 TO WORD_TO_INT("DB_LED".SZL_NREC) DO
        CASE "DB_LED".LED_INDEX[i] OF
            16#000C: // RUN LED
                ; // publish RUN state to HMI / tag
            16#000D: // REDF LED
                ; // publish REDF state to HMI / tag
            16#0009: // MSTR LED
                ; // master role status
        END_CASE;
    END_FOR;
END_FUNCTION_BLOCK

9. Verification Procedure

  1. Compile and download the program to the standby CPU of the 412-5HK06 H-system first; then perform a switchover and download to the master.
  2. Go online and open DB_LED in the watch table. The first four words must echo SZL_ID = W#16#0174, the first INDEX of the partial list, the record length (W#16#0008) and the record count.
  3. Toggle the CPU into STOP via the mode selector; LED_STATE[14] (STOP) must change to W#16#0001 (green steady) and LED_STATE[12] (RUN) must change to W#16#0000 (off). On a 412-5HK06 the STOP LED on the front panel will not change because the redundancy partner is still in RUN; the SZL nevertheless reports the local CPU state.
  4. Pull one of the sync cables to provoke a REDF event; LED_STATE[13] (REDF) must change to W#16#0003 or W#16#0004 within one OB1 cycle.
  5. Force SZL_LEN = 8 and RET_VAL must remain W#16#0000 – this proves that a 4-byte buffer would have overflowed the SZL and confirms the 8081 root cause.

10. Troubleshooting Matrix

Symptom RET_VAL Root cause Remedy
Always 8081, every call 8081h DR too small for the number of LED records returned by the H-CPU Expand the DB to ≥ 120 bytes and pass the full 120 bytes in the ANY
8081 only on REDF 8081h Reused an SZL buffer originally sized for a standard S7-400 CPU (60 bytes) Re-size to 120 bytes; S7-400H returns 14 records
8081 after firmware update 8081h New firmware added LED records beyond the previous total Re-read the SZL_LEN field and resize the DB
8081 then 8091 8091h Typo in SZL_ID (e.g. 17A) Use exactly W#16#0174
8081 then 8092 8092h Index not supported – e.g. 0004 used to query RUN Use W#16#000C for RUN, W#16#000D for REDF on a 412-5HK06
Works once, then 80C1 80C1h Concurrent SFC 51 calls on the same SZL Sequence calls with a single BUSY handshake or use a global semaphore
Returns no records 0000h INDEX filter excludes all records Pass INDEX = W#16#0000 to read the whole SZL
RET_VAL=0, LED_STATE always 0 0000h DR written to a non-existent / wrong DB Check the DB number in the ANY pointer

11. Variant Notes: S7-300, S7-400, S7-400H

The SZL W#16#0174 is implemented on S7-300 CPUs starting with firmware V2.0, on all S7-400 CPUs, and on every S7-400H CPU. The record count differs:

  • S7-300 (e.g. 319-3 PN/DP, 6ES7 318-3FL01-0AB0): typically 7 LED records – INT, EXT, BUS1F, BUS2F, IFM1F, IFM2F, RUN, STOP. Buffer 64 bytes is sufficient.
  • S7-400 standard (e.g. 416-3, 6ES7 416-3XR05-0AB0): 10 LED records. Buffer 88 bytes is sufficient.
  • S7-400H (e.g. 412-5HK06, 6ES7 412-5HK06-0AB0): 14 LED records (RUN, STOP, REDF, MSTR, LINK, RX/TX plus the standard fault LEDs). Buffer 120 bytes is required.

For S7-1500 the equivalent block is RDSYS_T (instruction "Read system status") – the LED partial list still uses SZL W#16#0174 but is published as a typed PLC tag instead of a raw byte buffer.

Why does SFC 51 return 8081h when I read SZL W#16#0174 on a CPU 412-5HK06?

RET_VAL 8081h means the destination area (DR) you passed to SFC 51 is smaller than the partial-list extract the CPU wants to write. The 412-5HK06 publishes 14 LED records (8 bytes each) plus an 8-byte SZL header, i.e. 120 bytes. A 4-byte buffer therefore overflows immediately and SFC 51 reports 8081h. Resize the destination DB and the ANY pointer to 120 bytes.

What is the correct SFC 51 INDEX to read the REDF LED on a 412-5HK06 H-CPU?

Use INDEX = W#16#000D (decimal 13). The H-CPU exposes REDF, MSTR, LINK, RX/TX, RUN, STOP and the standard fault LEDs through SZL W#16#0174 at indices 1 – 14. Reading only the REDF LED needs a destination buffer of exactly 16 bytes (SZL header 8 bytes + one record 8 bytes).

Can I read the RUN LED with INDEX 4?

No. INDEX 4 (W#16#0004) is the BUS2F LED (PROFIBUS DP2 / MPI fault). The RUN LED is INDEX W#16#000C and the STOP LED is INDEX W#16#000E on every S7-400 and S7-400H CPU. Using the wrong index returns RET_VAL 8092h (index not supported) on the H-CPU firmware 6.0.6 and later.

Which SZL ID gives me the current CPU operating mode (RUN / STOP / HOLD)?

The LED status of the RUN/STOP LEDs is in SZL W#16#0174 (INDEX 0C / 0E). For the actual mode word (STARTUP, RUN, STOP, HOLD, LINK-UP, UPDATE, …) use SZL W#16#0019 "Status of the priority classes" or read OB 1 / OB 100 / OB 101 start information. The CPU operating-state byte in the diagnostic buffer is also available via SZL W#16#0131 / W#16#0132.

Do I have to expand the DR struct for every firmware update?

Yes. Each firmware release can add new LED records (e.g. a new FO synchronization LED on 412-5H firmware V6.0.7 added the RX/TX record). The safest practice is to always read SZL W#16#0174 with INDEX = W#16#0000 and a buffer ≥ 120 bytes, then iterate over SZL_NREC records. The official reference is the RDSYSST documentation.

Back to blog