STM32 Bootloader基于ymodem传输协议串口IAP升级详解
硬件:stm32f103cbt6
软件:STM32F10x_StdPeriph_Lib_V3.5.0
文章目录
1 预备知识
基于标准外设库(STM32F10x_StdPeriph_Lib_V3.5.0
)的IAP升级相关资料可以参考 IAP ST官方资料汇总。
STM32升级的三种方式:IAP
,ICP
,ISP
;具体有什么区别可以自行Google
;
本文需要实现STM32的Bootloader
(后面Bootloader
/IAP
不加以区分),文件传输基于ymodem
协议通过串口进行传输,这里参考了ST
官方的DEMO
—— STM32F10xxx in-application programming using the USART AN2557,在此基础上做了部分修改,增加了延时启动的功能,最终可以实现想要的效果。
整体架构分为两个部分;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
启动文件的时候,我们可以知道,正常一个系统的启动流程,可以参考《STM32 标准库V3.5启动文件startup_stm32f10xxx.s分析》;
由该图可以知道程序正常启动流程;以下表格一
四个向量是必须的,从图中也可以了解到;
地址 | 异常编号 | 值 |
---|---|---|
0x0800_0000 | - | MSP 的初始值 |
0x0800_0004 | 1 | 复位向量(PC 初始值) |
0x0800_0008 | 2 | NMI 服务例程的入口地址 |
0x0800_000C | 3 | 硬 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();
}
计算方式:
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%\..\Bin\hex2bin.exe
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 附件
STM32 Bootloader基于ymodem传输协议串口IAP升级详解的更多相关文章
- 实时消息传输协议(RTMP)详解
一.概念与摘要 RTMP协议从属于应用层,被设计用来在适合的传输协议(如TCP)上复用和打包多媒体传输流(如音频.视频和互动内容).RTMP提供了一套全双工的可靠的多路复用消息服务,类似于TCP协议[ ...
- 安全超文本传输协议(HTTPS)详解
一.概念与摘要 HTTPS (Secure Hypertext Transfer Protocol)安全超文本传输协议,是一个安全通信通道,它基于HTTP开发用于在客户计算机和服务器之间交换信息.它使 ...
- stm32 Bootloader设计(YModem协议) (转)
源:stm32 Bootloader设计(YModem协议) 相信很多人都希望,不开盖就可以对固件进行升级吧,就像手机那些.下文中的bootload就来实现这样的功能. 前段时间有项目关于Bootlo ...
- FTP协议及工作原理详解
1. FTP协议 什么是FTP呢?FTP 是 TCP/IP 协议组中的协议之一,是英文File Transfer Protocol的缩写. 该协议是Internet文件传送的基础,它由一系列规格说明文 ...
- 第8章 应用协议 图解TCP/IP 详解
第8章 应用协议 图解TCP/IP 详解 8.1 应用层协议概要 应用层协议的定义 TCP和IP等下层协议是不依赖上层应用类型.实用性非常广的协议.而应用协议则是为了实现某种应用而设计和创造的协议. ...
- TCP协议粘包问题详解
TCP协议粘包问题详解 前言 在本章节中,我们将探讨TCP协议基于流式传输的最大一个问题,即粘包问题.本章主要介绍TCP粘包的原理与其三种解决粘包的方案.并且还会介绍为什么UDP协议不会产生粘包. 基 ...
- C#串口通信程序详解
C#串口通信程序详解 摘要:创建C#串口通信程序需要注意什么呢?创建C#串口通信程序的步骤是什么?那么本文就向你详细介绍创建C#串口通信程序集体的内容. 在.NET平台下创建C#串口通信程序,.NET ...
- SSL协议之数据加密过程详解
前言 总括: 原文博客地址:SSL协议之数据加密过程详解 知乎专栏&&简书专题:前端进击者(知乎)&&前端进击者(简书) 博主博客地址:Damonare的个人博客 生活 ...
- Java生鲜电商平台-APP/小程序接口传输常见的加密算法及详解
Java生鲜电商平台-APP/小程序接口传输常见的加密算法及详解 说明:Java生鲜电商平台-APP/小程序接口传输常见的加密算法及详解,加密算法,是现在每个软件项目里必须用到的内容. 广泛应用在包括 ...
随机推荐
- python 自动打包,发送邮件(包括附件)至多个收件人(qq邮箱,163邮箱)
-----------------------------打包部分---------------------------------- import zipfile def zipDir(dirpat ...
- gdb 调试中No symbol “***” in current context解决方法
主要是因为GCC/G++版本和GDB不匹配造成的,网上也有说是因为O2优化问题,具体啥原因需要自己尝试一下. 解决: 放狗搜索,解决办法是在编译是加-gdwarf-3即可,出现这样的原因是gcc,gd ...
- sftp的用法
linux sftp远程连接命令 sftp -oPort=60001 root@192.168.0.254 使用-o选项来指定端口号. -oPort=远程端口号 sftp> get /var/w ...
- linux CVE-2019-14287 Sudo提权漏洞
CVE-2019-14287 sudo介绍 sudo,也就是以超级管理员身份运行(superuser do)的意思.sudo 是 Linux 中最常使用的重要实用程序之一,它功能十分强大,几乎安装在每 ...
- Jmeter工具 组件简单认识
JMETER 所有的组件(元素)都是基于测试计划的,先有测试计划然后才有 JMETER 组件 JMETER 核心组件1.JMETER中的 Threads 类似与线程数,每一个线程数代表一个虚拟用户:测 ...
- 人体和电脑的关系——鸟哥的LINUX私房菜基础学习篇读书笔记
CUP=脑袋: 每个人会做的事情都不一样(指令集的差异),但主要都是通过脑袋来判断与控制身体各部分的行动 内存=脑袋中存放正在思考的数据区块: 在实际活动过程中,我们的脑袋需要有外界刺激的数据(例如光 ...
- [Abp vNext 入坑分享] - 3.简单的用户模块功能开发
一.简要说明 本篇文章开始进行业务模块的开发模拟,借助user模块来进行业务开发,主要是用户相关的基础操作.主要是先使用Users来体验整个开发的流程.主要是先把一个基础流程跑顺利,在这里我并不会过于 ...
- ASP.Net内置对象之网页之间传参(一)
Response对象 主要运用于数据从服务器发送到浏览器,可以输出数据.页面跳转.各个网页之间传参数等操作. 以下讲解几个常用例子: 在页面中输出数据 主要通过Write .WriteFile方法输出 ...
- Linux安全实验缓冲区溢出
缓冲区溢出实验: 缓冲区溢出是指程序试图向缓冲区写入超出预分配固定长度数据的情况.这一漏洞可以被恶意用户利用来改变程序的流控制,甚至执行代码的任意片段.这一漏洞的出现是由于数据缓冲器和返回地址的暂时关 ...
- Spring5参考指南:组件扫描
文章目录 组件扫描 @Component 元注解和组合注解 组件内部定义Bean元数据 为自动检测组件命名 为自动检测的组件提供作用域 生成候选组件的索引 组件扫描 上一篇文章我们讲到了annotat ...