Zephyr OS Nordic芯片的Flash 操作
目录
概述
1. 软硬件环境
1.1 软件开发环境
1.2 硬件环境
2 Flash操作库函数
2.1 nRF52832的Flash
2.2 Nordic 特有的 Flash 操作
2.2.1 nrfx_nvmc_bytes_write 函数
2.2.2 nrfx_nvmc_page_erase函数
2.2.3 nrfx_nvmc_write_done_check 函数
3 操作Flash的接口函数
3.1 接口实现
3.2 函数接口
4 验证
4.1 读取Flash的参数
4.2 大容量数据读写操作
5 使用Zephyr的Flash接口实现驱动
5.1 代码实现
5.2 测试代码实现
5.3 验证功能
概述
本文主要介绍基于 Zephyr RTOS 操作 Nordic 芯片的 Flash 存储器,其主要涉及以下几个方面:Nordic 内部Flash的资源,操作Flash的接口,验证读写数据功能等内容。
1. 软硬件环境
1.1 软件开发环境
nordic提供了基于zephyr平台sdk, 其提供了大量的demo可供开发者参考和使用,同时nordi还提供一个集成的软件库工具,方便开发者安装相应的SDK和编译工具链。集成环境同时包含了其他的一些软件,非常便于进行项目开发。
软件工具 | 功能 | 版本信息 |
nRF Connect SDK | nordic提供基于zephyr的代码库 | v2.9.0 |
nRF Connect SDK Toolchain | 代码编译工具 | v2.9.1 |
VS-CODE | 集成开发环境 | v1.99.3 |
nRF Connect for Desktop | nordic集成工具链 | v5.1.0 |
nRF Connect | 手机App |
手机App下载地址:
https://nav.nordicsemi.com/search?query=nRF%20Connect
1.2 硬件环境
本案例是在nRF52832开发板(nRF52-DK)上实现的,该开发板nRF52832的主要特点如下:
1)板载j-link调试接口
2)引出所有 IO接口,用户可根据实际应用,外载其他设备
3)支持4个LED
4)支持4路Key接口
5)板载UART调试接口,方便打印调试信息
2 Flash操作库函数
2.1 nRF52832的Flash
在 Zephyr 的设备树中配置 Flash如下,本文以nRF52832的设备树为例:
具体设备树代码如下:
&flash0 {partitions {compatible = "fixed-partitions";#address-cells = <1>;#size-cells = <1>;boot_partition: partition@0 {label = "mcuboot";reg = <0x00000000 0xc000>;};slot0_partition: partition@c000 {label = "image-0";reg = <0x0000C000 0x37000>;};slot1_partition: partition@43000 {label = "image-1";reg = <0x00043000 0x37000>;};storage_partition: partition@7a000 {label = "storage";reg = <0x0007a000 0x00006000>;};};
2.2 Nordic 特有的 Flash 操作
2.2.1 nrfx_nvmc_bytes_write
函数
nrfx_nvmc_bytes_write
是 Nordic 提供的用于向 Flash 写入数据的底层函数,属于 nrfx 驱动库的一部分。这个函数提供了比 Zephyr 通用 Flash API 更底层的访问方式。
函数原型
nrfx_err_t nrfx_nvmc_bytes_write(uint32_t addr, const void *p_src, uint32_t num_bytes);
参数说明
参数 | 类型 | 描述 |
---|---|---|
addr | uint32_t | Flash 中要写入的目标地址 |
p_src | const void * | 包含要写入数据的源缓冲区指针 |
num_bytes | uint32_t | 要写入的字节数 |
返回值
返回
nrfx_err_t
类型,可能的值为:
NRFX_SUCCESS
- 写入成功完成
NRFX_ERROR_INVALID_ADDR
- 提供的地址无效
NRFX_ERROR_INVALID_LENGTH
- 请求的长度无效
重要注意事项
地址对齐:
虽然函数名为
bytes_write
,但实际上写入操作是以32位字为单位进行的地址必须是4字节对齐的(addr % 4 == 0)
长度也必须是4的倍数
Flash状态:
目标区域必须已经被擦除(全为0xFF)
只能将1改为0(不能将0改为1)
中断影响:
Flash写入期间CPU会被暂停
建议在写入关键代码段时禁用中断
2.2.2 nrfx_nvmc_page_erase函数
nrfx_nvmc_page_erase
是 Nordic nRF 系列芯片提供的用于擦除 Flash 页面的底层函数,属于 nrfx 驱动库的一部分。这个函数执行的是对整个 Flash 页的擦除操作。
函数原型
void nrfx_nvmc_page_erase(uint32_t address);
参数说明
参数 | 类型 | 描述 |
---|---|---|
address | uint32_t | 要擦除的 Flash 页中的任意地址 |
注意事项:
页面大小:
不同 nRF 芯片的 Flash 页面大小不同
nRF51 系列:1024 字节 (1KB)
nRF52 系列:4096 字节 (4KB)
可以使用
NRF_FICR->CODEPAGESIZE
获取实际的页面大小地址对齐:
地址参数不需要严格对齐到页面起始地址
函数会自动对齐到包含该地址的页面起始地址
擦除效果:
擦除后,整个页面的所有位将被设置为 1 (0xFF)
擦除是写入操作的必要前提
2.2.3 nrfx_nvmc_write_done_check
函数
nrfx_nvmc_write_done_check
是 Nordic nRF 系列芯片提供的用于检查 Flash 写入/擦除操作是否完成的辅助函数,属于 nrfx 驱动库的一部分。
函数原型
bool nrfx_nvmc_write_done_check(void);
功能说明
主要用途:
检查 NVMC (Non-Volatile Memory Controller) 是否已完成前一次 Flash 编程或擦除操作
提供非阻塞式的操作完成状态检查机制
返回值:
true
:表示所有挂起的 Flash 操作已完成
false
:表示 Flash 操作仍在进行中底层原理:
通过检查 NVMC 的 READY 寄存器位来确定操作状态
对应寄存器位:
NRF_NVMC->READY
3 操作Flash的接口函数
3.1 接口实现
在Zephyr OS框架下使用Flash的相关接口,需要做如下配置:
1)在.conf文件中使能Flash的操作接口
CONFIG_NRFX_NVMC=y
CONFIG_FLASH=yCONFIG_FLASH_PAGE_LAYOUT=y
CONFIG_FLASH_MAP=y
2)引用相关的头文件
#include <zephyr/kernel.h>
#include <zephyr/drivers/flash.h>
#include <nrfx_nvmc.h>
3.2 函数接口
1)写操作
u32 user_flash_write(u32 addr, const u8 *buf, u32 size)
{nrfx_nvmc_bytes_write(addr, buf, size);while(nrfx_nvmc_write_done_check() == false);return size;
}
2)读操作
u32 user_flash_read(u32 addr, u8 *buf, u32 size)
{u32 i;const uint8_t *p = (const uint8_t *)addr;for (i = 0; i < size; i ++) {*buf ++ = *p ++;}return size;
}
3)擦除操作
s8 user_flash_erase(u32 addr)
{nrfx_err_t err_code = nrfx_nvmc_page_erase(addr);if (err_code != NRFX_SUCCESS){LOG_ERR("Erase flash page(0x%08x) err_code(0x%08x)", addr, err_code);}while(nrfx_nvmc_write_done_check() == false){// wait for erase to complete}return 0;
}
4 验证
4.1 读取Flash的参数
实现函数接口如下:
void user_drv_flash_msg( void )
{flash_msg.paga_size = nrfx_nvmc_flash_page_size_get();flash_msg.total_bytes = nrfx_nvmc_flash_size_get();flash_msg.total_page = nrfx_nvmc_flash_page_count_get();printf("Flash page size: %d bytes \r\n", flash_msg.paga_size );printf("Total flash size: %d bytes \r\n", flash_msg.total_bytes );printf("Total flash page count: %d \r\n ", flash_msg.total_page);
}
验证结果如下:
4.2 大容量数据读写操作
实现一个写大容量的数据函数:
#define NOR_FLASH_PAGE_SIZE 4096u8 wrflash_buff[NOR_FLASH_PAGE_SIZE];
void nor_flash_Write( u32 WriteAddr, u8 *pBuffer, u16 NumByteToWrite)
{ u32 secpos;u16 secoff;u16 secremain;u16 i;secpos = WriteAddr/NOR_FLASH_PAGE_SIZE;secoff = WriteAddr%NOR_FLASH_PAGE_SIZE;secremain = NOR_FLASH_PAGE_SIZE-secoff;if(NumByteToWrite <= secremain)secremain = NumByteToWrite;while(1) {user_flash_read(secpos*NOR_FLASH_PAGE_SIZE, wrflash_buff, NOR_FLASH_PAGE_SIZE); for( i=0; i<secremain; i++){if(wrflash_buff[secoff+i]!=0XFF)break; }if(i<secremain){user_flash_erase(secpos*NOR_FLASH_PAGE_SIZE);for(i=0;i<secremain;i++){wrflash_buff[i+secoff]=pBuffer[i];}user_flash_write(secpos*NOR_FLASH_PAGE_SIZE,wrflash_buff, NOR_FLASH_PAGE_SIZE);}else{user_flash_write( WriteAddr, pBuffer, secremain);} if( NumByteToWrite == secremain)break;else{secpos++;secoff=0;pBuffer += secremain; WriteAddr += secremain;NumByteToWrite -= secremain;if( NumByteToWrite>NOR_FLASH_PAGE_SIZE )secremain = NOR_FLASH_PAGE_SIZE;elsesecremain = NumByteToWrite; }}
}
验证函数:
u8 write_buff[1024];
u8 read_fuff[1024];
void test_flash()
{user_drv_flash_msg();for( int i = 0; i < 1024; i++ ){write_buff[i] = 0x5a;}u32 address = flash_msg.total_bytes - (flash_msg.total_page-3)*4096 - 12;nor_flash_Write(address,write_buff, 1024);// read buff user_flash_read(address, read_fuff, 1024);for( int i = 0; i < 1024; i++ ){if( read_fuff[i] != write_buff[i]){printk(" test_flash: failed \n"); return;}}printk(" test_flash: pass \n"); }
验证结果如下:
5 使用Zephyr的Flash接口实现驱动
5.1 代码实现
使用的主要接口:
#include <drivers/flash.h>// 获取 Flash 设备
const struct device *flash_dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_flash_controller));// 读取数据
int flash_read(const struct device *dev, off_t offset, void *data, size_t len);// 写入数据
int flash_write(const struct device *dev, off_t offset, const void *data, size_t len);// 擦除扇区
int flash_erase(const struct device *dev, off_t offset, size_t size);
5.2 测试代码实现
u8 write_buff[1024];
u8 read_fuff[1024];const struct device *flash_dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_flash_controller));void test_flash( void )
{u32 address;user_drv_flash_msg();address = flash_msg.total_bytes - (flash_msg.total_page-3)*4096;for( int i = 0; i < 1024; i++ ){write_buff[i] = 0x5a;}// 擦除一个页面 (通常4KB)flash_erase(flash_dev, address, 4096);// 写入数据flash_write(flash_dev, address, write_buff, sizeof(write_buff));// 读取验证flash_read(flash_dev, address, read_fuff, sizeof(read_fuff));for( int i = 0; i < 1024; i++ ){if( read_fuff[i] != write_buff[i]){printk(" test_flash: failed \n"); return;}}printk(" test_flash: pass \n");
}
5.3 验证功能
烧写代码,运行后结果如下:
相关文章:

Zephyr OS Nordic芯片的Flash 操作
目录 概述 1. 软硬件环境 1.1 软件开发环境 1.2 硬件环境 2 Flash操作库函数 2.1 nRF52832的Flash 2.2 Nordic 特有的 Flash 操作 2.2.1 nrfx_nvmc_bytes_write 函数 2.2.2 nrfx_nvmc_page_erase函数 2.2.3 nrfx_nvmc_write_done_check 函数 3 操作Flash的接口函数…...

uv python 卸载
又是查了半天 官网wiki没有 网上一堆傻子胡说 uv提示也不对 AI还在这尼玛胡编乱造 开始 我原来装了这几个环境 uv python list 现在python3.7.7不需要了,卸载,直接 uv python uninstall 3.7.7 去找你自己要卸载的版本号,不需要整个包名复制…...
MCP本地高效与云端实时:stdio 与 HTTP+SSE 传输机制深度对比
概览 模型上下文协议(MCP)定义了客户端与服务器之间通信的统一标准,所有消息均采用 JSON-RPC 2.0 格式进行封装,并在此基础上支持两种传输机制:stdio(标准输入/输出) 与 HTTPSSE(Se…...

浮点数截断法:四舍五入的精确模拟
理论解释: 1. 目标 假设 a 3.14159,我们想四舍五入到 小数点后两位(即 3.14 或 3.15)。 2. 步骤拆解 (1) a * 100 把 a 放大 100 倍,让小数点后两位变成整数部分: 3.14159 * 100 314.159 (2) 0.5 关…...

技术文章:解决汇川MD500系列变频器干扰问题——GRJ9000S EMC滤波器的应用
1. 引言 汇川MD500系列变频器(Variable Frequency Drive, VFD)以其高性能、宽功率范围(0.4kW-500kW)和灵活的控制方式,广泛应用于工业自动化领域,如风机、水泵、传送带和压缩机等。然而,MD500系…...

大模型数据分析破局之路20250512
大模型数据分析破局之路 本文面向 AI 初学者、数据分析从业者与企业技术负责人,围绕大模型如何为数据分析带来范式转变展开,从传统数据分析困境谈起,延伸到 LLM MCP 的协同突破,最终落脚在企业实践建议。 🌍 开篇导语…...

基于javaweb的SSM驾校管理系统设计与实现(源码+文档+部署讲解)
技术范围:SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容:免费功能设计、开题报告、任务书、中期检查PPT、系统功能实现、代码编写、论文编写和辅导、论文…...

Java内存泄露生产环境排查过程,通透了
昨天线上环境崩了 java堆内存溢出。。。 报错:java.lang.OutOfMemoryError: Java heap space 下面我将我排查问题的思路和过程记录了下来 1. 场景 客户端跟Java服务端通过websocket连接建立长链接并发送语音数据(text格式)Java服务端跟听…...

NHANES指标推荐:MDS
文章题目:The association between magnesium depletion score (MDS) and overactive bladder (OAB) among the U.S. population DOI:10.1186/s41043-025-00846-x 中文标题:美国人群镁耗竭评分 (MDS) 与膀胱过度活动症…...
以项目的方式学QT开发C++(二)——超详细讲解(120000多字详细讲解,涵盖qt大量知识)逐步更新!
API 描述 函数原型 参数说明 push_back() 在 list 尾部 添加一个元素 void push_back(const T& value); value :要添 加到尾部的元 素 这个示例演示了如何创建 std::list 容器,并对其进行插入、删除和迭代操作。在实际应用中&am…...
Docker使用经验-从Image导出dockerfile并进行修改
好久没进行记录写作了,还是得进行下去 0 前言 项目上拉下来的docker-image在我自己电脑上创建的容器不能正常启动,创建者在容器里面添加的了用户,容器启动后会进入该用户 1 docker导出dockerfile dfimage是一个用于从Docker镜像生成Docker…...

【HTML5学习笔记1】html标签(上)
web标准(重点) w3c 构成:结构、表现、行为,结构样式行为相分离 结构:网页元素整理分类 html 表现:外观css 行为:交互 javascript html标签 1.html语法规范 1) 所有标签都在…...

计算机视觉---目标检测(Object Detecting)概览
一、目标检测定义与核心任务 1. 定义 任务:在图像/视频中定位并分类所有感兴趣目标,输出边界框(Bounding Box)和类别标签。核心输出: 坐标:((x_1, y_1, x_2, y_2))(左上角右下角)或…...

在vue3中使用Cesium的保姆教程
1. 软件下载与安装 1. node安装 Vue.js 的开发依赖于 Node.js 环境,因此我们首先需要安装 Node.js。Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境,它允许你在服务器端运行 JavaScript 代码,同时也为前端开发提供了强大的工具支…...

IP地址、端口、TCP介绍、socket介绍、程序中socket管理
1、IP地址:IP 地址就是 标识网络中设备的一个地址,好比现实生活中的家庭地址。IP 地址的作用是 标识网络中唯一的一台设备的,也就是说通过IP地址能够找到网络中某台设备。 2、端口:代表不同的进程,如下图: 3、socket:…...
基于MCP的桥梁设计规范智能解析与校审系统构建实践
引言 在腾讯云开发者社区中,有多种MCP工具可以用于本系统的开发和优化中,以下是一些潜在的应用场景: PDF解析工具:如pdfplumber等,可以用于规范文件的预处理,提取文本和图像信息。自然语言处理工具…...

搭建运行若依微服务版本ruoyi-cloud最新教程
搭建运行若依微服务版本ruoyi-cloud 一、环境准备 JDK > 1.8MySQL > 5.7Maven > 3.0Node > 12Redis > 3 二、后端 2.1数据库准备 在navicat上创建数据库ry-seata、ry-config、ry-cloud运行SQL文件ry_20250425.sql、ry_config_20250224.sql、ry_seata_2021012…...
OM和SCADA的区别
在工业与能源领域,O&M(Operation and Maintenance,运维) 和 SCADA(Supervisory Control And Data Acquisition,监控与数据采集系统) 是两类截然不同的概念,前者是 人员与流程驱动…...
CentOS7 grub配置文件介绍
1. grub2-editenv list saved_entryCentOS Linux (3.10.0-1160.el7.x86_64) 7 (Core) 这个命令查询出当前启动的内核版本。 2.grep ^menu /boot/grub2/grub.cfg menuentry CentOS Linux (3.10.0-1160.el7.x86_64) 7 (Core) --class centos --class gnu-linux --class gnu --c…...
SpringBoot常用注解详解
文章目录 1. 前言2. 核心注解2.1 SpringBootApplication2.2 Configuration2.3 EnableAutoConfiguration2.4 ComponentScan2.5 Bean2.6 Autowired2.7 Qualifier2.8 Primary2.9 Value2.10 PropertySource2.11 ConfigurationProperties2.12 Profile 3. Web开发相关注解3.1 Control…...
Python字符串常用内置函数详解
文章目录 Python字符串常用内置函数详解一、基础字符串函数1. len() - 获取字符串长度2. ord() - 获取字符的Unicode码点3. chr() - 通过Unicode码点获取字符4. ascii() - 获取字符的ASCII表示 二、类型转换函数1. str() - 将对象转为字符串2. repr() - 获取对象的官方字符串表…...
MyBatis 批量新增与删除功能完整教程
一、功能概述 通过 MyBatis 动态 SQL 实现以下功能: 批量新增:一次性插入多条员工记录,支持自增主键回填。批量删除:根据 ID 数组一次性删除多条记录。二、代码逐行解析 1. Mapper 接口定义 // 批量新增:传入员工对象集合 void insertAll(List<Emp> empList);// …...
HTML常用标签用法全解析:构建语义化网页的核心指南
HTML作为网页开发的基石,其标签的合理使用直接影响页面的可读性、SEO效果及维护性。本文系统梳理HTML核心标签的用法,结合语义化设计原则与实战示例,助你构建规范、高效的网页结构。 一、基础结构与排版标签 1.1 文档结构 <!DOCTYPE htm…...
大数据架构选型全景指南:核心架构对比与实战案例 解析
目录 大数据架构选型全景指南:核心架构对比与实战案例解析1. 主流架构全景概览1.1 核心架构类型1.2 关键选型维度 2. 架构对比与选型矩阵2.1 主流架构对比表2.2 选型决策树 3. 案例分析与实现案例1:电商实时推荐系统(Lambda架构)案…...
FPGA: XILINX Kintex 7系列器件的架构
本文将详细介绍Kintex-7系列FPGA器件的架构。以下内容将涵盖Kintex-7的核心架构特性、主要组成部分以及关键技术,尽量全面且结构化,同时用简洁的语言确保清晰易懂。 Kintex-7系列FPGA架构概述 Kintex-7是Xilinx 7系列FPGA中的中高端产品线,基…...

