基于STM32的IAP技术分享

2023-11-16

1.烧录过程说明

在这里插入图片描述
公司做产品时,在线升级用户程序是一个比较常用的功能。那么如何给用户升级APP程序呢?难道让用户像开发人员一样使用一个仿真器去下载程序吗?这显然是不行的,大批量的产品一般都是通过串口去升级APP程序。
一次烧录:通过厂家bootloader烧录用户自定义bootloader,再通过用户自定义bootloader烧录用户APP。
二次烧录:如上图所示,一个产品在出厂时为了具备在线升级的功能,在出厂时生产厂家会先烧录一个自定义bootloader,然后再烧录用户APP程序。后续升级时通过用户APP程序跳转到用户自定义bootloader,然后通过用户自定义bootloader对用户APP程序进行升级。
对于新手而言,可能不太理解整个过程,因此这里有必要解释厂家bootloader、用户自定义bootloader、用户APP的区别。
厂家bootloader:芯片厂家编写的一段程序,这段程序不可更改。它的作用是通过串口去解析上位机下发的.bin文件然后将其写入FLASH中,即从0x08000000开始写入程序。与平常通过JLINK调试器下载程序不同的是,它是用串口实现烧录的。运行厂家bootloader的程序需要设置芯片boot0、boot1引脚的状态。这个后续会讲到。
用户自定义bootloader:这是开发人员自己编写的一段程序,用于实现和厂家bootloader一样的功能。它是可以自定义的,烧录时的通讯协议也由自己定义。它做的操作就是在对FLASH进行擦除和写入,将用户APP程序的.bin写入到用户APP程序的地址区域即可。用户自定义bootloader它的起始地址也是从0x08000000开始,其大小需要根据实际情况进行确定。所以我们需要做用户自定义bootloader和用户APP的地址划分。
用户APP:这个就是我们平常编程时的用户程序,只不过设置了一个偏移地址,它不是从芯片的0x08000000地址开始运行的,而是从我们设置的偏移地址开始运行。

为什么要自己写一个bootloader呢?直接用厂家的不香吗?
前面有讲到,运行在厂家bootloader需要设置boot0、boot1的状态。如果每次升级用户APP都去设置boot0和boot1的状态,这样很麻烦。而且厂家bootloader属于明文烧录,会造成程序泄密。

2.厂家bootloader

一般情况下正常运行程序时单片机是从主闪存FLASH运行,boot0和boot1都接GND。当使用ISP工具通过厂家bootloader进行程序烧录时,需要从系统存储器运行,系统存储器有一段厂家已经写好的程序,该区域只读不可被更改。从系统存储器运行需要设置单片机boot引脚,设置boot1=0,boot0=1,单片机上电将运行芯片厂商自带的bootloader程序。当运行在厂家bootloader时就可以通过USART/CAN来下载程序了。
厂家bootloader中做的事情其实就是解析上位机下发的.bin文件并将其写入到主闪存储器(FLASH)中。
在这里插入图片描述
STM32芯片有免费使用的ISP工具,可以在其官网进https://www.st.com行下载。软件虽然是免费的,但是需要注册该网站的账号才能进行下载。这款工具可以在设置芯片的boot引脚之后,下载用户程序编译生成的.hex文件和.bin文件。这里为了方便大家,可以从我的百度云盘进行下载。
在这里插入图片描述
链接:https://pan.baidu.com/s/1Q6CRqyjgDkeFaHG2GNeT_g
提取码:0y3b

软件打开后如下图所示。如果芯片的boot0已经拉高,那么就可以点击下一步进行下载了。如果boot0没拉高,测试时发现在如下界面下点击下一步软件会卡住。必须用任务管理器关掉后再重新打开软件才行,不知道是不是这个软件的bug。
在这里插入图片描述

3.bootloader区和APP区空间划分

这里说的boot区指的就是用户自定义的bootloader程序。根据芯片的型号查看其FLASH存储器的地址划分,本例中以STM32F103ZET6为例,它属于大容量产品,大小为512K,一共256页,每页2K。这里在划分区域时最好按照页大小进行划分,因为FLASH写入时必须先擦除页后在进行页的写入。
bootloader区需要多大的空间,根据编译后的map文件进行估算即可。记得留出一定的裕量。如下图所示总的大小为6.45KB,它是code+RO Data+RW Data的总和。
考虑到一定裕量和芯片页大小为2K,本次设置bootloader区域为16K。
得出:
bootloader的区域就是0x08000000~0x08003FFF
APP的区域就是0x08004000~0x0807FFFF

Code: 代码段,存放程序的代码部分;
RO-data: 只读数据段,存放程序中定义的常量;
RW-data: 读写数据段,存放程序中定义并且初始化的全局变量和静态变量;
ZI-data: 0数据段,存放程序中定义了但没有初始化的全局变量和静态变量;
在这里插入图片描述
在这里插入图片描述

4.bootloader区和APP程序内容说明

bootloader程序需要实现的内容:
1.解析上位机下发的.bin文件的内容,然后写入到FLASH中,写入完成之后跳转到APP用户程序
2.正常上电时,如果没有升级APP的指令则跳转至APP用户区运行。这里后续可以进行改进,首先对APP区进行一个检测,如果没有APP程序则不进行跳转。本次实例中没有做这个功能,而是通过串口连续发送3次0xf3指令后跳转到APP区。
APP程序需要实现的内容:
1.正常情况下,上电后最终会运行APP程序。APP程序中需要做一个跳转到bootloader区的操作,接收到上位机的特定指令进行跳转。这个操作的目的就是让bootloader区运行的程序去重新对APP区的FLASH进行编程。也就是所谓的在线升级啦。bootloader区操作完成之后再跳转到APP区就完成了用户APP的升级。

5.实验

5.1实验所用到的上位机软件

1.STMFlashLoader Demo(ST厂家的串口烧录工具,用于烧录bootloader程序)。本次试验的芯片为STM32F103ZET6。
2.fireTools(野火的一款上位机,基于Ymodem文件传输协议,用于烧录APP程序),可以在野火的官网上进行下载https://doc.embedfire.com/products/link/zh/latest/deskapp/ebf_trace_tool.html。这里使用的上位机版本为V1.0.2.9。
在这里插入图片描述
由于本人也是需要工作,精力有限,所以都是用的现成的软件,懒得再去造轮子了。这里讲一下为什么使用野火的这款串口调试软件,因为这个软件定义了一套文件传输协议,可以对发送的数据进行校验,保证了数据的可靠性,使得APP程序的升级更加稳妥,不至于出现错误。这种现成的软件肯定还有很多,看自己的需要进行选择。

5.2 bootloader和APP用户程序的偏移地址设置

根据之前已经划分好的bootloader和APP的区域,在keil中进行设置。
bootloader程序的keil工程中地址设置如下:
在这里插入图片描述

APP程序的keil工程中设置如下:
在这里插入图片描述

5.3 bootloader和APP用户程序中的细节

1.APP程序中需要设置APP用户程序的栈顶地址,也就是0x08004000,代码如下所示,将其放在SystemInit函数中,SystemInit函数是上电后执行的第一个函数,在启动文件里面可以看到,执行完SystemInit后才去执行的main函数。实际试验时将设置偏移地址的语句放在main函数的第一条语句也是可以的。
在这里插入图片描述
在这里插入图片描述

STM32单片机的上电启动过程可以查看野火的《STM32库开发实战指南——基于野火霸道开发板-20211109》手册。
手册中的第15章和第47章看完之后能对其有更深入的了解。这里要知道的是,单片机上电后在进入main前还做了很多其他的操作,而不是直接进入main函数的。

2.生成.bin文件,正常我们编译都只会在obj文件夹下生成一个hex文件。我们在进行APP升级时需要将.bin文件中的内容写入到FLASH中才行。那么怎么生成.bin文件呢。在keil中输入做如下设置,即可在生成.hex的地方生成.bin文件。
fromelf.exe --bin -o “$L@L.bin” “#L”
在这里插入图片描述

3.bootloader的keil配置不需做其他的特殊处理,平时怎么编程就怎么弄。APP的keil工程一般会配置两个工程,一个用于正常调试时使用不设置偏移地址,目的是为了方便调试。另一个keil工程需要设置一个偏移地址。APP程序中可以使用一个宏定义去配置偏移地址,开启了宏则设置偏移,不开启则不设置。宏定义放在keil的设置中,如下所示。当调试完成之后,使用带偏移地址的keil工程生成一个.bin文件,该.bin文件用做程序升级时往单片机下载的.bin。
在这里插入图片描述

4.APP程序设置偏移地址后,如何调试问题。可以配置一个.ini文件。这里网上有很多教程,所以就不多做介绍了。值得注意的就是配置完.ini文件后,Debug时不要擦除FLASH,否则会导致bootloader区被擦除。这样就看不到bootloader区对APP区的影响了。

5.4烧录的操作步骤以及实验中遇到的问题

1.首先烧录bootloader程序,在烧录前将boot0设置为高电平,让其进入厂家boot,然后通过STMFlashLoader Demo去烧录编译好的bootloader程序,.bin和.hex都可以。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2.等待bootloader烧录完成后,通过串口1烧录APP程序。烧录完APP后,bootloader进行跳转,通过串口发送跳转指令,跳转到APP后,APP能正常运行说明成功。
如果发现bootloader跳转后,APP没有运行,怎么查问题?
(1)确定APP烧录的正确性,利用J-FLASH软件将芯片的FLASH内容读上来。
在这里插入图片描述

截取APP程序的地址段的内容和APP烧录的.bin文件作对比,如果一致说明APP正确烧录,那么就是bootloader和APP之间的跳转处理有问题。重点查看跳转的代码写的是不是有问题,APP程序中的偏移设置的是不是有问题,或者APP本身程序有跑飞的问题。
如果内容不一致,说明bootloader在写入APP的FLASH地址段的处理有问题,导致写入了错误的APP程序。

3.跳转到APP后能正常运行,但是串口却死活进不了空闲中断。通过printf查看寄存器的方式,打印出了RCC、USART1、AFIO这几个寄存器中的内容,发现配置是正确的,和正常运行下的寄存器的值一样。bootloader跳转前有去关中断、清除时钟配置、清除所有中断标志位的操作。跳转到APP后开启了中断,APP中开了一个定时器,定时器中断中有一个LED取反操作,对外的现象是LED在闪,说明跳转到APP后还是能进中断的。但是APP的串口1死活接收不到数据,进不了空闲中断,但是可以发送数据,这个问题卡了很久。想了想是不是在串口中断中跳转APP导致的呢,因为bootloader跳转的操作是在串口中断中做的,做了关中断、复位时钟、清除所有中断标志的等操作。
后来将跳转放在串口中断外面处理则解决该问题,串口中断中只是打一个标记。

6.不足之处与思考

