STM32Bootloader基于ymodem传输协议串⼝IAP升级详解
硬件:stm32f103cbt6
软件:STM32F10x_StdPeriph_Lib_V3.5.0
⽂章⽬录
1 预备知识
基于标准外设库(STM32F10x_StdPeriph_Lib_V3.5.0)的IAP升级相关资料可以参考。
STM32升级的三种⽅式:IAP,ICP,ISP;具体有什么区别可以⾃⾏Google;
本⽂需要实现STM32的Bootloader(后⾯Bootloader/IAP不加以区分),⽂件传输基于ymodem协议通过串⼝进⾏传输,这⾥参考了ST官⽅的DEMO —— ,在此基础上做了部分修改,增加了延时启动的功能,最终可以实现想要的效果。
整体架构分为两个部分;Bootloader和Application,具体如下图所⽰;
由上图可知,STM32内置的Flash被分成了两个部分,分别⽤来保存Bootloader和Application程序,这⾥有两个有两个FLASH起始地
址0x8000000和0x8003000;
为什么是0x8000000这个地址呢?⽽不是其他地址呢?
这是由M3内核硬件上的设计就已经这么做了,⼈为设计好了,可以参考M3内核权威指南;
0x8003000这个地址则是由我们⾃⼰来规定的,这个地址的范围必须在0x8000000和0x8020000之间,所以⼀般根据Bootloader程序的最终⼤⼩,在这范围之间取⼀个⽐较合理的值即可。如下图所⽰;
注意:本⽂使⽤的stm32f103cb,属于中等⼤⼩Flash,128K = 0x20000,所以地址范围是0x8000000~0x8020000;
2 Bootloader
2.1 启动流程
这⾥的Bootloader即为IAP程序,它具备以下⼏个功能;
⽀持⽂件传输;本⽂基于ymodem协议通过串⼝通讯接收或发送的bin⽂件;当然也可以通过I2C,SPI,USB,WiFi,蓝⽛等等进⾏⽂件传输;
对内置Flash进⾏读写,擦除和编程;
启动Application程序;
前⾯分析STM32启动⽂件的时候,我们可以知道,正常⼀个系统的启动流程,可以参考;
由该图可以知道程序正常启动流程;以下表格⼀四个向量是必须的,从图中也可以了解到;
地址异常编号值
0x0800_0000-MSP 的初始值
0x0800_00041复位向量(PC 初始值)
0x0800_00082NMI 服务例程的⼊⼝地址
0x0800_000C3硬 fault 服务例程的⼊⼝地址
………
2.2 校验跳转地址是否有效
在主函数中可以看到如下程序;甚是不解和迷茫;沉思⼀会⼉才恍然⼤悟;
/* Test if user code is programmed starting from address "ApplicationAddress" */
if (((*(__IO uint32_t*)ApplicationAddress) & 0x2FFE0000 ) == 0x20000000)
{
/* Jump to user application */
JumpAddress = *(__IO uint32_t*) (ApplicationAddress + 4);
Jump_To_Application = (pFunction) JumpAddress;
/* Initialize user application's Stack Pointer */
__set_MSP(*(__IO uint32_t*) ApplicationAddress);
Jump_To_Application();
}
本⽂中ApplicationAddress = 0x8000000;
那么*(__IO uint32_t*)ApplicationAddress)则是这个地址中所保存的值,由表格⼀可以知道,程序起始地址的第⼀个向量地址保存的栈顶的,因此,地址0x800_0000和0x800_3000中保存的值都是指向栈顶,如下图所⽰;
栈是在RAM上分配,因此RAM的有效范围要做⼀个检测,栈顶地址和0x2FFE0000做与运算可以推算出,要校验的RAM范围是0x2000_0000—
0x2001_FFFF,所以RAM⼤⼩是128K,官⽅DEMO默认使⽤HD⾼密度系列,所以是128K,本⽂是CBT6,20K的RAM,则需要改
成0x2FFFB000:
/* Test if user code is programmed starting from address "ApplicationAddress" */
if (((*(__IO uint32_t*)ApplicationAddress) & 0x2FFFB000 ) == 0x20000000)
{
/* Jump to user application */
JumpAddress = *(__IO uint32_t*) (ApplicationAddress + 4);
Jump_To_Application = (pFunction) JumpAddress;
/* Initialize user application's Stack Pointer */
__set_MSP(*(__IO uint32_t*) ApplicationAddress);
Jump_To_Application();session和application的区别
}
计算⽅式:
20K = 20*1024= 0x5000,
0x2FFF_FFFF - (0x5000 - 1) = 0x2FFF_B000
2.3 Keil⼯程IAP的相关设置
2.3.1 修改Flash地址
设置程序起始地址0x800000和⼤⼩0x3000;
设置Debug⼯具烧写时Flash的起始地址0x800000和⼤⼩0x3000;
2.3.2 使⽤⾃⼰的链接脚本
该项为选配,与上述配置⼆选⼀即可,如果仍然想使⽤⾃⼰的链接脚本,在Option-->Linker下将Use Memort Layout from Target Dialog选项勾选去掉,然后选择⾃⼰的链接脚本,如下图进⾏配置;
参考ARMCC的链接脚本编写⽅法,可以⾃⼰编写的srt⽂件,参考ARM分散加载技术;
; *************************************************************
; *** Scatter-Loading Description File generated by uVision ***
; *************************************************************
LR_IROM1 0x08000000 0x00003000  {    ; load region size_region
ER_IROM1 0x08000000 0x00003000  {  ; load address = execution address
*.o (RESET, +First)
*(InRoot$$Sections)
.ANY (+RO)
.ANY (+XO)
}
RW_IRAM1 0x20000000 0x00005000  {  ; RW data
.ANY (+RW +ZI)
}
}
如果⽤的gcc⼯具链,则要编写gcc的链接脚本ld⽂件;
2.3.3 下载固件
配置完成之后进⾏Build,然后通过SWD的⽅式先下载固件,进⾏实验;
3 Application
3.1 启动流程
⽤户的Application需要在IAP启动完成后,才能正常执⾏;具体启动过程,⽐正常应⽤的启动多了⼀个IAP启动的过程,并最终通过IAP引导进⼊Application;具体如下图所⽰;
⽩⾊部分为IAP;
灰⾊部分为Application;
图中的0x8000004+N+M就等于0x8003004,所以Application的启动地址需要进⾏修改,另外还有其他需要修改的地⽅,下⾯会详细指出。
3.2 IAP中的引导部分
参考IAP中的引导程序;
#define ApplicationAddress    0x8003000
/* Jump to user application */
JumpAddress = *(__IO uint32_t*) (ApplicationAddress + 4);
Jump_To_Application = (pFunction) JumpAddress;
/* Initialize user application's Stack Pointer */
__set_MSP(*(__IO uint32_t*) ApplicationAddress);
Jump_To_Application();
可以发现的是SP的值为0x8003000,指向栈顶,⽽0x8003004则为ResetHander的地址,系统会进⾏复位,然后开始Application正常启动流程;3.3 关于 VTOR
VTOR是向量表偏移量寄存器,它将⽤来告诉CPU,从Flash的哪个地⽅去取向量地址,第⼀个要取的是MSP的值,然后就是复位向量地
址ResetHandler,如果这⾥设置错误,那么程序是⽆法正常启动的。下⾯是标准库中与其相关的代码⽚段;
__IO uint32_t VTOR;  /*!< Offset: 0x08  Vector Table Offset Register  */
/*!< FLASH base address in the alias region */
#define FLASH_BASE            ((uint32_t)0x08000000)
/*!< Vector Table base offset field. This value must be a multiple of 0x200. */
#define VECT_TAB_OFFSET  0x0
/* Vector Table Relocation in Internal FLASH. */
SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET;
所以Application中还需要修改VECT_TAB_OFFSET的值为0x3000;
参考M3权威指南:
如果需要动态地更改向量表,则对于任何器件来说,向量表的起始处都必须包含以下向量:
主堆栈指针(MSP)的初始值
复位向量
NMI
硬 fault 服务例程
后两者也是必需的,因为有可能在引导过程中发⽣这两种异常。可以在 SRAM 中开出⼀块空间⽤于存储向量表。在引导期
间先填写好各向量,然后在引导完成后,就可以启⽤内存中的新向量表,从⽽实现向量可动态调整的能⼒。
3.4 Keil⼯程设置
3.4.1 Flash地址设置
与IAP⼯程设置类似,这⾥的Application是另⼀个Keil⼯程,同样的需要对Flash进⾏设置,如下图所⽰;
这⾥Application⼯程的Flash地址偏移了0x3000,正是之前Bootloader所占⽤的Flash空间⼤⼩,这⾥和VTOR的设置也必须保持⼀致;
3.4.2 hex2bin
配置⼯程最终⽣成hex⽂件,如下图所⽰;
最终我们需要使⽤的是bin⽂件,所以,这⾥需要使⽤将hex⽂件转成bin⽂件,本⽂使⽤hex2bin的⼯具;配置⼯程运⾏之后执⾏转换⽂件的脚本;
create_bin.bat
echo %cd%
set ROOT_PATH=.\..\..
set SRC=%ROOT_PATH%\..\Project\STM32F10x_StdPeriph_Template\MDK-ARM\STM3210B-EVAL\*.hex
set TOOL=%ROOT_PATH%\..\
if exist %SRC% (%TOOL% %SRC%)
exit
copy_firmware.bat
echo %cd%
set ROOT_PATH=.\..\..
set HEX_FILE=%ROOT_PATH%\..\Project\STM32F10x_StdPeriph_Template\MDK-ARM\STM3210B-EVAL\*.hex
set BIN_FILE=%ROOT_PATH%\..\Project\STM32F10x_StdPeriph_Template\MDK-ARM\STM3210B-EVAL\*.bin
set DST_DIR=%ROOT_PATH%\..\Firmware\
if exist %HEX_FILE% (XCOPY /Y /S /F %HEX_FILE% %DST_DIR%)
if exist %BIN_FILE% (XCOPY /Y /S /F %BIN_FILE% %DST_DIR%)
exit
最终在Build之后,可以在Firmware中到STM321-APP.bin,这个⽂件就是要⽤来IAP程序进⾏串⼝下载的程序。
3.4.3 ⽤户程序串⼝下载测试
SecureCRT软件⽀持ymodem协议,可以安装该软件,打开串⼝连接,设置ymodem的协议;
打开菜单选项:Options–Session Options,配置如下;
为了便于测试,在STM32F1-APP进⾏串⼝发送以下信息,便于观察APP是否正常启动;
usart_printf(" \r\n STM32F1-APP start running*******************");
打开连接的串⼝,并根据终端提⽰进⾏操作,最终下载固件STM32F1-APP成功,并成功运⾏;
4 附件

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。