oss

F Prime gives flight software a typed wiring harness. The clock is still yours

11 sources 8 primary sources September 7, 2026

Text
NASA's Ingenuity Mars Helicopter stands on the rocky surface of Mars, its dusty solar panel and paired rotors seen by the Perseverance rover.

Ingenuity on Mars on April 16, 2023, photographed by Perseverance's Mastcam-Z camera from about 23 meters away. The vehicle ran F Prime; the photograph anchors the distinction between a reusable framework and the mission-specific application built around it. Photograph: NASA/JPL-Caltech/ASU/MSSS.[7][9]

F Prime is easiest to misunderstand as a box of Mars-proven C++ that can make an embedded project “flight software.” Its more consequential product is a typed wiring harness. An FPP model names components, the ports through which they may interact, and the topology that connects particular instances. Generated code turns those declarations into interfaces and deployment machinery. But the topology establishes who may call whom; it does not prove that a call will finish before the physical system needs its answer.

That distinction is especially visible in F Prime 4.3.0. The August 2026 release began modeling deployments as FPP systems, added an option for faster and more memory-efficient direct port calls, and expanded timing visibility in passive rate groups. Those are meaningful improvements to the framework's structural and measurement tools. They do not choose a mission's rates, thread priorities, queue depths, processor, worst-case workload, or response to stale sensor data.[4]

The system becomes easier to inspect when three contracts that are often collapsed into one are separated: the model contract, which makes interfaces and wiring checkable; the execution contract, which determines where a port handler runs; and the time contract, which turns a clock tick into scheduled work. F Prime helps engineers state all three. Only the mission can demonstrate that the assembled system is safe enough for its environment.

The Mars pedigree is a reference point, not a certificate

F Prime, also written F′, was architected at NASA's Jet Propulsion Laboratory in 2013 and released as open source in 2017. Before Ingenuity, it flew on the ISS-RapidScat instrument and the ASTERIA CubeSat. NASA describes it as a reusable, multi-mission framework for small spacecraft and instruments, supplying common services such as commanding, telemetry, parameters, and sequencing.[7]

Ingenuity made that lineage vivid. The little helicopter had to execute away from immediate human control, on commercial-class computing hardware, in an environment no test chamber could reproduce in full.[11] In a preflight interview, operations lead Tim Canham said its guidance loops ran at 500 hertz while image features were processed at 30 hertz. He also drew a careful autonomy boundary: Earth supplied a planned trajectory, while onboard software kept the craft on that trajectory and could abandon a flight when required sensor data became unhealthy.[8]

Those numbers are Ingenuity's requirements, not defaults bestowed by F Prime. The framework supplied an architecture in which reusable services and project-specific control code could be composed. It did not invent the aerodynamic model, select the sensor-fusion cadence, validate the Snapdragon board, or decide that landing was the safe response to a failed sensor. The open repository is therefore evidence that a framework with these constructs has flown; it is not a transferable qualification package for whatever a new user connects to them.

The cover photograph reinforces the boundary. It shows real hardware after two years on Mars: dust on the solar panel, rotors exposed to the atmosphere, a physical vehicle whose software competed for power and time while acting through imperfect sensors and actuators.[9] F Prime can make that software's structure legible. The world outside the ports remains the mission's problem.

Contract one: FPP makes architecture a build input

F Prime decomposes an application into components. A component owns a bounded piece of behavior and exposes typed ports; it should not reach into another component through an undeclared side channel. A topology instantiates components and connects compatible output and input ports. In the usual deployment, that topology is compiled into one binary, while commands, telemetry channels, events, and parameters declared by the components contribute to the ground-system dictionary.[1][2]

FPP—F Prime Prime—is the modeling language for those declarations. Its toolchain performs semantic checks and generates target artifacts including C++ and JSON. The generated component base class contains framework-facing plumbing; the developer derives from it and implements the mission behavior. This is more than boilerplate removal. The model becomes reviewable source: a code reviewer can see that a sensor component emits a particular type, that only named consumers receive it, and that a deployment includes one specific instance rather than discovering peers at runtime.[3]

Static, typed wiring eliminates useful classes of ambiguity. A mismatched port type can fail during generation or build rather than becoming a malformed packet in flight. Renaming or removing an interface creates a visible integration break. A simulation deployment can replace a hardware-facing component while retaining the same port contract. F Prime's own architecture account says Ingenuity development used 11 topologies that converged on the flight deployment, allowing shared components to run in different test venues.[1]

But type agreement is deliberately narrow. Two ports can agree that a value is a 32-bit integer while disagreeing about units, reference frame, freshness, saturation behavior, or whether zero means “valid reading” or “sensor unavailable.” A topology can prove that a command has a route without proving that the receiver is in a legal operational state. Generated code preserves the declared contract; it cannot repair an incomplete one.

Version 4.3.0 makes the same point from another direction. A deployment topology now needs to be marked as a deployment, and an FPP system identifies that deployment in the model. The release also permits generated direct port calls to avoid some invocation overhead.[4] Both changes bring more of the built system under explicit tooling. Neither makes a synchronous chain short, an asynchronous queue fresh, or a direct call harmless. To know those things, the reviewer has to read the second contract.

Contract two: a port chooses where the work happens

“Port” sounds like a message channel, but its input kind carries an execution decision. A synchronous input behaves like an ordinary function call: its handler runs immediately on the invoking component's thread and may return data. A guarded input is also synchronous, but all guarded calls into that component share a mutex. An asynchronous input serializes the invocation into the receiving component's queue; it cannot return a result through the same call.[2]

Components supply the other half of that choice. A passive component has neither thread nor queue, so its work runs in the caller's context. An active component has both and dispatches asynchronous work on its own thread—even though any synchronous or guarded inputs still run on the invoker's thread. A queued component has a queue but no thread; some synchronous activity, commonly a rate-driven call, must deliberately drain it.[2]

This vocabulary makes latency ownership inspectable. Put a slow device operation behind a synchronous port and the caller inherits the delay. Add a guarded port and the design gains mutual exclusion along with the possibility of contention or a re-entrant deadlock. Move work to an asynchronous input and the caller is released, but the system acquires queue sizing, overflow policy, ordering, service rate, and data-age questions. “Active” does not automatically mean isolated, because one synchronous input can still execute inside another component's supposedly protected schedule.

The useful review question is therefore not “Are these components decoupled?” It is “Where does this invocation execute, what can block it, and what happens to the information while it waits?” F Prime's current design guidance places cyclic work with hard deadlines primarily on synchronous rate-driven paths, event-driven work on asynchronous paths, and background work on lower-priority asynchronous paths. It also warns that real designs may depart from those patterns and must justify the departure.[2][10]

Contract three: rate groups turn ticks into obligations

Embedded software needs periodic work: read a sensor, update a controller, collect telemetry, check health. F Prime represents that rhythm with rate groups. A system-supplied clock source drives a RateGroupDriver; configured divisors produce slower ticks; active or passive rate-group components invoke their connected Sched ports in a defined order.[5]

A passive rate group executes in the clock caller's context. Its children run sequentially, making the critical path easy to describe but allowing one long handler to delay everything after it. An active rate group receives its tick asynchronously and wakes its own thread. That reduces blocking at the clock source and lets groups compete under the operating system scheduler, but it introduces dispatch jitter and makes thread priorities part of the timing argument. Its ordered sends do not guarantee that all child work finishes in the same order: when a member's Sched input is asynchronous, an active child receives the work on its own queue, where a backlog can outlive the rate-group dispatch that created it.[2][5]

An active rate group detects a slip when a new cycle arrives before its preceding dispatch completes and emits a warning. That alarm does not by itself reveal unfinished work already sitting in active child queues. Current passive-rate-group telemetry can expose whole-cycle time, per-port time, and high-water marks; 4.3.0 extended this measurement surface.[2][4][5] These signals are valuable because they turn missed assumptions into operator-visible evidence. They are still observations of executions that occurred. A clean high-water mark from nominal bench tests is not a proof of worst-case execution under cold hardware, maximum bus traffic, a full queue, error logging, and a simultaneous recovery action.

Ingenuity's reported 500-hertz guidance loop makes the timing pressure concrete: one period is only two milliseconds. The public interview does not map that loop to a particular F Prime rate group, so it should not be read as a topology claim.[8] In any design that assigns such work to a rate-group path, F Prime can carry the tick and make each scheduled edge explicit. The mission still has to budget the complete path on the actual processor, including synchronous callees, locks, cache effects, drivers, interrupts, and interference from active components. At a slower rate the numbers change; the obligation does not.

A test topology preserves interfaces, not physics

The same explicit connections that make a flight deployment reviewable also make substitution practical. A project can wire a simulated bus or sensor into the ports used by a flight driver, exercise component logic on a workstation, and preserve the mission-facing interface as hardware arrives. F Prime generates a component test harness that mirrors its ports, records output-port, event, telemetry, and command-response histories, and supplies parameter and time test values. Its own testing guide separates that unit work from integrated-system testing and asks tests to trace back to component requirements.[6]

That is a strong development loop, but the seam must remain visible. A fake sensor with the right output type may not reproduce bus arbitration, DMA behavior, timing jitter, electrical resets, or a device that returns an old sample with a valid status bit. A desktop topology may have abundant memory and a scheduler unlike the target RTOS. Even high coverage of component code does not establish which combined system states were reached; the F Prime guide explicitly distinguishes line coverage from state and path coverage.[6]

