Air32 | 合宙Air001单片机内部FLASH读写示例

news2024/11/23 22:12:08

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++;				//页地址增1
			secoff = 0;				//偏移位置为0
			Buffer += 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");
		}
	}
}

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

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

相关文章

仓储物流业如何实现精细化工时成本管理,提升出库效率?

面对日益复杂的物流需求&#xff0c;以及不断上涨的人力成本。仓储物流企业想要在市场竞争中脱颖而出&#xff0c;不仅需要提升出库效率&#xff0c;满足消费者次日达甚至当日达的高要求&#xff0c;更需要控制人力成本&#xff0c;保证企业持续盈利的能力。盖雅新推出的 「劳…

恒运资本:史上最强暑期档!总票房突破147亿,前三都是国产片!

暑期档电影又爆了&#xff01; 就在刚刚曩昔的周末&#xff0c;在《封神第一部》《巨齿鲨2&#xff1a;深渊》《火热》等电影的大卖&#xff0c;以及《背注一掷》点映及预售的加持下&#xff0c;短短两天的大盘票房就到达10亿元。 其间&#xff0c;据猫眼专业版数据&#xff0…

Windows下安装Kafka(图文记录详细步骤)

Windows下安装Kafka Kafka简介一、Kafka安装前提安装Kafka之前&#xff0c;需要安装JDK、Zookeeper、Scala。1.1、JDK安装&#xff08;version&#xff1a;1.8&#xff09;1.1.1、JDK官网下载1.1.2、JDK网盘下载1.1.3、JDK安装 1.2、Zookeeper安装1.2.1、Zookeeper官网下载1.2.…

Java方法重写

目录 1.什么是方法重写 2.方法重写的规则 3.重写与重载的区别 1.什么是方法重写 重写&#xff08;override&#xff0c;也称为覆盖&#xff09;&#xff1a;在子类中对父类中允许访问的方法的实现过程进行重新编写&#xff0c;子类中方法的名称、返回值类型、参数列表与父类…

Redis安装以及配置隧道连接(centOs)

目录 1.centOs安装Redis 2. Redis 启动和停⽌ 3. 操作Redis 2.Xshell配置隧道 1.centOs安装Redis #使⽤yum安装Redis yum -y install redis 2. Redis 启动和停⽌ #查看是否启动 ps -ef|grep redis#启动redis: redis-server /etc/redis.conf &#停⽌Redis redis-cli sh…

【web逆向】全报文加密流量的去加密测试方案

aHR0cHM6Ly90ZGx6LmNjYi5jb20vIy9sb2dpbg 国密混合 WEB JS逆向篇 先看报文&#xff1a;请求和响应都是全加密&#xff0c;这种情况就不像参数加密可以方便全文搜索定位加密代码&#xff0c;但因为前端必须解密响应的密文&#xff0c;因此万能的方法就是搜索拦截器&#xff0c…

B站电商分析,如何发现近期热门商品及优质视频带货达人?

哔哩哔哩是我们熟知的以二次元为基调的视频内容生产平台&#xff0c;具有浓厚而专注的二次元社区氛围&#xff0c;随着b站的迅猛发展&#xff0c;b站由原先的二次元市场逐渐扩张到电子竞技、美妆、生活、纪录片等多个领域。而b站的营收主要来自平台广告变现&#xff0c;内容付费…

python爬虫2:requests库-原理

python爬虫2&#xff1a;requests库-原理 前言 ​ python实现网络爬虫非常简单&#xff0c;只需要掌握一定的基础知识和一定的库使用技巧即可。本系列目标旨在梳理相关知识点&#xff0c;方便以后复习。 目录结构 文章目录 python爬虫2&#xff1a;requests库-原理1. 概述2. re…

JSP实训项目设计报告—MVC简易购物商城

JSP实训项目设计报告—MVC简易购物商城 文章目录 JSP实训项目设计报告—MVC简易购物商城设计目的设计要求设计思路系统要求单点登录模块商品展示模块购物车展示模块 概要设计Model层View层Controller层 详细设计Model层View层登录界面系统主界面 Controller层 系统运行效果项目…

基于Orangepi 3 lts 的云台相机

利用orangepi 3 lts 和arduino nano 制作了一个云台相机&#xff0c;可用于室内监控。 硬件&#xff1a; orangepi 3 ,arduino nano ,usb相机&#xff0c;180度舵机两个 WeChat_20230806213004 软件&#xff1a; 整体采用mqtt进行消息的中转。 相机采用python 利用opencv…

PAT(Advanced Level)刷题指南 —— 第四弹

一、1104 Sum of Number Segments 1. 问题描述 2. Sample Input 4 0.1 0.2 0.3 0.43. Sample Output 5.004. 题解 思路:打表,比如4个数,第一个数出现1*(4) = 4次,第二个数出现2*(4 - 1) 

以太网协议学习笔记

以太网接口电路主要由MAC&#xff08;Media Access Control&#xff09;控制器和物理层接口PHY两大部分构成。 PHY在发送数据时&#xff0c;接收MAC发过来的数据&#xff0c;把并行的数据转化为串行流数据&#xff0c;按照物理层的编码规则把数据编码转化为模拟信号发送出去&am…

【Opencv入门到项目实战】(一):Opencv安装及图像基本操作

文章目录 0.Opencv介绍及环境配置1.图像读取1.1 彩色图像读取1.2 灰色图像读取 2.视频读取3.ROI读取3.1 图形切片处理3.2 提取颜色通道 4.图像填充5.数值运算与图像融合5.1 加法运算5.2 图像融合 6. 总结 0.Opencv介绍及环境配置 OpenCV是一个强大的计算机视觉库&#xff0c;它…

Dockerfile部署golang

使用go镜像打包&#xff0c;运行在容器内 redis和mysql用外部的 项目目录结构 w1go项目&#xff1a; Dockerfile # 这种方式是docker项目加上 本地的mysql和redis环境 # go打包的容器 FROM golang:alpine AS builder# 为我们镜像设置一些必要的环境变量 ENV GO111MODULEon …

Maven-生命周期及命令

关于本文 ✍写作原因 之前在学校学习的时候&#xff0c;编写代码使用的项目都是单体架构&#xff0c;导入开源框架依赖时只需要在pom.xml里面添加依赖&#xff0c;点一下reload按钮即可解决大部分需求&#xff1b;但是在公司使用了dubbo微服务架构之后发现只知道使用reload不足…

编织代码的魔法:掌握Python字符串常用函数的奥秘!

在Python的编程世界里&#xff0c;字符串是你与计算机对话的语言&#xff0c;掌握字符串常用函数就像拥有了一把强大的魔杖&#xff0c;可以编织出令人惊叹的代码魔法。无论你是初学者还是有经验的开发者&#xff0c;本篇博客将带你深入探索Python字符串常用函数&#xff0c;揭…

(学习笔记-进程管理)线程

在早期的操作系统都是以进程为独立运行的基本单位&#xff0c;直到后面&#xff0c;计算机科学家们提出了更小的能独立运行的基本单位&#xff1a;线程 为什么使用线程? 举个例子&#xff0c;假设要编写一个视频播放软件&#xff0c;那么软件功能的核心模块有三个&#xff1a…

机器学习笔记:李宏毅ChatGPT课程1:刨析ChatGPT

ChatGPT——Chat Generative Pre-trained Transformer 1 文字接龙 每次输出一个概率分布&#xff0c;根据概率sample一个答案 ——>因为是根据概率采样&#xff0c;所以ChatGPT每次的答案是不一样的&#xff08;把生成式学习拆分成多个分类问题&#xff09;将生成的答案加到…

【Linux】总结1-命令工具

文章目录 基础指令shell命令以及运行原理Linux权限粘滞位工具 基础指令 ls、pwd、touch、mkdir、netstat、cp、mv、cd、tar、zip、unzip、grep、pstack、ps、rm、cat、more、less、head、tail、find、ulimit -a、clear、whoami、man touch&#xff1a;创建文件&#xff0c;也包…

怎么合并多个视频?简单视频合并方法分享

合并多个视频可以将它们组合成一个更长的视频&#xff0c;这对于需要播放多个短视频的情况非常有用。此外&#xff0c;合并视频还可以使视频编辑过程更加高效&#xff0c;因为不必将多个独立的视频文件分别处理。最后&#xff0c;合并视频可以减少文件数量&#xff0c;从而使整…