1.其实做在线升级不单单是为为了在线升级,更多的是为了保护自己的劳动成果不被窃取。这里就需要做一些加密的工作。
2.关于加密的一些思考:
由于在烧录用户bootloader的时候是用的芯片厂家定义的下载协议,因此属于明文烧录,如果这个过程被截获了报文。那么用户自定义bootloader程序内容就会被截获(通讯链路焊接飞线+逻辑分析仪抓取数据即可)。获取者通过反编译即可知道用户自定义bootloader中做了啥事。一般对于公司而言,烧录APP的上位机都是自己做的,公司想加密,必定在烧录APP的上位机上做文章。这个APP烧录软件与用户自定义bootloader之间的交互,肯定会定义一套加密和解密的算法,烧录APP上位机做加密,用户自定义bootloader做解密。类似于密码本,即使你抓取了通讯之间的内容,但是没有密码本,就没办法知晓数据内容。
说到这里,试想如果用户自定义bootloader程序内容被截取,通过反编译技术即可知晓用户自定义bootloader的程序内容,从而破解这套加密解密算法,那么整个APP程序的烧录将无秘密可言,APP程序也将被破解。
既然这样,那么就必须保证用户自定义bootloader内容不被截获,但是烧录用户自定义bootloader的时候是用的芯片厂家定义的协议,这个属于明文,大家都知道的呀,这是无解的,因为这个是用户改变不了的。
因此这里衍生出一个思路就是:烧录用户自定义bootloader也自己做一个上位机,在这个上位机中做权限设置,就是在拿到用户自定义bootloader的.bin文件后,必须有特定权限的人才能烧录,简单来说就是设置一个密码。但是这个烧录协议还是属于明文,当这个用户自定义bootloader的.bin文件外泄时,其他人换一个烧录软件按照芯片厂家的下载协议还是照样烧录。像是陷入死胡同了。。。。。。所以单单是做这个上位机的权限设置还是不行的,还得在.bin文件上下功夫,可以将.bin文件利用一套特定的规则打乱并进行加密,上位机中对这个被打乱的.bin文件进行重组并且解密。
感觉这样比较稳妥了吧?但还是有被破解的可能,如果.bin和上位机软件全部外泄,那么也就被破解了。所以当这两个机制建立完成之后,还得设置上位机软件权限,提到另外一个技术“加密狗”,只有手里掌握加密狗的人才可以使用这个上位机软件。加密狗就是钥匙,没有钥匙插入电脑,那么上位机将不能被使用,也就不能对被加密重组的.bin文件进行解密了。只有同时拿到加密狗+.bin文件+上位机才可以进行破解。这三样东西也是有可能的被同时获取的,但这个技术机制相对来说已经很完善,在此基础上进行修补即可。比如说加密狗中做烧录次数限制、定时更换加密算法,类似于电视剧中的定期更换密码本。
以上是软件层面的防破解,一般破解者为了复刻产品,肯定是从两个方面下手,软件是一方面,第二个方面就是抄板。所以硬件上也要做防抄板技术,比如说设计多层板、埋盲孔、各种误导陷阱、芯片上丝印擦除等。
但是从人的角度出发,没有完善不可破解的机制,因为机制都是被人设计出来的。技术上防破解做足了功夫,也需要考虑从人的角度。因为设计这个机制的人以及在这套机制流程下工作的人肯定是可以找到漏洞的,如果有足够的利益,那么这个机制是有可能被出卖的。当然,这是领导者需要考虑的问题,这里留给大家一个思考的空间。
3.实验中的bootloader程序和APP程序的.bin都是独立的,后续可以利用一个软件工具将其合并成一个。然后根据对加解密的思考,合并后的.bin通过两个上位机软件分别进行烧录,一个上位机专门用于烧录bootloader,一个上位机专门用户烧录APP。
4.以上提到的加解密,所要做的内容太多了,可能需要集合多人的技能才可以完成,毕竟不是每个人都是全能人才。这里想到一个简单的加密方式,就是利用芯片的唯一的序列号做加密,先读取序列,程序中做一个判断芯片序列号的操作,如果芯片序列号不正确则while1死循环,不执行往下的程序。但是这个方法的缺点不适合大批量生产,因为每个芯片都需要上电读一次序列号,并且修改程序内容,将其需要判断的序列号设置为当前芯片的序列号。但是这个方法简单粗暴,小批量的时候可以考虑一下。
5.APP区域的FLASH需进行CRC自检,所以在编译生成HEX文件时需要在HEX文件末尾添加CRC校验值,可以借助工具进行添加。本次试验没去做这个功能,后续可以加上。bootloader里面校验APP的FLASH,错误不进行跳转

7.参考资料