Ingenuity's team used simulation extensively, then tested physical prototypes in a vacuum chamber to identify where the model differed from the vehicle. Some conditions still could not be reproduced together—Mars atmosphere and Mars gravity among them—so validated pieces were recombined in simulation and exercised with repeated perturbations.[11] That is the right lesson to transfer. Reusable architecture makes it cheaper to build many truthful test venues. It does not make any one venue the truth.

What an adoption pilot should actually prove

F Prime fits best when a team needs a statically composed embedded system, values generated command-and-telemetry infrastructure, and has enough operational maturity to own timing and fault analysis. A useful pilot should use one real sensor-to-actuator or sensor-to-downlink path, not stop at the tutorial's build success.

First, reviewers should be able to trace that path through the FPP topology and label every crossing as synchronous, guarded, or asynchronous. For each active instance, the deployment should record queue depth, stack size, priority, CPU affinity where relevant, and the policy when work cannot be accepted. For each synchronous chain, the time budget should include every downstream handler that runs on the original caller.

Second, the team should run the intended rate groups on target-class hardware with nominal, peak, and deliberately faulty inputs. Capture cycle and per-port high-water marks, queue occupancy or overflow events, command latency, and the age of data at consumption. Then force the uncomfortable combinations: a slow device beside maximum telemetry, a recovery command during cyclic work, and a fault path that emits more logging than nominal operation.

Third, the pilot needs a stated safe response for missed time, not merely an alert. A rate-group slip may mean hold last output, enter a safe state, restart one component, reset the processor, or stop an actuator; that choice comes from the system hazard analysis. Likewise, a full queue can imply that newest data, oldest data, or no data is safe to discard. The framework cannot infer physical consequence from software shape.

Finally, qualification must name the exact stack being qualified: F Prime version, FPP tool version, generated artifacts, compiler and flags, OS abstraction, platform packages, board support, project components, configuration, and hardware. Flight heritage attaches to a tested assembly and process. It does not flow transitively from a public repository into a different vehicle.

That is why F Prime's open-source achievement is more interesting than “the code flew on Mars.” It gives engineers a common language for the seams that otherwise hide in C++: the topology says who can communicate, the port kind says where the handler runs, and the rate group says when work is requested. Once those are visible, a mission can measure, test, and argue about the remaining risks. The typed wiring harness is valuable precisely because it shows where the framework ends.

Sources

  1. F Prime project, “Powerful Software Architecture” — component, port, topology, deployment, execution-kind, and Ingenuity test-topology overview.
  2. F Prime 4.3.0 User Manual, “Core Constructs: Ports, Components, and Topologies” — typed connections and synchronous, guarded, asynchronous, passive, queued, and active execution semantics.
  3. F Prime project, The F Prime Prime (FPP) User’s Guide, version 3.3.0 — modeling goals, semantic checking, and C++/JSON generation.
  4. NASA F Prime maintainers, F Prime v4.3.0 release notes — FPP system modeling, direct port calls, rate-group measurements, configuration changes, and security hardening.
  5. F Prime 4.3.0 reference documentation, “Rate Group Scheduling Functionality” — clock division, active/passive dispatch, overrun detection, configuration, and timing telemetry.
  6. F Prime 4.3.0 User Manual, “Unit Testing in F′” — generated component test harnesses, requirements tracing, port histories, and the limits of line coverage.
  7. NASA, “Meet the Open-Source Software Powering NASA’s Ingenuity Mars Helicopter” — F Prime's origin, open-source release, flight lineage, common services, and reuse scope.
  8. Evan Ackerman, “How NASA Designed a Helicopter That Could Fly Autonomously on Mars,” IEEE Spectrum — independent interview on Ingenuity's hardware, loop rates, planned trajectories, and onboard autonomy boundary.
  9. NASA Science, “Ingenuity at Two Years on Mars” — Mastcam-Z photograph date, distance, dimensions, description, and NASA/JPL-Caltech/ASU/MSSS credit.
  10. F Prime 4.3.0 User Manual, “Selecting Component, Port, and Command Kinds” — cyclic, event-driven, and background-work patterns and their execution tradeoffs.
  11. Evan Ackerman, “Ingenuity’s Chief Pilot Explains How to Fly a Helicopter on Mars,” IEEE Spectrum — simulation validation, vacuum-chamber testing, irreducible environment gaps, and repeated perturbation runs.
Previous A LUT crossed OpenColorIO's trust boundary before it changed a single pixel Next The tank was a question before it was a picture

Recommended In oss

Matched by subject and format