View on GitHub

Flight Software & Embedded Systems Framework

Configuring F´

This guide is a first attempt to describe the various configuration settings in F´. Most users can operate with the default settings, but as the system design is finalized, some of these options may need to be changed such that the system is most efficient.

This guide includes:

How To Configure F´

All configurable files (top-level and component-specific) for F´ are available in the top-level config directory. By default, all deployments use the F´ provided default configuration options, but as of F´ version 1.5, deployments can provide their own AcConstants.ini and configuration *.hpp files by using the ac_constants and config_directory options in the deployment’s settings.ini file. See the settings.ini guide for more details.

A deployment can clone AcConstants.ini or the whole set of *.hpp files or both. The deployment must take ownership of all *.hpp due to C++ compiler constraints.

AcConstants.ini follows python’s INI format and the FpConfig.hpp file is a C++ header allowing the user to define global settings. Where components allow specific configuration, a <component>Cfg.hpp is available to be modified as well.

AcConstants.ini

AcConstants.ini is used to set the constants for the autocoded components provided by the framework. This allows projects to appropriately size the number of ports provided by many of the command and data handling components defined in the Svc package. Note: internal configurations like table sizes are set in the component specific header as these settings aren’t autocoded. See: Component Configuration

These settings may need to be increased for large projects with many components, or minimized for projects with a small number of components.

Setting Description Default Valid Values
ActiveRateGroupOutputPorts Number of outputs from active rate group. Limits number of components attached to a single rate group 10 Positive integer
CmdDispatcherComponentCommandPorts Number of command and command registration ports. Limits number of components handling commands 30 Positive integer
CmdDispatcherSequencePorts Number of incoming ports to command dispatcher, e.g. uplink and command sequencer 5 Positive integer
RateGroupDriverRateGroupPorts Number of rate group driver output ports. Limits total number of different rate groups 3 Positive integer
HealthPingPorts Number of health ping output ports. Limits number of components attached to health component 25 Positive integer

An example INI setting would look like:

setting = 123; Comment

FpConfig.hpp

Some configurations may be changed during compilation time. The F′ framework has a number of optional features that can be enabled or disabled by editing the config/FpConfig.hpp file. These changes affect of the whole of the F´ deployment. Users can change or override defined C macro values that activate or disable code by using compiler flags for different deployment settings. During flight software (FSW) execution, disabling unnecessary features saves memory and CPU cycles.

All of these settings should be set in FpConfig.hpp and for most projects, this whole file will be cloned and owned for their specific settings. These settings, typically the user will define the setting to be 0 for off and 1 for on.

e.g.

#define FW_SOME_SETTING 1

Type Settings

Many architectures support different sizes of types. In addition, projects may wish to change the size of the various custom types specified in the framework. This section will describe these settings.

Architecture Supported Primitive Types

The architecture is designed to be portable to different processor architectures. Some architectures such as small microcontrollers do not support the full range of types. The architecture supports a non-sized integer type named NATIVE_INT_TYPE. The NATIVE_INT_TYPE is recommended for code (e.g., loop variables) where a particular size is not needed in order to make it more portable. An additional type NATIVE_UINT_TYPE is available for unsigned variables. These types are defined in Fw/Types/BasicTypes.hpp and use compiler macros for sizing. See: Primitive Types

In addition to these types, F´ specifies types of a given size and allows for configuration values to turn the larger types on/off such that smaller architectures can disable them. These settings are described below.

Table 32. Macros for supported types.

Macro Definition Default Valid Values
FW_HAS_64_BIT The architecture supports 64-bit integers. 1 (on) 0 (off) 1 (on)
FW_HAS_32_BIT The architecture supports 32-bit integers. 1 (on) 0 (off) 1 (on)
FW_HAS_16_BIT The architecture supports 16-bit integers. 1 (on) 0 (off) 1 (on)
FW_HAS_F64 The architecture supports 64-bit double-precision floating point values. 1 (on) 0 (off) 1 (on)

Example:

// Turn of 64-bit integers (double)
#define FW_HAS_F64 0

Configured Type Definitions

WARNING: to run the system with the standard F´ GDS, these changes need to be made in the python GDS support code as well as here. This is non-trivial and will be fixed in future releases. Unless the project intended to modify the GDS code, or use an alternate GDS for all functions, these settings should be left as their defaults.

