/**************************************************************************** * arch/arm/src/nrf52/nrf52_nvmc.c * * Copyright (C) 2018 Zglue Inc. All rights reserved. * Author: Levin Li * Author: Alan Carvalho de Assis * * Ported from the Nordic SDK, this is the original license: * * Copyright (c) 2012 - 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 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. * ****************************************************************************/ /**************************************************************************** * Included Files ****************************************************************************/ #include #include #include "arm_arch.h" #include "barriers.h" #include "hardware/nrf52_ficr.h" #include "hardware/nrf52_nvmc.h" #include "nrf52_nvmc.h" /**************************************************************************** * Private Functions ****************************************************************************/ /**************************************************************************** * Name: wait_for_flash_ready * * Description: * Busy-wait until the flash operation is done. * * Input Parameter: * None * * Returned Values: * None * ****************************************************************************/ static inline void wait_for_flash_ready(void) { while (!(getreg32(NRF52_NVMC_READY) & NVMC_READY_READY)) { } } /**************************************************************************** * Name: nrf_mem_barrier * * Description: * Force memory sync before continuing. * * Input Parameter: * None * * Returned Values: * None * ****************************************************************************/ static inline void nrf_mem_barrier(void) { ARM_ISB(); ARM_DSB(); } /**************************************************************************** * Public Functions ****************************************************************************/ /**************************************************************************** * Name: nrf_nvmc_enable_icache * * Description: * Enable I-Cache for Flash * * Input Parameter: * flag - Flag to enable or disable. * * Returned Values: * None * ****************************************************************************/ void nrf_nvmc_enable_icache(bool flag) { uint32_t value; /* Read the current icache configuration */ value = getreg32(NRF52_NVMC_ICACHECNF); if (flag) { value |= NVMC_ICACHECNF_CACHEEN; } else { value &= ~NVMC_ICACHECNF_CACHEEN; } /* Setup the new icache configuration */ putreg32(value, NRF52_NVMC_ICACHECNF); } /**************************************************************************** * Name: nrf_nvmc_enable_profile * * Description: * Enable profiling I-Cache for flash * * Input Parameter: * flag - Flag to enable or disable. * * Returned Values: * None * ****************************************************************************/ void nrf_nvmc_enable_profile(bool flag) { uint32_t value; /* Read the current icache configuration */ value = getreg32(NRF52_NVMC_ICACHECNF); if (flag) { value |= NVMC_ICACHECNF_CACHEPROFEN; } else { value &= ~NVMC_ICACHECNF_CACHEPROFEN; } /* Setup the new icache configuration */ putreg32(value, NRF52_NVMC_ICACHECNF); } /**************************************************************************** * Name: nrf_nvmc_get_profiling_ihit * * Description: * Get I-Hit for profiling * * Input Parameter: * None * * Returned Values: * Number of cache hits. * ****************************************************************************/ uint32_t nrf_nvmc_get_profiling_ihit(void) { return getreg32(NRF52_NVMC_IHIT); } /**************************************************************************** * Name: nrf_nvmc_get_profiling_imiss * * Description: * Get I-Miss for profiling * * Input Parameter: * None * * Returned Values: * Number of cache misses. * ****************************************************************************/ uint32_t nrf_nvmc_get_profiling_imiss(void) { return getreg32(NRF52_NVMC_IMISS); } /**************************************************************************** * Name: nrf_nvmc_get_flash_size * * Description: * Get internal FLASH size * * Input Parameter: * None * * Returned Values: * Flash size. * ****************************************************************************/ uint32_t nrf_nvmc_get_flash_size(void) { return getreg32(NRF52_FICR_INFO_FLASH) * 1024; } /**************************************************************************** * Name: nrf_nvmc_get_ram_size * * Description: * Get internal RAM size. * * Input Parameter: * None * * Returned Values: * RAM size. * ****************************************************************************/ uint32_t nrf_nvmc_get_ram_size(void) { return getreg32(NRF52_FICR_INFO_RAM) * 1024; } /**************************************************************************** * Name: nrf_nvmc_read_dev_id0 * * Description: * Get device identifier 0 * * Input Parameter: * None * * Returned Values: * Value of ID0 * ****************************************************************************/ uint32_t nrf_nvmc_read_dev_id0(void) { return getreg32(NRF52_FICR_DEVICEID0); } /**************************************************************************** * Name: nrf_nvmc_read_dev_id1 * * Description: * Get device identifier 1 * * Input Parameter: * None * * Returned Values: * Value of ID1 * ****************************************************************************/ uint32_t nrf_nvmc_read_dev_id1(void) { return getreg32(NRF52_FICR_DEVICEID1); } /**************************************************************************** * Name: system_image_start_address * * Description: * Get system image code begin address. * * Input Parameter: * None * * Returned Values: * Address where code starts. * ****************************************************************************/ uint32_t system_image_start_address(void) { extern uint32_t _stext; return (uint32_t)&_stext; } /**************************************************************************** * Name: system_image_ro_section_end * * Description: * Get system image end address of read only section. * * Input Parameter: * None * * Returned Values: * The end address of the RO section. * ****************************************************************************/ uint32_t system_image_ro_section_end(void) { extern uint32_t _eronly; return (uint32_t)&_eronly; } /**************************************************************************** * Name: system_image_data_section_size * * Description: * Get system image data section size * * Input Parameter: * None * * Returned Values: * The size of the data section. * ****************************************************************************/ uint32_t system_image_data_section_size(void) { extern uint32_t _edata; extern uint32_t _sdata; uint32_t data_size; uint32_t start; uint32_t end; start = (uint32_t)&_sdata; end = (uint32_t)&_edata; data_size = end - start; return data_size; } /**************************************************************************** * Name: nrf_nvmc_page_erase * * Description: * Erase a page in flash. This is required before writing to any * address in the page. * * Input Parameter: * address - Start address of the page. * * Returned Values: * None * ****************************************************************************/ void nrf_nvmc_page_erase(uint32_t address) { /* Enable erase */ putreg32(NVMC_CONFIG_EEN, NRF52_NVMC_CONFIG); nrf_mem_barrier(); /* Erase the page */ putreg32(address, NRF52_NVMC_ERASEPAGE); wait_for_flash_ready(); /* Return to read-only mode */ putreg32(NVMC_CONFIG_REN, NRF52_NVMC_CONFIG); nrf_mem_barrier(); } /**************************************************************************** * Name: nrf_nvmc_write_byte * * Description: * The function reads the word containing the byte, and then * rewrites the entire word. * * Input Parameter: * address - Address to write to. * value - Value to write. * * Returned Values: * None * ****************************************************************************/ void nrf_nvmc_write_byte(uint32_t address, uint8_t value) { uint32_t byte_shift = address & (uint32_t)0x03; uint32_t address32 = address & ~byte_shift; /* Address to the word this byte is in. */ uint32_t value32 = (*(uint32_t *)address32 & ~((uint32_t)0xff << (byte_shift << (uint32_t)3))); value32 = value32 + ((uint32_t)value << (byte_shift << 3)); /* Enable write */ putreg32(NVMC_CONFIG_WEN, NRF52_NVMC_CONFIG); nrf_mem_barrier(); /* Write the byte, needs to be a single 32-bit write operation */ *(uint32_t *)address32 = value32; wait_for_flash_ready(); /* Return to read-only mode */ putreg32(NVMC_CONFIG_REN, NRF52_NVMC_CONFIG); nrf_mem_barrier(); } /**************************************************************************** * Name: nrf_nvmc_write_word * * Description: * Write a 32-bit word to flash. * * Input Parameter: * address - Address to write to. * value - Value to write. * * Returned Values: * None * ****************************************************************************/ void nrf_nvmc_write_word(uint32_t address, uint32_t value) { /* Enable write */ putreg32(NVMC_CONFIG_WEN, NRF52_NVMC_CONFIG); nrf_mem_barrier(); /* Write the word */ *(uint32_t *)address = value; wait_for_flash_ready(); /* Return to read-only mode */ putreg32(NVMC_CONFIG_REN, NRF52_NVMC_CONFIG); nrf_mem_barrier(); } /**************************************************************************** * Name: nrf_nvmc_write_bytes * * Description: * Write consecutive bytes to flash. * * Input Parameter: * address - Address to write to. * src - Pointer to data to copy from. * num_bytes - Number of bytes in src to write. * * Returned Values: * None * ****************************************************************************/ void nrf_nvmc_write_bytes(uint32_t address, const uint8_t *src, uint32_t num_bytes) { uint32_t i; for (i = 0; i < num_bytes; i++) { nrf_nvmc_write_byte(address + i, src[i]); } } /**************************************************************************** * Name: nrf_nvmc_write_words * * Description: * Write consecutive words to flash. * * Input Parameter: * address - Address to write to. * src - Pointer to data to copy from. * num_words - Number of words in src to write. * * Returned Values: * None * ****************************************************************************/ void nrf_nvmc_write_words(uint32_t address, const uint32_t *src, uint32_t num_words) { uint32_t i; /* Enable write */ putreg32(NVMC_CONFIG_WEN, NRF52_NVMC_CONFIG); nrf_mem_barrier(); for (i = 0; i < num_words; i++) { ((uint32_t *)address)[i] = src[i]; wait_for_flash_ready(); } /* Return to read-only mode */ putreg32(NVMC_CONFIG_REN, NRF52_NVMC_CONFIG); nrf_mem_barrier(); }