Resolving S7-400 OB35 Cyclic Interrupt Overrun with OB80

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

Resolving S7-400 OB35 Cyclic Interrupt Overrun with OB80 and CPU_RT

When a cyclic interrupt organization block (OB) on a SIMATIC S7-400 executes longer than its configured interrupt period, the CPU does not silently re-trigger the same OB. Instead, it detects a time-error condition, fires OB80, and either logs the fault, runs user recovery code, or—worst case—goes to STOP. This article gives a complete field reference for engineers running PCS 7 on a CPU 417-4 H (and the broader S7-400 / S7-400H family) where OB35 is the standard 500 ms cyclic interrupt. It explains the priority model that prevents OB35 from re-interrupting itself, the start-information buffering that keeps downstream timers consistent, and the role of CPU_RT (FB 128) and SFC 78 in a current PCS 7 image.

1. Problem Statement: OB35 Takes Longer Than Its 500 ms Period

Consider a realistic scenario. OB35 is configured with a 500 ms phase offset. Normal scan time of the OB35 body is 100 ms, well within budget. Once per hour, however, a peak workload (for example, a batch of message-frame processing, an FB-driven archive flush, or a remote I/O update burst) pushes the OB35 execution time to 600 ms.

The questions an engineer asks are:

  1. Does the new 500 ms OB35 trigger preempt the in-flight 600 ms OB35?
  2. Is the next OB35 trigger dropped, queued, or executed after the current one finishes?
  3. Does the cycle effectively stretch to 600 ms, or is the OB3x start information preserved at 500 ms?
  4. Does the CPU STOP, raise OB80, or remain in RUN?

The short answer, consistent with the Siemens SIMATIC S7 documentation on cyclic interrupt OBs:

  • OB35 cannot interrupt itself because the priority is identical.
  • A time error is reported to OB80.
  • If OB80 is not present in the CPU, the CPU goes to STOP.
  • If OB80 is present, the new OB35 start information is buffered, the in-flight OB35 finishes, OB80 runs, then the buffered OB35 executes immediately afterward.
  • TEMPs such as OB35_DATE_TIME continue to reflect the original 500 ms trigger instant, not the actual run-time end.

PCS 7 shields you from manual OB80 handling by installing CPU_RT (FB 128), which is the right place to look when you need to see exactly what the runtime is doing about overrun events.

2. OB Priority and the S7-400 Execution Model

Every organization block on a SIMATIC S7-400 carries a fixed or configurable priority class. Cyclic interrupt OBs (OB30–OB38) carry priorities 7 to 15 by default. OB1 (the main cyclic program) runs at priority 1, OB35 at priority 12, and OB80 (time error) at priority 26.

OB Type Default priority Trigger
OB1 Main cyclic 1 Free cycle (scan completes, restart)
OB10 Time-of-day 2 Calendar / time-of-day
OB30 Cyclic interrupt 7 Configurable period (minimum ~10 ms on S7-400)
OB35 Cyclic interrupt 12 500 ms typical in PCS 7
OB38 Cyclic interrupt 15 Configurable period
OB40 Hardware interrupt 16–23 Digital/analog input event
OB80 Time error 26 OB overrun, cycle time exceeded
OB82 Diagnostic interrupt 26 Module diagnostic event
OB100 Warm restart 27 Restart after power-up
OB101 Hot restart 27 Hot restart (S7-400 only)
OB102 Cold restart 27 Cold restart (S7-400 only)

The CPU dispatches OBs in priority order. A higher-priority OB that becomes due always preempts a lower-priority OB at an instruction boundary. A same-priority OB is never allowed to preempt the running instance of itself; that is the root reason the overrun must be reported through OB80 rather than silently stacked.

Same-priority rule: OB35 cannot interrupt OB35. Even though two distinct trigger events arrive 500 ms apart, the second one cannot preempt the first; it can only be buffered or rejected, and the rejection path is what generates OB80.

3. OB35 Cyclic Interrupt Mechanics on the S7-400

OB35 is the de-facto PCS 7 timebase. The standard PCS 7 master library configures OB35 with a 500 ms period and a 0 ms phase offset. The phase offset lets the engineer stagger multiple cyclic interrupt OBs so they do not all collide with OB1 at the same instant.

Configuration is performed in STEP 7 (classic) under CPU Properties → Cyclic Interrupts:

Parameter PCS 7 default Range on S7-400 Notes
OB OB35 OB30–OB38 9 distinct cyclic interrupt OBs in S7-400
Period 500 ms 10 ms – 60 000 ms (1 ms grid) Hardware-tick based
Phase offset 0 ms 0 – period Distributes multiple OBs across the cycle
Priority 12 2 (OB10) – 24 Editable in HW Config; PCS 7 usually leaves default

When the cyclic tick fires, the operating system pushes the OB35 start information onto the local TEMP stack. The start information is an OB35_DATE_TIME DATE_AND_TIME structure, plus the OB35-specific event class. The OB body runs to completion at the priority-12 class, and only higher-priority OBs (for example, OB40 hardware interrupts or OB80 if triggered) can preempt it.

According to the Siemens documentation on cyclic interrupt OBs, up to 20 cyclic interrupt events can be configured in the CPU event table, each tied to one OB. The buffer that holds pending start information is finite; the exact depth depends on CPU firmware but the conceptual limit is the count of events per OB scheduled before completion.

4. Root Cause: Why a 600 ms OB35 Generates a Time Error

The S7-400 monitors a hardware watchdog for every active OB. If the OB is still executing when its next scheduled tick arrives, the operating system classifies the situation as a time error (OB80 Zeitfehler). The fault is logical, not mechanical—the operating system could theoretically have queued the new event, but the Siemens design uses the overrun as a sign that the user program is exceeding its real-time budget and needs explicit acknowledgment.

The fault path is:

  1. OB35 begins (trigger at T0, start info stamped T0).
  2. OB35 still in progress at T0 + 500 ms when the next OB35 tick arrives.
  3. Operating system cannot preempt same-priority OB, so the new event is treated as a time error.
  4. OB80 is requested. If OB80 is not loaded, the CPU transitions to STOP with diagnostic buffer entry "Time error (OB not loaded)" and diagnostic LED SF on.
  5. If OB80 is loaded, OB80 fires; the pending OB35 start information is buffered for immediate execution after the in-flight OB35 finishes.

The buffered OB35 runs with the original T0+500 ms start info, so any code that derives timing from OB35_DATE_TIME sees a perfect 500 ms cadence even though wall-clock execution strayed to 600 ms or beyond.

5. OB80 Time-Error Organization Block

OB80 is the central handler for time errors. Its 20-byte local TEMP OB80_FLT_ID identifies the exact time-error subtype. The relevant codes are:

FLT_ID (hex) Meaning Typical cause
0x0A Cycle time of OB exceeded OB1 / OB35 ran longer than the configured maximum cycle time
0x0B OB still active when new trigger fires The OB35 600 ms scenario described above
0x0C Global interrupt (date/time) lost Time-of-day OB overrun
0x0D Stopwatch / counter event lost Overrun in a time-of-day OB after first execution

Other useful TEMPs in OB80:

  • OB80_ERROR_INFO – supplementary fault code (for 0x0B this includes the OB number that overran).
  • OB80_ERR_EV_CLASS / OB80_ERR_EV_NUM – event class and event number of the event that was lost.
  • OB80_OB_PRIOR – priority of the OB that caused the error.
  • OB80_DATE_TIME – DATE_AND_TIME of the time error occurrence.

If OB80 is present, the CPU stays in RUN; the user code in OB80 can read OB80_FLT_ID to decide whether to log, count, or take corrective action. PCS 7's CPU_RT (FB 128) does exactly this and is wired to the diagnostic buffer and the operator message system.

Stop without OB80: A CPU 417-4 H with no OB80 in the active S7 program will transition to STOP the first time OB35 overruns. The diagnostic buffer will show "OB80 Zeitfehler (OB nicht geladen)" or "STOP durch Zeitfehler OB (OB nicht geladen)". Always load OB80 in any PCS 7 project—CPU_RT already does this, but custom or stripped-down images can leave the slot empty.

6. Start Information Buffering Behavior

When OB80 is present, the new OB35 trigger is not lost. It is placed in a per-OB start-information queue managed by the operating system. The queue depth is implementation-defined but the practical limit is small—single-digit depth is typical for cyclic OBs.

Once the in-flight OB35 finishes, the CPU executes OB80 (priority 26, preempts any OB < 26) and then immediately drains the OB35 queue by re-entering OB35 once for each buffered start info. Each re-entry carries the original T0, T0+500 ms, T0+1000 ms, ... start information, so a one-hour spike that extends OB35 to 1100 ms can produce two buffered calls executed back-to-back at full priority-12 dispatch.