The value which represents a serialized boolean can be set using these macros. This only affects what value is written when the boolean is serialized

Table 33: Macros for boolean serialization

Macro Definition Default Valid Values
FW_SERIALIZE_TRUE_VALUE True value when serialized 0xFF 0 to 0xFF
FW_SERIALIZE_FALSE_VALUE False value when serialized 0x00 0 to 0xFF

Special named types used by F´ are mapped to some form of a primitive type integer type. This is done for ease of reading F´ code and is a standard practice in C/C++. The framework allows projects to change the type they used for these types to optimize transmitted bytes. Again, any changes must match the GDS in order to decode the values correctly and thus changing these values should be done carefully.

Table 34: Macros for custom types

Macro Definition Default Valid Values
FwPacketDescriptorType Type storing F´ packet type descriptor U32 U8, U16, U32, U64
FwOpcodeType Type storing F´ opcodes U32 U8, U16, U32, U64
FwChanIdType Type storing F´ channel ids U32 U8, U16, U32, U64
FwEventIdType Type storing F´ event ids U32 U8, U16, U32, U64
FwPrmIdType Type storing F´ parameter ids U32 U8, U16, U32, U64
FwBuffSizeType Type storing the size of an F´ buffer U16 U8, U16, U32, U64
FwEnumStoreType Type storing F´ enum values I32 I8, I16, I32, I64
FwTimeBaseStoreType Type storing F´ timebase enum U16 U8, U16, U32, U64
FwTimeContextStoreType Type storing F´ time context U8 U8, U16, U32, U64

Note: for a further understanding of timebase and time context, see the next section.

Time Base and Time Context

The F′ time tags have a field that specifies the time base of the time tag. A time base is defined as a clock in the system correlated with a known epoch. It is often the case that when a system is being initialized, it does not always have access to a clock correlated to external operations. It can transition through several time bases (processor, radio, Earth) on the way to becoming fully operational. The TimeBase type defines the set of clocks in the system tha can produce a time tag. It lets users of the system see which clock was used when time tagging telemetry.

Time contexts are another value associated with the time.

WARNING: changes to this value must be done in tandem with the F´ GDS for F´ GDS features to work. Thus most projects don’t modify these settings just like the types defined above.

enum TimeBase {
    TB_NONE, //!< No time base has been established
    TB_PROC_TIME, //!< Indicates time is processor cycle time. Not tied to external time
    TB_WORKSTATION_TIME, //!< Time as reported on workstation where software is running. For testing.
    TB_DONT_CARE = 0xFFFF //!< Don't care value for sequences. If FwTimeBaseStoreType is changed, value should be changed
};

Time base and time context usage may be turned on and off using the macros shown below:

Macro Definition Default Valid Values
FW_USE_TIME_BASE Enables the time base Fw::time field 1 (on) 0 (off) 1 (on)
FW_USE_TIME_CONTEXT Enables the time context Fw::time field 1 (on) 0 (off) 1 (on)

Object Settings

The architecture allows for various settings to control, monitor, and trace objects in the system. These settings typically result in a larger binary size, but make the framework and system easier to debug. This section includes a discussion of OS objects like Tasks and Queues as well.

Object Naming

The architecture can store names for each object created. This is useful when using object registries or tracing to see what objects exist and how they interact. The object naming does increase the per-object storage and code size, so in a resource-constrained environment, disabling this feature might be desirable. This macro should be used in developer implementation classes to call the correct constructor in the code-generated base classes. Table 35 provides the macros related to this feature.

The Os::Queue class stores a queue name as private data. Table 35 provides the macro for this feature. The Os::Task class stores a task name as private data. Table 35 provides the macro for this feature as well.

Table 35. Macros for object naming, queue naming, and task naming

Macro Definition Default Valid Values
FW_OBJECT_NAMES Enables storage and retrieval of the name 1 (on) 0 (off) 1 (on)
FW_OBJ_NAME_MAX_SIZE Size of the buffer storing the object name 80 Positive integer
FW_QUEUE_NAME_MAX_SIZE Size of the buffer storing the queue names 80 Positive integer
FW_TASK_NAME_MAX_SIZE Size of the buffer storing task names 80 Positive integer

