最近做一个项目用到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
算法工程创建步骤如下:
拷贝该模板工程到自己的工作目录下,注意此工程源文件是只读属性,我们需要右键选择文件去掉只读属性;
实现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
J-Flash/Keil工具会将FLM load到MCU的RAM中,然后使用其接口来操作Flash设备,FLM的代码必须是位置无关代码,其链接脚本为Target.lin
。
FLM下载算法,主要有以下几个函数需要实现,
其中,如果不做数据正确性的校验,BlankCheck、Verify可以暂时不实现,其他几个重要的函数实现如下:
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);
}
int EraseChip (void)
{
spi_flash_erase_chip();
return (0);
}
int EraseSector (unsigned long adr)
{
spi_flash_erase_sector(adr);
return (0);
}
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容量,使用时会报如下错误:
将配置工程优化等级为-Oz image size
,观察map文件结果,Code size小于8KB:
项目需要借助FLM烧写板载的Flash,因此我选用J-Flash作为烧写上位机。
FLM要支持J-Flash,要经过一些配置:
安装J-Link软件,会在J-Link安装目录下找到:C:\Program Files (x86)\SEGGER\JLink\JLinkDevices.xml
,我安装的J-Link版本为V6.98b,如果读者是安装的其他版本J-Link,方法也是类似。
为了方便,拷贝GD32E230_W25QXX.FLM文件到SEGGER\JLink\Devices\
目录下。
打开JLinkDevices.xml
文件,文末添加如下代码段:
<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>
本章介绍烧录资源bin文件步骤: