EasyFlash在GD32F303CC上面的移植

记录学习的过程,如果在GD32F303CC上面移植EasyFlash。关于EasyFlash的相关介绍和源码,请参考:https://gitee.com/Armink/EasyFlash 或者 https://github.com/armink/EasyFlash

主要记录移植过程中需要注意的点,移植还是比较简单的。基本就是填充几个宏定义和FLASH的操作函数即可。

一、下载源码、添加源码和头文件到工程中

这里就不具体展开了。作者给的文档有很详细,我就不复制搬运了,贴两张图片就好。

EasyFlash在GD32F303CC上面的移植_第1张图片

EasyFlash在GD32F303CC上面的移植_第2张图片

 二、根据芯片FLASH参数修改宏定义

 主要是修改ef_cfg.h文件。GD32F303CC用于手册里面的描述,可以知道一个页大小为2KB,支持编程写入16bit或者32bit。

EasyFlash在GD32F303CC上面的移植_第3张图片

基本修改的宏定义如下,具体含义参考注释。

/* The minimum size of flash erasure. May be a flash sector size. */
// 芯片FLASH的扇区大小或者说页大小 查询手册我使用芯片页大小为2K
#define EF_ERASE_MIN_SIZE       2048  /* @note you must define it for a value */  //2k
/* the flash write granularity, unit: bit
 * only support 1(nor flash)/ 8(stm32f4)/ 32(stm32f1) */
// FLASH支持的写入bit位数   查询手册 支持16bit和32bit 但是EasyFlash不支持 16bit
#define EF_WRITE_GRAN         32    /* @note you must define it for a value */
/* backup area start address */
// 使用内部FLASH来存储 存储的起始地址为 0x0803F000,即从252KB开始储存
#define EF_START_ADDR      0x0803F000       /* @note you must define it for a value */
/* ENV area size. It's at least one empty sector for GC. So it's definition must more then or equal 2 flash sector size. */
// 用来存储的空间大小 4KB  即从252~256KB
#define ENV_AREA_SIZE      (EF_ERASE_MIN_SIZE * 2)       /* @note you must define it for a value if you used ENV */
/* print debug information of flash */
// 宏定义开启串口调试输出
#define PRINT_DEBUG   1

三、接口移植

集中在ef_port.c文件下。主要需要完成,对FLASH读、写、擦除、加锁以及初始化等操作的接口。接口GD32固件库里面对FLASH操作的demo和EasyFlash提供的移植demo,依葫芦画瓢即可。

GD32固件库中关于FLASH操作demo(具体上GD32官网下载即可):

EasyFlash在GD32F303CC上面的移植_第4张图片

EasyFlash提供的移植demo:

EasyFlash在GD32F303CC上面的移植_第5张图片

最后附上自己修改的接口函数代码,注意的一点就是在RTOS和裸机上面采用的保护是不同的,RTOS直接利用了二值信号量,裸机直接关中断。

/* default environment variables set for user */
static const ef_env default_env_set[] = {
	      {"iap_need_copy_app","0"},
        {"iap_copy_app_size","0"},
        {"stop_in_bootloader","0"},
        {"device_id","1"},
        {"boot_times","0"},
};

EfErrCode ef_port_init(ef_env const **default_env, size_t *default_env_size)
{
    EfErrCode result = EF_NO_ERR;

    *default_env = default_env_set;
    *default_env_size = sizeof(default_env_set) / sizeof(default_env_set[0]);
		
	//如果使用了 RTOS 一般会在这里初始化信号量  rt_sem_init(&env_cache_lock, "env lock", 1, RT_IPC_FLAG_PRIO);
    return result;
}

EfErrCode ef_port_read(uint32_t addr, uint32_t *buf, size_t size)
{
    EfErrCode result = EF_NO_ERR;
    uint8_t *buf_8 = (uint8_t *)buf;
    size_t i;
    /* You can add your code under here. */
    /*copy from flash to ram */
    for (i = 0; i < size; i++, addr++, buf_8++)
    {
        *buf_8 = *(uint8_t *)addr;
    }
    return result;
}

EfErrCode ef_port_erase(uint32_t addr, size_t size)
{
    EfErrCode result = EF_NO_ERR;
    fmc_state_enum flash_status;
    size_t erase_pages, i;

    /* make sure the start address is a multiple of EF_ERASE_MIN_SIZE */
    EF_ASSERT(addr % EF_ERASE_MIN_SIZE == 0);

    /* You can add your code under here. */

    /* calculate pages */
    erase_pages = size / EF_ERASE_MIN_SIZE;
    if (size % EF_ERASE_MIN_SIZE != 0)
    {
        erase_pages++;
    }

    /* start erase */
    fmc_unlock();

    /* clear all pending flags */
    fmc_flag_clear(FMC_FLAG_BANK0_END);
    fmc_flag_clear(FMC_FLAG_BANK0_WPERR);
    fmc_flag_clear(FMC_FLAG_BANK0_PGERR);
    // 一个扇区一个扇区的擦除
    for (i = 0; i < erase_pages; i++)
    {
        flash_status = fmc_page_erase(addr + (EF_ERASE_MIN_SIZE * i));
        fmc_flag_clear(FMC_FLAG_BANK0_END);
        fmc_flag_clear(FMC_FLAG_BANK0_WPERR);
        fmc_flag_clear(FMC_FLAG_BANK0_PGERR);
        if (flash_status != FMC_READY)
        {
            result = EF_ERASE_ERR;
            break;
        }
    }
    fmc_lock();

    return result;
}

EfErrCode ef_port_write(uint32_t addr, const uint32_t *buf, size_t size)
{
    EfErrCode result = EF_NO_ERR;

    /* You can add your code under here. */
    size_t i;
    uint32_t read_data;

    /* unlock the flash program/erase controller */
    fmc_unlock();
    fmc_flag_clear(FMC_FLAG_BANK0_END);
    fmc_flag_clear(FMC_FLAG_BANK0_WPERR);
    fmc_flag_clear(FMC_FLAG_BANK0_PGERR);

    for (i = 0; i < size; i += 4, buf++, addr += 4)
    {
        /* write data */
        fmc_word_program(addr, *buf);
        read_data = *(uint32_t *)addr;

        fmc_flag_clear(FMC_FLAG_BANK0_END);
        fmc_flag_clear(FMC_FLAG_BANK0_WPERR);
        fmc_flag_clear(FMC_FLAG_BANK0_PGERR);

        /* check data */
        if (read_data != *buf)
        {
            result = EF_WRITE_ERR;
            break;
        }
    }
    /* lock the main FMC after the program operation */
    fmc_lock();

    return result;
}

void ef_port_env_lock(void)
{

    /* You can add your code under here. */
    // TODO:这里根据实际情况来判断
    // 如果是裸机就直接关中断
    __disable_irq();
    // 如果RTOS利用互斥量  rt_sem_take(&env_cache_lock, RT_WAITING_FOREVER);
}

void ef_port_env_unlock(void)
{

    /* You can add your code under here. */
    // TODO:这里根据实际情况来判断
    // 如果是裸机就直接开中断
    __enable_irq();
    // 如果RTOS利用互斥量    rt_sem_release(&env_cache_lock);
}



 

你可能感兴趣的:(嵌入式开源软件包,单片机,嵌入式系统,EasyFlash)