Note: The macro FW_OPTIONAL_NAME("string") can be used to conditionally return the given string or an empty string depending on whether FW_OBJECT_NAMES is on. This can be used to strip out component names from code when building without FW_OBJECT_NAMES.

Note: If the size of the string passed to the code-generated component base classes is larger than this size, the string will be truncated. FW_OBJECT_NAMES must be turned on for FW_OBJ_NAME_MAX_SIZ to have any effect.

Note: FW_QUEUE_NAME_MAX_SIZE and FW_TASK_NAME_MAX_SIZE are only used if FW_OBJECT_NAMES is turned off. Otherwise the supplied object name is used.

Object to String

The framework port and object classes have an optional toString() method. This method by default returns the instance name of the object, but toString() is defined as a virtual method so a developer class can override this and provide custom information. Table 35 provides the macros to configure this feature.

Note: for these settings to work FW_OBJECT_NAMES must be turned on.

Table 36. Macros for object to string.

Macro Definition Default Valid Values
FW_OBJECT_TO_STRING Enables the toString() method 1 (on) 0 (off) 1 (on)
FW_OBJ_TO_STRING_BUFFER_SIZE Defines buffer size used to store toString() results 255 Positive integer
FW_SERIALIZABLE_TO_STRING Defines a toString() method for code-generated serializable 1 (on) 0 (off) 1 (on)
FW_SERIALIZABLE_TO_STRING_BUFFER_SIZE Defines buffer size of toString() result for serializables 255 Positive integer
FW_ARRAY_TO_STRING Defines a toString() method for code-generated arrays 1 (on) 0 (off) 1 (on)
FW_ARRAY_TO_STRING_BUFFER_SIZE Defines buffer size of toString() result for arrays 256 Positive integer

Object Registry

An object registry is a class that holds a list of framework component and port objects. The registry can be used to list all the objects, or call common functions on all objects. A base class for the object registry is defined in Fw/Obj/ObjBase.hpp, and a simple implementation can be found in Fw/Obj/SimpleObjRegistry.hpp. Table 37 provides the macros to configure this feature. Message queues allow for their own registration such that the project may track them as well.

Table 37. Macros for object registry.

Macro Definition Default Valid Values
FW_OBJECT_REGISTRATION Enables object registries. 1 (on) 0 (off) 1 (on)
FW_OBJ_SIMPLE_REG_ENTRIES The size of the array in the simple object registry used to store objects. 500 Positive integer
FW_OBJ_SIMPLE_REG_BUFF_SIZE The size of the buffer used to store object names in the simple registry. 255 Positive integer
FW_QUEUE_REGISTRATION Enables queue registries. 1 (on) 0 (off) 1 (on)
FW_QUEUE_SIMPLE_QUEUE_ENTRIES The size of the array in the simple object registry used to store queues. 100 Positive integer

Note: FW_OBJECT_REGISTRATION must be turned on for FW_OBJ_SIMPLE_REG_ENTRIES and FW_OBJ_SIMPLE_REG_BUFF_SIZE to have any effect.

Note: See table 35 for configuring queue name sizes.

Asserts

The assert feature is described in F´ Asserts. This configuration allows a project to turn asserts off, use hash IDs for the assert message, or use full filenames for the assert message. Table 38 provides ways that asserts can be configured.

Table 38. Macros for assert.

Macro Definition   Default
FW_ASSERT_LEVEL Sets the assert report level to:   FW_FILENAME_ASSERT
  Value Definition  
  FW_NO_ASSERT Asserts turned off, removing all assert code.  
  FW_FILEID_ASSERT Asserts turned on, hash value used in place of FILE on message  
  FW_FILENAME_ASSERT Asserts turned on, FILE macro is used in the assert message  
FW_ASSERT_TEXT_SIZE The buffer size used to store the assert message   120

Setting assert level FW_FILEID_ASSERT saves a lot of code space since no file name is stored. The make system supplies this to the compiler by hashing the file name. The original filename can be recovered by running fprime-util hash-to-file <hash>.

Setting assert level to FW_ASSERT_TEXT_SIZE can ease debugging asserts, but typically FW_ASSERT_TEXT_SIZE must be increased as most file name paths are longer than 120.

Port Tracing

When components are interconnected, it is often useful to trace the set of invocations through components and ports. The port base class has a trace() call that is invoked by the derived port classes whenever the port is invoked. The trace() calls Os::Log::log() with the name of the port once the port base class method setTrace() has been called. Individual ports can be have tracing turned on and off by calling the overrideTrace() method on the port instance. Table 39 provides the macro to configure this feature.

Table 39. Macro for port tracing.

Macro Definition Default Valid Values
FW_PORT_TRACING Enables port tracing. 1 (on) 0 (off) 1 (on)

Port Serialization

As discussed in the user guide, a port type (Input/OutputSerializePort) exists that has no interface type, but instead receives (or sends) a serialized form of the port invocation for the attached port. The primary pattern for this is to invoke components on remote nodes. The code generator generates code in each port that will serialize or deserialize the invocation if it detects that it is connected to a serializing port. If development is for a single node, this feature can be disabled to reduce the code size. Table 40 provides the macro to configure this feature.

Table 40. Macro for port serialization.

Macro Definition Default Valid Values
FW_PORT_SERIALIZATION Enables port serialization. 1 (on) 0 (off) 1 (on)

Serializable Type ID

As described in serializable types, serializable types can be defined for use in the code. When objects of those types are serialized, an integer representing the type ID can be serialized along with the object data. This allows the type to be determined later if only the serialized form is available. Turning off this feature will lower the amount of data moved around for a given object when it is serialized. Table 41 provides the macros to configure this feature.

Table 41. Macros for serializable type ID.

Macro Definition Default Valid Values
FW_SERIALIZATION_TYPE_ID Enables serializing the type ID 0 (off) 0 (off) 1 (on)
FW_SERIALIZATION_TYPE_ID_BYTES Defines size of serialization ID 4 1 - 4

Note: smaller values for FW_SERIALIZATION_TYPE_ID_BYTES means that less data storage is needed, but also limits the number of types that can be defined. FW_SERIALIZATION_TYPE_ID is required to have type IDs in the buffer and thus to introspect what type is contained in the buffer.

Buffer Sizes

Many of the built in F´ data types define buffer sizes that allow them to be passed as a com buffer type, sent out through the ground interface, serialized and more. This section will discuss the com buffer configuration, command, channel, event, parameter and other buffer size arguments.

The com buffer must be able to store all the other types such that they can all be passed as generic communication. Thus FW_COM_BUFFER_MAX_SIZE must be large enough to hold each buffer size and the header data for each type. Thus these settings are typically derived and this is done by default. WARNING: only modify the comm buffer size to ensure that there will be no faults in the system.

In all cases, these definitions are global for each types in the system. Thus the buffer must be large enough to hold the data for the largest of a given type in the system. An assert will result if the buffer is set too-small. i.e. the FW_CMD_ARG_BUFFER_MAX_SIZE cannot be smaller than the serialized size of the command with the largest arguments.

These types also provide optional string sizes for their constituent pieces. However, the MAX_STRING_SIZE settings must always be smaller than the BUFFER_MAX_SIZE. i.e. the command string max size cannot be larger than the command buffer max size, as the string is serialized into the buffer.

Commands serialize argument values into these buffers. Events (aka log events) also serialize just the arguments. Channelized telemetry and parameters serialize the values. Other information like event strings is not serialized but rather reconstructed when needed from the dictionary. This is all placed in a comm buffer.

Table 42 provides the macros to configure these features.

Table 42. Macros for buffers.

Macro Definition Default Valid Values
FW_COM_BUFFER_MAX_SIZE Defines the size of a com buffer 128 Positive integer
FW_CMD_ARG_BUFFER_MAX_SIZE Defines the size of command argument buffers Derived  
FW_CMD_STRING_MAX_SIZE Defines the maximum size of a command string argument 40  
FW_LOG_BUFFER_MAX_SIZE Defines the size of event buffers Derived  
FW_LOG_STRING_MAX_SIZE Defines the maximum size of an event string argument 100  
FW_TLM_BUFFER_MAX_SIZE Defines the size of telemetry channel buffers Derived  
FW_TLM_STRING_MAX_SIZE Defines the maximum size of a channel string value 40  
FW_PRM_BUFFER_MAX_SIZE Defines the size of parameter buffers Derived  
FW_PRM_STRING_MAX_SIZE Defines the maximum size of a parameter string value 40  

