diff options
Diffstat (limited to 'thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/fstorage')
6 files changed, 1576 insertions, 0 deletions
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/fstorage/nrf_fstorage.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/fstorage/nrf_fstorage.c new file mode 100644 index 0000000..d96abce --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/fstorage/nrf_fstorage.c @@ -0,0 +1,244 @@ +/** + * Copyright (c) 2016 - 2018, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "sdk_config.h" + +#if NRF_FSTORAGE_ENABLED + +#include "nrf_fstorage.h" +#include <stddef.h> +#include <stdint.h> +#include "sdk_errors.h" +#include "sdk_macros.h" +#include "nrf_section.h" + +#define NRF_LOG_MODULE_NAME nrf_fstorage +#include "nrf_log.h" +NRF_LOG_MODULE_REGISTER(); + + +/* Create the section "fs_data". */ +NRF_SECTION_DEF(fs_data, nrf_fstorage_t); + + +/**@brief Macro to handle user input validation. + * + * If @p _cond evaluates to true, does nothing. Otherwise, + * if the NRF_FSTORAGE_PARAM_CHECK_DISABLED is not set, logs an error message and returns @p _err. + * If the NRF_FSTORAGE_PARAM_CHECK_DISABLED is set, behaves like the @ref ASSERT macro. + * + * Parameter checking implemented using this macro can be optionally turned off for release code. + * Only disable runtime parameter checks if size if a major concern. + * + * @param _cond The condition to be evaluated. + * @param _err The error code to be returned. + */ +#define NRF_FSTORAGE_PARAM_CHECK(_cond, _err) \ + NRF_PARAM_CHECK(NRF_FSTORAGE, _cond, _err, NRF_LOG_ERROR) + + +static bool addr_is_aligned32(uint32_t addr); +static bool addr_is_page_aligned(nrf_fstorage_t const * p_fs, uint32_t addr); +static bool addr_is_within_bounds(nrf_fstorage_t const * p_fs, uint32_t addr, uint32_t len); + + +ret_code_t nrf_fstorage_init(nrf_fstorage_t * p_fs, + nrf_fstorage_api_t * p_api, + void * p_param) +{ + NRF_FSTORAGE_PARAM_CHECK(p_fs, NRF_ERROR_NULL); + NRF_FSTORAGE_PARAM_CHECK(p_api, NRF_ERROR_NULL); + + p_fs->p_api = p_api; + + return (p_fs->p_api)->init(p_fs, p_param); +} + + +ret_code_t nrf_fstorage_uninit(nrf_fstorage_t * p_fs, + void * p_param) +{ + ret_code_t rc; + + NRF_FSTORAGE_PARAM_CHECK(p_fs, NRF_ERROR_NULL); + NRF_FSTORAGE_PARAM_CHECK(p_fs->p_api, NRF_ERROR_INVALID_STATE); + + rc = (p_fs->p_api)->uninit(p_fs, p_param); + + /* Uninitialize the API. */ + p_fs->p_api = NULL; + p_fs->p_flash_info = NULL; + + return rc; +} + + +ret_code_t nrf_fstorage_read(nrf_fstorage_t const * p_fs, + uint32_t src, + void * p_dest, + uint32_t len) +{ + NRF_FSTORAGE_PARAM_CHECK(p_fs, NRF_ERROR_NULL); + NRF_FSTORAGE_PARAM_CHECK(p_dest, NRF_ERROR_NULL); + NRF_FSTORAGE_PARAM_CHECK(p_fs->p_api, NRF_ERROR_INVALID_STATE); + NRF_FSTORAGE_PARAM_CHECK(len, NRF_ERROR_INVALID_LENGTH); + + /* Source addres must be word-aligned. */ + NRF_FSTORAGE_PARAM_CHECK(addr_is_aligned32(src), NRF_ERROR_INVALID_ADDR); + NRF_FSTORAGE_PARAM_CHECK(addr_is_within_bounds(p_fs, src, len), NRF_ERROR_INVALID_ADDR); + + return (p_fs->p_api)->read(p_fs, src, p_dest, len); +} + + +ret_code_t nrf_fstorage_write(nrf_fstorage_t const * p_fs, + uint32_t dest, + void const * p_src, + uint32_t len, + void * p_context) +{ + NRF_FSTORAGE_PARAM_CHECK(p_fs, NRF_ERROR_NULL); + NRF_FSTORAGE_PARAM_CHECK(p_src, NRF_ERROR_NULL); + NRF_FSTORAGE_PARAM_CHECK(p_fs->p_api, NRF_ERROR_INVALID_STATE); + NRF_FSTORAGE_PARAM_CHECK(len, NRF_ERROR_INVALID_LENGTH); + + /* Length must be a multiple of the program unit. */ + NRF_FSTORAGE_PARAM_CHECK(!(len % p_fs->p_flash_info->program_unit), NRF_ERROR_INVALID_LENGTH); + + /* Source and destination addresses must be word-aligned. */ + NRF_FSTORAGE_PARAM_CHECK(addr_is_aligned32(dest), NRF_ERROR_INVALID_ADDR); + NRF_FSTORAGE_PARAM_CHECK(addr_is_aligned32((uint32_t)p_src), NRF_ERROR_INVALID_ADDR); + NRF_FSTORAGE_PARAM_CHECK(addr_is_within_bounds(p_fs, dest, len), NRF_ERROR_INVALID_ADDR); + + return (p_fs->p_api)->write(p_fs, dest, p_src, len, p_context); +} + + +ret_code_t nrf_fstorage_erase(nrf_fstorage_t const * p_fs, + uint32_t page_addr, + uint32_t len, + void * p_context) +{ + NRF_FSTORAGE_PARAM_CHECK(p_fs, NRF_ERROR_NULL); + NRF_FSTORAGE_PARAM_CHECK(p_fs->p_api, NRF_ERROR_INVALID_STATE); + NRF_FSTORAGE_PARAM_CHECK(len, NRF_ERROR_INVALID_LENGTH); + + /* Address must be aligned to a page boundary. */ + NRF_FSTORAGE_PARAM_CHECK(addr_is_page_aligned(p_fs, page_addr), NRF_ERROR_INVALID_ADDR); + + NRF_FSTORAGE_PARAM_CHECK( + addr_is_within_bounds(p_fs, page_addr, (len * p_fs->p_flash_info->erase_unit)), + NRF_ERROR_INVALID_ADDR + ); + + return (p_fs->p_api)->erase(p_fs, page_addr, len, p_context); +} + + +uint8_t const * nrf_fstorage_rmap(nrf_fstorage_t const * p_fs, uint32_t addr) +{ + if ((p_fs == NULL) || (p_fs->p_api == NULL)) + { + return NULL; + } + + return (p_fs->p_api)->rmap(p_fs, addr); +} + + +uint8_t * nrf_fstorage_wmap(nrf_fstorage_t const * p_fs, uint32_t addr) +{ + if ((p_fs == NULL) || (p_fs->p_api == NULL)) + { + return NULL; + } + + return (p_fs->p_api)->wmap(p_fs, addr); +} + + +bool nrf_fstorage_is_busy(nrf_fstorage_t const * p_fs) +{ + /* If a NULL instance is provided, return true if any instance is busy. + * Uninitialized instances are considered not busy. */ + if ((p_fs == NULL) || (p_fs->p_api == NULL)) + { + for (uint32_t i = 0; i < NRF_FSTORAGE_INSTANCE_CNT; i++) + { + p_fs = NRF_FSTORAGE_INSTANCE_GET(i); /* cannot be NULL. */ + if (p_fs->p_api != NULL) + { + /* p_api->is_busy() cannot be NULL. */ + if (p_fs->p_api->is_busy(p_fs)) + { + return true; + } + } + } + + return false; + } + + return p_fs->p_api->is_busy(p_fs); +} + + +static bool addr_is_within_bounds(nrf_fstorage_t const * p_fs, + uint32_t addr, + uint32_t len) +{ + return ( (addr >= p_fs->start_addr) + && (addr + len - 1 <= p_fs->end_addr)); +} + + +static bool addr_is_aligned32(uint32_t addr) +{ + return !(addr & 0x03); +} + + +static bool addr_is_page_aligned(nrf_fstorage_t const * p_fs, + uint32_t addr) +{ + return (addr & (p_fs->p_flash_info->erase_unit - 1)) == 0; +} + + +#endif // NRF_FSTORAGE_ENABLED diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/fstorage/nrf_fstorage.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/fstorage/nrf_fstorage.h new file mode 100644 index 0000000..b678950 --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/fstorage/nrf_fstorage.h @@ -0,0 +1,341 @@ +/** + * Copyright (c) 2016 - 2018, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef NRF_FSTORAGE_H__ +#define NRF_FSTORAGE_H__ + +/** + * @file + * + * @defgroup nrf_fstorage Flash storage (fstorage) + * @ingroup app_common + * @{ + * + * @brief Flash abstraction library that provides basic read, write, and erase operations. + * + * @details The fstorage library can be implemented in different ways. Two implementations are provided: + * - The @ref nrf_fstorage_sd implements flash access through the SoftDevice. + * - The @ref nrf_fstorage_nvmc implements flash access through the non-volatile memory controller. + * + * You can select the implementation that should be used independently for each instance of fstorage. + */ + +#include <stdint.h> +#include <stdbool.h> +#include "sdk_errors.h" +#include "nrf_section.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/**@brief Macro for defining an fstorage instance. + * + * Users of fstorage must define an instance variable by using this macro. + * Each instance is tied to an API implementation and contains information such + * as the program and erase units for the target flash peripheral. + * Instance variables are placed in the "fs_data" section of the binary. + * + * @param[in] inst A definition of an @ref nrf_fstorage_t variable. + */ +#define NRF_FSTORAGE_DEF(inst) NRF_SECTION_ITEM_REGISTER(fs_data, inst) + +/**@brief Macro for retrieving an fstorage instance. */ +#define NRF_FSTORAGE_INSTANCE_GET(i) NRF_SECTION_ITEM_GET(fs_data, nrf_fstorage_t, (i)) + +/**@brief Macro for retrieving the total number of fstorage instances. */ +#define NRF_FSTORAGE_INSTANCE_CNT NRF_SECTION_ITEM_COUNT(fs_data, nrf_fstorage_t) + + +/**@brief Event IDs. */ +typedef enum +{ + NRF_FSTORAGE_EVT_READ_RESULT, + NRF_FSTORAGE_EVT_WRITE_RESULT, //!< Event for @ref nrf_fstorage_write. + NRF_FSTORAGE_EVT_ERASE_RESULT //!< Event for @ref nrf_fstorage_erase. +} nrf_fstorage_evt_id_t; + + +/**@brief An fstorage event. */ +typedef struct +{ + nrf_fstorage_evt_id_t id; //!< The event ID. + ret_code_t result; //!< Result of the operation. + uint32_t addr; //!< Address at which the operation was performed. + void const * p_src; //!< Buffer written to flash. + uint32_t len; //!< Length of the operation. + void * p_param; //!< User-defined parameter passed to the event handler. +} nrf_fstorage_evt_t; + + +/**@brief Event handler function prototype. + * + * @param[in] p_evt The event. + */ +typedef void (*nrf_fstorage_evt_handler_t)(nrf_fstorage_evt_t * p_evt); + + +/**@brief Information about the implementation and the flash peripheral. */ +typedef struct +{ + uint32_t erase_unit; //!< Size of a flash page (in bytes). A flash page is the smallest unit that can be erased. + uint32_t program_unit; //!< Size of the smallest programmable unit (in bytes). + bool rmap; //!< The device address space is memory mapped to the MCU address space. + bool wmap; //!< The device address space is memory mapped to a writable MCU address space. +} const nrf_fstorage_info_t; + + +/* Necessary forward declaration. */ +struct nrf_fstorage_api_s; + + +/**@brief An fstorage instance. + * + * @details Use the @ref NRF_FSTORAGE_DEF macro to define an fstorage instance. + * + * An instance is tied to an API implementation and contains information about the flash device, + * such as the program and erase units as well and implementation-specific functionality. + */ +typedef struct +{ + /**@brief The API implementation used by this instance. */ + struct nrf_fstorage_api_s const * p_api; + + /**@brief Information about the implementation functionality and the flash peripheral. */ + nrf_fstorage_info_t * p_flash_info; + + /**@brief The event handler function. + * + * If set to NULL, no events will be sent. + */ + nrf_fstorage_evt_handler_t evt_handler; + + /**@brief The beginning of the flash space on which this fstorage instance should operate. + * All flash operations must be within the address specified in + * this field and @ref end_addr. + * + * This field must be set manually. + */ + uint32_t start_addr; + + /**@brief The last address (exclusive) of flash on which this fstorage instance should operate. + * All flash operations must be within the address specified in + * this field and @ref start_addr. + * + * This field must be set manually. + */ + uint32_t end_addr; +} nrf_fstorage_t; + + +/**@brief Functions provided by the API implementation. */ +typedef struct nrf_fstorage_api_s +{ + /**@brief Initialize the flash peripheral. */ + ret_code_t (*init)(nrf_fstorage_t * p_fs, void * p_param); + /**@brief Uninitialize the flash peripheral. */ + ret_code_t (*uninit)(nrf_fstorage_t * p_fs, void * p_param); + /**@brief Read data from flash. */ + ret_code_t (*read)(nrf_fstorage_t const * p_fs, uint32_t src, void * p_dest, uint32_t len); + /**@brief Write bytes to flash. */ + ret_code_t (*write)(nrf_fstorage_t const * p_fs, uint32_t dest, void const * p_src, uint32_t len, void * p_param); + /**@brief Erase flash pages. */ + ret_code_t (*erase)(nrf_fstorage_t const * p_fs, uint32_t addr, uint32_t len, void * p_param); + /**@brief Map a device address to a readable address within the MCU address space. */ + uint8_t const * (*rmap)(nrf_fstorage_t const * p_fs, uint32_t addr); + /**@brief Map a device address to a writable address within the MCU address space. */ + uint8_t * (*wmap)(nrf_fstorage_t const * p_fs, uint32_t addr); + /**@brief Check if there are any pending flash operations. */ + bool (*is_busy)(nrf_fstorage_t const * p_fs); +} const nrf_fstorage_api_t; + + +/**@brief Function for initializing fstorage. + * + * @param[in] p_fs The fstorage instance to initialize. + * @param[in] p_api The API implementation to use. + * @param[in] p_param An optional parameter to pass to the implementation-specific API call. + * + * @retval NRF_SUCCESS If initialization was successful. + * @retval NRF_ERROR_NULL If @p p_fs or @p p_api field in @p p_fs is NULL. + * @retval NRF_ERROR_INTERNAL If another error occurred. + */ +ret_code_t nrf_fstorage_init(nrf_fstorage_t * p_fs, + nrf_fstorage_api_t * p_api, + void * p_param); + + +/**@brief Function for uninitializing an fstorage instance. + * + * @param[in] p_fs The fstorage instance to uninitialize. + * @param[in] p_param An optional parameter to pass to the implementation-specific API call. + * + * @retval NRF_SUCCESS If uninitialization was successful. + * @retval NRF_ERROR_NULL If @p p_fs is NULL. + * @retval NRF_ERROR_INVALID_STATE If the module is not initialized. + * @retval NRF_ERROR_INTERNAL If another error occurred. + */ +ret_code_t nrf_fstorage_uninit(nrf_fstorage_t * p_fs, void * p_param); + + +/**@brief Function for reading data from flash. + * + * Copy @p len bytes from @p addr to @p p_dest. + * + * @param[in] p_fs The fstorage instance. + * @param[in] addr Address in flash where to read from. + * @param[in] p_dest Buffer where the data should be copied. + * @param[in] len Length of the data to be copied (in bytes). + * + * @retval NRF_SUCCESS If the operation was successful. + * @retval NRF_ERROR_NULL If @p p_fs or @p p_dest is NULL. + * @retval NRF_ERROR_INVALID_STATE If the module is not initialized. + * @retval NRF_ERROR_INVALID_LENGTH If @p len is zero or otherwise invalid. + * @retval NRF_ERROR_INVALID_ADDR If the address @p addr is outside the flash memory + * boundaries specified in @p p_fs, or if it is unaligned. + */ +ret_code_t nrf_fstorage_read(nrf_fstorage_t const * p_fs, + uint32_t addr, + void * p_dest, + uint32_t len); + + +/**@brief Function for writing data to flash. + * + * Write @p len bytes from @p p_src to @p dest. + * + * When using @ref nrf_fstorage_sd, the data is written by several calls to @ref sd_flash_write if + * the length of the data exceeds @ref NRF_FSTORAGE_SD_MAX_WRITE_SIZE bytes. + * Only one event is sent upon completion. + * + * @note The data to be written to flash must be kept in memory until the operation has + * terminated and an event is received. + * + * @param[in] p_fs The fstorage instance. + * @param[in] dest Address in flash memory where to write the data. + * @param[in] p_src Data to be written. + * @param[in] len Length of the data (in bytes). + * @param[in] p_param User-defined parameter passed to the event handler (may be NULL). + * + * @retval NRF_SUCCESS If the operation was accepted. + * @retval NRF_ERROR_NULL If @p p_fs or @p p_src is NULL. + * @retval NRF_ERROR_INVALID_STATE If the module is not initialized. + * @retval NRF_ERROR_INVALID_LENGTH If @p len is zero or not a multiple of the program unit, + * or if it is otherwise invalid. + * @retval NRF_ERROR_INVALID_ADDR If the address @p dest is outside the flash memory + * boundaries specified in @p p_fs, or if it is unaligned. + * @retval NRF_ERROR_NO_MEM If no memory is available to accept the operation. + * When using the @ref nrf_fstorage_sd, this error + * indicates that the internal queue of operations is full. + */ +ret_code_t nrf_fstorage_write(nrf_fstorage_t const * p_fs, + uint32_t dest, + void const * p_src, + uint32_t len, + void * p_param); + + +/**@brief Function for erasing flash pages. + * + * @details This function erases @p len pages starting from the page at address @p page_addr. + * The erase operation must be initiated on a page boundary. + * + * @param[in] p_fs The fstorage instance. + * @param[in] page_addr Address of the page to erase. + * @param[in] len Number of pages to erase. + * @param[in] p_param User-defined parameter passed to the event handler (may be NULL). + * + * @retval NRF_SUCCESS If the operation was accepted. + * @retval NRF_ERROR_NULL If @p p_fs is NULL. + * @retval NRF_ERROR_INVALID_STATE If the module is not initialized. + * @retval NRF_ERROR_INVALID_LENGTH If @p len is zero. + * @retval NRF_ERROR_INVALID_ADDR If the address @p page_addr is outside the flash memory + * boundaries specified in @p p_fs, or if it is unaligned. + * @retval NRF_ERROR_NO_MEM If no memory is available to accept the operation. + * When using the @ref nrf_fstorage_sd, this error + * indicates that the internal queue of operations is full. + */ +ret_code_t nrf_fstorage_erase(nrf_fstorage_t const * p_fs, + uint32_t page_addr, + uint32_t len, + void * p_param); + + +/**@brief Map a flash address to a pointer in the MCU address space that can be dereferenced. + * + * @param p_fs The fstorage instance. + * @param addr The address to map. + * + * @retval A pointer to the specified address, + * or @c NULL if the address cannot be mapped or if @p p_fs is @c NULL. + */ +uint8_t const * nrf_fstorage_rmap(nrf_fstorage_t const * p_fs, uint32_t addr); + + +/**@brief Map a flash address to a pointer in the MCU address space that can be written to. + * + * @param p_fs The fstorage instance. + * @param addr The address to map. + * + * @retval A pointer to the specified address, + * or @c NULL if the address cannot be mapped or if @p p_fs is @c NULL. + */ +uint8_t * nrf_fstorage_wmap(nrf_fstorage_t const * p_fs, uint32_t addr); + + +/**@brief Function for querying the status of fstorage. + * + * @details An uninitialized instance of fstorage is treated as not busy. + * + * @param[in] p_fs The fstorage instance. Pass NULL to query all instances. + * + * @returns If @p p_fs is @c NULL, this function returns true if any fstorage instance is busy or false otherwise. + * @returns If @p p_fs is not @c NULL, this function returns true if the fstorage instance is busy or false otherwise. + */ + bool nrf_fstorage_is_busy(nrf_fstorage_t const * p_fs); + +/** @} */ + + +#ifdef __cplusplus +} +#endif + +#endif // NRF_FSTORAGE_H__ diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/fstorage/nrf_fstorage_nvmc.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/fstorage/nrf_fstorage_nvmc.c new file mode 100644 index 0000000..14b1859 --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/fstorage/nrf_fstorage_nvmc.c @@ -0,0 +1,217 @@ +/** + * Copyright (c) 2016 - 2018, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "sdk_common.h" + +#if NRF_MODULE_ENABLED(NRF_FSTORAGE) + +#include "nrf_fstorage_nvmc.h" +#include <stdint.h> +#include <string.h> +#include <stdbool.h> +#include "nrf_nvmc.h" +#include "nrf_atomic.h" + + +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, +}; + + + /* An operation initiated by fstorage is ongoing. */ +static nrf_atomic_flag_t m_flash_operation_ongoing; + + +/* Send event to the event handler. */ +static void event_send(nrf_fstorage_t const * p_fs, + nrf_fstorage_evt_id_t evt_id, + void const * p_src, + uint32_t addr, + uint32_t len, + void * p_param) +{ + if (p_fs->evt_handler == NULL) + { + /* Nothing to do. */ + return; + } + + nrf_fstorage_evt_t evt = + { + .result = NRF_SUCCESS, + .id = evt_id, + .addr = addr, + .p_src = p_src, + .len = len, + .p_param = p_param, + }; + + p_fs->evt_handler(&evt); +} + + +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; + + return NRF_SUCCESS; +} + + +static ret_code_t uninit(nrf_fstorage_t * p_fs, void * p_param) +{ + UNUSED_PARAMETER(p_fs); + UNUSED_PARAMETER(p_param); + + (void) nrf_atomic_flag_clear(&m_flash_operation_ongoing); + + return NRF_SUCCESS; +} + + +static ret_code_t read(nrf_fstorage_t const * p_fs, uint32_t src, void * p_dest, uint32_t len) +{ + UNUSED_PARAMETER(p_fs); + + memcpy(p_dest, (uint32_t*)src, len); + + 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) +{ + if (nrf_atomic_flag_set_fetch(&m_flash_operation_ongoing)) + { + return NRF_ERROR_BUSY; + } + + nrf_nvmc_write_words(dest, (uint32_t*)p_src, (len / m_flash_info.program_unit)); + + /* Clear the flag before sending the event, to allow API calls in the event context. */ + (void) nrf_atomic_flag_clear(&m_flash_operation_ongoing); + + event_send(p_fs, NRF_FSTORAGE_EVT_WRITE_RESULT, p_src, dest, len, p_param); + + return NRF_SUCCESS; +} + + +static ret_code_t erase(nrf_fstorage_t const * p_fs, + uint32_t page_addr, + uint32_t len, + void * p_param) +{ + uint32_t progress = 0; + + if (nrf_atomic_flag_set_fetch(&m_flash_operation_ongoing)) + { + return NRF_ERROR_BUSY; + } + + while (progress != len) + { + nrf_nvmc_page_erase(page_addr + (progress * m_flash_info.erase_unit)); + progress++; + } + + /* Clear the flag before sending the event, to allow API calls in the event context. */ + (void) nrf_atomic_flag_clear(&m_flash_operation_ongoing); + + event_send(p_fs, NRF_FSTORAGE_EVT_ERASE_RESULT, NULL, page_addr, len, p_param); + + 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); + + /* Not supported. */ + return NULL; +} + + +static bool is_busy(nrf_fstorage_t const * p_fs) +{ + UNUSED_PARAMETER(p_fs); + + return m_flash_operation_ongoing; +} + + +/* The exported API. */ +nrf_fstorage_api_t nrf_fstorage_nvmc = +{ + .init = init, + .uninit = uninit, + .read = read, + .write = write, + .erase = erase, + .rmap = rmap, + .wmap = wmap, + .is_busy = is_busy +}; + + +#endif // NRF_FSTORAGE_ENABLED diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/fstorage/nrf_fstorage_nvmc.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/fstorage/nrf_fstorage_nvmc.h new file mode 100644 index 0000000..bacd745 --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/fstorage/nrf_fstorage_nvmc.h @@ -0,0 +1,75 @@ +/** + * Copyright (c) 2016 - 2018, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/** + * @file + * + * @defgroup nrf_fstorage_nvmc NVMC implementation + * @ingroup nrf_fstorage + * @{ + * + * @brief API implementation of fstorage that uses the non-volatile memory controller (NVMC). +*/ + +#ifndef NRF_FSTORAGE_NVMC_H__ +#define NRF_FSTORAGE_NVMC_H__ + +#include "nrf_fstorage.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/**@brief API implementation that uses the non-volatile memory controller. + * + * @details An fstorage instance with this API implementation can be initialized by providing + * this structure as a parameter to @ref nrf_fstorage_init. + * The structure is defined in @c nrf_fstorage_nvmc.c. + */ +extern nrf_fstorage_api_t nrf_fstorage_nvmc; + + +#ifdef __cplusplus +} +#endif + +#endif // NRF_FSTORAGE_NVMC_H__ +/** @} */ diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/fstorage/nrf_fstorage_sd.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/fstorage/nrf_fstorage_sd.c new file mode 100644 index 0000000..ef5f6b8 --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/fstorage/nrf_fstorage_sd.c @@ -0,0 +1,624 @@ +/** + * Copyright (c) 2016 - 2018, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#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 + + +/**@brief fstorage operation codes. */ +typedef enum +{ + NRF_FSTORAGE_OP_WRITE, //!< Write bytes to flash. + NRF_FSTORAGE_OP_ERASE //!< Erase flash pages. +} nrf_fstorage_sd_opcode_t; + +ANON_UNIONS_ENABLE; +/**@brief fstorage operation queue element. */ +typedef struct +{ + nrf_fstorage_t const * p_fs; //!< The fstorage instance that requested the operation. + nrf_fstorage_sd_opcode_t op_code; //!< Requested operation. + void * p_param; //!< User-defined parameter passed to the event handler. + union + { + struct + { + void const * p_src; //!< Data to be written to flash. + uint32_t dest; //!< Destination of the data in flash. + uint32_t len; //!< Length of the data to be written (in bytes). + uint32_t offset; //!< Write offset. + } write; + struct + { + uint32_t page; //!< Physical page number. + uint32_t progress; //!< Number of pages erased. + uint32_t pages_to_erase; //!< Total number of pages to erase. + } erase; + }; +} nrf_fstorage_sd_op_t; +ANON_UNIONS_DISABLE; + +typedef enum +{ + NRF_FSTORAGE_STATE_IDLE, //!< No operations requested to the SoftDevice. + NRF_FSTORAGE_STATE_OP_PENDING, //!< A non-fstorage operation is pending. + NRF_FSTORAGE_STATE_OP_EXECUTING, //!< An fstorage operation is executing. +} nrf_fstorage_sd_state_t; + +/**@brief Internal state. */ +typedef struct +{ + nrf_atomic_flag_t initialized; //!< fstorage is initalized. + nrf_atomic_flag_t queue_running; //!< The queue is running. + /** Prevent API calls from entering queue_process(). */ + nrf_fstorage_sd_state_t state; //!< Internal fstorage state. + uint32_t retries; //!< Number of times an operation has been retried on timeout. + bool sd_enabled; //!< The SoftDevice is enabled. + bool paused; //!< A SoftDevice state change is impending. + /** Do not load a new operation when the last one completes. */ +} 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 *); + + +/* Flash device information. */ +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, +}; + +/* Queue of fstorage operations. */ +NRF_ATFIFO_DEF(m_fifo, nrf_fstorage_sd_op_t, NRF_FSTORAGE_SD_QUEUE_SIZE); + +/* Define a nrf_sdh_soc event observer to receive SoftDevice system events. */ +NRF_SDH_SOC_OBSERVER(m_sys_obs, 0, nrf_fstorage_sys_evt_handler, NULL); + +/* nrf_sdh request observer. */ +NRF_SDH_REQUEST_OBSERVER(m_req_obs, 0) = +{ + .handler = nrf_fstorage_sdh_req_handler, +}; + +/* nrf_sdh state observer. */ +NRF_SDH_STATE_OBSERVER(m_state_obs, 0) = +{ + .handler = nrf_fstorage_sdh_state_handler, +}; + +static nrf_fstorage_sd_work_t m_flags; /* Internal status. */ +static nrf_fstorage_sd_op_t * m_p_cur_op; /* The current operation being executed. */ +static nrf_atfifo_item_get_t m_iget_ctx; /* Context for nrf_atfifo_item_get() and nrf_atfifo_item_free(). */ + + +/* Send events to the application. */ +static void event_send(nrf_fstorage_sd_op_t const * p_op, ret_code_t result) +{ + if (p_op->p_fs->evt_handler == NULL) + { + /* Nothing to do. */ + 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: + /* Should not happen. */ + break; + } + + p_op->p_fs->evt_handler(&evt); +} + + +/* Write to flash. */ +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); + + /* Cast to p_src to uint32_t to perform arithmetic. */ + 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); +} + + +/* Erase flash page(s). */ +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); +} + + +/* Free the current queue element. */ +static void queue_free(void) +{ + (void) nrf_atfifo_item_free(m_fifo, &m_iget_ctx); +} + + +/* Load a new operation from the queue. */ +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); +} + + +/* Execute an operation in the queue. */ +static void queue_process(void) +{ + uint32_t rc; + + if (m_flags.state == NRF_FSTORAGE_STATE_IDLE) + { + if (!queue_load_next()) + { + /* No more operations, nothing to do. */ + 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: + { + /* The operation was accepted by the SoftDevice. + * If the SoftDevice is enabled, wait for a system event. Otherwise, + * the SoftDevice call is synchronous and will not send an event so we simulate it. */ + if (!m_flags.sd_enabled) + { + nrf_fstorage_sys_evt_handler(NRF_EVT_FLASH_OPERATION_SUCCESS, NULL); + } + } break; + + case NRF_ERROR_BUSY: + { + /* The SoftDevice is executing a flash operation that was not requested by fstorage. + * Stop processing the queue until a system event is received. */ + m_flags.state = NRF_FSTORAGE_STATE_OP_PENDING; + } break; + + default: + { + /* An error has occurred. We cannot proceed further with this operation. */ + event_send(m_p_cur_op, NRF_ERROR_INTERNAL); + /* Reset the internal state so we can accept other operations. */ + m_flags.state = NRF_FSTORAGE_STATE_IDLE; + m_flags.queue_running = false; + /* Free the current queue element. */ + queue_free(); + } break; + } +} + + +/* Start processing the queue if it is not running and fstorage is not paused. */ +static void queue_start(void) +{ + if ( (!nrf_atomic_flag_set_fetch(&m_flags.queue_running)) + && (!m_flags.paused)) + { + queue_process(); + } +} + + +/* Flash operation success callback. Keeps track of the progress of an operation. */ +static bool on_operation_success(nrf_fstorage_sd_op_t * const p_op) +{ + /* Reset the retry counter on success. */ + m_flags.retries = 0; + + switch (p_op->op_code) + { + case NRF_FSTORAGE_OP_WRITE: + { + /* Update the offset only if the operation is successful + * so that it can be retried in case it times out. */ + 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: + /* Should not happen. */ + break; + } + + return false; +} + + +/* Flash operation failure callback. */ +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) + { + /* Maximum amount of retries reached. Give up. */ + 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); + + /* The state is re-initialized upon init(). + * The common uninitialization code is run by the caller. */ + + 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; + + /* Get a free queue element. */ + p_op = nrf_atfifo_item_alloc(m_fifo, &iput_ctx); + + if (p_op == NULL) + { + return NRF_ERROR_NO_MEM; + } + + /* Initialize the operation. */ + 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; + + /* Put the operation on the queue. */ + (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; + + /* Get a free queue element. */ + p_op = nrf_atfifo_item_alloc(m_fifo, &iput_ctx); + + if (p_op == NULL) + { + return NRF_ERROR_NO_MEM; + } + + /* Initialize the operation. */ + 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; + + /* Put the operation on the queue. */ + (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); + + /* Not supported. */ + 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)) + { + /* Ignore any non-flash events. */ + return; + } + + switch (m_flags.state) + { + case NRF_FSTORAGE_STATE_IDLE: + /* Ignore flash events if no flash operation was requested. */ + return; + + case NRF_FSTORAGE_STATE_OP_PENDING: + /* The SoftDevice has completed a flash operation that was not requested by fstorage. + * It should be possible to request an operation now. + * Process the queue at the end of this function. */ + break; + + case NRF_FSTORAGE_STATE_OP_EXECUTING: + { + /* Handle the result of a flash operation initiated by this module. */ + 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) + { + /* The operation has finished. Change state to NRF_FSTORAGE_STATE_IDLE + * so that queue_process() will fetch a new operation from the queue. */ + 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); + + /* Free the queue element after sending out the event to prevent API calls made + * in the event context to queue elements indefinitely, without this function + * ever returning in case the SoftDevice calls are synchronous. */ + queue_free(); + } + } break; + } + + if (!m_flags.paused) + { + queue_process(); + } + else + { + /* A flash operation has completed. Let the SoftDevice change state. */ + (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; + + /* If there are any operations ongoing, pause the SoftDevice state change. */ + 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); + + /* Execute any operations still in the queue. */ + queue_process(); + } +} + + +/* Exported API implementation. */ +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 // NRF_FSTORAGE_ENABLED diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/fstorage/nrf_fstorage_sd.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/fstorage/nrf_fstorage_sd.h new file mode 100644 index 0000000..b35d15f --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/fstorage/nrf_fstorage_sd.h @@ -0,0 +1,75 @@ +/** + * Copyright (c) 2016 - 2018, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/** + * @file + * + * @defgroup nrf_fstorage_sd SoftDevice implementation + * @ingroup nrf_fstorage + * @{ + * + * @brief API implementation of fstorage that uses the SoftDevice. +*/ + +#ifndef NRF_FSTORAGE_SD_H__ +#define NRF_FSTORAGE_SD_H__ + +#include "nrf_fstorage.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/**@brief API implementation that uses the SoftDevice. + * + * @details An fstorage instance with this API implementation can be initialized by providing + * this structure as a parameter to @ref nrf_fstorage_init. + * The structure is defined in @c nrf_fstorage_sd.c. + */ +extern nrf_fstorage_api_t nrf_fstorage_sd; + + +#ifdef __cplusplus +} +#endif + +#endif // NRF_FSTORAGE_SD_H__ +/** @} */ |