第五十五章 串口IAP实验
IAP,即在应用编程,通俗地说法就是“程序升级”。产品阶段设计完成后,在脱离实验室的调试环境下,如果想对产品做功能升级或BUG修复会十分麻烦,如果硬件支持,在出厂时预留一套升级固件的流程,就可以很好解决这个问题,IAP技术就是为此而生的。在之前的FLASH模拟EEPROM实验里面,我们学习了STM32H562的FLASH自编程,本章我们将结合FLASH自编程的知识,通过STM32H562的串口实现一个简单的IAP功能。
本章分为如下几个小节:
55.1 IAP简介
55.2 硬件设计
55.3 程序设计
55.4 下载验证
55.1 IAP简介
IAP(In Application Programming)即在应用编程。在讲解STM32的启动模式时我们已经知道STM32可以通过设置MSP的方式从不同的地址启动:包括Flash地址、RAM地址等,在默认方式下,我们的嵌入式程序是以连续二进制的方式烧录到STM32的可寻址Flash区域上的。如果我们用的Flash容量大到可以存储两个或多个的完整程序,在保证每个程序完整的情况下,上电后的程序通过修改MSP的方式,就可以保证一个单片机上有多个有功能差异的嵌入式软件,这就是我们要讲解的IAP的设计思路。
IAP是用户自己的程序在运行过程中对User Flash的部分区域进行烧写,目的是为了在产品发布后可以方便地通过预留的通信口对产品中的固件程序进行更 新升级。通常实现IAP功能时,即用户程序运行中作自身的更新操作,需要在设计固件程序时编写两个项目代码,第一个项目程序不执行正常的功能操作,而只是通过某种通信方式(如USB、USART)接收程序或数据,执行对第二部分代码的更新;第二个项目代码才是真正的功能代码。这两部分项目代码都同时烧录在User Flash中,当芯片上电后,首先是第一个项目代码开始运行,它做如下操作:
1)检查是否需要对第二部分代码进行更新
2)如果不需要更新则转到4)
3)执行更新操作
4)跳转到第二部分代码执行
第一部分代码必须通过其它手段,如JTAG或ISP烧入;第二部分代码可以使用第一部分代码IAP功能烧入,也可以和第一部分代码一起烧入,以后需要程序更新时再通过第一部分IAP代码更新。
我们将第一个项目代码称之为Bootloader程序,第二个项目代码称之为APP程序,他们存放在STM32H562 FLASH的不同地址范围,一般从最低地址区开始存放Bootloader,紧跟其后的就是APP程序(注意,如果FLASH容量足够,是可以设计很多APP程序的,本章我们只讨论一个APP程序的情况)。这样我们就是要实现2个程序:Bootloader和APP。
STM32H5的APP程序不仅可以放到FLASH里面运行,也可以放到SRAM里面运行,本章,我们将制作两个APP,一个用于FLASH运行,一个用于内部SRAM运行。
我们先来看看STM32H5正常的程序运行流程(为了方便说明IAP过程,我们先仅考虑代码全部存放在内部FLASH的情况),如图55.1.1所示:

图55.1.1 STM32H562正常运行流程图
STM32H5的内部闪存(FLASH)地址起始于0X0800 0000,一般情况下,程序文件就从此地址开始写入。此外STM32H562是基于Cortex-M33内核的微控制器,其内部通过一张“中断向量表”来响应中断,程序启动后,将首先从“中断向量表”取出复位中断向量执行复位中断程序完成启动,而这张“中断向量表”的起始地址是0x08000004,当中断来临,STM32H562的内部硬件机制亦会自动将PC指针定位到“中断向量表”处,并根据中断源取出对应的中断向量执行中断服务程序。
在图55.1.1中,STM32H562在复位后,先从0X08000004地址取出复位中断向量的地址,并跳转到复位中断服务程序,如图标号①所示;在复位中断服务程序执行完之后,会跳转到我们的main函数,如图标号②所示;而我们的main函数一般都是一个死循环,在main函数执行过程中,如果收到中断请求(发生了中断),此时STM32H562强制将PC指针指回中断向量表处,如图标号③所示;然后,根据中断源进入相应的中断服务程序,如图标号④所示;在执行完中断服务程序以后,程序再次返回main函数执行,如图标号⑤所示。
当加入IAP程序之后,程序运行流程如图55.1.2所示:

图55.1.2 加入IAP之后程序运行流程图
在图55.1.2所示流程中,STM32H562复位后,还是从0X08000004地址取出复位中断向量的地址,并跳转到复位中断服务程序,在运行完复位中断服务程序之后跳转到IAP的main函数,如图标号①所示,此部分同图56.1.1一样;在执行完IAP以后(即将新的APP代码写入STM32H562的FLASH,灰底部分。新程序的复位中断向量起始地址为0X08000004+N+M),跳转至新写入程序的复位向量表,取出新程序的复位中断向量的地址,并跳转执行新程序的复位中断服务程序,随后跳转至新程序的main函数,如图标号②和③所示,同样main函数为一个死循环,并且注意到此时STM32H562的FLASH,在不同位置上,共有两个中断向量表。
在main函数执行过程中,如果CPU得到一个中断请求,PC指针仍然会强制跳转到地址0X08000004中断向量表处,而不是新程序的中断向量表,如图标号④所示;程序再根据我们设置的中断向量表偏移量,跳转到对应中断源新的中断服务程序中,如图标号⑤所示;在执行完中断服务程序后,程序返回main函数继续运行,如图标号⑥所示。
通过以上两个过程的分析,我们知道IAP程序必须满足两个要求:
1) 新程序必须在IAP程序之后的某个偏移量为x的地址开始;
2) 必须将新程序的中断向量表相应的移动,移动的偏移量为x;
本章,我们有2个APP程序:
1,FLASH APP程序,即只运行在内部FLASH的APP程序。
2,SRAM APP程序,即只运行在内部SRAM的APP程序,其运行过程和图55.1.2相似,不过需要设置向量表的地址为SRAM的地址。
1. APP程序起始地址设置方法
APP程序使用以前例程即可,不需要对程序进行修改。
默认的条件下,图55.1.3中IROM1的起始地址(Start)一般为0x08000000,大小(Size)为0x200000,即从0x08000000开始的2MB空间为我们的程序存储区。

图55.1.3 FLASH APP Target选项卡设置
实际上,在实验14 RTC实验_FLASH_APP中,图55.1.3的配置,我们设置起始地址(Start)为0x08020000,即偏移量为0x20000(128K字节,即留给BootLoader的空间),因而,留给APP用的FLASH空间(Size)为0x200000-0x20000=0x1E0000(1920KB)。设置好Start和Size,就完成APP程序的起始地址设置。IRAM是内存的地址,APP可以独占这些内存,我们不需要修改。
注意:需要确保APP起始地址在Bootloader程序结束位置之后,并且偏移量为0x200的倍数即可(相关知识,请参考: http://www.openedv.com/posts/list/392.htm )。
这是针对FLASH APP的起始地址设置,如果是SRAM APP,那么起始地址设置如图55.1.4所示:

图55.1.4 SRAM APP Target选项卡设置
这里我们将IROM1的起始地址(Start)定义为:0x20001000,大小为0x3F000(252K字节),即从地址0x20000000偏移0x1000开始,存放SRAM APP代码。这个分配关系大家可以根据自己的实际情况修改,由于STM32H562VIT6有一个640K的片内SRAM,存放程序的位置与变量的加载位置不能重复,所以我们需要设置IRAM1中的地址(SRAM)的起始地址变为0x20040000,分配大小只有0x60000(384K字节)。整个STM32H562VIT6的SRAM分配情况为:最开始的4K给Bootloader程序使用,随后的252K存放APP程序,最后384K,用作APP程序的内存。
关于APP起始地址的设置方法,我们就介绍到这里,大家可以根据自己项目的实际需求进行修改。
2. 中断向量表的偏移量设置方法
VTOR寄存器存放的是中断向量表的起始地址。默认的情况它由BOOT的启动模式决定,对于STM32H562来说就是指向0x0800 0000这个位置,也就是从默认的启动位置加载中断向量等信息,不过ST允许重定向这个位置,这样就可以从Flash区域的任意位置启动我们的程序了。我们可以通过调用sys.c里面的sys_nvic_set_vector_table函数实现,该函数定义如下:
/**
* @brief 设置中断向量表偏移地址
* @param baseaddr: 基址
* @param offset: 偏移量
* @retval 无
*/
void sys_nvic_set_vector_table(uint32_t baseaddr, uint32_t offset)
{
/* 设置NVIC的向量表偏移寄存器,VTOR低9位保留,即[8:0]保留 */
SCB->VTOR = baseaddr | (offset & (uint32_t)0xFFFFFE00);
}
该函数用于设置中断向量偏移,baseaddr为基地址(即APP程序首地址),Offset为偏移量,需要根据自己的实际情况进行设置。比如FLASH APP设置中断向量表偏移量为0x20000,调用情况如下:
/* 设置中断向量表偏移量为0X20000 */ sys_nvic_set_vector_table(FLASH_BASE, 0x20000);
这是设置FLASH APP的情况,SRAM APP的情况可以参考实验24 触摸屏实验_SRAM_APP版本,其具体的调用情况请看到main函数。
通过以上两个步骤的设置,我们就可以生成APP程序了,只要APP程序的FLASH和SRAM大小不超过我们的设置即可。不过MDK默认生成的文件是.hex文件,并不方便我们用作IAP更新,我们希望生成的文件是.bin文件,这样可以方便进行IAP升级(至于为什么,请大家自行百度HEX和BIN文件的区别!)。这里我们通过 MDK 自带的格式转换工具 fromelf.exe,来实现.axf 文件到.bin 文件的转换。该工具在 MDK 的安装目录\ARM\ARMCC\bin 文件夹里面。
fromelf.exe转换工具的语法格式为:fromelf [options] input_file。其中options有很多选项可以设置,详细使用请参考光盘《mdk如何生成bin文件.doc》。
本实验,我们可以通过在MDK点击Options for TargetàUser选项卡,在After Build/Rebuild一栏中,勾选Run #1,我们推荐使用相对地址,在勾选的同一行后的输入框并写入命令行:fromelf.exe --bin -o ..\..\Output\atk_h562.bin ..\..\Output\atk_h562.axf,如图55.1.5所示:

图55.1.5 设置生成编译结果文件名
通过这一步设置,我们就可以在MDK编译成功之后,调用fromelf.exe,根据当前工程的atk_h562.axf,生成一个atk_h562.bin 的文件。并存放在 axf 文件相同的目录下,即工程的Output 文件夹里面。在得到.bin 文件之后,我们只需要将这个 bin 文件传送给单片机,即可执行 IAP 升级。
最后来看看APP程序的生成步骤:
1) 设置APP程序的起始地址和存储空间大小
对于在FLASH里面运行的APP程序,我们只需要设置APP程序的起始地址,和存储空间大小即可。而对于在SRAM里面运行的APP程序,我们还需要设置SRAM的起始地址和大小。无论哪种APP程序,都需要确保APP程序的大小和所占SRAM大小不超过我们的设置范围。
2) 设置中断向量表偏移量
此步,通过调用sys_nvic_set_vector_table函数,实现对中断向量表偏移量的设置。
3) 设置编译后运行fromelf.exe,生成.bin文件
通过在User选项卡,设置编译后调用fromelf.exe,根据.axf文件生成.bin文件,用于IAP更新。
以上3个步骤,就可以得到一个.bin的APP程序,通过Bootlader程序即可实现更新。
55.2 硬件设计
1. 例程功能
本实验开机的时候先显示提示信息,然后等待串口输入接收APP程序(无校验,一次性接收),在串口接收到APP程序之后,即可执行IAP。
1) 如果是SRAM APP,通过按下KEY0即可执行这个已收到的SRAM APP程序。
2) 如果是FLASH APP,则需要先按下KEY_UP按键,将FLASH APP从SRAM中写入到FLASH,再通过KEY1按键,跳转并执行FLASH APP。
LED0闪烁,提示程序运行。
2. 硬件资源
1)LED灯 LED0 - PB4
2)独立按键
KEY0 – PA1
KEY1 – PA15
WK_UP – PA0
3)串口1 (PA9/PA10连接在板载USB转串口芯片CH340上面)
4)正点原子2.8/3.5/4.3/7寸TFTLCD模块(仅限MCU屏,16位8080并口驱动)
5)内部FLASH
55.3 程序设计
55.3.1 程序流程图

