本篇文章来自极术社区与兆易创新组织的GD32F427开发板评测活动,更多开发板试用活动请关注极术社区网站。作者:羁傲不驯ぃ
什么是ISP?
ISP是In-System Program的缩写,即在系统编程。通常我们开发使用仿真器来下载和调试程序,当固件稳定需要转生产,此时仿真器就不如ISP烧录。
当同一块板卡上有多个MCU,或者MCU作为协处理器时,可以通过主处理器来为MCU烧录程序,此时就是ISP大显身手的地方了。
ISP怎么用?
ISP需要MCU本身支持,例如我们当前的GD32F427,就支持有三种启动方式,我们通常下载时固件会存放再Flash中:我们可以通过复位后的 BOOT管脚的电平状态来选择当前的启动方式:1是正常启动 2是从系统存储空间启动 3是从外部SRAM中启动。
GD手册上这样写:
嵌入式的Bootloader存放在系统存储空间,用于对FLASH存储器进行重新编程。Bootloader可 以通过USART0(PA9 and PA10)、USART2(PB10 and PB11 or PC10 and PC11)或USB FS(PA9、PA11和PA12)和外界交互。
那么我们就可以通过,控制MCU的复位+BOOT0 来控制启动方式。
首先我们需要准备一个MCU的bin文件,我们可以通过Keil设置来生产bin文件。
再每次执行完 build 和 rebuild 之后都会生成 bin 文件。
MCU型号判断
由于使用ISP烧录不如JTAG或DAP,我们不清楚当前MCU型号信息,所以我们需要先从MCU中读取MCU的唯一ID,ST和GD当前都支持读取该ID,我们此处查看GD32F427的ID:
GD32用户手册中有:
烧录步骤
我们参考项目:
stm32flash / Wiki / Home (sourceforge.net)
main.c · master · stm32flash / Stm32flash · GitLab
这个项目为STM32使用UART和IIC等工具来烧录的软件,我们参考这个项目,实现我们自己的GD32 的ISP烧录。
此处只贴出部分代码:
// 1. 读取芯片唯一ID
read_gd_mcu_pid()
// 2. 拉住BOOT0 复位MCU
int mcu_isp_init(){
printf(" ==========> [isp init]. \n");
MCU_ISP_NRST_L;
usleep(100000);
MCU_ISP_BOOT0_H;
usleep(100000);
MCU_ISP_NRST_H;
usleep(100000);
MCU_ISP_NRST_L;
usleep(100000);
MCU_ISP_BOOT0_H;
usleep(100000);
MCU_ISP_NRST_H;
usleep(100000);
return 0;
}
// 3. 通过串口向MCU烧录bin文件
bootsize = file_size(bootname);
buffer = malloc(bootsize);
memset(buffer, 0, bootsize);
file_read(bootname, buffer, bootsize);
writememory_2mcu(ADDR_MCU_BOOT, buffer, bootsize);
// 4. 释放BOOT0 复位MCU, MCU正常运行烧录完成
int mcu_isp_close(){
MCU_ISP_BOOT0_L;
usleep(100000);
MCU_ISP_NRST_L;
usleep(100000);
MCU_ISP_NRST_H;
usleep(100000);
printf(" <========== [isp close]. \n");
return 0;
}
读取芯片ID由主机发出,由于串口不具备调试能力,所以需要MCU程序提供支持,我们此处只发送了读取MCU ID的指令,ID的读取和返回由MCU来完成
GD32F303 :0x46455633
GD32F470 :0x4e455a30
小结
使用ISP烧录可以帮助我们更加深入的了解芯片启动过程和原理,有兴趣研究的小伙伴可以参考上述参考程序实现自己的烧录软件。
比如:正点原子的FlyMCU就是这样的一个软件。