Problem Description
The Siemens SIMATIC S7-300 CPU 314C-2 PtP integrates 24 digital inputs, 16 digital outputs, 4 (plus one RTD) analog inputs, 2 analog outputs, 4 high-speed counters, and one point-to-point RS-422/485 serial interface in a single compact CPU. Its onboard digital inputs occupy the byte range E124.0 through E126.7 and support configurable hardware interrupts on rising edge, falling edge, or both. The onboard analog inputs occupy the peripheral input word range PIW752 through PIW759 and support hardware interrupts when configured limits are exceeded.
A recurring field symptom is observed when four onboard digital inputs — for example E126.0, E126.1, E126.3, and E126.4 — are configured for rising-edge hardware interrupts. OB40 is loaded as the hardware interrupt organization block. Each OB40 invocation is expected to transfer PIW752 into one of four marker words (MW230, MW232, MW234, MW236) based on which input triggered. After roughly 8 to 15 cycles the operator notes that OB40 fails to fire for one of the four inputs even though the corresponding physical input is clearly asserted. The matching marker word is never updated, producing a stale reading or zero.
The same pattern is reported in variants where the source code instead starts in the standard process image (E0.0–E0.3) and reads PIW256 instead of PIW752. The cycle is short and the application is simple — a single OB1 scan plus an OB40 invocation per event — yet the loss is intermittent, random, and reproduces consistently on the bench. From the application's perspective the channel seems “skipped”; from the firmware's perspective something else is happening.
Affected Hardware and Firmware
The relevant product line is the S7-300 CPU 31xC family. The CPU 314C-2 PtP ships in several MLFB variants across firmware releases V2.0 through V3.3; all share the same OB40 interrupt mechanism and are exposed to the same edge-case behavior. Reference data for the family is published in the Siemens manual “SIMATIC S7-300 CPU 31xC and CPU 31x: Technical specifications” (entry ID 12996906 in the Siemens Industry Online Support). Key numbers from that document for the CPU 314C-2 PtP:
- Maximum number of simultaneously enabled interrupt-driven S blocks: 300.
- Process image, address range for inputs, maximum: 124 bytes.
- Hardware interrupt sources: digital inputs (rising/falling edge) and analog inputs (limit exceeded).
- Number of process image partitions supported: up to 15 (PIP 1 through PIP 15), enabling per-OB image updates.
- OB40 priority class: configurable per project, default priority 16 (above OB1 priority 1).
The 300-block figure refers to SFB-driven (SFB36 / SFB37 / SFB47) interrupt execution, not to raw hardware-interrupt events on onboard DIs. For raw edge events the practical queue depth is limited by the firmware interrupt controller; this is the first place where symptoms arise.
Root Cause Analysis
OB40 is the S7-300 hardware interrupt organization block. It is invoked once per recognized edge event. The triggering identity is provided through its temporary local variables, the most important being OB40_POINT_ADDR at bytes 12–13 of the OB40 start information. For the CPU 314C-2 PtP onboard digital inputs, when input E126.0 fires, the firmware writes the byte address 0x007E (= 126) into OB40_POINT_ADDR byte 12 and the bit mask 0x0001 into byte 13. The four sample inputs therefore produce the following OB40_POINT_ADDR values:
| Input | Byte (OB40_POINT_ADDR low) | Bit mask (OB40_POINT_ADDR high) | Comment |
|---|---|---|---|
| E126.0 | 0x007E | 0x0001 | Bit 0 of byte 126 |
| E126.1 | 0x007E | 0x0002 | Bit 1 of byte 126 |
| E126.3 | 0x007E | 0x0008 | Bit 3 of byte 126 |
| E126.4 | 0x007E | 0x0010 | Bit 4 of byte 126 |
When two or more configured inputs rise inside the same hardware window — typically within one PLC scan cycle or even within tens of microseconds — the following failure modes are observed:
Cause A: Multiple Edges Within One OB40 Invocation Window
If the PLC detects two rising edges faster than OB40 can be scheduled and dispatched, only one event is queued. The second edge is treated by the interrupt controller as “already pending” and is silently dropped. The diagnostic buffer records this as Interrupt lost. With the default 3 ms hardware input filter on the CPU 314C-2 PtP onboard inputs, mechanical contact bounce shorter than 3 ms is filtered; clean 24 V transitions faster than 0.5 ms apart still collide on the same hardware cycle and overflow the queue.
Cause B: Process-Image Read on a Fast-Changing Analog Channel
If the application reads PIW752 (or PIW256 in the alternative example) inside OB40, it is reading the process image, not the physical input. The process image of the analog area is refreshed at the start of OB1, or at the start of the OB configured with the relevant process-image partition update. If OB40 fires between two OB1 scans, PIW752 in OB40 still holds the value from the previous OB1 start. Worse, an interrupt that fired but is attributed to the wrong channel because of queueing effects will silently overwrite a different marker word with the same stale PIW value, producing the appearance of “OB40 skipped an input” when in fact OB40 fired for the wrong channel or with a stale value.
Cause C: Limited Hardware Interrupt Queue Depth
The CPU 314C-2 PtP maintains a small interrupt queue for raw hardware events on the onboard DIs. The practical queue depth for OB40 is two slots — one currently executing and one pending. A third simultaneous edge is lost without producing a diagnostic entry other than the Interrupt lost record. The 300-block figure in the Siemens manual refers to SFB usage, not raw edge events.
Cause D: OB40 Priority and Re-Entrancy
OB40 runs at the configured priority (default 16). While OB40 is executing, a new hardware interrupt on a different input raises a second OB40 request. After OB40 returns the queued request is dispatched. The diagnostic buffer therefore shows two OB40 entries per cycle when both edges are captured, and one entry when one is lost. The application that assumes a single OB40 invocation per cycle will see a different MW missing on each cycle.
Cause E: Process-Image Partition Not Assigned
If OB40 is not linked to a process image partition (PIP), the firmware does not refresh DI/AI between OB1 and OB40. The application reads stale values. Worse, on the CPU 314C-2 PtP the default behavior is that OB40 reads from the same PIP as OB1 (PIP 1, full image). If the engineering has not selected a PIP for OB40, OB40 will not trigger an image refresh on entry, and the analog value in PIW will lag by one OB1 scan. The 3 ms input filter setting compounds this: short analog transitions that triggered the interrupt may have already passed by the time the stale PIW is read.
Cause F: Misinterpretation of L9.x Local Flags
The original application uses local flags L9.0, L9.1, L9.2, and L9.3 as if they were automatically populated by the OB40 runtime. They are not. L9.x is a free temporary local variable in the OB40 stack frame; the firmware does not set it. The correct way to identify the triggering channel is to decode OB40_POINT_ADDR manually, either in STL or via the symbolic temporary variable exposed in TIA Portal. If the application sets L9.x itself, the apparent “missed interrupt” is in fact a correctly executed OB40 that set the wrong local flag.
Diagnostic Buffer Interpretation
Open the CPU's online diagnostic buffer in STEP 7 V5.5 or in TIA Portal V13 SP1 and later. Filter for OB40 entries and Interrupt lost entries. The entries most commonly seen in this scenario are:
-
“Interrupt OB 40 start event” — the firmware records the OB40 dispatch, including
OB40_POINT_ADDRfor the channel that fired. Compare the address against the expected channel to confirm which channel actually caused the interrupt. - “Interrupt lost” — the firmware detected a second edge before the previous OB40 could be queued. The lost-event entry contains the channel number that was dropped.
- “STOP because of interrupt overflow” — only seen in extreme cases when the CPU 31xC loses all process synchronization; rare on the CPU 314C-2 PtP but reported on heavily loaded configurations with long OB40 execution times.
For a permanent record, configure CPU messaging in NetPro so that each OB40 invocation writes a system timestamp and the OB40_POINT_ADDR into a global DB. The system timestamp comes from SFC64 (TIME_TCK) and provides 100 ns resolution. A second global DB counter incremented inside OB40 gives a continuous invocation count that can be cross-checked against the count of rising edges on the physical inputs (read via PEW counters or a high-speed counter channel).
PEW (direct peripheral access) inside OB40 rather than PIW for the diagnostic counters. PIW values are stale until the next OB1 scan refresh; PEW reflects the current hardware state.OB40 Hardware Interrupt Mechanics
A complete mental model of OB40 helps avoid the trap. When a configured edge is detected on a digital input of the CPU 314C-2 PtP:
- The input hardware latches the edge and sets the channel's pending bit in the interrupt control register of the onboard I/O.
- The CPU firmware reads the interrupt control register at the boundary between two machine cycles (sub-microsecond scale).
- If an OB40 is not already pending and the channel is enabled in HW Config, the firmware sets the OB40 request flag and queues one OB40 execution.
- After the current task (OB1 or higher-priority OB) completes, the CPU dispatches OB40.
- Inside OB40,
OB40_POINT_ADDR(bytes 12–13) holds the address of the channel that triggered. The application'sL9.xflags are not automatically set. - The application code reads
OB40_POINT_ADDR, branches on it, and copies the desired value into the corresponding MW. - OB40 returns. The firmware processes the next queued event (if any). If no other event queued, control returns to OB1.
The following SVG flow captures the dispatch logic for one cycle:
The diagram shows the five ways the system can drop an edge: filter rejection, queue overflow, and — critically — the timing relationship between OB40_POINT_ADDR arrival and the freshness of PIW / PEW. The application must be designed against this state machine, not against the assumption of one OB40 invocation per cycle.
Step-by-Step Resolution
Apply the following changes in order. Each step is independently verifiable.
Step 1: Confirm Hardware Configuration
Open HW Config in STEP 7 V5.5 (or the device configuration in TIA Portal V13 SP1 and later). Select the CPU 314C-2 PtP and open the Inputs tab of the onboard DI24 module. For each of the four inputs used:
- Check Hardware interrupt → Rising edge (or Both edges if needed).
- Verify the input address range: CPU 314C-2 PtP onboard DI bytes are 124, 125, 126.
- Open Input filter and note the default 3 ms input filter. For mechanical contacts with bounce shorter than 3 ms the input filter hides the bounce but also hides legitimate short pulses. Set the filter to 1 ms only if you have clean 24 V signals from a sourcing sensor with sub-millisecond rise time.
- If you use analog interrupts instead, open the Analog inputs tab and enable Hardware interrupt when limit exceeded for each channel. Enter high and low limits that bracket the normal operating range with sufficient margin (typically 10% above/below nominal).
Step 2: Assign OB40 to a Process Image Partition
In HW Config, right-click the CPU and select Properties → Cycle / Clock Memory → OB40 → Process image partition and assign PIP 2 to OB40. PIP 2 should contain only the onboard DI bytes 124–126 and the onboard AI words 752–759. When OB40 fires the CPU refreshes this partition first, so PIW752 in OB40 is current.
In TIA Portal the equivalent is the Process image tab of the device configuration: enable Automatic update of process image partitions and place the relevant DI/AI tags into PIP 2.
Step 3: Read Physical Inputs, Not the Process Image, in OB40
For the analog value, replace PIW752 with PEW752 (or %IW752 in TIA Portal) inside OB40. PEW reads the analog input directly without going through the process image. This guarantees the current value regardless of PIP configuration. The downside is that PEW on the CPU 314C-2 PtP may take slightly longer to read than PIW; for a four-channel application the additional 10–20 µs is negligible.
Step 4: Decode OB40_POINT_ADDR Explicitly
Replace the implicit assumption that L9.x is automatically set with explicit decoding. In STL:
L #OB40_POINT_ADDR // load the byte address (low word)
L W#16#7E // = 126 decimal = 0x7E
==I
JC CHK1 // jump if byte matches
JU END
CHK1: L #OB40_POINT_ADDR+2 // load the bit mask (high word)
L W#16#0001 // mask for bit 0
==I
S M 230.0 // set flag for channel 0
JU END
END: BE
In LAD/FBD, evaluate OB40_POINT_ADDR symbolically through an == comparison on the temporary variable. In TIA Portal, the same variable is exposed as OB40_POINT_ADDR in the OB40 interface, with the byte address and bit mask split into the low and high words of the temporary DWORD.
If only one input can fire at a time this decoding is sufficient. If more than one can fire, continue with steps 5–7.
Step 5: Handle Multiple Events With a Sequencer
For applications where two or more inputs can fire within a few hundred microseconds, replace the four L9.x flags with a sequencer — a small ring buffer in a global DB that stores the channel number and PEW reading for each OB40 invocation. In OB40:
L #OB40_POINT_ADDR // identify channel
T DBW 10 // write channel into slot 0
L PEW 752 // read fresh analog value
T DBW 12 // write value into slot 0
L DBW 0 // current head pointer
+ 2 // advance 2 bytes
T DBW 0 // store new head pointer
In OB1, drain the ring buffer into the four MW values:
L DBW 0 // current head
L DBW 2 // current tail
==I
JC EMPTY // nothing to drain
L DBW 4 // channel of next slot
T MW 230 // route to MWx based on channel
L DBW 6 // value of next slot
T MW 232 // store (example)
L DBW 2 // advance tail
+ 2
T DBW 2
This separates interrupt capture from value processing and prevents collisions even when OB40 fires twice within one OB1 scan.
Step 6: Verify the Diagnostic Buffer Is Clean
After applying the fix, monitor the diagnostic buffer for at least 30 minutes of normal operation. There should be no Interrupt lost entries and no unexpected OB40_POINT_ADDR values. If an Interrupt lost entry still appears, the input filter is too short for the application; raise the filter to 3 ms or 5 ms.
Step 7: Verify With the Trace Tool
Use the STEP 7 trace (Tools → Trace) or the TIA Portal trace (Project → Traces) to record:
- The state of
E126.0,E126.1,E126.3,E126.4over time. - The OB40 entry timestamp via
SFC64 (TIME_TCK)written into a global DB at the start of OB40. - The
MW230,MW232,MW234,MW236values. - The
PEW752value (the raw analog reading).
Run the trace for 10 minutes while triggering all four inputs at random intervals from 100 ms to 5 s. The trace should show exactly one OB40 entry per rising edge and the correct MW update for each channel.
Verification Checks
To prove the fix, perform the following checks in order:
-
Static read test: with all four inputs held high, observe
MW230,MW232,MW234,MW236in the variable table. All four should hold the currentPEW752value within ±1 LSB. Before the fix, at least one of them is stale or zero. - Sequence test: trigger input 1, then input 2, then input 3, then input 4 with 500 ms spacing. Each OB40 should fire once and each MW should update once.
- Burst test: trigger two inputs within 100 ms. Both MW values should update. With the ring-buffer sequencer from Step 5, both updates are captured even if OB40 fires twice within one OB1 scan.
- Diagnostic buffer review: zero Interrupt lost entries during the test sequence.
- Long-duration test: run the application for 24 hours under normal load. Before the fix, the missing-update fault appears every 8–15 cycles. After the fix, no missing updates.
Preventive Best Practices
For new applications on the CPU 314C-2 PtP and other S7-300 compact CPUs with onboard interrupts:
- Always assign OB40 to its own process image partition (typically PIP 2). Configure the DI/AI bytes you need into that partition only.
- Always use
PEW(direct I/O access) inside OB40 for time-critical analog values.PIWis acceptable only when the value changes slower than the OB1 scan time and you can tolerate one-cycle latency. - Always decode
OB40_POINT_ADDRexplicitly; never assumeL9.xor other local bits are set automatically by the firmware. - Always document the maximum edge rate and verify it against the input filter setting and the OB40 execution time budget.
- Always implement a diagnostic DB that records OB40 invocations with
SFC64timestamps. This is invaluable for post-mortem analysis and is required by most Siemens application audits. - For applications with more than two simultaneously expected edges, use the ring-buffer sequencer pattern from Step 5.
- For analog limit detection, prefer OB40 +
PEWfor direct reading rather than OB1 polling. OB1 polling is acceptable only if the cycle time is well below the limit-change rate. - Keep OB40 short. Every additional line of code in OB40 increases the chance of an interrupt-queue overflow.
- Do not call communication SFCs that block (e.g.
BSEND,USEND,PUT,GET) inside OB40. Use asynchronous variants or move the call to OB1. - Do not call FB/SFB that requires an instantiation DB if the DB is being used by OB1; OB40 has a different priority and can deadlock on shared DBs.
- Set the OB40 priority explicitly in HW Config and document it. The default priority 16 is appropriate for most applications; raise it to 17–22 for time-critical applications, and avoid setting it below 9.
Troubleshooting Matrix
| Symptom | Most Likely Cause | First Check |
|---|---|---|
| OB40 skips input after 8–15 cycles | Simultaneous edges colliding with queue depth | Diagnostic buffer for Interrupt lost |
| OB40 always fires but MW stays zero |
PIW read inside OB40 returns stale value |
Replace PIW with PEW; enable PIP for OB40 |
| OB40 fires for wrong channel |
L9.x flag assumed; OB40_POINT_ADDR not decoded |
Decode OB40_POINT_ADDR explicitly |
| OB40 never fires at all | Hardware interrupt not enabled in HW Config | Re-check Hardware interrupt checkbox on DI tab |
OB40 fires but PEW752 returns 0x7FFF |
Analog input open or overrange | Check wiring, channel diagnostics in HW Config |
| Intermittent OB40 with mechanical contacts | Input filter hides bounces but also legitimate edges | Use clean 24 V signal or external debounce |
| OB40 stops after CPU STOP/RUN transition | OB40 not loaded after restart | Re-download blocks after online STOP |
| OB40 runs but MW value is one cycle old | Process image partition not assigned to OB40 | Configure PIP 2 in HW Config |
| OB40 executes but application reports “no event” | Edge faster than input filter; firmware rejected it | Reduce input filter from 3 ms to 1 ms |
| Diagnostic buffer shows OB 40 not loaded | OB40 missing from offline project | Add OB40 to project, download blocks |
Platform Notes
The same diagnostic pattern applies to other S7-300 CPUs with onboard interrupts:
- CPU 312C: smaller DI count, same OB40 model, same caveats on queue depth.
- CPU 313C: identical architecture, same caveats. Onboard AI addresses differ; verify in the device manual.
- CPU 315-2 PN/DP and CPU 317-2 PN/DP: same OB40 mechanism for onboard DIs; PN/DP variants have additional PROFINET/PROFIBUS interrupts handled by OB82 through OB86.
- CPU 319-3 PN/DP: extends OB40 queue depth; fewer edge collisions are observed but the same patterns apply.
-
ET200S high-feature digital input modules (e.g. 6ES7131-4BF00-0AB0): use OB40 the same way but the
OB40_POINT_ADDRbytes reflect the slot-based address, not the CPU onboard byte. The module address is inOB40_MDL_ADDR.
For S7-1500, the equivalent OB is OB40 as well but with the new local-data model and direct access via the process image of Isochronous mode or the standard image. S7-1200 uses OB200 hardware interrupts (rising/falling) and a slightly different POINT_ADDR layout. Both controllers use the same fix pattern: assign PIP, use direct I/O access inside OB40, decode POINT_ADDR explicitly, and implement a ring buffer for burst events.
Why does OB40 skip an input on the CPU 314C-2 PtP after a few cycles?
When two configured rising edges occur faster than OB40 can be queued and dispatched, the queue depth of two is exceeded and the firmware drops the second event silently. Check the diagnostic buffer for Interrupt lost entries and either reduce the edge rate, increase the input filter from 3 ms to 5 ms, or implement a ring-buffer sequencer in OB40 as described in Step 5.
Does L9.x in OB40 automatically indicate which input triggered?
No. L9.x is a temporary local flag in the application's OB40 interface; the firmware does not set it. The correct way to identify the triggering channel is to read OB40_POINT_ADDR (bytes 12–13 of the OB40 temp area, exposed as the OB40_POINT_ADDR symbolic variable in TIA Portal) and decode the byte address and bit mask explicitly.
Why does PIW752 read a stale value inside OB40?
The process image is refreshed at OB1 start, or at the PIP update you assign. OB40 runs at a higher priority and does not automatically refresh the image unless you assign it a process image partition. To read the current value use PEW752 (direct access) or assign PIP 2 to OB40 in HW Config and place the AI words in that partition.
How many hardware interrupts can the CPU 314C-2 PtP queue?
For raw hardware interrupts on onboard DIs, the effective queue depth is two — one currently executing and one pending. The 300 figure in the Siemens technical specifications manual refers to SFB-based interrupt-driven blocks (SFB36, SFB37, SFB47), not to raw hardware events. A third simultaneous edge is lost.
Should I use the analog input hardware interrupt or OB1 polling for limit detection?
Use the analog hardware interrupt (configurable in HW Config on the AI channels of the CPU 314C-2 PtP) for fast limit detection; it produces an OB40 event with the channel coded in OB40_POINT_ADDR. OB1 polling is acceptable only if the cycle time is well below the limit-change rate. For four-channel monitoring with sub-100 ms response, OB40 is the right choice; remember to use PEW instead of PIW inside the OB and assign a dedicated PIP to ensure the analog value is current.