Overview: Redundant Communication Processor Topology in S7-400H
A Siemens S7-400H fault-tolerant system can be equipped with two Communication Processors (CPs) per rack segment to provide redundant paths between the H-CPUs and external devices such as a PC station, a redundant server, or a higher-level SCADA. In the typical configuration the user inserts two CP 443-1 (Industrial Ethernet) modules, each with its own IP address, into the redundant rack. The H-CPUs run a synchronized user program and maintain two separate TCP connections — one per CP — toward the partner station.
Unlike an S7 Redundant connection (S7-Redconnect), which is configured once in NetPro and is automatically managed by the S7-400H firmware as a single logical path, two plain TCP connections are visible to the application as two independent ISO-on-TCP or TCP channels. The user program must therefore decide, for every send/receive operation, which CP is the currently active one and which NetPro connection ID belongs to that CP. The remainder of this reference describes the supported techniques for making that decision deterministically.
Prerequisites and Hardware Configuration
Before any active-CP detection logic is written, the following configuration must be in place:
- Two CP 443-1 modules (6GK7 443-1EX11/EX20/EX30 or current equivalent) inserted in the H-rack, each assigned its own Ethernet subnet and IP address.
- STEP 7 V5.5 / V5.6 (or TIA Portal with H-package) project with an H-station containing both CPs as separate IO devices.
- NetPro contains two unidirectional or bidirectional TCP/ISO-on-TCP connections — one terminating on CP A, the other on CP B. The connection partner is typically a PC station with two CP 1613 / CP 1623 cards (or a softnet route) configured with the matching IPs and TSAPs.
- For S7 Redundant, the option "Use S7-Redconnect" is not checked; the connections must remain standard TCP so that the application can address them individually.
- CPU firmware ≥ V4.0 (H-CPU 412-3H / 414-3H / 416-3H / 417-4H) — required for the SZL identifiers used below.
Diagnostic Methods: SFC51 and System Status Lists
SFC 51 "RDSYSST" (Read System State) is the standard interface for reading partial lists of system status (SZL) from an S7-400 CPU. The relevant SZLs for H-system and CP diagnostics are summarized below.
| SZL ID (W#16#…) | Meaning | Use Case |
|---|---|---|
| xy71 | Module identification | Read the order number (MLFB) and firmware of every inserted module, including both CPs. |
| xy72 | Module status | Identify whether a given slot is occupied, faulted, or OK — directly reveals a failed CP. |
| xy74 | Status of the H-system (master/reserve CPU) | Identifies which H-CPU is currently master and which is reserve. |
| xy91 | Module LED status | Returns the SF/BF/IF LED state of each slot — useful for CP field diagnostics. |
| xy0C | CP diagnosis (extended, partial) | Provides connection-state information accessible from the CPU side, when supported by the CP firmware. |
| xy1C | CP status (CP 443-1) | Reports whether the CP is in RUN/STOP, the number of configured vs. active connections, and link state. |
For each SZL, SFC 51 is called with parameters SZL_ID = W#16#xy.., INDEX = slot_number, SZL_HEADER_PTR pointing to a 12-byte header buffer, and DR = p#db.buffer_pointer pointing to a destination area large enough to hold the data record(s).
Reference: Siemens: SFC51 RDSYSST in S7-300/400 — Function Manual.
Reading CPU Master/Reserve Status (SZL W#16#xy74)
The original question asked how to read which H-CPU is currently master. The well-known call is:
CALL SFC 51
REQ := TRUE
SZL_ID := W#16#0074 // 0074 = standard header; x074 family = H-status
INDEX := 0
RET_VAL := MW100
BUSY := M101.0
SZL_HEADER_PTR := P#DB99.DBX0.0 BYTE 12
DR := P#DB99.DBX12.0 BYTE 32
NOP 0
The returned record at DB99 contains a 32-bit mask in which bit 0 represents CPU 0 (rack 0) and bit 1 represents CPU 1 (rack 1). The set bit identifies the master; the cleared bit identifies the reserve CPU.
CP Diagnostics via SZL xy72 / xy91 / xy1C
To know whether a given CP is "alive" (configured, error-free, link up), poll its slot with SZL xy72. The call is identical in structure, only the SZL ID and INDEX change:
CALL SFC 51
REQ := TRUE
SZL_ID := W#16#0172 // partial-list extract for one slot
INDEX := 4 // logical base slot of CP A (example)
RET_VAL := MW110
BUSY := M111.0
SZL_HEADER_PTR := P#DB99.DBX0.0 BYTE 12
DR := P#DB99.DBX12.0 BYTE 26
NOP 0
The xy72 data record is 26 bytes and contains, among other fields:
- Word 0 — module status:
0000H= module OK,0011H= module faulty/not available. - Word 1 — module identifier (always
0006Hfor FM/CP). - Word 2 — logical base address (diagnostic address from NetPro).
- Byte 4+ — module order number (MLFB) as ASCII.
Combine xy72 with xy91 (LED status) for a quick on-screen health check of each CP. A failed link is reported as BF LED set in xy91, which is faster to read than parsing the diagnostic buffer of OB82.
Reference: Siemens — System and Standard Functions for S7-300/400 manual (entry ID 1117740).
NetPro Connection IDs and Diagnostic Addresses
Every TCP connection in NetPro has a unique connection ID (positive integer) and a diagnostic address (the input word of the CP that owns the connection). In a dual-CP H-system with two TCP connections you will have, for example:
| Path | Connection ID | Diagnostic Address (IW) | CP Module | Local IP | Partner IP | |
|---|---|---|---|---|---|---|
| Path A (primary) | 1 | IW 512 | CP 443-1 #1 (slot 4) | 192.168.10.11 | 192.168.10.50 | Path B (backup) |
| Path B (backup) | 2 | IW 514 | CP 443-1 #2 (slot 5) | 192.168.10.12 | 192.168.10.50 |
Note: Both connection endpoints share the same partner IP because the partner station is a PC with two CP 1613/1623 cards. Each card has its own IP and each terminates one of the two connections.
The diagnostic address assigned to the CP is the Input/Output word the CP uses to surface its own status to the CPU. Reading IW 512 and IW 514 cyclically from the user program gives a fast hardware-level health signal — these words are non-zero and update continuously when the CP and its connection are healthy; a value frozen or zero indicates a fault.
Implementing Active-CP Detection in the User Program
The recommended decision logic in the S7-400H application program is the following three-step pipeline. All three checks should be performed every OB1 cycle and the result stored in a global ACTIVE_CP tag (0 = path A, 1 = path B, 2 = both faulted).
Step 1 — Verify physical CP health
// CP A healthy?
CALL SFC 51
REQ := TRUE
SZL_ID := W#16#0172
INDEX := 4 // CP A slot
RET_VAL := MW120
BUSY := M121.0
SZL_HEADER_PTR := P#DB100.DBX0.0 BYTE 12
DR := P#DB100.DBX12.0 BYTE 26
// DB100.DBW12 = module-status word; must be W#16#0000 for "module OK"
A "CP_A_OK"
= "CP_A_HEALTHY" // SET/Reset coil follows
Repeat for CP B with INDEX = 5. The user program should debounce the health bits over at least three OB1 cycles before publishing them, because SZL reads are not synchronized to the CP scan.
Step 2 — Verify connection state via diagnostic address
L IW 512 // Diagnostic address of CP A connection
L 0
>I
= "CP_A_CONN_LIVE"
L IW 514 // Diagnostic address of CP B connection
L 0
>I
= "CP_B_CONN_LIVE"
The diagnostic word is non-zero as long as the TCP connection is established; a value of zero means the connection is down or the CP is not yet online.
Step 3 — Verify application-level life-bit
The most reliable evidence of a healthy path is a counter that increments at the partner side and is echoed back by the user program. The standard implementation is:
// Read received life-counter from CP A into DB200.DBD0
L DB200.DBD 0 // Last received life-counter from CP A
L "LIFECOUNT_RECEIVED_A"
<>I
= "CP_A_LIFE_CHANGED"
// edge-trigger a "stale" timer
A "CP_A_LIFE_CHANGED"
L S5T#3S // allow 3 s without change before declaring stale
SD T 10
A T 10
= "CP_A_STALE"
After 3 seconds of no change in the life-counter the path is considered failed, regardless of the SZL or diagnostic-word status. This catches cases where the CP and TCP connection are up but the partner application has stopped polling.
Selecting the Connection ID for AG_SEND / AG_RECV
Once ACTIVE_CP has been computed, the send/receive calls switch their ID parameter accordingly. A typical send block in SCL:
IF ACTIVE_CP = 0 THEN
// Send via CP A — connection ID 1
AG_SEND(REQ := TRUE,
ID := 1,
LADDR := 512,
SEND := "SendBuf",
LEN := 100,
DONE => "SendDone_A",
ERROR => "SendErr_A",
STATUS => "SendStat_A");
ELSE
// Send via CP B — connection ID 2
AG_SEND(REQ := TRUE,
ID := 2,
LADDR := 514,
SEND := "SendBuf",
LEN := 100,
DONE => "SendDone_B",
ERROR => "SendErr_B",
STATUS => "SendStat_B");
END_IF;
Note that ID and LADDR always come as a pair from the same NetPro connection. The wrong pairing is the most common reason for an immediate STATUS = 0x8xxx on first commissioning.
Reference: Siemens — AG_SEND / AG_RECV function blocks for S7-300/400 (entry ID 18513325).
LED-Based Field Diagnostics
When the S7 program reports a fault, the operator can confirm by reading the LEDs on the physical CP 443-1. The relevant LEDs are:
| LED | Meaning when ON |
|---|---|
| SF (red, group fault) | CP has a configuration or hardware fault — check SZL xy72 module status word. |
| BF (red, bus fault) | Ethernet link is down or partner is unreachable. Common during cable swap or switch reboot. |
| IF (red, interface fault) | Internal CP firmware error — usually requires firmware update or module replacement. |
| TXD/RXD (green, blink) | Traffic indicator. A steady green with no blink over several seconds is an early warning that the partner is not polling. |
| LINK (green, steady) | Physical Ethernet link present. |
The TX LED only blinks when the local CP transmits on a connection. Observing which CP is blinking more frequently under steady-state load gives a quick visual indication of the active path — but it must not be the only evidence the application relies on.
Standard TCP vs. S7 Redundant (S7-Redconnect) Connections
| Aspect | Standard TCP x 2 | S7 Redundant (Redconnect) |
|---|---|---|
| Configuration complexity | Two NetPro connections, two IDs, two diagnostic addresses | One NetPro connection with the "Redconnect" flag set |
| Active-path handling | User program selects ID 1 or ID 2 | CP firmware transparently selects the live path; user program sees a single ID |
| Switchover time | Depends on life-bit timeout (typical 2–5 s) | Sub-second, managed by CP 443-1R / CP 1623 firmware |
| PC partner | Any S7 OPC server with two NICs | Requires S7-Redconnect license on the PC (Softnet-S7 Redconnect) |
| When to use | Non-S7 peer, third-party SCADA, custom protocol over ISO-on-TCP | S7-400H ↔ S7-400H, S7-400H ↔ WinCC with Redconnect |
The user's case — two plain TCP connections because the peer is not an S7 station — rules out S7 Redconnect. The "active path" decision must therefore live in the S7 user program, and the methods above apply.
For comparison with non-Siemens architectures, see the Rockwell Automation ControlLogix Redundancy System user manual (1756-UM523) for an example of how a different vendor handles the same problem (NAP-based single point of failure, no path switching at the application layer when the CNB module drops).
Verification and Commissioning Procedure
- Compile and download the H-station. Both CPs should report
SFoff andLINKon within 30 seconds. - Open NetPro → right-click each connection → "Connection status". Both TCP connections must show
ESTABLISHED. - In the S7 program, force
ACTIVE_CP = 0from the watch table. Confirm that the partner receives data on CP A (partner logs or Wireshark on 192.168.10.50:2000). - Force
ACTIVE_CP = 1. Confirm that traffic migrates to CP B (Wireshark shows frames from 192.168.10.12 instead of .11). - Disconnect the Ethernet cable of the currently active CP. The life-bit timer should expire within 3 s and the program should switch
ACTIVE_CPto the surviving path automatically. - Reconnect the cable. Verify that the program does not flap (add hysteresis: only switch back after the alternate path has been continuously healthy for at least 30 s).
- Trigger a full H-CPU switchover (master ↔ reserve) using
SFC 90 "H-Ctrl". Both CP paths must remainESTABLISHED— if not, the diagnostic addresses are misaligned and need to be re-checked against the hardware configuration.
Edge Cases and Field-Proven Caveats
-
SFC51 BUSY handling:
SFC 51is asynchronous. Calling it faster than the CPU can service the request returnsRET_VAL = W#16#7000and the result is delayed. The user must wait on theBUSYflag before re-reading the destination DB. - CP slot numbers change after rack expansion: If you later add an IM or FM in slot 3, the logical slot of CP A shifts. Re-read the slot from HW Config — do not hard-code it.
- OB82 / OB86 may fire on a healthy link flap: Some CP 443-1 firmware revisions generate an OB82 within 1 s of a brief link loss. Make sure OB82 only logs and does not stop the CPU.
- Connection ID is per-CPU, not per-rack: In a partial hot standby or link-up configuration, the connection IDs may be different on master and reserve. Read them from the connection DB or compute them at startup from a table — do not hard-code across the H-pair.
-
Wireshark confirmation: If the application reports a switchover but the partner logs show otherwise, the most common cause is a wrong
LADDRon the AG_SEND call (the send goes out on the wrong CP and is silently dropped at the switch). - Softnet on the PC side: CP 1613 / CP 1623 with Softnet-S7 Redconnect is one approach, but with raw TCP/ISO-on-TCP the PC simply needs two NICs bound to two different IPs and the application's socket listening on both.
FAQ
Can I read the active CP directly with a single SFC call?
No. The CPU only knows that the CP occupies a slot and is OK or faulty (via SZL xy72). Whether the CP carries the "active" TCP traffic is determined by the partner's behavior and the connection state, which the CPU cannot observe directly. You must combine SFC51 with diagnostic-address polling and an application-level life-bit.
What SZL ID identifies the active CPU in a 400H system?
SZL W#16#xy74 returns a 32-bit mask where the set bit indicates the master and the cleared bit the reserve CPU. Read it with SFC 51 and INDEX = 0.
How do I find the diagnostic address of a TCP connection in NetPro?
Open the connection properties in NetPro → "Addresses" tab. The "Local ID" (connection ID) and the diagnostic address of the owning CP are listed there. They must be passed together to AG_SEND / AG_RECV.
Is it safe to use one TCP connection and rely on S7-Redconnect instead?
Yes — S7-Redconnect manages the active path in the CP firmware and the application sees a single connection ID. It requires an S7-Redconnect license on the PC partner and the CP 443-1 must be a "-1GX" or current variant. For non-S7 partners (raw TCP) you must use the two-connection approach described above.
Why does the partner see traffic from the "wrong" CP after a switchover?
Almost always because AG_SEND was called with a mismatched (ID, LADDR) pair — the connection ID and the diagnostic address must come from the same NetPro connection. Check that both come from the path the program intends to use before each send.