S7-400 AG_LRECV Returns Stale Data: ISO-on-TCP Migration Fix

David Krause17 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. Problem Overview

An S7-412-3H station equipped with a CP-443-1 Advanced communicates over a TCP native connection to a CP-343-1 Lean on a remote S7-317-2DP/PN. The send direction (S7-400 -> S7-300) operates correctly with AG_LSEND/AG_SEND, but the receive direction produces a precise and reproducible symptom: AG_LRECV (FC40) returns STATUS = 8181H with NDR toggling from 1 to 0, yet the receive DB continues to display the previous payload. The receive buffer only updates once, immediately after an AG_CNTL (FC10) job 2 (abort/reset connection) is executed, then freezes on the stale data for every subsequent receive call.

This behavior is distinct from a hard communication fault. The CP diagnostics buffer, the S7-400H system diagnostics, and the partner-side CP diagnostics do not report link-down conditions, partner-unreachable errors, or resource exhaustion. The receive block completes its handshake with the CP successfully; a typical "no data" troubleshooting path therefore misses the actual defect. The defect is in the protocol selection, not in the wiring, the connection table, the receive block wiring, or the partner's transmit logic.

2. Affected Hardware and Firmware

The configuration in this class of fault uses the following components:

  • S7-412-3H redundant controller, e.g. 6ES7412-3HJ14-0AB0, 6ES7412-3HK14-0AB0, 6ES7412-3HL14-0AB0, or 6ES7412-3HM14-0AB0. The F-variant is not required to reproduce the fault.
  • CP-443-1 Advanced, e.g. 6GK7443-1EX30-0XE0 (current) or 6GK7443-1EX20-0XE0 (previous generation). The 6GK7443-1GX30-0XE0 variant adds a 4-port ERTEC switch on the module. The Advanced variant supports ISO, ISO-on-TCP (RFC 1006), TCP, UDP, and S7 communication; the Standard CP 443-1 (6GK7443-1EX10/EX11) supports ISO and TCP only with a reduced connection count.
  • CP-343-1 Lean, e.g. 6GK7343-1CX10-0XE0 (legacy) or 6GK7343-1CX30-0XE0 (current). The Lean variant supports ISO, ISO-on-TCP, TCP, UDP, S7 communication, and PROFINET IO controller on the CX30. Connection resources are limited to 4 S7 connections and 4 SEND/RECV connections total; exceeding either limit surfaces as STATUS 80C3H on the partner.
  • S7-300 station: S7-317-2DP/PN, e.g. 6ES7317-2EK14-0AB0 or 6ES7317-2AJ10-0AB0.
  • Engineering tool: STEP 7 V5.5 + latest SP, with the S7-H add-on for the redundant CPU and NCM S7 Industrial Ethernet for the CP configuration. TIA Portal is not used for the S7-400H portion of the project; the equivalent TIA blocks for S7-1500/ET 200SP are TSEND_C/TRCV_C and do not apply to the S7-400 in this configuration.

References: Siemens Industry Online Support entry pages for the S7-400H fault-tolerant systems manual and the CP-443-1 Advanced / CP-343-1 Lean operating instructions.

3. Root Cause Analysis

Three conditions combine to produce the stale-data symptom.

  1. TCP native stream semantics. TCP is a byte-stream protocol. The AG receive blocks (AG_RECV, AG_LRECV) on a CP that supports TCP native copy a fixed-length area of bytes from the receive buffer of the CP, but the protocol itself has no length prefix, no message boundary, and no implicit acknowledgement. The S7-400 receive function reads whatever bytes are present in the CP receive buffer at the moment the call is issued, and the CP receive buffer is only updated when the partner issues a SEND of equal or larger size. If the partner (S7-300) sends a 50-byte payload and the S7-400 receive area is configured for 100 bytes, the S7-400 receives only the first 50 bytes from the new SEND and retains the previous 50 bytes from the prior SEND in the rest of the area. The receive function reports success because bytes were received; it does not zero the area before copying, and the partner did not push 100 bytes to refresh the whole buffer.
  2. S7-400H connection resource layout. The S7-400-3H is a fault-tolerant system with two H-CPUs. The H-tying pattern in the configuration creates one connection on each H-CPU to the S7-300, but only the active CPU's connection carries live data. When AG_CNTL job 2 is issued, the connection on the active CPU is reset, the partner sees a TCP RST/FIN, the new active CPU's connection re-establishes, and the first receive gets a fresh buffer. Subsequent receives revert to the stale state because the partner S7-300 has not pushed a new payload in the interim. Field reports confirm that switching the standby PLC off does not change the symptom in this configuration, which rules out a partner-side H-tying problem and confirms the active path as the source of the defect.
  3. CP-343-1 Lean transmit cadence. The S7-300 issues AG_SEND (FC5) only when the application code calls it. Between SEND calls, the CP-343-1 Lean has no data to deliver to the partner, and the S7-400 CP-443-1 has no new data in its receive buffer. The S7-400 receive function then returns the previously buffered bytes. This is normal TCP semantics, not a fault. The fault is treating TCP native as if it were a message-oriented transport in a polled receive application.

