Overview: What Happens When an S7 CPU Reports a Cycle Time Exceeded Fault
A Siemens S7-300, S7-400, S7-1200, or S7-1500 CPU monitors the execution time of the main cyclic program (OB 1) against a configurable maximum cycle monitoring time. If OB 1 does not complete within that window, the CPU calls the time-error organization block (OB 80 on S7-300/400, OB 80 on S7-1200/1500) and, if OB 80 is not loaded, the CPU transitions to STOP with the diagnostic buffer entry "Cycle time exceeded". On S7-300/400, the diagnostic event is also written as a CPU LED pattern (SF on, BF depending on the fault) and is recoverable only by warm restart, cold restart, or power cycle after the cause is removed.
The fault is non-fatal in code terms: the user program did not crash, it simply ran too long. The CPU's job is to protect the process from being controlled by a PLC that cannot keep up with its own scan, so it shuts down cleanly. The engineering task is to determine why the scan blew past its budget and to restructure the program so that OB 1 fits inside the configured monitoring time.
How the Cycle Watchdog Works on S7-300, S7-400, and S7-1200
The OB 1 cycle is supervised by the operating system. According to the Siemens Support entry 109975922 on STOP caused by cycle time exceeded, the maximum cycle time (a.k.a. cycle monitoring time) must always be set higher than the longest actual cycle time measured for the current user program. The default is 150 ms on most S7-300 CPUs (CPU 313C/314/315/317 family) and 6000 ms on S7-1200 CPUs, but both are configurable in the CPU properties under Cycle Time > Maximum Cycle Time.
The exact behavior is platform-specific:
| CPU Family | Watchdog Default | Configurable Range | Reaction on Exceed | Recovery OB |
|---|---|---|---|---|
| S7-300 (CPU 31x) | 150 ms | 1 ms – 6000 ms (HW config) | OB 80, else STOP | OB 80 |
| S7-400 (CPU 41x) | 150 ms – 6000 ms (model dependent) | 1 ms – 255000 ms | OB 80, else STOP | OB 80 |
| S7-1200 (CPU 12xx) | 6000 ms | 1 ms – 60000 ms | OB 80, else STOP | OB 80 |
| S7-1500 (CPU 15xx) | 6000 ms | 1 ms – 60000 ms | OB 80, else STOP | OB 80 |
Per the STEP 7 V20 S7-1200 functional description on cycle time: "If the cyclic program exceeds the maximum cycle time, the operating system will attempt to start the time error OB (OB 80). If the OB is not available, the S7-… will go to STOP." The same rule applies to S7-300/400 in STEP 7 V5.x and to S7-1500 in TIA Portal.
Important nuance on S7-300/400: a double exceed (i.e., the cycle time exceeds 2× the configured maximum) is treated as a hard fault and goes to STOP even if OB 80 exists. This is documented in the S7-300 CPU 31x/319F manuals under Cycle and Reaction Times.
Typical Root Causes
Cycle time exceeded faults fall into four categories. Before refactoring code, confirm the category using the diagnostic buffer and the online scan time monitor.
- Algorithmic overload in OB 1. Heavy numerical work (matrix inversion, N×N matrix math, polynomial fits, FFT, large FOR loops) executed in a single scan. This is the most common cause when simulation runs fine but the real CPU faults: PLCSIM on a workstation executes the same instructions in microseconds, while the real CPU executes them in tens of milliseconds, exposing the budget breach.
-
Infinite or runaway loops. A
FOR/WHILE/REPEAT/ SCL loop whose exit condition is never satisfied. The CPU watchdog trips before the loop terminates. Examples include divisions where the divisor approaches zero, counters that never increment, or anIFinside a loop that re-triggers the same branch. - Communication stack starvation. Too many simultaneous PG/HMI/OPC-UA/S7 connections, large PUT/GET payloads, BSEND/BRCV calls without handshake, or unacknowledged TSEND/TRCV jobs. The communications OB adds wall time to the cycle.
- Edge cases in cyclic interrupt OBs. OB 30–OB 38 (S7-300/400) and the equivalent on S7-1200/1500 that run faster than OB 1 can finish. If a 2 ms OB 35 is configured and its execution exceeds 2 ms, OB 80 fires; if OB 35 exceeds 2× its period, the CPU goes to STOP regardless of OB 80.
Diagnostic Workflow
- Capture the diagnostic buffer. In TIA Portal: Online > Online & Diagnostics > Diagnostics Buffer. Look for an event with text "Cycle time exceeded" or "Time error OB (OB 80)". Note the OB that triggered it (OB 1 vs. OB 35), the actual measured cycle, and the configured maximum.
- Measure the OB 1 time online. Use Online & Diagnostics > Cycle Time, or read the system clock via SFC 64 (TIME_TCK) at the start and end of OB 1 and compute the delta. Persist the values in a DB so post-mortem analysis is possible.
- Identify the hot block. Comment out suspected heavy blocks and re-download. Better, use the S7-300/400 Profiling tool or the TIA Portal Trace function (S7-1200/1500) to record the execution time of individual blocks. A 100 ms+ jump in a single FB is the typical signature of a matrix or iterative routine.
- Confirm in PLCSIM vs. real CPU. If PLCSIM runs and the real CPU does not, the workload is at the boundary of the real CPU's throughput. This is a sign that the algorithm is too large for a single scan on that hardware.
- Check the watchdog configuration. Verify that the configured maximum cycle time is at least 2× the measured worst-case scan. If it is already at 6000 ms and the CPU still faults, the algorithm itself must be refactored; increasing the watchdog further is not a solution.
Resolution Strategy 1 — Load OB 80 as a Safety Net
Before fixing the algorithm, install OB 80 with at least one line of code that sets a BOOL in a non-volatile DB (retain DB or instance DB) and then returns. This achieves two things:
- It prevents a single transient exceed (e.g., a 200 ms blip during commissioning) from stopping production.
- It records the fault so you know it happened. Reset the flag in OB 1 once it has been read by the HMI or historian.
OB 80 does not, however, prevent the double-exceed hard STOP, and on a single-CPU setup it does not retry the failed cycle. Treat OB 80 as a diagnostic tool and a soft cushion, not a fix.
Resolution Strategy 2 — Spread the Work Across Multiple Scans
For numerical work that does not change every scan, the standard S7 pattern is to split the work into smaller pieces and rotate through them using a state machine in OB 1. The pattern is straightforward in SCL:
FUNCTION_BLOCK "FB_MatrixWorker"
VAR
iState : INT := 0; // 0 = idle, 1..N = work chunks
iChunk : INT; // current chunk index
aWork : ARRAY[1..200] OF REAL; // pre-allocated work buffer
END_VAR
CASE iState OF
0: // waiting for new request
IF bRequest THEN
iState := 1;
iChunk := 1;
END_IF;
1..200:
// process one chunk of the matrix per scan
MatrixChunk( a := aWork, i := iChunk, bResult := aWork[iChunk] );
iChunk := iChunk + 1;
IF iChunk > 200 THEN
iState := 255; // done
END_IF;
255: // finished, set output and clear request
bResultValid := TRUE;
bRequest := FALSE;
iState := 0;
END_CASE;
END_FUNCTION_BLOCK
Each scan now does 1/200th of the work, so a 200 ms matrix routine becomes 1 ms per scan and the watchdog is never threatened. The trade-off is that the result is only valid 200 scans later. If the process needs the result every 100 ms and the cycle is 10 ms, you can do 10 chunks per scan and still meet the deadline.
For long pipelines, the Siemens Open Development Kit and OSCAT library provide pre-built matrix primitives that can be scheduled in this way. OSCAT is community-vetted and ships with documented SCL sources; the Siemens-bundled matrix blocks are listed in the next section.
Resolution Strategy 3 — Use Siemens Matrix Function Blocks
Siemens ships a free library of mathematical function blocks for S7-300/400 that includes matrix operations, root finders, integrators, and statistical functions. The blocks are documented in "Operationen Bausteine" (entry ID 29851674) on the Siemens Industry Online Support portal. The matrix blocks implement the operations with fixed-size arrays and avoid the heap-allocation cost that MATLAB/Simulink-generated code carries on a real CPU.
| FB | Symbolic Name | Function | Typical Use |
|---|---|---|---|
| FB 1023 | MTRX_INV | Matrix inversion (LU decomposition) | Solve small linear systems |
| FB 1024 | MTRX_TRA | Matrix transpose | Coordinate transforms |
| FB 1025 | MTRX_MUL | Matrix multiplication | Kinematic chains |
| FB 1026 | MTRX_ADD | Matrix add / subtract | Bias correction |
| FB 1027 | MTRX_DET | Determinant | Singularity check |
These blocks are designed for cyclic execution and can be split across scans by passing partial results. When migrating from MATLAB/Simulink, replace the auto-generated M-files with these primitives; the MATLAB-generated code is not optimized for SCL and often produces nested loops that scale as N^3 or worse.
Resolution Strategy 4 — Move Heavy Math Off the PLC
If the matrix is needed for a value that the operator sees but the process does not control (a trend, a recipe preview, a quality KPI), move the math to the HMI or a separate industrial PC. Comfort panels, WinCC, and TIA Portal Unified HMI panels all support VBScript, C scripts, or the HMI-side SCL that can compute the result without burdening OB 1. The HMI can also be the master for a one-second or one-minute recompute cadence, in which case the PLC only needs to provide the raw inputs.
This is a legitimate architecture choice when:
- The result is consumed by a human, not a control loop.
- The result feeds a setpoint that updates at 1 Hz or slower.
- The PLC must reserve its cycle for I/O, drives, and safety.
Resolution Strategy 5 — Tune OB 35 and Other Cyclic Interrupts
Cyclic interrupt OBs (OB 30–OB 38 on S7-300/400) run at a fixed period and have their own implicit watchdog: if the OB exceeds 2× its configured period, the CPU goes to STOP. Common mistakes:
- Setting OB 35 to 2 ms but executing 5 ms of math inside it.
- Sharing the same FB instance between OB 1 and OB 35, causing two simultaneous executions to contend for the same resources.
- Forgetting to load OB 80; a single 4 ms blip in OB 35 will then stop the CPU.
Right-size OB 35 to the math. A 50 ms OB 35 with a 40 ms body is safe; a 2 ms OB 35 with the same body is not. If the math is heavy, push it to OB 1 with chunked execution and let the cyclic interrupt handle only the I/O scan.
Step-by-Step Refactor Procedure
-
Create a watchdog DB. Add a retain DB with a
bCycleFaultBOOL. Load OB 80 and set the flag in it. This is your safety net. - Measure current scan. Run the program online, read SFC 64 ticks at the start and end of OB 1, log the maximum for 1 hour. The maximum is the true budget you must beat.
- Profile the heavy FB. Use the TIA Portal Trace or an internal SFC 64 sample in the FB itself to record the FB's execution time. Confirm it is the dominant cost.
- Choose a strategy. If the FB does N units of work in one scan, decide: chunk across N scans, substitute a Siemens matrix FB, move the work to the HMI, or upgrade the CPU.
- Implement chunked execution. Add a state machine inside the FB. Keep the input contract unchanged so callers do not need to know the work is now asynchronous.
- Verify online. Download, go online, force a request, and watch the cycle time monitor. The maximum should drop well below the watchdog. Confirm the result is produced within the required latency.
- Document the new cycle budget. Update the HMI diagnostic page to show the actual scan, the configured maximum, and the OB 80 latch. Operators should see whether the system is running with margin.
Verification Checklist
| Check | Expected | How |
|---|---|---|
| OB 80 loaded | Yes | TIA Portal > Program blocks > System blocks |
| OB 80 latch flag set | Only when fault occurred | Watch in online monitor |
| Maximum cycle time online | < 50% of watchdog | Online & Diagnostics > Cycle Time |
| Diagnostic buffer | No new "Cycle time exceeded" events | Online & Diagnostics > Diagnostics Buffer |
| OB 35 period vs. execution | Period > 2× execution | Trace or SFC 64 sample inside OB 35 |
| Heavy FB measured time | Within its budget per scan | SFC 64 deltas at FB entry/exit |
| Result latency | Within process requirement | Functional test with worst-case input |
Troubleshooting Matrix
| Symptom | Likely Cause | First Action | Long-Term Fix |
|---|---|---|---|
| PLCSIM runs, real CPU stops | Workload above real CPU throughput | Check online cycle time | Chunk across scans or upgrade CPU |
| CPU stops on first download | Infinite loop in initialization | Comment out suspect FBs, re-download | Fix loop exit condition |
| Fault only at warm restart | Startup OB runs heavy work | Move init to OB 100 with chunks | Defer init to first scans of OB 1 |
| Fault intermittent, often at night | HMI poll or recipe load during off-shift | Check comms OB stats | Throttle HMI requests or use event-driven reads |
| Fault in OB 35, not OB 1 | Cyclic interrupt too fast for its workload | Increase OB 35 period | Refactor OB 35 to do less |
| Fault after firmware update | Library FB timing changed | Compare new vs. old scan times | Re-tune watchdog or refactor |
| Fault during online edit | Edit triggers recompile in mid-scan | Disable online edits in production | Use offline downloads only |
When to Upgrade Hardware
Sometimes the algorithm genuinely cannot be chunked (a control loop that needs the result every 5 ms) and the budget is too tight. In that case, a CPU upgrade is the correct answer. Comparison of typical S7-300/1200 bit-operation throughput:
| CPU | Bit op time (typical) | Floating-point op time (typical) | Notes |
|---|---|---|---|
| CPU 313C | ~100 ns | ~1.2 µs (REAL) | Compact, low headroom for math |
| CPU 315-2 PN/DP | ~50 ns | ~0.5 µs | Standard workhorse |
| CPU 317-2 PN/DP | ~25 ns | ~0.18 µs | High performance |
| CPU 319-3 PN/DP | ~10 ns | ~0.07 µs | Top of S7-300 line |
| CPU 1214C | ~80 ns | ~2.3 µs | Compact S7-1200 |
| CPU 1215C | ~70 ns | ~2.0 µs | Mid S7-1200 |
| CPU 1217C | ~40 ns | ~1.0 µs | High-end S7-1200 |
| CPU 1515-2 PN | ~30 ns | ~0.06 µs | S7-1500 entry |
For pure matrix math, a 319-3 or 1515-2 is roughly 10–20× faster than a 313C. If a refactor would compromise a hard real-time deadline, that upgrade pays for itself quickly in commissioning time and reduced stoppages.
Frequently Asked Questions
Why does my S7-300/400 CPU go to STOP with "cycle time exceeded" in the diagnostic buffer?
OB 1 ran longer than the configured maximum cycle monitoring time (default 150 ms on S7-300, configurable per CPU). If OB 80 is not loaded, the OS halts the CPU. Load OB 80 to recover, then refactor the user program so OB 1 fits inside the budget — see the Siemens Support entry 109975922 for the official behavior.
How do I run a heavy matrix calculation on a CPU that cannot finish it in one scan?
Split the matrix work into N chunks and execute one chunk per OB 1 scan using a state machine. For a 200-cell matrix, do 1–10 cells per scan so the cycle time stays under the watchdog. The result becomes valid N scans later, which is acceptable for non-control applications.
Does loading OB 80 stop the "cycle time exceeded" STOP fault?
No. OB 80 turns a single exceed into a recoverable event, but a double exceed (2× the configured maximum) is treated as a hard fault and the CPU still goes to STOP. OB 80 is a diagnostic and cushion, not a substitute for keeping the cycle inside its budget.
Why does the program run in PLCSIM but the real CPU stops?
PLCSIM executes user code on the workstation CPU at near-native speed, often 10–100× faster than a real S7-300. A routine that takes 5 ms in PLCSIM may take 80 ms on a CPU 313C, which trips the 150 ms watchdog under load. Measure the real CPU's scan with SFC 64 and refactor accordingly.
What is the safest way to set the maximum cycle monitoring time?
Set the watchdog to at least 2× the measured worst-case scan, and ideally 3–5× to absorb jitter. On S7-300 the maximum is 6000 ms; on S7-1200/1500 it is 60000 ms. A larger watchdog is not a fix for an algorithm that is too large — it only delays the inevitable stop.
Can I use cyclic interrupt OBs like OB 35 to offload the heavy math?
Yes, but each cyclic OB has its own period and its own 2× watchdog. If OB 35 is configured to 2 ms and the math takes 5 ms, OB 80 fires and a 4 ms overrun still stops the CPU. Match the OB 35 period to the actual workload and prefer OB 1 with chunked execution for anything larger than a few hundred microseconds.