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");
		}
	}
}
相关推荐
国科安芯8 小时前
高速CANFD收发器ASM1042在割草机器人轮毂电机通信系统中的适配性研究
网络·单片机·嵌入式硬件·性能优化·机器人·硬件工程
CC呢8 小时前
基于单片机智能路灯控制
单片机·嵌入式硬件·智能路灯
DDUU__8 小时前
STM32低功耗模式
stm32·单片机·嵌入式硬件
小莞尔10 小时前
【51单片机】【protues仿真】基于51单片机宠物投食器系统
c语言·stm32·单片机·嵌入式硬件·51单片机·proteus
逼子格10 小时前
【Protues仿真】基于AT89C52单片机的数码管驱动事例
单片机·嵌入式硬件·硬件工程·硬件工程师·protues·数码管·电路仿真
風清掦10 小时前
零基础玩转STM32:深入理解ARM Cortex-M内核与寄存器编程
stm32·单片机·嵌入式硬件·mcu·物联网
芯岭技术14 小时前
PY32F003国产单片机、外设丰富、高性价比的国产替代方案
单片机·嵌入式硬件
QQ52862112416 小时前
单片机GD32F230芯片解密解析及专业操作建议
单片机·嵌入式硬件
一枚小小程序员哈17 小时前
基于stm32的智能建筑能源管理系统/基于单片机的能源管理系统
stm32·单片机·能源
物联网牛七七17 小时前
51和stm32的点灯区别
stm32·单片机·51单片机