Siemens S7-300 Work Memory 100% Full: MMC Sizing and Code Fix

David Krause22 min read
S7-300SiemensTroubleshooting
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

Overview: Why S7-300 Stops Processing New Code Near 100% Work Memory

On the Siemens S7-300 platform, work memory (the RAM area the CPU executes from at runtime) and load memory (the MMC card that stores the compiled project) are decoupled in size. When work memory utilization climbs above roughly 90% on a CPU 315-2 DP, behavior diverges from what the percent figure alone suggests: the CPU may continue to indicate RUN yet stop executing newly downloaded networks, or refuse to bring new blocks into RAM at all if the MMC is undersized relative to the project. Field experience on CPU 315-2 DP stations with a 128 KB work memory and a 128 KB MMC shows that adding even a small block can produce a "no processing" symptom, even when Step 7 reports the download as successful and the simulator runs the same code without fault.

This article consolidates the engineering constraints that govern that situation: memory sizing, MMC capacity, multi-instance function block layout, communication load budget, and the code regeneration procedure used to rebuild a project from STL source when online and offline blocks drift out of sync. The recommendations apply to all CPU 31x-2 DP variants with comparable work memory budgets, and to the S7-300 family in general wherever the cited memory architecture matches.

S7-300 Memory Architecture

The S7-300 CPU separates executable code and data across three distinct storage areas. Each area has its own physical backing and its own sizing rule; mixing them up is the most common root cause of "code compiles, CPU does not process" symptoms.

Area Backing Store Volatile? Purpose
Load memory Micro Memory Card (MMC) No (MMC is non-volatile flash) Stores the compiled project: all OB, FB, FC, SFB, SFC, DB, and system data blocks.
Work memory Internal RAM Yes on battery-less CPUs, battery-backed on older CPUs Runtime copy that the CPU scans. Code and DB data needed for execution are mirrored here from the MMC at startup.
Retentive memory Internal RAM Yes, retained across power cycles if a backup battery is present and configured Holds a configurable subset of bit memory (M), timers (T), counters (C), and DB areas across power cycles.
System memory Process image (PII/PIQ), bit memory (M), timers (T), counters (C) Yes, sized per CPU Fixed addressable areas used by the scan; not part of work memory for the user-program counter.

The work memory is not a strict subset of load memory: a project with N bytes of compiled blocks must fit on the MMC, and the work memory must be large enough to hold the runtime mirror. A mismatch (small MMC, large work memory) is the root cause of "code compiles, but the CPU does not process new logic" symptoms. The size of the runtime mirror is usually 60-80% of the compiled project size; the rest is block headers, system data, and the DB image that the OS keeps on the MMC and pages in on demand.

What Goes Where When You Download

When you download a project to the CPU, Step 7 writes the compiled blocks to the MMC (load memory). At the next STOP-to-RUN transition (or at power-up), the CPU copies a subset of those blocks into work memory: the OB1, all FBs and FCs called by OB1 directly or indirectly, and the instance DBs of those FBs. Other blocks remain on the MMC and are paged in as the OS calls them. If a block has been edited offline but the MMC is full, the CPU cannot refresh the on-MMC copy, and the next scan continues to run the old version from work memory. This is the "I added code, the CPU shows RUN, but the new code is not processed" symptom that drives most of the calls to this article.

CPU 315-2 DP Memory Sizing Reference

Parameter CPU 315-2 DP (6ES7315-2AF03-0AB0 / -2AH14-0AB0)
Order number (typical) 6ES7315-2AF03-0AB0 / -2AH14-0AB0
Work memory, integrated 128 KB (code + data, integrated)
Load memory Plug-in MMC, project-dependent
Typical MMC sizes used 64 KB / 128 KB / 256 KB / 512 KB / 1 MB / 2 MB / 4 MB / 8 MB
Bit memory (M) 2 048 bytes (default), retentive configurable
S7 timers / counters 256 / 256 (default), retentive configurable
DB count (max) Up to 1 024 (CPU-dependent)
FB / FC count (max) Up to 2 048 / 2 048 (CPU-dependent)
SFB / SFC count CPU-defined (full S7-300 set integrated)
Communication scan load max 50% of OB1 cycle time (configurable)
Profibus DP interface 1 x DP master/slave, isolated
PG / OP / S7 communication Up to 16 connections via MPI/DP and CP 343-1
Note: The 128 KB work memory figure is the value reported on CPU 315-2 DP variants cited in the source case. Different order numbers (the 315-2 EH 14-0AB0, 315-2 PN/DP, and 317-2 variants) carry larger work memory; always read the work memory figure from the module's diagnostic buffer or the Step 7 module information rather than from the catalog family alone. The catalog headline "128 KB / 256 KB" is a family-level summary, not a per-order-number spec.

Work Memory Utilization Thresholds

Step 7 reports work memory as a percentage in two locations:

  1. Module Information > Memory: bytes used / bytes available for work memory and load memory separately.
  2. Online > Accessible Nodes > Diagnostics: percent utilization of the CPU's work memory.

Field-observed thresholds on a CPU 315-2 DP with a typical Profibus DP and CP 343-1 footprint:

Work Memory Used Observed Behavior Recommended Action
≤ 70% Normal operation, new blocks download and run reliably. None.
70-85% Compiles and runs, but download time and cycle time increase noticeably. Plan a memory expansion before adding new features.
85-95% New blocks compile in Step 7 but the CPU may refuse to load, or may load without executing. Stop, expand MMC, refactor code (delete dead blocks, consolidate DBs).
> 95% Stop / run cycles can drop newly added code, scan cycle time rises, OB80 (time error) becomes likely. Stop, expand MMC, refactor code, or migrate to a CPU with larger work memory (e.g. 315-2 PN/DP, 317-2).

At 100% reported utilization, the CPU may still indicate RUN but behave as if it has lost the new code. The "100%" label means work memory is full; it does not mean that 100% of the executable program is being processed by the CPU. The two are not the same because of the way the OS swaps blocks between the MMC and work memory: a block can be present on the MMC and absent from work memory, and the OS only pages it in if it is on the current call stack. If your new block is not on OB1's call stack, the CPU will not page it in just because it is on the MMC.

MMC Sizing Rule

To use the full work memory of an S7-300 CPU, the MMC must be at least as large as the sum of:

  1. All compiled blocks (OB + FB + FC + DB + SDB + SFB + SFC + system data).
  2. System data blocks generated by the hardware configuration (HW Config). One SDB per Profibus slave, one per Ethernet connection, one for the global SDB.
  3. A working reserve for future expansion (typically 25-50% of the current compiled project size).

For a CPU 315-2 DP with 128 KB of work memory, a 128 KB MMC is rarely enough because the compiled project is always larger than the in-RAM runtime image: each block has a header, every DB is placed on the MMC, and HW Config adds system data blocks for every Profibus slave and for the CP 343-1. The conservative rule of thumb is to use an MMC whose capacity is 2x the work memory figure. For a 128 KB work memory CPU, that means a 256 KB MMC minimum.

For a station with 18 Profibus slaves (ET200, WAGO, S7-200), a 256 KB MMC will be tight; 512 KB is the safer choice. Each Profibus slave generates at least one SDB (about 2-4 KB), so 18 slaves add roughly 50-70 KB of SDBs on top of the user project.

Engineering rule: Match the MMC to the largest project you expect to deploy, not the project you have today. Step 7 cannot resize an MMC in place; you must read the MMC with a PG, expand the project offline, and write the MMC back. Always archive the MMC contents before resizing. The PG file format for MMC read/write is *.s7p or *.s7l depending on Step 7 version.

MMC Capacity Reference for CPU 315-2 DP

MMC Order Number (6ES7953-...) Capacity Suitable Work Memory Notes
...-8LF00 64 KB ≤ 32 KB Bootstrap and small test projects only.
...-8LH00 128 KB ≤ 64 KB Bare minimum for CPU 315-2 DP if the project is tight. The source case shows this size is insufficient for a 128 KB work memory CPU with 18 Profibus slaves.
...-8LJ00 256 KB ≤ 128 KB Recommended for typical 315-2 DP installations with light I/O.
...-8LK00 512 KB ≤ 256 KB Recommended for installations with multiple CP modules or 10+ Profibus slaves.
...-8LL00 1 MB ≤ 512 KB Use when there is a heavy Profibus / Profinet I/O footprint.
...-8LM00 2 MB ≤ 1 MB Use for projects approaching 800 KB.
...-8LP00 4 MB ≤ 2 MB Use for projects with large recipe DBs or many instance DBs.
...-8LR00 8 MB ≤ 4 MB Use for archive-class projects, firmware updates, and large documentation sets.

Communication Load Budget (Profibus + Ethernet)

For a CPU 315-2 DP with a CP 343-1 Ethernet and 18 Profibus slaves (ET200 UD73, WAGO I/O, S7-200), the OB1 cycle is shared between user program execution and the operating system's communication stack. Step 7 exposes this split as the Scan cycle load from communication parameter, expressed as a percentage of OB1 time.

Parameter Default Maximum Allowed
Scan cycle load from communication 20% 50%
OB1 minimum cycle time - Set per project, watchdog-aware
PG / OP communication Included in the 20% Counted toward the budget
S7-200 (Profibus slave) I/O scan Included in the 20% Counted toward the budget

Configured at 20%, the communication stack receives 20% of the OB1 cycle time. Increasing the value to 50% gives the operating system more time for Profibus DP-V0/V1 cycles, S7 communication, and PG/OP traffic, but it proportionally reduces time available to the user program. Past 50%, the CPU no longer guarantees scan timing, and OB80 (time error) becomes likely.

On the cited station with 18 Profibus slaves, a 20% figure is healthy; an increase to 50% should only be needed if the application is dropping connections to the WAGO couplers or the S7-200 slave during full I/O scans. The 20% figure is reported by the CPU itself and is read in the diagnostic buffer or in the cycle-time statistics dialog of the online view.

S7-200 as a Profibus Slave

An S7-200 connected to a CPU 315-2 DP over Profibus DP is a slave: it does not initiate communication, it does not run user-programmable blocks visible to the master, and its I/O is mapped into the master's process image as a fixed I/O area. The S7-300 reads the slave's inputs via DP-V0 cyclic I/O and writes its outputs via the same mechanism. The data is then placed into a DB on the S7-300 side; the user program reads and writes the DB to exchange data with the S7-200.

This matters for memory budgeting: the I/O area of the S7-200 (typically 4-32 bytes in, 4-32 bytes out) occupies a fixed slice of the master process image. If the S7-200 is in CLEAR (slave disabled by the master), the inputs from that slave freeze at their last value. If the S7-200 is in POWER-OFF, the inputs are reported as 0. Both cases are visible in NetPro / HW Config and in the diagnostic buffer of the DP master.

Multi-Instance Function Block Pattern

Multi-instance FBs let a parent FB declare static instances of other FBs (its own children) so that each child instance is embedded inside the parent's instance DB rather than allocated a separate instance DB. On a CPU whose DB count is bounded (CPU 315-2 DP: up to 1 024 DBs), this pattern is the standard way to keep DB count low while still using FB-based modular code. It also lets the parent and its children share a single data view, which simplifies data exchange.

Pattern

FUNCTION_BLOCK FB_Machine
VAR
  bStart  : BOOL;           // input
  iSpd    : INT;            // input
  bOpen1  : BOOL;           // input
  bOpen2  : BOOL;           // input
  Pump1   : FB_Pump;        // STAT multi-instance
  Valve1  : FB_Valve;       // STAT multi-instance
  Valve2  : FB_Valve;       // STAT multi-instance
END_VAR

BEGIN
  Pump1(Run := bStart, Spd := iSpd);
  Valve1(Opn := bOpen1);
  Valve2(Opn := bOpen2);
END_FUNCTION_BLOCK

