GD32外部SPI Flash下载算法制作

GD32外部SPI Flash下载算法制作

前言

最近做一个项目用到GD32E230这款MCU,原厂配套有非常全的SDK例程和Datasheet,驱动库与STM32的标准库很类似,只要有STM32的使用经验,很快就可以上手GD32的开发。

项目中外挂一个4MB的W25Q32 SPI-Flash存放字体资源数据,在前期调试功能阶段,需要频繁更改资源数据,改完再重新烧录数据到SPI-Flash,一般使用专用的烧录工具飞线到flash引脚上,用上位机软件烧录资源bin,如果有多台样机需要测试,那么则需要每台样机都要飞线,且要拆掉外壳,显然很麻烦。

本文介绍如何制作一个烧写外部Flash的FLM下载算法,借助J-Link SWD就可以方便地更新Flash资源文件。

本文完整工程下载:GD32E230_W25Q32_FLM

Keil官方指导文档:《Programming External Flash used with STM32 Devices》

创建下载算法工程

安装Keil后,可以在其安装目录下找到FLM下载算法的模板工程:

Keil_v5\ARM\PACK\ARM\CMSIS\5.6.0\Device\_Template_Flash
FLM模板工程

算法工程创建步骤如下:

  1. 拷贝该模板工程到自己的工作目录下,注意此工程源文件是只读属性,我们需要右键选择文件去掉只读属性;

  2. 我这里将工程名重命名为GD32E230_W25QXX,同时将CMSIS和GD32E23x的驱动库拷贝到工程目录下:
    驱动库添加

  3. 实现spi驱动,spi_flash驱动,为了调试方便能够使用打印一些调试信息,也实现串口驱动和printf打印,这里存放在Drivers目录下:

.Drivers
├── bsp_spi.c      #SPI驱动
├── bsp_spi.h
├── bsp_uart.c     #UART驱动
├── bsp_uart.h
├── spi_flash.c    #FALSH驱动
└── spi_flash.h
  1. 将源文件添加到工程,组织关系如下:
    源文件组织关系
  2. 修改工程Device配置,选择为GD32E230C8:
    修改Device
  3. FLM算法名改为GD32E230_W25QXX:
    FLM重命名

算法实现

J-Flash/Keil工具会将FLM load到MCU的RAM中,然后使用其接口来操作Flash设备,FLM的代码必须是位置无关代码,其链接脚本为Target.lin
FLM原理框图
FLM下载算法,主要有以下几个函数需要实现,
需要实现的函数
其中,如果不做数据正确性的校验,BlankCheck、Verify可以暂时不实现,其他几个重要的函数实现如下:

Flash操作函数实现

  1. 系统时钟、Flash器件的初始化:
int Init (unsigned long adr, unsigned long clk, unsigned long fnc)
{
    int id = 0;

    SystemInit();            /* 系统出初始化  */
    spi0_init();             /* SPI外设初始化 */
    uart0_init();            /* UART外设初始化 */
    id = spi_flash_read_id();
    if (id != W25Q32) {
        log_printf("[SPI-Flash] ERR:spi flash not exist!\r\n");
    }
    log_printf("[SPI-Flash] spi flash id=0x%x\r\n", id);

    return (0);
}
  1. Flash整片擦除:
int EraseChip (void)
{
    spi_flash_erase_chip();
    return (0);
}

  1. Flash按扇区擦除:
int EraseSector (unsigned long adr)
{
    spi_flash_erase_sector(adr);
    return (0);
}
  1. Flash编程,将对应长度的数据写到对应的Flash地址上:
int ProgramPage (unsigned long adr, unsigned long sz, unsigned char *buf)
{
    spi_flash_write_no_check(adr, buf, (uint16_t)sz);
    return (0);
}

FlashDev参数调整

FlashDev.c中,FlashDevice结构体定义了Flash的描述参数,需要根据实际情况调整其参数:

struct FlashDevice const FlashDevice  =  {
   FLASH_DRV_VERS,             // Driver Version, do not modify!
   "GD32E230_W25QXX",          // Device Name
   EXTSPI,                     // Device Type
   0x00000000,                 // Device Start Address
   0x00400000,                 // Device Size in Bytes (重要:需要根据实际器件容量进行调整)
   4096,                       // Programming Page Size
   0,                          // Reserved, must be 0
   0xFF,                       // Initial Content of Erased Memory
   1000,                       // Program Page Timeout 100 mSec
   3000,                       // Erase Sector Timeout 3000 mSec

   // Specify Size and Address of Sectors
   0x001000, 0x000000,         // Sector Size  4kB (8 Sectors)
   SECTOR_END
};

