Cortex-M4F Lazy FPU Stacking: Budget the First Floating-Point Instruction in an ISR

An interrupt can enter promptly yet encounter deferred floating-point context-saving work later, at its first FPU instruction. Measuring only the first GPIO transition inside the handler can miss that cost. Qualify the complete deadline-critical path under both floating-point-active and inactive interrupted contexts.

This guide concerns Cortex-M4 processors with the optional FPU, commonly called Cortex-M4F, using automatic floating-point state preservation. The architectural reference is Arm Application Note 298, DAI0298A, released 16 March 2012. The concrete RTOS example is FreeRTOS Kernel V11.1.0, GCC ARM_CM4F port. It does not establish timing for another Cortex-M core, compiler port, memory system or silicon revision.

Locate the deferred work in the execution path

With automatic and lazy preservation enabled, an active floating-point context causes exception entry to reserve stack space for floating-point state. The actual register stores can be deferred until a handler executes an FPU instruction. If no handler requires that preservation before return, the reserved area need not be populated. Arm AN298 describes the relevant FPCCR controls and distinguishes reserved storage from saved register contents.

This produces two separate engineering questions: when is the deadline-sensitive action reached, and how much stack space must remain valid? Deferring memory writes does not make the reservation disappear. Conversely, a larger reserved frame does not prove that all floating-point stores occurred during interrupt entry.

Conditional lazy-FPU sequence: an active interrupted FP context reserves stack space at exception entry, then the first ISR FP instruction triggers preservation before the deadline-critical action.
Conceptual order only, not a cycle-scaled waveform. The deferred-save branch requires an active interrupted floating-point context and lazy preservation.

Freeze the build and inspect the emitted instructions

Record the exact MCU and revision, FPU availability, clock tree, executable and stack memory locations, compiler version, optimization settings, floating-point ABI and RTOS port. Keep the linked image and disassembly alongside the timing record. Source code alone is not enough to identify the first floating-point instruction on every path.

For GCC 14.3, softfp permits hardware floating-point instructions while retaining soft-float calling conventions; hard permits them with FPU-specific calling conventions. Soft requests library calls for floating-point operations. GCC also documents a general-register-only option, with an explicit limitation for assembler code. These are compiler controls, not guarantees about an entire call graph. See the versioned GCC ARM options.

Walk every function reachable before the critical output. Include error handling, conversion helpers, logging and library routines. Mark the first actual FPU instruction in each path. An apparently integer-only wrapper can call code built with different options; an apparent arithmetic expression can be optimized away. Inspect the final linked binary rather than a convenient intermediate assembly file.

Verify who owns the preservation policy

Read the policy after startup and after the scheduler begins. The FreeRTOS V11.1.0 GCC ARM_CM4F port enables the automatic/lazy preservation bits during scheduler startup and conditionally saves high floating-point registers in PendSV. That is a versioned implementation fact, visible in the official port source; it must not be generalized to every FreeRTOS port.

A board-startup write is not necessarily the final policy. Trace later initialization, library startup and any diagnostic code that touches FPU control. If an experiment compares lazy with eager preservation, make the change in a reviewed test build with a compatible context-switch design. Do not clear both automatic and lazy preservation controls as a casual latency optimization: that changes who is responsible for protecting floating-point state.

The aim is not to choose a universally “faster” policy. Eager preservation can move required work earlier, while lazy preservation can avoid unnecessary work. Select a policy only after the full interrupt deadline, context integrity and stack requirements are demonstrated for the intended workload.

Use a context-sensitive measurement matrix

The following is a proposed target test plan, not a set of measured results. Begin with a controlled interrupt source and an independently observable critical output. Use production-equivalent memory placement and optimization. Establish the overhead and ordering of any instrumentation before interpreting small timing differences.

  1. Inactive context, no ISR FPU use: create a controlled non-FP execution path and verify its context state. This is a baseline, not the worst-case claim.
  2. Active context, no ISR FPU use: execute a verified FP operation before the interrupt, then follow a handler path without FP instructions.
  3. Active context, early ISR FPU use: exercise the real first FP instruction before the deadline-critical action.
  4. Active context, late ISR FPU use: trigger the path where conversion or error handling introduces FP work later in the handler.
  5. Nested handlers: exercise relevant nesting with and without FP use in the preempted and preempting handlers. Record the actual entry sequence.
  6. Scheduler boundary: include the relevant interrupt-to-task transition and subsequent context switch when the product deadline includes that path.

Measure interrupt assertion to the first handler observation, assertion to the required action, and completion of the relevant return or task handoff. A GPIO set near handler entry measures only the first interval. A second mark near the output can reveal movement of work within the handler, but its own instructions must not alter the path being investigated.

Do not assume “this task does not currently calculate floats” means its floating-point context is inactive. Establish the state deliberately in the test setup and record it using an observation method that does not itself introduce FPU instructions. Keep genuine background execution and a controlled baseline as separate cases.

Check stack reservation and preservation integrity together

Map which stack contains the interrupted context and which stack subsequent handlers use. Include relevant nesting, alignment, compiler saves and RTOS context-switch storage in the review. A single fixed byte allowance copied from an unrelated project cannot establish the budget.

Arm’s architectural mechanism automatically handles the low floating-point register context, while software has additional responsibilities for other registers during context switching. The exact port source is therefore part of the evidence, not merely an implementation detail. Verify preserved FP values after repeated preemption and task switches as well as timing; a fast interrupt that corrupts the resumed calculation is a failed result.

Hypothetical example: an added conversion moves the deadline

Consider a hypothetical actuator controller whose ISR acknowledges a peripheral, then evaluates a diagnostic threshold before updating an output. The original threshold path uses integers. A later change calls a floating-point conversion helper. Entry-marker timing remains similar, so the first regression test reports no problem.

The revised test interrupts a task after verified FPU use and observes the actual output transition. Disassembly identifies the helper’s first FP instruction before that output. This gives a concrete hypothesis: deferred preservation now lies inside the deadline path. It does not yet establish the size of the delay, which requires measurement on the selected MCU and memory configuration.

Possible responses include moving nonessential conversion after the required action, deferring it to a task, or qualifying a different preservation policy. Each response needs a fresh linked-image review and context-sensitive test. Close the investigation with the worst observed case, test coverage and remaining uncertainty, rather than a universal cycle claim.

Similar Posts