S7-1200 TCP Reconnection Failure After Soft Reboot TRCV vs

David Krause14 min read
S7-1200SiemensTroubleshooting
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

Problem Description: TRCV Hangs After Soft CPU Reboot

An S7-1200 CPU configured as an Open User Communication (OUC) TCP client using the legacy TCON + TSEND + TRCV instruction triplet can establish a session to a remote PC server (Java, C#, Python, or LabVIEW socket listener) on first power-up, but fails to recover when the PLC performs a soft reboot — an initialization cycle triggered by an HMI button, a recipe change, or a user logic reset, not a STOP/RUN transition. The CPU does not toggle the RUN/STOP LED, no diagnostic buffer entry is generated, yet the TRCV instruction remains in BUSY = 1 and never returns a frame even though the PC server reports that the socket remains open and is still transmitting.

Symptom summary observed in the field:

  • First connection after power-on: OK (data is received, RCVD_LEN increments, no ERROR bit).
  • Soft reboot is executed (e.g. RESTART OB call, RUN-to-RUN transition triggered by SFC, or a self-initiated re-initialization routine).
  • PC server logs: connection from PLC IP, then periodic send() calls succeed at socket level.
  • PLC side: TRCV stays in BUSY = 1, DONE = 0, ERROR = 0 indefinitely. No data ever appears in the receive area.
  • TCON reports STATUS = 0000_0000 (idle, not connected) or stuck in STATUS = 7000_0000 (no job pending) depending on the watchdog timing.

Attempting a manual reconnection sequence — energizing TDISCON, waiting for DONE or ERROR, then re-energizing TCON.REQ — does not clear the fault. The connection is marked established on the PC side, but no TCP traffic is observed on Wireshark captures from the PLC switch port for the receive direction.

Root Cause Analysis

The failure is rooted in how the legacy TCON / TRCV pair manages the internal connection table on firmware versions prior to the TSEND_C auto-state machine, combined with the one-cycle visibility of the STATUS output of the Open User Communication blocks. Two distinct issues overlap in this scenario:

Issue 1: TCON Does Not Re-Arm After Soft Reboot

The S7-1200 maintains the OUC connection descriptor in a non-retentive work memory area that is re-initialized only on STOP→RUN or power-cycle. A soft reboot — for example, calling RESTART in OB100 or a logic-driven initialization that re-runs OB1 from the top without STOP→RUN — does not invalidate the connection ID entry the way a hard reset does. The TCON block returns STATUS = 0000_0000 because it considers the connection slot empty, but the underlying CP socket layer still owns the TCP handle. When the user code then re-triggers TCON.REQ, the CP layer rejects the bind request with an internal W#16#80E2-class error that is immediately overwritten on the next scan because the STATUS output is only valid for one cycle (see Issue 2). The visible result is a silent hang.

Reference: Siemens KB 109744220 — Open User Communication: STATUS of TCON/TRCV/TDISCON only valid in one cycle.

Issue 2: STATUS/ERROR Are One-Cycle Diagnostics

For all blocks in the OUC family (TCON, TDISCON, TSEND, TRCV, TUSEND, TURCV), the STATUS and ERROR outputs are non-retentive and overwritten every scan. Reading them with an HMI tag without a mirroring tag in a global DB or M-area means the engineer is reading 16#0000_0000 99% of the time, even when a real error was raised the cycle before. This is the single most common cause of “TRCV hangs with no error” reports.

Reference: Siemens KB 109751826 — Why does the TRCV block show STATUS = 0 even though the connection is broken?

Issue 3: Asymmetric T-Block Pairing

When the engineer wrote the original code, TCON was used to open the connection, then TSEND and TRCV were used independently for send/receive. This pattern is documented but fragile: TCON must complete (DONE = 1) before TRCV is enabled, otherwise TRCV enters W#16#80C8 (“Connection not established”) which is then lost to the one-cycle STATUS issue. A single FB (TSEND_C) bundles the connection state machine with the send and receive calls, eliminating the hand-off race.

Diagnostic Procedure

Before changing the code, capture the actual error class. The following procedure is what the original poster did not do and is the recommended first step in any OUC hang.

  1. Create a global DB named DB_OUC_Diag with two DWORD tags: lastTrcvStatus and lastTconStatus.
  2. In OB1, after each OUC block call, copy the STATUS output to the corresponding DB tag using a simple MOVE. Do not read the STATUS tag from the HMI without this mirror.
  3. Add the mirror tags to an HMI watch table or a Web Server user-defined page for live observation.
  4. Trigger the soft reboot and observe the captured STATUS codes in the cycle following the failure. Typical signatures for this scenario include:
    • W#16#80E2 — Connection ID already in use / resource busy.
    • W#16#80C3 — Connection terminated by remote (server closed).
    • W#16#80B0 — No free connection resource.
    • W#16#80A1 — Connection or channel error.
  5. Cross-check with Wireshark (port mirror on the switch): look for SYN without SYN-ACK, FIN without close, or RST from the PLC after the soft reboot.

Solution: Replace TCON/TRCV With TSEND_C

The verified workaround — confirmed by the original poster and consistent with Siemens’ recommended migration path — is to abandon the manual TCON+TRCV pattern and use the consolidated TSEND_C FB. The TSEND_C instruction internally manages the connection state, handles the TCON bind, the TRCV polling, and the TDISCON teardown in a single state machine that is re-entrant across soft reboots.

Why TSEND_C Survives the Soft Reboot

The TSEND_C FB stores its state in the instance DB, which is retained across a RUN-to-RUN cycle as long as the DB is configured as non-optimized (or accessible via “Set in IDB”). On a soft reboot, the instance is re-initialized to the idle state and the connection is reopened by the internal state machine, producing a fresh SYN that the PC server accepts. The CP-layer stale-handle problem that affects the legacy triplet does not occur because the new bind goes through the same descriptor TSEND_C owns.

Implementation in TIA Portal V15.1 to V18

The following step-by-step migration keeps the existing connection description in the Connection properties DB and replaces only the FBs in OB1. It is valid for CPU firmware V4.2 and later (S7-1200, part numbers 6ES721x-1xxxxx-0XB0 with FW V4.2 to V4.6).

  1. Open the project in TIA Portal, expand Program blocks, and locate the existing TCON, TSEND, TRCV instances.
  2. Right-click the program block folder → Add new block → Standard → Communications → TSEND_C. Place it as FB_OUC in OB1 with instance DB DB_OUC_IDB (auto-numbered).
  3. Open the Properties of the new TSEND_C instance and configure:
    • REQ — a pulse from your initialization logic; rising edge triggers a send. Tie to a “send on change” trigger or a periodic pulse (e.g. clock bit from _1s in the system clock).
    • CONT — TRUE to keep the connection open after each send.
    • LEN — fixed length matching the PC server protocol (typical: 32, 64, 128 bytes). For variable-length frames, use LEN = 0 and rely on the NDR (New Data Received) output.
    • DATA — point to a standard access DB or P# pointer to a data block. If using optimized access, ensure the DB has the “Accessible from HMI” attribute.
    • CONNECT — reuse the TCON_Param UDT or build a new one. Active connection = TRUE for the PLC as client. RemoteAddress = '192.168.0.50', RemotePort = 2000, LocalPort = 0 (any).
  4. Delete the legacy TCON, TSEND, TRCV, and TDISCON instances to avoid descriptor collisions.
  5. Add a STATUS mirror:
    // OB1, network 10
          L     "FB_OUC".STATUS
          T     "DB_OUC_Diag".lastStatus  // DWORD
  6. Compile and download with “Download to device → All” (do not do a software reset on download; that will mask the fix).
  7. Trigger the soft reboot and watch the PC server log: the connection is dropped and a new TCP session is established within 2–5 s.

Example: TSEND_C Interface in Structured Text (SCL)

The SCL source for the call, suitable for an S7-1200 with firmware V4.4 and TIA Portal V17 or later, is shown below. This is the exact pattern that resolved the field case.

// FB_OUC wrapper, SCL
DATA_BLOCK "DB_OUC_IDB"
{ S7_Optimized_Access := 'TRUE' }
BEGIN
END_DATA_BLOCK

FUNCTION_BLOCK "FB_OUC"
VAR
    bInitDone : BOOL;
    bSendTrig : BOOL;
    diRxLen   : DINT;
    tRstTimer : TON_TIME;
END_VAR
BEGIN
    // State 0: Wait for first init
    IF NOT bInitDone THEN
        "FB_TSEND_C".REQ := FALSE;
        "FB_TSEND_C".CONT := TRUE;
        "FB_TSEND_C".LEN  := 32;
        "FB_TSEND_C".DATA := P#DB_OUC.TxBuffer DBW 0 BYTE 32;
        // CONNECT is configured in the instance properties
        bInitDone := TRUE;
    END_IF;

    // Periodic send pulse (1 Hz) for heartbeat
    bSendTrig := "Clock_1Hz" AND NOT "bPrev1Hz";
    "bPrev1Hz" := "Clock_1Hz";
    "FB_TSEND_C".REQ := bSendTrig;

    // Mirror status for diagnostics
    "DB_OUC_Diag".lastStatus := "FB_TSEND_C".STATUS;
    "DB_OUC_Diag".busy       := "FB_TSEND_C".BUSY;
    "DB_OUC_Diag".error      := "FB_TSEND_C".ERROR;
    "DB_OUC_Diag".done       := "FB_TSEND_C".DONE;
    "DB_OUC_Diag".ndr        := "FB_TSEND_C".NDR;

    // Capture received length
    IF "FB_TSEND_C".NDR THEN
        diRxLen := DWORD_TO_DINT("FB_TSEND_C".RCVD_LEN);
        "DB_OUC_Diag".lastRxLen := diRxLen;
    END_IF;
END_FUNCTION_BLOCK

Ladder Logic Alternative (TIA Portal V15.1)

For engineers on the classic LAD editor without SCL, the equivalent call is a single network with the TSEND_C instance:

Network 5: TSEND_C call
   "Tag_SendTrig"    ---|"| |----+----( "FB_TSEND_C".REQ )
                                 |
   TRUE              ---------|"  |----( "FB_TSEND_C".CONT )
                                 |
   32                ---------|-/P-+----( "FB_TSEND_C".LEN )

Receive data is automatically written to the configured DATA range; no separate TRCV call is needed.

Status Code Reference for OUC Blocks

The following table covers the status codes most commonly encountered during a soft-reboot reconnection failure on the S7-1200 platform. All values are 16-bit in the lower word of the STATUS DWORD; the upper word is reserved.

STATUS (hex) Block Meaning Field Action
0000_0000 All No error / no job active Normal idle state.
7000_0000 TRCV / TCON No job pending (initial state) Ensure REQ is pulsed.
7001_0000 TRCV Receive started, waiting for data Normal; do not re-trigger.
7002_0000 TRCV Receive in progress, data incoming Wait for NDR or ERROR.
7003_0000 TCON Connection establishment in progress Wait for DONE.
80A1_0000 All Connection or channel error (e.g. partner closed) Issue TDISCON, then TCON or rely on TSEND_C auto-reconnect.
80A7_0000 TRCV / TSEND Partner initiated disconnect (FIN received) Same as above; TSEND_C handles it automatically.
80B0_0000 TCON No free connection resource Reduce simultaneous connections; max 8 per CPU on V4.x.
80C3_0000 TCON Connection terminated by remote Re-arm with TDISCON + TCON, or migrate to TSEND_C.
80C8_0000 TRCV Connection not established Check TCON status; check CONNECT UDT fields.
80E2_0000 TCON Connection ID already in use / internal resource busy Re-arm after TDISCON, or migrate to TSEND_C (root cause of this article).
80E3_0000 TDISCON Disconnect in progress Wait for DONE.
80FF_0000 All Internal CP error / firmware fault Power-cycle CPU; check firmware version.

Verification Procedure

  1. With the new TSEND_C code loaded, place the CPU in RUN.
  2. Confirm a TCP session to the PC server is established (Wireshark or netstat on the server).
  3. Trigger the soft reboot via your HMI button or RESTART call.
  4. Within 2–5 s, observe in Wireshark: a FIN, ACK from the PLC, followed by a fresh SYN from the PLC and a SYN, ACK from the server.
  5. On the server, confirm the new client port and the heartbeat payload is being received.
  6. Check DB_OUC_Diag.lastStatus — it should be 7001_0000 (receive started) or 0000_0000 (idle between sends), not 80A1 or 80E2.
  7. Run a 24-hour soak test with a soft-reboot triggered every 30 minutes; log the lastStatus and lastRxLen to confirm no degradation.

Edge Cases and Additional Caveats

Firmware-Specific Behavior

S7-1200 CPUs with firmware V4.0 to V4.1 do not support TSEND_C in the same consolidated form; on those platforms, the recommended pattern is a periodic TDISCON-then-TCON cycle driven by a watchdog timer. Reference: Siemens FAQ 67364622 — Open User Communication with S7-1200.

Keep-Alive vs Soft Reboot

The PLC does not emit TCP keep-alives by default. If the PC server has an idle-timeout of 60 s and the PLC only sends every 5 minutes, the server will close the socket while the PLC is still in 7001_0000 state. Add a 10-s heartbeat in the application layer, or enable the “Keep alive” parameter in the TCON_Param UDT (field “ActiveEstablishment” plus the keep-alive interval, supported on FW V4.3+).

Multiple Soft Reboots in Quick Succession

If your user logic re-initializes more than once per second, the CP layer will reject the second bind with W#16#80B0 (no free resource). Insert a 2-s TON timer between initialization cycles; this is the minimum recovery time for the internal TCP close-handshake on the S7-1200.

Replacing TCON With TSEND_C on a Live System

The migration requires a STOP→RUN transition once, because the connection descriptor must be cleared from the work memory. Plan a 30-s outage. After the first RUN, no further restarts are required for reconnection logic.

Troubleshooting Matrix

Symptom First-Cycle STATUS (mirrored) Wireshark Signature Likely Root Cause Fix
TRCV hangs after soft reboot, no error visible 80E2_0000 then 0000 No SYN after FIN Stale CP handle; legacy TCON+TRCV pattern Migrate to TSEND_C (this article’s scenario)
Connection establishes, then server logs “client closed” after 60 s 80A7_0000 FIN from PLC, no further SYN Server idle timeout, no app-layer heartbeat Add 10-s heartbeat; enable keep-alive in CONNECT UDT
TRCV reports “data” but buffer is zeroed 7002_0000 Normal traffic DATA pointer overlap or DB optimized-access mismatch Use standard-access DB for DATA pointer
Status always 0000 even on fault 0000_0000 (read late) Any STATUS one-cycle visibility Mirror STATUS to a global DB tag
TSEND_C “DONE” never sets 7003_0000 SYN without SYN-ACK Firewall on PC or wrong IP/port Disable Windows firewall rule for inbound 2000/TCP; verify IP
Multiple soft reboots, second one fails 80B0_0000 SYN retransmit Re-arming too fast Add 2-s TON between init cycles

Why the STATUS-Mirror Pattern Is Non-Negotiable

Even after migrating to TSEND_C, the diagnostic mirror in DB_OUC_Diag must remain. The STATUS output of TSEND_C is subject to the same one-cycle visibility rule. A Siemens support entry states explicitly: “the parameter ERROR, STATUS etc shows the value only for its own cycle. You have to copy the DWORD of STATUS in another memory to analyze the error code.” Without the mirror, a future firmware update or a new error condition will produce the same “no error” mystery the original poster encountered.

Alternative Controller Platforms (Cross-Reference)

For engineers who may need to replicate this pattern on other Siemens families:

  • S7-1500: The same TSEND_C / TRCV_C pattern applies, but the consolidated block is named TRCV_C for receive-dominant flows. State machine is identical. Reference: Siemens KB 109768639.
  • ET 200SP CPU: Identical to S7-1500, FW V2.5 and later. Uses the same instruction set.
  • S7-300/400: No TSEND_C; use TCON+TRCV from the standard library. The hang behavior is similar and requires the periodic disconnect/connect pattern.

Field-Proven Commissioning Checklist

  • Confirm CPU firmware ≥ V4.2 (use Online → Diagnostics → CPU Information).
  • Configure the CONNECT UDT in the TSEND_C instance with ActiveEstablished = TRUE (PLC is client).
  • Set LocalPort = 0 to let the CPU assign an ephemeral port; the PC server identifies the PLC by IP only.
  • Set RemotePort to a fixed value on the server (e.g. 2000) and disable the server-side idle timeout or extend it to >5 minutes.
  • Enable Web Server on the CPU (default port 80) to view the mirrored DB_OUC_Diag from a browser — useful for remote troubleshooting without TIA Portal.
  • Add the DB_OUC_Diag tags to a watch table in TIA Portal and pin them for permanent online monitoring.
  • Document the soft-reboot trigger path (HMI tag, OB100, or application) so the same sequence can be replayed in QA.

Why does my S7-1200 TRCV block show STATUS = 0 even though the TCP connection is broken?

The STATUS output of all Open User Communication blocks (TCON, TDISCON, TSEND, TRCV, TSEND_C) is valid for one scan cycle only. If you read it from an HMI or watch table after that cycle, you will see W#16#0000_0000. Mirror STATUS to a global DB tag immediately after the block call to capture transient errors.

How do I re-establish a TCP connection after a soft reboot on the S7-1200 without stopping the CPU?

Replace the legacy TCON + TSEND + TRCV + TDISCON instruction set with the consolidated TSEND_C block. TSEND_C contains an internal state machine that re-arms the connection on every RUN transition, including soft reboots, without requiring the user to manually pulse TDISCON and TCON.

What STATUS code indicates the connection ID is already in use after a soft reboot?

W#16#80E2_0000 on TCON indicates that the connection descriptor in the CP layer still holds a stale TCP handle from the previous session. This is the root cause of the “TRCV hangs after soft reboot” symptom and is the specific code the original poster missed because it was overwritten on the next scan.

Does TSEND_C work on S7-1200 firmware V4.0 or V4.1?

No. TSEND_C in its consolidated form requires S7-1200 firmware V4.2 or later (6ES721x-1xxxxx-0XB0 with FW V4.2+). On V4.0/V4.1 you must use the legacy TCON + TRCV pattern with a periodic TDISCON/TCON watchdog cycle.

How many simultaneous TCP connections does an S7-1200 support?

The S7-1200 CPU supports up to 8 Open User Communication connections (active, passive, or mixed) on firmware V4.x. Exceeding this limit returns W#16#80B0_0000 on TCON. For more connections, add a CP 1243-1 or CP 1242-7 communications processor.

Back to blog