Memory Decisions That Break Timing Guarantees: WCET and Time-Aware Allocation in Safety-Critical Firmware

Memory Decisions That Break Timing Guarantees: WCET and Time-Aware Allocation in Safety-Critical Firmware


A safety-critical embedded system that passes every functional test can still fail certification if its developers cannot demonstrate that the worst-case execution time of every safety-relevant task has been bounded and that those bounds are respected under all operating conditions. The correctness of an automotive brake controller or a medical infusion pump depends not only on computing the right answer but on computing it within the time budget the system was designed around. A control loop that produces a correct output 200 microseconds after its deadline has already failed, regardless of the numerical accuracy of its calculation.

Worst-case execution time is the maximum time a specific task can take to execute on a specific hardware platform under any combination of input values and system state. The word maximum is doing significant work in that definition. The WCET is not an average, not a typical maximum, and not the longest time observed during testing. It is the upper bound across every possible execution path, every possible cache state at entry, every possible memory access sequence — including the adversarial combination that testing almost certainly never exercised. The gap between observed execution time and true WCET is where real-time systems fail.

Memory management is the primary engineering domain where WCET violations originate in well-designed systems. The processor's behavior in executing arithmetic, logic, and control flow operations is largely deterministic and tractable to analysis. The behavior of the memory subsystem — cache hit and miss patterns, DRAM access latency variation, prefetcher behavior, bus contention — introduces timing variability that is difficult to bound tightly and easy to underestimate. Building embedded firmware that is time-aware at the memory management level is the practical requirement that ISO 26262 (automotive), DO-178C (avionics), and IEC 61508 (general functional safety) all create, even when they do not prescribe specific memory management techniques.

Why Memory Is the Primary Source of WCET Uncertainty

On a modern processor executing a tight computational loop from data already resident in L1 cache, the execution time is predictable to within a few percent. The same loop executing when data must be fetched from DRAM may take 50 to 200 times longer — the access latency of DDR4 SDRAM at 60 to 80 nanoseconds per access versus 1 to 3 nanoseconds for an L1 cache hit is the dominant determinant of whether a timing budget is met or violated.

This is not a hardware defect. Cache hierarchies exist because the average-case performance benefit of caching is enormous, and processors are designed around average-case workloads. The problem for safety-critical real-time systems is that cache behavior is history-dependent: whether a specific memory access is a cache hit or miss depends on what other memory accesses have occurred since the cache was last populated. In a system running multiple tasks, a task that finds its working set in cache will execute much faster than the same task executing after a different task that evicted its data. The WCET of the first task is determined by the cache miss case, but the average-case execution time is much lower if cache hits are common. Analysis that relies on observed execution times captures the average; certification requires the worst case.

Three specific memory subsystem phenomena produce the largest WCET uncertainty in typical safety-critical embedded systems:

Cache eviction conflicts. When two tasks or two code paths compete for the same cache set — because their memory addresses alias to the same cache index bits — one evicts the other's data every time it executes. The victim task then experiences cache misses that would not occur if the other task ran less frequently or its data were located at different addresses. This conflict is invisible during single-task testing and emerges only when the tasks are exercised in the specific interleaving where conflicts are worst.

Branch prediction state. Modern processors predict the taken/not-taken direction of conditional branches and pipeline instructions ahead of the actual branch resolution. When the prediction is wrong, the pipeline is flushed and restarted from the correct path, adding cycles equal to the branch misprediction penalty — typically 10 to 20 cycles on a modern pipeline. The misprediction rate depends on the pattern of branch execution, which depends on the input data. A task that rarely executes a particular branch in normal operation may encounter it on every invocation under the specific input combination that defines the WCET path.

DRAM refresh stalls. DDR SDRAM must periodically be refreshed to maintain stored charge, and the memory controller pauses normal access operations during the refresh cycle. The timing of refresh events relative to a specific task's memory accesses is non-deterministic and can extend access latency by one to several refresh cycle durations. On processors with DRAM refresh intervals that can coincide with safety-critical access patterns, the refresh latency must be included in the WCET bound but is frequently overlooked in analysis that focuses on cache behavior while treating DRAM access as having uniform latency.

 

Can your firmware still meet timing guarantees under worst-case memory behavior?


Scratchpad Memory — Predictability by Design

The architectural response to cache-induced WCET uncertainty that has the most direct engineering impact is scratchpad memory. A scratchpad is a small, fast on-chip SRAM whose contents are managed entirely by software, with no hardware-managed replacement or eviction policy. Every byte in the scratchpad is there because the firmware explicitly put it there, and every access to scratchpad has a fixed, known latency — typically one to four clock cycles depending on the SoC design.

This predictability is the property that makes scratchpad valuable for safety-critical real-time firmware: the WCET contribution of a scratchpad access is fixed regardless of task history, interrupt preemption, or concurrent execution on other cores. A loop that executes entirely from scratchpad-resident code and data has a WCET equal to the sum of its instruction execution times plus fixed-latency scratchpad accesses, with no cache miss uncertainty contributing to the bound.

The engineering challenge with scratchpad is that it is limited in size — typically 16 KB to 256 KB on microcontrollers used in safety-critical applications — and must be managed explicitly. The compiler cannot automatically manage scratchpad the way hardware manages a cache. The firmware developer must decide which code and data live in scratchpad permanently and which are loaded on demand.

Static scratchpad allocation assigns the most timing-critical code and data to scratchpad at compile time. The allocation problem is to select which functions, global data structures, and frequently-accessed arrays benefit most from scratchpad placement, given the size constraint. WCET-directed allocation algorithms formulate this as an integer linear programming problem: which subset of memory objects, when placed in scratchpad, minimizes the WCET of the most critical task, subject to the scratchpad capacity constraint. Research results on realistic automotive and avionics benchmarks demonstrate WCET reductions of 50 to 80 percent from optimal static scratchpad allocation compared to cache-based execution, because the analysis can guarantee hit latency rather than being forced to assume miss latency for conservatism.

Dynamic scratchpad management extends this approach to programs whose working sets exceed the scratchpad capacity by loading different code or data sections into the scratchpad at runtime using DMA transfers. The DMA transfer itself has a known latency and can be scheduled to overlap with computation — the processor continues executing from one part of the scratchpad while the DMA engine populates another region with data needed for the next computation phase. The WCET impact of DMA transfers must be accounted for in the timing model: the analysis must bound the worst-case DMA transfer time and verify that the control flow cannot require DMA-resident data before the transfer completes.

Cache Locking and Partitioning — Managing Cache Without Abandoning It

Complete migration of safety-critical code to scratchpad is not always feasible due to the size constraints. The alternative that preserves cache hardware while restoring timing predictability is cache locking: reserving specific cache lines for specific memory objects and preventing the hardware replacement policy from evicting those lines.

Locked cache lines always produce cache hit latency for the locked addresses, regardless of the access history on other memory regions. The firmware explicitly writes the critical code or data into specific cache lines at the appropriate moment in the execution sequence and then locks those lines until they are no longer needed. WCET analysis treats locked lines as guaranteed hits, eliminating the worst-case miss latency contribution for those accesses from the timing bound.

Cache partitioning divides the cache into disjoint regions, each assigned to a specific task or task group. When task A's partition holds task A's working set and task B's partition holds task B's working set, neither can evict the other's data regardless of execution interleaving. The WCET of each task can be computed as if the other tasks do not exist from a cache perspective, dramatically reducing the pessimism of the worst-case bound.

Both locking and partitioning require hardware support: the processor must expose mechanisms to write to specific cache sets and ways and to prevent eviction of locked lines. ARM Cortex-R processors used in automotive safety applications include cache lockdown registers for exactly this purpose. Many automotive-grade microcontrollers from Renesas, NXP, and Infineon in the AURIX family include cache locking mechanisms as first-class features specifically to support safety-critical software development.

The engineering discipline required to use cache locking effectively is substantial. The developer must identify the critical memory regions whose WCET contribution must be bounded, determine when they need to be locked (during initialization, at task entry, at specific program points), manage the limited number of lockable cache ways without interfering with the general-purpose cache behavior needed by non-critical code paths, and validate that the locking strategy achieves the WCET reduction assumed in the timing analysis. The interaction between cache locking decisions and WCET analysis tools must be explicitly modeled: a WCET analysis that does not know which lines are locked will make conservative assumptions that may significantly overestimate the actual WCET.

Dynamic Memory Allocation — Why malloc Is Incompatible with Hard Real-Time

Dynamic memory allocation from a heap — the malloc/free model familiar from general-purpose software — is incompatible with hard real-time systems as a design principle, not merely as a coding guideline. The incompatibility operates at two levels.

The first level is allocation latency. Heap allocators must search for a free block of the requested size, which involves traversing a free list of variable length depending on the allocation history. The worst-case execution time of malloc is proportional to the number of free blocks in the heap, which varies at runtime. A program that calls malloc at any point in a safety-critical execution path has an execution time that depends on the state of the heap accumulated from all prior allocations and deallocations throughout the program's execution — a dependency that cannot be bounded by static analysis and that produces WCET estimates that are either so conservative as to be useless or optimistically wrong.

