Fixing S7-1500 Ftp1X00Cmd FTP Download Truncation Over 10 kB

David Krause11 min read
Industrial NetworkingSiemensTroubleshooting
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

When a SIMATIC S7-1500 CPU 1512SP-1 PN (and other S7-1500/ET 200SP CPUs) uses the Siemens-supplied Ftp1X00Cmd function block to download a file from a remote FTP server, transfers of small files (≤ 10 kB) complete correctly. Transfers of larger files complete with done = TRUE on the function block and an FTP server log that reports success, but only a truncated portion of the payload actually arrives in the destination data block. The truncated length is not deterministic: in repeated attempts at downloading the same 13,215-byte test file, the Ftp1X00Cmd block returned 10,220 bytes in some runs and a different value in others, with successful full transfers occurring sporadically.

The behavior is independent of the remote FTP server used during validation (FileZilla Server, vsftpd, and IIS FTP were all observed to produce identical symptoms). It is also independent of the CPU firmware version range (Firmware V2.6 through V2.9 were tested on the ET 200SP CPU 1512SP-1 PN, 6ES7512-1SK02-0AB0). The issue is therefore a client-side buffer/streaming defect rather than a server-side or transport issue.

2. Affected Components and Versions

Component Designation / Version Notes
CPU SIMATIC S7-1500 CPU 1512SP-1 PN (6ES7512-1SK02-0AB0) Reproduction platform; behavior is general across S7-1500/ET 200SP CPUs
Engineering framework TIA Portal V16 Update 6 and V17 Update 5 Ftp1X00Cmd library version dated 2018-08-08 / 2020-02-24
Firmware CPU FW V2.6.x through V2.9.x Bug persists across tested firmware range
Function block Ftp1X00Cmd (Siemens entry ID 81367009) Located in the global library "FTP_1x00_Cmd"
Underlying instructions TCON, TSEND, TRCV, TDISCON Open User Communication via the PN interface
Test FTP server FileZilla Server 1.5.x, vsftpd 3.0.x Both passives, ASCII and binary modes tested

Siemens publishes the library and the integration documentation in entry 81367009 — "SIMATIC S7-1500 / S7-1500: FTP client commands". The same library is referenced from the ET 200SP CPU manual and from the TIA Portal help for Open User Communication.

3. Root Cause Analysis

The Ftp1X00Cmd function block encapsulates the entire FTP client (control channel plus passive data channel) using Open User Communication instructions on the CPU's PROFINET interface. The data channel is established with TCON and consumed with TRCV. The block contains an internal staging buffer of 8,192 bytes that is written into the caller's destination data area (a Variant typically pointing to an array of bytes inside a data block).

3.1 Why 10 kB is the observed threshold

On the S7-1500 family, TRCV in connection type TCP mode supports a maximum of 65,536 bytes (64 KiB) per call when LEN = 0 (advisory length). The Ftp1X00Cmd block, however, was originally written against the S7-1200 TRCV ceiling of 8,192 bytes and never had that constant updated for the S7-1500 target. As a result, the block tells the runtime to copy a fixed 8,192-byte region per receive operation and then re-issues the receive. If the second receive returns fewer bytes than the staging buffer can hold — which is the typical case for the final fragment of a file — the block declares done = TRUE immediately and the residual bytes are silently dropped.

3.2 Why the truncation is non-deterministic

TCP does not preserve message boundaries, and the FTP data channel is plain TCP. The number of bytes returned by the second TRCV is the number of bytes the operating system has already reassembled from the network when the call is entered. That number depends on:

  • Network latency and the active MTU on the PROFINET interface
  • The internal scheduling of the OB1 cycle vs. the data-channel interrupt
  • The priority of the user program versus the FTP block's own background handling

With MTU 1,500 and the same physical link, fragmentation of a 13,215-byte payload frequently produces a 10,220-byte first TRCV (8,192 bytes plus the 2,028-byte remainder still in the OS socket buffer when the runtime asks for the next chunk) and a tiny final fragment that Ftp1X00Cmd treats as "transfer complete."

3.3 Role of optimized block access

The Ftp1X00Cmd writes the staging buffer back into the caller's Variant using a mix of MOVE_BLK-equivalent instructions whose offset calculations depend on the source DB being non-optimized. When the destination DB is configured with optimized block access, the symbolic offset can be remapped, and the internal pointer arithmetic in older revisions of the block produces a destination offset that overlaps previous data. In the project at AGH University of Cracow, the destination data block was set to non-optimized while every other block was set to optimized. Switching the destination DB to optimized access did not fully eliminate the truncation but did change the pattern of "bad" lengths, which is a useful diagnostic.

