How it is built
Architecture overview
Satellite flight software (FSW) is the program on the spacecraft's computer that keeps it alive and doing its job without a human in the loop most of the time. The computer is slow by ground standards, the radio link is short and intermittent, radiation flips memory bits, and nobody can reboot it by hand, so the design is built around three ideas. First, isolation by layers: a thin operating-system and hardware abstraction below, a set of core services (messaging, time, events, tables, files) in the middle, and many small applications on top, each of which does one job and talks to the others only through messages. Second, everything is a command or a telemetry packet: the ground sends commands, the spacecraft returns packets, and applications inside use the same format, so ground tools and flight code share one vocabulary. Third, autonomy for faults: monitors compare telemetry with limits and trigger stored responses (safe mode) faster than the ground could. NASA's core Flight System (cFS) and JPL's F Prime (F´) are the open frameworks for this shape; cFS flew on flagship and human missions and runs on CubeSats and Raspberry Pi, F´ targets smaller systems (source: cFS README; F´ README).
Parts:
- OS abstraction and platform layer — hides the real-time OS and the board from the rest — Preemptive priority scheduling underneath, with cFS's OSAL and PSP layers on top
- Message bus — decouples producers and consumers of commands and telemetry —
publish-subscribe-event-bus(no page yet), packet formatccsds-space-packets(no page yet) - Time and scheduling — mission time, a periodic schedule that wakes applications — Clock synchronization, Hierarchical timing wheel
- Fault detection and recovery — monitors, limit checks, safe-mode responses, watchdog —
fault-detection-isolation-recovery(no page yet), Watchdog timer, Hierarchical state machine,redundancy-voting(no page yet) - Memory and storage — pools, survive-reset data, error-correcting memory — Slab allocator,
edac-memory-scrubbing(no page yet), CRC32C checksums (family of integrity checks) - Link and data handling — packets, files, error correction, authentication — Reed-Solomon codes, Convolutional codes and Viterbi,
ldpc-codes(no page yet), Message authentication codes - Guidance, navigation and control (GNC) — where is the spacecraft, which way does it point, what to command —
attitude-determination(no page yet), Extended Kalman filter, Kalman filter, Quaternion rotations, PID control - Orbit and frames — position over time and between coordinate frames —
orbit-propagation(no page yet), Adaptive Runge-Kutta, Rigid-body transforms,spherical-harmonic-transform(no page yet)
ground ──uplink (packets, files)──► radio/decoder ──► command ingest ──┐
▲ ▼
│ ┌──────────── software bus (pub/sub) ───────────┐
downlink ◄── telemetry output ◄─────────────┤ │
(packets, files) │ scheduler GNC apps health & safety limit │
│ (time) (EKF, PID) (watchdog, apps) checker│
│ stored commands data storage file xfer │
└──── core services: events, tables, time, memory ┘
│
OS abstraction + platform layer ──► RTOS ──► CPU, sensors, actuators
There are two products of the same design: the flight build (a fixed set of applications and tables for one mission, verified for that mission) and the ground and test builds (the same code on a workstation or a development board, used with a simulator). The cFS bundle on GitHub is explicitly a demo, not a flight distribution (source: cFS README).
How the parts fit together
OS abstraction and platform layer
Flight code that calls the operating system directly cannot move to the next mission. cFS therefore has two layers below the applications: the Operating System Abstraction Layer (OSAL, tasks, queues, semaphores, files behind one API) and the Platform Support Package (PSP, board and memory specifics) (source: cFS component READMEs). The cFE guide tells application authors to call only the cFE and OSAL APIs and never the hardware or the OS directly (source: cFE Application Developer's Guide). Under that layer sits a real-time kernel with fixed-priority preemption: Preemptive priority scheduling is the dominant choice because worst-case latency can be analysed. See also the system page on RTOS.
One contract is worth knowing: interrupt handling is not abstracted. The guide notes that the OSAL interrupt functions were deprecated for platform dependencies, and it describes the device-driver pattern instead: a three-function model in which a short ISR does the time-critical part, then wakes a task that may call the full API (source: cFE Application Developer's Guide). The same split exists in every RTOS: the ISR cannot use calls that may block.
Message bus
The software bus (SB) is how applications talk. An application creates a pipe, a queue with a fixed depth, and subscribes its pipe to the message IDs it wants; senders just publish a message with an ID and the bus routes it to every subscribed pipe. This is publish-subscribe-event-bus (no page yet) specialised for flight (source: cFE Application Developer's Guide, Software Bus). The contracts:
- A pipe is read by exactly one application, though an application may read several pipes.
- Bounded queues, explicit overflow. If a pipe reaches its depth, further messages to that pipe are rejected (an overflow) while other pipes continue normally, so a slow application cannot stall the bus. A per-subscription message limit adds a second bound per message ID.
- Opaque IDs. The message ID is not to be interpreted by applications; by default it maps to a CCSDS stream ID, and the format is selectable (source: same guide). Commands and telemetry use the CCSDS packet shape (
ccsds-space-packets, no page yet), which is why ground tools can read bus traffic directly. - No bus calls from interrupt handlers, since the bus uses OS calls that may block.
- Routing table: a direct-indexed map by message ID, or a hashed map to save memory when IDs are sparse. That is a space/speed trade-off the guide documents with the memory impact "significant".
The alternative is direct function calls between modules, which is simpler and faster but ties every module to every other. The bus costs a copy and a queue per message; it buys replaceable, testable, individually restartable applications.
F´ makes the same decoupling with typed ports between components: a port is an interface of a fixed type and a component's ports are connected in a topology. A port can be synchronous (runs on the caller's thread), guarded (the same, under a component mutex) or asynchronous (the call is placed on a queue and handled on the component's own thread) (source: F´ User Manual). The difference from cFS is in when connections are made: F´ connects components at build time from a model and generates code, cFS connects applications at runtime by subscription.
Time and scheduling
Telemetry and control need a shared timebase. The cFE Time Service keeps Mission Elapsed Time (MET) in a hardware register, applies a Spacecraft Time Correlation Factor (STCF) to relate it to an epoch, and defines TAI = MET + STCF; the factor can compensate a known oscillator drift (source: cFE Application Developer's Guide, Time Service). That is Clock synchronization in the small: estimate the offset between the on-board clock and a reference, and steer it gradually. The feedback loops PID control and Phase-locked loop, are the standard tools for locking a local oscillator to a reference such as a one-pulse-per-second signal.
Activity is scheduled from a table. The scheduler application releases message IDs on a fixed one-second grid in the demo version (sch_lab), and applications wake when their message arrives (source: nasa/sch_lab README; the cFE guide names Scheduler and Stored Command as typical software-only applications). This is a coarse timing wheel: the table slot is the bucket; Hierarchical timing wheel is the general structure when timers are many and irregular.
Fault detection and recovery
The spacecraft must handle failures by itself, in time. fault-detection-isolation-recovery (no page yet) is realised in cFS by cooperating applications:
- Health and Safety (HS) monitors applications and events, and services a hardware watchdog (source: nasa/HS README).
- Limit Checker (LC) compares telemetry data points with thresholds; on a violation it issues an event and can start a Relative Time Sequence script as the response (source: nasa/LC README).
- Stored Command (SC) holds command sequences with time tags or wake-up counts: absolute-time sequences (ATS) and relative-time sequences (RTS) (source: nasa/SC README). The response to a limit violation is an RTS; the ground-visible record is an event.
Together this is a monitor/response table pair: a monitor table (LC) says what is wrong, a response table (SC) says what to do, and escalation climbs from restarting one application to rebooting the processor to safe mode. The Watchdog timer is the last resort, and the contract is the usual one: it is serviced only by something that verifies health (HS here), not by an unconditional timer. A Hierarchical state machine is the natural model of the operating modes (nominal, safe, survival) with entry and exit actions; F´ documents state machine support in the framework. Redundant sensors or computers add redundancy-voting (no page yet): two-out-of-three voting masks one bad input, at the cost of triple the hardware.
Memory and storage
Memory is scarce and radiation-prone. The cFE memory pool provides pseudo-dynamic allocation from a block that the application gives it: fixed-size blocks, without the fragmentation of malloc (source: cFE Application Developer's Guide). That is the Slab allocator idea; buddy-allocator and arena-allocator (no pages yet) are the alternatives for mixed sizes or per-cycle memory. F´ offers a buffer pool for the same reason.
Data that must survive a processor reset goes to the Critical Data Store (CDS): an area not modified during a reset, which the application copies its working data into periodically; the cFE adds an integrity value and the application decides whether the contents are logically valid (source: same guide). The cFE offers a mission-wide CRC API; historically a single algorithm, CRC-16/ARC, and others by option. CRC32C checksums are the strong-integrity variant for storage, but the check chosen is a mission decision.
Radiation flips bits in RAM, so edac-memory-scrubbing (no page yet) uses error-correcting memory plus a background task that reads every word periodically, so single-bit errors are fixed before a second one accumulates into an uncorrectable error. The scrub period is chosen from the expected upset rate. The Data Storage application writes bus messages to files on a recorder, and the CFDP application transfers them to the ground, mapping CFDP PDUs onto the software bus (source: nasa/DS and nasa/CF READMEs).
Tables carry configuration (thresholds, schedule, routes). Each table has an active and an inactive image; ground loads and validates the inactive image, then commands the switch. A single-buffered table shares one inactive buffer (less memory, but the reader may be delayed), a double-buffered table has its own and switches without blocking, good for time-critical readers (source: cFE guide, Table Service). The result is that thresholds change by uplinking a file, not by reflashing code.
Link and data handling
Commands arrive and telemetry leaves over a lossy link. Layers, from the radio up: modulation and demodulation (qam-soft-demapping, no page yet, converts received symbols to soft bits); forward error correction (Reed-Solomon codes, Convolutional codes and Viterbi, ldpc-codes (no page yet) as the modern high-gain choice); framing into CCSDS transfer frames; then packets on the bus. The FEC is usually in the radio hardware or a dedicated decoder, because LDPC decoding at high rates is heavy work (sparse matrices, Sparse matrices (CSR), and SIMD programming on the ground), and flight software handles frames and files above it. Which code to choose is a link-budget decision: LDPC and turbo codes (ldpc-codes ↔ polar-codes, turbo-codes, no pages yet) come closer to channel capacity than Reed-Solomon, at higher decoder cost.
Uplink authentication matters because a command can change the orbit. Message authentication codes give each command a keyed tag and a counter, so a recorded command cannot be replayed (see Replay protection window). The public cFS is limited to the framework and common applications; security measures for a full flight mission are part of the government version (source: cFS README).
Guidance, navigation and control
GNC is mission-specific application code on top of the framework. The pieces: attitude-determination (no page yet) turns star-tracker and sun-sensor vectors (TRIAD, QUEST for Wahba's problem) and gyro rates into a quaternion orientation; an Extended Kalman filter fuses gyro propagation with vector measurements, where the plain Kalman filter suffices if the model is linear; PCA/SVD appears in the SVD solution of Wahba's problem. The estimate feeds a PID control or similar loop driving reaction wheels or magnetorquers. The alternative to a Kalman filter is the complementary filter, simpler and cheaper but without covariance.
Orbit and frames
orbit-propagation (no page yet) predicts where the spacecraft is: analytic models (Kepler, SGP4) for low-cost use, numerical integration with perturbations (gravity harmonics via spherical-harmonic-transform, drag, solar radiation) when precision matters. The integrator is Adaptive Runge-Kutta when step size should follow the dynamics, or fixed-step Runge-Kutta 4 when run time must be constant; Explicit Euler is the baseline that is cheap but loses accuracy fast. Position in the Earth-fixed, inertial and body frames is converted with Rigid-body transforms and calendar-date-arithmetic (no page yet) for time scales.
Data and control flow
A ground command:
- The radio decodes the frame (FEC) and checks the integrity and authenticity tag.
- The command-ingest application publishes the packet on the bus under its message ID.
- The subscribing application reads it from its pipe, validates length and arguments, executes it, and emits an event and housekeeping telemetry with a command counter.
- Telemetry output applications collect those packets and queue them for the next downlink pass.
A fault response:
- A sensor value drifts; the limit checker compares the telemetry point against its table and finds a violation.
- It issues an event and starts a stored command sequence.
- The sequence disables a payload and commands safe mode through the bus.
- Health and Safety services the hardware watchdog; the design intent is that it does so only while monitored applications are healthy, so a hang ends in a processor reset, after which applications restore state from the Critical Data Store.
- The ground sees the event and the housekeeping telemetry on the next pass and decides how to recover.
Scaling
- Link capacity limits how much telemetry reaches the ground per pass. Levers: onboard storage with prioritised downlink, event filtering (cFE's binary filter masks a counter to suppress repeats), compression, a stronger code.
- Processor time limits control rate and onboard estimation. Levers: fixed-rate schedule, simple filters, offload orbit work to ground.
- Memory limits the number of applications and tables. Levers: pools, single-buffered tables, a small routing map.
- Application count grows the bus traffic and the test matrix. Levers: reuse unchanged, previously flown applications; keep interfaces in header files so a change recompiles only what it touches (a cFS guideline).
- Reliability is paid for in redundancy: voted sensors, cold or hot spares, and verification effort.
Failure modes
| Failure | Symptom | Cause | Fix |
|---|---|---|---|
| Pipe overflow | an application misses messages | queue depth too small or the application too slow | size depth from rates; per-message limits; fix the slow path |
| Single-event upset in RAM | bad data, odd behaviour that clears on reboot | radiation flips a bit | EDAC memory with scrubbing; checksums on tables |
| Latch-up or reset | the processor reboots | radiation or a software hang | watchdog, restore from the Critical Data Store, safe mode |
| Wrong table | unexpected thresholds or schedule | uploaded values not validated | load to the inactive image, validate, then activate |
| Estimator divergence | attitude error grows, wrong pointing | bad sensor, wrong noise model, singularity | outlier rejection, covariance monitoring, fall back to a simple mode |
| Command replay or spoof | an old command executes again | no counter or tag | authenticated commands with a replay window |
| Fault cascade | one fault trips many monitors | thresholds overlap, no isolation | isolate by subsystem, escalation levels, hold-off timers |
| Lost link | no contact | wrong pointing or transmitter fault | autonomous recovery that re-points and retries on a schedule |
Real implementations
| name | what it is | repo | licence | notes |
|---|---|---|---|---|
| cFS (core Flight System) | framework: cFE core services, OSAL, PSP, and flight apps (HS, LC, SC, DS, CF, ...) | nasa/cFS | Apache-2.0 | bundle repo; submodules nasa/cFE, nasa/osal, nasa/PSP |
| F Prime (F´) | component framework: ports, components, topologies, modelling language, code generation, ground data system | nasa/fprime | Apache-2.0 | aimed at CubeSats, SmallSats, instruments; project site fprime.jpl.nasa.gov |
The alternative: F´ and cFS differ in how the system is wired. In cFS an application is a separate task that finds its peers at runtime through message subscription, so configuring a mission is a matter of tables and a startup script. In F´ the wiring is a topology written in a modelling language, from which code is generated, so a mismatch of interfaces is a build error. cFS has a longer flight history on larger spacecraft and a rich set of ready-made applications; F´ gives a typed, model-driven path that suits small teams.
Sources
- NASA cFS: bundle repository and README, official site; component repositories cFE, OSAL, PSP. The cFE Application Developer's Guide (
docs/cFE Application Developers Guide.mdin the cFE repository) covers services, software bus, tables, time and memory utilities. - cFS applications: Health and Safety (
nasa/HS), Limit Checker (nasa/LC), Stored Command (nasa/SC), Data Storage (nasa/DS), CFDP (nasa/CF), Scheduler Lab (nasa/sch_lab) READMEs on GitHub. - F Prime: nasa/fprime; documentation; user manual pages Core Constructs: Ports, Components, and Topologies and Commands, Events, Channels, Parameters.