S7-300 PUT/GET Timing: CPU Priority Classes and OPC Execution
Overview of S7 Communication
S7 Communication is the native Siemens protocol used to exchange data between SIMATIC S7 PLCs and between S7 PLCs and external systems such as OPC servers, HMIs, and other controllers. On the S7-300 and S7-400 platforms, S7 Communication rides on top of Industrial Ethernet (PROFINET), PROFIBUS, or MPI, depending on the CPU hardware. When a PC-based application — typically the SIMATIC NET OPC server or an HMI runtime — reads or writes tags on an S7-300 CPU, the data movement happens through one of the S7 Communication function blocks: PUT, GET, USEND/URCV, or BSEND/BRECV.
The behavior most engineers need to predict is when those instructions actually move data. PUT and GET are not executed instantly at the moment a user calls them; they participate in the S7 CPU's OB-based priority scheduler. Likewise, the OPC server does not maintain a real-time mirror of the PLC — it polls the CPU through S7 Communication whenever an OPC client request arrives. The remainder of this article dissects that scheduling model so PUT/GET latency and OPC refresh behavior can be predicted and tuned.
S7 CPU Execution Model
The S7-300 CPU uses a priority-based, preemptive scheduler. Every block of user code lives inside an Organization Block (OB), and every OB has a priority class assigned either by the CPU firmware (fixed classes for hardware-triggered OBs) or by configuration in HW Config or TIA Portal (for time-of-day, cyclic, and delay OBs). At any given moment the CPU is running the highest-priority OB whose trigger event has fired and that is not blocked.
Fixed OB Priority Classes
| OB | Name | Priority | Trigger |
|---|---|---|---|
| OB1 | Main cyclic program | 1 | Cyclic, free cycle |
| OB10–OB17 | Time-of-day interrupts | 2 (configurable 2–24) | Configured time/date |
| OB20–OB23 | Delay interrupts | 3–6 | After SFC32 delay expires |
| OB30–OB38 | Cyclic interrupts | 7–15 (configurable) | Configured interval (e.g. 100 ms) |
| OB40–OB47 | Hardware interrupts | 16–23 | Rising/falling edge on DI, MSI/MSO, or PN I/O |
| OB55–OB57 | DP interrupts | 2 | PROFIBUS DP diagnostic events |
| OB60 | Multicomputing interrupt | 25 | SFC35 trigger |
| OB80 | Time error | 26 (or cause + 1) | OB1 overrun, OB call missed |
| OB82 | Diagnostic interrupt | 24 | I/O fault on a diagnostic-capable module |
| OB83 | Insert/remove interrupt | 24 | Module insertion or removal |
| OB85 | Program execution error | 24 | OB not loaded when event occurred |
| OB86 | Rack failure | 24 | DP/PN master failure |
| OB87 | Communication error | 24 | Communication fault |
| OB90 | Background OB | 0 | Idle time in OB1 |
| OB100–OB102 | Startup | 27 | Restart / warm restart / cold restart |
Critical scheduling rule: Any OB whose priority class is strictly greater than the currently running OB may interrupt it immediately. OB1 runs at priority 1; a hardware interrupt in OB40 fires at priority 16 and will preempt OB1 in microseconds. PUT/GET calls placed inside OB1 will pause — and partially lose their scheduling slot — every time an OB40–OB47 fires.
CPU Priority Class Interaction Diagram
PUT and GET Instruction Execution
PUT (FB15) writes data from the local CPU to a remote CPU, GET (FB14) reads data from a remote CPU into the local CPU. Both are S7 Communication blocks that operate over a configured S7 connection and run inside whichever OB calls them — typically OB1, but they can equally well be called from a cyclic interrupt OB if deterministic timing is required.
Step-by-Step Execution of GET
- The
REQinput of the GET instance receives a rising edge (typically from a one-shot of the OB cycle counter). - The CPU schedules the S7 Communication request in the next communication time slice of the running OB.
- The request is sent over the configured S7 connection (ID parameter, LADDR or partner parameters).
- The remote CPU's S7 Communication service receives the request and prepares a response.
- The response arrives at the local CPU in a subsequent communication time slice.
- The
DONEbit goes TRUE for one scan,ERRORandSTATUSprovide the result.
Key Timing Truths
- PUT and GET are not triggered by the OPC server. They are triggered by the OB cycle in which the block instance resides.
- A PUT/GET request placed in OB1 will only fire once per OB1 cycle maximum (unless retriggered in the same scan).
- If a higher-priority OB fires during the GET call, the call is paused; the communication state machine resumes when control returns.
- The CPU allocates a configurable portion of every scan — by default ~10–20% — to communication processing. PUT/GET requests submitted in OB1 are buffered and serviced in that time slice.
PUT Instance Parameter Block (S7-300/400 STL)
DATA_BLOCK DB200 "PUT_DB"
// Instance data block for PUT block (FB15)
// Adjust to your application
BEGIN
// Inputs (driven from OB1 or cyclic OB)
REQ := FALSE; // Trigger: rising edge starts a write
ID := W#16#0001; // S7 connection ID from NetPro/PCD
DONE := FALSE; // Set by FB15: write complete (one scan)
ERROR := FALSE; // Set by FB15: error occurred
STATUS := DW#16#00000000; // Set by FB15: detailed status code
// Remote CPU addresses (max 4 ranges, max 160 bytes total)
ADDR_1 := P#DB100.DBX 0.0 BYTE 50;
ADDR_2 := P#M 200.0 BYTE 30;
ADDR_3 := P#DB120.DBX 0.0 BYTE 40;
ADDR_4 := P#E 0.0 BYTE 40; // not allowed in remote — example
// Local source data (must match ADDR_n byte counts)
SD_1 := P#DB200.DBX 0.0 BYTE 50;
SD_2 := P#M 0.0 BYTE 30;
SD_3 := P#DB210.DBX 0.0 BYTE 40;
SD_4 := P#M 50.0 BYTE 40;
END_DATA_BLOCK
// Call in OB1
CALL "PUT_DB" , DB200 ;
Data Size Limits
| Block | Direction | Max Data | Acknowledged | Typical Use |
|---|---|---|---|---|
| PUT (FB15) | PLC → Remote | 160 bytes | Yes | Small writes, recipe download |
| GET (FB14) | PLC ← Remote | 160 bytes | Yes | Small reads, status polling |
| BSEND (FB12) | PLC → Remote | 32 768 bytes | Yes | Large block writes |
| BRECV (FB13) | PLC ← Remote | 32 768 bytes | Yes | Large block reads |
| USEND (FB8) | PLC → Remote | 4 bytes | No | Fast unacknowledged sends |
| URCV (FB9) | PLC ← Remote | 4 bytes | No | Fast unacknowledged receives |
PUT/GET cap at 160 bytes because each block call constructs a single S7 Communication SDU (Service Data Unit) containing user data plus four address descriptors. For data volumes exceeding that, BSEND/BRECV fragment the data into multiple SDUs across multiple communication time slices.
BSEND and BRECV Behavior
BSEND/BRECV are the right blocks when a single exchange must move more than 160 bytes. From the CPU scheduling perspective they are identical to PUT/GET — they run inside the calling OB, use the same communication time slice, and are subject to the same priority preemption. The visible difference is that BSEND returns DONE only when the full buffer has been acknowledged, which can take multiple communication cycles for a 32 KB transfer. During that window, BSEND must continue to be called (typically from OB1) so the S7 Communication state machine can advance; if the calling OB is starved by higher-priority OBs, BSEND will take proportionally longer to complete.
For an S7-300 with a configured communication load of 20% and an OB1 cycle of 30 ms, a 4 KB BSEND typically completes in 30–80 ms; a 32 KB BSEND can take 250–650 ms. These numbers are rough — actual throughput depends on network latency and the partner's S7 Communication load. Always validate with PUT/GET/BSEND DONE/STATUS timing captured in the user program.
SIMATIC NET OPC Server Communication
The SIMATIC NET OPC server (now distributed as part of TIA Portal and the SIMATIC NET PC software) is the most common way for SCADA, MES, and historian systems to read S7-300/400 tags. The OPC server wraps an S7 Communication connection to the PLC and exposes each tag as an OPC item. Internally it uses GET (reads) and PUT (writes) over its single S7 connection to the PLC — there is no special "OPC protocol" on the wire.
OPC Request Lifecycle
Synchronous vs Asynchronous — Where It Matters
The synchronous or asynchronous access type that OPC clients see refers strictly to the OPC client↔OPC server dialog on the PC side:
- Synchronous read: OPC client thread blocks until the OPC server returns the value (or times out).
- Asynchronous read: OPC client continues other work; OPC server invokes the client's callback when the read completes.
From the PLC's perspective, neither mode changes anything. Both modes result in exactly one S7 Communication GET being issued, and that GET is processed in the PLC's communication time slice as soon as scheduling allows. If the SCADA vendor advertises "asynchronous OPC for faster PLC refresh," that is misleading — what they really mean is that the SCADA application thread isn't blocked waiting on the OPC server.
OPC Server Configuration Touchpoints
| Parameter | Default | Effect on PLC Refresh |
|---|---|---|
| S7 connection count | 1 | More connections → more PLC time slices consumed |
| Update rate (cache poll) | 100 ms | Lower → tighter CPU load |
| Single / multiple read per cycle | Multiple | Single-read recommended for determinism |
| Tag group bandwidth | — | Lower bandwidth → more time slices needed |
| PG/PC interface selection | TCP/IP Auto | Wrong selection → no S7 connection at all |
Interrupt Protection and OB4x Handling
There is no single instruction in S7-300/400 to globally disable hardware interrupts at runtime the way some IEC 61131-3 runtimes expose DISABLE_INTERRUPTS. Instead, interrupt gating is achieved through several mechanisms:
- SFC36 / SFC37 (SET_CLK / SET_CINT): Activate/deactivate time-of-day interrupts (OB10–OB17).
- SFC32 / SFC33 / SFC34 (SRT_DINT / CAN_DINT / QRY_DINT): Start, cancel, and query delay interrupts (OB20–OB23).
- SFC40 (EN_IRT) / SFC41 (DIS_IRT): Enable/disable interrupts generically (process, alarm, status, update, manufacturer).
- Custom gating: Use a boolean flag in OB40–OB47 that is set by user logic when the protected section is active. Hardware interrupts during the protected window can be either ignored (counter incremented) or queued depending on logic.
SFC40 / SFC41 — Interrupt Gating Example
// In OB1, before entering critical section
CALL SFC 41 "DIS_IRT" ; // Disable all interrupts
MODE := B#16#0; // 0 = all interrupts
OB_NR := 0; // 0 = no specific OB filter
// ... critical user code (must be short,
Leaving DIS_IRT active for longer than OB1 cycle can suppress OB80 time errors. Always pair SFC41 with a matching SFC40 before the OB1 cycle ends. If OB1 is so heavily loaded that SFC40 never runs, the CPU will eventually raise an OB85 program execution error indicating that OB80 was missed.
Why PUT/GET Are Not "Interrupt-Proof"
PUT and GET do not internally call SFC40/SFC41, so any OB40–OB47 that fires during a PUT/GET call will preempt it. If the preemption window is longer than the S7 partner's response timeout, the local PUT/GET will eventually fail with STATUS = W#16#80B1 or similar. The standard mitigation is to either (a) shorten the OB4x handler, (b) use OB90 background OB for non-critical code, or (c) call PUT/GET from a cyclic interrupt OB with a known, bounded duration.
Communication Time Slice Configuration
The communication time slice is configured per-CPU via HW Config (Step 7) or TIA Portal. The setting determines the maximum fraction of each scan dedicated to communication.
| Setting | Default | Range | Side Effect |
|---|---|---|---|
| Communication load (% of cycle) | 20 % | 5 % – 50 % | Higher → faster comms, slower OB1 |
| Scan cycle monitoring time | 150 ms (default) | 1 ms – 6 s | Below 150 ms requires explicit confirmation |
| OB85 call behavior | Special OB80 handling | — | Wrong setting → OB80 storms |
| Number of S7 connections | CPU-dependent (typically 4–16) | — | More → more CPU RAM, slower table lookup |
Reading Live CPU Load
System State List (SZL) entries report live cycle and load metrics. Read them via SFC51 "RDSYSST":
// Read OB1 cycle time and cycle count
CALL SFC 51 "RDSYSST" ;
SZL_ID := W#16#0A92; // CPU runtime / load metrics
INDEX := W#16#0000;
RET_VAL := MW 100; // 0 = success
BUSY := M 110.0;
SZL_HEADER := MW 112; // length / count
DR := P#DB 250 DBX 0.0 BYTE 34;
// After SFC51 completes (BUSY=FALSE), DB250 contains:
// DBW0 – OB1 minimum cycle time (ms)
// DBW2 – OB1 maximum cycle time (ms)
// DBW4 – OB1 current cycle time (ms)
// DBD6 – CPU utilisation % (x100)
// DBW10 – Communication load %
Typical Timing Reference (S7-300 CPU 315-2 PN/DP)
| Scenario | OB1 Cycle | PUT/GET Round-Trip | Notes |
|---|---|---|---|
| Light load, no PROFINET IO | 5–15 ms | 30–80 ms | 2–3 OB1 cycles per exchange |
| Medium load with 32 PROFINET IO devices | 20–50 ms | 80–250 ms | Comm time slice shared with PN IO |
| Heavy load + cyclic OB35 @ 20 ms | 30–80 ms | 150–500 ms | OB35 preemption fragments comms |
| S7-300 with 5 active S7 connections + OPC | 40–100 ms | 200–800 ms | Connection round-robin arbitration |
PUT/GET Status Codes Worth Memorising
| STATUS | Meaning | Field Action |
|---|---|---|
| W#16#0000 | Idle / no error | None |
| W#16#0001 | DONE — operation complete | Process result |
| W#16#7000 | REQ seen, request in progress | Wait |
| W#16#7001 | First request executing | Wait |
| W#16#7002 | Follow-up request executing | Wait |
| W#16#80A0 | Negative ack from partner | Check partner CPU state |
| W#16#80A1 | Partner rejected — DB not loaded | Download missing DB |
| W#16#80A2 | Partner rejected — wrong DB / write protection | Check DB attributes |
| W#16#80B1 | Partner timeout | Check network, partner CPU STOP |
| W#16#80B2 | Local connection not configured | NetPro connection missing |
| W#16#80C3 | Resource exhausted | Reduce connection count |
| W#16#80D0 | Wrong ID parameter | Verify SZL W#16#0B99 for valid IDs |
| W#16#80F3 | Address range error | Check ADDR_n parameters |
Verification Methods
Before deploying a PUT/GET or OPC integration, validate the actual latency against expected values using these methods:
- Timestamp DONE bit in user code — store a time stamp on REQ rising edge and on DONE rising edge; compute delta. Best field-proven method.
- SFC17 / SFC18 "SYNC_PI / SYNC_PO" — for process image consistency checks; not directly a comms verification but useful for interrupt coordination.
- SFC51 SZL read — read W#16#0A92 / W#16#0A91 entries for live cycle and load metrics (see code block above).
- SFC6 "RD_SINFO" — read OB1 start info to inspect the last scan time.
- SFC87 "C_DIAG" — read CPU diagnostic buffer; OB80/OB85/OB86 events reveal communication stalls.
- SIMATIC NET OPC Scout — built-in test client; reports round-trip and connection state per tag.
- Wireshark + S7 dissector — capture on the PROFINET segment and decode S7 Communication PDUs; visible immediately on the wire.
Troubleshooting Matrix
| Symptom | Likely Root Cause | Diagnostic Step | Fix |
|---|---|---|---|
| PUT/GET takes 1+ seconds | Heavy OB4x preemption of OB1 | SFC51 read W#16#0A92, check OB40 run-time | Shorten OB4x handlers; move PUT/GET to OB35 |
| OPC client shows "stale" data | OPC refresh faster than PLC comm time slice | Reduce OPC update rate to 500 ms | Increase comm time slice to 30 % |
| GET completes then fails next cycle | Connection table overflow | Check STATUS = W#16#80C3 | Reduce active S7 connections / OPC item count |
| PUT/GET STATUS = 80B1 | Partner CPU STOP or network loss | SFC87 diagnostic buffer; check partner LED | Restore partner; check cabling |
| OPC server cannot establish connection | Wrong PG/PC interface / no S7 connection in NetPro | OPC Scout test connection | Configure S7 connection in NetPro, select correct interface |
| Intermittent OB85 program errors | OB90 background overflowed | Diagnostic buffer OB85 entries | Reduce background OB work; shorten OB1 cycle |
| OB80 time errors every few minutes | OB1 cycle > scan monitoring time | Diagnostic buffer OB80 entries | Raise scan monitoring time, or shorten OB1 |
| OPC tag reads return quality BAD | S7 connection lost / PG/PC interface wrong | OPC Scout → connection state | Verify NetPro, fix Set PG/PC Interface selection |
Practical Deployment Recommendations
- Keep PUT/GET in OB1 by default. It is the simplest and most predictable. Only move to OB35 / OB36 if OB1 jitter is unacceptable and you can prove OB35 will run reliably.
- For SCADA/OPC, prefer single-read OPC mode (one GET per tag group per cycle). It reduces S7 Connection load dramatically versus individual reads.
- Configure communication load to 20 %–30 % for systems with mixed OB1 and PROFINET IO; 50 % is occasionally justified for heavy SCADA traffic.
- Use BSEND/BRECV for > 160 B — never chain multiple PUT calls to compensate; the second PUT will queue behind the first and consume two full comm time slices.
- Always size OB1 cycle margin to ≥ 2× the scan monitoring time. A 50 ms OB1 with a 100 ms monitor gives you no headroom for transient OB4x storms.
- Document the connection ID ↔ partner mapping in the project header. STATUS W#16#80B2 is much easier to diagnose if you can read the ID-to-partner table from NetPro.
Standards and Reference Material
- SIMATIC S7-300 CPU 31xC and CPU 31x: Technical Specifications — official Siemens support portal entry.
- SIMATIC NET: S7 Programming Interface — Communication Blocks — FB12/FB13/FB14/FB15 reference.
- SIMATIC NET: OPC Server Configuration and Diagnostics — official OPC server manual.
- IEC 61131-3:2013 — Programmable controllers, Part 3 (OB organization block model).
- PI (PROFIBUS & PROFINET International) — PROFINET specification for cyclic interrupt timing references.
When exactly does a PUT/GET instruction execute in an S7-300 CPU?
PUT/GET execute inside whatever OB calls them — typically OB1 — and the actual S7 Communication request is processed during the CPU's communication time slice. They are not immediate; the request is buffered and sent when the scheduler reaches the comm slice, subject to preemption by higher-priority OBs such as OB40–OB47.
Does the SIMATIC NET OPC server read PLC data continuously or only on request?
Only on request, unless an explicit polling interval is configured in the OPC server. Each client read generates a GET over the S7 connection. The PLC does not maintain a continuous data stream to the OPC server — it responds inside its scheduled communication time slice, so refresh latency equals one or more OB1 cycles plus the comm slot.
Can S7 Communication interrupt OB1 execution?
No. PUT/GET and the communication time slice cannot preempt OB1 directly. They are part of the OB1 cycle or run in OB90 background. However, if OB1 calls PUT/GET and a hardware interrupt (OB40–OB47) fires during that call, the higher-priority OB immediately preempts OB1, suspending the PUT/GET state machine until OB1 regains control.
What is the maximum data size for PUT/GET vs BSEND/BRECV?
PUT and GET are limited to 160 bytes per call across all address ranges combined. BSEND and BRECV support up to 32 768 bytes (32 KB) per exchange. For any single exchange above 160 bytes, switch to BSEND/BRECV; chaining multiple PUT calls is slower and consumes twice the comm time slots.
How can I reduce PUT/GET latency in an S7-300 system?
Increase the CPU's configured communication load (HW Config → CPU properties → Communication) toward 30 %, shorten OB4x handlers or move PUT/GET to a cyclic interrupt OB with a bounded duration, lower the OPC server's update rate to match achievable PLC throughput, and use BSEND/BRECV when transfers exceed 160 bytes. Always verify by timestamping REQ and DONE in user code.