The second level is fragmentation-induced failure. After a long sequence of allocations and deallocations of varying sizes, the heap may contain sufficient total free space to satisfy a new allocation request but no contiguous free region of the required size — a condition called external fragmentation. In a hard real-time context, this allocation failure is a timing violation of the worst kind: the task fails to execute at all rather than executing slowly. Certification standards for safety-critical systems require demonstrating that the system meets its timing requirements under all operating conditions; an allocation failure that occurs only after a specific sequence of several thousand prior operations is precisely the kind of adversarial combination that WCET analysis is designed to expose.

The practical engineering response is to prohibit dynamic heap allocation entirely in safety-critical execution paths and use static allocation patterns instead. All memory objects needed by the safety-critical execution path are allocated at system initialization, their lifetimes extend to the end of the mission, and their WCET contribution is fixed and analyzable. This is codified as a specific requirement in DO-178C for safety-critical avionics software and is strongly implied by the timing analysis requirements of ISO 26262 ASIL C and D software.

Where variable-lifetime objects are genuinely necessary, fixed-size memory pools provide a bounded-time alternative to malloc. A pool contains a fixed number of objects of identical size, allocated from a pre-allocated array. Allocation time is bounded — typically O(1) with a free list implementation — and fragmentation is eliminated because all objects have the same size. The WCET of pool allocation is analyzable and small. The tradeoff is that pool capacity must be statically determined: the pool size must accommodate the maximum concurrent live object count, which requires analysis of the execution model.

Stack Management and Overflow Prevention

The call stack is the memory region whose WCET impact is most frequently underestimated in embedded systems development because it grows and shrinks dynamically at runtime in response to function calls and returns. Every function call pushes a stack frame; every return pops it. The maximum stack depth — and thus the maximum memory address the stack will ever write — is determined by the deepest call chain the program can execute, including chains that only occur under specific input combinations.

Stack overflow — when the stack pointer reaches and writes past the boundary of the allocated stack region — is a catastrophic failure mode in safety-critical systems. The write corrupts data in adjacent memory regions, which in embedded systems with fixed memory maps typically means corrupting global data or program code. The resulting behavior is undefined, unpredictable, and produces failure modes that are extremely difficult to diagnose because the root cause (stack overflow) manifests as apparent corruption of unrelated data or code.

WCET analysis tools that model stack behavior produce bounds on stack depth as a byproduct of the call graph analysis required for execution time estimation. These bounds, when accurate, allow the firmware developer to verify that the stack allocation is large enough to accommodate the worst-case stack depth with a defined margin. When the static analysis cannot bound the stack depth — because recursive calls or indirect function calls through function pointers prevent static traversal of the complete call graph — the firmware should prohibit these patterns in safety-critical code.

Two hardware mechanisms support stack overflow detection when software constraints are insufficient. Memory Protection Unit (MPU) configurations can mark the guard region below the stack as no-access, causing a hardware fault on the first overflow write rather than allowing silent corruption. Stack pointer monitoring features available on some Cortex-M and Cortex-R processors detect when the stack pointer crosses a configured watermark and generate an interrupt before overflow occurs. Combining static stack depth analysis with MPU-based runtime protection provides defense in depth: the static analysis proves that overflow does not occur under analyzed conditions, and the hardware protection catches overflow that occurs under conditions the static analysis did not model.

 

modular-hardware-architecture


Multicore Memory Interference — The New WCET Frontier

Safety-critical embedded systems in automotive, avionics, and industrial automation are increasingly moving to multicore processors to meet computational demands that single-core processors cannot satisfy within the available power and area budget. The transition to multicore introduces a new category of WCET uncertainty that is more difficult to analyze than single-core cache behavior: inter-core memory interference.

On a multicore SoC, all cores share the DRAM interface and typically share at least the last level of cache. When two cores execute concurrently, the memory requests from both cores compete for the shared DRAM bandwidth. The time a memory request waits in the memory controller queue before being serviced — the memory access latency seen by the requesting core — depends on how many other requests are in the queue from other cores. In the worst case, all other cores are simultaneously generating maximum memory traffic, and the requesting core's access is delayed by the combined queuing time. This worst-case contention latency can be many times the nominal memory access latency, and it depends on the execution behavior of all other cores — not just the task being analyzed.

