NRF52832学习笔记(27)——非易失性存储器控制器NVMC

一、简介

1.1 NVMC

nRF52832 的非易失性存储器是通过 NVMC 来管理的,NVMC 是 Non-volatile memory controller(非易失性存储器控制器)的缩写,NVMC 提供了写或擦除 Flash 区域和 UICR(用户信息配置寄存器)的功能。

写 Flash 之前必须通过写寄存器 CONFIG.WEN 来使能 Flash 的写操作,同样,擦除 Flash 之前必须通过写寄存器 CONFIG.WEN 来使能 Flash 的擦除操作。并且,对 Flash 进行操作的时候要特别注意,不能同时使能 Flash 的写和擦除,否则将导致无法预测的后果。

1.2 片内 Flash 分布

nRF52832-QFAA 片内 Flash 大小如下:


nRF52832 的 Flash 地址范围是:0x0000 0000 ~ 0x0008 0000,共 512k 字节。Flash 区域分为 128 个 4k 字节大小的页面, 每个页面包含 8 个 512 字节大小的块,需要注意的是 Flash 分布的最小单位是块,但是擦除操作最小的单位是页。

Flash 是有使用寿命的,nRF52832 片内 Flash 可擦除/写的次数是 10000 次。写和擦除所需的时间如下:

二、SDK配置

2.1 添加文件

读写 Flash 需要加入的文件如下:

文件名 SDK中的目录 描述
nrf_nvmc.c …\modules\nrfx\hal NVMC 驱动文件

2.2 添加及引用头文件

#include "nrf_nvmc.h"

三、API

3.1 擦除页

函数原型 void nrf_nvmc_page_erase(uint32_t address)
函数功能 擦除页
参数 address:页起始地铁
返回值
  • 示例:擦除第 127 页(第 127 页的起始地址是:127 * 4 * 1024 = 0x0007F000)。
    nrf_nvmc_page_erase(0x0007F000);

3.2 写

函数原型 void nrf_nvmc_write_word(uint32_t address, uint32_t value)
函数功能 向 Flash 指定地址写入一个字。注意 Flash 写之前必须擦除。
参数 address:写入的地址
value:写入的 Flash 的数据
返回值
  • 示例:向 Flash 地址 0x0007F000 写入数据“0x12345678”。
    nrf_nvmc_write_word(0x0007F000, 0x12345678);
函数原型 void nrf_nvmc_write_words(uint32_t address, const uint32_t * src, uint32_t num_words)
函数功能 向 Flash 指定地址连续写入多个字。注意 Flash 写之前必须擦除。
参数 address:写入的地址
src:写入的 Flash 的数据
num_words:写入字的数量
返回值
函数原型 void nrf_nvmc_write_byte(uint32_t address, uint8_t value)
函数功能 向 Flash 指定地址写入一字节数据。注意 Flash 写之前必须擦除。由于写 Flash 的最小单位是字,将自动补齐剩余3字节。
参数 address:写入的地址
value:写入的 Flash 的数据
返回值
函数原型 void nrf_nvmc_write_bytes(uint32_t address, const uint8_t * src, uint32_t num_bytes)
函数功能 向 Flash 指定地址写入一字节数据。注意 Flash 写之前必须擦除。由于写 Flash 的最小单位是字,不够部分将自动补齐。
参数 address:写入的地址
src:写入的 Flash 的数据
num_bytes:写入字节的数量
返回值

3.3 读

Flash 中的数据需要通过指针来读取。读取的过程是先定义指针变量,然后将该指针指向数据存放的地址,这样就可以获取 Flash 中该地址上的数据。

  • 示例:从地址 0x0007F000 读取一个字。
uint32_t *pdat; // 定义指针变量
pdat = (uint32_t *)0x0007F000; // 指针指向地址0x0007F000
printf("%x", *pdat); // 打印出读取的数据

上述代码中,因为 pdat 是指针变量,0x0007F000 是一个常数,所以要将 0x0007F000 强制转换为指针类型后赋值给 pdat。

四、读写示例(仅限于没有协议栈的工程或协议栈工作以前)


执行 Flash 写操作时,首先要规划写入数据的 Flash 空间,如第 127 页(第 127 页的起始地址是:127 * 4 * 1024 = 0x0007F000),0x0007F000 就是第 127 页的起始地址。

#include "nrf_nvmc.h"

int main(void)
{
    
    
    uint32_t addr = 0x0007F000;
    uint32_t *pdat;

    nrf_nvmc_page_erase(addr);
    nrf_nvmc_write_word(addr, 0x12345678);
    pdat = (uint32_t *)addr;
    printf("0x%x", *pdat);
}

五、读写示例(对于有softdevice协议栈的工程)

使用 sd_flash_page_erasesd_flash_write 两个函数,并且每次操作需要延时,等待协议栈有空时才执行 Flash 操作。

int main(void)
{
    
    
    uint32_t *addr;
    addr = (uint32_t *)0x7F000;
    uint32_t value = 0x12345678;
    sd_flash_page_erase(127); // 擦除第 127 页
    nrf_delay_ms(100);
    sd_flash_write(addr, (uint32_t *)&value, 1);
    nrf_delay_ms(100);
    uint32_t *pdat;
    pdat = (uint32_t *)0x7F000;
    printf("0x%x", *pdat);
}

• 由 Leung 写于 2020 年 9 月 24 日

• 参考:[艾克姆科技]

猜你喜欢

转载自blog.csdn.net/qq_36347513/article/details/108769286