ESA2GJK1DH1K升级篇: IAP详解
前言:
源码下载链接:
https://gitee.com/yang456/STM32_IAP_Learn.git
后期所有出售的升级程序皆在此代码之上进行优化和开发
请必须把此文章各个的地方的说明看懂,其它教程不再重复叙述.
下载bootloader程序 我用stlink下载哈,方便


选择程序文件

首先需要发送一条指令
updata start

然后发送程序文件



说明接收并运行了咱写的APP程序.
IAP详细说明:
所谓单片机的升级实质上就是把手动用软件下载程序,改为咱人为通过某种方式写到Flash
打开下面的程序

如果编译出错,可能是这里

我这里是让软件帮忙生成bin文件
我写的是
E:\MDK5\ARM\ARMCC\bin\fromelf.exe --bin -o .\Progect\Progect.bin .\output\Progect.axf
E:\MDK5\ARM\ARMCC\bin\fromelf.exe --bin -o 这是命令,意思是让软件生成bin文件
前面这个路径和自己安装软件的路径有关,下面是我的路径

.\Progect\Progect.bin 就是生成的bin文件名字是 Progect.bin ,路径是工程目录的 Progect文件夹里面(如果没有则会自动建个文件夹)
所谓工程目录

.\output\Progect.axf 当前工程目录的output文件夹里面的Progect.axf文件
.axf这个文件也是由软件生成的,这个文件里面有咱要的bin文件数据,当然还有一些调试信息
我设置的是生成的文件名字是Progect.axf

我自己设置的 让文件生成到output文件夹



其实整理下就是
E:\MDK5\ARM\ARMCC\bin\fromelf.exe --bin -o .\Progect\Progect.bin .\output\Progect.axf
用fromelf.exe里面的--bin -o指令,把Progect.axf文件里面的bin数据提取出来以后生成一个新的文件 Progect.bin
现在看bin文件 和 hex文件的区别


看没看到hex比bin文件多了前面一部分,和后面一部分
大家下载单片机程序应该都知道是下载hex文件
但是大家了解整个的下载过程不
其实咱用软件下载的时候首先单片机需要知道下载的这段程序下载到哪个地址上(把程序数据写到哪个Flash地址)
所以hex文件的前面部分就是地址信息,就是告诉芯片我后面的代码段存储到哪个地址上
当然为了保险起见,数据需要加校验,其实hex文件的最后一位就是校验位
像51单片机,STM32的串口下载,下载的时候需要断电上电,或者复位一下,其实咱的单片机里面有一段程序(接收单片机程序,写入Flash) 就是咱所说的bootloader
记不记得都是先点一下下载软件的下载按钮,然后再复位单片机
其实点一下下载软件,下载软件就一直串口输出下载命令呢!单片机一启动是先执行里面内嵌的bootloader,bootloader一检测到下载命令,就开始执行下载操作了,接收下载软件过来的数据,然后写到Flash里面.....写完了,有的单片机重启下才运行,有的就直接运行了
好,现在说bin文件为啥去掉了前面的地址信息
记住,咱自己更新的时候咱就规定好了程序的运行位置
注:大家应该知道0x08000000 和 0x8000000 是相等的
STM32默认一开始是从0x8000000开始运行的,程序默认也写到这里(注意这个是不可改变的)
但是呢咱可以手写个代码把一个完整的程序文件写到一个位置(假设写到 0x8004000开始)
然后呢!调用STM32给的跳转函数,填上跳转地址(0x8004000),程序就跳转到新地址运行了
我这几代码呢!是这样做的,第一部分代码(简称:bootloader),什么也不配置,就是默认运行在 0x8000000地址
bootloader 代码主要做的就是串口接收程序文件(简称APP,注意是bin文件哈),然后把程序bin文件写到指定的Flash地址,写完之后,跳转到这个地址执行
不过呢!APP代码除了上面说的是下载bin文件以外,还需要配置
我先说明 APP程序写到哪个地址其实和bootloader程序有关
注意没

咱的bootloader 程序需要占用10KB的空间,也就是说
10KB = 10*1024 = 10240字节 = 0x2800

那么咱的APP程序一开始写入的地址必须大于 0x8002800
如果写入的地址占用了bootloader的地址,那么程序就崩了
我的bootloader 代码主要做的就是串口接收程序文件(简称APP,注意是bin文件哈),然后把程序bin文件写到指定的Flash地址,写完之后,跳转到这个地址执行,你可不能让这个代码崩....程序一开始就是执行bootloader,如果这个程序有问题了,整个就崩了...
现在看用户程序的其它配置
假设我想让APP个程序运行在0x8004000地址,那么需要让软件生成可以运行在这个地址的bin文件才可以,所以

默认是0x8000000
还需要修改下SIZE,上面写的是0x10000 也就是65536字节 = 64KB 我用的单片机是C8T6哈,Flash就是64KB的
咱改为 0x8004000
0x4000 就是 16384字节 其实整个FLASH还剩下 65536 - 16384 = 49152 字节 也就是 0xC000

好,现在生成的程序就是可以运行在 0x8004000的程序了
但是呢还有个问题!
中断问题!
咱可以在bootloader MAP文件里面看到


往下还有各种中断
如果咱不在APP程序里面做一下设置,那么APP程序里面的中断其实会跳进 bootloader 里面(假设bootloader 也使用了一样的中断)
这个我的视频会给大家演示
咱需要让APP里面生成自己单独的一套中断
所以呢咱需要设置下中断向量偏移,一般都是咱的APP程序相对于Flash地址偏移了多少,咱就设置中断向量偏移多少
SCB->VTOR = FLASH_BASE | 0x4000;
这样的话,所有的APP里面分配的中断函数地址最起码是在0x8004000地址的基础上的

其实现在APP程序就准备好了,
不过大家百度STM32 IAP,有很多人在bootloader里面这样写
if(((*(vu32*)(UpdateAddrCopy+4))&0xFF000000)==0x08000000 && ((*(vu32*)UpdateAddrCopy)&0x2FFE0000)==0x20000000)
这就是对接收bin数据的(看的bootloader的bin数据) 

这两个位置进行判断
前面的四位是说明咱的整个程序占用的RAM空间最高地址 注意:STM32是小端模式,低位存在低位,高位存在高位
所以上面的是 0x20000978
大家应该知道咱的全局变量和局部变量都是存在RAM里面的

咱的STM32 RAM的首地址是0x20000000 我的后面是0x5000 = 20480字节 = 20KB (20480/1024)
咱可以看一下那个MAP

其实咱知道咱用的RAM空间是 0x20005000
其实在细致一点就是判断高16位是不是 0x2000 然后低16位是不是小于0x5000
而程序中只是 ((*(vu32*)UpdateAddrCopy)&0x2FFE0000)==0x20000000
然后还有个 ((*(vu32*)(UpdateAddrCopy+4))&0xFF000000)==0x08000000
大家看MAP文件
bootloader 的MAP文件为例

0x08001F35

实际上这个Flash地址里面存储的是复位中断入口地址,得到这个地址以后执行复位中断服务程序
复位中断入口地址是0x08001F35
这个数据存在了 Flash的 0x08000004 (1F35) 和 0x08000006 (0800) 地址里面
注意:所有的中断入口地址都存在了Flash里面,咱定义的函数的入口地址也是在Flash里面
咱编译的时候,软件就给中断函数和咱写的普通函数分配空间 (从0x08000XXX)开始分,注意不是从0x08000000开始哈,具体前面的空间具体给谁我也不知道,但是呢!看上面就知道第一个32位(0x08000000 - 0x08000003),存储的是堆栈栈顶地址(整个程序占用的RAM空间最高地址)
第二个32位(0x08000004 - 0x08000007) 存储的是复位中断入口地址
可以看下MAP,这是分配的地址

分完以后函数的首地址就有了
然后再把这些地址存到Flash里面,从0x08000000开始存
不过Cortex-M3内核规定,Flash起始地址必须存放堆顶指针,而第二个地址则必须存放复位中断入口向量地址
其它的我就不知道按照什么规则存了
当然后面的

不可屏蔽中断,就是说系统出现了不可挽回的错误的时候会进去这个中断

还有

硬件错误中断,像数组越界,内存溢出等等都会进去

然后,发现后面基本上都是各种中断函数...如果大家想判断的更准确的话,就多判断几个08
其实各种中断函数的地址都存在了Flash里面,由于一开始是初始化各种中断,所以才出现这么多08

接收完程序就可以跳转了

其实呢跳转是固定形式,上面有注释
所有涉及到的主要的IAP知识点就说完了
现在说下我的源码思路
我为了方便我修改用户程序软件上的配置

我设置的bootloader使用了16K,实际上我的bootloader只用了10K

其实只要内存充足,自己愿意定义多少就定义多少,前提看APP程序占用多少空间,只要预留的够APP使用就可以

总共 64K 去掉 16K 还有 48K...足够用
然后我再主函数里面打印了一下


其实就对应用户程序

这样方便一点
bootloader函数接收到 updata start以后先擦除APP程序所用的Flash地址空间

然后咱发bin数据的时候

环形队列: https://www.cnblogs.com/yangfengwu/p/11670917.html
环形队列实际上就是用一些函数操作数组,可以一边往里面存数据,一边取数据

我就是用5字节大小的数组,来接收的APP程序(21K),然后写入Flash

由于读环形队列然后写入其实挺快的,有时候串口接收数据的速度赶不上,所以


其实就是类似于空闲中断,10ms的时间内串口都没有接收到数据,就认为接收到一条完整的数据

其实用户程序也就是上面说的那些配置
来吧!说说这节升级程序的BUG
来吧!说说这节升级程序的BUG
来吧!说说这节升级程序的BUG
记住一句话: BootLoader 程序里面设置的硬件配置,中断配置在跳转到APP程序里面的时候同样有效!!!!
除非APP里面重写硬件配置,中断配置,否则,还是默认运行的BootLoader里面配置的
所以,看一下BootLoader函数里面的

而,用户程序里面

实际上BootLoader里面的

在加载用户程序的过程中还在运行,
由于加载用户程序的时候会重新分配RAM,
导致了BootLoader定时器里面的用到的那些变量没有了,
那么执行用户程序就可能造成死机,
注意:不是用户程序导致的死机,而是由于运行BootLoader里面的定时器中断里面的程序导致的死机
因为变量没有了,所以程序执行就崩溃了.
但是大家测试这节的时候发现并没有死机,
我认为原因是加载用户程序的时候及时的重新重新配置了 延时函数

大家可以把这个函数往后放放试一试.
解决方法
首先要明确: 凡是BootLoader程序里面用到的中断函数,在用户程序里面都需要重写

