stm32f103使用hal库函数读写内部flash
文章目录
- 一、写内部flash
- 二、读内部flash
- 三、代码
本次使用RT-Thread studio编写,使用为5.02完整版,直接编写函数使用hal库函数读写内部flash。
一、写内部flash
在写数据的逻辑上是比较简单的,因为hal库将底层已经进行了封装,步骤就是解锁flash->擦除要写入的扇区->清除CR寄存器的PER位(这个本来应该在擦除里面的,基础库就是这样做的,但HAL库里面没写)->写入数据->上锁flash。
代码:
void Flash_Write(uint32_t TypeProgram, uint32_t Address, uint64_t (*Data), uint32_t len)
{
HAL_FLASH_Unlock();
FLASH_PageErase(Address); //擦除这个扇区
CLEAR_BIT(FLASH->CR, FLASH_CR_PER); //清除CR寄存器的PER位,此操作应该在FLASH_PageErase()中完成!
//但是HAL库里面并没有做,应该是HAL库bug!
if (TypeProgram==TYPEPROGRAM_CHAR) {
for (int var = 0; var < len/2; var++) {
uint8_t data1=(uint8_t)*Data;
uint8_t data2=(uint8_t)*(Data+1);
uint64_t datar = data2<<8|data1;
HAL_FLASH_Program(TYPEPROGRAM_HALFWORD, Address,datar);
Address+=2;
Data+=2;
}
} else {
for (int var = 0; var < len; var++) {
HAL_FLASH_Program(TypeProgram, Address, *Data);
Address+=(1<<TypeProgram);
Data+=1;
}
}
HAL_FLASH_Lock();
}
这里面我想要8位,16位,32位,64位的数据都能写入,所以定义了一个写入类型的参数,由于库函数至少是按半字处理的,所以8位需要特殊处理,而且要进行兼容,传入的数据就只能是64位的,这点比较麻烦,就是说传入的数组必须是64位,不然写入的结果会不对,已经测试过。
二、读内部flash
读内部就比较简单了,只需要按照类型返回不同指针强转和不同地址增加就行了,但是同样传入的指针是64位,使用数据时还的强转为自己想要的类型:
void Flash_Read(uint32_t TypeProgram, uint32_t Address, uint64_t (*Data), uint32_t len)
{
int32_t i=0;
if (TypeProgram==TYPEPROGRAM_CHAR) {
for (i = 0; i < len; i++, Address+=1, Data++)
{
*Data = *(uint8_t *) Address;
}
}else if (TypeProgram==TYPEPROGRAM_HALFWORD) {
for (i = 0; i < len; i++, Address+=2, Data++)
{
*Data = *(uint16_t *) Address;
}
}else if (TypeProgram==TYPEPROGRAM_WORD) {
for (i = 0; i < len; i++, Address+=4, Data++)
{
*Data = *(uint32_t *) Address;
}
}else if (TypeProgram==TYPEPROGRAM_DOUBLEWORD) {
for (i = 0; i < len; i++, Address+=8, Data++)
{
*Data = *(uint64_t *) Address;
}
}
}
三、代码
.c文件:
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2023-12-07 Windows the first version
*/
#include "flash.h"
extern void FLASH_PageErase(uint32_t PageAddress);
extern HAL_StatusTypeDef FLASH_WaitForLastOperation(uint32_t Timeout);
//#define TYPEPROGRAM_CHAR 0x00U /*!<Program a char (8-bit) at a specified address.*/
//#define TYPEPROGRAM_HALFWORD 0x01U /*!<Program a half-word (16-bit) at a specified address.*/
//#define TYPEPROGRAM_WORD 0x02U /*!<Program a word (32-bit) at a specified address.*/
//#define TYPEPROGRAM_DOUBLEWORD 0x03U /*!<Program a double word (64-bit) at a specified address*/
void Flash_Write(uint32_t TypeProgram, uint32_t Address, uint64_t (*Data), uint32_t len)
{
HAL_FLASH_Unlock();
FLASH_PageErase(Address); //擦除这个扇区
CLEAR_BIT(FLASH->CR, FLASH_CR_PER); //清除CR寄存器的PER位,此操作应该在FLASH_PageErase()中完成!
//但是HAL库里面并没有做,应该是HAL库bug!
if (TypeProgram==TYPEPROGRAM_CHAR) {
for (int var = 0; var < len/2; var++) {
uint8_t data1=(uint8_t)*Data;
uint8_t data2=(uint8_t)*(Data+1);
uint64_t datar = data2<<8|data1;
HAL_FLASH_Program(TYPEPROGRAM_HALFWORD, Address,datar);
Address+=2;
Data+=2;
}
} else {
for (int var = 0; var < len; var++) {
HAL_FLASH_Program(TypeProgram, Address, *Data);
Address+=(1<<TypeProgram);
Data+=1;
}
}
HAL_FLASH_Lock();
}
void Flash_Read(uint32_t TypeProgram, uint32_t Address, uint64_t (*Data), uint32_t len)
{
int32_t i=0;
if (TypeProgram==TYPEPROGRAM_CHAR) {
for (i = 0; i < len; i++, Address+=1, Data++)
{
*Data = *(uint8_t *) Address;
}
}else if (TypeProgram==TYPEPROGRAM_HALFWORD) {
for (i = 0; i < len; i++, Address+=2, Data++)
{
*Data = *(uint16_t *) Address;
}
}else if (TypeProgram==TYPEPROGRAM_WORD) {
for (i = 0; i < len; i++, Address+=4, Data++)
{
*Data = *(uint32_t *) Address;
}
}else if (TypeProgram==TYPEPROGRAM_DOUBLEWORD) {
for (i = 0; i < len; i++, Address+=8, Data++)
{
*Data = *(uint64_t *) Address;
}
}
}
.h文件
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2023-12-07 Windows the first version
*/
#ifndef APPLICATIONS_FLASH_H_
#define APPLICATIONS_FLASH_H_
#include "main.h"
#include "stm32f1xx_hal_flash.h"
#define TYPEPROGRAM_CHAR 0x00U /*!<Program a char (8-bit) at a specified address.*/
#define TYPEPROGRAM_HALFWORD 0x01U /*!<Program a half-word (16-bit) at a specified address.*/
#define TYPEPROGRAM_WORD 0x02U /*!<Program a word (32-bit) at a specified address.*/
#define TYPEPROGRAM_DOUBLEWORD 0x03U /*!<Program a double word (64-bit) at a specified address*/
void Flash_Write(uint32_t TypeProgram, uint32_t Address, uint64_t (*Data), uint32_t len);
void Flash_Read(uint32_t TypeProgram, uint32_t Address, uint64_t (*Data), uint32_t len);
#endif /* APPLICATIONS_FLASH_H_ */
main函数测试:
uint64_t flash_buf[] = {2,3,31,45};
Flash_Write(TYPEPROGRAM_HALFWORD,FLASH_DATA_ADDR,flash_buf,4);
uint64_t data_buf[4];
rt_kprintf("FLASH_DATA_ADDR:%x\n",(FLASH_DATA_ADDR));
Flash_Read(TYPEPROGRAM_HALFWORD,FLASH_DATA_ADDR,data_buf,4);
rt_kprintf("flash_buf:%d\n",(uint16_t)data_buf[0]);
rt_kprintf("flash_buf:%d\n",(uint16_t)data_buf[1]);
rt_kprintf("flash_buf:%d\n",(uint16_t)data_buf[2]);
rt_kprintf("flash_buf:%d\n",(uint16_t)data_buf[3]);
data_buf[0]=0x123456789abcdef0;
rt_kprintf("(uint8_t)data_buf[0]:%x\n",(uint8_t)data_buf[0]);
rt_kprintf("(uint16_t)data_buf[0]:%x\n",(uint16_t)data_buf[0]);
rt_kprintf("(uint32_t)data_buf[0]:%x\n",(uint32_t)data_buf[0]);
rt_kprintf("(uint64_t)data_buf[0]:%x\n",(uint64_t)data_buf[0]);
rt_kprintf("(uint64_t)data_buf[0]:%x\n",(uint32_t)(data_buf[0]>>32));
测试结果: