43 #if RUUVI_NRF5_SDK15_FLASH_ENABLED
51 #include "nrf_sdh_ble.h"
53 #include "nrf_fstorage.h"
55 #if (FDS_BACKEND == NRF_FSTORAGE_SD)
56 #include "nrf_fstorage_sd.h"
57 #elif (FDS_BACKEND == NRF_FSTORAGE_NVMC)
58 #include "nrf_fstorage_nvmc.h"
60 #error Invalid FDS backend.
64 #if defined(__SES_ARM)
72 extern uint32_t __start_storage_flash;
73 extern uint32_t __stop_storage_flash;
75 #define FSTORAGE_SECTION_START ((uint32_t)&__start_storage_flash)
76 #define FSTORAGE_SECTION_END ((uint32_t)&__stop_storage_flash)
77 #elif defined ( __GNUC__ )
87 extern uint32_t __start_storage_flash;
88 extern uint32_t __stop_storage_flash;
89 #define FSTORAGE_SECTION_START ((uint32_t)&__start_storage_flash)
90 #define FSTORAGE_SECTION_END ((uint32_t)&__stop_storage_flash)
110 #define LOG_LEVEL RI_LOG_LEVEL_DEBUG
112 static size_t m_number_of_pages = 0;
115 static rd_status_t fds_to_ruuvi_error (ret_code_t err_code)
174 static bool volatile m_fds_initialized;
176 static bool volatile m_fds_processing;
178 static bool m_fds_registered;
180 static void fds_evt_handler (
fds_evt_t const * p_evt)
187 m_fds_initialized =
true;
188 ri_log (LOG_LEVEL,
"FDS init\r\n");
197 ri_log (LOG_LEVEL,
"Record written\r\n");
198 m_fds_processing =
false;
207 ri_log (LOG_LEVEL,
"Record updated\r\n");
208 m_fds_processing =
false;
217 ri_log (LOG_LEVEL,
"Record deleted\r\n");
218 m_fds_processing =
false;
227 ri_log (LOG_LEVEL,
"File deleted\r\n");
228 m_fds_processing =
false;
237 ri_log (LOG_LEVEL,
"Garbage collected\r\n");
238 m_fds_processing =
false;
256 else if (
false == m_fds_initialized)
263 *size *= m_number_of_pages;
277 else if (
false == m_fds_initialized)
287 err_code |= fds_to_ruuvi_error (rc);
301 else if (
false == m_fds_initialized)
314 const uint32_t record_id)
318 if (
false == m_fds_initialized)
332 m_fds_processing =
true;
338 m_fds_processing =
false;
342 err_code |= fds_to_ruuvi_error (rc);
349 const uint32_t record_id,
const size_t data_size,
const void *
const data)
357 else if (
false == m_fds_initialized)
361 else if (m_fds_processing)
377 .data.length_words = (data_size + 3) /
sizeof (uint32_t),
385 m_fds_processing =
true;
387 err_code |= fds_to_ruuvi_error (rc);
391 m_fds_processing =
false;
399 m_fds_processing =
true;
402 err_code |= fds_to_ruuvi_error (rc);
406 m_fds_processing =
false;
416 const uint32_t record_id,
const size_t data_size,
void *
const data)
419 ret_code_t rc = NRF_SUCCESS;
425 else if (
false == m_fds_initialized)
429 else if (m_fds_processing)
439 err_code |= fds_to_ruuvi_error (rc);
451 err_code |= fds_to_ruuvi_error (rc);
470 return err_code | fds_to_ruuvi_error (rc);
477 if (
false == m_fds_initialized)
481 else if (m_fds_processing)
487 m_fds_processing =
true;
489 err_code |= fds_to_ruuvi_error (rc);
498 ret_code_t rc = NRF_SUCCESS;
500 if (m_fds_initialized)
507 if (!m_fds_registered)
511 m_fds_registered =
true;
515 err_code |= fds_to_ruuvi_error (rc);
520 while (!m_fds_initialized) {};
531 err_code |= fds_to_ruuvi_error (rc);
538 m_fds_initialized =
false;
539 m_fds_processing =
false;
546 ret_code_t rc = NRF_SUCCESS;
548 const int erase_unit = 1024;
549 #elif defined(NRF52_SERIES)
550 const int erase_unit = 4096;
552 const int total_pages = (FSTORAGE_SECTION_END - FSTORAGE_SECTION_START)
555 for (
int p = 0; (p < total_pages) && (NRF_SUCCESS == rc); p++)
557 int page = (FSTORAGE_SECTION_START / erase_unit) + p;
558 rc = sd_flash_page_erase (page);
566 return m_fds_processing;
572 const uint8_t register_num = page / 32U;
573 const uint8_t page_num = page % 32U;
576 if ( (register_num > 3) || (page_num > 31U))
580 else switch (register_num)
583 NRF_BPROT->CONFIG0 = 1 << page_num;
587 NRF_BPROT->CONFIG1 = 1 << page_num;
591 NRF_BPROT->CONFIG2 = 1 << page_num;
595 NRF_BPROT->CONFIG3 = 1 << page_num;
#define RD_ERROR_INVALID_PARAM
Invalid Parameter.
#define RD_ERROR_NULL
Null Pointer.
uint32_t rd_status_t
bitfield for representing errors
#define RD_ERROR_CHECK(error, mask)
Shorthand macro for calling the rd_error_check with current file & line.
#define RD_ERROR_RESOURCES
Not enough resources for operation.
#define RD_SUCCESS
Internal Error.
#define RD_ERROR_DATA_SIZE
Invalid Data size.
#define RD_ERROR_NO_MEM
No Memory for operation.
#define RD_ERROR_TIMEOUT
Operation timed out.
#define RD_ERROR_SELFTEST
Self-test fail.
#define RD_ERROR_NOT_FOUND
Not found.
#define RD_ERROR_INVALID_STATE
Invalid state, operation disallowed in this state.
#define RD_ERROR_INTERNAL
Internal Error.
#define RD_ERROR_BUSY
Busy.
rd_status_t ri_flash_gc_run(void)
Run garbage collection.
bool ri_flash_is_busy()
Check if flash is busy.
rd_status_t ri_flash_uninit(void)
Unintialize flash. After uninitialization only initialization can be used.
rd_status_t ri_flash_page_size_get(size_t *size)
Get size of usable page, excluding any overhead bytes If returned value is N, a record of N bytes mus...
rd_status_t ri_flash_total_size_get(size_t *size)
Get total size of usable flash, excluding any overhead bytes.
void ri_flash_purge(void)
Purge flash.
rd_status_t ri_flash_record_set(const uint32_t page_id, const uint32_t record_id, const size_t data_size, const void *const data)
Set data to record in page.
rd_status_t ri_flash_init(void)
rd_status_t ri_flash_record_delete(const uint32_t file_id, const uint32_t record_id)
Mark a record for deletion.
rd_status_t ri_flash_free_size_get(size_t *size)
Get total size of free flash.
rd_status_t ri_flash_protect(const size_t page)
rd_status_t ri_flash_record_get(const uint32_t page_id, const uint32_t record_id, const size_t data_size, void *const data)
Get data from record in page.
void ri_log(const ri_log_severity_t severity, const char *const message)
Queues messages into log.
ret_code_t fds_record_write(fds_record_desc_t *p_desc, fds_record_t const *p_record)
Function for writing a record to flash.
ret_code_t fds_record_find(uint16_t file_id, uint16_t record_key, fds_record_desc_t *p_desc, fds_find_token_t *p_token)
Function for searching for records with a given record key in a file.
ret_code_t fds_init(void)
Function for initializing the module.
ret_code_t fds_stat(fds_stat_t *p_stat)
Function for retrieving file system statistics.
ret_code_t flash_bounds_set(const uint32_t start_addr, const uint32_t end_addr)
Set physical boundaries for FDS.
ret_code_t fds_gc(void)
Function for running garbage collection.
ret_code_t fds_record_update(fds_record_desc_t *p_desc, fds_record_t const *p_record)
Function for updating a record.
ret_code_t fds_record_open(fds_record_desc_t *p_desc, fds_flash_record_t *p_flash_record)
Function for opening a record for reading.
ret_code_t fds_register(fds_cb_t cb)
Function for registering an FDS event handler.
ret_code_t fds_record_close(fds_record_desc_t *p_desc)
Function for closing a record.
ret_code_t fds_record_delete(fds_record_desc_t *p_desc)
Function for deleting a record.
@ FDS_ERR_NOT_FOUND
Error. The record was not found.
@ FDS_ERR_INTERNAL
Error. An internal error occurred.
@ FDS_ERR_INVALID_ARG
Error. The parameter contains invalid data.
@ FDS_ERR_NO_PAGES
Error. No flash pages are available.
@ FDS_ERR_USER_LIMIT_REACHED
Error. The maximum number of users has been reached.
@ FDS_ERR_NO_SPACE_IN_QUEUES
Error. There is no space in the internal queues.
@ FDS_ERR_RECORD_TOO_LARGE
Error. The record exceeds the maximum allowed size.
@ FDS_ERR_NULL_ARG
Error. The parameter is NULL.
@ FDS_ERR_NO_OPEN_RECORDS
Error. The record is not open, so it cannot be closed.
@ FDS_ERR_UNALIGNED_ADDR
Error. The input data is not aligned to a word boundary.
@ FDS_ERR_BUSY
Error. The underlying flash subsystem was busy.
@ FDS_ERR_NO_SPACE_IN_FLASH
Error. There is no space in flash memory.
@ FDS_ERR_OPERATION_TIMEOUT
Error. The operation timed out.
@ FDS_SUCCESS
The operation completed successfully.
@ FDS_ERR_CRC_CHECK_FAILED
Error. The CRC check failed.
@ FDS_ERR_NOT_INITIALIZED
Error. The module has not been initialized.
@ FDS_EVT_DEL_FILE
Event for fds_file_delete.
@ FDS_EVT_INIT
Event for fds_init.
@ FDS_EVT_GC
Event for fds_gc.
@ FDS_EVT_DEL_RECORD
Event for fds_record_delete.
@ FDS_EVT_UPDATE
Event for fds_record_update.
@ FDS_EVT_WRITE
Event for fds_record_write and fds_record_write_reserved.
Header to enable and disable module compilation.
Ruuvi error codes and error check function.
Interface functions to persistent flash storage.
rd_status_t ri_delay_ms(uint32_t time)
Delay a given number of milliseconds.
#define FDS_VIRTUAL_PAGE_SIZE
fds_evt_id_t id
The event ID. See fds_evt_id_t.
ret_code_t result
The result of the operation related to this event.
A token to keep information about the progress of fds_record_find, fds_record_find_by_key,...
Structure that can be used to read the contents of a record stored in flash.
fds_header_t const * p_header
Location of the record header in flash.
void const * p_data
Location of the record data in flash.
The record descriptor structure that is used to manipulate records.
uint32_t record_id
The unique record ID.
A record to be written to flash.
uint16_t file_id
The ID of the file that the record belongs to.
uint16_t pages_available
The number of pages available.
uint16_t largest_contig
The largest number of free contiguous words in the file system.