DO-178C guidance for multicore processors (CAST-32A in the US) and the corresponding ARP4968 document for avionics require either demonstrating that interference paths between cores do not affect safety-critical software or providing specific interference mitigation evidence. ISO 26262 Part 9 (Automotive safety integrity levels) addresses processor-related issues including multi-core and requires analysis of the interaction between software running on different cores. IEC 61508:2010 Part 3 similarly requires that timing constraints are met with appropriate rigor for the target safety integrity level.

The practical engineering responses to multicore WCET interference fall into several categories. Spatial isolation — assigning safety-critical tasks to dedicated cores with exclusive access to specific DRAM regions and cache partitions — eliminates interference by architectural separation. Memory bandwidth throttling — configuring the memory controller to cap the bandwidth allocated to each core — converts the non-deterministic worst-case contention scenario into a bounded worst-case delay determined by the throttle configuration. Both approaches impose overhead: spatial isolation reduces utilization of the hardware resources not assigned to the safety-critical partition, and bandwidth throttling reduces average-case memory performance. The WCET bound improves at the cost of average throughput.

The interaction between multicore interference analysis and WCET tools is an active area of standards development. LDRA, AbsInt, and Rapita Systems offer static and hybrid WCET analysis capabilities that are increasingly addressing multicore interference modeling, though comprehensive automated multicore WCET analysis for realistic SoC designs with complex memory controller behavior remains a challenging problem where manual analysis augments automated tooling.

Time-Aware Memory Layout — What the Linker Script Decides

The linker script that places code and data sections into the embedded system's memory map makes timing decisions that most embedded developers do not recognize as timing decisions. Where a function body lives in the processor's address space determines which cache sets it maps to. Two functions that execute in sequence on the same task will cache-conflict with each other if their addresses alias to the same cache set, even if each function individually fits in cache.

WCET-aware memory layout analysis tools examine the control flow graph of the program, identify which functions are likely to execute in the same cache occupancy window, and suggest or automatically generate linker script configurations that minimize cache set conflicts for the critical paths. This is a compile-time optimization with runtime timing impact: changing the address of a function by padding its alignment by a few bytes can shift it to a different cache set and eliminate a conflict that otherwise contributes to WCET.

The same principle applies to data layout. Stack frames and frequently accessed global arrays that are accessed in the same loop iteration should be placed at addresses that use different cache sets, preventing stack writes from evicting the array data accessed in the same iteration. The compiler's default data layout decisions optimize for packing and alignment without regard for cache set conflicts; WCET-aware layout requires either compiler analysis that models cache behavior during layout or post-processing tools that identify and resolve conflicts in the final binary.

This level of memory layout attention is required for the tightest timing budgets — typically ASIL D or DAL A software where timing margins are narrow and every microsecond of WCET reduction is valuable. For systems with looser timing margins, scratchpad allocation of the most critical functions and conservative WCET budgeting provide an adequate engineering approach without the complexity of cache-set-aware layout analysis across the entire program.

Quick Overview

WCET violations in safety-critical embedded systems originate primarily in memory subsystem behavior: cache miss latency variation, branch misprediction state, DRAM refresh stalls, and in multicore systems, inter-core memory interference at the shared memory controller. Time-aware memory management uses architectural choices and allocation strategies that replace unbounded worst-case memory latency with fixed or bounded latency: scratchpad memory for software-managed on-chip SRAM with fixed access time, cache locking to reserve specific lines for safety-critical data, static allocation patterns that eliminate heap-induced timing uncertainty, and cache partitioning or spatial isolation to bound multicore interference. ISO 26262, DO-178C, and IEC 61508 all require WCET evidence for safety-critical tasks, making memory timing behavior a certification concern rather than only a performance concern.

Key Applications

Automotive brake, steering, and powertrain control software at ASIL C and D safety integrity levels requiring ISO 26262-compliant WCET evidence, avionics flight control and engine management software at DO-178C DAL A and B requiring CAST-32A multicore compliance, medical device firmware for infusion pumps and respiratory equipment at IEC 62304 Class C, industrial safety controller firmware at IEC 61508 SIL 3, and any safety-critical embedded system transitioning from single-core to multicore where inter-core interference analysis is required for recertification.

Benefits

Scratchpad allocation eliminates cache-miss uncertainty for the most timing-critical code and data, reducing WCET bounds by 50 to 80 percent for well-characterized workloads compared to cache-based execution under worst-case miss assumptions. Static allocation patterns with prohibition of heap use in safety-critical paths make WCET analysis tractable — execution time becomes a function of control flow and instruction timing rather than runtime state. Cache locking provides bounded-latency access without requiring explicit DMA management, making it a lower-complexity alternative to scratchpad for systems with hardware lockdown support. Multicore bandwidth throttling converts non-deterministic contention into bounded-latency contention, enabling provable WCET analysis across cores.

