525 lines
13 KiB
C
525 lines
13 KiB
C
|
/****************************************************************************
|
||
|
* arch/arm/src/nrf52/nrf52_nvmc.c
|
||
|
*
|
||
|
* Copyright (C) 2018 Zglue Inc. All rights reserved.
|
||
|
* Author: Levin Li <zhiqiang@zglue.com>
|
||
|
* Author: Alan Carvalho de Assis <acassis@gmail.com>
|
||
|
*
|
||
|
* 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 <nuttx/config.h>
|
||
|
#include <stdbool.h>
|
||
|
|
||
|
#include "chip/nrf52_ficr.h"
|
||
|
#include "chip/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();
|
||
|
}
|