图55.3.1.1 串口IAP实验程序流程图
55.3.2 程序解析
本实验,我们总共需要3个程序(1个IAP,2个APP):
1、FLASH IAP Bootloader,起始地址为0x0800 0000,预留128KB FLASH方便后续升级,作用:用串口1来接收APP的bin文件,通过按键选择对应功能,如:复制APP程序到FLASH、跳转运行FLASH APP、跳转运行SRAM APP。
2、FLASH APP,起始地址为0x0802 0000,往后的1920KB FLASH都可以存放FLASH APP程序。本程序使用:实验15 RTC实验,作为FLASH APP程序。
3、SRAM APP,起始地址为0x2000 1000,预留4KB SRAM给FLASH IAP Bootloader程序使用。从地址0x2000 1000开始,预留了252KB的SRAM存放SRAM APP代码。从地址0x20040000开始,预留了384KB的SRAM给SRAM APP程序使用。本程序使用:实验28 触摸屏实验,作为SRAM APP程序。
本章关于APP程序的生成和修改比较简单,我们就不细说,请大家结合光盘源码以及55.1节的介绍,自行理解。本章程序解析小节仅针对Bootloader程序。
1. IAP代码
这里我们只讲解核心代码,详细的源码请大家参考光盘本实验对应源码,IAP的驱动主要包括两个文件:iap.c和iap.h。
本实验的IAP Bootloader工程可以使用“实验29 FLASH模拟EEPROM实验”作为基础工程,我们要用到里面的STMFLASH驱动,然后在“实验44 串口IAP实验\IAP Bootloader V1.0\User\IAP”路径下,添加iap.c和iap.h两个文件。
下面首先查看我们的iap.h头文件,里面有一个重要的宏定义,如下:
/* 第一个应用程序起始地址(存放在内部FLASH) * 保留 0X08000000~0X0801FFFF(共128KB) 的空间给 Bootloader 使用 */ #define FLASH_APP1_ADDR 0x08020000
该宏定义是FLASH APP程序存放的起始地址。
接下来是iap.c文件函数介绍,首先是IAP写入APP BIN函数,其定义如下:
/**
* @brief IAP写入APP BIN
* @param appxaddr : 应用程序的起始地址
* @param appbuf : 应用程序CODE
* @param appsize : 应用程序大小(字节)
* @retval 无
*/
void iap_write_appbin(uint32_t appxaddr, uint8_t *appbuf, uint32_t appsize)
{
uint16_t t;
uint16_t i = 0;
uint16_t temp;
uint32_t fwaddr = appxaddr; /* 当前写入的地址 */
uint8_t *dfu = appbuf;
for (t = 0; t < appsize; t += 4)
{
temp = (uint16_t)dfu[3] << 24;
temp |= (uint16_t)dfu[2] << 16;
temp |= (uint16_t)dfu[1] << 8;
temp |= (uint16_t)dfu[0];
dfu += 4; /* 偏移2个字节 */
g_iapbuf[i++] = temp;
if (i == 512)
{
i = 0;
stmflash_write(fwaddr, g_iapbuf, 512);
fwaddr += 2048; /* 偏移2048 16 = 2 * 8 所以要乘以2 */
}
}
if (i)
{
stmflash_write(fwaddr, g_iapbuf, i); /* 将最后的一些内容字节写进去 */
}
}
iap_write_appbin 函数用于将存放在串口接收 buf 里面的APP 程序写入到 FLASH。
接下来是跳转到应用程序段(执行APP)函数,其定义如下:
/**
* @brief 跳转到应用程序段(执行APP)
* @param appxaddr : 应用程序的起始地址
* @retval 无
*/
void iap_load_app(uint32_t appxaddr)
{
/* 检查栈顶地址是否合法 */
if (((*(volatile uint32_t *)appxaddr) & 0x2FF00000) == 0x20000000)
{
/* 用户代码区第二个字为程序开始地址(复位地址) */
jump2app = (iapfun) * (volatile uint32_t *)(appxaddr + 4);
/* 初始化APP堆栈指针(用户代码区的第一个字用于存放栈顶地址) */
sys_msr_msp(*(volatile uint32_t *)appxaddr);
/* 跳转到APP */
jump2app();
}
}
iap_load_app 函数用于跳转到 APP 程序运行, 其参数 appxaddr 为APP 程序的起始地址,程序先判断栈顶地址是否合法,在得到合法的栈顶地址后,通过 sys_msr_msp 函数(该函数在 sys.c 文件)设置栈顶地址,最后通过一个虚拟的函数(jump2app)跳转到 APP 程序执行代码,实现 IAP→APP 的跳转。
2. usart代码
我们需要修改串口接收部分的程序,才能通过接受串口接收上位机传输过来的APP BIN文件。我们定义一个大的接收数组g_usart_rx_buf[USART_REC_LEN],并保证这个数组能接收并缓存一个完整的bin文件。在例程中,我们定义这个USART_REC_LEN宏定义为500*1024,即这个数组大小为500KB,这个大小需要根据芯片可用的SRAM来定,STM32H562VIT6的SRAM有640KB,所以这里设置了500KB。g_usart_rx_buf数组的定义如下:
/* 接收缓冲, 最大USART_REC_LEN个字节 */
uint8_t g_usart_rx_buf[USART_REC_LEN]
__attribute__((section(".bss.ARM.__at_0x20001000")));
这里,我们指定 g_usart_rx_buf 的地址是从 0x20001000 开始,该地址也就是 SRAM APP 程序的起始地址!
在usart.c 里面,我们修改 USART_UX_IRQHandler 部分代码,具体如下:
/**
* @brief 串口1中断服务函数
* @param 无
* @retval 无
*/
void USART_UX_IRQHandler(void)
{
uint8_t rxdata;
#if SYS_SUPPORT_OS /* 使用OS */
OSIntEnter();
#endif
if ((__HAL_UART_GET_FLAG(&g_uart1_handle, UART_FLAG_RXNE) != RESET))
{
HAL_UART_Receive(&g_uart1_handle, &rxdata, 1, 1000);
if (g_usart_rx_cnt < USART_REC_LEN)
{
g_usart_rx_buf[g_usart_rx_cnt] = rxdata;
g_usart_rx_cnt++;
}
}
HAL_UART_IRQHandler(&g_uart1_handle); /* 调用HAL库中断处理公用函数 */
#if SYS_SUPPORT_OS /* 使用OS */
OSIntExit();
#endif
}
在USART_UX_IRQHandler函数里面,将串口发送过来的数据,全部接收到g_usart_rx_buf,并通过g_usart_rx_cnt计数。此外,我们还屏蔽了HAL_UART_RxCpltCallback函数的代码,具体请大家参考源码。
3. main代码
我们把接收标记的处理放在main.c中处理,具体如下:
int main(void)
{
uint8_t t = 0;
uint8_t key;
uint32_t oldcount = 0; /* 老的串口接收数据值 */
uint32_t applenth = 0; /* 接收到的app代码长度 */
uint8_t clearflag = 0;
HAL_Init(); /* HAL库初始化 */
HAL_ICACHE_Enable(); /* 使能指令缓存 */
sys_stm32_clock_init(250, 4, 2, 2); /* 系统时钟初始化, 250Mhz */
delay_init(250); /* 延时初始化 */
usart_init(115200); /* 串口初始化 */
led_init(); /* LED初始化 */
key_init(); /* 按键初始化 */
lcd_init(); /* LCD初始化 */
lcd_show_string(30, 50, 200, 16, 16, "STM32", RED);
lcd_show_string(30, 70, 200, 16, 16, "IAP TEST", RED);
lcd_show_string(30, 90, 200, 16, 16, "ATOM@ALIENTEK", RED);
lcd_show_string(30, 110, 200, 16, 16, "KEY_UP: Copy APP2FLASH!", RED);
lcd_show_string(30, 130, 200, 16, 16, "KEY1: Run FLASH APP", RED);
lcd_show_string(30, 150, 200, 16, 16, "KEY0: Run SRAM APP", RED);
while (1)
{
if (g_usart_rx_cnt)
{
/* 新周期内,没有收到任何数据,认为本次数据接收完成 */
if (oldcount == g_usart_rx_cnt)
{
applenth = g_usart_rx_cnt;
oldcount = 0;
g_usart_rx_cnt = 0;
printf("用户程序接收完成!\r\n");
printf("代码长度:%dBytes\r\n", applenth);
}
else oldcount = g_usart_rx_cnt;
}
t++;
delay_ms(10);
if (t == 30)
{
LED0_TOGGLE();
t = 0;
if (clearflag)
{
clearflag--;
if (clearflag == 0)
{
lcd_fill(30, 190, 240, 210 + 16, WHITE); /* 清除显示 */
}
}
}
key = key_scan(0);
if (key == WKUP_PRES) /* WKUP按下,更新固件到FLASH */
{
if (applenth)
{
printf("开始更新固件...\r\n");
lcd_show_string(30, 190, 200, 16, 16,"Copying APP2FLASH...",BLUE);
if (((*(volatile uint32_t *)(0X20001000 + 4)) & 0xFF000000)
== 0x08000000) /* 判断是否为0X08XXXXXX */
{
/* 更新FLASH代码 */
iap_write_appbin(FLASH_APP1_ADDR, g_usart_rx_buf, applenth);
lcd_show_string(30, 190, 200, 16, 16,
"Copy APP Successed!!", BLUE);
printf("固件更新完成!\r\n");
}
else
{
lcd_show_string(30, 190, 200, 16, 16,
"Illegal FLASH APP! ", BLUE);
printf("非FLASH应用程序!\r\n");
}
}
else
{
printf("没有可以更新的固件!\r\n");
lcd_show_string(30, 190, 200, 16, 16, "No APP!", BLUE);
}
clearflag = 7; /* 标志更新了显示,并且设置7*300ms后清除显示 */
}
if (key == KEY1_PRES) /* KEY1按键按下, 运行FLASH APP代码 */
{
printf("flash addr :%x \r\n",(*(volatile uint32_t *)
(FLASH_APP1_ADDR + 4)) & 0xFF000000);
if (((*(volatile uint32_t *)(FLASH_APP1_ADDR + 4)) & 0xFF000000)
== 0x08000000) /* 判断FLASH里面是否有APP,有的话执行 */
{
printf("开始执行FLASH用户代码!!\r\n\r\n");
delay_ms(10);
iap_load_app(FLASH_APP1_ADDR);/* 执行FLASH APP代码 */
}
else
{
printf("没有可以运行的固件!\r\n");
lcd_show_string(30, 190, 200, 16, 16, "No APP!", BLUE);
}
clearflag = 7; /* 标志更新了显示,并且设置7*300ms后清除显示 */
}
if (key == KEY0_PRES) /* KEY0按下 */
{
printf("开始执行SRAM用户代码!!\r\n\r\n");
delay_ms(10);
if (((*(volatile uint32_t *)(0x20001000 + 4)) & 0xFF000000)
== 0x20000000) /* 判断是否为0X20XXXXXX */
{
iap_load_app(0x20001000); /* SRAM地址 */
}
else
{
printf("非SRAM应用程序,无法执行!\r\n");
lcd_show_string(30, 190, 200, 16, 16, "Illegal SRAM APP!", BLUE);
}
clearflag = 7; /* 标志更新了显示,并且设置7*300ms后清除显示 */
}
}
}
该段代码,实现了串口数据处理,以及IAP更新和跳转等各项操作。Bootloader程序就设计完成了,一般要求bootloader程序越小越好(给APP省空间嘛),实际应用时,可以根据需要尽量精简代码来得到最小的IAP。本章例程我们仅作演示用,所以不对代码做任何精简,最后得到IAP Bootloader工程的编译信息,如图55.3.2.1所示:

图55.3.2.1 IAP Bootloader工程编译信息
从上图可以看出,Bootloader大小为49K左右,比较大,主要原因是液晶驱动和printf占用了比较多的flash,如果大家想删减代码,可以去掉不用的LCD部分代码和printf 等,不过我们在本章为了演示效果,所以保留了这些代码。
至此,本实验的软件设计部分结束。
FLASH APP和SRAM APP 两部分代码,根据55.1节的介绍,大家自行修改都比较简单,我们这里就不介绍了,不过要提醒大家: FLASH APP 的起始地址必须是 0X08020000,而 SRAM APP的起始地址必须是0X20001000。
55.4 下载验证
将程序下载到开发板后,可以看到LCD首先显示一些实验相关的信息,如图55.4.1所示:

图55.4.1 IAP程序界面
此时,我们可以通过串口,发送FLASH APP或者SRAM APP到开发板,如图55.4.2所示:

图55.4.2 串口发送APP程序界面
首先找到开发板USB转串口的串口号,打开串口(我电脑是COM26),然后设置波特率为115200(图中标号1所示),然后,点击打开文件按钮(如图标号 2 所示),找到 APP 程序生成的.bin 文件(注意:文件类型得选择所有文件!!默认是只打开 txt 文件的),最后点击发送文件(图中标号 3 所示),将.bin 文件发送给Mini STM32H5开发板,发送完成后, XCOM 会打印代码长度(图中标号4所示)和提示文件发送完毕,点击确定即可(图中标号5所示)。
如果收到的bin文件是FLASH APP,我们需要先按下按键KEY_UP,将这个bin文件从SARM存入FLASH中,然后才可以按下按键KEY1,运行FLASH APP。
如果收到的bin文件是SRAM APP,我们可以直接按下按键KEY0,运行SRAM APP。
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/70040860/viewspace-3107355/ ,如需转载,请注明出处,否则将追究法律责任。