The combined effect: the receive block is polled on every OB1 cycle, it always reports STATUS = 8181H and NDR=1 the first cycle after a connection reset (because the CP returns the most recent payload), and it reports STATUS = 0000H and NDR=0 thereafter (because the CP has no new bytes to deliver). The user buffer is never overwritten because no new bytes have arrived.

4. Diagnostic Indicators and Status Codes

AG_LRECV (FC40) on the S7-400 and AG_RECV (FC6) on the S7-300 use a uniform status convention. The following table summarizes the status values relevant to the stale-data scenario.

STATUS (hex) Meaning Interpretation in this fault
0000H No active receive job, no error Normal idle state when no new data has arrived
8181H New data received, NDR = 1, LEN contains byte count Visible only immediately after a connection reset in this fault
8183H No data available yet, REQ=1 still in progress Not observed; the receive completes within one OB1 cycle
8186H Receive completed with warning (LEN < requested) Not observed with this configuration
8381H Connection aborted by partner or AG_CNTL job 2 Observed after a manual connection reset
80A1H Connection not yet established Not observed; the link is up
80C3H Connection resource exhausted Not observed unless the Lean connection count is exceeded
80B0H Error accessing user buffer (DB) address Not observed; the DB area is correct

The critical observation is the transition 8181H -> 0000H with NDR 1->0. This confirms that the receive function is being polled faster than the partner is sending. A correctly framed ISO-on-TCP receive behaves identically on idle, but the receive area is rewritten only when a complete TPDU (Transport Protocol Data Unit) is present, and the byte count (LEN) returned in STATUS=8181H exactly matches the bytes just transmitted by the partner. The mismatch between buffer area length and payload length disappears when the protocol provides explicit length framing.

5. The Fix: ISO-on-TCP (RFC 1006)

ISO-on-TCP is the Siemens standard transport for S7-to-S7 user-data exchange. It is defined by ISO/IEC 8073 (Transport Class 4) carried over TCP, with the framing defined by RFC 1006. Each SEND on the partner is a discrete TPDU with a 4-byte ISO transport header that contains the payload length. The CP receiver uses the header to know exactly how many bytes the message contains, copies only that many bytes into the receive buffer, and the AG receive function returns LEN = message length on the call that observes the new data.

For S7-400 to S7-300 communication, ISO-on-TCP is always preferred over TCP native. There is no application benefit to TCP native for this use case, and the message-framing properties of ISO-on-TCP eliminate the stale-data class of fault entirely. The migration is configuration-only: the application code on both stations is updated to use the new Connection ID returned by NetPro, but the call interface of AG_LSEND/AG_LRECV is unchanged.

Reference: Siemens Industry Online Support for the STEP 7 Communication with SIMATIC manual and the NCM S7 Industrial Ethernet programming manual.

6. Reconfiguration Procedure in STEP 7 / NCM S7

