Bluenet
5.7.0
Bluenet, firmware for nRF52 smart home devices
|
Stores state values in RAM and/or FLASH. More...
#include <cs_State.h>
Public Member Functions | |
virtual | ~State () |
void | init (boards_config_t *boardsConfig) |
Initialize the State object with the board configuration. More... | |
cs_ret_code_t | get (cs_state_data_t &data, const PersistenceMode mode=PersistenceMode::STRATEGY1) |
Get copy of a state value. More... | |
cs_ret_code_t | get (const CS_TYPE type, void *value, size16_t size) |
Convenience function for get() with id 0. More... | |
bool | isTrue (CS_TYPE type, const PersistenceMode mode=PersistenceMode::STRATEGY1) |
Shorthand for get() for boolean data types, and id 0. More... | |
cs_ret_code_t | getIds (CS_TYPE type, std::vector< cs_state_id_t > *&ids) |
Get a list of IDs for given type. More... | |
cs_ret_code_t | set (const cs_state_data_t &data, PersistenceMode mode=PersistenceMode::STRATEGY1) |
Set state to new value, via copy. More... | |
cs_ret_code_t | set (const CS_TYPE type, void *value, size16_t size) |
Convenience function for set(). More... | |
cs_ret_code_t | setDelayed (const cs_state_data_t &data, uint8_t delay) |
Set the state to a new value, but delay the write to flash. More... | |
cs_ret_code_t | setThrottled (const cs_state_data_t &data, uint32_t period) |
Write variable to flash in a throttled mode. More... | |
cs_ret_code_t | verifySizeForGet (const cs_state_data_t &data) |
Verify size of user data for getting a state. More... | |
cs_ret_code_t | verifySizeForSet (const cs_state_data_t &data) |
Verify size of user data for setting a state. More... | |
cs_ret_code_t | remove (const CS_TYPE &type, cs_state_id_t id, const PersistenceMode mode=PersistenceMode::STRATEGY1) |
Remove a state variable. More... | |
void | factoryReset () |
Erase all used persistent storage. More... | |
cs_ret_code_t | cleanUp () |
Clean up persistent storage. More... | |
cs_ret_code_t | getViaPointer (cs_state_data_t &data, const PersistenceMode mode=PersistenceMode::STRATEGY1) |
Get pointer to state value. More... | |
cs_ret_code_t | setViaPointer (CS_TYPE type) |
Update state value. More... | |
void | startWritesToFlash () |
After calling this, state is allowed to write to flash. More... | |
void | handleStorageError (cs_storage_operation_t operation, CS_TYPE type, cs_state_id_t id) |
Internal usage. More... | |
void | handleEvent (event_t &event) |
Handle (crownstone) events. More... | |
![]() | |
BaseClass () | |
bool | isInitialized (uint8_t i=0) |
void | setInitialized (uint8_t i=0) |
void | setUninitialized (uint8_t i=0) |
Static Public Member Functions | |
static State & | getInstance () |
Get a reference to the State object. More... | |
Protected Member Functions | |
cs_ret_code_t | findInRam (const CS_TYPE &type, cs_state_id_t id, size16_t &index_in_ram) |
Find given type in ram. More... | |
cs_ret_code_t | storeInRam (const cs_state_data_t &data, size16_t &index_in_ram) |
Stores state variable in ram. More... | |
cs_ret_code_t | storeInRam (const cs_state_data_t &data) |
Convenience function, in case you're not interested in index in ram. More... | |
cs_ret_code_t | loadFromRam (cs_state_data_t &data) |
Copies from ram to target buffer. More... | |
cs_state_data_t & | addToRam (const CS_TYPE &type, cs_state_id_t id, size16_t size) |
Adds a new state_data struct to ram. More... | |
cs_ret_code_t | removeFromRam (const CS_TYPE &type, cs_state_id_t id) |
Removed a state variable from ram. More... | |
cs_ret_code_t | compareWithRam (const cs_state_data_t &data, uint32_t &cmp_result) |
Check a particular value with the value currently in ram. More... | |
cs_ret_code_t | storeInFlash (size16_t &index_in_ram) |
Writes state variable in ram to flash. More... | |
cs_ret_code_t | removeFromFlash (const CS_TYPE &type, const cs_state_id_t id) |
Remove given id of given type from flash. More... | |
cs_ret_code_t | addToQueue (StateQueueOp operation, const CS_TYPE &type, cs_state_id_t id, uint32_t delayMs, const StateQueueMode mode) |
Add an operation to queue. More... | |
cs_ret_code_t | allocate (cs_state_data_t &data) |
void | delayedStoreTick () |
Protected Attributes | |
Storage * | _storage |
boards_config_t * | _boardsConfig |
std::vector< cs_state_data_t > | _ram_data_register |
Stores state data structs with pointers to state data. More... | |
std::vector< cs_id_list_t > | _idsCache |
Stores list of existing ids for certain types. More... | |
std::vector< cs_state_store_queue_t > | _store_queue |
Stores the queue of flash operations. More... | |
bool | _startedWritingToFlash = false |
bool | _performingFactoryReset = false |
Private Member Functions | |
State () | |
State constructor, singleton, thus made private. More... | |
State (State const &) | |
State copy constructor, singleton, thus made private. More... | |
void | operator= (State const &) |
Assignment operator, singleton, thus made private. More... | |
cs_ret_code_t | setInternal (const cs_state_data_t &data, PersistenceMode mode) |
cs_ret_code_t | removeInternal (const CS_TYPE &type, cs_state_id_t id, const PersistenceMode mode) |
bool | handleFactoryResetResult (cs_ret_code_t retCode) |
Handle factory reset result. More... | |
cs_ret_code_t | getDefaultValue (cs_state_data_t &data) |
cs_ret_code_t | getIdsFromFlash (const CS_TYPE &type, std::vector< cs_state_id_t > *&ids) |
Get and cache all IDs with given type from flash. More... | |
cs_ret_code_t | addId (const CS_TYPE &type, cs_state_id_t id) |
Add ID to list of cached IDs. More... | |
cs_ret_code_t | remId (const CS_TYPE &type, cs_state_id_t id) |
Remove ID from list of cached IDs. More... | |
![]() | |
EventListener () | |
virtual | ~EventListener () |
unregisters the listener. More... | |
virtual void | handleEvent (event_t &event)=0 |
Handle events. More... | |
void | listen () |
Registers this with the EventDispatcher. More... | |
Stores state values in RAM and/or FLASH.
Each state type always has a FIRMWARE_DEFAULT value. Values that are set, always take precedence over the FIRMWARE_DEFAULT.
Values like chip temperature, that don't have to be stored over reboots should be stored in and read from RAM.
Values like CONFIG_BOOT_DELAY should be known over reboots of the device. Moreover, they should also persist over firmware updates. These values are stored in FLASH. If the values are not changed, they should NOT be stored to FLASH. They can then immediately be read from the FIRMWARE_DEFAULT. If these values are stored in FLASH, they always take precedence over FIRMWARE_DEFAULT values. Values that are stored in FLASH will be cached in RAM, to prevent having to read from FLASH every time. This complete persistence strategy is called STRATEGY1.
If a new firmware has a new FIRMWARE_DEFAULT that should be enforced, we need to explicitly remove the value from FLASH before updating the firmware. For example, a new CONFIG_BOOT_DELAY may have to be enforced, or else it might go into an infinite reboot loop.
For each state type it is defined whether it should be stored in RAM or FLASH.
All values that are stored to flash should also be stored in RAM. This is required, because storing to flash is asynchronous, the value must remain in RAM at least until the write is done.
Storing to flash can also fail, in which case it can be retried later. The state type will be put in a queue and retried after about STATE_RETRY_STORE_DELAY_MS ms.
Get procedure:
Set procedure:
|
virtual |
|
private |
State constructor, singleton, thus made private.
|
private |
State copy constructor, singleton, thus made private.
|
private |
Add ID to list of cached IDs.
Will NOT create a new list if no list for this type exists.
|
protected |
Add an operation to queue.
Entries with the same type and operation will be overwritten. Write and remove of the same type will also overwrite each other.
[in] | operation | Type of operation. |
[in] | fileId | Flash file ID of the entry. |
[in] | type | State type. |
[in] | delayMs | Delay in ms. |
|
protected |
|
protected |
cs_ret_code_t State::cleanUp | ( | ) |
Clean up persistent storage.
Permanently deletes removed state variables, and defragments the persistent storage.
|
protected |
Check a particular value with the value currently in ram.
[in] | data | Data with type, id, value, and size. |
[out] | cmp_result | Value that indicates comparison (equality indicated by 0). |
|
protected |
void State::factoryReset | ( | ) |
Erase all used persistent storage.
|
protected |
Find given type in ram.
[in] | Type | to search for. |
[in] | Id | to search for. |
[out] | Index | in ram register where the type was found. |
cs_ret_code_t State::get | ( | const CS_TYPE | type, |
void * | value, | ||
size16_t | size | ||
) |
Convenience function for get() with id 0.
Avoids having to create a temp every time you want to get a state variable.
cs_ret_code_t State::get | ( | cs_state_data_t & | data, |
const PersistenceMode | mode = PersistenceMode::STRATEGY1 |
||
) |
Get copy of a state value.
[in,out] | data | Data struct with state type, id, data, and size. See cs_state_data_t. |
[in] | mode | Indicates whether to get data from RAM, FLASH, FIRMWARE_DEFAULT, or a combination of this. |
|
private |
cs_ret_code_t State::getIds | ( | CS_TYPE | type, |
std::vector< cs_state_id_t > *& | ids | ||
) |
Get a list of IDs for given type.
Example usage: std::vector<cs_state_id_t>* ids = nullptr; retCode = State::getInstance().getIds(CS_TYPE::STATE_EXAMPLE, ids); if (retCode == ERR_SUCCESS) { for (auto id: *ids) {
[in] | type | State type. |
[out] | ids | Pointer to list of ids. This is not a copy, so make sure not to modify this list. |
|
private |
Get and cache all IDs with given type from flash.
[in] | type | State type. |
[out] | ids | List of ids. |
cs_ret_code_t State::getViaPointer | ( | cs_state_data_t & | data, |
const PersistenceMode | mode = PersistenceMode::STRATEGY1 |
||
) |
Get pointer to state value.
TODO: implement You can use this to avoid copying large state values of fixed length. However, you have to make sure to call setViaPointer() immediately after any change made in the data.
[in,out] | data | Data struct with state type and size. |
|
virtual |
Handle (crownstone) events.
Implements EventListener.
|
private |
Handle factory reset result.
@retrun False when factory reset needs to be retried.
void State::handleStorageError | ( | cs_storage_operation_t | operation, |
CS_TYPE | type, | ||
cs_state_id_t | id | ||
) |
Internal usage.
void State::init | ( | boards_config_t * | boardsConfig | ) |
Initialize the State object with the board configuration.
[in] | boardsConfig | Board configuration (pin layout, etc.). |
bool State::isTrue | ( | CS_TYPE | type, |
const PersistenceMode | mode = PersistenceMode::STRATEGY1 |
||
) |
|
protected |
Copies from ram to target buffer.
Does not check if target buffer has a large enough size.
[in] | data.type | Type of data. |
[in] | data.id | Identifier of the data (to get a particular instance of a type). |
[out] | data.size | The size of the data retrieved. |
[out] | data.value | The data itself. |
|
private |
Assignment operator, singleton, thus made private.
|
private |
Remove ID from list of cached IDs.
cs_ret_code_t State::remove | ( | const CS_TYPE & | type, |
cs_state_id_t | id, | ||
const PersistenceMode | mode = PersistenceMode::STRATEGY1 |
||
) |
Remove a state variable.
[in] | type | The state type to be removed. |
[in] | mode | Indicates whether to remove data from RAM, FLASH, or a combination of this. |
|
protected |
|
protected |
Removed a state variable from ram.
Frees the data pointer and struct.
[in] | type | State type. |
|
private |
cs_ret_code_t State::set | ( | const cs_state_data_t & | data, |
PersistenceMode | mode = PersistenceMode::STRATEGY1 |
||
) |
Set state to new value, via copy.
[in] | data | Data struct with state type, optional id, data, and size. |
[in] | mode | Indicates whether to set data in RAM, FLASH, or a combination of this. |
cs_ret_code_t State::set | ( | const CS_TYPE | type, |
void * | value, | ||
size16_t | size | ||
) |
Convenience function for set().
Avoids having to create a temp every time you want to set a state variable.
cs_ret_code_t State::setDelayed | ( | const cs_state_data_t & | data, |
uint8_t | delay | ||
) |
Set the state to a new value, but delay the write to flash.
Assumes persistence mode STRATEGY1. Use this when you know a lot of sets of the same type may be done in a short time period. Each time this function is called, the timeout is reset.
[in] | data | Data struct with state type, data, and size. |
[in] | delay | How long the delay should be, in seconds. |
|
private |
cs_ret_code_t State::setThrottled | ( | const cs_state_data_t & | data, |
uint32_t | period | ||
) |
Write variable to flash in a throttled mode.
This function setThrottled will immediately write a value to flash, except when this has happened in the last period (indicated by a parameter). If this function is called during this period, the value will be updated in ram. Only after this period this value will then be written to flash. Also after this time, this will lead to a period in which throttling happens. For example, when the period parameter is set to 60000, all calls to setThrottled will result to calls to flash at a maximum rate of once per minute (for given data type).
[in] | data | Data to store. |
[in] | period | Period in seconds that throttling will be in effect. Must be smaller than CS_STATE_QUEUE_DELAY_SECONDS_MAX. |
cs_ret_code_t State::setViaPointer | ( | CS_TYPE | type | ) |
Update state value.
TODO: implement Call this function after data has been changed via pointer. This makes sure the update will be propagated correctly.
[in] | type | The state type that has been changed. |
void State::startWritesToFlash | ( | ) |
After calling this, state is allowed to write to flash.
Should be called once all reads are finished.
This is a quickfix to prevent failing flash reads during garbage collection. To properly fix this, read should be blocking. This can be done by handling FDS events in the interrupt, instead of via the app_scheduler. In those events, the busy state can be cleared, while cs events can be dispatched via the app_scheduler. Then, the read function can just wait with nrf_delay() until no longer busy.
|
protected |
Writes state variable in ram to flash.
Can return ERR_BUSY, in which case you have to retry again later.
[in] | index | Index in ram with the data to be written. |
|
protected |
Convenience function, in case you're not interested in index in ram.
|
protected |
Stores state variable in ram.
Allocates memory when not in ram yet, or when size changed.
[in] | data | Data to be stored. |
[out] | index_in_ram | Index where the data is stored. |
cs_ret_code_t State::verifySizeForGet | ( | const cs_state_data_t & | data | ) |
Verify size of user data for getting a state.
[in] | data | Data struct with state type, target, and size. |
cs_ret_code_t State::verifySizeForSet | ( | const cs_state_data_t & | data | ) |
Verify size of user data for setting a state.
[in] | data | Data struct with state type, data, and size. |
|
protected |
|
protected |
Stores list of existing ids for certain types.
|
protected |
|
protected |
Stores state data structs with pointers to state data.
|
protected |
|
protected |
|
protected |
Stores the queue of flash operations.