一、Onchip Flash 特性

  1. 在STM32G070 的片内 Flash写入数据之前必须先对目标地址进行擦除后才能写入数据
  2. 数据写入:G070 Flash 写入数据必须保证8字节对齐,一次写入双字数据64bit 8Byte
  3. 数据读取:使用地址直接读取

二、移植FAL

1. 添加以下文件到工程

STM32G070 onchip移植FlashDB-LMLPHP

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 onchip移植FlashDB-LMLPHP
由于STM32G070 片上Flash 目标地址 只要写入过一次数据()就不可以再次写入数据,必须先擦除在写入,也许与FLASH的校验、纠错机制有关系

#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文件到工程

STM32G070 onchip移植FlashDB-LMLPHP

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移植

04-17 18:12