You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
451 lines
15 KiB
451 lines
15 KiB
/*
|
|
* 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__
|
|
|