Reconfigure the connection as ISO-on-TCP, then rebuild and download to both stations.

  1. Open the S7 project in STEP 7 V5.5 with the S7-400H station as the active project.
  2. Open NetPro (Options > Configure Network) and select the CP-443-1 Advanced in the S7-412-3H rack.
  3. Delete the existing TCP native connection to the S7-300 station. Confirm the deletion; the connection entry is removed from both the S7-400 and the S7-300 NetPro view.
  4. Right-click the CP-443-1 Advanced and select Insert New Connection. In the connection dialog, set:
    • Partner station: the S7-300 (CPU 317-2DP/PN)
    • Partner interface: CP-343-1 Lean
    • Type: ISO-on-TCP connection
    • Connection name: descriptive, e.g. H_to_300_DATA
  5. In the connection properties dialog, set the local TSAP (Transport Service Access Point). For the S7-400 side a typical value is 10.01, entered as the two hex bytes 0x10 0x01. Set the partner TSAP on the S7-300 side, e.g. 30.01 = bytes 0x30 0x01. For S7-400H redundant operation the TSAP must be identical on both H-CPUs; configure the same TSAP on the standby CPU's CP-443-1 Advanced.
  6. Confirm with OK. NetPro regenerates the connection DB and assigns a Connection ID. Note the ID; it must match the ID parameter on the AG_LRECV/AG_LSEND calls in the user program.
  7. Compile and download the hardware configuration and the connection configuration to both the S7-400 (both H-CPUs) and the S7-300 stations. The download brings up the connection on each CP-443-1 Advanced and on the CP-343-1 Lean.
  8. Open the S7-300 station in NetPro. The new ISO-on-TCP connection is visible on the CP-343-1 Lean with matching TSAP and Connection ID. No additional user-side action is required for ISO-on-TCP; the connection is managed by the CP firmware.
  9. Update the user program on the S7-400: change the ID parameter of every AG_LRECV and AG_LSEND call to the new Connection ID, and update the LADDR parameter to the logical base address of the active CPU's CP-443-1 Advanced (visible in HW Config, e.g. W#16#0 for the first CP or a higher value for subsequent CPs).
  10. Update the user program on the S7-300: change the ID parameter of every AG_SEND and AG_RECV call to the new Connection ID, and update LADDR to the logical base address of the CP-343-1 Lean.

7. AG Block Configuration

The user program must be updated to match the new connection's Connection ID. The receive buffer length parameter (LEN on AG_LRECV) is critical: it must equal the maximum payload length transmitted by the partner, not the data block size used by the application. For ISO-on-TCP, the maximum is 8192 bytes per call on FC40/FC41 and the minimum is 1 byte.

Typical AG_LRECV call (Structured Text, S7-400):

// Receive call on OB1, polled every cycle
"AG_LRECV_DB"(
    REQ     := TRUE,                       // request to issue a receive
    ID      := 1,                          // Connection ID from NetPro
    ADDR    := W#16#0,                     // LADDR of CP-443-1 in HW Config
    LEN     := 100,                        // expected payload length in bytes
    DATA    := P#DB20.DBX0.0 BYTE 100      // receive area: 100 bytes from DB20
    ;NDR    := "rcv_ndr",                  // new-data-received flag
    ;ERROR  := "rcv_err",                  // error flag
    ;STATUS := "rcv_status",               // 16-bit status word
    ;LEN_OUT := "rcv_len"                  // bytes actually received
);

For ISO-on-TCP, LEN_OUT will be less than or equal to LEN and will match the partner's last AG_SEND length exactly. If LEN_OUT is less than LEN on a given call, only the first LEN_OUT bytes of DATA are valid; the rest of the area is preserved from the prior call (this is normal ISO-on-TCP behavior). Use the NDR rising edge to trigger processing of the new data and use LEN_OUT to copy only the valid bytes into the application buffer.

Mirror send call (S7-400, FC41 AG_LSEND):

"AG_LSEND_DB"(
    REQ     := "send_trigger",             // rising edge to send
    ID      := 1,                          // Connection ID
    ADDR    := W#16#0,                     // LADDR of CP
    LEN     := 100,                        // bytes to send
    DATA    := P#DB21.DBX0.0 BYTE 100      // send area
    ;DONE   := "snd_done",
    ;ERROR  := "snd_err",
    ;STATUS := "snd_status"
);

On the S7-300, the partner uses AG_SEND (FC5) and AG_RECV (FC6) with the same Connection ID and LADDR. The block numbers are not interchangeable across the S7-400 and S7-300 line: FC5/FC6 on the S7-300 maps to long-version semantics on the S7-400 only by virtue of the connection type. ISO-on-TCP supports up to 8192 bytes per call on the S7-300 AG_SEND/AG_RECV as well, but the application must still call FC5/FC6 (not a long-version block, which does not exist for the S7-300).

8. S7-400H Specific Notes

The S7-400H redundant system has two H-CPUs. Each H-CPU owns a CP-443-1 Advanced with a connection to the S7-300. The two connections are independent; only the active CPU's connection carries live data. When the system fails over from the master to the standby CPU, the new active CPU's connection takes over without dropping from the partner's perspective, provided both CPs are configured with the same Connection ID and the partner S7-300 has its connection endpoint resolved by IP address (not by CP slot).

For the ISO-on-TCP reconfiguration on a redundant system:

  • Configure the Connection ID identically on both H-CPUs (e.g. ID = 1 on each CP-443-1 Advanced).
  • Configure the partner TSAP identically on both H-CPUs (e.g. 30.01 on both).
  • Use the same LADDR on both H-CPUs if the CPs occupy the same slot in each rack.
  • The user program runs on the active CPU only; the AG_LRECV call uses the LADDR/ID of the active CPU's CP. The H-system link-update mechanism ensures that the LADDR points to the active CPU's CP at all times.
  • Download the connection configuration to both H-CPUs. A common commissioning error is downloading only to the active CPU; the standby CP must also receive the connection, otherwise the failover path has no live connection and the partner sees a link-down event during the H-switch.

Reference: Siemens Industry Online Support for the S7-400H Fault-Tolerant Systems manual and the CP-443-1 Advanced operating instructions.

9. Verification and Commissioning Tests

After reconfiguration, run a four-step commissioning sequence to confirm the fault is cleared.

  1. Connection establishment check. Open an online view on the S7-400, right-click the CP-443-1 Advanced > Diagnostic > Connections. Verify the ISO-on-TCP connection shows status "Established" and that the partner IP and partner TSAP are correct.
  2. Send/receive loopback. Create a small test DB on the S7-300 with a counter. Increment the counter in OB1 and call AG_SEND with the counter DB. On the S7-400, call AG_LRECV into a second DB. Monitor both DBs online; the S7-400 DB must track the S7-300 counter within one OB1 cycle of any change. With ISO-on-TCP this is exact; with TCP native this is the exact symptom that failed in the original configuration.
  3. Status trace. Add the AG_LRECV STATUS and LEN_OUT tags to a watch table and force a trigger on the S7-300 to send 50 bytes. Verify STATUS transitions to 8181H, NDR pulses, and LEN_OUT = 50. Repeat with 100 bytes and 1 byte; LEN_OUT must match the sent length each time.
  4. Long-run stability. Run the system for at least 1 hour with a 1-second send cadence on the S7-300. Verify the S7-400 receive area remains in lockstep with the S7-300 source. Any instance of stale data, missed NDR pulses, or duplicated values indicates a residual configuration issue; the most common causes are a TSAP mismatch between the H-CPUs, the standby CP not having its connection downloaded, or a leftover TCP native connection entry in NetPro that the S7-400 is silently using in place of the new ISO-on-TCP entry.

10. Comparison: TCP Native vs ISO-on-TCP for S7-S7 Communication

Property TCP native ISO-on-TCP (RFC 1006)
Message framing Byte stream, no inherent boundaries 4-byte ISO transport header with explicit payload length
Receive area behavior Area contents preserved when no new bytes arrive Area is rewritten with the bytes of the latest TPDU; LEN_OUT = exact payload
Maximum payload per call (S7-400 AG_LRECV/AG_LSEND) 8192 bytes (FC40/FC41) 8192 bytes (FC40/FC41)
Maximum connections on CP-443-1 Advanced Up to 64 total (S7 + SEND/RECV combined) Same
Recommended for S7 <-> S7 No Yes
Recommended for S7 <-> third-party device without ISO-on-TCP support Yes No (use TCP native or PROFINET)
Susceptible to stale-data class of fault Yes, in polled receive applications No, when LEN is sized to the partner's max payload

11. Field Tips, Pitfalls, and Block Reference

Tip - Sizing LEN to the partner's payload. Always set AG_LRECV.LEN equal to or larger than the largest possible AG_SEND/AG_LSEND payload from the partner. If the partner may send variable-length messages, use a fixed maximum and use LEN_OUT to determine the actual message length; ignore the bytes beyond LEN_OUT. Do not size LEN to the application's DB size unless they happen to match.

Pitfall - Mixing connection IDs across H-CPUs. The standby CPU's CP-443-1 Advanced must be configured with the same Connection ID as the active CPU's CP. If the IDs differ, the standby cannot take over the connection on failover and the S7-300 sees a link-down event during the H-switch.

Pitfall - Downloading only the active CPU. A common commissioning error is downloading the connection configuration to the active CPU only. The standby CPU's CP must also receive the connection, otherwise the failover path has no live connection. Verify by checking the S7-400H link status (H-system diagnostics) and the CP-443-1 Advanced connection status on both H-CPUs.

Pitfall - Using AG_RECV (FC6) on the S7-400 instead of AG_LRECV (FC40). AG_RECV (FC6) and AG_LRECV (FC40) are both available in the S7-400 standard library. AG_RECV has a 240-byte maximum and uses a different parameter layout. For ISO-on-TCP with payloads above 240 bytes, AG_LRECV is required. Using AG_RECV on the S7-400 to receive from the S7-300's AG_SEND will not exhibit the stale-data fault specifically, but will silently truncate above 240 bytes and is the wrong block for the application.

Tip - When to use S7 communication instead of ISO-on-TCP. If the data exchange is variable-length and the application only needs a shared data area (PUT/GET semantics), use the S7 connection type with BSEND/BRCV on the S7-400 side and PUT/GET on the S7-300 side. S7 communication is even more robust for S7-to-S7 exchange and is the Siemens recommended approach for non-frame-oriented data sharing. The ISO-on-TCP path described here is the right choice when the application needs explicit per-message boundaries or when interop with a non-S7 partner is required.

AG block cross-reference (S7-300 / S7-400):

Block CPU family Function Max bytes/call
AG_SEND (FC5) S7-300 / S7-400 Send over SEND/RECV connection 240 (standard)
AG_RECV (FC6) S7-300 / S7-400 Receive over SEND/RECV connection 240
AG_LSEND (FC41) S7-400 only Long send (SEND/RECV) 8192
AG_LRECV (FC40) S7-400 only Long receive (SEND/RECV) 8192
AG_CNTL (FC10) S7-300 / S7-400 Connection control (abort, status) n/a
BSEND (FC12) / BRCV (FC13) S7-400 S7 communication, variable-length segmented 32768 / 65534
PUT (FC3) / GET (FC4) S7-300 / S7-400 S7 communication, fixed-area 400 S7-300, 462 S7-400

The AG_LRECV stale-data symptom in this class of fault is a protocol-selection fault, not a receive-block, connection, or hardware fault. Switching the connection from TCP native to ISO-on-TCP (RFC 1006) in NetPro, downloading the new connection configuration to both H-CPUs and to the S7-300, and updating the user program to use the new Connection ID eliminates the symptom. The send and receive directions then operate with explicit per-message framing, the receive area is rewritten only on a complete TPDU, and LEN_OUT returns the exact number of bytes the partner just sent.

If the S7-300 partner is replaced with a non-S7 device that does not support ISO-on-TCP, retain TCP native but add an application-level length prefix and a discard-and-poll pattern: only consume the receive area when LEN_OUT matches the expected next-payload length, and zero the receive area between calls if the partner may send a smaller payload than the area size. This is the engineering workaround for TCP-native polled receive on the S7-400.

12. Frequently Asked Questions

Why does AG_LRECV report STATUS 8181H but show old data?

STATUS 8181H means a new receive job completed and the receive area was updated with the bytes present in the CP receive buffer. With TCP native, the CP receive buffer retains bytes from prior sends until the partner pushes equal or larger payloads. If your AG_SEND on the S7-300 is called less frequently than AG_LRECV is polled, the receive area is rewritten with stale bytes that the CP still holds. Switch to ISO-on-TCP so each SEND is a discrete, length-framed TPDU.

Should I use TCP native or ISO-on-TCP between S7-400 and S7-300?

Always use ISO-on-TCP for S7-to-S7 data exchange. TCP native has no message framing, and polled receive applications exhibit stale-data symptoms. ISO-on-TCP adds a 4-byte length header per message, the CP receiver uses it to copy exactly the right number of bytes, and LEN_OUT on AG_LRECV returns the partner's actual payload length.

What is the difference between AG_RECV and AG_LRECV?

AG_RECV (FC6) is the standard receive block, common to S7-300 and S7-400, with a 240-byte maximum payload per call. AG_LRECV (FC40) is the long-version receive block on the S7-400 only, with an 8192-byte maximum per call. For ISO-on-TCP applications that may exceed 240 bytes per message, use AG_LRECV on the S7-400. The same applies to AG_SEND (FC5) vs AG_LSEND (FC41).

Does this fix apply to S7-400H redundant operation?

Yes. Configure the same Connection ID, the same partner TSAP, and the same LADDR on both H-CPUs, and download the connection configuration to both H-CPUs. The user program runs on the active CPU only and uses the active CPU's LADDR; the H-system updates the active link on failover. With ISO-on-TCP, the partner S7-300 does not need to know which H-CPU is active - it simply sees a live TCP connection.

Can I keep TCP native and avoid the stale-data symptom?

Yes, by enforcing an application-level length prefix and only consuming the receive area when LEN_OUT matches the expected next-payload length, and zeroing the receive area between calls. This is fragile and requires custom protocol logic on both sides. For S7-400 to S7-300, the recommended and supported path is ISO-on-TCP, which removes the protocol ambiguity and is the Siemens default for S7-to-S7 user-data exchange.

Back to blog