PCS 7 S7 CPU Memory Consumption: SFC 51 RDSYSST Guide

David Krause15 min read
Process ControlSiemensTutorial / How-to
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: Reading CPU Memory Consumption in PCS 7 and SIMATIC S7

Plant operators running PCS 7 on SIMATIC S7-300, S7-400, S7-1500, or ET 200MP CPUs routinely need to monitor the live memory footprint of the controller: how much of the work memory is consumed by the user program, how much load memory is still available on the SIMATIC Memory Card, and how large the retentive memory segment has grown after years of recipe data. The TIA Portal online diagnostics and the SIMATIC Manager module information dialog both show a static snapshot, but neither is designed for cyclic reporting to WinCC, a historian, or a centralized asset monitoring tool. To expose those values as live tags you must read the System State Lists (SSL) directly from the CPU using SFC 51 RDSYSST with SSL partial list W#16#0113.

This reference covers the full engineering workflow: the underlying S7-1500/ET 200MP memory model, the parameter set of SFC 51, the exact data structure returned by SSL_ID 0113, ready-to-paste SCL and STL implementations, integration of the resulting tags into WinCC, the limits of the PCS 7 @CPU_RT block, and a troubleshooting matrix for the most common error codes returned by the function call.

Scope. SFC 51 (RDSYSST) is available on every S7-300, S7-400, S7-1500, WinAC, and ET 200SP/ET 200MP CPU that supports standard system functions. The SSL partial list described here (W#16#xy13) is part of the standard system diagnostics and is supported across all of these product families, although the exact memory sub-area codes vary slightly by CPU generation.

Prerequisites

  • SIMATIC PCS 7 V8.x or higher, or STEP 7 V5.5 / TIA Portal V15 or higher for S7-1500/ET 200MP engineering.
  • Firmware requirements for using the PCS 7 driver wizard block @CPU_RT (only relevant if you choose that path):
    • Single (non-redundant) S7-400 CPU: firmware 5.0 or higher.
    • Redundant H-CPU (e.g. CPU 410-5H): firmware 4.5 or higher.
  • The CPU must be in RUN or RUN-P mode to read SSL data.
  • An OB1 (or any cyclic OB) in which to call SFC 51.
  • A shared DB that buffers the returned memory values, or a tag group that is published to WinCC via the standard PCS 7 driver.
  • For S7-1500 specifically, reference the manual collection at the Siemens docs portal for the memory model of your specific CPU order number (e.g. CPU 1515-2 PN, CPU 1518-4 PN/DP, CPU 1513-1 PN).

Memory Architecture of S7-1500/ET 200MP CPUs

Before you read SSL data you must understand what the controller actually stores and where. The S7-1500/ET 200MP system separates memory into the following areas, as documented in the S7-1500/ET 200MP Manual Collection — Memory Requirements and Memory Usage:

Memory area Physical location Volatile? Typical use
Load memory SIMATIC Memory Card (SMC) No (card-backed) Code blocks (OB/FB/FC/DB), project data, system data
Work memory CPU-internal RAM Yes Runtime execution of code and data blocks
Retentive memory CPU-internal NVRAM / backed by SMC No Retentive bit memory, retentive DB contents, counters, timers
System memory CPU-internal RAM Yes Process image (I/O), bit memory (M), timers (T), counters (C)

When SSL partial list W#16#0113 is read, the CPU returns a row for each of these areas with the total size, the amount currently used, and (depending on CPU generation) the free remainder. The exact coding of the memory type identifier in the returned data record is documented in the SSL reference of your CPU's function manual.

S7-300/400 vs S7-1500 memory layout. On S7-300 and S7-400 the load memory is split between the integrated RAM and the flash card. On S7-1500 the load memory is the SIMATIC Memory Card only. Always interpret the SSL row's memory type identifier before assuming a physical location.

Method 1 — SFC 51 (RDSYSST) System State List Read

SFC 51 RDSYSST is the canonical way to read system state lists on every S7 CPU that supports the standard system function library. It is located in the Standard Library > System Function Blocks > DIAGNSTC folder of every STEP 7 and TIA Portal installation. The function is asynchronous on multi-read SSLs: you trigger the read, poll the BUSY output, and consume the data only after BUSY returns to FALSE with RET_VAL = 0.

Formal parameters of SFC 51

Parameter Declaration Type Description
REQ INPUT BOOL Rising edge starts the read of the requested SSL partial list.
SZL_ID INPUT WORD System state list identifier (e.g. W#16#0113).
INDEX INPUT WORD Object / sub-list index. Use W#16#0000 for the standard partial list.
RET_VAL OUTPUT INT Return value / error code (see troubleshooting matrix below).
BUSY OUTPUT BOOL TRUE while the read is in progress.
SZL_HEADER OUTPUT STRUCT STRUCT with LENTHDR (WORD, length of one data record) and N_DR (WORD, number of data records returned).
DR OUTPUT ANY Pointer to a work memory area that receives the data records. Must be a DB or a static instance; a local TEMP variable is not allowed because the read is asynchronous.

SSL_ID W#16#0113 — Module Memory Areas Partial List

SSL partial list W#16#0113 is the standardized request that returns the memory areas of the module. The xy in the official documentation form W#16#xy13 encodes whether the read should be performed synchronously or asynchronously, and whether the partial list should be re-read fully or incrementally — for cyclic monitoring use W#16#0113 (synchronous partial list read).

The SZL_HEADER tells you two things:

  • LENTHDR — length of one data record in bytes (e.g. 28 bytes for a typical S7-1500 memory row).
  • N_DR — number of data records actually returned. The S7-1500 typically returns 4 to 6 rows (one per memory area), older S7-400 firmware may return a different number.

Each returned data record contains, in this order on a typical S7-1500 CPU:

Offset (bytes) Field Type Meaning
0..1 Memory type code WORD Identifier of the memory area (work / load / retentive / system).
2..5 Total size DWORD Total size of the area in bytes.
6..9 Used size DWORD Currently used bytes.
10..13 Free size DWORD Remaining free bytes.
14..LENTHDR-1 Reserved / CPU-specific BYTE[] Vendor-specific fields, do not interpret.
Field variability. The exact data record layout (field order, padding, additional fields like "fragmentation" or "largest free block") is firmware-dependent. The table above is representative of current S7-1500 firmware. Cross-check the value of SZL_HEADER.LENTHDR at runtime and parse the data record by means of the actual length, not by hard-coded offsets, if you want portable code.

Implementation in Structured Text (SCL) for TIA Portal

The cleanest implementation is in SCL inside a function block (FB) that holds the asynchronous state. The FB is called once per cycle from OB1; the rising-edge detection on REQ prevents the SSL from being re-issued every cycle.

FUNCTION_BLOCK "FB_MemMon"
VAR
    bStart          : BOOL;          // rising-edge trigger
    bBusy           : BOOL;
    iRetVal         : INT;
    szlHeader       : STRUCT
        LENTHDR     : WORD;          // length of one DR in bytes
        N_DR        : WORD;          // number of DRs returned
    END_STRUCT;
    aDr             : ARRAY[0..15] OF DWORD;  // raw DR buffer (16 DWORD = 64 bytes)
    iDrLen          : INT;
    iDrCount        : INT;
    drWorkTotal     : DWORD;
    drWorkUsed      : DWORD;
    drLoadTotal     : DWORD;
    drLoadUsed      : DWORD;
    drRetainTotal   : DWORD;
    drRetainUsed    : DWORD;
    drSystemTotal   : DWORD;
    drSystemUsed    : DWORD;
END_VAR

BEGIN
    // Trigger a new read every 5 seconds (prescaler in OB1)
    IF bStart AND NOT bBusy THEN
        RDSYSST(
            REQ        := TRUE,
            SZL_ID     := W#16#0113,
            INDEX      := W#16#0000,
            RET_VAL    := iRetVal,
            BUSY       := bBusy,
            SZL_HEADER := szlHeader,
            DR         := aDr
        );
    ELSIF bBusy THEN
        // Poll the asynchronous read
        RDSYSST(
            REQ        := FALSE,
            SZL_ID     := W#16#0113,
            INDEX      := W#16#0000,
            RET_VAL    := iRetVal,
            BUSY       := bBusy,
            SZL_HEADER := szlHeader,
            DR         := aDr
        );
        IF NOT bBusy AND iRetVal = 0 THEN
            // Parse N_DR records of LENTHDR bytes each
            iDrCount := WORD_TO_INT(szlHeader.N_DR);
            // Application-specific parsing: walk aDr[] based on LENTHDR
            // and dispatch on Memory type code to the right output WORD.
        END_IF;
    END_IF;
END_FUNCTION_BLOCK

Implementation in STL (Statement List) for STEP 7 V5.x and PCS 7

For classic PCS 7 stations on S7-400 the same logic in STL is typically embedded in a small FB inside the master data library. The pattern is identical: fire REQ on a rising edge, poll BUSY, copy the DR to a global DB when BUSY = 0.

// In OB1, calling FB100 "FB_MemoryMonitor" once per cycle
CALL  FB100, DB100
      bStart := "tag_5s_tick"
      bBusy  := DB100.bBusy
      iRetVal:= DB100.iRetVal
      szlHdr := DB100.szlHdr
      aDR    := DB100.aDR
      // ...

// Inside FB100, network 1: rising edge + asynchronous call
A     #bStart
AN    #bBusy
JC    _DO
// BUSY poll path
CALL  SFC 51
      REQ    :=FALSE
      SZL_ID :=W#16#0113
      INDEX  :=W#16#0000
      RET_VAL:=#iRetVal
      BUSY   :=#bBusy
      SZL_HEADER:=#szlHdr
      DR     :=#aDR
      BE

_DO:  CALL  SFC 51
      REQ    :=TRUE
      SZL_ID :=W#16#0113
      INDEX  :=W#16#0000
      RET_VAL:=#iRetVal
      BUSY   :=#bBusy
      SZL_HEADER:=#szlHdr
      DR     :=#aDR
      BE

@CPU_RT Block in PCS 7 — What It Does and Does Not Provide

From PCS 7 V7.0 onward the driver wizard automatically inserts the APL block @CPU_RT into the AS program. It exposes runtime statistics of the CPU: OB cycle times (OB1, OB35, OB82, …), the current and average runtimes of the priority classes, and the communication load contributed by the five most active partners. Many engineers expect @CPU_RT to also report work and load memory — it does not. @CPU_RT is built on SFC 78 / SFC 79 and on SFB 52 (diagnostic data record read), not on SFC 51.

To expose memory statistics to WinCC in PCS 7, the recommended architecture is therefore:

  1. Create a small FB (e.g. FB100) that calls SFC 51 with W#16#0113, parses the data records, and writes the result to a dedicated DB (e.g. DB100) in the AS.
  2. Run the driver wizard so the DB100 tags appear in the WinCC tag list as "Memory.WorkUsed", "Memory.WorkTotal", "Memory.LoadUsed", "Memory.LoadTotal", "Memory.RetainUsed", "Memory.RetainTotal".
  3. Add the tags to a WinCC picture with a bar graph or a numeric I/O field; archive them with a 1-minute tag logging cycle if you need long-term trending.
Do not mix @CPU_RT with SFC 51 in the same OB cycle without staggering them. Both functions are slow operations; back-to-back calls in OB1 with a 100 ms cycle can stretch the OB1 runtime by 10 to 30 ms on S7-400 and significantly more on S7-1500 with a busy communication stack. Trigger SFC 51 from a low-priority OB (e.g. OB35 at 1 s) and @CPU_RT from OB1, or interleave them on a 5 s prescaler.

WinCC Integration of Memory Tags

Once the parsed memory values are written to the AS-side DB, the rest is standard PCS 7 / WinCC engineering:

  1. In SIMATIC Manager, open the S7 program and add the DB (e.g. DB100) to the symbol table with the type DB_Memory.
  2. Re-run the PCS 7 driver wizard (Component View > AS > Driver Wizard > Compile OS). The wizard generates the WinCC tag structures for the OS server.
  3. In WinCC Explorer, add the new structure tags to your faceplate. Use a horizontal bar with two thresholds (yellow at 75 % used, red at 90 % used) for each memory area.
  4. For S7-1500 with WinCC Professional / TIA Portal HMI, the equivalent path is Project tree > PLC > Program blocks > DB100 > HMI tag synchronization. Tick the HMI-visible flags on the data blocks whose values you want to expose.

A common panel template is a single faceplate with six bar graphs (work used, work free, load used, load free, retentive used, retentive free), each bound to one DWORD. The raw DWORD is the byte count; divide by 1024 to display in KiB, or by (1024*1024) for MiB. The conversion is purely cosmetic; the raw value is what the SSL reports.

Alternative Methods: Web Server, TIA Diagnostics, and RD_DINFO

SFC 51 is not the only path. The following alternatives are useful when the SFC is unavailable (e.g. on a non-standard CPU type) or when you need richer diagnostics than SSL 0113 provides.

S7-1500 web server

Every S7-1500 / ET 200MP CPU ships with an integrated web server. Activate it in CPU Properties > Web Server and grant the user group read access to diagnostics. The Diagnostics > Memory page renders the same values as SFC 51 W#16#0113 in human-readable form, refreshed every 5 s by the CPU firmware. You can scrape that page with a small Python or PowerShell script for asset monitoring, but the SFC remains the better path for cyclic WinCC integration because the web server does not expose the data as a tag.

RD_DINFO / RD_DIAG data record read

For S7-1500 in TIA Portal, the Get_Memory_Usage data record (diagnostics index 0x0011) can be read with the standard RD_DINFO or RD_DIAG instruction. This is a different encoding than SFC 51 SSL 0113 — it returns the same logical information but as a self-describing JSON-like structure inside the diagnostics buffer. Use this path if you want a structured payload that already separates work, load, and retentive usage into named fields.

Online diagnostics in TIA Portal

The Online > Diagnostics > Memory view in TIA Portal is a manual read of the same data; it is not scriptable and not visible to WinCC. Useful for commissioning, not for production reporting.

Verification and Field Commissioning

After the FB is compiled and downloaded, verify the implementation in five steps:

  1. Place the CPU in RUN and force the trigger tag (bStart) to TRUE. In a watch table, observe iRetVal; it must read W#16#0000 after one read cycle.
  2. Read szlHeader.LENTHDR and szlHeader.N_DR. For an S7-1500 CPU 1515-2 PN with firmware 2.9, expect LENTHDR = 28 and N_DR ≥ 4.
  3. Walk the data records with a watch table and a SCL debug snippet that prints Memory type code — Total — Used — Free in human-readable form. Cross-check the totals against the CPU's online diagnostics page.
  4. Confirm that the WinCC tag group populates by opening WinCC Explorer and inspecting the tag list; if the tags are missing, the driver wizard has not been re-compiled.
  5. Run the system under load (force a high communication load and a large DB) and confirm the values move within two OB cycles of the trigger.

Sanity checks

  • For any memory area, Used + Free should equal Total within one DWORD. If it does not, the CPU is in the middle of a memory re-organization (e.g. online block delete) — wait one cycle and re-read.
  • The work memory total must match the value printed on the CPU's front label (e.g. 500 KB for CPU 1515-2 PN, 3 MB for CPU 1518-4 PN/DP). If it does not, you are reading the wrong partial list or the wrong CPU type.
  • Load memory total must be ≤ the size of the SIMATIC Memory Card. If it is greater, the firmware is reporting the logical size of the project, not the card size.

Troubleshooting Matrix

RET_VAL (hex) Meaning Likely cause Corrective action
0000 No error, data valid Proceed to parse the data records.
7000 First call, BUSY not yet started REQ was TRUE but the call has not been processed Wait one OB cycle and re-call with REQ = FALSE.
7001 First call, data being read Asynchronous read is in progress Continue polling with REQ = FALSE.
7002 Follow-up call in progress Multi-record read still running Continue polling.
8090 Address error (DR pointer invalid) DR points to a TEMP variable or to a non-existent DB Re-target DR to a static instance or a global DB.
8091 Error in parameters SZL_ID = 0, INDEX = 0, or DR length = 0 Verify all input parameters before the call.
8092 SSL_ID / INDEX combination invalid The CPU does not support the requested partial list Cross-check the CPU's function manual for supported SSL partial lists.
80A0 Negative acknowledgement from module Communication error on the backplane Check the diagnostic buffer of the CPU for rack faults.
80A1 Resource bottleneck CPU is too heavily loaded to service the SSL read Increase the cycle time of the calling OB or reduce the trigger frequency.
80B0 SSL_ID not supported Wrong CPU generation (e.g. 0113 not supported on very old S7-300) Use SSL 0013 (full list) or upgrade firmware.
80B1 / 80B2 SSL_ID not available / not supported by module The partial list has been disabled in the CPU configuration Re-enable the corresponding diagnostic in HW Config / device configuration.
80C0 / 80C1 Cannot read / information not available CPU in STOP, FW update in progress, or partial list transiently unavailable Wait for the CPU to return to RUN and re-try.
80C2 Information not available due to overload CPU is sampling diagnostics faster than the firmware can update the SSL Increase the cycle time of the calling OB to 500 ms or more.
80D0 SZL_HEADER is too small DR buffer is smaller than LENTHDR * N_DR Resize the DR buffer to at least LENTHDR * N_DR bytes.

Which SSL_ID should I use to read CPU memory in PCS 7?

Use SFC 51 (RDSYSST) with SSL_ID W#16#0113 to read the partial list of memory areas of the module. SZL_ID 0x0113 is the synchronous partial-list read and is supported on S7-300, S7-400, S7-1500, and ET 200MP CPUs with current firmware. If your CPU does not return 0113, fall back to W#16#0013 (full list) or read the structured diagnostic data record 0x0011 with RD_DINFO on S7-1500.

Does the @CPU_RT block in PCS 7 report work and load memory?

No. @CPU_RT reports OB cycle times, priority-class runtimes, and the top five communication partners. It does not expose work-memory, load-memory, or retentive-memory values. For those, implement your own FB that calls SFC 51 with W#16#0113 and publishes the parsed values to WinCC via the standard PCS 7 driver wizard.

What is the minimum firmware for the @CPU_RT PCS 7 driver wizard block?

Single (non-redundant) S7-400 CPUs require firmware 5.0 or higher; redundant H-CPUs (e.g. CPU 410-5H) require firmware 4.5 or higher. These firmware levels are also the lower bound for consistent SSL 0113 data on the corresponding CPUs.

How can I read memory usage on an S7-1500 without writing any code?

Activate the integrated web server on the S7-1500/ET 200MP CPU (CPU Properties > Web Server > Activate), grant a user group read access, and open the Diagnostics > Memory page from a browser. The page renders the same values that SSL 0113 returns. For cyclic WinCC reporting, however, SFC 51 is the correct path because the web server is not scriptable as a tag source.

What size DR buffer do I need to allocate for SFC 51 SSL 0113?

Allocate at least LENTHDR x N_DR bytes. Read the SZL_HEADER on the first successful call and size the buffer to that product plus a 20 % safety margin. On a typical S7-1500 CPU 1515-2 PN with current firmware, LENTHDR is 28 bytes and N_DR is 4 to 6 records, so a 256-byte buffer is more than enough; for S7-400 firmware 5.x the same 28-byte record format applies. Never point DR to a TEMP area; the read is asynchronous and the temporary stack is not preserved across OB cycles.

Back to blog