S7-1500 OB80 Time Error: Finding the Failing FC in TIA Portal

David Krause15 min read
SiemensTIA PortalTroubleshooting
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

On a SIMATIC S7-1516-3 running TIA Portal, a programming error in an AWL (STL) function block produces a watch-dog overflow. The CPU goes to STOP, calls OB80 (Time Error OB), and writes an entry to the diagnostic buffer. The buffer entry confirms that OB1 is the active task, but it does not name the FC that contains the runaway jump. In STEP 7 V5.x the same scenario did report the offending block number; in TIA Portal the deep call-stack information is intentionally hidden behind the standard diagnostic view. This article documents how to retrieve that information anyway, using only the tools shipped with TIA Portal, and how to prevent the issue from recurring in AWL.

Typical conditions that reproduce the fault:

  • Code authored in AWL (Statement List) with conditional/unconditional jump instructions (JC, JCN, JU, JL, LOOP).
  • Label typo or label deleted during refactoring so the jump points at an earlier label in the same code network.
  • No call to OB80 in the project — the CPU uses the default behavior of going to STOP after a single time-error.
  • Cycle-time monitoring set to the project default (typically 150 ms for OB1) — long enough to flag a runaway loop but short enough to halt the CPU before manual intervention.
Safety impact: a CPU that goes to STOP without a configured restart strategy will drop all outputs. Verify that the controlled process tolerates the resulting coast-down before reproducing the fault on a live machine.

2. How OB80 Behaves on S7-1500

OB80 is the Time Error Organization Block. On an S7-1500 (firmware V1.x through V3.x as of this writing) it is invoked when the operating system detects one of the conditions listed below. The operating system populates the OB80 local-data area with an event class, a fault identifier, and the address of the OB that was running when the fault was raised.

OB80 fault identifiers (S7-1500)
FLT_ID (hex) Cause Typical user response
0x01 Cycle time of OB1 exceeded (watchdog trip) Check for runaway loops, infinite jumps, blocking communications
0x02 OB request still being executed when a new instance of the same OB is requested Check priority configuration, shorten the OB execution time
0x03 Time-of-day interrupt missed Verify clock synchronization and OB priority
0x05 Time-of-day interrupt time already passed when OB started Reschedule the alarm
0x07 Watchdog overflow while requesting an OB Reduce interrupt load
0x09 Interrupt loss due to excessive interrupt load Raise OB priority, reduce nesting
0x0A Time-of-day interrupt counter overflow Reduce alarm frequency
0x0C Synchronous cycle alarm overflow (Technology objects) Increase IPO cycle, reduce synchronous objects
0x0D Isochronous mode violation Check PROFINET IRT topology
0x10 Master/slave SYNC loss Check sync cable and master configuration

An infinite AWL jump in OB1 typically raises FLT_ID = 16#01 (cycle-time exceeded). The user sees the CPU stop and the diagnostic buffer reads:

Event 1 of 10:  Time error (OB 80) - Event ID 16#3501
  - OB:          OB1 (active)
  - Priority:    1  (cycle)
  - FLT_ID:      16#01 (maximum cycle time exceeded)
  - Cycle time:  6000 ms (configured 150 ms, exceeded by 5850 ms)
  - Time stamp:  2024-05-18 09:42:11.318

Nothing in the standard buffer entry tells the engineer which FC in OB1's call tree contains the bad jump. The information does exist in the CPU's runtime stack, but TIA Portal exposes it through separate views.

3. Why the Diagnostic Buffer Stops at OB1

STEP 7 V5.x and the older diagnostics toolset (ProAgent, S7-PDIAG) parsed the BS2000-style diagnostic buffer of the S7-300/400 firmware and showed the last active block in the event log. S7-1500 firmware stores an enriched event record in the same buffer, but the TIA Portal Diagnostics > Diagnostic buffer view intentionally suppresses the call stack of cyclic OBs to keep the entry concise.

The data is still there — it lives in the OB80 local-data area of the offending cyclic OB. The S7-1500 firmware writes the start information of the OB that was running when the fault was raised, plus the current statement within that OB. The catch is that the operating system only records the statement number at the OB1 level; once control has been passed to an FC, the runtime does not keep a per-statement back-trace for time errors. TIA Portal therefore relies on the engineer to walk the call hierarchy and bisect the code by hand.

4. Method 1 — Online > Call Hierarchy

