源码下载链接:

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. html+css底部自动固定底部

    前端在切图过程中,肯定遇见过这种情况. 页面结构由三个部分组成,头部.内容.底部. 当一个页面的内容没撑满屏幕时,底部是跟着内容而并列存在的. 这个时候如果是大屏的话,底部下面会有多余的空白区域,而网 ...

  2. 极化SAR图像基础知识(2)

    本篇主要关注物理含义 1.极化 电磁波在传播时,传播的方向和电场.磁场相互垂直,我们把电波的电场方向叫电波的极化.(i.e.依据电场E的方向来定义电磁波的极化). 如果电场矢量端点随时间变化的轨迹是一 ...

  3. 手把手教做单点登录(SSO)系列之一:概述与示例

    本系列将由浅入深的结合示例.源码以及演示视频,手把手的带大家深入最新的单点登录SSO方案选型与架构开发实战.文末附5个满足不同单点登录场景的gif动画演示(如果看不清请在图片上右键用新窗口打开),本系 ...

  4. JavaScript中undefined 和not defined

    首先呢,我们来介绍undefined,xx is not defined的区别 (创建一个html文件,在头部编写JavaScript代码) 我们先编写如下代码: <script type=&q ...

  5. HTML5 拖放(Drag 和 Drop)功能开发——基础实战

    随着HTML5的普及度越来越高,现在写代码也遇到一些了,经过同事的点播开展了一次Dojo活动用以技术交流,我也乘此机会将HTML5的拖放功能整理了一下. 简介 拖拽(Drag/Drop)是个非常普遍的 ...

  6. 详解Java动态代理机制(二)----cglib实现动态代理

    上篇文章的结尾我们介绍了普通的jdk实现动态代理的主要不足在于:它只能代理实现了接口的类,如果一个类没有继承于任何的接口,那么就不能代理该类,原因是我们动态生成的所有代理类都必须继承Proxy这个类, ...

  7. IOS中的JSON数据的解析

    解析Json数据 //加载.json文件 NSString *path = [[NSBundle mainBundle]pathForResource:@"product.json" ...

  8. poj 1008

    #include<iostream>#include<string> using namespace std;string hname[19] = { "pop&qu ...

  9. Numpy的使用

    Numpy的主要功能: 可以观察以上的规律,会发现,代码类型的简写,计量都是以8作为起始1的. # -*- coding: utf-8 -*- #向量相加-Python def pythonsum(n ...

  10. php学习之目录

    一. 关于php中dirname(_file_)的使用 php中定义了一个很有用的常数,即 __file__ 这个内定常数是当前php程序的就是完整路径(路径+文件名). 即使这个文件被其他文件引用( ...