43#if RUUVI_NRF5_SDK15_FLASH_ENABLED
51#include "nrf_sdh_ble.h"
53#include "nrf_fstorage.h"
54#include "fds_internal_defs.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.
72extern uint32_t __start_storage_flash;
73extern 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__ )
87extern uint32_t __start_storage_flash;
88extern 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
112static size_t m_number_of_pages = 0;
115static rd_status_t fds_to_ruuvi_error (ret_code_t err_code)
122 case FDS_ERR_OPERATION_TIMEOUT:
125 case FDS_ERR_NOT_INITIALIZED:
128 case FDS_ERR_UNALIGNED_ADDR:
131 case FDS_ERR_INVALID_ARG:
134 case FDS_ERR_NULL_ARG:
137 case FDS_ERR_NO_OPEN_RECORDS:
140 case FDS_ERR_NO_SPACE_IN_FLASH:
143 case FDS_ERR_NO_SPACE_IN_QUEUES:
146 case FDS_ERR_RECORD_TOO_LARGE:
149 case FDS_ERR_NOT_FOUND:
152 case FDS_ERR_NO_PAGES:
155 case FDS_ERR_USER_LIMIT_REACHED:
158 case FDS_ERR_CRC_CHECK_FAILED:
164 case FDS_ERR_INTERNAL:
174static bool volatile m_fds_initialized;
176static bool volatile m_fds_processing;
178static bool m_fds_registered;
180static void fds_evt_handler (fds_evt_t
const * p_evt)
185 if (p_evt->result == FDS_SUCCESS)
187 m_fds_initialized =
true;
188 ri_log (LOG_LEVEL,
"FDS init\r\n");
195 if (p_evt->result == FDS_SUCCESS)
197 ri_log (LOG_LEVEL,
"Record written\r\n");
198 m_fds_processing =
false;
205 if (p_evt->result == FDS_SUCCESS)
207 ri_log (LOG_LEVEL,
"Record updated\r\n");
208 m_fds_processing =
false;
213 case FDS_EVT_DEL_RECORD:
215 if (p_evt->result == FDS_SUCCESS)
217 ri_log (LOG_LEVEL,
"Record deleted\r\n");
218 m_fds_processing =
false;
223 case FDS_EVT_DEL_FILE:
225 if (p_evt->result == FDS_SUCCESS)
227 ri_log (LOG_LEVEL,
"File deleted\r\n");
228 m_fds_processing =
false;
235 if (p_evt->result == FDS_SUCCESS)
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)
284 fds_stat_t stat = {0};
285 ret_code_t rc = fds_stat (&stat);
286 *size = stat.largest_contig *
sizeof (uint32_t);
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)
324 fds_record_desc_t desc = {0};
325 fds_find_token_t tok = {0};
326 ret_code_t rc = fds_record_find (page_id, record_id, &desc, &tok);
328 if (FDS_SUCCESS == rc)
332 m_fds_processing =
true;
333 rc = fds_record_delete (&desc);
336 if (FDS_SUCCESS != rc)
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)
368 fds_record_desc_t desc = {0};
369 fds_find_token_t tok = {0};
371 fds_record_t
const record =
377 .data.length_words = (data_size + 3) /
sizeof (uint32_t),
379 ret_code_t rc = fds_record_find (page_id, record_id, &desc, &tok);
382 if (FDS_SUCCESS == rc)
385 m_fds_processing =
true;
386 rc = fds_record_update (&desc, &record);
387 err_code |= fds_to_ruuvi_error (rc);
391 m_fds_processing =
false;
399 m_fds_processing =
true;
400 desc.record_id = record_id;
401 rc = fds_record_write (&desc, &record);
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)
436 fds_record_desc_t desc = {0};
437 fds_find_token_t tok = {0};
438 rc = fds_record_find (page_id, record_id, &desc, &tok);
439 err_code |= fds_to_ruuvi_error (rc);
442 if (FDS_SUCCESS == rc)
444 fds_flash_record_t record = {0};
446 rc = fds_record_open (&desc, &record);
449 if (FDS_SUCCESS != rc)
451 err_code |= fds_to_ruuvi_error (rc);
454 else if (record.p_header->length_words * 4 > data_size)
462 memcpy (data, record.p_data, record.p_header->length_words * 4);
466 rc = fds_record_close (&desc);
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;
488 ret_code_t rc = fds_gc();
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)
509 rc |= flash_bounds_set (FSTORAGE_SECTION_START, FSTORAGE_SECTION_END);
510 (void) fds_register (fds_evt_handler);
511 m_fds_registered =
true;
515 err_code |= fds_to_ruuvi_error (rc);
520 while (!m_fds_initialized) {};
523 fds_stat_t stat = {0};
525 rc = fds_stat (&stat);
527 m_number_of_pages = stat.pages_available;
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.
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