| /* |
| * Copyright (c) 2012 - 2019, 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 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 the copyright holder nor the names of its |
| * contributors may be used to endorse or promote products derived from this |
| * software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
| * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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_NVMC_H__ |
| #define NRF_NVMC_H__ |
| |
| #include <nrfx.h> |
| |
| #ifdef __cplusplus |
| extern "C" { |
| #endif |
| |
| /** |
| * @defgroup nrf_nvmc_hal_deprecated NVMC HAL (deprecated) |
| * @{ |
| * @ingroup nrf_nvmc |
| * @brief Hardware access layer (HAL) for managing the Non-Volatile Memory Controller (NVMC) peripheral. |
| * |
| * This driver allows writing to the non-volatile memory (NVM) regions |
| * of the chip. To write to NVM, the controller must be powered |
| * on and the relevant page must be erased. |
| */ |
| |
| /** |
| * @brief Erase a page in flash. This is required before writing to any address in the page. |
| * |
| * @param address Start address of the page. |
| */ |
| void nrf_nvmc_page_erase(uint32_t address); |
| |
| /** |
| * @brief Write a single byte to flash. |
| * |
| * The function reads the word containing the byte, and then rewrites the entire word. |
| * |
| * @param address Address to write to. |
| * @param value Value to write. |
| */ |
| void nrf_nvmc_write_byte(uint32_t address , uint8_t value); |
| |
| /** |
| * @brief Write a 32-bit word to flash. |
| * |
| * @param address Address to write to. |
| * @param value Value to write. |
| */ |
| void nrf_nvmc_write_word(uint32_t address, uint32_t value); |
| |
| /** |
| * @brief Write consecutive bytes to flash. |
| * |
| * @param address Address to write to. |
| * @param src Pointer to data to copy from. |
| * @param num_bytes Number of bytes in src to write. |
| */ |
| void nrf_nvmc_write_bytes(uint32_t address, const uint8_t * src, uint32_t num_bytes); |
| |
| /** |
| * @brief Write consecutive words to flash. |
| * |
| * @param address Address to write to. |
| * @param src Pointer to data to copy from. |
| * @param num_words Number of words in src to write. |
| */ |
| void nrf_nvmc_write_words(uint32_t address, const uint32_t * src, uint32_t num_words); |
| |
| /** @} */ |
| |
| /** |
| * @defgroup nrf_nvmc_hal NVMC HAL |
| * @{ |
| * @ingroup nrf_nvmc |
| * @brief Hardware access layer (HAL) for managing the Non-Volatile Memory Controller (NVMC) peripheral. |
| */ |
| |
| #if defined(NVMC_ICACHECNF_CACHEEN_Msk) || defined(__NRFX_DOXYGEN__) |
| /** @brief Symbol indicating whether Instruction Cache (ICache) is present. */ |
| #define NRF_NVMC_ICACHE_PRESENT |
| #endif |
| |
| #if defined(NVMC_ERASEPAGEPARTIALCFG_DURATION_Msk) || defined(__NRFX_DOXYGEN__) |
| /** @brief Symbol indicating whether the option of page partial erase is present. */ |
| #define NRF_NVMC_PARTIAL_ERASE_PRESENT |
| #endif |
| |
| /** @brief NVMC modes. */ |
| typedef enum |
| { |
| NRF_NVMC_MODE_READONLY = NVMC_CONFIG_WEN_Ren, ///< NVMC in read-only mode. |
| NRF_NVMC_MODE_WRITE = NVMC_CONFIG_WEN_Wen, ///< NVMC in read and write mode. |
| NRF_NVMC_MODE_ERASE = NVMC_CONFIG_WEN_Een, ///< NVMC in read and erase mode. |
| #if defined(NVMC_CONFIG_WEN_PEen) |
| NRF_NVMC_MODE_PARTIAL_ERASE = NVMC_CONFIG_WEN_PEen ///< NVMC in read and partial erase mode. |
| #endif |
| } nrf_nvmc_mode_t; |
| |
| #if defined(NVMC_CONFIGNS_WEN_Msk) || defined(__NRFX_DOXYGEN__) |
| /** @brief Non-secure NVMC modes. */ |
| typedef enum |
| { |
| NRF_NVMC_NS_MODE_READONLY = NVMC_CONFIGNS_WEN_Ren, ///< Non-secure NVMC in read-only mode. |
| NRF_NVMC_NS_MODE_WRITE = NVMC_CONFIGNS_WEN_Wen, ///< Non-secure NVMC in read and write mode. |
| NRF_NVMC_NS_MODE_ERASE = NVMC_CONFIGNS_WEN_Een, ///< Non-secure NVMC in read and erase mode. |
| } nrf_nvmc_ns_mode_t; |
| #endif |
| |
| #if defined(NRF_NVMC_ICACHE_PRESENT) |
| /** @brief NVMC ICache configuration. */ |
| typedef enum |
| { |
| NRF_NVMC_ICACHE_DISABLE = NVMC_ICACHECNF_CACHEEN_Disabled, ///< Instruction Cache disabled. |
| NRF_NVMC_ICACHE_ENABLE = NVMC_ICACHECNF_CACHEEN_Enabled, ///< Instruction Cache enabled. |
| NRF_NVMC_ICACHE_ENABLE_WITH_PROFILING = NVMC_ICACHECNF_CACHEEN_Enabled | ///< Instruction Cache with cache profiling enabled. |
| NVMC_ICACHECNF_CACHEPROFEN_Msk |
| } nrf_nvmc_icache_config_t; |
| #endif // defined(NRF_NVMC_ICACHE_PRESENT) |
| |
| /** |
| * @brief Function for checking if NVMC is ready to perform write or erase operation. |
| * |
| * @param[in] p_reg Pointer to the structure of registers of the peripheral. |
| * |
| * @retval true NVMC can perform write or erase. |
| * @retval false NVMC is busy and cannot perform next operation yet. |
| */ |
| __STATIC_INLINE bool nrf_nvmc_ready_check(NRF_NVMC_Type const * p_reg); |
| |
| #if defined(NVMC_READYNEXT_READYNEXT_Msk) || defined(__NRFX_DOXYGEN__) |
| /** |
| * @brief Function for checking if NVMC is ready to accept the next write operation. |
| * |
| * NVM writing time can be reduced by using this function. |
| * |
| * @param[in] p_reg Pointer to the structure of registers of the peripheral. |
| * |
| * @retval true NVMC can accept the next write. It will be buffered and will be taken |
| * into account as soon as the ongoing write operation is completed. |
| * @retval false NVMC is busy and cannot accept the next write yet. |
| */ |
| __STATIC_INLINE bool nrf_nvmc_write_ready_check(NRF_NVMC_Type const * p_reg); |
| #endif // defined(NVMC_READYNEXT_READYNEXT_Msk) || defined(__NRFX_DOXYGEN__) |
| |
| /** |
| * @brief Function for setting the NVMC mode. |
| * |
| * Only activate erase and write modes when they are actively used. |
| * If Instruction Cache (ICache) is present, enabling write or erase will |
| * invalidate the cache and keep it invalidated. |
| * |
| * @param[in] p_reg Pointer to the structure of registers of the peripheral. |
| * @param[in] mode Desired operating mode for NVMC. |
| */ |
| __STATIC_INLINE void nrf_nvmc_mode_set(NRF_NVMC_Type * p_reg, |
| nrf_nvmc_mode_t mode); |
| |
| #if defined(NVMC_CONFIGNS_WEN_Msk) || defined(__NRFX_DOXYGEN__) |
| /** |
| * @brief Function for setting the NVMC mode for non-secure Flash page operations. |
| * |
| * @param[in] p_reg Pointer to the structure of registers of the peripheral. |
| * @param[in] mode Desired operating mode for NVMC. |
| */ |
| __STATIC_INLINE void nrf_nvmc_nonsecure_mode_set(NRF_NVMC_Type * p_reg, |
| nrf_nvmc_ns_mode_t mode); |
| #endif |
| |
| /** |
| * @brief Function for starting a single page erase in the Flash memory. |
| * |
| * The NVMC mode must be correctly configured with @ref nrf_nvmc_mode_set |
| * before starting the erase operation. |
| * |
| * @param[in] p_reg Pointer to the structure of registers of the peripheral. |
| * @param[in] page_addr Address of the first word of the page to erase. |
| */ |
| __STATIC_INLINE void nrf_nvmc_page_erase_start(NRF_NVMC_Type * p_reg, |
| uint32_t page_addr); |
| |
| #if defined(NVMC_ERASEUICR_ERASEUICR_Msk) || defined(__NRFX_DOXYGEN__) |
| /** |
| * @brief Function for starting the user information configuration registers (UICR) erase. |
| * |
| * @param[in] p_reg Pointer to the structure of registers of the peripheral. |
| */ |
| __STATIC_INLINE void nrf_nvmc_uicr_erase_start(NRF_NVMC_Type * p_reg); |
| #endif |
| |
| /** |
| * @brief Function for starting the erase of the whole NVM, including UICR. |
| * |
| * This function purges all user code. |
| * |
| * @param[in] p_reg Pointer to the structure of registers of the peripheral. |
| */ |
| __STATIC_INLINE void nrf_nvmc_erase_all_start(NRF_NVMC_Type * p_reg); |
| |
| #if defined(NRF_NVMC_PARTIAL_ERASE_PRESENT) |
| /** |
| * @brief Function for configuring the page partial erase duration in milliseconds. |
| * |
| * @param[in] p_reg Pointer to the structure of registers of the peripheral. |
| * @param[in] duration_ms Page partial erase duration in milliseconds. |
| */ |
| __STATIC_INLINE void nrf_nvmc_partial_erase_duration_set(NRF_NVMC_Type * p_reg, |
| uint32_t duration_ms); |
| |
| /** |
| * @brief Function for getting the current setting for the page partial erase duration. |
| * |
| * @param[in] p_reg Pointer to the structure of registers of the peripheral. |
| * |
| * @retval Interval duration setting in milliseconds. |
| */ |
| __STATIC_INLINE uint32_t nrf_nvmc_partial_erase_duration_get(NRF_NVMC_Type const * p_reg); |
| |
| /** |
| * @brief Function for starting a partial erase operation. |
| * |
| * It must be called successively until the page erase time is reached. |
| * |
| * @param[in] p_reg Pointer to the structure of registers of the peripheral. |
| * @param[in] page_addr Address of the first word of the page to erase. |
| */ |
| __STATIC_INLINE void nrf_nvmc_page_partial_erase_start(NRF_NVMC_Type * p_reg, |
| uint32_t page_addr); |
| #endif // defined(NRF_NVMC_PARTIAL_ERASE_PRESENT) |
| |
| #if defined(NRF_NVMC_ICACHE_PRESENT) |
| /** |
| * @brief Function for applying the Instruction Cache (ICache) configuration. |
| * |
| * Enabling the cache can increase CPU performance and reduce power |
| * consumption by reducing the number of wait cycles and the number |
| * of flash accesses. |
| * |
| * @param[in] p_reg Pointer to the structure of registers of the peripheral. |
| * @param[in] config ICache configuration. |
| */ |
| __STATIC_INLINE void nrf_nvmc_icache_config_set(NRF_NVMC_Type * p_reg, |
| nrf_nvmc_icache_config_t config); |
| |
| /** |
| * @brief Function for checking if ICache is enabled. |
| * |
| * @param[in] p_reg Pointer to the structure of registers of the peripheral. |
| * |
| * @retval true ICache enabled. |
| * @retval false ICache disabled. |
| */ |
| __STATIC_INLINE bool nrf_nvmc_icache_enable_check(NRF_NVMC_Type const * p_reg); |
| |
| /** |
| * @brief Function for checking if the ICache profiling option is enabled. |
| * |
| * @param[in] p_reg Pointer to the structure of registers of the peripheral. |
| * |
| * @retval true ICache profiling enabled. |
| * @retval false ICache profiling disabled. |
| */ |
| __STATIC_INLINE bool nrf_nvmc_icache_profiling_enable_check(NRF_NVMC_Type const * p_reg); |
| |
| /** |
| * @brief Function for getting the number of ICache hits. |
| * |
| * @param[in] p_reg Pointer to the structure of registers of the peripheral. |
| * |
| * @retval Number of the ICache hits. |
| */ |
| __STATIC_INLINE uint32_t nrf_nvmc_icache_hit_get(NRF_NVMC_Type const * p_reg); |
| |
| /** |
| * @brief Function for getting the number of ICache misses. |
| * |
| * @param[in] p_reg Pointer to the structure of registers of the peripheral. |
| * |
| * @retval Number of the ICache misses. |
| */ |
| __STATIC_INLINE uint32_t nrf_nvmc_icache_miss_get(NRF_NVMC_Type const * p_reg); |
| |
| /** |
| * @brief Function for resetting the ICache hit and miss counters. |
| * |
| * @param[in] p_reg Pointer to the structure of registers of the peripheral. |
| */ |
| __STATIC_INLINE void nrf_nvmc_icache_hit_miss_reset(NRF_NVMC_Type * p_reg); |
| #endif // defined(NRF_NVMC_ICACHE_PRESENT) |
| |
| #ifndef SUPPRESS_INLINE_IMPLEMENTATION |
| |
| __STATIC_INLINE bool nrf_nvmc_ready_check(NRF_NVMC_Type const * p_reg) |
| { |
| return (bool)(p_reg->READY & NVMC_READY_READY_Msk); |
| } |
| |
| #if defined(NVMC_READYNEXT_READYNEXT_Msk) |
| __STATIC_INLINE bool nrf_nvmc_write_ready_check(NRF_NVMC_Type const * p_reg) |
| { |
| return (bool)(p_reg->READYNEXT & NVMC_READYNEXT_READYNEXT_Msk); |
| } |
| #endif |
| |
| __STATIC_INLINE void nrf_nvmc_mode_set(NRF_NVMC_Type * p_reg, |
| nrf_nvmc_mode_t mode) |
| { |
| p_reg->CONFIG = (uint32_t)mode; |
| } |
| |
| #if defined(NVMC_CONFIGNS_WEN_Msk) |
| __STATIC_INLINE void nrf_nvmc_nonsecure_mode_set(NRF_NVMC_Type * p_reg, |
| nrf_nvmc_ns_mode_t mode) |
| { |
| p_reg->CONFIGNS = (uint32_t)mode; |
| } |
| #endif |
| |
| __STATIC_INLINE void nrf_nvmc_page_erase_start(NRF_NVMC_Type * p_reg, |
| uint32_t page_addr) |
| { |
| #if defined(NRF51) |
| /* On nRF51, the code area can be divided into two regions: CR0 and CR1. |
| * The length of CR0 is specified in the CLENR0 register of UICR. |
| * If CLENR0 contains the 0xFFFFFFFF value, CR0 is not set. |
| * Moreover, the page from CR0 can be written or erased only from code |
| * running in CR0.*/ |
| uint32_t cr0_len = NRF_UICR->CLENR0 == 0xFFFFFFFF ? 0 : NRF_UICR->CLENR0; |
| if (page_addr < cr0_len) |
| { |
| p_reg->ERASEPCR0 = page_addr; |
| } |
| else |
| { |
| p_reg->ERASEPCR1 = page_addr; |
| } |
| #elif defined(NRF52_SERIES) |
| p_reg->ERASEPAGE = page_addr; |
| #elif defined(NRF9160_XXAA) |
| *(volatile uint32_t *)page_addr = 0xFFFFFFFF; |
| (void)p_reg; |
| #else |
| #error "Unknown device." |
| #endif |
| } |
| |
| #if defined(NVMC_ERASEUICR_ERASEUICR_Msk) |
| __STATIC_INLINE void nrf_nvmc_uicr_erase_start(NRF_NVMC_Type * p_reg) |
| { |
| p_reg->ERASEUICR = 1; |
| } |
| #endif |
| |
| __STATIC_INLINE void nrf_nvmc_erase_all_start(NRF_NVMC_Type * p_reg) |
| { |
| p_reg->ERASEALL = 1; |
| } |
| |
| #if defined(NRF_NVMC_PARTIAL_ERASE_PRESENT) |
| __STATIC_INLINE void nrf_nvmc_partial_erase_duration_set(NRF_NVMC_Type * p_reg, |
| uint32_t duration_ms) |
| { |
| p_reg->ERASEPAGEPARTIALCFG = duration_ms; |
| } |
| |
| __STATIC_INLINE uint32_t nrf_nvmc_partial_erase_duration_get(NRF_NVMC_Type const * p_reg) |
| { |
| return p_reg->ERASEPAGEPARTIALCFG; |
| } |
| |
| __STATIC_INLINE void nrf_nvmc_page_partial_erase_start(NRF_NVMC_Type * p_reg, |
| uint32_t page_addr) |
| { |
| #if defined(NVMC_ERASEPAGEPARTIAL_ERASEPAGEPARTIAL_Msk) |
| p_reg->ERASEPAGEPARTIAL = page_addr; |
| #elif defined(NRF9160_XXAA) |
| nrf_nvmc_page_erase_start(p_reg, page_addr); |
| #else |
| #error "Unknown device." |
| #endif |
| } |
| #endif // defined(NRF_NVMC_PARTIAL_ERASE_PRESENT) |
| |
| #if defined(NRF_NVMC_ICACHE_PRESENT) |
| __STATIC_INLINE void nrf_nvmc_icache_config_set(NRF_NVMC_Type * p_reg, |
| nrf_nvmc_icache_config_t config) |
| { |
| p_reg->ICACHECNF = (uint32_t)config; |
| } |
| |
| __STATIC_INLINE bool nrf_nvmc_icache_enable_check(NRF_NVMC_Type const * p_reg) |
| { |
| return (bool)(p_reg->ICACHECNF & NVMC_ICACHECNF_CACHEEN_Msk); |
| } |
| |
| __STATIC_INLINE bool nrf_nvmc_icache_profiling_enable_check(NRF_NVMC_Type const * p_reg) |
| { |
| return (bool)(p_reg->ICACHECNF & NVMC_ICACHECNF_CACHEPROFEN_Msk); |
| } |
| |
| __STATIC_INLINE uint32_t nrf_nvmc_icache_hit_get(NRF_NVMC_Type const * p_reg) |
| { |
| return p_reg->IHIT; |
| } |
| |
| __STATIC_INLINE uint32_t nrf_nvmc_icache_miss_get(NRF_NVMC_Type const * p_reg) |
| { |
| return p_reg->IMISS; |
| } |
| |
| __STATIC_INLINE void nrf_nvmc_icache_hit_miss_reset(NRF_NVMC_Type * p_reg) |
| { |
| p_reg->IHIT = 0; |
| p_reg->IMISS = 0; |
| } |
| #endif // defined(NRF_NVMC_ICACHE_PRESENT) |
| |
| #endif // SUPPRESS_INLINE_IMPLEMENTATION |
| |
| /** @} */ |
| |
| #ifdef __cplusplus |
| } |
| #endif |
| |
| #endif // NRF_NVMC_H__ |