123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624 |
- #include "sdk_common.h"
- #if NRF_MODULE_ENABLED(NRF_FSTORAGE)
- #include "nrf_fstorage_sd.h"
- #include <stdint.h>
- #include <string.h>
- #include <stdbool.h>
- #include "nordic_common.h"
- #include "nrf_soc.h"
- #include "nrf_sdh.h"
- #include "nrf_sdh_soc.h"
- #include "nrf_atomic.h"
- #include "nrf_atfifo.h"
- #include "app_util_platform.h"
- #if (NRF_FSTORAGE_SD_MAX_WRITE_SIZE % 4)
- #error NRF_FSTORAGE_SD_MAX_WRITE_SIZE must be a multiple of the word size.
- #endif
- typedef enum
- {
- NRF_FSTORAGE_OP_WRITE,
- NRF_FSTORAGE_OP_ERASE
- } nrf_fstorage_sd_opcode_t;
- ANON_UNIONS_ENABLE;
- typedef struct
- {
- nrf_fstorage_t const * p_fs;
- nrf_fstorage_sd_opcode_t op_code;
- void * p_param;
- union
- {
- struct
- {
- void const * p_src;
- uint32_t dest;
- uint32_t len;
- uint32_t offset;
- } write;
- struct
- {
- uint32_t page;
- uint32_t progress;
- uint32_t pages_to_erase;
- } erase;
- };
- } nrf_fstorage_sd_op_t;
- ANON_UNIONS_DISABLE;
- typedef enum
- {
- NRF_FSTORAGE_STATE_IDLE,
- NRF_FSTORAGE_STATE_OP_PENDING,
- NRF_FSTORAGE_STATE_OP_EXECUTING,
- } nrf_fstorage_sd_state_t;
- typedef struct
- {
- nrf_atomic_flag_t initialized;
- nrf_atomic_flag_t queue_running;
-
- nrf_fstorage_sd_state_t state;
- uint32_t retries;
- bool sd_enabled;
- bool paused;
-
- } nrf_fstorage_sd_work_t;
- void nrf_fstorage_sys_evt_handler(uint32_t, void *);
- bool nrf_fstorage_sdh_req_handler(nrf_sdh_req_evt_t, void *);
- void nrf_fstorage_sdh_state_handler(nrf_sdh_state_evt_t, void *);
- static nrf_fstorage_info_t m_flash_info =
- {
- #if defined(NRF51)
- .erase_unit = 1024,
- #elif defined(NRF52_SERIES)
- .erase_unit = 4096,
- #endif
- .program_unit = 4,
- .rmap = true,
- .wmap = false,
- };
- NRF_ATFIFO_DEF(m_fifo, nrf_fstorage_sd_op_t, NRF_FSTORAGE_SD_QUEUE_SIZE);
- NRF_SDH_SOC_OBSERVER(m_sys_obs, 0, nrf_fstorage_sys_evt_handler, NULL);
- NRF_SDH_REQUEST_OBSERVER(m_req_obs, 0) =
- {
- .handler = nrf_fstorage_sdh_req_handler,
- };
- NRF_SDH_STATE_OBSERVER(m_state_obs, 0) =
- {
- .handler = nrf_fstorage_sdh_state_handler,
- };
- static nrf_fstorage_sd_work_t m_flags;
- static nrf_fstorage_sd_op_t * m_p_cur_op;
- static nrf_atfifo_item_get_t m_iget_ctx;
- static void event_send(nrf_fstorage_sd_op_t const * p_op, ret_code_t result)
- {
- if (p_op->p_fs->evt_handler == NULL)
- {
-
- return;
- }
- nrf_fstorage_evt_t evt =
- {
- .result = result,
- .p_param = p_op->p_param,
- };
- switch (p_op->op_code)
- {
- case NRF_FSTORAGE_OP_WRITE:
- evt.id = NRF_FSTORAGE_EVT_WRITE_RESULT;
- evt.addr = p_op->write.dest;
- evt.p_src = p_op->write.p_src;
- evt.len = p_op->write.len;
- break;
- case NRF_FSTORAGE_OP_ERASE:
- evt.id = NRF_FSTORAGE_EVT_ERASE_RESULT;
- evt.addr = (p_op->erase.page * m_flash_info.erase_unit);
- evt.len = p_op->erase.pages_to_erase;
- break;
- default:
-
- break;
- }
- p_op->p_fs->evt_handler(&evt);
- }
- static uint32_t write_execute(nrf_fstorage_sd_op_t const * p_op)
- {
- uint32_t chunk_len;
- chunk_len = MIN(p_op->write.len - p_op->write.offset, NRF_FSTORAGE_SD_MAX_WRITE_SIZE);
- chunk_len = MAX(1, chunk_len / m_flash_info.program_unit);
-
- uint32_t * p_dest = (uint32_t*)(p_op->write.dest + p_op->write.offset);
- uint32_t const * p_src = (uint32_t*)((uint32_t)p_op->write.p_src + p_op->write.offset);
- return sd_flash_write(p_dest, p_src, chunk_len);
- }
- static uint32_t erase_execute(nrf_fstorage_sd_op_t const * p_op)
- {
- return sd_flash_page_erase(p_op->erase.page + p_op->erase.progress);
- }
- static void queue_free(void)
- {
- (void) nrf_atfifo_item_free(m_fifo, &m_iget_ctx);
- }
- static bool queue_load_next(void)
- {
- m_p_cur_op = nrf_atfifo_item_get(m_fifo, &m_iget_ctx);
- return (m_p_cur_op != NULL);
- }
- static void queue_process(void)
- {
- uint32_t rc;
- if (m_flags.state == NRF_FSTORAGE_STATE_IDLE)
- {
- if (!queue_load_next())
- {
-
- m_flags.queue_running = false;
- return;
- }
- }
- m_flags.state = NRF_FSTORAGE_STATE_OP_EXECUTING;
- switch (m_p_cur_op->op_code)
- {
- case NRF_FSTORAGE_OP_WRITE:
- rc = write_execute(m_p_cur_op);
- break;
- case NRF_FSTORAGE_OP_ERASE:
- rc = erase_execute(m_p_cur_op);
- break;
- default:
- rc = NRF_ERROR_INTERNAL;
- break;
- }
- switch (rc)
- {
- case NRF_SUCCESS:
- {
-
- if (!m_flags.sd_enabled)
- {
- nrf_fstorage_sys_evt_handler(NRF_EVT_FLASH_OPERATION_SUCCESS, NULL);
- }
- } break;
- case NRF_ERROR_BUSY:
- {
-
- m_flags.state = NRF_FSTORAGE_STATE_OP_PENDING;
- } break;
- default:
- {
-
- event_send(m_p_cur_op, NRF_ERROR_INTERNAL);
-
- m_flags.state = NRF_FSTORAGE_STATE_IDLE;
- m_flags.queue_running = false;
-
- queue_free();
- } break;
- }
- }
- static void queue_start(void)
- {
- if ( (!nrf_atomic_flag_set_fetch(&m_flags.queue_running))
- && (!m_flags.paused))
- {
- queue_process();
- }
- }
- static bool on_operation_success(nrf_fstorage_sd_op_t * const p_op)
- {
-
- m_flags.retries = 0;
- switch (p_op->op_code)
- {
- case NRF_FSTORAGE_OP_WRITE:
- {
-
- uint32_t const chunk_len = MIN(p_op->write.len - p_op->write.offset,
- NRF_FSTORAGE_SD_MAX_WRITE_SIZE);
- p_op->write.offset += chunk_len;
- if (p_op->write.offset == p_op->write.len)
- {
- return true;
- }
- } break;
- case NRF_FSTORAGE_OP_ERASE:
- {
- p_op->erase.progress++;
- if (p_op->erase.progress == p_op->erase.pages_to_erase)
- {
- return true;
- }
- } break;
- default:
-
- break;
- }
- return false;
- }
- static bool on_operation_failure(nrf_fstorage_sd_op_t const * p_op)
- {
- UNUSED_PARAMETER(p_op);
- m_flags.retries++;
- if (m_flags.retries > NRF_FSTORAGE_SD_MAX_RETRIES)
- {
-
- m_flags.retries = 0;
- return true;
- }
- return false;
- }
- static ret_code_t init(nrf_fstorage_t * p_fs, void * p_param)
- {
- UNUSED_PARAMETER(p_param);
- p_fs->p_flash_info = &m_flash_info;
- if (!nrf_atomic_flag_set_fetch(&m_flags.initialized))
- {
- #if NRF_SDH_ENABLED
- m_flags.sd_enabled = nrf_sdh_is_enabled();
- #endif
- (void) NRF_ATFIFO_INIT(m_fifo);
- }
- return NRF_SUCCESS;
- }
- static ret_code_t uninit(nrf_fstorage_t * p_fs, void * p_param)
- {
- UNUSED_PARAMETER(p_fs);
- UNUSED_PARAMETER(p_param);
-
- memset(&m_flags, 0x00, sizeof(m_flags));
- (void) nrf_atfifo_clear(m_fifo);
- return NRF_SUCCESS;
- }
- static ret_code_t write(nrf_fstorage_t const * p_fs,
- uint32_t dest,
- void const * p_src,
- uint32_t len,
- void * p_param)
- {
- nrf_fstorage_sd_op_t * p_op;
- nrf_atfifo_item_put_t iput_ctx;
-
- p_op = nrf_atfifo_item_alloc(m_fifo, &iput_ctx);
- if (p_op == NULL)
- {
- return NRF_ERROR_NO_MEM;
- }
-
- memset(p_op, 0x00, sizeof(nrf_fstorage_sd_op_t));
- p_op->op_code = NRF_FSTORAGE_OP_WRITE;
- p_op->p_fs = p_fs;
- p_op->p_param = p_param;
- p_op->write.dest = dest;
- p_op->write.p_src = p_src;
- p_op->write.len = len;
-
- (void) nrf_atfifo_item_put(m_fifo, &iput_ctx);
- queue_start();
- return NRF_SUCCESS;
- }
- static ret_code_t read(nrf_fstorage_t const * p_fs, uint32_t src, void * p_dest, uint32_t len)
- {
- memcpy(p_dest, (uint32_t*)src, len);
- return NRF_SUCCESS;
- }
- static ret_code_t erase(nrf_fstorage_t const * p_fs,
- uint32_t page_addr,
- uint32_t len,
- void * p_param)
- {
- nrf_fstorage_sd_op_t * p_op;
- nrf_atfifo_item_put_t iput_ctx;
-
- p_op = nrf_atfifo_item_alloc(m_fifo, &iput_ctx);
- if (p_op == NULL)
- {
- return NRF_ERROR_NO_MEM;
- }
-
- memset(p_op, 0x00, sizeof(nrf_fstorage_sd_op_t));
- p_op->op_code = NRF_FSTORAGE_OP_ERASE;
- p_op->p_fs = p_fs;
- p_op->p_param = p_param;
- p_op->erase.page = (page_addr / m_flash_info.erase_unit);
- p_op->erase.pages_to_erase = len;
-
- (void) nrf_atfifo_item_put(m_fifo, &iput_ctx);
- queue_start();
- return NRF_SUCCESS;
- }
- static uint8_t const * rmap(nrf_fstorage_t const * p_fs, uint32_t addr)
- {
- UNUSED_PARAMETER(p_fs);
- return (uint8_t*)addr;
- }
- static uint8_t * wmap(nrf_fstorage_t const * p_fs, uint32_t addr)
- {
- UNUSED_PARAMETER(p_fs);
- UNUSED_PARAMETER(addr);
-
- return NULL;
- }
- static bool is_busy(nrf_fstorage_t const * p_fs)
- {
- UNUSED_PARAMETER(p_fs);
- return (m_flags.state != NRF_FSTORAGE_STATE_IDLE);
- }
- void nrf_fstorage_sys_evt_handler(uint32_t sys_evt, void * p_context)
- {
- UNUSED_PARAMETER(p_context);
- if ( (sys_evt != NRF_EVT_FLASH_OPERATION_SUCCESS)
- && (sys_evt != NRF_EVT_FLASH_OPERATION_ERROR))
- {
-
- return;
- }
- switch (m_flags.state)
- {
- case NRF_FSTORAGE_STATE_IDLE:
-
- return;
- case NRF_FSTORAGE_STATE_OP_PENDING:
-
- break;
- case NRF_FSTORAGE_STATE_OP_EXECUTING:
- {
-
- bool operation_finished = false;
- switch (sys_evt)
- {
- case NRF_EVT_FLASH_OPERATION_SUCCESS:
- operation_finished = on_operation_success(m_p_cur_op);
- break;
- case NRF_EVT_FLASH_OPERATION_ERROR:
- operation_finished = on_operation_failure(m_p_cur_op);
- break;
- default:
- break;
- }
- if (operation_finished)
- {
-
- m_flags.state = NRF_FSTORAGE_STATE_IDLE;
- event_send(m_p_cur_op, (sys_evt == NRF_EVT_FLASH_OPERATION_SUCCESS) ?
- NRF_SUCCESS : NRF_ERROR_TIMEOUT);
-
- queue_free();
- }
- } break;
- }
- if (!m_flags.paused)
- {
- queue_process();
- }
- else
- {
-
- (void) nrf_sdh_request_continue();
- }
- }
- bool nrf_fstorage_sdh_req_handler(nrf_sdh_req_evt_t req, void * p_context)
- {
- UNUSED_PARAMETER(req);
- UNUSED_PARAMETER(p_context);
- m_flags.paused = true;
-
- return (m_flags.state == NRF_FSTORAGE_STATE_IDLE);
- }
- void nrf_fstorage_sdh_state_handler(nrf_sdh_state_evt_t state, void * p_context)
- {
- UNUSED_PARAMETER(p_context);
- if ( (state == NRF_SDH_EVT_STATE_ENABLED)
- || (state == NRF_SDH_EVT_STATE_DISABLED))
- {
- m_flags.paused = false;
- m_flags.sd_enabled = (state == NRF_SDH_EVT_STATE_ENABLED);
-
- queue_process();
- }
- }
- nrf_fstorage_api_t nrf_fstorage_sd =
- {
- .init = init,
- .uninit = uninit,
- .read = read,
- .write = write,
- .erase = erase,
- .rmap = rmap,
- .wmap = wmap,
- .is_busy = is_busy
- };
- #endif
|