Rules When Using Multi-Instances

  1. The child FB must already exist in the block folder before the parent FB is compiled. If the child is missing, the parent compile fails with a "type not found" error.
  2. Declare the child as a STAT variable, not as a TEMP variable. TEMP is destroyed at the end of the call and is not a valid multi-instance container. A TEMP-declared "multi-instance" will compile but its state will be lost every scan.
  3. Call the child with CALL #Pump1 (or the equivalent LAD/FBD call) inside the parent's code; do not call the child's standalone instance DB. The call to a multi-instance is the call to the local symbol, not to an instance DB number.
  4. If a child FB's interface is changed, recompile every parent that uses it. Step 7 will not auto-update parent instance layouts across multi-instance hierarchies. A signature mismatch will surface as a compile error in the parent.
  5. Avoid declaring the same child FB as both a multi-instance in a parent and a separately allocated instance DB in any other block; the two will not share state and Step 7 will not warn about it.
  6. The instance DB of the parent must be large enough to hold all child instances. If a child is added later and the instance DB is not refreshed, the parent's call to the new child will write outside the DB and may corrupt adjacent data or trigger OB121 (programming error).
Misuse to avoid: Treating a multi-instance as a "loose" reference. If the child is declared as STAT in the parent and the parent itself is never called, the child is never executed. Always confirm the parent has a call site before debugging missing-child behavior. A multi-instance FB with no parent call is invisible to the scan.

Shared DB Anti-Pattern

In a shared DB anti-pattern, a single DB is treated as a data pool and every FB is handed a pointer or absolute offset into it. This pattern is brittle because:

  1. Step 7 cannot protect the data layout when multiple FBs read/write the same offsets. Two FBs writing the same byte of a shared DB will silently corrupt each other's state.
  2. Renumbering a DB or moving a struct breaks every consumer. There is no compiler check to catch a missed offset update.
  3. Multi-instance FBs do not get a per-instance data view; the DB becomes the de-facto instance, which defeats the purpose of FB encapsulation and prevents reuse of the FB in a second machine with different state.
  4. The shared DB itself occupies a fixed slot in the DB count budget and can push the project toward the 1 024 DB limit on the CPU 315-2 DP sooner than a multi-instance layout would.

Replace with: a typed DB per machine, with the parent FB declared as a multi-instance, or one instance DB per call site. The compiled code size is similar, but the data layout is protected and the FB is reusable.

Code Regeneration Procedure from STL Source

When the online block view and the offline project drift out of sync, with symptoms including "block exists online but not offline", "block timestamp mismatch", and downloaded code that the CPU does not run, regenerate the entire project from STL source. This rebuilds blocks in a deterministic order from one source file and resolves the online/offline drift in a single operation.

  1. Open the project in Step 7 (SIMATIC Manager).
  2. Open the block that you want to export (or the Blocks folder) in the STL/LAD/FBD editor.
  3. Press Ctrl + T in the editor to generate the STL source. Select All blocks (or a defined subset) and confirm the source file name. Step 7 writes the source to the Sources folder of the S7 program.
  4. Alternatively, right-click the project S7 program > Generate source from blocks if a per-block export is preferred.
  5. Delete every block in the Blocks folder except system blocks (SFB, SFC, SDB, system data). The deletion removes both the offline copy in the PG and the online copy on the CPU after a download.
  6. Open the generated source file from the Sources folder, right-click and choose Compile. Step 7 recompiles the source and recreates the blocks in the Blocks folder in source order.
  7. Download the regenerated blocks to the CPU. Confirm in the online view that every block timestamp matches the offline timestamp. Mismatches indicate a download that did not complete.
Caution: Do not delete blocks by name and recreate them; the CPU will retain the original instance DB and the new block will be considered a "different" block, which causes instance-DB consistency errors at the next STOP-to-RUN transition. Always regenerate from a single source to keep the block-number-to-block-name mapping stable. The instance DB number is bound to the parent FB number; if the FB is renumbered, every consumer of the instance DB must be updated.

Diagnostic Procedure: When New Code Is Not Processed

  1. Read the diagnostic buffer. In SIMATIC Manager, target the CPU > Module Information > Diagnostic Buffer. Look for events with IDs in the 0x1xxx range (user program / memory events) and 0x9xxx (module events). An "OB not loaded" or "block not found" event points at work memory; an "MMC full" or "load memory overflow" event points at the MMC.
  2. Check work memory utilization. Module Information > Memory. Note both the absolute bytes used and the percentage. If utilization is greater than 90%, proceed to step 3 before adding code.
  3. Check load memory (MMC) free space. Same dialog. If load memory used is at or above the MMC's nominal size, the next download will be rejected or silently dropped.
  4. Verify block timestamps online vs offline. Right-click the Blocks folder > Compare blocks online/offline. Any block whose timestamp differs has not been downloaded correctly.
  5. Verify that the new code was actually called. In VAT (Variable Table) or a status watch, force a Boolean or integer at the entry of the new network and confirm that the next instruction changes it. If the value does not propagate, the block is loaded but not called. This is usually a multi-instance parenting or call-wiring problem.
  6. Check the S7-200 (or other DP slave) status bytes. The S7-200 on Profibus DP is a slave; the S7-300 reads its inputs via DP-V0 cyclic I/O. If the slave is in clear, the inputs are frozen. Step 7's slave diagnostics will show a slave in CLEAR or POWER-OFF state with a diagnostic event in the DP master.
  7. Check the communication load. CPU > Properties > Cycle / Clock Memory. Read the "Scan cycle load from communication" parameter; if it is at 20% (default) and the OB1 cycle time is rising, increase it to 50% only after confirming that the issue is communication, not user-program time.
  8. Check the Profibus diagnostics. In NetPro, right-click the DP master system > Diagnostics. Verify that every slave is in OPERATION and that no slave reports a diagnostic interrupt. A slave in CLEAR will not contribute inputs to the S7-300's process image even if the S7-300 program runs.
  9. Force a STOP-to-RUN transition. After correcting the issue, perform a STOP followed by RUN (MRES is not required unless you also want to clear retentive data). Confirm the diagnostic buffer entry "Restart (warm)" or "Restart (cold)" appears with timestamp matching the moment of the transition.

Diagnostic Buffer Event Reference (Selected IDs)

Event ID (hex) Meaning Memory-Side Cause Remediation
0x1xxx series User program / OB events OB not loaded, programming error, block not found Reload missing blocks; check OB85/OB86/OB121/OB122 setup.
0x2522 "MMC full" / "load memory overflow" Compiled project size exceeds MMC capacity Expand MMC to the next size up.
0x2523 "Work memory overflow" CPU work memory at 100% Refactor code, delete dead blocks, or migrate to a CPU with larger work memory.
0x3xxx series Module / Profibus events DP slave failure, station failure Check slave power, bus termination, slave diagnostics.
0x9xxx series Module status Module pulled, module failure Check physical module seating and backplane.

Verification Checklist

Check Pass Criteria How to Verify
Work memory utilization ≤ 85% after adding the new code. Module Information > Memory.
Load memory (MMC) free space ≥ 25% of MMC nominal size. Module Information > Memory > Load memory.
Block timestamp match (online vs offline) All blocks identical. Blocks > Compare blocks online/offline.
New code execution Status watch on first instruction of the new network changes when the input is forced. VAT / Monitor/Modify.
Diagnostic buffer No OB85, OB86, OB121, OB122 events for the new code. Module Information > Diagnostic Buffer.
Communication scan cycle load ≤ 50% of OB1 cycle time. CPU Properties > Cycle / Clock Memory.
Profibus slave state All slaves in OPERATION (green check in NetPro / HW Config). NetPro > DP master system > Diagnostics.
CP 343-1 connection state All S7 connections in ESTABLISHED. NetPro > S7 connection > Connection status.