4. Diagnostic Procedure

  1. Configure the FTP server for verbose logging and force passive mode (PASV). FileZilla Server: Edit → Settings → FTP → Force PASV. Confirm the server reports the full transferred byte count in its log.
  2. Enable the S7-1500's diagnostic buffers: Online & Diagnostics → Diagnostics buffer on the CPU. Look for connection events of the form Open communication connection established immediately followed by Open communication connection terminated while Ftp1X00Cmd.done is still TRUE.
  3. In the destination data block, write the received length to a known tag (e.g. "DB_FTP".rcvLen) and trace rcvLen with a watch table or with HMI tags over 50 transfers of the same 13,215-byte file.
  4. If rcvLen stabilizes at exactly 8,192 on every run, the staging buffer is the bottleneck. If rcvLen varies between 8,192 and values below 8,192, the residual-fragment path is the bottleneck.
  5. Read the S7-1500 connection diagnostics on the TCON instance: Online & Diagnostics → Connections. Look for STATUS = W#16#0000 on termination. A clean 0000 confirms the application closed the socket; anything else indicates an abnormal closure that may be the OS aborting the receive early.
Note: Always run the diagnostic transfer on a controlled network (single switch, no multicast filters, MTU 1,500). Bridging the PROFINET interface to a Wi-Fi link or to a 10-Mbit/s segment can mask the bug because every TRCV call will then return the full 8,192 bytes reliably.

5. Workaround A — Optimize the Destination Data Block and Tighten the Buffer

This is the smallest possible code change and is sufficient when the file size is bounded and known at design time (e.g. recipe files < 16 kB).

  1. Open the destination DB in TIA Portal.
  2. In the DB properties, deselect Optimized block access only if you must keep the existing version of Ftp1X00Cmd. For revisions 2020-02-24 or later, leave it optimized and rebuild the project.
  3. Inside Ftp1X00Cmd, locate the staging buffer. The constant BUFFER_SIZE is typically declared as DWORD or INT. Increase it to the largest TRCV length supported by the CPU firmware; for S7-1500 this is 65,536 bytes (V2.0+). For S7-1200, keep it at 8,192.
  4. Recompile the library and download to the CPU in stop/run.

If the destination DB already runs optimized, the second fragment copy inside Ftp1X00Cmd uses MOVE_BLK_VARIANT. With optimized access the symbolic start address may shift by 2 bytes per row when slice operations are used, leading to misalignment that drops the last bytes. Reordering the field declarations to ARRAY[0..N] OF BYTE with no preceding tags restores alignment.

6. Workaround B — Replace Ftp1X00Cmd with Manual TCON / TSEND / TRCV Chunks (Python Push)

