关于STM32 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/6822984.html
环形队列实际上就是用一些函数操作数组,可以一边往里面存数据,一边取数据

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

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


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

其实用户程序也就是上面说的那些配置
大家有不明白的再问吧.
关于STM32 IAP的更多相关文章
- stm32 IAP + APP ==>双剑合一
(扩展-IAP主要用于产品出厂后应用程序的更新作用,上一篇博文详细的对IAP 升级程序做了详细的分析http://blog.csdn.net/yx_l128125/article/details/12 ...
- STM32 IAP 固件升级设计/U盘升级固件
源:STM32 IAP 固件升级设计/U盘升级固件 固件升级的基本思路是: 将stm32 的flash划分为两个区域: 1.Bootloader区:存放bootloader的代码,bootloader ...
- stm32 IAP + APP ==>双剑合一(转)
源:http://blog.csdn.net/yx_l128125/article/details/13591743 (扩展-IAP主要用于产品出厂后应用程序的更新作用,上一篇博文详细的对IAP 升级 ...
- STM32 IAP 在线升级详解(转)
源:http://blog.csdn.net/yx_l128125/article/details/12992773 (扩展-IAP主要用于产品出厂后应用程序的更新作用,考虑到出厂时要先烧写IAP ...
- STM32 IAP docs
/********************************************************************************* * STM32 IAP docs ...
- STM32 IAP升级
STM32 IAP在线升级,用Jlink设置读保护后前5K字节是默认加了写保护的,导致IAP升级时擦除和写入FLASH不成功,可以做两个boot,前5k为第一个boot程序,上电时负责跳转到APP还是 ...
- STM32+IAP方案 实现网络升级应用固件
关注了这个概念有些日子了,这段时间总算有机会实战==网络升级应用固件,这里记录下遇到的问题,及解决方案. 原理与网上流传的串口作为传输手段 一致:不同之处,无非我这里使用了网络设备传输.==(lwip ...
- STM32 IAP程序 源码 和测试代码 有详细的中文注释
http://bbs.21ic.com/forum.php?mod=viewthread&tid=588265&reltid=624002&pre_pos=2&ext= ...
- 【转载】STM32 IAP 在线升级详解
(扩展-IAP主要用于产品出厂后应用程序的更新作用,考虑到出厂时要先烧写IAP 再烧写APP应用程序要烧写2次增加工人劳动力基础上写了“STM32 IAP+APP ==>双剑合一”链接稍后 ...
随机推荐
- css 实现旋转八卦图
虽然这不算什么亮点,不过也可以供路上的小伙伴学习下 直接上干货: <!doctype html> <html lang="en"> <head> ...
- 浅谈echo、print、var_dump()、print_r()的区别
1.echo 和 print 的区别 共同点:首先echo 和 print 都不是严格意义上的函数,他们都是语言结构;他们都只能输出 字符串,整型跟int型浮点型数据.不能打印复合型和资源型数据: 而 ...
- Sql日期时间格式转换大全
简介:我们经常会用到sql日期转换,这里列出了日期输出为字符串的所有代码 输出格式 2014-06-12 ), ) 输出格式 2014-06-12 22:31:18 ), ) 以下是各种转换日期代码号 ...
- html的常用基础应用
HTML结构 如下一段最简单的HTML代码:<html> <head> <title>HTML页面</title> ...
- 项目中如何使用babel6详解
由于浏览器的版本和兼容性问题,很多es6,es7的新的方法都不能使用,等到可以使用的时候,可能已经过去了很多年.Babel可以把es6,es7的新代码编译成兼容绝大多数的主流浏览器的代码. 本篇文章主 ...
- javascript——数据类型
在内存中,分为栈.堆.代码段.静态区,为了快速处理复杂的代码,在不同的区间储存不同的数据类型. 数据类型分为初始类型与引用类型,初始类型在栈中存储,变量赋值传值不传址,引用类型在堆中存储,传址不传值. ...
- win7下安装memcached出现failed to install service or service already installed解决办法
安装memcached时总是提示“failed to install service or service already installed”,开始以为是版本问题,就下了好几个不同版本,可还是老问题 ...
- JTextArea自动换行以及设置滚动条
应将JTextArea置于JScrollPanel中若要使只有垂直滚动条而没有水平滚动条,使用JTextArea.setLineWrap(true),自动换行. 文本换行代码片段如下: JTextAr ...
- Java计算两个程序运行时间
一.获取系统当前时间 long startTime = System.currentTimeMillis(); //获取开始时间 doSomething(); //测试的代码段 long endTim ...
- Java中的多线程Demo
一.关于Java多线程中的一些概念 1.1 线程基本概念 从JDK1.5开始,Java提供了3中方式来创建.启动多线程: 方式一(不推荐).通过继承Thread类来创建线程类,重写run()方法作为线 ...