This explains the observed behavior in the field:

  • "The cycle stretched to 600 ms." Wall-clock yes, but the next OB35 also ran, so effective OB35 throughput over the hour is preserved.
  • "OB3x_DATE_TIME always reads 500 ms apart." Correct. The start information is the trigger instant, not the end instant. Time-difference math using this variable is immune to overrun drift.
  • "I see a tight double-execution spike on the scope trace." The buffered calls run immediately after the overrun. If your OB35 touches fast outputs, the burst can show up as a paired pulse train on a logic analyzer.

7. PCS 7 CPU_RT (FB 128) and SFC 78 Handling

PCS 7 since V8.x installs CPU_RT (FB 128) and calls it from OB80. FB 128 exposes a comprehensive fault-handling interface and also provides access to SFC 78 OB_RT, a system function that changes the run-time of an OB at runtime (used for thermal and lifecycle management of OB35).

Typical wiring in a PCS 7 AS station:

  • OB1 contains the cyclic PCS 7 driver and a call to CFC_OB35 for the 500 ms layer.
  • OB35 contains the high-priority PCS 7 blocks (MOD, CH_U, CTRL_PID, ...).
  • OB80 contains a single call to CPU_RT (FB 128). The instance DB is DB 128 by default.
  • OB82, OB83, OB85, OB86, OB87, OB121, OB122 all contain a call to CPU_RT as well, so that diagnostic interrupts, pull/plug events, rack faults, and programming errors are uniformly captured.

FB 128's input OB_NR (INT) tells CPU_RT which OB called it. On a time error from OB35, the block raises an operator message, logs the count to the instance DB, and can be configured to call SFC 78 to raise OB35's run-time budget if the overrun pattern is sustained.

You can read the cumulative count of OB80 invocations from the CPU_RT instance DB or via the HMI faceplate. This is the cleanest way to detect a chronic 600 ms OB35 problem in a running plant without taking the system offline.

8. OB Cycle Time Configuration and Tuning

Tuning a 500 ms OB35 with a 100 ms typical and 600 ms peak requires looking at three knobs:

  1. Extend the period. If the 100 ms typical is comfortable but the peak is structural, consider OB35 = 1000 ms. PCS 7 will still meet its soft-real-time targets because the underlying process time constants (level, temperature, flow) are usually > 5 s.
  2. Distribute the load. Move the spike-causing work to OB38 (configurable period) or to OB1's background, or to a separate OB30 that runs at a lower rate. PCS 7's CFC compiler supports multiple time slices; you can pin each chart to its own OB and phase.
  3. Reduce the work per cycle. Profile the OB35 body. The 600 ms peak is rarely the same code that takes 100 ms typical; it is usually a conditional block (alarm, archive flush, batch transition) that can be split into a slower OB or moved to OB1.

PCS 7 also supports the OB3x_OFFSET parameter. By shifting OB35 to a non-zero phase offset (for example, 100 ms after OB1 starts), you prevent OB35 and OB1 from competing for the same dispatch slice, which reduces instantaneous jitter and headroom pressure.

Watchdog limit: The S7-400 enforces a maximum OB cycle time independent of the period. The default is 1500 ms for OB1 and 5000 ms for OB35 on a CPU 417. If your OB35 ever hits that, OB80 with OB80_FLT_ID = 0x0A fires regardless of OB35 period.

9. Watchdog Timer and Short-Period OB Pitfalls

Each OB has an associated maximum cycle time. For OB35, the default is 5000 ms in the CPU properties. If you lower the period to 10 ms (the minimum on a CPU 417-4 H), the monitor code in the operating system itself becomes a measurable part of the cycle. Field experience shows that running OB35 at 10 ms while online-monitored from STEP 7 can push the cycle past 10 ms, triggering OB80 with FLT_ID = 0x0A and a STOP transition.

Mitigations:

  • Raise the maximum cycle time in HW Config → CPU Properties → Cycle/Clock Memory.
  • Remove online monitors from OB35 during commissioning of fast loops.
  • Do not call SFC 17 / SFC 18 (alarm_S / alarm_SQ) inside a fast cyclic OB with deep nesting; the alarm-job queue is part of the same dispatch budget.

10. Verification and Diagnostics