RK3568-鸿蒙5.1与原生固件-扇区对比分析
编译生成的固件目录地址 ../openharmony/out/rk3568/packages/phone/images鸿蒙OS RK3568固件分析 通过查看提供的信息,分析RK3568开发板固件的各个组件及其用途: 主要固件组件 根据终端输出的文件列表,RK3568固件包含以下关键组件&#x…...

常见激活函数——作用、意义、特点及实现
文章目录 激活函数的意义常见激活函数及其特点1. Sigmoid(Logistic 函数、S型函数)2. Tanh(双曲正切函数)3. ReLU(Rectified Linear Unit修正线性单元)4. Softmax5. Swish(Google 提出ÿ…...
Spring模拟转账开发
完成转账代码的编写 service public class AccountServiceImpl implements AccountService {Autowiredprivate AccountDao accountDao;public void setAccountDao(AccountDao accountDao) {this.accountDao accountDao;}public void pay(String out, String in, Double money)…...

基于微信小程序的在线聊天功能实现:WebSocket通信实战
基于微信小程序的在线聊天功能实现:WebSocket通信实战 摘要 本文将详细介绍如何使用微信小程序结合WebSocket协议开发一个实时在线聊天功能。通过完整的代码示例和分步解析,涵盖界面布局、WebSocket连接管理、消息交互逻辑及服务端实现,适合…...

小波变换+注意力机制成为nature收割机
小波变换作为一种新兴的信号分析工具,能够高效地提取信号的局部特征,为复杂数据的处理提供了有力支持。然而,它在捕捉数据中最为关键的部分时仍存在局限性。为了弥补这一不足,我们引入了注意力机制,借助其能够强化关注…...