'Parameter Groups' is the name of the pattern that is used in Betaflight to store (and at a later point transfer) firmware configuration data.
With parameter groups, parameters are combined in logical groups (e.g. all the parameters for one particular device / feature go into one parameter group). These groups are modelled as data structures in the firmware.
The following rules have to be taken into consideration when dealing with parameter groups in code:
- Each feature or group of related features, hardware driver or group of related hardware drivers should use a parameter group of its own;
- A parameter group of any given ID and version shall be identical across all targets and build configurations - this means that nothing that is contained in a parameter group directly or indirectly can be conditional. The finest granularity for parameters to be available on a given target is by having or not having support for a given parameter group;
- The only exception to 2. are parameter group arrays. For parameter group arrays, it is permissible to have the length of the array defined conditionally. Because the length of the struct defining the array elements is fixed for any given version, and the overall size of the array is stored with the array, the length of the array can be calculated when reading it. This consideration only applies to parameter group arrays declared with
PG_DECLARE_ARRAY, and the length supplied in the declaration. For the length of any arrays inside a parameter group struct (directly or nested), 2. applies;
- As a consequence of 1. and 2., all of the parameters required for the configuration of the feature or driver should be contained within this parameter group. If a parameter is required by more than one feature or driver, it shall be moved 'upwards' into a generic parameter group that all the features or drivers requiring the parameter depend upon - if necessary such a parameter group has to be created;
- New parameters should always be appended at the end of the parameter group. If this is the only change to the parameter group, there are no further changes required. Previously stored versions of the data in this parameter group can still be read. New elements will be initialised to 0 in this case. If 0 is an invalid value for a new parameter, this has to be treated as described in 6., in order to ensure the parameter is initialised to a valid value. If the parameter group that the new parameter is appended to is a parameter group array declared with
PG_DECLARE_ARRAY, then the version of the parameter group has to be incremented as described in 6. as well, in order get the change in the struct properly handled;
- Any changes to a parameter group that are not covered in 5. (e.g. removing elements, changing the type of elements), the version of the parameter group (as defined in
PG_REGISTER...) has to be incremented in order to make the code handling parameter groups aware that the format of the parameter group has changed and previously stored versions of it are now invalid;
- All changes to parameter group arrays (declared with
PG_DECLARE_ARRAY()) or arrays contained within the struct of a parameter group require that the version of the parameter group (as defined in
PG_REGISTER..has to be incremented as well, and the same considerations as for 6. apply;
- When creating a new parameter group, the
PG_DECLARE_ARRAY()shall be placed right after the definition of the struct used as the type of the parameter group in the code. This serves the purpose of making it easy for developers to determine when a struct they are working on is used in a parameter group and subject to these rules;
- Any struct that is used as an element in a struct that is used in a parameter group (directly or indirectly) is subject to constraints 6. and 7. above. In order to make it possible for developers to determine that this is the case, a comment
// Used in parameter group <group name>shall be added after the definition of the struct for every parameter group that the struct is used in.