Common Pitfalls

  • Reading "100% work memory" as "100% of the program is running". It is not. The CPU may be swapping blocks in and out of work memory on a per-call basis; a block that is loaded but not in the current scan window is not executing. The percent figure is a size measure, not a coverage measure.
  • Believing the simulator equals the CPU. S7-PLCSIM runs the project without the MMC and without the OS-level communication load. Code that runs in the simulator can still fail to load on a real CPU if the MMC is too small or if the OB1 scan load leaves no time for the new networks. Always validate on the real CPU after a PLCSIM pass.
  • Adding code to VAT only. A Variable Table is a monitoring and forcing tool. A change in a VAT does not become part of the executing program. New code must be added in the offline project's FC/FB blocks and downloaded to the CPU to take effect.
  • Confusing "MMC size" with "work memory size". The MMC is the load memory; it is not the same thing as work memory. Replacing the MMC with a larger one does not increase work memory, but it does allow the CPU to bring more blocks into RAM at startup. The two are decoupled.
  • Using multi-instance FBs without a parent call. A multi-instance FB that is never called by its parent has no effect on the scan. The instance data is allocated, but the action code never runs. A multi-instance that compiles and loads but is not called will not appear in the scan, which is the same "code added, nothing runs" symptom that motivates this article.
  • MRES without first archiving the MMC. MRES on a CPU 315-2 DP clears work memory and resets the MMC content. The project must be reloaded from the PG. Always archive the project to the PG (or to a memory card reader) before MRES.
  • Editing an FB that is used as a multi-instance without recompiling every parent. If a child FB's interface changes, the parent's instance data layout becomes invalid. Step 7 will not silently update the parent; the next download will fail with a "block consistency" error. Regenerate from STL source to force a clean rebuild.

Step-by-Step Recovery Procedure (Summary)

  1. Archive the current project to the PG. File > Archive or right-click the project > Archive.
  2. Read the MMC contents to the PG. PLC > Memory Card File > Read from Memory Card (or use an external MMC reader).
  3. In SIMATIC Manager, open the offline project. Go to Module Information > Memory on the online CPU and read both work memory and load memory percentages. Confirm that work memory is greater than 90% or load memory is greater than 90%.
  4. If load memory (MMC) is the bottleneck, replace the MMC with the next size up (256 KB minimum for a 128 KB work memory CPU). Read the new MMC, write the project to it, insert it into the CPU, and STOP-RUN.
  5. If work memory is the bottleneck, refactor: delete unused FBs/FCs/DBs, consolidate shared DBs, reduce instance DB count, move rarely called FBs to FCs.
  6. Re-check the diagnostic buffer. Confirm no 0x2522 (MMC full) or 0x2523 (work memory overflow) events appear after the change.
  7. Add the new code, compile, and download. Confirm block timestamps match online vs offline.
  8. Force a Boolean at the entry of the new code from a VAT. Confirm propagation to the next instruction in the new network.
  9. Re-check OB1 cycle time and communication load. The cycle time should fall back to nominal within 5-10 scans of the change.

FAQ

How much work memory can I use before new code stops running on a CPU 315-2 DP?

Plan to keep work memory below 85% utilization. Between 85% and 95% the CPU may refuse to load new blocks, and above 95% it may stop processing newly added code while still indicating RUN. The 100% line in Step 7's memory view is a hard ceiling, not a working headroom figure.

What MMC size do I need for a CPU 315-2 DP with 128 KB of work memory?

Use a 256 KB MMC as the minimum for a typical project. The compiled project is always larger than the in-RAM runtime image, so a 128 KB MMC is rarely enough to use the full 128 KB of work memory. For projects with heavy I/O, large DBs, or many instance DBs (for example 18 Profibus slaves with one SDB each), go to 512 KB or 1 MB.

Why does my new code run in PLCSIM but not on the real CPU?

PLCSIM does not enforce the MMC size, the OS-level communication load, or the work memory limit. A block that compiles and runs in PLCSIM can still fail to load on the real CPU if the MMC is too small or if the OB1 scan load leaves no time for the new networks. Always validate on the real CPU after a PLCSIM pass.

What is the maximum communication scan cycle load on the CPU 315-2 DP?

50% of the OB1 cycle time. The default is 20%. Increase it only if you can confirm that user-program time is the cause of cycle overruns; raising it past 50% is not supported and triggers OB80 (time error).

How do I rebuild an S7-300 project from STL source?

Open the block folder, press Ctrl + T to generate the STL source, delete every non-system block from the Blocks folder, open the source file from the Sources folder, and recompile. This rebuilds the project from one source file in a deterministic order and resolves online/offline block drift.

Why does my multi-instance FB never run?

The most common reason is that the parent FB that contains the multi-instance declaration is never called. Multi-instance FBs run only when their parent runs. Open the call tree (Options > Reference Data > Call Structure) and confirm the parent is on OB1's call path. If the parent is not called, no code inside it, including its multi-instance children, will execute.

Back to blog