S7-400H Startup OB Inhibit Logic: OB1/OB35 and SFC90

David Krause13 min read
S7-400SiemensTechnical Reference
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

Problem Statement and Operating Context

The S7-400H redundant PLC executes a defined startup sequence on POWER ON, restart, and cold restart. The user question of record is whether OB1 and OB35 (the cyclic and time-of-day interrupt OBs) can be inhibited at user-program level while the H system is still in startup, link-up, or self-test. The short answer is that the operating system already does this for the user: a hand-written inhibit is usually unnecessary, and the cases where it is genuinely needed (large-scale commissioning, warm-restart after a master changeover, or a defective user program that crashes OB1 in the first scan) are handled by structured patterns rather than a global disable.

Throughout this article, the term startup is used in the S7-400H sense defined in the SIMATIC S7-400H Programmable Controller manual (Chapter 8, Startup and Operating Modes), and not in the generic sense of "booting". The H-specific phases are POWER ON, self-test, restart (OB100) or cold restart (OB102), RUN (Single mode), link-up, update, and RUN (Redundant mode).

S7-400H Startup Phases and OB Execution

The S7-400H operating system sequences the OBs as follows during a controlled startup:

  1. POWER ON - Hardware reset; both CPUs initialize memory, copy from load memory to work memory, and clear process-image output tables (PIQ) to the configured substitute value.
  2. Self-test - Hardware functional test of the CPU, RAM, and the redundancy coupling. The duration of this test is the long pole in the startup window, especially when the CPU was powered up without backup batteries.
  3. Restart (warm restart) - OB100 - Called once on the master CPU.
  4. Cold restart - OB102 - Called on the master only when the operating-mode selector is in MRES or when no valid configuration is detected at POWER ON.
  5. RUN, single mode - The master enters OB1 cyclic processing; the standby remains in standby or in OB101 until the redundant link is healthy.
  6. Link-up - Both CPUs synchronize their data, exchange role information, and verify the redundancy link.
  7. Update - Both CPUs copy dynamic state from master to standby; the standby becomes a hot backup.
  8. RUN, redundant mode - Both CPUs execute OB1 in parallel; OB35 fires on the configured interrupt cycle.
Key point: OB1 and OB35 are not called during phases 1-4. They are not even scheduled. Any user logic that lives only in OB1 and OB35 is therefore already inhibited at the operating-system level. The user's request is satisfied without writing a single line of inhibit code.

During link-up and update, OB1 and OB35 are similarly held. Per the S7-400H manual, with the exception of special OBs (OB80-OB87 error OBs, OB121/122 programming-error OBs, OB100-OB102 startup OBs), the cyclic program is suspended until both CPUs have completed link-up and update. This behavior is built into the firmware and is not user-configurable on a per-OB basis.

Why Inhibit Logic in User Program During Startup Is Usually Wrong

Treating startup as if it were a runtime phase to be controlled from inside OB1 introduces several problems:

  • OB1 is not running, so any inhibit flag set inside OB1 cannot be evaluated there. The first scan of OB1 only begins after link-up + update complete.
  • Output periphery is replaced with substitute values during the entire startup window. There is no need to "freeze" the program because the program is not running.
  • OB100 already has a one-shot semantic. A flag or bit set in OB100 and cleared in OB1's first scan is the standard Siemens pattern for "first run after restart".
  • OB35 is a cyclic interrupt. In the time between OB100 completing and OB35's first scheduled fire, the OB35 counter has not advanced and the OB is not queued. In other words, no inhibit is needed; the OB simply does not run.

Patterns for Conditional OB Execution When You Really Do Need to Skip

There are legitimate scenarios where a one-shot inhibit is useful. The classic case is a recipe-driven process where the previous cycle's state variables must not be evaluated until the H system has been in redundant RUN for a configurable grace period (e.g., 60 s). Another is a controlled sequential start-up of an entire plant section, where individual stations must hold outputs at zero until a global "ready" flag is raised by the master CPU's first scan in redundant mode.

The pattern published in Siemens application notes uses a timer in OB100 to mask OB1 and OB35 execution for a fixed window. The code below is the canonical form, applicable to STEP 7 V5.x STL and to SCL with the equivalent assignment.

Restart OB (OB100)

// OB100 - Restart (warm restart)
// Purpose: Arm the inhibit timer that masks OB1/OB35
//          processing for S5T#1M after the CPU enters RUN.

      CLR                       // Clear RLO
      SE   T 0                  // Reset T0; clear residual time
      NOP 0

      SET                       // Set RLO = 1
      L   S5T#1M                // 1 minute inhibit window
      SE   T 0                  // Start T0 as extended pulse

      NOP 0

For an S7-400H system, OB100 is executed on the master CPU. If a redundant update is required for T0 to survive the standby's takeover, declare T0 in the shared data block of the H-system synchronization region, or use a flag from a retentive area flagged with the H-compatible attribute. The default behavior is that T0 is per-CPU; the new master will start a fresh inhibit window after a role switch, which is usually the desired behavior.

Cyclic Interrupt OB (OB35)

// OB35 - Cyclic interrupt (default 100 ms in S7-400H)
// Purpose: Bypass the entire OB body while T0 is running.

      A   T 0                   // Query T0
      BEC                       // Block End Conditional:
                               //  - if RLO = 1 (T0 active), exit
                               //  - if RLO = 0, fall through

// ---- User program below this line is only executed
//      once T0 has timed out. ----

      L   MW 100
      L   1
      +I
      T   MW 100

Why BEC, Not SPAE or JU

BEC (Block End Conditional) is the only STL instruction that does not set BR, does not write to the DB register, and does not invalidate the MCR stack. The instructions SPAE (unconditional block end) and JU (jump unconditional) either skip the BE without cleaning the DB stack or cause the MCR to fall through incorrectly. Use BEC for early-exit patterns in time-of-day or cyclic interrupt OBs.

SFC90 (H_CTRL) and Self-Test Control

SFC90 "H_CTRL" is the only system function in the S7-300/400 family that allows user influence over the H-system self-test. It is documented in the System Software for S7-300/400 System and Standard Functions Volume 1 and Volume 2 reference manual.

Parameter Type Description
REQ BOOL 1 = start test sequence / 0 = no action
MODE BYTE 1 = start link-up, 2 = start update, 4 = stop link-up, 5 = stop update, 8 = stop self-test, 9 = start self-test, 12 = stop partial self-test, 13 = start partial self-test
FT_IDENT WORD Identifier of partial self-test; defined in CPU-specific documentation
BUSY BOOL 1 = SFC90 is active, do not call again
ERROR BOOL 1 = error occurred
STATUS WORD Detailed error code; see manual

Calling SFC90 with MODE = 8 ("stop self-test") returns W#16#8090 if the request is rejected because a self-test slice is already in progress. In practice, partial self-test slices run in a 100 ms background window and have no effect on OB1/OB35 execution latency. Disabling them is not recommended in production; it is useful only on bench test or for HALT-on-error diagnostics.

Warning: SFC90's MODE = 9 (start full self-test) can block all cyclic OBs for the duration of the test, which can run for several minutes when the CPU was powered up without backup batteries. If you trigger MODE = 9 from OB1, you can lock the CPU out of OB1 for the rest of the test and never return. Call SFC90 only from OB100, OB101, or from a one-shot FC that runs in OB1's first scan.

Link-Up and Update Mode Behavior

During link-up, the standby CPU requests all process image inputs (PII) and the contents of the data blocks marked as "H-sync relevant" from the master. The duration of link-up scales with the size of the synchronized data area. A 32 KB H-sync area can take 2-4 s on an S7-417H; a 256 KB area can take 15-25 s. During this window, OB1 is held on both CPUs.

During update, the standby copies the master's dynamic state (S7-timers, counters that are not flagged as non-H, bit memory flagged as H-sync) and verifies the role assignment. The user program remains held. After update completes, OB1 begins executing on both CPUs within the same cycle. OB35's first interrupt is then scheduled normally; it will fire on the next 100 ms boundary, not retroactively.

Disabling Cyclic Interrupts Explicitly

If the application requires OB35 to be disabled for a defined period (for example, to give a downstream servo drive time to come up), SFC39 "DIS_IRT" (Disable Interrupt) and SFC40 "EN_IRT" (Enable Interrupt) are the documented mechanism. They are part of the S7-300/400 system software and are described in System Software for S7-300/400 System and Standard Functions Volume 2.

// Disable OB35 (cyclic interrupt 10) globally
      CALL "DIS_IRT"
        MODE    := 0             // 0 = disable all cyclic interrupts
        OB_NR   := 10            // 10 = OB35
        RET_VAL := MW 200        // Return value (0 = OK,
                                 // 80A1 = invalid OB number)
// Re-enable OB35
      CALL "EN_IRT"
        MODE    := 0
        OB_NR   := 10
        RET_VAL := MW 202

Call these from OB100 to arm the disable, and from a delayed FC scheduled by SFC32 (SRT_DINT) when the enable should be issued. MODE = 1 affects only the specified OB; MODE = 0 affects the entire OB class. For OB35 specifically, MODE = 0 is safe because no other OB shares its priority class (default priority 12) on the S7-400H.

Configuration in STEP 7 / TIA Portal

On the S7-1500H and S7-400H, the "Startup after POWER ON" property of the CPU is configurable. According to the TIA Portal manual collection for the S7-1200, this setting lives in the device configuration of the CPU, under Properties → Startup. The supported options on the S7-1200 are warm restart (OB100) and cold restart (OB102); the H-specific link-up option is not exposed on the S7-1200. The same configuration path applies to the S7-400H and S7-1500H; the H platforms add a "Startup only after complete link-up" checkbox under the redundancy group.

  • Warm restart - Run OB100 on POWER ON; data blocks marked as retentive retain their values.
  • Cold restart - Run OB102 on POWER ON; all work memory is initialized from load memory.

On the S7-400H, the additional "Startup only after complete link-up" option is exposed. When checked, the master CPU does not call OB1 until the standby has finished its self-test. This is the most conservative setting and is recommended for high-integrity process plants.

