How to Manage F Prime Parameters: A Complete Guide to PrmDb and Component Configuration

F Prime parameters are persistent configuration values managed through the PrmDb service, defined in FPP model files, and accessed via auto-generated getter methods that load from a serialized backing file during component initialization.

F Prime (F') is NASA's open-source flight software framework used for CubeSats, rovers, and spacecraft. Parameters provide a type-safe mechanism for storing mission-configurable values that survive power cycles, distinct from telecommands and telemetry channels. This guide explains the complete lifecycle of parameter management from FPP definition to runtime persistence.

Defining Parameters in FPP

Parameters originate in F Prime Prime (FPP) model files. Each component declares its parameters with a unique ID, type, and default value.

In MyComponent.fpp:

module MyModule {
  component MyComponent {
    # Parameters declaration

    param MY_MODE: U32 = 0x01
    param THRESHOLD: F32 = 3.14
    param DEVICE_NAME: string = "DEFAULT"
  }
}

The F Prime code generator creates accessor methods in the component's base class. These methods follow the naming convention paramGet_<PARAMETER_NAME>() and paramSet_<PARAMETER_NAME>() for each declared parameter.

Understanding the PrmDb Architecture

All parameter storage flows through the Parameter Database (PrmDb) service located in Svc/PrmDb/. This centralized architecture decouples components from storage implementation details.

Key architectural components:

  • PrmDbImpl.hpp/cpp: Implements the Svc::PrmDb class handling serialization, file I/O, and notification logic
  • Parameter output port: Each component connects to PrmDb via an auto-generated port for value retrieval
  • Binary backing file: Stores serialized parameter values; loaded at system startup

According to the F Prime source code in Svc/PrmDb/PrmDbImpl.cpp, the database maintains an in-memory table mapping parameter IDs to their serialized values. If the backing file is missing or corrupted, components automatically fall back to the default values defined in their FPP models.

Loading Parameters at Runtime

During component initialization, the framework automatically invokes loadParameters(). This method queries PrmDb through the parameter output port and receives a validity status with each value.

In MyComponent.cpp:

void MyComponent::init(void) {
    // Framework call to load from PrmDb
    loadParameters();
    
    // Retrieve values using auto-generated getters
    Fw::ParamValid stat;
    MyModeType mode;
    
    stat = paramGet_MY_MODE(mode);
    if (stat == Fw::PARAM_VALID) {
        this->currentMode = mode;
    }
    
    F32 threshold;
    stat = paramGet_THRESHOLD(threshold);
    if (stat == Fw::PARAM_VALID) {
        this->threshold = threshold;
    }
}

The Fw::ParamValid enum indicates whether the value is PARAM_VALID, PARAM_INVALID, PARAM_DEFAULT, or PARAM_UNINIT.

Updating Parameters via Ground Commands

Runtime updates follow a command-driven pattern. Ground operators send SET commands targeting specific component-parameter pairs.

Update flow:

  1. Ground system sends command with component ID, parameter ID, and new value
  2. PrmDb stores the new value in its in-memory table
  3. PrmDb invokes the parameterUpdated(FwPrmIdType id) callback on the owning component
  4. Component re-reads the value and applies changes immediately

In MyComponent.cpp:

void MyComponent::parameterUpdated(FwPrmIdType id) {
    if (id == MY_MODE_PRM_ID) {
        MyModeType newMode;
        if (paramGet_MY_MODE(newMode) == Fw::PARAM_VALID) {
            this->currentMode = newMode;
            // Reconfigure algorithms based on new mode
            reconfigureSubsystem(newMode);
        }
    }
}

Example ground command (Python):


# Send SET command to MyComponent

# Component instance ID: 0x1234

# Parameter ID: 0x01 (MY_MODE)

# New value: U32 = 2 (little-endian)

cmd_payload = [0x1234, 0x01, b'\x02\x00\x00\x00']
gds.send_command("MyComponent.SET", cmd_payload)

Saving Parameters to Persistent Storage

Updates reside in memory until explicitly persisted. The SAVE command forces PrmDb to write the current in-memory table to the filesystem.

From ground (Python):


# Persist all parameter changes to backing file

gds.send_command("PrmDb.SAVE")

The backing file path is configurable at deployment time. According to Svc/PrmDb/PrmDbImpl.hpp, the implementation handles atomic file writes to prevent corruption during power loss.

Handling External Parameters

Some parameters must reside outside PrmDb, such as hardware registers or external EEPROM. Components still implement the standard ports, but the underlying serialization targets external storage.

The component implements setParameter and getParameter port handlers to serialize/deserialize values to a buffer that external sources can read or write. This pattern is documented in the autocoded functions guide, allowing seamless integration with non-standard storage mechanisms while maintaining the same ground interface.

Configuring Parameter Limits in CMake

Buffer sizes and string limits are tunable via CMake options in the F Prime build system:

  • FW_PRM_BUFFER_MAX_SIZE: Maximum size of serialized parameter data
  • FW_PRM_STRING_MAX_SIZE: Maximum length for string parameters
  • Default backing file name and path

These settings are defined in the F Prime configuration headers and affect the PrmDb implementation compile-time limits.

Summary

  • Define parameters in component .fpp files with types and default values
  • Access values via auto-generated paramGet_* methods after calling loadParameters()
  • Store values centrally in Svc::PrmDb, which manages persistence to a binary backing file
  • Update values at runtime via SET commands, triggering parameterUpdated() callbacks
  • Persist changes using the SAVE command to survive power cycles
  • Configure buffer sizes via FW_PRM_BUFFER_MAX_SIZE and related CMake options

Frequently Asked Questions

What is the difference between parameters and commands in F Prime?

Parameters are persistent configuration values stored in PrmDb and survive reboots, while commands are ephemeral actions that trigger immediate behavior. Parameters use the paramGet_* and paramSet_* accessors, whereas commands invoke execute handlers. Components typically read parameters once during initialization and react to updates via parameterUpdated() callbacks.

How does PrmDb handle missing or corrupted parameter files?

When Svc/PrmDb/PrmDbImpl.cpp loads the backing file, it validates the serialization format. If the file is missing, corrupted, or contains invalid checksums, PrmDb returns PARAM_DEFAULT or PARAM_INVALID status codes to requesting components. Components then use the default values defined in their FPP models, ensuring the system remains operational with safe defaults.

Can parameters be updated without restarting the F Prime application?

Yes. Parameters are designed for in-flight updates. Ground operators send SET commands to modify values in the running PrmDb memory. The database immediately notifies the owning component via the parameterUpdated() callback, allowing dynamic reconfiguration without restart. Changes persist only after issuing the SAVE command to write the backing file.

What is the maximum size of a parameter buffer in F Prime?

The maximum size is controlled by the FW_PRM_BUFFER_MAX_SIZE CMake configuration option, typically set in the deployment's config directory. This limit governs the serialized size of complex types like arrays or strings. String parameters have an additional limit, FW_PRM_STRING_MAX_SIZE, which constrains the maximum character length for parameter strings.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →