源码下载链接:

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的更多相关文章

  1. stm32 IAP + APP ==>双剑合一

    (扩展-IAP主要用于产品出厂后应用程序的更新作用,上一篇博文详细的对IAP 升级程序做了详细的分析http://blog.csdn.net/yx_l128125/article/details/12 ...

  2. STM32 IAP 固件升级设计/U盘升级固件

    源:STM32 IAP 固件升级设计/U盘升级固件 固件升级的基本思路是: 将stm32 的flash划分为两个区域: 1.Bootloader区:存放bootloader的代码,bootloader ...

  3. stm32 IAP + APP ==>双剑合一(转)

    源:http://blog.csdn.net/yx_l128125/article/details/13591743 (扩展-IAP主要用于产品出厂后应用程序的更新作用,上一篇博文详细的对IAP 升级 ...

  4. STM32 IAP 在线升级详解(转)

    源:http://blog.csdn.net/yx_l128125/article/details/12992773 (扩展-IAP主要用于产品出厂后应用程序的更新作用,考虑到出厂时要先烧写IAP   ...

  5. STM32 IAP docs

    /********************************************************************************* * STM32 IAP docs ...

  6. STM32 IAP升级

    STM32 IAP在线升级,用Jlink设置读保护后前5K字节是默认加了写保护的,导致IAP升级时擦除和写入FLASH不成功,可以做两个boot,前5k为第一个boot程序,上电时负责跳转到APP还是 ...

  7. STM32+IAP方案 实现网络升级应用固件

    关注了这个概念有些日子了,这段时间总算有机会实战==网络升级应用固件,这里记录下遇到的问题,及解决方案. 原理与网上流传的串口作为传输手段 一致:不同之处,无非我这里使用了网络设备传输.==(lwip ...

  8. STM32 IAP程序 源码 和测试代码 有详细的中文注释

    http://bbs.21ic.com/forum.php?mod=viewthread&tid=588265&reltid=624002&pre_pos=2&ext= ...

  9. 【转载】STM32 IAP 在线升级详解

      (扩展-IAP主要用于产品出厂后应用程序的更新作用,考虑到出厂时要先烧写IAP  再烧写APP应用程序要烧写2次增加工人劳动力基础上写了“STM32 IAP+APP ==>双剑合一”链接稍后 ...

随机推荐

  1. ios sqlite3的简单使用

    第一:创建表格 //创建表格 -(void)creatTab{ NSString*creatSQL=@"CREATE TABLE IF NOT EXISTS PERSIONFO(ID INT ...

  2. Spring Boot 中如何使用 Dubbo Activate 扩展点

    摘要: 原创出处 www.bysocket.com 「泥瓦匠BYSocket 」欢迎转载,保留摘要,谢谢! 『 公司的核心竞争力在于创新 – <启示录> 』 继续上一篇:< Spri ...

  3. Nginx反向代理以及负载均衡配置

    项目地址:http://git.oschina.net/miki-long/nginx 前提:最近在研究nginx的用法,在windows上小试了一下,由于windows下不支持nginx缓存配置,所 ...

  4. Unity 相机的聚焦功能

    摘要:本文原创,转载请注明出处 需求: 在游戏的任务编辑场景进行编辑的时候,摄像机需要在多个需要编辑的物体之间来回切换,如果只是用摄像机的移动旋转,对于相对位置较近的物体还好说,当相对位置过远的时候, ...

  5. Android 性能优化——之控件的优化

    Android 性能优化——之控件的优化 前面讲了图像的优化,接下来分享一下控件的性能优化,这里主要是面向自定义View的优化. 1.首先先说一下我们在自定义View中可能会犯的3个错误: 1)Use ...

  6. C语言学习第二章

    今天开始学习常量,变量,基本数据类型,printf()函数和scanf()函数,算术运算符. 首先常量:是在程序中保持不变的量 变量:编写程序时,常常需要将数据存储在内存中,方便后面使用这个数据或者修 ...

  7. 在同一个系统上装两个不同版本的jdk,配置环境变量不起作用,jdk版本的切换问题

    本人这台笔记本前面装了jdk8,现在准备用jdk7,我安装好了jdk7:把系统变量中的JAVA_HOME 改为 D:\java\jdk\jdk7\jdk1.7.0_67,Path 下添加如下变量,记得 ...

  8. 【渗透测试】hydra使用小结

    -R:继续从上一次进度接着破解 -S:大写,采用SSL链接 -s <PORT>:小写,可通过这个参数指定非默认端口 -l <LOGIN>:指定破解的用户,对特定用户破解 -L ...

  9. bzoj1834 [ZJOI2010]网络扩容

    Description 给定一张有向图,每条边都有一个容量C和一个扩容费用W.这里扩容费用是指将容量扩大1所需的费用.求: 1. 在不扩容的情况下,1到N的最大流: 2. 将1到N的最大流增加K所需的 ...

  10. 设计模式的征途—3.抽象工厂(Abstract Factory)模式

    上一篇的工厂方法模式引入了工厂等级结构,解决了在原来简单工厂模式中工厂类职责太重的原则,但是由于工厂方法模式的每个工厂只生产一类产品,可能会导致系统中存在大量的工厂类,从而增加系统开销.那么,我们应该 ...