Bluenet
5.7.0
Bluenet, firmware for nRF52 smart home devices
|
Class to store items persistently in flash (persistent) memory. More...
#include <cs_Storage.h>
Public Member Functions | |
cs_ret_code_t | init () |
bool | isInitialized () |
bool | isBusy () |
void | setErrorCallback (cs_storage_error_callback_t callback) |
Set the callback for errors. More... | |
cs_ret_code_t | findFirst (CS_TYPE type, cs_state_id_t &id) |
Find first id of stored values of given type. More... | |
cs_ret_code_t | findNext (CS_TYPE type, cs_state_id_t &id) |
Find next id of stored values of given type. More... | |
cs_ret_code_t | read (cs_state_data_t &data) |
Find and read stored value of given type and id. More... | |
cs_ret_code_t | readV3ResetCounter (cs_state_data_t &data) |
Read the old (v3) reset counter. More... | |
cs_ret_code_t | readFirst (cs_state_data_t &data) |
Find and read from first stored value of given type. More... | |
cs_ret_code_t | readNext (cs_state_data_t &data) |
Find and read next stored value of given type. More... | |
cs_ret_code_t | write (const cs_state_data_t &data) |
Write to persistent storage. More... | |
cs_ret_code_t | remove (CS_TYPE type, cs_state_id_t id) |
Remove value of given type and id. More... | |
cs_ret_code_t | remove (CS_TYPE type) |
Remove all values of a type. More... | |
cs_ret_code_t | remove (cs_state_id_t id) |
Remove all values with given id. More... | |
cs_ret_code_t | factoryReset () |
Perform factory reset. More... | |
cs_ret_code_t | garbageCollect () |
Garbage collection reclaims the flash space that is occupied by records that have been deleted, or that failed to be completely written due to, for example, a power loss. More... | |
cs_ret_code_t | eraseAllPages () |
Erase all flash pages used by FDS. More... | |
cs_ret_code_t | erasePages (const CS_TYPE doneEvent, void *startAddress, void *endAddress) |
Erase flash pages. More... | |
uint8_t * | allocate (size16_t &size) |
Allocate ram that is correctly aligned and padded. More... | |
void | handleFileStorageEvent (fds_evt_t const *p_fds_evt) |
Handle FDS events. More... | |
void | handleFlashOperationSuccess () |
Handle FDS SOC event NRF_EVT_FLASH_OPERATION_SUCCESS. More... | |
void | handleFlashOperationError () |
Handle FDS SOC event NRF_EVT_FLASH_OPERATION_ERROR. More... | |
Static Public Member Functions | |
static Storage & | getInstance () |
Returns the singleton instance of this class. More... | |
Private Member Functions | |
Storage ()=default | |
Storage (Storage const &)=delete | |
void | operator= (Storage const &)=delete |
cs_ret_code_t | findNextInternal (uint16_t recordKey, uint16_t &fileId) |
Find next fileId for given recordKey. More... | |
cs_ret_code_t | readNextInternal (uint16_t recordKey, uint16_t &fileId, uint8_t *buf, uint16_t size) |
Read next fileId for given recordKey. More... | |
cs_ret_code_t | readRecord (fds_record_desc_t recordDesc, uint8_t *buf, uint16_t size, uint16_t &fileId) |
Read a record: copy data to buffer, and sets fileId. More... | |
ret_code_t | writeInternal (const cs_state_data_t &data) |
Write to persistent storage. More... | |
ret_code_t | garbageCollectInternal () |
bool | isErasingPages () |
void | eraseNextPage () |
Erase next page, started via eraseAllPages(). More... | |
cs_ret_code_t | continueFactoryReset () |
Continue the factory reset process. More... | |
size16_t | getPaddedSize (size16_t size) |
Returns size after padding for flash. More... | |
uint16_t | getFileId (cs_state_id_t valueId) |
Get file id, given state value id. More... | |
cs_state_id_t | getStateId (uint16_t fileId) |
Get state value id, given file id. More... | |
bool | isValidRecordKey (uint16_t recordKey) |
bool | isValidFileId (uint16_t fileId) |
void | initSearch (CS_TYPE type) |
Start a new search, where the user wants to iterate over a certain type. More... | |
void | initSearch () |
Start a new search. More... | |
ret_code_t | exists (cs_file_id_t file_id, uint16_t recordKey, fds_record_desc_t &record_desc, bool &result) |
Check if a type of record exists and return the record descriptor. More... | |
void | setBusy (uint16_t recordKey) |
void | clearBusy (uint16_t recordKey) |
bool | isBusy (uint16_t recordKey) |
cs_ret_code_t | getErrorCode (ret_code_t code) |
void | handleWriteEvent (fds_evt_t const *p_fds_evt) |
void | handleRemoveRecordEvent (fds_evt_t const *p_fds_evt) |
void | handleRemoveFileEvent (fds_evt_t const *p_fds_evt) |
void | handleGarbageCollectionEvent (fds_evt_t const *p_fds_evt) |
Private Attributes | |
bool | _initialized = false |
bool | _registeredFds = false |
cs_storage_error_callback_t | _errorCallback = NULL |
fds_find_token_t | _findToken |
CS_TYPE | _currentSearchType = CS_TYPE::CONFIG_DO_NOT_USE |
bool | _collectingGarbage = false |
bool | _removingFile = false |
bool | _performingFactoryReset = false |
std::vector< uint16_t > | _busyRecordKeys |
uint32_t | _erasePage = 0 |
Next page to erase. More... | |
uint32_t | _eraseEndPage = 0 |
Page that should not be erased. More... | |
CS_TYPE | _eraseDoneEvent = CS_TYPE::CONFIG_DO_NOT_USE |
Friends | |
class | TestAccess< Storage > |
Class to store items persistently in flash (persistent) memory.
This class provides functions to initialize, clear, write and read persistent memory (flash) through the use of Flash Data Storage.
The information on the Flash Data Storage from Nordic can be found at the link: https://www.nordicsemi.com/DocLib/Content/SDK_Doc/nRF5_SDK/v15-2-0/lib_fds old: https://infocenter.nordicsemi.com/index.jsp?topic=%2Fcom.nordic.infocenter.sdk%2Fdita%2Fsdk%2Fnrf5_sdk.html
CS_TYPE is used as record key.
Garbage collection will be automatically started by this class when needed.
When a record is corrupted, most likely in case of power loss while writing, the CRC check will fail when opening a file. In this case the record will be deleted (TODO).
Only one record for each record key should exist. In case there are multiple (duplicates), they will be removed (TODO). Since FDS always appends records, it is assumed that the last valid record should be kept. Checking for duplicates is done for each write and each read.
Some operations will block other operations. For example, you can't write a record while performing garbage collection. You can't write a record while it's already being written. This is what the "busy" functions are for. Each type can be set busy multiple times, for example in case multiple records of the same type are being deleted.
FDS internally uses events NRF_EVT_FLASH_OPERATION_SUCCESS and NRF_EVT_FLASH_OPERATION_ERROR. These events don't give any context of the operation, so it is not adviced to use FDS together with something else that writes to flash (like Flash Manager).
|
privatedefault |
|
privatedelete |
uint8_t * Storage::allocate | ( | size16_t & | size | ) |
Allocate ram that is correctly aligned and padded.
[in,out] | size | Requested size, afterwards set to the allocated size. |
|
private |
|
private |
Continue the factory reset process.
ERR_SUCCESS | Successfully started factory reset process. |
ERR_BUSY | Busy, restart the whole factory reset from the beginning. |
other | Other errors. |
cs_ret_code_t Storage::eraseAllPages | ( | ) |
Erase all flash pages used by FDS.
This should only be used to recover from a failing init.
ERR_SUCCESS | When successfully started erasing all pages. |
ERR_NOT_AVAILABLE | When you can't use this function (storage initialized already). |
|
private |
Erase next page, started via eraseAllPages().
cs_ret_code_t Storage::erasePages | ( | const CS_TYPE | doneEvent, |
void * | startAddress, | ||
void * | endAddress | ||
) |
Erase flash pages.
Must be called before storage is initialized.
[in] | doneEvent | Type of event that should be sent when pages have been erased. |
[in] | startAddress | Address of first page to erase. |
[in] | endAddress | Address of first page not to erase. |
ERR_SUCCESS | When successfully started erasing all pages. |
ERR_NOT_AVAILABLE | When you can't use this function (storage initialized already). |
|
private |
Check if a type of record exists and return the record descriptor.
[in] | file_id | File id to search. |
[in] | recordKey | Record key to search for. |
[out] | record_desc | Record descriptor, used to manipulate records. |
[out] | result | True if record was found. |
cs_ret_code_t Storage::factoryReset | ( | ) |
Perform factory reset.
Make sure to restart factory reset on any error callback.
ERR_WAIT_FOR_SUCCESS | Successfully started removing a record. |
ERR_SUCCESS | All records have been removed. |
ERR_BUSY | Busy, try again later. |
other | Other errors, maybe retry again later? |
cs_ret_code_t Storage::findFirst | ( | CS_TYPE | type, |
cs_state_id_t & | id | ||
) |
Find first id of stored values of given type.
NOTE: you should complete or abort this findFirst() / findNext() before starting a new one.
[in] | type | Type to search for. |
[out] | id | ID of the found value. |
ERR_SUCCESS | When successful. |
ERR_NOT_FOUND | When the first id of this type was not found. |
ERR_BUSY | When busy, try again later. |
cs_ret_code_t Storage::findNext | ( | CS_TYPE | type, |
cs_state_id_t & | id | ||
) |
Find next id of stored values of given type.
NOTE: must be called immediately after findFirst(), no other storage operations should be done in between.
[in] | type | Type to search for. |
[out] | id | ID of the found value. |
ERR_SUCCESS | When successful. |
ERR_NOT_FOUND | When the next id of this type was not found. |
ERR_WRONG_STATE | When not called after findFirst(), or another storage operation was done in between. |
ERR_BUSY | When busy, try again later. |
|
private |
Find next fileId for given recordKey.
cs_ret_code_t Storage::garbageCollect | ( | ) |
Garbage collection reclaims the flash space that is occupied by records that have been deleted, or that failed to be completely written due to, for example, a power loss.
ERR_SUCCESS | When successfully started garbage collection. |
ERR_BUSY | When busy, try again later. |
|
private |
|
private |
|
private |
Get file id, given state value id.
|
inlinestatic |
Returns the singleton instance of this class.
|
private |
Get state value id, given file id.
void Storage::handleFileStorageEvent | ( | fds_evt_t const * | p_fds_evt | ) |
Handle FDS events.
void Storage::handleFlashOperationError | ( | ) |
Handle FDS SOC event NRF_EVT_FLASH_OPERATION_ERROR.
void Storage::handleFlashOperationSuccess | ( | ) |
Handle FDS SOC event NRF_EVT_FLASH_OPERATION_SUCCESS.
|
private |
|
private |
|
private |
|
private |
cs_ret_code_t Storage::init | ( | ) |
|
private |
Start a new search.
Call before using _findToken
|
private |
Start a new search, where the user wants to iterate over a certain type.
bool Storage::isBusy | ( | ) |
|
private |
|
private |
|
inline |
|
private |
|
private |
|
privatedelete |
cs_ret_code_t Storage::read | ( | cs_state_data_t & | data | ) |
Find and read stored value of given type and id.
In case of duplicates (values with same type and id), you will get the latest value.
[in,out] | data | Data struct with type and id to read. Pointer and size will be set afterwards. |
ERR_SUCCESS | When successful. |
ERR_NOT_FOUND | When the type was not found. |
ERR_WRONG_PAYLOAD_LENGTH | When the given size does not match the stored size. |
ERR_BUSY | When busy, try again later. |
cs_ret_code_t Storage::readFirst | ( | cs_state_data_t & | data | ) |
Find and read from first stored value of given type.
NOTE: you should complete or abort this readFirst() / readNext() before starting a new one.
[in,out] | data | Data struct with type to read. ID, pointer, and size will be set afterwards. |
ERR_SUCCESS | When successful. |
ERR_NOT_FOUND | When the type was not found. |
ERR_WRONG_PAYLOAD_LENGTH | When the given size does not match the stored size. |
ERR_BUSY | When busy, try again later. |
cs_ret_code_t Storage::readNext | ( | cs_state_data_t & | data | ) |
Find and read next stored value of given type.
NOTE: must be called immediately after readFirst(), no other storage operations should be done in between.
When iterating: just keep overwriting, so in case of duplicates (same type and id), you end up with the latest value.
[in,out] | data | Data struct with type to read. ID, pointer, and size will be set afterwards. |
ERR_SUCCESS | When successful. |
ERR_NOT_FOUND | When the type was not found. |
ERR_WRONG_PAYLOAD_LENGTH | When the given size does not match the stored size. |
ERR_BUSY | When busy, try again later. |
|
private |
Read next fileId for given recordKey.
|
private |
Read a record: copy data to buffer, and sets fileId.
Only returns success when data has been copied to buffer.
cs_ret_code_t Storage::readV3ResetCounter | ( | cs_state_data_t & | data | ) |
Read the old (v3) reset counter.
Made to transfer reset counter from old location to new.
[in,out] | data | Data struct with type and id to read. Pointer and size will be set afterwards. |
cs_ret_code_t Storage::remove | ( | cs_state_id_t | id | ) |
Remove all values with given id.
[in] | id | ID of the values to remove. |
ERR_SUCCESS | When successfully started removing. |
ERR_NOT_FOUND | When no match was not found, consider this a success, but don't wait for an event. |
ERR_BUSY | When busy, try again later. |
ERR_NOT_INITIALIZED | When storage hasn't been initialized yet. |
cs_ret_code_t Storage::remove | ( | CS_TYPE | type | ) |
Remove all values of a type.
[in] | type | Type to remove. |
ERR_SUCCESS | When successfully started removing the type. |
ERR_NOT_FOUND | When no match was not found, consider this a success, but don't wait for an event. |
ERR_BUSY | When busy, try again later. |
ERR_NOT_INITIALIZED | When storage hasn't been initialized yet. |
cs_ret_code_t Storage::remove | ( | CS_TYPE | type, |
cs_state_id_t | id | ||
) |
Remove value of given type and id.
[in] | type | Type to remove. |
[in] | id | ID of value to remove. |
ERR_SUCCESS | When successfully started removing the value. |
ERR_NOT_FOUND | When no match was found, consider this a success, but don't wait for an event. |
ERR_BUSY | When busy, try again later. |
ERR_NOT_INITIALIZED | When storage hasn't been initialized yet. |
|
private |
void Storage::setErrorCallback | ( | cs_storage_error_callback_t | callback | ) |
Set the callback for errors.
These are errors like timeouts, that come in after a write/read/remove function returned.
[in] | callback | Function to be called when an error occurred. |
cs_ret_code_t Storage::write | ( | const cs_state_data_t & | data | ) |
Write to persistent storage.
It is assumed that data pointer was allocated by this class.
Automatically starts garbage collection when needed.
[in] | data | Data struct with type, data pointer, and size. |
ERR_SUCCESS | When successfully started to write. |
ERR_BUSY | When busy, try again later. |
ERR_NO_SPACE | When there is no space, not even after garbage collection. |
|
private |
Write to persistent storage.
|
friend |
|
private |
|
private |
|
private |
|
private |
|
private |
Page that should not be erased.
Used by eraseAllPages().
|
private |
Next page to erase.
Used by eraseAllPages().
|
private |
|
private |
|
private |
|
private |
|
private |
|
private |