简介
IAR 在MCU 开发中是个经常使用的IDE,在IAR 环境下如何将编译器编译好的程序下载到MCU 中运行。整个下载过程主要有以下四个步骤。
准备:连接目标硬件与计算机,C-SPY 读取.flash 和.board 文件信息获取flash参数及flashloader信息。
启动:进入调试模式,C-SPY 初始化通信并建立连接,读取.board 文件选定 Flash Loader,将其下载到目标设备 RAM。
下载:C - SPY 划分应用程序映像数据到 RAM 缓冲区,执行 FlashErase 函数擦除目标 Flash 区域,再用 FlashWrite 函数将数据逐页写入 Flash,每写一页检查一次。
完成:校验 Flash 数据,若无误可退出调试,程序存于 Flash 可独立运行,也可继续调试分析。
我们基于上述四个步骤使用GD32F427开发板环境来解析flash 的下载过程。
准备及启动过程
以本地的GD32F427 的工程为示例,在deubug菜单的Download选项下可以配置对应的。board 配置文件。“$TOOLKIT_DIR$\config\flashloader\GD\FlashGD32F427xK.board”
默认情况下,使用的.board 文件为IAR 安装目录下的\config\flashloader\GD\FlashGD32F427xK.board 文件,对应的文件内容如下。
<?xml version="1.0" encoding="iso-8859-1"?> <flash_board> <pass> <loader>$TOOLKIT_DIR$/config/flashloader/GD/FlashGD32F4xxxK.flash</loader> <range>CODE 0x08000000 0x082FFFFF</range> </pass> <pass> <loader>$TOOLKIT_DIR$/config/flashloader/GD/FlashGD32F4xxx_OTP.flash</loader> <range>CODE 0x1FFF7800 0x1FFF7A0F</range> </pass> </flash_board>
上述xml 文件描述了芯片内部的有两块flah,分别为FlashGD32F4xxxK.flash 和 FlashGD32F4xxx_OTP.flash 和两块flash 的大小信息。
每块flash 有各自的配置的xml 文件来描述,对应的FlashGD32F4xxxK.flash 文件信息如下。
<?xml version="1.0" encoding="iso-8859-1"?> <flash_device> <exe>$TOOLKIT_DIR$/config/flashloader/GD/FlashGD32F4xxx.out</exe> <page>4</page> <block>4 0x4000</block> <block>1 0x10000</block> <block>7 0x20000</block> <block>4 0x4000</block> <block>1 0x10000</block> <block>7 0x20000</block> <block>4 0x40000</block> <flash_base>0x08000000</flash_base> <macro>$TOOLKIT_DIR$/config/flashloader/GD/FlashGD32F4xx.mac</macro> <online>1</online> <aggregate>1</aggregate> </flash_device>
FlashGD32F4xxx_OTP.flash 文件信息如下。
<?xml version="1.0" encoding="iso-8859-1"?> <flash_device> <exe>$TOOLKIT_DIR$/config/flashloader/GD/FlashGD32F4xxx_OTP.out</exe> <page>1</page> <block>1 0x210</block> <flash_base>0x1FFF7800</flash_base> <macro>$TOOLKIT_DIR$/config/flashloader/GD/FlashGD32F4xx.mac</macro> <aggregate>1</aggregate> </flash_device>
上述配置文件描述了flash 最小编程page 大小,块信息以及要使用的flash 下载程序,FlashGD32F4xxx.out/FlashGD32F4xxx_OTP.out 以及C-SPY调用的flashloader初始化配置宏函数。
FlashGD32F4xx.mac文件内容如下:
__var RCU_CFG0; __var RCU_CTL; __var RCU_INT; __var FWDGT_PSC; __var FWDGT_RLD; __var FMC_WS; __var FMC_CTL; execUserFlashInit() { RCU_CTL = __readMemory32(0x40023800, "Memory"); RCU_CFG0 = __readMemory32(0x40023808, "Memory"); RCU_INT = __readMemory32(0x4002380C, "Memory"); __writeMemory32(0x00000000, 0x4002380C, "Memory"); // Disable interrupts __writeMemory32(RCU_CTL | 0x1, 0x40023800, "Memory"); // Enable IRC16M __writeMemory32(0x00000000, 0x40023808, "Memory"); // Switch system clock to IRC16M // Check if hardware watchdog is enabled if(!(0x20 & __readMemory32(0x40023C14,"Memory"))) { FWDGT_PSC = __readMemory32(0x40003004, "Memory"); FWDGT_RLD = __readMemory32(0x40003008, "Memory"); // Unlock FWDGT registers __writeMemory32(0x5555, 0x40003000,"Memory"); // Prescaler if (FWDGT_PSC != 0x7) { __writeMemory32(0x7, 0x40003004, "Memory"); } // Reload if (FWDGT_RLD != 0xFFF) { __writeMemory32(0xFFF, 0x40003008, "Memory"); } // Reload FWDGT __writeMemory32(0xAAAA, 0x40003000,"Memory"); } // Keep FMC register values FMC_WS = __readMemory32(0x40023C00,"Memory"); FMC_CTL = __readMemory32(0x40023C10,"Memory") & 0xFFFF0000; // Unlock FMC_CTL register if(FMC_CTL & (1<<31)) { __writeMemory32(0x45670123, 0x40023C04, "Memory"); // FMC_KEY = FMC_KEY1; __writeMemory32(0xCDEF89AB, 0x40023C04, "Memory"); // FMC_KEY = FMC_KEY2; } __writeMemory32(0x00000000, 0x40023C00, "Memory"); // Flash 0 wait state __writeMemory32(0x00000000, 0x40023C10, "Memory"); // Clear Interrupt Enable __writeMemory32(0x000001D3, 0x40023C0C, "Memory"); // Clear Status Flags } execUserFlashExit() { // Restore registers modified earlier __writeMemory32(FMC_WS, 0x40023C00, "Memory"); __writeMemory32(FMC_CTL, 0x40023C10, "Memory"); if(!(0x20 & __readMemory32(0x40023C14, "Memory"))) { __writeMemory32(0x5555, 0x40003000, "Memory"); if (FWDGT_PSC != 0x7) { __writeMemory32(IWDG_PR, 0x40003004, "Memory"); } if (FWDGT_RLD != 0xFFF) { __writeMemory32(FWDGT_RLD, 0x40003008, "Memory"); } __writeMemory32(0xAAAA, 0x40003000, "Memory"); } __writeMemory32(RCU_CFG0, 0x40023808, "Memory"); __writeMemory32(RCU_CTL, 0x40023800, "Memory"); __writeMemory32(RCU_INT, 0x4002380C, "Memory"); }
上述宏函数会完成flashloader 程序FlashGD32F4xxx.out 运行前的初始化工作,关闭中断,配置时钟为内部的RC16M时钟,并解锁flash 编程,为flashloader程序的装载运行提供运行时环境。
下载过程
初始化flashloader 运行时环境后,C-SPY 会将FlashGD32F4xxx.out 加载到内存中运行,并调用其中的erase/write接口完成flash 的下载更新。
完成阶段
下载完成后会校验flash,并设置PC指针至Reset 地址运行更新后的程序。
IAR 开启如下配置校验下载的flash 镜像
对应的debug 窗口log 信息如下:
如果不开启上述的校验配置,只会有下载完成的日志信息。