《STM32F10X闪存编程手册》
《STM32库开发实战指南——基于野火霸道开发板-20211109》
知乎:
https://www.baidu.com/link?url=DG2Zc2Zfo8r2B2etnxAfUC-8r2HTCO2HEdTVCKvi-MXonB6a-9rsJKQw1jIbIPBP&wd=&eqid=f3bf01c50038199000000004645793da
正点原子相关教程

8.试验代码

bootloader程序:
链接:https://pan.baidu.com/s/1iQRH89u6o1mASJEu2ZDUIA
提取码:4a0h
APP程序:
链接:https://pan.baidu.com/s/1KwZlSpaWeMMxjOxoT11vLA
提取码:47b1
Ymodem协议说明:
链接:https://pan.baidu.com/s/15v7nRoC_n5wgrF-nVsgo6g
提取码:8e0x

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

基于STM32的IAP技术分享 的相关文章

  • C语言:助学贷款额度计算

    大学可以申请助学贷款 申请额度不超过学费和生活费总额的60 分两行依次输入每学分应缴纳的学费 整数 单位为元 和你每个月的生活费 浮点数 单位为元 请计算你每个学期能够贷款多少元 结果保留小数点后2位数字 每个学期按5个月计算 输出格式请参
  • 国际版腾讯云/阿里云:全站加快有哪些功用?有哪些优势?适用于什么场景?

    腾讯云全站加快有哪些功用 有哪些优势 适用于什么场景 产品功用 全站加快 ECDN 经过在全球各区域部署加快节点 有用下降跨国拜访推迟 保证全球加快作用 最优链路 各加快节点两两相连 实时勘探 结合腾讯自研的最优链路算法 获取用于传输的最优

