GD32上FAL Flash分区驱动移植及Easyflash移植说明
程序员文章站
2022-06-11 16:55:40
...
GD32上FAL Flash分区驱动移植及Easyflash移植说明
移植前提
下载源码
移植过程
加入以下文件及文件夹到工程目录和工程
将demo目录下的接口文件做下修改
修改配置文件fal_cfg.h
#ifndef _FAL_CFG_H_
#define _FAL_CFG_H_
#define FAL_PART_HAS_TABLE_CFG
#define NOR_FLASH_DEV_NAME "norflash0"
/* ===================== Flash device Configuration ========================= */
extern const struct fal_flash_dev gd32f4_onchip_flash;
extern struct fal_flash_dev nor_flash0;
/* flash device table */
#define FAL_FLASH_DEV_TABLE \
{ \
&gd32f4_onchip_flash, \
&nor_flash0, \
}
/* ====================== Partition Configuration ========================== */
#ifdef FAL_PART_HAS_TABLE_CFG
/* partition table */
#define FAL_PART_TABLE \
{ \
{FAL_PART_MAGIC_WORD, "app", "gd32_onchip", 0, 704*1024, 0}, \
{FAL_PART_MAGIC_WORD, "param", "gd32_onchip", 704*1024, 64*1024, 0}, \
{FAL_PART_MAGIC_WORD, "easyflash", NOR_FLASH_DEV_NAME, 0, 1024*1024, 0}, \
{FAL_PART_MAGIC_WORD, "download", NOR_FLASH_DEV_NAME, 1024*1024, 1024*1024, 0}, \
}
#endif /* FAL_PART_HAS_TABLE_CFG */
#endif /* _FAL_CFG_H_ */
复制demo中文件修改内部flash驱动接口
更名为:fal_flash_gd32f2_port.c(这个操作依据自己芯片平台非必须)
主要完善以下接口:
- 内部FLASH的读取,写入,擦除操作
- 内部FLASH的属性配置
GD32的FLASH操作接口已改为HAL方式,HAL的移植方式参考我的博客https://editor.csdn.net/md/?articleId=106135522
#include <fal.h>
#include <gd32f4xx.h>
#include "flash.h"
/* base address of the flash sectors */
/*bank1*/
#define ADDR_FLASH_SECTOR_0 ((uint32_t)0x08000000) /* Base address of Sector 0, 16 K bytes */
#define ADDR_FLASH_SECTOR_1 ((uint32_t)16*1024+ADDR_FLASH_SECTOR_0) /* Base address of Sector 1, 16 K bytes */
#define ADDR_FLASH_SECTOR_2 ((uint32_t)16*1024+ADDR_FLASH_SECTOR_1) /* Base address of Sector 2, 16 K bytes */
#define ADDR_FLASH_SECTOR_3 ((uint32_t)16*1024+ADDR_FLASH_SECTOR_2) /* Base address of Sector 3, 16 K bytes */
#define ADDR_FLASH_SECTOR_4 ((uint32_t)16*1024+ADDR_FLASH_SECTOR_3) /* Base address of Sector 4, 64 K bytes */
#define ADDR_FLASH_SECTOR_5 ((uint32_t)64*1024+ADDR_FLASH_SECTOR_4) /* Base address of Sector 5, 128 K bytes */
#define ADDR_FLASH_SECTOR_6 ((uint32_t)128*1024+ADDR_FLASH_SECTOR_5) /* Base address of Sector 6, 128 K bytes */
#define ADDR_FLASH_SECTOR_7 ((uint32_t)128*1024+ADDR_FLASH_SECTOR_6) /* Base address of Sector 7, 128 K bytes */
#define ADDR_FLASH_SECTOR_8 ((uint32_t)128*1024+ADDR_FLASH_SECTOR_7) /* Base address of Sector 8, 128 K bytes */
#define ADDR_FLASH_SECTOR_9 ((uint32_t)128*1024+ADDR_FLASH_SECTOR_8) /* Base address of Sector 9, 128 K bytes */
#define ADDR_FLASH_SECTOR_10 ((uint32_t)128*1024+ADDR_FLASH_SECTOR_9) /* Base address of Sector 10, 128 K bytes */
#define ADDR_FLASH_SECTOR_11 ((uint32_t)128*1024+ADDR_FLASH_SECTOR_10)/* Base address of Sector 11, 128 K bytes */
/*bank2*/
#define ADDR_FLASH_SECTOR_12 ((uint32_t)128*1024+ADDR_FLASH_SECTOR_11)/* Base address of Sector 12, 16 K bytes */
#define ADDR_FLASH_SECTOR_13 ((uint32_t)16*1024+ADDR_FLASH_SECTOR_12) /* Base address of Sector 13, 16 K bytes */
#define ADDR_FLASH_SECTOR_14 ((uint32_t)16*1024+ADDR_FLASH_SECTOR_13) /* Base address of Sector 14, 16 K bytes */
#define ADDR_FLASH_SECTOR_15 ((uint32_t)16*1024+ADDR_FLASH_SECTOR_14) /* Base address of Sector 15, 16 K bytes */
#define ADDR_FLASH_SECTOR_16 ((uint32_t)16*1024+ADDR_FLASH_SECTOR_15) /* Base address of Sector 16, 64 K bytes */
#define ADDR_FLASH_SECTOR_17 ((uint32_t)64*1024+ADDR_FLASH_SECTOR_16) /* Base address of Sector 17, 128 K bytes */
#define ADDR_FLASH_SECTOR_18 ((uint32_t)128*1024+ADDR_FLASH_SECTOR_17)/* Base address of Sector 18, 128 K bytes */
#define ADDR_FLASH_SECTOR_19 ((uint32_t)128*1024+ADDR_FLASH_SECTOR_18)/* Base address of Sector 19, 128 K bytes */
#define ADDR_FLASH_SECTOR_20 ((uint32_t)128*1024+ADDR_FLASH_SECTOR_19)/* Base address of Sector 20, 128 K bytes */
#define ADDR_FLASH_SECTOR_21 ((uint32_t)128*1024+ADDR_FLASH_SECTOR_20)/* Base address of Sector 21, 128 K bytes */
#define ADDR_FLASH_SECTOR_22 ((uint32_t)128*1024+ADDR_FLASH_SECTOR_21)/* Base address of Sector 22, 128 K bytes */
#define ADDR_FLASH_SECTOR_23 ((uint32_t)128*1024+ADDR_FLASH_SECTOR_22)/* Base address of Sector 23, 128 K bytes */
#define ADDR_FLASH_SECTOR_24 ((uint32_t)128*1024+ADDR_FLASH_SECTOR_23)/* Base address of Sector 24, 256 K bytes */
#define ADDR_FLASH_SECTOR_25 ((uint32_t)256*1024+ADDR_FLASH_SECTOR_24)/* Base address of Sector 25, 256 K bytes */
#define ADDR_FLASH_SECTOR_26 ((uint32_t)256*1024+ADDR_FLASH_SECTOR_15)/* Base address of Sector 26, 256 K bytes */
#define ADDR_FLASH_SECTOR_27 ((uint32_t)256*1024+ADDR_FLASH_SECTOR_16)/* Base address of Sector 27, 256 K bytes */
#define ADDR_FLASH_ECTOR_MAX ((uint32_t)256*1024+ADDR_FLASH_SECTOR_17)/*flash最大地址*/
/**
* Get the sector of a given address
*
* @param address flash address
*
* @return The sector of a given address
*/
static uint32_t gd32_get_sector(uint32_t address)
{
uint32_t sector = 0;
if ((address < ADDR_FLASH_SECTOR_1) && (address >= ADDR_FLASH_SECTOR_0))
{
sector = FLASH_SECTOR_0;
}
else if ((address < ADDR_FLASH_SECTOR_2) && (address >= ADDR_FLASH_SECTOR_1))
{
sector = FLASH_SECTOR_1;
}
else if ((address < ADDR_FLASH_SECTOR_3) && (address >= ADDR_FLASH_SECTOR_2))
{
sector = FLASH_SECTOR_2;
}
else if ((address < ADDR_FLASH_SECTOR_4) && (address >= ADDR_FLASH_SECTOR_3))
{
sector = FLASH_SECTOR_3;
}
else if ((address < ADDR_FLASH_SECTOR_5) && (address >= ADDR_FLASH_SECTOR_4))
{
sector = FLASH_SECTOR_4;
}
else if ((address < ADDR_FLASH_SECTOR_6) && (address >= ADDR_FLASH_SECTOR_5))
{
sector = FLASH_SECTOR_5;
}
else if ((address < ADDR_FLASH_SECTOR_7) && (address >= ADDR_FLASH_SECTOR_6))
{
sector = FLASH_SECTOR_6;
}
else if ((address < ADDR_FLASH_SECTOR_8) && (address >= ADDR_FLASH_SECTOR_7))
{
sector = FLASH_SECTOR_7;
}
else if ((address < ADDR_FLASH_SECTOR_9) && (address >= ADDR_FLASH_SECTOR_8))
{
sector = FLASH_SECTOR_8;
}
else if ((address < ADDR_FLASH_SECTOR_10) && (address >= ADDR_FLASH_SECTOR_9))
{
sector = FLASH_SECTOR_9;
}
else if ((address < ADDR_FLASH_SECTOR_11) && (address >= ADDR_FLASH_SECTOR_10))
{
sector = FLASH_SECTOR_10;
}
else if ((address < ADDR_FLASH_SECTOR_12) && (address >= ADDR_FLASH_SECTOR_11))
{
sector = FLASH_SECTOR_11;
}
else if ((address < ADDR_FLASH_SECTOR_13) && (address >= ADDR_FLASH_SECTOR_12))
{
sector = FLASH_SECTOR_12;
}
else if ((address < ADDR_FLASH_SECTOR_14) && (address >= ADDR_FLASH_SECTOR_13))
{
sector = FLASH_SECTOR_13;
}
else if ((address < ADDR_FLASH_SECTOR_15) && (address >= ADDR_FLASH_SECTOR_14))
{
sector = FLASH_SECTOR_14;
}
else if ((address < ADDR_FLASH_SECTOR_16) && (address >= ADDR_FLASH_SECTOR_15))
{
sector = FLASH_SECTOR_15;
}
else if ((address < ADDR_FLASH_SECTOR_17) && (address >= ADDR_FLASH_SECTOR_16))
{
sector = FLASH_SECTOR_16;
}
else if ((address < ADDR_FLASH_SECTOR_18) && (address >= ADDR_FLASH_SECTOR_17))
{
sector = FLASH_SECTOR_17;
}
else if ((address < ADDR_FLASH_SECTOR_19) && (address >= ADDR_FLASH_SECTOR_18))
{
sector = FLASH_SECTOR_18;
}
else if ((address < ADDR_FLASH_SECTOR_20) && (address >= ADDR_FLASH_SECTOR_19))
{
sector = FLASH_SECTOR_19;
}
else if ((address < ADDR_FLASH_SECTOR_21) && (address >= ADDR_FLASH_SECTOR_20))
{
sector = FLASH_SECTOR_20;
}
else if ((address < ADDR_FLASH_SECTOR_22) && (address >= ADDR_FLASH_SECTOR_21))
{
sector = FLASH_SECTOR_21;
}
else if ((address < ADDR_FLASH_SECTOR_23) && (address >= ADDR_FLASH_SECTOR_22))
{
sector = FLASH_SECTOR_22;
}
else if ((address < ADDR_FLASH_SECTOR_24) && (address >= ADDR_FLASH_SECTOR_23))
{
sector = FLASH_SECTOR_23;
}
else if ((address < ADDR_FLASH_SECTOR_25) && (address >= ADDR_FLASH_SECTOR_24))
{
sector = FLASH_SECTOR_24;
}
else if ((address < ADDR_FLASH_SECTOR_26) && (address >= ADDR_FLASH_SECTOR_25))
{
sector = FLASH_SECTOR_25;
}
else if ((address < ADDR_FLASH_SECTOR_27) && (address >= ADDR_FLASH_SECTOR_26))
{
sector = FLASH_SECTOR_26;
}
else
{
sector = FLASH_SECTOR_27;
}
return sector;
}
/**
* Get the sector size
*
* @param sector sector
*
* @return sector size
*/
static uint32_t gd32_get_sector_size(uint32_t sector) {
assert(IS_FLASH_SECTOR(sector));
switch (sector) {
case FLASH_SECTOR_0:
case FLASH_SECTOR_1:
case FLASH_SECTOR_2:
case FLASH_SECTOR_3: return 16 * 1024;
case FLASH_SECTOR_4: return 64 * 1024;
case FLASH_SECTOR_5:
case FLASH_SECTOR_6:
case FLASH_SECTOR_7:
case FLASH_SECTOR_8:
case FLASH_SECTOR_9:
case FLASH_SECTOR_10:
case FLASH_SECTOR_11: return 128 * 1024;
case FLASH_SECTOR_12:
case FLASH_SECTOR_13:
case FLASH_SECTOR_14:
case FLASH_SECTOR_15: return 16 * 1024;
case FLASH_SECTOR_16: return 64 * 1024;
case FLASH_SECTOR_17:
case FLASH_SECTOR_18:
case FLASH_SECTOR_19:
case FLASH_SECTOR_20:
case FLASH_SECTOR_21:
case FLASH_SECTOR_22:
case FLASH_SECTOR_23: return 128 * 1024;
case FLASH_SECTOR_24:
case FLASH_SECTOR_25:
case FLASH_SECTOR_26:
case FLASH_SECTOR_27: return 256 * 1024;
default : return 256 * 1024;
}
}
static int init(void)
{
/* do nothing now */
}
static int read(long offset, uint8_t *buf, size_t size)
{
size_t i;
uint32_t addr = gd32f4_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 read_data;
uint32_t addr = gd32f4_onchip_flash.addr + offset;
HAL_FLASH_Unlock();
for (i = 0; i < size; i++, buf++, addr++)
{
/* write data */
FLASH_ProgramByte(addr, *buf);
read_data = *(uint8_t *) addr;
/* check data */
if (read_data != *buf)
{
return -1;
}
}
HAL_FLASH_Lock();
return size;
}
/**
******************************************************************
* @brief 获取当前扇区所属bank
* @param [in]扇区号
* @retval flash bank号
* @author aron566
* @version V1.0
* @date 2020-6-3
******************************************************************
*/
static uint32_t Get_SectorBank(uint32_t Sector)
{
if(Sector < ADDR_FLASH_SECTOR_12)
{
return FLASH_BANK_1;
}
else
{
return FLASH_BANK_2;
}
}
static int erase(long offset, size_t size)
{
HAL_StatusTypeDef flash_status;
size_t erased_size = 0;
uint32_t cur_erase_sector;
uint32_t addr = gd32f4_onchip_flash.addr + offset;
FLASH_EraseInitTypeDef config;
uint32_t ERROR = 0;
config.NbSectors = 1;
config.TypeErase = FLASH_TYPEERASE_SECTORS;
config.VoltageRange = FLASH_VOLTAGE_RANGE_4;
/* start erase */
HAL_FLASH_Unlock();
/* it will stop when erased size is greater than setting size */
while (erased_size < size)
{
config.Sector = gd32_get_sector(addr + erased_size);
config.Banks = Get_SectorBank(config.Sector);
flash_status = HAL_FLASHEx_Erase(&config, &ERROR);
if (flash_status != HAL_OK)
{
return -1;
}
erased_size += gd32_get_sector_size(cur_erase_sector);
}
HAL_FLASH_Lock();
return size;
}
const struct fal_flash_dev gd32f4_onchip_flash =
{
.name = "gd32_onchip",
.addr = ADDR_FLASH_SECTOR_0,
.len = ADDR_FLASH_ECTOR_MAX - ADDR_FLASH_SECTOR_0,
.blk_size = 256*1024,
.ops = {init, read, write, erase},
.write_gran = 8
};
外部SPI Flash的接口配置
由于操作flash的接口是由sfud万能驱动接口做的,所以参考sfud的移植,当然不移植就需要自己实现外部SPI Flash的读取/写入/擦除驱动。fal_flash_sfud_port.c
修改如下:
#include <fal.h>
#include <sfud.h>
#define FAL_USING_SFUD_PORT
#ifdef FAL_USING_SFUD_PORT
#ifdef RT_USING_SFUD
#include <spi_flash_sfud.h>
#endif
#ifndef FAL_USING_NOR_FLASH_DEV_NAME
#define FAL_USING_NOR_FLASH_DEV_NAME "norflash0"
#endif
static int init(void);
static int read(long offset, uint8_t *buf, size_t size);
static int write(long offset, const uint8_t *buf, size_t size);
static int erase(long offset, size_t size);
static sfud_flash_t sfud_dev = NULL;
struct fal_flash_dev nor_flash0 =
{
.name = FAL_USING_NOR_FLASH_DEV_NAME,
.addr = 0,
.len = 8 * 1024 * 1024,
.blk_size = 4096,
.ops = {init, read, write, erase},
.write_gran = 1
};
static int init(void)
{
#ifdef RT_USING_SFUD
/* RT-Thread RTOS platform */
sfud_dev = rt_sfud_flash_find_by_dev_name(FAL_USING_NOR_FLASH_DEV_NAME);
#else
/* bare metal platform */
sfud_dev = sfud_get_device(SFUD_GD25Q16B_DEVICE_INDEX);
#endif
if (NULL == sfud_dev)
{
return -1;
}
/* update the flash chip information */
nor_flash0.blk_size = sfud_dev->chip.erase_gran;
nor_flash0.len = sfud_dev->chip.capacity;
return 0;
}
static int read(long offset, uint8_t *buf, size_t size)
{
assert(sfud_dev);
assert(sfud_dev->init_ok);
sfud_read(sfud_dev, nor_flash0.addr + offset, size, buf);
return size;
}
static int write(long offset, const uint8_t *buf, size_t size)
{
assert(sfud_dev);
assert(sfud_dev->init_ok);
if (sfud_write(sfud_dev, nor_flash0.addr + offset, size, buf) != SFUD_SUCCESS)
{
return -1;
}
return size;
}
static int erase(long offset, size_t size)
{
assert(sfud_dev);
assert(sfud_dev->init_ok);
if (sfud_erase(sfud_dev, nor_flash0.addr + offset, size) != SFUD_SUCCESS)
{
return -1;
}
return size;
}
#endif /* FAL_USING_SFUD_PORT */
测试代码
必须的初始化
#include "fal.h"
int main(void)
{
fal_init();
}
读写擦除
接口都在fal.h中
懒得写了。。。。。。
Easyflash的移植
目前最新版本的Easyflash V5.X
或者最新更名的FlashDB
底层调用接口都是FAL,所以实现了FAL移植,Easyflash和FlashDB都无需较大更改,直接加入源码到工程目录即可使用。