Overview of SFC59 RD_REC
Siemens SFC 59 "RD_REC" (Read Record) is a standard system function supplied in the SIMATIC S7-300 and S7-400 CPU operating system. It is the canonical mechanism for reading parameter records (data records / DS) out of a distributed I/O module on PROFIBUS-DP or PROFINET IO. The function transfers a request to the addressed module, the module interprets the record number and replies with a byte stream whose layout is defined entirely by the device manufacturer (Siemens or third-party).
The function executes asynchronously on S7-300/400: a single call dispatches the request, and the CPU continues. The programmer must poll the BUSY and RET_VAL outputs to determine completion. This behavior is different from the IEC-standard RDREC instruction on S7-1500, which is also asynchronous but reports status through the ENO / STATUS semantics of TIA Portal instructions.
The defining engineering rule is the one that the original forum question was about: SFC 59 does not allocate or interpret the destination area. The programmer must declare RECORD as a sufficiently large ANY-pointer-compatible area before the call, and the byte layout of that area must match the data record layout specified in the device manual. If the target area is undefined, has the wrong length, or is not in a global DB, the function returns one of the negative acknowledgments documented below.
Prerequisites
- STEP 7 V5.5 or V5.7 with the S7-300/S7-400 system functions library installed. The relevant reference manual is the SIMATIC S7-300/400 Standard Software - System and Standard Functions Reference Manual.
- Hardware configuration (HW Config) loaded into the CPU with the target module configured at a known logical base address.
- The module's GSD file imported, or for Siemens ET 200 stations, the ET 200 device manual defining the available data record numbers (0, 1, 2, ... 240 typically).
- A global DB with a destination area of the correct size and an ANY-compatible declaration. The DB may be of any block type (DB, M, bit memory), but the pointer passed to
RECORDmust point to a global data area; instance DBs and local stack are not permitted. - STEP 7 online connection to the CPU for testing; the RD_REC call cannot be verified offline.
Call Interface and Parameters
The function block is called with the following input and output parameters. All multi-byte values are little-endian per Siemens convention. RECNUM and LADDR are WORD-type; the value of LADDR is the same logical address that appears in HW Config for the slot or channel of the target module.
| Parameter | I/O | Type | Description |
|---|---|---|---|
REQ |
IN | BOOL | Edge-triggered start. Set TRUE to dispatch a new read job. Reset before the next edge to retrigger. |
IOID |
IN | BYTE | Identifier of the address area. B#16#00 = inputs, B#16#01 = outputs, B#16#02 = mixed (e.g. for PROFINET modules where the slot is not separated into pure I or Q). |
LADDR |
IN | WORD | Logical base address of the module (slot start address from HW Config). Example: W#16#0100 for input address 256. |
RECNUM |
IN | BYTE | Data record number to read (0-240 decimal, 0-EF hex). |
RET_VAL |
OUT | INT | Return value / error code. 0000 on success (after the call that finishes the job), 7000h-7002h for status, negative (8xxxh) for error. |
BUSY |
OUT | BOOL | TRUE while the job is in progress. FALSE means the job is finished and RET_VAL is final. |
RECORD |
IN_OUT | ANY | Destination area where the read data record bytes are written. The first 2 bytes of the area are reserved by Siemens in some interpretations for the record length; consult the device manual. |
RECORD parameter is a full ANY pointer. Pass it exactly as you would for a BLKMOV (SFC 20) or PUT/GET call. Local stack variables (declared TEMP) are not acceptable as RECORD targets because they may be overwritten by interrupt OBs before the asynchronous job completes.Designing the Destination Area (RECORD)
The original forum thread touched on the most common source of error: calling SFC 59 with an undefined or under-sized destination. SFC 59 does not create a DB on demand and does not validate that the destination layout matches the record. The CPU firmware simply performs a fixed-length byte copy of the response payload into the memory region pointed to by RECORD, then returns. If the target is too small, the surplus bytes are lost; if it is too large, the unused bytes are untouched.
Recommended procedure:
- Open the device manual of the target module (e.g. ET 200S 1SI module manual) and identify the record numbers you intend to read.
- For each record number, note the data type, length, and meaning of every byte or word. Most diagnostic records are 4-32 bytes, but parameter records can exceed 200 bytes (e.g. ET 200S parameter record 128 = 128 bytes).
- In a global DB, declare a structure whose total length is at least the record's maximum possible size. Allow a few bytes of headroom for vendor revisions that extend a record.
- Pass the structure's symbolic name to
RECORDusing the STEP 7 "Point to symbol" feature, or build the ANY pointer manually withP#DB100.DBX0.0 BYTE 64syntax.
Data Record Structure Per Device Family
The byte stream returned by RD_REC is 100% vendor-defined. The following table gives a quick reference for the most common Siemens modules. Always verify against the device manual before commissioning.
| Module / Family | Record # | Length (bytes) | Contents |
|---|---|---|---|
| ET 200S 1SI serial interface | 0-3 | 4-128 | Serial port parameters (baud, parity, framing), per-channel. |
| ET 200S motor starter | 0-7 | 4-16 | Trip history, motor current, switching cycle counters. |
| ET 200M analog input SM 331 | 0, 1, 128 | 8-16 | Manufacturer diagnostics, channel-specific errors, parameter re-read. |
| ET 200eco PN | 0-127 | varies | Channel diagnostics, port status. |
| PROFINET IO device, generic | 0x8000-0xBFFF | varies | Per-channel / per-slot diagnostics, index assignment per GSDML. |
| PROFIBUS-DP slave, generic | 0-240 | varies | Per-slot diagnostic; record 0 is always the standard DP diagnostic. |
| S7-1500 (via RDREC) | 0-240, plus 0x8000+ | varies | Same conceptual model; see TIA Portal HELP RDREC. |
Code Examples
STL (Statement List) - S7-300/400
// Assumes DB100 has been pre-declared with a 64-byte array "DiagBuffer"
CALL SFC 59
REQ := M 10.0 // Edge-triggered start request
IOID := B#16#54 // 0x54 = input identifier (legacy form)
// For mixed modules use B#16#55
LADDR := W#16#0100 // Module base address 256 decimal
RECNUM := B#16#01 // Read data record 1
RET_VAL := MW 12 // Return code, integer
BUSY := M 10.1 // TRUE while job running
RECORD := P#DB100.DBX0.0 BYTE 64 // Destination: 64 bytes in DB100
SCL (Structured Control Language) - S7-300/400
IF StartRecord AND NOT BusyFlag THEN
BusyFlag := TRUE;
SFC59_REQ := TRUE;
ELSE
SFC59_REQ := FALSE;
END_IF;
IF BusyFlag THEN
// SFC 59 returns through a multi-instance call;
// here we use the symbolic form via FB wrapping
RetVal := RD_REC(
REQ := SFC59_REQ,
IOID := 0, // 0 = input
LADDR := 256, // base address
RECNUM := 1,
RECORD := DiagBuffer // symbol from global DB
);
IF RetVal = 0 THEN
BusyFlag := FALSE;
// DiagBuffer now contains data record 1
ELSIF (RetVal < 0) OR (RetVal = 7000) THEN
BusyFlag := FALSE;
// Handle error - see RET_VAL codes table below
END_IF;
END_IF;
LAD (Ladder) - S7-300/400
In LAD/FBD, drag SFC 59 from the standard library onto your network. STEP 7 will auto-generate the EN/ENO calls and an instance DB for the parameter retention. Wire REQ from a positive edge contact, LADDR from a constant of type WORD, and connect the RECORD input by right-clicking and selecting the DB symbol.
S7-1500 / TIA Portal (RDREC)
// RDREC on S7-1500: TIA Portal instruction, NOT SFC 59
#Busy := RDREC(
REQ := #startTrigger,
ID := 256, // HW identifier from device table
INDEX := 1, // Data record number
MLEN := 64, // Max length to be read
VALID := #recordValid,
BUSY := #busy,
ERROR := #error,
STATUS := #status,
RECORD := %DB100.DiagBuffer // Symbolic DB access
);
The ID parameter is the HW identifier from the device configuration (a DWORD, e.g. 257), not a byte address. MLEN is the maximum bytes to read - this explicit length parameter is a safety improvement over SFC 59.
RET_VAL Error Codes
The RET_VAL (or STATUS on RDREC) return is the single most important field for diagnostics. The following values apply to SFC 59 on S7-300/400; RDREC on S7-1500 uses a superset of these plus the IEC 61131-3 error classes.
| RET_VAL (hex) | Meaning | Typical Cause |
|---|---|---|
| 0000 | Success - record read, BUSY now FALSE | Normal completion on the call that returns BUSY=FALSE |
| 7000 | No job active, BUSY=FALSE | Initial call before REQ=TRUE, or just completed |
| 7001 | First call, job dispatched, BUSY=TRUE | REQ just went TRUE; check back next OB1 cycle |
| 7002 | Intermediate call, job in progress, BUSY=TRUE | Job still pending - do NOT re-trigger |
| 8090 | Logical base address invalid | LADDR not in HW Config, or wrong module type |
| 8092 | RECORD points to a length of 0 | Destination ANY with zero-byte length |
| 8093 | LADDR is configured but no slot is present | Slot pulled or module swapped and not re-parameterized |
| 80A0 | Negative acknowledgment reading from module | Module does not support this record number |
| 80A1 | Negative acknowledgment writing to module | Usually a RD_REC quirk - check RECNUM range |
| 80B0 | Module not configured / not PROFIBUS/PROFINET | Wrong LADDR - check the slot table |
| 80B1 | Target length (RECORD) < source length | RECORD too small - extend destination DB |
| 80B2 | RECNUM greater than 240 | Check record number encoding (BYTE, 0-EF) |
| 80B3 | Not allowed (record not permitted) | Vendor has restricted access to this record |
| 80C0 | Vendor-specific read error | Module returned error code; consult vendor manual |
| 80C1 | Record length exceeds max | Vendor says this record is longer than the bus allows |
| 80C2 | Record length less than minimum | Record is reserved for vendor and is too small to use |
| 80C3 | Resource busy, retry recommended | Module is processing another job; back off and retry |
| 80C4 | Communication error on DP/PN | Bus fault, station failure, re-diagnose |
| 80D0 | System error in module | Module returned without data; usually a hardware fault |
Asynchronous Execution and Polling Logic
Because SFC 59 executes across multiple OB1 cycles, the call must be edge-triggered and the BUSY flag must be used to gate the next call. The recommended pattern is:
- On a positive edge of the user's start trigger, set
REQ := TRUEand call SFC 59. - Read back
BUSYandRET_VAL. - If
BUSY := TRUE, do nothing - let the next OB1 cycle observe the result. Critically, do NOT re-setREQwhileBUSYis TRUE, or you will cancel the in-flight job. - When
BUSY := FALSE, evaluateRET_VAL.0000= success, negative = error (see table above). - Reset
REQand arm for the next edge.
Migration to S7-1500 (RDREC)
For new projects on S7-1500, ET 200SP, or any TIA Portal target, the IEC-standard instruction RDREC replaces SFC 59. Key behavioral differences:
- Identifier is
ID(DWORD, HW identifier from the device table), notLADDR+IOID. -
MLENexplicitly bounds the read, eliminating the over-write risk of SFC 59. - Output
VALIDpulses for one cycle when new data is available - a cleaner edge signal than the BUSY/FALSE pattern of SFC 59. - Error reporting uses
ERROR/STATUSinstead of a singleRET_VALwith hex codes.STATUSfollows IEC 61131-3 error classes (e.g.16#80B1for RECORD overflow). - RDREC is placed in the program directly, not as a system function from a library. It is found under "Extended instructions > Distributed I/O > RDREC".
For migration of legacy SFC 59 code, the wrapper is straightforward: replace the IOID + LADDR pair with a single ID DWORD, add an MLEN literal matching the RECORD size, and adjust the post-call evaluation logic to use ERROR/STATUS. The full conversion table is in the TIA Portal online help under "RDREC - Read data record".
Verification Procedure
- Build a global DB with a 64-byte byte array named
DiagBuffer. This is the RECORD target. - In OB1, insert a CALL to SFC 59 with
REQtied to a tag-controlled edge,IOID= 0 (input),LADDR= 256 (your module base address),RECNUM= 1,RECORD=P#DB100.DBX0.0 BYTE 64. - Trigger a positive edge on the
REQtag (use aSET/RESETfrom the STEP 7 debug watch table, or a force in online mode). - Open the SFC 59 instance in the online block view and observe
BUSYtoggle from TRUE to FALSE within a few OB1 cycles. - Check
RET_VAL; if 0, open the destination DB and verify the byte pattern matches the record layout from the device manual. A diagnostic record from an ET 200S 1SI module, for example, will start with bytes that correspond to baud rate, then parity, framing, etc. - Test the error path: change
RECNUMto an unsupported value (e.g. 200) and re-trigger. ExpectRET_VAL = 16#80A0(negative ack) and a new error entry in the diagnostic buffer.
Troubleshooting Matrix
| Symptom | First Check | Fix |
|---|---|---|
| RET_VAL = 8090 at first call | Verify LADDR in HW Config | Use the slot's input base address, not the diagnostic address |
| RET_VAL = 80B1 after first cycle | RECORD ANY too small | Resize destination DB to vendor-spec length |
| RET_VAL stays at 7001 / BUSY never clears | Bus fault? Module pulled? | Check SF LED on the slave, look at OB82 (diagnostic interrupt) and OB86 (rack failure) |
| Record data looks like garbage | Byte order wrong in the DB | Confirm the device manual's byte order; some vendors use big-endian |
| Different PLC gets different values for the same record | CPU firmware version | Newer CPU firmware may enforce stricter RECORD size checks |
| Call works once then RET_VAL = 8093 | LADDR conflicting with another call | Make sure multiple SFC 59 calls do not share LADDR on S7-300 with limited parallel jobs |
| RDREC on S7-1500 returns STATUS 16#80B2 | INDEX too large | Limit INDEX to 0-255 (BYTE) unless the device manual explicitly says otherwise |
Performance and Concurrency Limits
S7-300 CPUs have a limited number of asynchronous job slots. S7-313/314 allow 1-2 concurrent RD_REC calls, S7-315/316 allow 4-8, and S7-400 scales with the CPU type. If you issue more parallel calls than the CPU supports, the call returns RET_VAL = 16#80C3 (resource busy) and the request should be retried after a short back-off. S7-1500 RDREC does not have this hardware-imposed limit but is still subject to the underlying PROFINET/PROFIBUS job scheduler.
For high-frequency polling (e.g. reading diagnostic records every OB1 cycle), prefer the GET_DIAG function (SFC 13) for module-level diagnostics, and use RD_REC only for the less-frequent parameter-record reads. SFC 13 is fully synchronous and cheaper on the job pool.
FAQ
Does SFC 59 automatically create a destination DB for the read data record?
No. SFC 59 requires the destination area to be pre-declared by the programmer - typically a global DB with a byte array sized to match the maximum record length from the device manual. Pass it as an ANY pointer (e.g. P#DB100.DBX0.0 BYTE 64). If the destination is undefined or too small, the call returns RET_VAL = 16#80B1.
Where do I find the structure of the data record I want to read?
In the device manual of the addressed module (Siemens ET 200 manuals list records 0-240 with byte-by-byte layouts) or in the GSD/GSDML file for third-party devices. Record 0 on PROFIBUS is always the standard DP-V0 diagnostic; PROFINET uses indices in the 0x8000-0xBFFF range for channel diagnostics.
Why is BUSY still TRUE several OB1 cycles after I called SFC 59?
RD_REC executes asynchronously. The CPU dispatches the request, the bus scheduler queues it, the module processes it, and only on the next poll cycle does BUSY drop to FALSE. Wait for BUSY = FALSE before evaluating RET_VAL, and do not re-trigger REQ while BUSY is TRUE - that cancels the in-flight job.
What is the difference between SFC 59 and SFB 52 / SFB 53?
SFB 52 (RDREC) and SFB 53 (WRREC) are the S7-400 multi-instance / PROFIBUS-DP equivalents that support multiple parallel jobs and can be embedded as instances. On S7-300, SFC 59 / SFC 58 are the only options. On S7-1500, the RDREC / WRREC instructions replace both, with cleaner VALID/ERROR/STATUS outputs.
Can I use SFC 59 to read data records from an S7-1500 module on an ET 200SP?
No - SFC 59 is not available in the S7-1500 firmware. Use the RDREC instruction in TIA Portal. The call interface is similar (REQ, ID, INDEX, RECORD) but with an additional MLEN parameter and an HW identifier for ID instead of a byte address.