一、Onchip Flash 特性
- 在STM32G070 的片内 Flash写入数据之前必须先对目标地址进行擦除后才能写入数据
- 数据写入:G070 Flash 写入数据必须保证8字节对齐,一次写入双字数据64bit 8Byte
- 数据读取:使用地址直接读取
二、移植FAL
1. 添加以下文件到工程
2. 修改fal_cfg.h 中分区表
片上Flash需要注意 分区地址避开程序的存储地址否则将导致程序不能正常运行
#define FAL_PART_TABLE \
{ \
{FAL_PART_MAGIC_WORD, "fdb_tsdb", "stm32_onchip", 100*1024, 4*1024, 0}, \
{FAL_PART_MAGIC_WORD, "fdb_kvdb", "stm32_onchip", 104*1024, 4*1024, 0}, \
}
3. 添加fal_flash_stm32g0_port.c
由于STM32G070 片上Flash 目标地址 只要写入过一次数据(包含0xFF)就不可以再次写入数据,必须先擦除在写入,也许与FLASH的校验、纠错机制有关系
所以在write函数内,写入数据之前需要先读取即将写入目标地址的存储值与写入值是否相同,若是相同就不必再次写入,否则会写入失败
#define PAGE_SIZE 2048
static int init(void)
{
return 1;
}
static int read(long offset, uint8_t *buf, size_t size)
{
size_t i;
uint32_t addr = stm32_onchip_flash.addr + offset;
for (i = 0; i < size; i++, addr++, buf++)
{
*buf = *(uint8_t *)addr;
}
return size;
}
static int write(long offset, const uint8_t *buf, size_t size)
{
size_t i;
uint32_t addr = stm32_onchip_flash.addr + offset;
__ALIGN_BEGIN uint64_t write_data __ALIGN_END;
__ALIGN_BEGIN uint64_t read_data __ALIGN_END;
HAL_FLASH_Unlock();
for (i = 0; i < size; i+=8)
{
read_data = *(uint64_t *)(addr+i);
if (read_data != (uint64_t)(*((uint64_t *)((uint32_t)buf + i))))
{
HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, (uint32_t)(uint64_t*)(addr+i),(uint64_t)(*((uint64_t *)((uint32_t)buf + i))));
read_data = *(uint64_t *)(addr+i);
if (read_data != (uint64_t)(*((uint64_t *)((uint32_t)buf + i))))
{
HAL_FLASH_Lock();
return -1;
}
else
{
feed_dog();//FLash操作可能非常耗时,如果有看门狗需要喂狗,以下代码由用户实现
}
}
}
HAL_FLASH_Lock();
return size;
}
static int erase(long offset, size_t size)
{
HAL_StatusTypeDef flash_status;
FLASH_EraseInitTypeDef EraseInitStruct;
uint32_t HeadErasePage = offset/FLASH_PAGE_SIZE,PAGEError = 0;
size_t erase_pages = size / FLASH_PAGE_SIZE;
if(size % FLASH_PAGE_SIZE != 0) erase_pages++;
EraseInitStruct.Banks = FLASH_BANK_1;
EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES;
EraseInitStruct.NbPages = 1; //一次擦出一个扇区, 以执行一次喂狗,防止超时
HAL_FLASH_Unlock();
for (size_t i = 0; i < erase_pages; i++)
{
EraseInitStruct.Page = HeadErasePage + i;
flash_status = HAL_FLASHEx_Erase(&EraseInitStruct, &PAGEError);
if (flash_status != HAL_OK)
{
HAL_FLASH_Lock();
return -1;
}
else
{
feed_dog();
}
}
HAL_FLASH_Lock();
return size;
}
const struct fal_flash_dev stm32_onchip_flash =
{
.name = "stm32_onchip",//Flash名称
.addr = 0x08000000,//Flash起始地址
.len = 128*1024,//Flash的大小
.blk_size = 2*1024,//一次性可擦除的Flash大小
.ops = {init, read, write, erase},//Flash访问驱动
.write_gran = 64 //最小写入粒度64位按照8字节对齐
};
三、移植FlashDB
1. 添加FlashDB文件到工程
2. 修改fdb_cfg.h头文件中关于写入粒度的定义
/* the flash write granularity, unit: bit
* only support 1(nor flash)/ 8(stm32f2/f4)/ 32(stm32f1) */
#define FDB_WRITE_GRAN 64
3.参考sample案列使用
以下地址包含API说明
FlashDB仓库
SFUD移植