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

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


代码已经通过测试,开发环境KEIL-MDK 5.36。

测试代码

c 复制代码
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");
		}
	}
}

头文件

c 复制代码
/**
 * @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

源文件

c 复制代码
/**
 * @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");
		}
	}
}
相关推荐
hairenjing11235 小时前
使用 Mac 数据恢复从 iPhoto 图库中恢复照片
windows·stm32·嵌入式硬件·macos·word
模拟IC攻城狮6 小时前
华为海思招聘-芯片与器件设计工程师-模拟芯片方向- 机试题-真题套题题目——共8套(每套四十题)
嵌入式硬件·华为·硬件架构·芯片
IT B业生7 小时前
51单片机教程(六)- LED流水灯
单片机·嵌入式硬件·51单片机
一枝小雨7 小时前
51单片机学习心得2(基于STC89C52):串口通信(UART)
单片机·嵌入式硬件·51单片机
IT B业生8 小时前
51单片机教程(一)- 开发环境搭建
单片机·嵌入式硬件·51单片机
海绵波波10710 小时前
Webserver(4.8)UDP、广播、组播
单片机·网络协议·udp
好想有猫猫10 小时前
【51单片机】串口通信原理 + 使用
c语言·单片机·嵌入式硬件·51单片机·1024程序员节
云卓科技10 小时前
无人车之路径规划篇
人工智能·嵌入式硬件·算法·自动驾驶
stm 学习ing11 小时前
C语言 循环高级
c语言·开发语言·单片机·嵌入式硬件·算法·嵌入式实时数据库
w微信1501350781212 小时前
小华一级 代理商 HC32F005C6PA-TSSOP20 HC32F005系列
c语言·arm开发·单片机·嵌入式硬件