This is the fastest path to the offending block when the CPU is in STOP.

  1. Bring the CPU back to RUN only if safe. If the process is hazardous, keep the CPU in STOP and use the Offline/Diff tools described later.
  2. Open the project in TIA Portal and select the PLC_1 device in the project tree.
  3. Go online: Online > Go online (Ctrl+K).
  4. From the menu, choose Online > Call hierarchy. TIA Portal opens a window listing the static call tree of OB1.
  5. Right-click OB1 in the tree and select Display in call hierarchy.
  6. Switch the bottom pane from Static calls to Dynamic calls. The dynamic view shows the last executed block when the CPU stopped, including the call depth at the time of the fault.
  7. Click the deepest highlighted FC — that is the block that contained the runaway jump. The editor opens it at the last executed network.
Availability: Dynamic call hierarchy requires the project to have been compiled with Generate block status enabled. In TIA Portal V17 and later this is on by default; for older V13/V14 projects, activate it under Project tree > PLC_1 > Properties > Compile > Generate block status, recompile, and download to the CPU before re-running.

5. Method 2 — Watch Tables and Block Status Counters

If the dynamic call hierarchy is unavailable (older firmware, project compiled without status), instrument the suspect FCs with a single self-resetting tag and watch it online.

  1. Create a global tag "DB_Diag"."FC_EntryCount" (DWORD) in a data block dedicated to diagnostics.
  2. In every FC that you suspect, insert the very first network:
          L "DB_Diag"."FC_EntryCount"  // load current count
          + 1                          // increment
          T "DB_Diag"."FC_EntryCount"  // store
          L DW#16#00FC0001             // magic ID: block + slot
          T "DB_Diag"."LastFC_Visited" // log identifier
    
  3. Force the CPU to RUN. The runaway loop will fill FC_EntryCount with the count from the FC that contains the infinite jump — every other FC either does not enter the loop, or its counter stops incrementing the moment the CPU halts.
  4. Open a Watch table, add "DB_Diag"."FC_EntryCount" and "DB_Diag"."LastFC_Visited", go online, and read the values immediately after the CPU drops to STOP.