Verification Procedure

To verify the inhibit pattern, perform the following steps on a single S7-417H rack (or the H-station if available):

  1. Load the program with the OB100/OB35 code shown above.
  2. Connect the programming device to CPU0 (master) via PROFIBUS or Ethernet.
  3. Open "Monitor / Modify" (STEP 7 V5.x) or "Online & Diagnostics" (TIA Portal).
  4. Force the CPU to STOP, then back to RUN. Observe OB100 executing once.
  5. In the VAT, watch T0. It should be active for 60 s. During this period, MW100 should not increment; OB35 should execute BEC immediately.
  6. After 60 s, T0 times out and OB35 begins its normal work; MW100 should increment every 100 ms.

On the H system, repeat with the standby CPU in STOP and confirm that the inhibit survives a master-to-standby role switch. If T0 is declared in the H-sync data area, the value is replicated; if not, the new master starts its own timer fresh, which is usually the desired behavior.

Troubleshooting Matrix

Symptom Probable Cause Corrective Action
OB35 runs immediately after POWER ON OB100 was not loaded, or the timer is in a non-retentive area and was cleared on restart Verify OB100 is present in the offline program; mark T0 in a retentive DB
OB1 runs during link-up Firmware bug on early H-series CPUs; or "Startup only after complete link-up" is unchecked Check the CPU's firmware version; enable the link-up option in HW Config
OB35 does not run after T0 expires DIS_IRT was called and EN_IRT was never issued Insert EN_IRT call in OB100 with a delay block (SFC32)
CPU goes to STOP with SF LED after OB100 OB100 has a programming error; OB121 is not loaded Load OB121; check the diagnostic buffer for the exact block offset
T0 still active 10 minutes after POWER ON S5T#1M value was mistyped as S5T#1H Correct the constant; reload OB100

Comparison with Other Siemens Platforms

The S7-400H is the only Siemens platform in current production that has explicit link-up and update phases. The S7-1500H (firmware V2.0 and later) behaves similarly but uses S7-1500 task names ("Program cycle OB" instead of OB1) and exposes the link-up option under Properties → Redundancy → Startup. The S7-1200 does not have a redundant variant; its startup OBs are OB100 (warm restart) and OB102 (cold restart) and the cyclic OB is OB1. Per the TIA Portal startup configuration manual, the S7-1200 startup behavior is much simpler: OB100 runs, then OB1 begins on the next cycle, with no link-up phase.

For the older S7-300, OB100 (restart) and OB102 (cold restart) are present but there is no link-up phase. The same BEC pattern works identically on S7-300 cyclic interrupt OBs, and SFC39/SFC40 can be used in the same way.

Common Pitfalls

  • Setting T0 in OB35 itself - The timer is reset every 100 ms and the inhibit never expires. Always arm T0 in OB100 and read it in OB35.
  • Using M0.0/M0.1 as the inhibit flag - These are non-retentive and are cleared at every restart, which is the desired behavior, but they are also overwritten by OB1 in cycle 1, so any flag set in OB100 must be a bit that OB1 will not touch. Best practice: use a dedicated bit in a retentive DB, with the bit cleared at the end of OB1's first scan.
  • Calling SFC39 in OB35 - Calling DIS_IRT in OB35 disables OB35 itself; the next time it fires, the call has already disabled it, but only the current execution continues. This causes a 100 ms latency on the disable. Always arm the disable in OB100 and the enable in a delayed FC.
  • Forgetting OB101 - On the S7-400H, the standby executes OB101 at link-up. If OB101 is missing, the CPU goes to STOP. If OB101 is present but contains code that clears T0, the inhibit will not survive a role switch.

FAQ

Do I need to write inhibit code in OB1 and OB35 for S7-400H startup?

No. The S7-400H operating system does not call OB1 or OB35 during the POWER ON, self-test, restart (OB100), cold restart (OB102), link-up, or update phases. Cyclic OBs are held by the firmware until the redundant system enters RUN. See the S7-400H manual Chapter 8.

What is SFC90 (H_CTRL) and when should I use it?

SFC90 is the H-system control SFC. It can start and stop link-up, update, and self-test slices. Common use is MODE = 8 (stop self-test) for bench diagnostics only; never disable self-test in production because fault detection depends on it.

How do I delay the first scan of OB35 by 60 seconds after restart?

Arm a 60 s S5 timer (S5T#1M) in OB100, then in OB35 use A T0 followed by BEC. The OB exits immediately while T0 is running and executes normally after the timer expires.

Why is OB1 not running on the standby CPU during link-up?

Link-up requires the standby to read the master's H-sync data block. OB1 is held on both CPUs until this exchange completes, then both CPUs begin OB1 in the same cycle. This is firmware behavior and cannot be overridden.

Can I use DIS_IRT (SFC39) to skip OB35 during startup?

Yes. Call SFC39 in OB100 with OB_NR = 10 to disable OB35, then schedule an SFC32 (SRT_DINT) timer to call SFC40 (EN_IRT) after the desired grace period. This is the documented method when BEC is not sufficient.

Back to blog