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");
		}
	}
}
相关推荐
普中科技11 小时前
【普中STM32F1xx开发攻略--标准库版】-- 第 45 章 FSMC-外扩 SRAM 实验
stm32·单片机·嵌入式硬件·fsmc·普中科技·外扩sram·is62wv51216
xiaoyuchidayuma13 小时前
永磁同步发电机的线电压和直流母线电压的关系
嵌入式硬件
潜创微科技13 小时前
4K60 over IP 方案简介
网络·嵌入式硬件·网络协议·tcp/ip·音视频
rit843249913 小时前
基于C#的USB HID设备读取测试软件
嵌入式硬件
三佛科技-1873661339714 小时前
FT32F103C8AT7兼容GD32F103C8T632 位通用微控制器MCU,替代性分析
单片机·嵌入式硬件
iCxhust14 小时前
8086汇编 word ptr
汇编·单片机·嵌入式硬件·微机原理·8088单板机
嵌入式ZYXC14 小时前
第3篇:《面试题:I2C为什么要加上拉电阻?阻值怎么选?》
stm32·单片机·嵌入式硬件·面试·职场和发展
leo__52015 小时前
C# 虚拟键盘(软键盘)实现
单片机·c#·计算机外设
你疯了抱抱我15 小时前
【STM32】使用 STM32CubeMX 生成项目,LED测试;上位机:STM32F411CEU6
stm32·单片机·嵌入式硬件