The magic ID technique is useful when several FCs share the same code template. Replace the constant with the FC number (e.g. DW#16#00FC0017 for FC23) so the logged value tells you exactly which block was hot when the fault was raised.

6. Method 3 — Binary Search With Breakpoints

When the fault is reproducible and the cycle time is short, the most efficient technique is a classic divide-and-conquer breakpoint sweep. This works on S7-1500 CPUs with firmware V2.0 or later.

  1. Open the project, go online, and select Online > Set breakpoints for the active editor. The breakpoint toolbar appears.
  2. Set a breakpoint at the first executable network of OB1.
  3. Set the CPU to RUN-P. The CPU halts at the breakpoint with a yellow arrow on the next network.
  4. Step into the first FC call (F5 or Debug > Step Into). The editor opens that FC and halts at its first network.
  5. If the FC is the source of the runaway loop, the watchdog will fire while you are paused on a breakpoint — the CPU stops, the diagnostic buffer records OB80, and you know the active FC was the culprit.
  6. If the FC returns normally, continue to the next FC call. The first FC that does not return is the offender.
Caveat: Breakpoints in S7-1500 do not pause a runaway loop in real time; the loop continues to execute until the cycle-time watchdog trips. Always combine this method with a short configured maximum cycle (e.g. 200 ms) and a low OB80 priority so the diagnostic data is captured before the CPU stops.

7. Method 4 — Program Info > Cross References

If you have an offline project that matches the running program, the static cross-reference can help narrow the search before going online.

  1. In the project tree, right-click the PLC and choose Program info > Cross references.
  2. Filter by Jump labels and sort by Block number. The list shows every JU/JC/JL/LOOP instruction and the label it targets.
  3. Export the list to CSV (Export > CSV) and look for any jump where the target label is defined before the jump instruction in the same network — that is the structural signature of a runaway loop.

Example snippet that would be flagged by this search:

Network 5:  // FC12 — Mode selection
0001  L     "Mode"            // load current mode tag
0002  L     0                 // compare with 0
0003  <>I                    // not equal?
0004  JC    LBL_A             // <-- jumps BACKWARDS to LBL_A
0005  L     "Mode"            // this line never executes
0006  T     "Output"
LBL_A: NOP 0                  // label is *before* the jump

The cross-reference view does not prove the code is wrong, but it does narrow a 200-block project down to a handful of candidates in seconds.

8. Method 5 — Diagnostic Buffer Event Detail in TIA Portal

TIA Portal's diagnostic buffer shows one level of detail by default. Pressing F1 on the highlighted event, or clicking Details, reveals the Additional information pane that contains the OB80 start information in hexadecimal form.

Event 1 of 10:  Time error (OB 80) - Event ID 16#3501
  Additional information (hex):
    0000  01 01 12 0A 00 00 00 00  00 00 00 00 00 00 00 00
    0010  01 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00
    0020  12 0A 0A 19 09 2A 13 E2  00 00 00 00 00 00 00 00

Decoded, the same buffer decodes to:

Decoded OB80 start information (S7-1500)
Byte offset Field Value Meaning
0..1 OB80_EV_CLASS 16#01 01 OB80 active, incoming
2..3 OB80_FLT_ID 16#12 0A 0x01 = cycle-time exceeded
4..5 OB80_PRIORITY 16#00 00 Priority 1 (cyclic)
6..7 OB80_OB_NUMBER 16#00 00 OB1 (index = 1)
8..11 OB80_RESERVED_1 16#00 00 00 00 Reserved on S7-1500
12..15 OB80_ERROR_INFO 16#00 00 00 00 No additional error info
16..17 OB80_ERR_EV_CLASS 16#01 00 Event class of the triggering OB
18..19 OB80_ERR_EV_NUM 16#00 00 Triggering event number
20..21 OB80_OB_PRIORITY 16#00 00 Triggering OB priority (1)
22..23 OB80_OB_NUM 16#00 00 Triggering OB (1 = OB1)
24..31 OB80_DATE_TIME 16#12 0A 0A 19 09 2A 13 E2 Date/time BCD-encoded

The OB80_OB_NUM field repeats the OB that raised the fault (OB1). It does not include the FC number. This is by design — the runtime does not preserve the FC call depth in the OB80 start information, only the OB that was active when the watchdog tripped.

9. AWL Jump Pitfalls Specific to S7-1500

The S7-1500 instruction set is a superset of the S7-300/400 AWL. Existing AWL code that ran on an S7-315/S7-317 may behave differently on an S7-1500 for two reasons:

  1. Symbolic addressing is mandatory for some instructions on S7-1500. Mixing fully-qualified symbolic operands with absolute jumps can produce label-resolution surprises during incremental compiles.
  2. Compiler optimization in TIA Portal is more aggressive than STEP 7 V5.5. A label that was at network N in V5.5 may shift to network N-1 after a recompile, so a backward jump that was one network in the source may now be 50 instructions in the generated code, dramatically shortening the cycle time and triggering the watchdog.

Common AWL patterns that produce runaway loops on S7-1500:

AWL jump patterns that risk infinite loops on S7-1500
Pattern Why it loops Safer alternative
JC LBL_A with LBL_A: in the same network and before the jump Branch back to the comparator, no progress Use DO ... WHILE in SCL or a state variable
JU LBL_A inside a network whose only exit depends on an input that the network does not read Unconditional branch with no I/O update Insert a BE or BEC branch and verify the ladder logic
LOOP LBL_A with the accumulator loaded from a tag that is never decremented Loop counter never reaches zero Use a FOR loop in SCL with explicit bounds
JL LBL_0 with a jump list that re-enters the same network for several selector values Distribution table points back to the dispatcher Use a CASE statement in SCL

10. Why SCL Is Less Prone to This Class of Bug

SCL compiles AWL-style under the hood, but the language is structured: every WHILE, REPEAT, and FOR loop has a single, unambiguous entry point. There is no equivalent of a free-standing JC jumping into the middle of a network. The TIA Portal SCL editor also performs a control-flow check during compile time, so a label-typo in AWL that compiles silently is a hard compile error in SCL.

For the rare case where a free-form branch is necessary, SCL exposes a GOTO statement that is restricted to local labels within the same block. SCL also supports a Watchdog property in the CPU properties (under PLC > Properties > Cycle), so the maximum cycle time can be tuned per project without changing OB80 behavior.

For mixed-language projects, TIA Portal V14 SP1 and later allow LAD, FBD, and SCL networks inside the same block (a feature the S7-300/400 never had). Engineers who want the readability of LAD for I/O logic and the control flow of SCL for sequencing can place a single SCL region inside a LAD block, or vice versa, without breaking the offline/online synchronization.

11. Recovery Procedure

Use the following checklist the first time an S7-1500 CPU drops to STOP with OB80 on AWL code.

  1. Capture the diagnostic buffer. In TIA Portal, go online, open Diagnostics > Diagnostic buffer, and export it (right-click > Export) before doing anything else.
  2. Note the FLT_ID. Confirm that it is 16#01 (cycle-time exceeded). If it is 0x02 or 0x07, the issue is OB nesting, not a runaway loop.
  3. Use the call hierarchy (Section 4) while the CPU is still in STOP. The dynamic call view shows the deepest FC that was running.
  4. Open the suspect FC and read it in the AWL editor view, not the LAD/FBD view, so the jump targets and label positions match the compiled code.
  5. Verify the label position. In the AWL view, the Network comment field shows the network number; if the label is at a lower network number than the JC/JU, the loop is structural.
  6. Apply the fix — either move the label after the jump, replace the AWL with a structured SCL IF/WHILE, or insert a BE branch.
  7. Recompile and download with Generate block status enabled.
  8. Run the test cycle for at least ten full process iterations with the maximum cycle time doubled, then return the cycle time to the production value.

12. Verification

After the fix, verify the recovery in three independent ways:

  • Diagnostic buffer remains clean. Run the process for a full shift; the buffer must not contain any additional OB80 entries. Filter the buffer by event ID 16#35xx; the count must be zero.
  • Cycle time stays below the watchdog. Open a watch table with the OB1_PREV_CYC_TIME and OB1_MAX_CYC_TIME tags from the CPU's system clock (under System > Clock > Cycle). The PREV value must remain below 80 % of the configured maximum during the worst-case process cycle.
  • Program status in TIA Portal shows the FC reaching its BE instruction under all operating conditions. Step through every branch and confirm that no network can re-enter itself.

13. Long-Term Prevention

For projects that will be maintained for years, three practices keep this class of bug out of the field:

  1. Enforce SCL for new code via the project setting Programming language > Default for new blocks > SCL. Existing AWL blocks are preserved but new logic grows in SCL.
  2. Add a software watchdog in OB1: increment a tag every cycle and reset it to zero in OB35 (a 100 ms cyclic interrupt). If OB35 is starved by the runaway loop, the tag overflows and the application can take a safe-state action before the CPU watchdog trips.
  3. Use static analysis. The TIA Portal Program info > Consistency check reports blocks that contain unreachable code. Run it on every build as part of the CI pipeline.
Vendor documentation: refer to the SIMATIC S7-1500 Function Manual, section on organization blocks, and the STEP 7 Professional V18 Programming and Operating Manual for the full local-data layout of OB80 on the S7-1500. For TIA Portal call-hierarchy options, see the Online & Diagnostics Manual.

Why does TIA Portal show OB1 as the offending block in OB80 when the bug is in an FC?

OB80 is triggered by the operating system when the cycle watchdog fires. The start information written by the firmware records the OB that was active (OB1) plus the statement number inside that OB. It does not record the FC call depth. Use the dynamic call hierarchy (Online > Call hierarchy) or a watch table on a self-incrementing tag to identify the FC.

How do I enable dynamic call hierarchy in TIA Portal?

Open the PLC device properties, go to Compile, enable Generate block status, recompile the project, and download to the CPU. The dynamic call hierarchy view then shows the last executed block on STOP.

Can I jump backward in AWL on S7-1500 without tripping OB80?

Yes — a backward jump is legal and is how LOOP is implemented. The watchdog trips only when the resulting loop never terminates within the configured maximum cycle time. For a structural loop, the cycle time is effectively infinite and OB80 always fires.

Is there a STEP 7 V5.x equivalent of the TIA Portal watch table approach?

Yes. The same pattern works in V5.x using VAT (Variable Table) and a self-incrementing tag in each suspect FC. The benefit is identical: the value frozen in the VAT when the CPU drops to STOP points at the FC that was hot.

Does SCL protect against infinite loops on S7-1500?

SCL prevents accidental runaway jumps by enforcing a single entry and exit point for every block. The same WHILE TRUE written in SCL still loops, but the language makes the intent explicit and the TIA Portal compiler flags dead code after a RETURN or EXIT. For mission-critical loops, pair SCL with a software watchdog in OB35.

Back to blog