Other Buffers are defined in the system for specific purposes. These do not need to fit inside a comm buffer, and thus are less restrictive in sizing.

Macro Definition Default Valid Values
FW_FILE_BUFFER_MAX_SIZE Defines buffer and chunk size for file uplink and downlink 255 Positive integer
FW_INTERNAL_INTERFACE_STRING_MAX_SIZE Maximum size for interface string 40 Positive integer

Text Logging

Event functions that are called are turned into two output port calls. One is a binary port that is used to store the event to be transported to ground software or a testing interface external to the software. The component also takes the format string specified in the XML and populates it with the event arguments, and calls an output port with a readable text version of the event. This is meant to be used for a console interface so the user can see, in text form, the same events being stored for transmission. A component with the text logging input port can be used to display the text. A very simple implementation of this can be seen in Svc/PassiveConsoleTextLogger. In a resource-constrained environment or in a flight implementation where the console is not viewable, the text formatting and extra code can consume an undesirable number of processor cycles. For this reason, the text logging can be turned off via a macro. This compiles out the code and format strings for text logging. Table 46 provides the macros to configure text logging.

Table 46. Macros for text logging.

Macro Definition Default Valid Values
FW_ENABLE_TEXT_LOGGING Enables or disables text logging 1 (on) 0 (off) 1 (on)
FW_LOG_TEXT_BUFFER_SIZE Maximum size of the textual representation of the event 256 Positive integer

Note: the FW_LOG_TEXT_BUFFER_SIZE should be large enough to store the full event including its text format string after being populated with arguments.

Misc Configuration Settings

This setting describes some of the other settings available in FpConfig.hpp and did not fit in other sections. These are described in tables below. Table 47 describes other user settings. Table 48 describes settings defined by the build system that should never be hand-set.

Table 48. Misc macros available to user.

Macro Definition Default Valid Values
FW_CMD_CHECK_RESIDUAL Enables command serialization extra bytes check 1 (on) 0 (off) 1 (on)
FW_AMPCS_COMPATIBLE Adds argument sizes to event argument serialization 0 (off) 0 (off) 1 (on)

Note: Normally when a command is deserialized, the handler checks to see if there are any leftover bytes in the buffer. If there are, it assumes that the command was corrupted somehow since the serialized size should match the serialized size of the argument list. In some cases, command buffers are padded so the data can be larger than the serialized size of the command. Turning FW_CMD_CHECK_RESIDUAL off can disable this check and allow leftover bytes.

Note: some ground systems require the size of the event argument to be serialized into the buffer instead of predicting the size using the dictionary. Setting FW_AMPCS_COMPATIBLE will serialize these sizes into the event buffers and break compatibility with the F´ ground system as it does not use this feature.

WARNING: the following settings are defined by the build system and are in FpConfig.hpp to provide a default off value. These must be set by the build system as the setting works in unison with other modules that the build system includes when enabling these settings.

Table 48. Macros for use by build system only

Macro Definition Default Valid Values
FW_BAREMETAL_SCHEDULER Enables baremetal scheduler hooks in active components 0 (off) 0 (off) 1 (on)

Component Configuration

Component configurations are also provided as part of the project’s config directory. If the directory is not provided, then the default from the framework is used. Remember: if the project overrides any configuration, that new directory must contain all the component headers as well as the FpConfig.hpp as C++ prevents including individual headers.

These component headers follow the form <Component>Cfg.hpp and allows a project to set the configuration for each component’s C++ implementation. This is typically to set maximum sizes for tables, and other static memory allocations. Some components allow users to turn on and off features. If a component does not have a header, it has no configuration for the user to set.

Users are encouraged to look through the header for the component of interest as they should be self descriptive.

Conclusion

The user should now have a very detailed understanding of how to configure F´. Although there are some automatic checks built into F´ to check for some invalid configurations, the user should take care to understand the implication of changes to these settings. The F´ team sincerely hopes this bombardment of information will prove useful.