After applying a fix, verify the following on the running AS:

  1. Diagnostic buffer: Online → CPU → Diagnostic Buffer. Look for time-error entries with EV_CLASS = "OB not loaded" or "OB80 Zeitfehler". Confirm no new entries appear after the fix.
  2. CPU_RT counter: Open the CPU_RT instance DB and read the cumulative time-error count. Trend it on the PCS 7 OS. The count should plateau.
  3. Cycle time histogram: STEP 7 → PLC → Module Information → Performance Data. The "Cycle time OB35 (current/min/max)" field gives you the live trace. Max should drop back to a stable value < period.
  4. OS scope on a 500 ms heartbeat: Add a flip-flop in OB35 that toggles a process tag once per call. Plot it on the OS trend. The cadence should be 500 ms ± tolerance. Buffered overrun calls appear as a brief < 500 ms double pulse.
  5. Operator message suppression: CPU_RT raises a message on every OB80. Confirm the message class is configured to either alarm or warning depending on your philosophy.

11. Field Tips and Best Practices

  • Always keep OB80 loaded. PCS 7's CPU_RT does this. For a non-PCS 7 STEP 7 program, drop a single-instance OB80 with at least a "beep" or diagnostic-buffer write—never leave the slot empty.
  • Read OB3x_DATE_TIME, not the wall clock. All user timing in OB35 should derive from this TEMP if you want a stable 500 ms grid. Comparing against the S7 system clock will show overrun drift.
  • Avoid call-by-reference deep into OB35. Indirect FC/FB calls inside OB35 are the most common source of the 600 ms peak. Inline critical hot paths in CFC charts that compile to single scans.
  • Prefer multiple OBs to a single fast one. PCS 7 supports the time-slice model precisely to avoid this scenario. OB30 = 100 ms, OB35 = 500 ms, OB38 = 1000 ms covers the vast majority of process-control sample times.
  • CPU_RT is the supported seam. Custom OB80 logic is fine, but in a PCS 7 plant any deviation from FB 128 must be documented and version-controlled; it affects every AS in the project.

12. Quick Reference: OB35 Overrun Decision Matrix

Condition CPU state Next OB35 start info User action
OB35 finishes before next tick RUN, no event Used immediately at next tick None
OB35 overruns, OB80 loaded, queue empty RUN, OB80 fires Buffered, executed after current OB35 Log via CPU_RT, retune
OB35 overruns, OB80 loaded, queue has capacity RUN, OB80 fires All missed ticks buffered, executed back-to-back Log, retune, or extend period
OB35 overruns, OB80 loaded, queue full RUN, OB80 fires (loss event) Newest start info discarded Critical—redesign the cycle
OB35 overruns, OB80 not loaded STOP, diagnostic buffer entry Lost Load OB80, retune, restart
OB35 overruns maximum cycle time STOP, OB80 (FLT_ID 0x0A) Lost Raise max cycle time, retune

FAQ

Does OB35 interrupt itself if the cycle is overrun?

No. Same-priority OBs cannot preempt each other. A 600 ms execution of OB35 with a 500 ms period triggers OB80 instead; the new OB35 start information is buffered for execution after the current OB35 finishes. See the Siemens cyclic interrupt OB documentation for the priority model.

What happens if OB80 is not loaded in the S7-400 program?

The CPU transitions to STOP the first time OB35 overruns. The diagnostic buffer records a "Zeitfehler OB (OB nicht geladen)" entry. PCS 7's CPU_RT (FB 128) is the standard fix; for non-PCS 7 programs, drop a minimal OB80 into the S7 project and write the fault info to the diagnostic buffer.

Will OB35_DATE_TIME show the overrun or the trigger time?

It shows the trigger time. A buffered OB35 carries the original T0 + 500 ms instant in its start info, so user code that measures delta time between OB35 starts using this TEMP will always read exactly 500 ms, even when wall-clock execution was 600 ms or more.

How is the OB35 buffered-call queue sized?

Siemens does not publish a fixed depth for the cyclic interrupt start-info buffer; the depth is implementation-defined per CPU. In practice, two or three missed calls can typically be buffered before the operating system declares an event loss in OB80. Sustained overruns must be eliminated by retuning the cycle, not by relying on the buffer.

Can I run OB35 at 10 ms on a CPU 417-4 H without stopping?

Possible, but the operating-system monitor plus any online monitor from STEP 7 often pushes the cycle over 10 ms, firing OB80 with FLT_ID 0x0A and stopping the CPU. Raise the maximum cycle time in HW Config and remove online monitoring from OB35 during commissioning of fast loops. PCS 7's standard 500 ms OB35 is the recommended baseline for process control.

Back to blog