欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

GD32上FAL Flash分区驱动移植及Easyflash移植说明

程序员文章站 2022-06-11 16:55:40
...

移植前提

下载源码

前往下载

移植过程

加入以下文件及文件夹到工程目录和工程

GD32上FAL Flash分区驱动移植及Easyflash移植说明

将demo目录下的接口文件做下修改

GD32上FAL Flash分区驱动移植及Easyflash移植说明

修改配置文件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都无需较大更改,直接加入源码到工程目录即可使用。

相关标签: 移植应用