编译

完成上述工作后,直接编译,会在工程根目录生成GD32E230_W25QXX.FLM文件。

但是此时的FLM还有问题,因为SPI、UART、Clock驱动底层使用了GD32E23x的标准驱动库,函数层级较多,代码量已超过8KB的RAM容量,使用时会报如下错误:
RAM不足
将配置工程优化等级为-Oz image size,观察map文件结果,Code size小于8KB:
map文件Code size

J-Flash配置

项目需要借助FLM烧写板载的Flash,因此我选用J-Flash作为烧写上位机。

FLM要支持J-Flash,要经过一些配置:

  1. 安装J-Link软件,会在J-Link安装目录下找到:C:\Program Files (x86)\SEGGER\JLink\JLinkDevices.xml,我安装的J-Link版本为V6.98b,如果读者是安装的其他版本J-Link,方法也是类似。

  2. 为了方便,拷贝GD32E230_W25QXX.FLM文件到SEGGER\JLink\Devices\目录下。

  3. 打开JLinkDevices.xml文件,文末添加如下代码段:

  <!--                                    -->
  <!-- Analog Devices (Cortex-M23 devices)-->
  <!--                                    -->
  <Device>
    <ChipInfo Vendor="GD" Name="GD32E230_W25Q32"  Core="JLINK_CORE_CORTEX_M23" WorkRAMAddr="0x20000000" WorkRAMSize="0x2000"/>
    <FlashBankInfo Name="SPI FLASH" BaseAddr="0x00000000" MaxSize="0x00400000" Loader="Devices/GD32E230_W25QXX.FLM" LoaderType="FLASH_ALGO_TYPE_CMSIS" />
  </Device>

  1. 打开JFlash.exe,按下图找到我们新加入的GD32E230_W25Q32设备:
    选择设备
  2. [Target]->[Connect]成功连接上设备:
    连接设备

烧录体验

本章介绍烧录资源bin文件步骤:

  1. [File]->[Open data file]打开资源bin文件:
    打开资源bin
  2. [Target]->[Mannua Programming]->[Erase Sectors]擦除扇区:
    擦除扇区
  3. [Target]->[Mannua Programming]->[Program]开始烧写:
    开始烧写
    至此,本文介绍如何制作部一个烧写外部Flash的FLM文件完毕,本文虽然是针对GD32E230这款MCU,但是可以类比和搬移到其他MCU,方法都是相通的。
  • 3
    点赞
  • 57
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
根据提供的引用内容,我可以给你介绍一下GD32F350芯片中的SPI DMA FLASHGD32F350芯片是一款基于ARM Cortex-M3内核的微控制器,它具有SPI(串行外设接口)和DMA(直接内存访问)功能。SPI是一种用于在芯片之间进行通信的串行通信协议,而DMA是一种用于在外设和内存之间传输数据的技术。 在GD32F350芯片中,可以使用SPI DMA来实现对FLASH存储器的读写操作。通过使用SPI DMA,可以减轻CPU的工作负担,提高数据传输的效率。 以下是一个使用SPI DMA进行FLASH读取的示例代码: ```c #include "gd32f3x0.h" #define FLASH_BASE_ADDR 0x08000000 void spi_dma_flash_read(uint32_t addr, uint8_t *data, uint32_t size) { /* 配置SPI DMA传输 */ dma_single_data_mode_init(DMA0, DMA_CH2, (uint32_t)&SPI_DATA(SPI1), (uint32_t)data, DMA_DIR_PERIPHERAL_TO_MEMORY); dma_channel_enable(DMA0, DMA_CH2); /* 配置SPI数据长度 */ spi_i2s_data_length_config(SPI1, size); /* 配置SPI地址 */ spi_i2s_data_transmit(SPI1, addr); /* 等待SPI DMA传输完成 */ while (RESET == dma_flag_get(DMA0, DMA_CH2, DMA_FLAG_FTF)) { } /* 关闭SPI DMA传输 */ dma_channel_disable(DMA0, DMA_CH2); } int main(void) { uint8_t data[256]; /* 初始化SPI和DMA */ spi_dma_flash_init(); dma_config(); /* 从FLASH读取数据 */ spi_dma_flash_read(FLASH_BASE_ADDR, data, sizeof(data)); /* 处理读取到的数据 */ while (1) { } } ``` 在这个示例代码中,`spi_dma_flash_read`函数用于从FLASH中读取数据。首先,配置SPI DMA传输,然后设置SPI数据长度和地址,最后等待SPI DMA传输完成。读取到的数据存储在`data`数组中,你可以根据需要进行进一步处理。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值