Air32 | 合宙Air001单片机内部FLASH读写示例
Air32 | 合宙Air001单片机内部FLASH读写示例
代码已经通过测试,开发环境KEIL-MDK 5.36。

测试代码
void FLASH_RdWrTest(void)
{uint32_t Address;uint32_t PageReadBuffer[FLASH_PAGE_SIZE >> 2];uint32_t PageWriteBuffer[FLASH_PAGE_SIZE >> 2];memset(PageWriteBuffer, 0XAA, sizeof(PageWriteBuffer));for(Address = 0x08003000; Address < 0x08008000; Address += FLASH_PAGE_SIZE) // 16K~32K{FLASH_Write(Address, PageWriteBuffer, sizeof(PageReadBuffer) >> 2);memset(PageReadBuffer, 0, sizeof(PageReadBuffer));FLASH_Read(Address, PageReadBuffer, sizeof(PageReadBuffer) >> 2);if(memcmp(PageReadBuffer, PageWriteBuffer, sizeof(PageReadBuffer)) == 0){printf("page[%04d] 0x%08X read & write %s \r\n", (Address - FLASH_BASE) / FLASH_PAGE_SIZE, Address, "ok");}else{printf("page[%04d] 0x%08X read & write %s \r\n", (Address - FLASH_BASE) / FLASH_PAGE_SIZE, Address, "failed");}}
}
头文件
/*** @brief Create by AnKun on 2019/10/10*/#ifndef FLASH_H__
#define FLASH_H__#include "air001xx_hal.h"/// 导出函数声明
void FLASH_Init(void);
void FLASH_Read(uint32_t Address, uint32_t *Buffer, uint32_t NumToRead);
void FLASH_Write(uint32_t Address, const uint32_t *Buffer, uint32_t NumToWrite);
void FLASH_WritePage_NoCheck(uint32_t Address, const uint32_t* Buffer);
void FLASH_ErasePage(uint32_t Address);
void FLASH_SetReadProtectionState(int state);#endif // !__FLASH_H
源文件
/*** @file flash.c** @brief Create by AnKun on 2023/7/20**/#include "flash.h"
#include <string.h>static uint32_t FlashBuffer[FLASH_PAGE_SIZE >> 2];void FLASH_Init(void)
{HAL_FLASH_Unlock();__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_ALL_ERRORS); /* Clear SR register */HAL_FLASH_Lock();
}void FLASH_Read(uint32_t Address, uint32_t *Buffer, uint32_t NumToRead)
{while(NumToRead--){*Buffer++ = (*((volatile unsigned int *)Address));Address += 4;}
}void FLASH_WritePage_NoCheck(uint32_t Address, const uint32_t* Buffer)
{HAL_FLASH_Lock(); //解锁HAL_FLASH_Program(FLASH_TYPEPROGRAM_PAGE, Address, (uint32_t *)Buffer);HAL_FLASH_Unlock(); //上锁
}void FLASH_ErasePage(uint32_t Address)
{uint32_t PageError = 0;FLASH_EraseInitTypeDef EraseInitStruct = {0};HAL_FLASH_Unlock();EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGEERASE;EraseInitStruct.PageAddress = Address;EraseInitStruct.NbPages = 1; /* erase nums pages. */if(HAL_FLASHEx_Erase(&EraseInitStruct, &PageError) != HAL_OK){printf("%s\r\n", __FUNCTION__);}HAL_FLASH_Lock();
}void FLASH_Write(uint32_t Address, const uint32_t *Buffer, uint32_t NumToWrite)
{uint32_t secpos; //页地址uint32_t secoff; //页内偏移地址(16位字计算)uint32_t secremain; //页内剩余地址(16位字计算)uint32_t i;uint32_t offaddr; //去掉0X08000000后的地址HAL_FLASH_Unlock(); //解锁offaddr = Address - FLASH_BASE; //实际偏移地址.secpos = offaddr / FLASH_PAGE_SIZE; //页地址secoff = (offaddr % FLASH_PAGE_SIZE) >> 2; //在页内的偏移(2个字节为基本单位.)secremain = (FLASH_PAGE_SIZE >> 2) - secoff; //页剩余空间大小if(NumToWrite <= secremain)secremain = NumToWrite; //不大于该页范围while(1){FLASH_Read(secpos * FLASH_PAGE_SIZE + FLASH_BASE, FlashBuffer, FLASH_PAGE_SIZE >> 2); //读出整个页的内容for(i = 0; i < (FLASH_PAGE_SIZE >> 2); i++) //校验数据{if(FlashBuffer[i] != 0XFFFFFFFF){uint32_t PageError = 0;FLASH_EraseInitTypeDef EraseInitStruct = {0};EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGEERASE;EraseInitStruct.PageAddress = Address;EraseInitStruct.NbPages = 1; /* erase nums pages. */HAL_FLASHEx_Erase(&EraseInitStruct, &PageError);break;}}for(i = 0; i < secremain; i++) //复制{FlashBuffer[i + secoff] = Buffer[i];}HAL_FLASH_Program(FLASH_TYPEPROGRAM_PAGE, secpos * FLASH_PAGE_SIZE + FLASH_BASE, (uint32_t *)FlashBuffer); //写入整个页if(NumToWrite == secremain)break; //写入结束了else//写入未结束{secpos++; //页地址增1secoff = 0; //偏移位置为0Buffer += secremain; //指针偏移Address += secremain; //写地址偏移NumToWrite -= secremain; //字节(16位)数递减if(NumToWrite > (FLASH_PAGE_SIZE >> 2)) secremain = (FLASH_PAGE_SIZE >> 2); //下一个页还是写不完else secremain = NumToWrite; //下一个页可以写完了}}HAL_FLASH_Lock(); //解锁
}void FLASH_SetReadProtectionState(int onoff)
{FLASH_OBProgramInitTypeDef OptionsBytesStruct;HAL_FLASH_Unlock();HAL_FLASH_OB_Unlock();HAL_FLASH_OBGetConfig(&OptionsBytesStruct);if(onoff){if(OptionsBytesStruct.RDPLevel == OB_RDP_LEVEL_0){OptionsBytesStruct.OptionType = OPTIONBYTE_RDP;OptionsBytesStruct.RDPLevel = OB_RDP_LEVEL_1;HAL_FLASH_OBProgram(&OptionsBytesStruct);HAL_FLASH_OB_Launch();}}else{if(OptionsBytesStruct.RDPLevel == OB_RDP_LEVEL_1){OptionsBytesStruct.OptionType = OPTIONBYTE_RDP;OptionsBytesStruct.RDPLevel = OB_RDP_LEVEL_0;HAL_FLASH_OBProgram(&OptionsBytesStruct);HAL_FLASH_OB_Launch();}}HAL_FLASH_OB_Lock();HAL_FLASH_Lock();
}void FLASH_RdWrTest(void)
{uint32_t Address;uint32_t PageReadBuffer[FLASH_PAGE_SIZE >> 2];uint32_t PageWriteBuffer[FLASH_PAGE_SIZE >> 2];memset(PageWriteBuffer, 0XAA, sizeof(PageWriteBuffer));for(Address = 0x08003000; Address < 0x08008000; Address += FLASH_PAGE_SIZE) // 16K~32K{FLASH_Write(Address, PageWriteBuffer, sizeof(PageReadBuffer) >> 2);memset(PageReadBuffer, 0, sizeof(PageReadBuffer));FLASH_Read(Address, PageReadBuffer, sizeof(PageReadBuffer) >> 2);if(memcmp(PageReadBuffer, PageWriteBuffer, sizeof(PageReadBuffer)) == 0){printf("page[%04d] 0x%08X read & write %s \r\n", (int)((Address - FLASH_BASE) / FLASH_PAGE_SIZE), Address, "ok");}else{printf("page[%04d] 0x%08X read & write %s \r\n", (int)((Address - FLASH_BASE) / FLASH_PAGE_SIZE), Address, "failed");}}
}相关文章:
Air32 | 合宙Air001单片机内部FLASH读写示例
Air32 | 合宙Air001单片机内部FLASH读写示例 代码已经通过测试,开发环境KEIL-MDK 5.36。 测试代码 void FLASH_RdWrTest(void) {uint32_t Address;uint32_t PageReadBuffer[FLASH_PAGE_SIZE >> 2];uint32_t PageWriteBuffer[FLASH_PAGE_SIZE >> 2];mem…...
C语言基本语法-第一章
C 语言基本语法 语句 C 语言的代码由一行行语句(statement)组成。语句就是程序执行的一个操作命令。C 语言规定,语句必须使用分号结尾,除非有明确规定可以不写分号。 int x 1;上面就是一个变量声明语句,声明整数变…...
八、Spring 整合 MyBatis
文章目录 一、Spring 整合 MyBatis 的关键点二、Spring 整合 MyBatis 的步骤2.1 创建 Maven 项目,并导入相关依赖2.2 配置 Mybatis 部分2.3 配置 Spring 部分2.3 配置测试类 一、Spring 整合 MyBatis 的关键点 1、 将 Mybatis 的 DataSource (数据来源)的创建和管理…...
Flutter Flar动画实战
在Flare动面出现之前,Flare动画大体可以分为使用AnimationController控制的基础动画以及使用Hero的转场动画,如果遇到一些复杂的场景,使用这些动画方案实现起来还是有难度的。不过,随着Flutter开始支持Flare矢量动面,Flutter的动画开发也变得越来越简单。事实上,Flare动画…...
A stop job is running for xxxxxx
有时候服务器关机时,会有个进程卡在那里,使系统无法关闭 提示: A stop job is running for xxxxxx方法: 设置一个启动/停止的默认超时时间即可 vim /etc/systemd/system.conf DefaultTimeoutStartSec300s DefaultTimeoutStopSe…...
C++入门之stl六大组件--List源码深度剖析及模拟实现
文章目录 前言 一、List源码阅读 二、List常用接口模拟实现 1.定义一个list节点 2.实现一个迭代器 2.2const迭代器 3.定义一个链表,以及实现链表的常用接口 三、List和Vector 总结 前言 本文中出现的模拟实现经过本地vs测试无误,文件已上传gite…...
windows下以指定用户访问SMB服务器进行读写
一 概述 最近遇到一个问题,linux 的 smb服务器开启匿名访问,windows访问linux文件夹不需要用户名密码就可以进去使用,但是存在一个问题,ssh连接到linux 后修改的文件,在windows已smb方式下打开某个文件修改 是没有权限…...
数组根据属性去重
利用reduce函数处理,直接上代码! let data [{name:晓明,id:1},{name:德华,id:2},{name:德华,id:2},{name:晓明,id:1},] var obj {}; let arr data.reduce(function (item, next) {obj[next.id] ? : obj[next.id] true && item.push(next)…...
无损音乐从哪找?五个网站+免费下载,你确定不来看看?
hi,大家好我是技术苟,每天晚上22点准时上线为你带来实用黑科技!由于公众号改版,现在的公众号消息已经不再按照时间顺序排送了。因此小伙伴们就很容易错过精彩内容。喜欢黑科技的小伙伴,可以将黑科技百科公众号设为标星…...
2023华数杯数学建模B题思路模型论文分析
目录 一.2023华数杯数学建模最新思路:比赛开始后第一时间更新 更新查看文末名片 二.华数杯简介 三.往年华数杯赛题简介分析: 一.2023华数杯数学建模最新思路:比赛开始后第一时间更新 更新查看文末名片 二.华数杯简介 华数杯简介 国赛前…...
K8S系列文章之 使用Kind部署K8S 并发布服务
简单介绍 kind 即 Kubernetes In Docker,顾名思义,就是将 k8s 所需要的所有组件,全部部署在一个docker容器中,是一套开箱即用的 k8s 环境搭建方案。使用 kind 搭建的集群无法在生产中使用,但是如果你只是想在本地简单…...
从0到1开发go-tcp框架【4实战片— — 开发MMO之玩家聊天篇】
从0到1开发go-tcp框架【实战片— — 开发MMO】 MMO(MassiveMultiplayerOnlineGame):大型多人在线游戏(多人在线网游) 1 AOI兴趣点的算法 游戏中的坐标模型: 场景相关数值计算 ● 场景大小: 250…...
无重复字符的最长子串 LeetCode热题100
题目 给定一个字符串 s ,请你找出其中不含有重复字符的 最长连续子字符串 的长度。 思路 使用滑动窗口,记录窗口区间的长度大小,取最大值。用map存储滑动窗口内所有字符,字符作为key,每个字符的数量作为value。遍历…...
Docker搭建zookeeper
问题背景 前言 本文参考自:docker-compose快速搭建Zookeeper集群还有一种更加详细更加全面的部署方式:Docker之docker-compose一键部署Zookeeper集群,但笔者还未验证,先记录下来 搭建 安装docker-ce 此处不赘述 安装docker-co…...
LeetCode 热题 100 JavaScript--160. 相交链表
/*** Definition for singly-linked list.* function ListNode(val) {* this.val val;* this.next null;* }*//*** param {ListNode} headA* param {ListNode} headB* return {ListNode}*/// 1、暴力解法 var getIntersectionNode function(headA, headB) {var p1 …...
AWS S3 协议对接 minio/oss 等
使用亚马逊 S3 协议访问对象存储 [s3-API](https://docs.aws.amazon.com/zh_cn/AmazonS3/latest/API/API_Operations_Amazon_Simple_Storage_Service.html)- 兼容S3协议的对象存储有- minio- 似乎是完全兼容 [兼容文档](https://www.minio.org.cn/product/s3-compatibility.htm…...
手机便签内容不见了怎么恢复正常?
在日常生活和工作中,很多人都需要随手记录事情,例如家庭琐事、孩子相关的事情、指定时间需要完成的工作任务、会议安排等。当我们需要随时随地记录事情的时候,手机便签应用就是非常不多的选择,我们直接打开手机上的便签APP就可以新…...
【架构】Java 系统架构演进的思考
文章目录 1 前言2 单体应用架构3 垂直应用架构4 分布式架构5 SOA 架构6 微服务云架构7 总结 1 前言 随着移动互联的发展,网站、H5、移动端的应用规模也不断扩大,不管是应用的数量还是质量都得到了指数级的提升。开发者的数量与日俱增,应用的…...
Python爬虫——解析_jsonpath
jsonpath的安装 pip install jsonpathjsonpath的使用: obj json.load(open(json文件, r, encodingutf-8)) ret jsonpath.jsonpath(obj, jsonpath语法)json文件: { "store": {"book": [{ "category": "末世"…...
华为发布数字资产继承功能
在华为开发者大会2023(HDC.Together)上,华为常务董事、终端BG CEO、智能汽车解决方案BU CEO余承东正式发布了数字资产继承功能,HarmonyOS提供了安全便捷的数字资产继承路径。 在鸿蒙世界中,我们每个人在每台设备、应用…...
MongoDB学习和应用(高效的非关系型数据库)
一丶 MongoDB简介 对于社交类软件的功能,我们需要对它的功能特点进行分析: 数据量会随着用户数增大而增大读多写少价值较低非好友看不到其动态信息地理位置的查询… 针对以上特点进行分析各大存储工具: mysql:关系型数据库&am…...
python爬虫:Newspaper3k 的详细使用(好用的新闻网站文章抓取和解析的Python库)
更多内容请见: 爬虫和逆向教程-专栏介绍和目录 文章目录 一、Newspaper3k 概述1.1 Newspaper3k 介绍1.2 主要功能1.3 典型应用场景1.4 安装二、基本用法2.2 提取单篇文章的内容2.2 处理多篇文档三、高级选项3.1 自定义配置3.2 分析文章情感四、实战案例4.1 构建新闻摘要聚合器…...
Go 并发编程基础:通道(Channel)的使用
在 Go 中,Channel 是 Goroutine 之间通信的核心机制。它提供了一个线程安全的通信方式,用于在多个 Goroutine 之间传递数据,从而实现高效的并发编程。 本章将介绍 Channel 的基本概念、用法、缓冲、关闭机制以及 select 的使用。 一、Channel…...
MySQL JOIN 表过多的优化思路
当 MySQL 查询涉及大量表 JOIN 时,性能会显著下降。以下是优化思路和简易实现方法: 一、核心优化思路 减少 JOIN 数量 数据冗余:添加必要的冗余字段(如订单表直接存储用户名)合并表:将频繁关联的小表合并成…...
【WebSocket】SpringBoot项目中使用WebSocket
1. 导入坐标 如果springboot父工程没有加入websocket的起步依赖,添加它的坐标的时候需要带上版本号。 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId> </dep…...
动态规划-1035.不相交的线-力扣(LeetCode)
一、题目解析 光看题目要求和例图,感觉这题好麻烦,直线不能相交啊,每个数字只属于一条连线啊等等,但我们结合题目所给的信息和例图的内容,这不就是最长公共子序列吗?,我们把最长公共子序列连线起…...
无需布线的革命:电力载波技术赋能楼宇自控系统-亚川科技
无需布线的革命:电力载波技术赋能楼宇自控系统 在楼宇自动化领域,传统控制系统依赖复杂的专用通信线路,不仅施工成本高昂,后期维护和扩展也极为不便。电力载波技术(PLC)的突破性应用,彻底改变了…...
零基础在实践中学习网络安全-皮卡丘靶场(第十一期-目录遍历模块)
经过前面几期的内容我们学习了很多网络安全的知识,而这期内容就涉及到了前面的第六期-RCE模块,第七期-File inclusion模块,第八期-Unsafe Filedownload模块。 什么是"遍历"呢:对学过一些开发语言的朋友来说应该知道&…...
【笔记】结合 Conda任意创建和配置不同 Python 版本的双轨隔离的 Poetry 虚拟环境
如何结合 Conda 任意创建和配置不同 Python 版本的双轨隔离的Poetry 虚拟环境? 在 Python 开发中,为不同项目配置独立且适配的虚拟环境至关重要。结合 Conda 和 Poetry 工具,能高效创建不同 Python 版本的 Poetry 虚拟环境,接下来…...
Tableau for mac 驱动
Tableau 驱动程序安装指南 对于希望在 Mac OS 上使用 Tableau 进行数据分析的用户来说,确保正确安装相应的驱动程序至关重要。Tableau 支持多种数据库连接方式,并提供官方文档指导如何设置这些连接。 安装适用于 Mac 的 JDBC 或 ODBC 驱动程序 为了使…...