Challenges

Scratchpad is limited in size and requires explicit management that the compiler cannot fully automate, increasing firmware developer burden for performance-critical code paths. Cache locking reduces available cache ways for general-purpose code, which may degrade average-case performance of non-safety-critical functions that cannot use the locked region. Multicore WCET analysis for realistic SoC memory controller behavior remains an open problem where manual analysis augments automated tooling, and the required evidence for certification is still being standardized across regulatory bodies. Static analysis WCET tools are conservative and may produce bounds 30 to 100 percent above the true WCET, requiring time budget headroom that constrains task density.

Outlook

The pressure on safety-critical embedded systems to use multicore processors for computational density — driven by ADAS, electric vehicle software-defined architectures, and modern avionics — is the primary force driving continued development of multicore WCET analysis tools and techniques. CAST-32A compliance frameworks for avionics and the evolving ISO 26262 guidance for multicore automotive processors are creating regulatory pressure to formalize multicore interference analysis as a required certification artifact. Hybrid WCET analysis approaches combining static analysis with measurement-based validation on target hardware are increasingly adopted in practice because they produce tighter bounds than pure static analysis while providing safety margins over pure measurement approaches.

Related Terms

WCET, worst-case execution time, BCET, best-case execution time, scratchpad memory, SPM, cache locking, cache partitioning, DMA transfer, static allocation, heap allocation, malloc, memory pool, stack overflow, MPU, memory protection unit, ISO 26262, DO-178C, IEC 61508, ASIL, DAL, CAST-32A, ARP4968, multicore interference, DRAM refresh stall, branch misprediction, cache eviction conflict, ILP, integer linear programming, real-time scheduling, rate monotonic scheduling, schedulability analysis, abstract interpretation, aiT, Rapita Systems, LDRA, AbsInt, OTAWA, Mälardalen benchmark suite, MiBench, Cortex-R, AURIX, cache set conflict, linker script, memory layout

 

 

Our Case Studies

 

FAQ

Why is dynamic heap allocation prohibited in safety-critical real-time embedded software?

 

Heap allocators such as malloc have execution times that depend on the state of the heap accumulated from prior allocations, which makes their worst-case execution time unbounded by static analysis. Additionally, heap fragmentation can cause allocation failure at runtime when sufficient total free space exists but no contiguous block of the required size is available. Both properties are incompatible with hard real-time systems that require provable worst-case timing bounds for all safety-critical execution paths. Static allocation at system initialization or fixed-size memory pools with O(1) allocation time are the certified alternatives.
 

What is scratchpad memory and why does it improve WCET bounds compared to cache?

 

Scratchpad memory is a small, fast on-chip SRAM whose contents are managed entirely by software, with no hardware replacement or eviction policy. Every access to scratchpad has a fixed, known latency regardless of execution history, cache state, or concurrent activity on other cores. Cache accesses, by contrast, may be hits or misses depending on prior access patterns, and the worst-case WCET analysis must conservatively assume cache misses for accesses that cannot be proven to be hits. Placing safety-critical code and data in scratchpad eliminates this uncertainty: WCET analysis treats every scratchpad access as having fixed latency, producing tighter bounds than cache-based analysis.
 

How does multicore processor execution introduce WCET uncertainty that single-core analysis does not face?

 

On a multicore SoC, all cores share DRAM bandwidth and typically share the last-level cache. When safety-critical tasks on one core execute concurrently with tasks on other cores, memory requests from all cores queue at the shared memory controller. The waiting time before a request is serviced depends on the volume of competing requests from other cores. In the worst case, all other cores simultaneously generate maximum traffic, dramatically extending memory access latency. This inter-core interference is not present in single-core analysis and requires either architectural isolation, such as dedicated memory regions per core, bandwidth throttling that caps per-core DRAM bandwidth, or explicit interference analysis that bounds the worst-case contention delay.
 

What is cache locking and when is it appropriate in safety-critical firmware?

 

Cache locking reserves specific cache lines for specific memory objects and prevents the hardware replacement policy from evicting those lines. Locked addresses always experience cache hit latency, regardless of access history or concurrent activity. Cache locking is appropriate when the processor includes lockdown registers that support it and when the safety-critical code or data is small enough to fit in the lockable portion of the cache. It provides bounded-latency memory access for locked regions without requiring the firmware developer to manage explicit DMA transfers as scratchpad requires. ARM Cortex-R and many automotive-grade microcontrollers from Renesas and Infineon support cache locking as a dedicated safety feature.