随机推荐

  • matplotlib绘制折线图与散点图

    coding utf 8 import numpy as np import matplotlib pyplot as plt 折线图 figure no表示显示图的顺序 def simple line plot x y figure no
  • 拓扑排序算法原理及Java代码实现

    一 拓扑排序的概念 对一个有向无环图 Directed Acyclic Graph简称DAG G进行拓扑排序 是将G中所有顶点排成一个线性序列 使得图中任意一对顶点u和v 若边
  • mysql 向上取整_mysql的取整函数

    一 ROUND 函数用法 ROUND X 表示将值 X 四舍五入为整数 无小数位 ROUND X D 表示将值 X 四舍五入为小数点后 D 位的数值 D为小数点后小数位数 若要保留 X 值小数点左边的 D 位 可将 D 设为负值 SELEC
  • 【STM32F1标准库】PWM生产4路PWM

    void TIM2 PWM Init u16 psc u16 arr GPIO InitTypeDef GPIO InitStructure 1 GPIO RCC APB2PeriphClockCmd RCC APB2Periph GPIO
  • vue项目编译、运行过慢如何提升编译(编译包括运行编译与打包编译)速度

    要说优化提升编译速度之前 我先给大家说一个能够列出输出 loader和plugins的耗时的插件 耗时过长将会使用黄色和红色显示 speed measure webpack plugin 这个插件我们在具体的项目中如何配置呢 下面请来看看我
  • 母牛的问题(C语言)

    题目 有一头母牛 它每年年中生一头小母牛 每头小母牛从第四个年头开始 每年年中也生一头小母牛 请编程实现在第 nn 年的时候 不算第 nn 年出生的小母牛 共有多少头母牛 输入格式 输入包括一个整数 n 0 lt n lt 55 n 0
  • Android逆向实战 - 腾讯新闻去开屏广告

    上次反编译一个工具类app失败 原因是使用了360加固 回编译后无法启动 一般来讲 大厂的app考虑到性能 兼容性 包体积等 通常不用加固 因此 本次我们选一个大一些的app 腾讯新闻 写在前面 本篇博客仅用来研究和学习 如有侵权 请联系我
  • 权力的游戏第七季/全集Game of Thrones迅雷下载

    艾美及金球奖获奖HBO原创剧集 权力的游戏 第七季将于2016年夏天晚些时候开拍 新的一季共有七集 主要拍摄地为北爱尔兰 部分镜头也将在西班牙和冰岛取景 上映时间预计将略有推迟 至2017年夏季 HBO公布 权力的游戏 第七季最新主演人选
  • 使用Python,OpenCV进行图像哈希

    使用Python OpenCV进行图像哈希 1 效果图 2 原理 3 源代码 参考 这篇博客将介绍图像哈希 感知哈希以及这些算法如何用于 快速 确定图像的视觉内容是否相同或相似 并实现了差异散列 一个常见的感知散列算法 1 非常快 而 2
  • SSE 指令

    数据类型 m64 任意整型 m128 4 位 32 bit 浮点型 m128d 2 位 64 bit 浮点型 m128i 任意整型 数学运算 m128 mm add ss m128 a m128 b 单精度浮点 低位加法 result a0
  • [技术发展-20]:高级研修班-智能电网-能源互联网的关键技术

    作者主页 https blog csdn net HiWangWenBing 文章出处 https blog csdn net HiWangWenBing article details 118314590 目录 目录 第一章 能源互联网的
  • 深度学习笔记8:softmax层的实现

    如果有什么疑问或者发现什么错误 欢迎在评论区留言 有时间我会一一回复 softmax简介 Softmax回归模型是logistic回归模型在多分类问题上的推广 在多分类问题中 待分类的类别数量大于2 且类别之间互斥 比如我们的网络要完成的功
  • if ...if和if...elif区别

    我一直以为写if还是elif都是一样的 今天没事做了下试验 证明凡是存在的都是合理的 不会存在无谓的东西 通过运行下面的代码我可以看出 if elif的逻辑是 程序先走if 能走就走 走完就不走elif了 走不通的情况才走elif 比如当a
  • Flask(二):flask数据库操作+ORM封装+flask配置文件编写规则

    flask数据库操作 django中使用ORM连接操作数据库 python使用pymysql链接数操作数据库 flask中也可以使用pymysql链接 sqlalchemy python的开源的ORM框架 flask sqlalchemy
  • Linq 三表 left join 的实现

    目的实现 select id name jname cname from userinfo u left join job j on u job j jid left join city c on u city c cid 多表left j
  • 家长叫我别天天我在房间没事多看看新闻,我说我马上写个爬虫爬新闻看!!!

    文章目录 前言 撸起袖子开始看新闻 爬新闻 完整代码 爬取结果 看新闻喽 最后 前言 本文爬虫源码已由 GitHub https github com 2335119327 PythonSpider 已经收录 内涵更多本博文没有的爬虫 有兴
  • 使用webpack打包vue项目

    使用webpack打包vue项目 安装webpack工具 安装方式有两种 全局安装 命令 npm install g webpack webpack cli 以及安装在项目中 这里使用第二种 在项目中安装 这里的 D表示运用到开发 deve
  • Python中,如何初始化不同的变量类型为空值

    常见的数字 字符 很简单 不多解释 列表List的其值是 x y z 的形式 字典Dictionary的值是 x a y b z c 的形式 元组Tuple的值是 a b c 的形式 所以 这些数据类型的变量 初始化为空值分别是 数值 di
  • 影视剪辑,短视频从拍摄到剪辑,超详细教程

    Hello 在这个短视频时代很多小伙伴想拍摄短视频 却无从下手 给你们分享一下 新手拍短视频的技巧 希望能帮助你轻松入门 关于视频后期制作也分享8个技巧 一 闪白 在视频拍摄剪辑合成节目时 如果不直接使用白帧叠化 而是在原素材上调高gamm
  • 基于STM32的IAP技术分享

    基于STM32的IAP技术分享 1 烧录过程说明 2 厂家bootloader 3 bootloader区和APP区空间划分 4 bootloader区和APP程序内容说明 5 实验 5 1实验所用到的上位机软件 5 2 bootloade