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 Desktopnordic集成工具链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);

参数说明

参数类型描述
addruint32_tFlash 中要写入的目标地址
p_srcconst void *包含要写入数据的源缓冲区指针
num_bytesuint32_t要写入的字节数

 返回值

返回 nrfx_err_t 类型,可能的值为:

  • NRFX_SUCCESS - 写入成功完成

  • NRFX_ERROR_INVALID_ADDR - 提供的地址无效

  • NRFX_ERROR_INVALID_LENGTH - 请求的长度无效

  重要注意事项

  1. 地址对齐

    • 虽然函数名为 bytes_write,但实际上写入操作是以32位字为单位进行的

    • 地址必须是4字节对齐的(addr % 4 == 0)

    • 长度也必须是4的倍数

  2. Flash状态

    • 目标区域必须已经被擦除(全为0xFF)

    • 只能将1改为0(不能将0改为1)

  3. 中断影响

    • 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);

参数说明

参数类型描述
addressuint32_t要擦除的 Flash 页中的任意地址

 注意事项:

  1. 页面大小

    • 不同 nRF 芯片的 Flash 页面大小不同

    • nRF51 系列:1024 字节 (1KB)

    • nRF52 系列:4096 字节 (4KB)

    • 可以使用 NRF_FICR->CODEPAGESIZE 获取实际的页面大小

  2. 地址对齐

    • 地址参数不需要严格对齐到页面起始地址

    • 函数会自动对齐到包含该地址的页面起始地址

  3. 擦除效果

    • 擦除后,整个页面的所有位将被设置为 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);

功能说明

  1. 主要用途

    • 检查 NVMC (Non-Volatile Memory Controller) 是否已完成前一次 Flash 编程或擦除操作

    • 提供非阻塞式的操作完成状态检查机制

  2. 返回值

    • true:表示所有挂起的 Flash 操作已完成

    • false:表示 Flash 操作仍在进行中

  3. 底层原理

    • 通过检查 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 验证功能

烧写代码,运行后结果如下:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/905788.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

03、基础入门-SpringBoot的大时代背景

03、基础入门-SpringBoot的大时代背景 # Spring Boot的大时代背景 Spring Boot的出现和发展&#xff0c;与以下时代背景密切相关&#xff1a; ## 1. 微服务架构的兴起 ### 背景 随着互联网应用的复杂度增加&#xff0c;传统的单体架构在扩展性、维护性和团队协作方面遇到瓶…

ChromaDB 向量库优化技巧实战

chroma 一步步使用 安装 # 安装chromadb pip install chromadb,sentence_transformers# 不启动服务会出现sock.connect(sa)TimeoutError: timed out chroma run服务启动后&#xff0c;您将看到类似以下输出&#xff1a; 建立连接 部署完成后&#xff0c;需要建立与Chroma服…

全球泳装与沙滩装市场深度洞察:从功能性需求到可持续时尚的蜕变(2025-2031)

泳装与沙滩装作为水上活动与度假场景的核心服饰&#xff0c;正经历从单一功能性产品向“科技时尚可持续”融合的转型。根据QYResearch预测&#xff0c;2031年全球市场规模将达2512.4亿元人民币&#xff0c;年复合增长率&#xff08;CAGR&#xff09;4.0%&#xff08;2025-2031&…

WebRTC技术下的EasyRTC音视频实时通话SDK,助力车载通信打造安全高效的智能出行体验

一、方案背景​ 随着智能交通与车联网技术的飞速发展&#xff0c;车载通信在提升行车安全、优化驾驶体验以及实现智能交通管理等方面发挥着越来越重要的作用。传统的车载通信方式在实时性、稳定性以及多媒体交互能力上存在一定局限&#xff0c;难以满足现代车载场景日益复杂的…

主流数据库运维故障排查卡片式速查表与视觉图谱

主流数据库运维故障排查卡片式速查表与视觉图谱 本文件将主文档内容转化为模块化卡片结构&#xff0c;并补充数据库结构图、排查路径图、锁机制对比等视觉图谱&#xff0c;以便在演示、教学或现场排障中快速引用。 &#x1f4cc; 故障卡片速查&#xff1a;连接失败 数据库检查…

升级kafka4.0.0,无ZK版本

设备规划&#xff1a; 172.20.192.47 kafka-0 172.20.192.48 kafka-1 172.20.192.49 kafka-2 单机块7TB Nvme磁盘一共9块 # 格式化成GPT分区 sudo parted /dev/nvme0n1 --script mklabel gpt sudo parted /dev/nvme1n1 --script mklabel gpt sudo parted /dev/nvme2n1 --s…

Vue 学习随笔系列二十三 -- el-date-picker 组件

el-date-picker 组件 文章目录 el-date-picker 组件el-date-picker 只有某些日期可选 el-date-picker 只有某些日期可选 <template><div><el-form ref"form" size"mini":model"form" :rules"rules"label-width"8…

使用Python实现简单的人工智能聊天机器人

最近研学过程中发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击链接跳转到网站人工智能及编程语言学习教程。读者们可以通过里面的文章详细了解一下人工智能及其编程等教程和学习方法。下面开始对正文内容的…