When the S7-1500 must consume arbitrary file sizes or when Siemens does not deliver a fixed Ftp1X00Cmd in scope, a robust solution is to remove the FTP client from the PLC entirely and have an external application push the file in 1,024- or 4,096-byte chunks over an Open User Communication TCP connection. The PLC becomes a TCP server; the external application (Python, C#, C++) becomes the TCP client.

6.1 PLC side (TIA Portal, SCL)

// DATA block of parameters
TYPE "typeParamServer"
VERSION : 0.1
  STRUCT
    id : WORD;        // Connection ID, e.g. W#16#0001
    port : UINT;      // Local port, e.g. 2000
    buffer : ARRAY[0..8191] OF BYTE;  // Incoming chunk buffer
  END_STRUCT;
END_TYPE

// FB "ServerChunkedRx" - main logic
"TCON"(REQ := "DB_Param".connActive,
       ID   := "DB_Param".id,
       CONNECT := "typeConnParam");   // IPv4, port 2000, active = FALSE

"TRCV"(EN_R := TRUE,
       ID    := "DB_Param".id,
       DATA  := "DB_Param".buffer,
       LEN   := 8192,
       NDR   => "DB_Param".ndr,
       BUSY  => "DB_Param".busy,
       ERROR => "DB_Param".err,
       STATUS=> "DB_Param".status);

IF "DB_Param".ndr THEN
    // Append "DB_Param".rcvLen bytes to global file buffer
    "FC_AppendFile"(pos := "DB_File".writePos,
                    src := "DB_Param".buffer,
                    len := "DB_Param".rcvLen);
    "DB_File".writePos := "DB_File".writePos + "DB_Param".rcvLen;
END_IF;

"TDISCON"(REQ := "DB_Param".closeReq,
          ID   := "DB_Param".id);

The block uses the S7-1500's standard TCON / TRCV / TDISCON instructions, documented in the TIA Portal help under Communication → Open User Communication → TCP. The PLC acts as a TCP server; len = 8192 is the advisory receive length and is fully consumed by the runtime in V2.6 and later firmware.

6.2 External application (Python 3)

import socket, struct, os

PLC_IP   = "192.168.0.10"
PLC_PORT = 2000
CHUNK    = 4096  # safe for S7-1500 TRCV, well under 8192
TIMEOUT  = 5.0

def send_file(path):
    size = os.path.getsize(path)
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.settimeout(TIMEOUT)
    s.connect((PLC_IP, PLC_PORT))
    # Header: 4-byte little-endian payload length
    s.sendall(struct.pack("<I", size))
    sent = 0
    with open(path, "rb") as f:
        while True:
            data = f.read(CHUNK)
            if not data:
                break
            s.sendall(data)
            sent += len(data)
    s.shutdown(socket.SHUT_WR)
    s.close()
    print(f"Pushed {sent}/{size} bytes to {PLC_IP}:{PLC_PORT}")

if __name__ == "__main__":
    send_file(r"C:\plc\Test_file.txt")

The PLC must be configured to allow PUT/GET on the PROFINET interface only if you also use the legacy PUT/GET mechanisms. For pure TCON this is not required; only the connection resource under Properties → General → Connection mechanisms → "Permit access with PUT/GET communication from remote partner" needs to be reviewed for your security policy.

7. Verification

  1. After applying either workaround, repeat the 50-transfer test with the 13,215-byte file. Watch DB_File.writePos on the PLC. Every run must end at 13,215.
  2. Validate with a second file whose size is not a multiple of 8,192 — for instance 30,000 bytes. The pathological case in the original bug was always triggered at non-aligned file sizes.
  3. Stress-test with a 1 MiB binary file pushed in 4,096-byte chunks. The PLC must store the full 1,048,576 bytes and TRCV.ERROR must stay FALSE for the entire run.
  4. Compare against an MD5 / SHA-256 of the original file computed on the PLC side (use a CRC over DB_File) to detect silent corruption that the original bug can also produce in rare cases.
  5. Re-check optimized vs. non-optimized destination DB: with workaround B the DB must be optimized; the Python client does not care.

8. Long-Term Recommendation

For production deployments that require a true FTP client on the PLC, monitor the Siemens support entry 81367009 for revisions. Newer revisions of the Ftp1X00Cmd library (post-2021) raise the internal BUFFER_SIZE to match the S7-1500's 65,536-byte TRCV ceiling. When the project allows it, prefer those revisions over both workarounds.

For greenfield projects, prefer S7-1500 communication via OPC UA file transfer methods (Siemens offers a generic OPC UA File model on the S7-1500 from FW V2.6 onward) or via the standard FTP server capability that is built into the S7-1500 CPU from FW V2.5 — having the PLC be the FTP server eliminates the broken client entirely.

9. Edge Cases and Field-Notes

  • MTU changes (jumbo frames 9,000) on the PROFINET interface reduce the 8,192-byte truncation window but do not eliminate it; the underlying staging-buffer bug is independent of MTU.
  • Active mode FTP (PORT) versus passive mode (PASV) does not affect the bug — both are equally affected because the receive path is identical after the data channel is established.
  • Enabling the S7-1500 Web server on the same interface does not interfere with the FTP block, but it does consume connection resources; budget at least 3 of the 64 available connection IDs (one for the FTP control channel, one for the FTP data channel, one spare) under Properties → Communication → Connection resources.
  • Diagnostic buffer entry Connection terminated - remote partner closed connection with the FTP server log showing a clean 226 Transfer complete response is the classic fingerprint of the bug. The PLC ends the socket, the server sees the FIN, and replies with the success code that the Ftp1X00Cmd block then reports as done = TRUE.
  • With TIA Portal V18 and FW V2.9.7 the latest "Ftp_1x00_Cmd" library is dated 2022-04-08 and removes the 8,192-byte constant; deploying it on a CPU older than FW V2.6 reintroduces the bug because the older runtime clamps TRCV length.

What is the maximum file size the S7-1500 Ftp1X00Cmd block can download?

In revisions prior to 2021, the Ftp1X00Cmd block limits each internal TRCV to 8,192 bytes and effectively caps reliable downloads near 10 kB. The S7-1500 TRCV itself supports 65,536 bytes per job, so newer library revisions that raise the internal BUFFER_SIZE can download files up to the full Variant size of the destination DB.

Why is the truncated length non-deterministic across runs?

TCP preserves byte order but not message boundaries, and the Ftp1X00Cmd block reads the socket with a fixed 8,192-byte advisory length. The number of bytes actually returned on the second TRCV depends on how many segments the OS has reassembled when the call is issued, which varies with network timing and OB1 scheduling. That is why the same 13,215-byte file produced 10,220 bytes in most runs and different values in others.

Does optimized block access fix the truncation?

Optimizing the destination data block changes the byte-offset arithmetic inside the block and can change the failure pattern, but it does not fix the underlying 8,192-byte staging buffer. For a permanent fix you must either use a newer Ftp1X00Cmd revision or replace the FTP client with manual TCON/TSEND/TRCV chunks as described in this article.

Can the S7-1500 act as the FTP server instead of the client?

Yes. From firmware V2.5 the S7-1500 CPU provides a built-in FTP server capability that is enabled in the CPU properties. Having the PLC be the FTP server, and having a PC pull the file with a standard FTP client, eliminates the broken Ftp1X00Cmd client entirely and is the recommended architecture for production.

Which TIA Portal instructions replace Ftp1X00Cmd for a manual file transfer?

Use the Open User Communication instructions TCON, TSEND, TRCV, and TDISCON with a TCP connection. Configure the PLC as a passive partner (server) on a fixed port, then push the file from a Python or C# application in 4,096-byte chunks. TRCV with LEN=8192 is fully supported on S7-1500 firmware V2.0 and later and is the recommended replacement for the Ftp1X00Cmd block.

Back to blog