-
Notifications
You must be signed in to change notification settings - Fork 3
Flag File
The flag file is used to hold nonvolatile flags, such as whether we've reset due to PBIST fail, and the filesystem prefix.
Its name in the filesystem is 'zE' so as to not collide with other files.
When we start up, before we create or append to any regular data files, we attempt to open the flag file. If we can't open, we create it and populate the default values.
If the flag file does exist, we update various variables from the data contained in the flag file.
Please see logPBISTFails()
in sfu_startup.c for usage.
- The flag file entries do not contain a timestamp
- The flag file is populated sequentially
- It is extremely important to maintain the existing sequence of entries. Otherwise, we will end up reading false flags
- dump the file with
file dump 7a45
(not currently auto-decoded in Houston, must manually review)
The flag file is intended to hold configuration parameters and other important data. The idea is that we will always maintain a copy in RAM and a copy in external flash. When the OBC resets, it looks for the flag file on the external flash and uses the values inside to initialize itself.
Whenever the value of a flag is changed on the OBC, the flag file should be written to flash again so they stay in sync.
In some important cases, we check the value of the flag from flash and compare it to the OBC's local value. It's up to the application to decide what happens in the event of a mismatch. Usually going with the value in external flash is a good call since flash is quite radiation resistant.
If no flag file is found, it will be created and each flag will be initialized to the current value in RAM.
The flag file is built from a struct which itself contains a bunch of structs. These sub-structs are a single flag. The struct-of-structs is the flag table, which is what gets written to flash.
The system is designed so that any data type can be added to the flag table. So you can put whatever info you may need inside a flag and be sure that it's backed up if the OBC resets. All flags have a timestamp that is automatically updated when the flag data changes.
All of this wizardry is accomplished with a bunch of x-macros. Therefore, to set and get values from flags, you MUST go through the macros or everything will get messed up.
Assuming you know the name of the flag you want to use, here's how to read and write to it.
Example: GEN_TELEM
The accessor macro is used to read and write the local flag value. It's used because accessing the flag without it is a really long gross call.
Before you use the accessor macro, you need to know the names of the flag struct's members. You can look up the flag type name in the FLAG_TABLE
in obc_filesystem/sfu_flags.h
. You see that the type is telemConfig_t
. Right click that and choose "Open Declaration" to find it.
telemConfig_t looks like this:
typedef struct telem_config{
uint32_t timestamp; // timestamp of update
int16_t max; // max permissible sensor reading
int16_t min; // min permissible sensor reading
uint32_t period; // period in ms
} telemConfig_t;
Now that we know what the member types and names are, we can use the accessor macro to get/set them. The accessor macro just takes the place of the variable name.
The accessor macro format: FLAG(<flag name>, <flag member>)
Example:
uint16_t new_max = 234;
uint16_t flag_existing_period;
// Set a new max in the flag:
FLAG(GEN_TELEM, max) = new_max;
// Get the value of the flag's period:
flag_existing_period = FLAG(GEN_TELEM, period);
// Sync to external flash
writeAllFlagsToFlash()
Cool, we have successfully set and retrieved values. Now you should sync to the external flash by calling: writeAllFlagsToFlash()
.
The files you're after are obc_filesystem/sfu_flags.h
and obc_filesystem/sfu_flags.c
.