[QMT量化交易小白入门]-五十四、核心资产ETF轮动目前年化只有74%了,在过滤掉当天止损,当天买入的之后

本专栏主要是介绍QMT的基础用法,常见函数,写策略的方法,也会分享一些量化交易的思路,大概会写100篇左右。 QMT的相关资料较少,在使用过程中不断的摸索,遇到了一些问题,记录下来和大家一起沟通,共同进步。 文章目录 相关阅读买入逻辑详解代码块作用解析止损逻辑详解代码…

实战解析MCP-使用本地的Qwen-2.5模型-AI协议的未来?

文章目录 目录 文章目录 前言 一、MCP是什么&#xff1f; 1.1MCP定义 1.2工作原理 二、为什么要MCP&#xff1f; 2.1 打破碎片化的困局 2.2 实时双向通信&#xff0c;提升交互效率 2.3 提高安全性与数据隐私保护 三、MCP 与 LangChain 的区别 3.1 目标定位不同 3.…

数据中心末端配电监控产品

精密配电介绍 数据中心配电系统图 交流220V和直流-48V、240V、336V(400V)对比 产品简介 AMC精密配电监控解决方案是针对精密配电柜&#xff08;列头柜&#xff09;的监控要求&#xff0c;设计开发一套完整的解决方案&#xff0c;包括交流&#xff08;AC 220V&#xff09;、直…

工业4G路由器IR5000公交站台物联网应用解决方案

随着城市化进程的加速&#xff0c;公共交通是智慧城市的重要枢纽。城市公共交通由无数的公交站台作作为节点组合而成&#xff0c;其智能化升级成为提升城市出行效率与服务质量的关键。传统公交站台信息发布滞后、缺乏实时性&#xff0c;难以满足乘客对公交信息快速获取的需求&a…

Qt图表绘制(QtCharts)- 性能优化(13)

文章目录 1 批量替换代替追加1.1 测试11.2 测试21.3 测试3 2 开启OpenGL2.1 测试12.2 测试22.3 测试32.4 测试4 更多精彩内容&#x1f449;内容导航 &#x1f448;&#x1f449;Qt开发 &#x1f448;&#x1f449;QtCharts绘图 &#x1f448;&#x1f449;python开发 &#x1f…

嵌入式故障码管理系统设计实现

文章目录 前言一、故障码管理系统概述二、核心数据结构设计2.1 故障严重等级定义2.2 模块 ID 定义2.3 故障代码结构2.4 故障记录结构 三、故障管理核心功能实现3.1 初始化功能3.2 故障记录功能3.3 记录查询与清除功能3.4 系统自检功能 四、故障存储实现4.1 Flash 存储实现4.2 R…

动态规划-63.不同路径II-力扣(LeetCode)

一、题目解析 与62.不同路径不同的一点是现在网格中有了障碍物&#xff0c;其他的并没有什么不同 二、算法解析 1.状态表示 dp[i][j]表示&#xff1a;到[i,j]位置时&#xff0c;不同的路径数 2.状态转移方程 由于多了障碍物&#xff0c;所以我们要判断是否遇到障碍物 3.初…

使用CherryStudio +SiliconFlow 部署独立的deepseek+知识库

deepseek知识库&#xff0c;独立的deepseek 首先我们先了解 CherryStudio&#xff1f;SiliconFlow&#xff1f; CherryStudio是一个支持多平台的AI客户端&#xff0c;我们致力于让更多人能够享受到AI带来的便利。 简单来说&#xff0c;它是一个能让普通人轻松用上AI 的「万能工…

Openshift节点Disk pressure

OpenShift 监控以下指标&#xff0c;并定义以下垃圾回收的驱逐阈值。请参阅产品文档以更改任何驱逐值。 nodefs.available 从 cadvisor 来看&#xff0c;该node.stats.fs.available指标表示节点文件系统&#xff08;所在位置&#xff09;上有多少可用&#xff08;剩余&#xf…

MySQL的 JOIN 优化终极指南

目录 前言序章&#xff1a;为何要有JOIN&#xff1f;——“一个好汉三个帮”的数据库哲学 &#x1f91d;第一章&#xff1a;JOIN的“七十二变”——常见JOIN类型速览 &#x1f3ad;第二章&#xff1a;MySQL的“红娘秘籍”——JOIN执行原理大揭秘 &#x1f575;️‍♀️&#x1…

TLS 1.3黑魔法:从协议破解到极致性能调优

一、TLS协议逆向工程实验 1.1 密码学套件破解剧场 实验准备&#xff1a; 靶机&#xff1a;启用TLS 1.2的Nginx服务器 工具集&#xff1a;Wireshark OpenSSL s_client 定制Python脚本 实战攻击复现&#xff1a; # 强制使用弱加密套件连接 openssl s_client -connect exa…

国标GB/T 12536-90滑行试验全解析:纯电动轻卡行驶阻力模型参数精准标定

摘要 本文以国标GB/T 12536-90为核心框架&#xff0c;深度解析纯电动轻卡滑行试验的完整流程与数据建模方法&#xff0c;提供&#xff1a; 法规级试验规范&#xff1a;从环境要求到数据采集全流程详解行驶阻力模型精准标定&#xff1a;最小二乘法求解 ( FAv^2BvC ) 的MATLAB实…