可以什么也不干,但是必须写上
最好的方式是凡是BootLoader里面用到的中断函数,用户程序全部重新写一遍.可以不用,但是必须重写!
ESA2GJK1DH1K升级篇: IAP详解的更多相关文章
- Mysql高手系列 - 第8篇:详解排序和分页(order by & limit),及存在的坑
这是Mysql系列第8篇. 环境:mysql5.7.25,cmd命令中进行演示. 代码中被[]包含的表示可选,|符号分开的表示可选其一. 本章内容 详解排序查询 详解limit limit存在的坑 分 ...
- Mysql高手系列 - 第9篇:详解分组查询,mysql分组有大坑!
这是Mysql系列第9篇. 环境:mysql5.7.25,cmd命令中进行演示. 本篇内容 分组查询语法 聚合函数 单字段分组 多字段分组 分组前筛选数据 分组后筛选数据 where和having的区 ...
- Mysql高手系列 - 第14篇:详解事务
这是Mysql系列第14篇. 环境:mysql5.7.25,cmd命令中进行演示. 开发过程中,会经常用到数据库事务,所以本章非常重要. 本篇内容 什么是事务,它有什么用? 事务的几个特性 事务常见操 ...
- 小白进阶之Scrapy第六篇Scrapy-Redis详解(转)
Scrapy-Redis 详解 通常我们在一个站站点进行采集的时候,如果是小站的话 我们使用scrapy本身就可以满足. 但是如果在面对一些比较大型的站点的时候,单个scrapy就显得力不从心了. 要 ...
- 学会Git玩转GitHub(第一篇) 入门详解 - 精简归纳
学会Git玩转GitHub(第一篇) 入门详解 - 精简归纳 JERRY_Z. ~ 2020 / 9 / 25 转载请注明出处!️ 目录 学会Git玩转GitHub(第一篇) 入门详解 - 精简归纳 ...
- 学会Git玩转GitHub(第二篇) 入门详解 - 精简归纳
学会Git玩转GitHub(第二篇) 入门详解 - 精简归纳 JERRY_Z. ~ 2020 / 10 / 25 转载请注明出处!️ 目录 学会Git玩转GitHub(第二篇) 入门详解 - 精简归纳 ...
- 学会Git玩转GitHub(第三篇) 入门详解 - 精简归纳
学会Git玩转GitHub(第三篇) 入门详解 - 精简归纳 JERRY_Z. ~ 2020 / 10 / 25 转载请注明出处!️ 目录 学会Git玩转GitHub(第三篇) 入门详解 - 精简归纳 ...
- 《手把手教你》系列技巧篇(三十一)-java+ selenium自动化测试- Actions的相关操作-番外篇(详解教程)
1.简介 上一篇中,宏哥说的宏哥在最后提到网站的反爬虫机制,那么宏哥在自己本地做一个网页,没有那个反爬虫的机制,谷歌浏览器是不是就可以验证成功了,宏哥就想验证一下自己想法,于是写了这一篇文章,另外也是 ...
- 《手把手教你》系列技巧篇(三十六)-java+ selenium自动化测试-单选和多选按钮操作-番外篇(详解教程)
1.简介 前边几篇文章是宏哥自己在本地弄了一个单选和多选的demo,然后又找了网上相关联的例子给小伙伴或童鞋们演示了一下如何自动化测试,这一篇宏哥在网上找了一个问卷调查,给小伙伴或童鞋们来演示一下.上 ...
随机推荐
- 使用Django创建RESTful API
Agenda 1.What is an api Api refers to application programming interface It is a set of subroutine de ...
- AngularJS入门Demo
1 :表达式 <html> <head> <title>入门小Demo-1</title> <script src="angular.m ...
- IDEA整合GIT所有操作
IDEA整合GIT操作 1.1 配置Idea集成Git 1.2 在使用SSH key 创建公钥私钥,上传公钥到github (1).点击开始菜单-->所有程序--->git选择 Git B ...
- Makefile的简洁模版
博客地址:http://www.cnblogs.com/zengjianrong/p/4184854.html 为了方便编译零碎的测试代码,在代码的存放目录编辑了一个Makefile,添加新代码文件后 ...
- c++小学期大作业攻略(五)基于QSS的样式美化
这回真的是最后一篇了. 前面说过,我们开发过程中暂时不搭理样式问题,等最后再一起处理,那么现在就是最后处理时刻了!看到网上说QSS跟CSS差不多,我还觉得自己可以干回老本行了,结果用起来发现,QSS是 ...
- Android Studio Analyze APK 一直显示 Parsing Manifest探因及解决
一.背景 大家都知道,Android Studio开发工具自带了Analyze Apk,可以很方便的分析Apk文件.具体位于菜单build >> Analyze APK...路径下,点击后 ...
- WPF ResourceDictionary XAML资源 c#代码 获取与遍历
使用C#代码来获取XAML资源,除去正常的FindResource.而且是能查询到资源的对象. 说实话还是很麻烦的. 比如说我现在有一堆静态资源放在xaml的资源中,我想通过绑定的方式来获取. 好比是 ...
- 外网IP和内网IP区别
外网IP和内网IP区别? 网络结构 如图,假设我们的计算机现在就是设备一,我们想要访问百度.如果我们正使用着校园网,那么首先我们需要先通过校园网的路由器把我们的内网ip转为校园网的外网ip.然后通过这 ...
- 后台数据转换成Excel,前台下载
<dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactI ...
- Qt高仿Excel表格组件-支持冻结列、冻结行、内容自适应和合并单元格
目录 一.概述 二.效果展示 三.实现思路 1.冻结行.冻结列 2.行高自适应 3.蚂蚁线 四.测试代码 1.添加表格数据 2.设置冻结行.列 3.行高.列宽 4.单元格背景色 5.单元格文字 6.其 ...