tangcdong 发表于 2012-11-22 10:09:24

基于STM32F103VE单片机IAP的实现

1、STM32F103VE每页大小为2K。
   (1)、整个ROM 空间分为四个部分:
    三个程序区: Boot程序、用户程序、IAP升级程序备份
    一个标志区: 用户程序标志
    a、 Boot程序地址:             0x08000000-0x080027FF      0-4页       共10k       用于程序升级并判断是否有有效程序并跳转到0x08002804   处运行程序
    b、 用户程序地址:             0x08002800-0x080347FF      5—104页   共200k      用户程序
    c、 IAP升级程序备份地址:0x08034800-0x080667FF   105—204页共200k   用于IAP对用户程序进行升级
    d、 程序标志地址:       0x08070000-0x080703FF   224页       共2k         保存用户程序是否已经写入标志只有最低四个字节有用。
    (2)、RAM分为三个部分:
    a、0x20000000-0x200013FF    共5K               用于Boot程序变量使用
    b、0x20001400-0x2000EFFF    共60K             用于应用程序变量使用

2. 程序更新过程
    (1)、加电后先进入0x0800 0004 Boot程序区
    (2)、判断是否有升级程序命令,如果有则进行程序升级,如果3S之内没有升级程序命令,判断224页(0x08070000--0x080703FF)的值进行相应的跳转或不跳转。
    a、(0x08070000-- 0x08070003)的值为0x0000 0001,则跳转到地址0x08002804处开始执行程序,此地址为应用程序的起始地址。
    b、(0x08070000-- 0x08070003)的值不为0x0000 0001,则等待升级命令。
   (3)、注意事项1、应用程序的向量表偏移地址需改为0x2800(NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x2800);)2、在我的程序里面加入应用程序的时候总中断是屏蔽的,在应用程序中需打开总中断。
3、贴出源代码(里面总共有三部分1、BOOT代码2、带ucos应用程序代码3、VC6.0编写的简单升级程序)

meme1oo 发表于 2012-11-22 10:38:51

顶贴,沙发!!!!!

abnerle 发表于 2012-11-22 13:29:37

10K有点小,我的boot文件占60K,boot里面驱动了一些有用的外设

xyz2008 发表于 2012-11-22 13:32:34

本帖最后由 xyz2008 于 2012-11-22 13:36 编辑

楼主是用这个软件升级吗,升级完了有提示吗,我这边怎么报错了,有图为证

xyz2008 发表于 2012-11-22 13:37:51

本帖最后由 xyz2008 于 2012-11-22 13:39 编辑

点编程怎么就出错了

xyz2008 发表于 2012-11-22 13:44:27

怎么没有选择烧写文件的对话框啊,郁闷,真不知道怎么用楼主的东西

xyz2008 发表于 2012-11-22 13:44:44

怎么没有选择烧写文件的对话框啊,郁闷,真不知道怎么用楼主的东西

tangcdong 发表于 2012-11-22 14:50:30

xyz2008 发表于 2012-11-22 13:44 static/image/common/back.gif
怎么没有选择烧写文件的对话框啊,郁闷,真不知道怎么用楼主的东西

我只是简单写了个下载的程序点击编程的时候直接读取里面的bin文件然后通过串口与下位机通讯。{:smile:}

xyz2008 发表于 2012-11-22 15:52:17

楼主要是能完善一下程序,加上选择文件的对话框,加上烧写的进度条,界面再好看点就造福大众了,可惜本人不懂上位机程序

tangcdong 发表于 2012-11-23 09:44:41

这个的话对于会VC编程的人来说是很容易的事,我这里只是简单测试了一下,具体应用的时候可以再修改。本人VC编程实力也有限啊,工作时候也很少用......

mint 发表于 2012-12-19 19:33:11

楼主有没有试过通过网口来IAP~~~

eehong 发表于 2012-12-19 21:35:15

建议楼主改用其他方案实现,这样的安排学习还行,实际使用起来太浪费了,512k的ROM,实际应用程序只有200k空间可用。可以将程序备份区放在外部FLASH中,提高MCU本身FLASH的使用价值。

eehong 发表于 2012-12-19 21:36:07

不过还是要强力顶起,哈哈

Onsunsl 发表于 2012-12-20 11:21:32

优化一下iap,放到小片子里用

和为和 发表于 2012-12-21 08:49:14

学习了,谢谢楼主!

coslight_dt 发表于 2012-12-21 09:26:05

学习了,谢谢楼主!

tangcdong 发表于 2013-1-14 12:47:29

呵呵,我放上去主要的目的是为IAP还在迷茫中的同志提供一种实现方式,只要理解了它的过程具体怎么实现就不难了,如楼上说的通过网口或者外接flash什么的都可以实现。{:smile:}

tangcdong 发表于 2013-1-14 12:57:27

mint 发表于 2012-12-19 19:33 static/image/common/back.gif
楼主有没有试过通过网口来IAP~~~

其实使用网口比串口更简单,可以少去帧头帧尾及校验等判断,你只要调通网口的驱动及uip使用方法基本完成了一大半了。

caesar_song 发表于 2013-1-14 13:13:34

lqf343122 发表于 2013-1-24 17:22:21

正在学习stm32怎样IAP,谢谢了!!

工程师030 发表于 2013-1-24 18:05:53

其实我一直有点好奇,这两段程序既然是完全独立的,那么ram的地址为何还要重新分配呢,反正跳至用户程序区,iap的ram也不需要了,楼主可以解答一下吗?

redroof 发表于 2013-1-24 20:20:32

其实无需iap程序备份区,只要给程序带个校验码就行了。如果下载一半断电,下次就自动停在boot里,等待再次下载

tangcdong 发表于 2013-1-31 08:03:13

工程师030 发表于 2013-1-24 18:05 static/image/common/back.gif
其实我一直有点好奇,这两段程序既然是完全独立的,那么ram的地址为何还要重新分配呢,反正跳至用户程序区 ...

如果你确定都没有什么初始赋值的变量,理论上是可以共用的。

tangcdong 发表于 2013-1-31 08:08:49

redroof 发表于 2013-1-24 20:20 static/image/common/back.gif
其实无需iap程序备份区,只要给程序带个校验码就行了。如果下载一半断电,下次就自动停在boot里,等待再次 ...

是啊。带个IAP程序备份区的好处就是升级失败后还可以继续使用。工程应用中如果此次升级失败而且没有供电的状态可以过段时间来升级,控制板还可以继续使用以前的应用程序。

xizi 发表于 2013-2-6 21:05:02

比原厂的IAP有改进,增加了备份区。

arefeng 发表于 2013-2-16 17:16:59

工程师030 发表于 2013-1-24 18:05 static/image/common/back.gif
其实我一直有点好奇,这两段程序既然是完全独立的,那么ram的地址为何还要重新分配呢,反正跳至用户程序区 ...

是不是考虑了堆栈的问题?我觉得在应用程序中重新初始化堆栈的话,应该是可以的

tangcdong 发表于 2013-2-19 14:10:55

xizi 发表于 2013-2-6 21:05 static/image/common/back.gif
比原厂的IAP有改进,增加了备份区。

原厂的IAP还要去设置BOOT引脚,感觉不是很方便。本文的IAP就不用设置,不过要在应用程序中添加解析命令的代码。

linh05 发表于 2013-4-24 22:04:13

mark一下。{:smile:}

jackmo 发表于 2013-5-7 14:45:36

STM32 IAPNO OS

syaoraner 发表于 2013-5-8 21:06:42

一定会好好学习的!!!

yuanye1127 发表于 2013-7-5 14:25:27

mark 马上就要用到新项目上 , 还不太明白~~学习一下,谢谢楼主

Maurice 发表于 2013-7-8 10:29:28

MARK! 正在倒腾IAP,感谢楼主分享

nuncle 发表于 2013-7-8 21:21:57

mark 马上要用到。。 收藏了 牛逼

竹云万里 发表于 2013-8-10 13:35:55

好样的,学习了。谢谢。

wazhiyi 发表于 2013-8-10 13:59:10

{:lol:}{:lol:}{:lol:}{:lol:}

tangcdong 发表于 2013-8-12 08:08:26

竹云万里 发表于 2013-8-10 13:35 static/image/common/back.gif
好样的,学习了。谢谢。

初来咋到!

xiefy21 发表于 2013-8-13 22:50:30

mark……
顶一个…

竹云万里 发表于 2013-8-16 09:27:05

tangcdong 发表于 2013-8-12 08:08 static/image/common/back.gif
初来咋到!

不是。正巧要做这个,遇到了点问题,就来拜读楼主的帖子啦。现在上位机通信还有点问题。呵呵。{:smile:}

gdmgb520 发表于 2013-8-16 16:27:26

我们是通过GPRS远程IAP

tangcdong 发表于 2013-8-17 13:34:10

竹云万里 发表于 2013-8-16 09:27 static/image/common/back.gif
不是。正巧要做这个,遇到了点问题,就来拜读楼主的帖子啦。现在上位机通信还有点问题。呵呵。...

呵呵,努力努力问题终究都会解决的。

tangcdong 发表于 2013-8-17 13:39:06

gdmgb520 发表于 2013-8-16 16:27 static/image/common/back.gif
我们是通过GPRS远程IAP

好样的!GPRS远程升级不知道稳不稳定,还有就是升级速度怎么样?

gdmgb520 发表于 2013-8-17 14:51:37

tangcdong 发表于 2013-8-17 13:39 static/image/common/back.gif
好样的!GPRS远程升级不知道稳不稳定,还有就是升级速度怎么样?

我们使用FTP下载方式,速度方面是可以接受的,APP程序也就一百多K,稳定性主要靠文件校验来保障。

wch54403 发表于 2013-9-3 22:14:19

{:smile:} xuexi

冰雪王爵 发表于 2013-9-3 23:52:42

qinshiysb 发表于 2013-10-29 08:47:07

好东西、

sinc_mark 发表于 2013-10-29 09:10:01

gdmgb520 发表于 2013-8-17 14:51 static/image/common/back.gif
我们使用FTP下载方式,速度方面是可以接受的,APP程序也就一百多K,稳定性主要靠文件校验来保障。 ...

想问问,你们的GPRS方式IAP实现了吗?对于GPRS的远程升级,好像实现起来比较麻烦,不知道效果怎么样了?

gdmgb520 发表于 2013-10-30 17:21:54

sinc_mark 发表于 2013-10-29 09:10 static/image/common/back.gif
想问问,你们的GPRS方式IAP实现了吗?对于GPRS的远程升级,好像实现起来比较麻烦,不知道效果怎么样了? ...

我们已经实现了

isakura 发表于 2013-11-15 12:49:10


#define ApplicationAddress 0x08002800

那么这个
if (((*(__IO uint32_t*)ApplicationAddress) & 0x2FFE0000 ) == 0x20000000)
是什么意思?怎么理解

tangcdong 发表于 2013-11-15 13:47:37

isakura 发表于 2013-11-15 12:49 static/image/common/back.gif
#define ApplicationAddress 0x08002800

那么这个


第一个是堆栈地址,而堆栈地址在RAM区中,这里用来判断是否已经有应用程序

isakura 发表于 2013-11-15 16:13:14

tangcdong 发表于 2013-11-15 13:47 static/image/common/back.gif
第一个是堆栈地址,而堆栈地址在RAM区中,这里用来判断是否已经有应用程序 ...

谢谢,可是我还是有些不明白,请指点下

ApplicationAddress这个是地址,程序的入口地址,

(*(__IO uint32_t*)ApplicationAddress) 这个是就是读取这个地址的值,这个值是什么意思??

那么 0x2FFE0000 是什么?是一个地址还是一个值?是一个值那是怎么定出来的?


JumpAddress = *(__IO uint32_t*) (ApplicationAddress + 4);   这一步是 取这个地址里面的值?

Jump_To_Application = (pFunction) JumpAddress;   这个是类型转换,吧这个值作为函数地址

__set_MSP(*(__IO uint32_t*) ApplicationAddress);    设置main的函数地址?地址就是*(__IO uint32_t*) ApplicationAddress   ???

这两个可以省略?
__set_CONTROL(0);
__set_PRIMASK(1);

Jump_To_Application();   //跳转到 Jump_To_Application 函数? 为什么不是 main 函数?

tangcdong 发表于 2013-11-15 16:47:27

本帖最后由 tangcdong 于 2013-11-15 17:00 编辑

isakura 发表于 2013-11-15 16:13 static/image/common/back.gif
谢谢,可是我还是有些不明白,请指点下

ApplicationAddress这个是地址,程序的入口地址,


你看看RAM的大小,我的例程里对应单片机RAM的大小为65K,十六进制为0x10000;RAM区起始地址为0x2000 0000;你在回头看0x2FFE0000就什么都明白了。(*(__IO uint32_t*)ApplicationAddress) -(*(__IO uint32_t*)(ApplicationAddress+3)) 这个是向量表里最前面的是4个字节(堆栈的地址),(*(__IO uint32_t*)(ApplicationAddress+4))-(*(__IO uint32_t*)(ApplicationAddress+7)) 是复位时程序的入口地址,单片机运行时最先从这里开始运行的。

tangcdong 发表于 2013-11-15 16:48:43

isakura 发表于 2013-11-15 16:13 static/image/common/back.gif
谢谢,可是我还是有些不明白,请指点下

ApplicationAddress这个是地址,程序的入口地址,


程序在跳转到main()函数之前还有很多事要做,具体做什么你可以看看启动代码。

loves6036 发表于 2013-11-17 19:14:14

谢谢楼主分享!!!

miniqq80 发表于 2013-11-26 16:18:50

看了好几天资料了,很晕

三毛杨 发表于 2014-1-26 11:15:43

正准备通过网络进行IAP操作,学习一哈!!!

tangcdong 发表于 2014-2-7 10:29:08

本帖最后由 tangcdong 于 2014-2-7 10:30 编辑

三毛杨 发表于 2014-1-26 11:15
正准备通过网络进行IAP操作,学习一哈!!!

呵呵,各种升级!我也弄过TFTP升级。

jingwaner 发表于 2014-2-7 10:33:20

非常赞!

三毛杨 发表于 2014-2-8 10:07:35

tangcdong 发表于 2014-2-7 10:29
呵呵,各种升级!我也弄过TFTP升级。

我还处于尝试阶段,空了可以交流一下!QQ:401459470

xjtyOnly51 发表于 2014-4-17 14:48:00

thanks for share

cy_ygs 发表于 2014-4-25 14:32:41

好资料,mark

wyang0824 发表于 2014-4-27 23:13:29

时间有点长了 扒出来看看!

tlsmf 发表于 2014-5-6 15:19:30

mark                              

tangcdong 发表于 2014-6-17 13:19:48

好久没来了,修改一下上位机软件.

tangcdong 发表于 2014-6-17 13:25:39

添加了文件选择按钮,自动探测可用串口,编程进度条以及接受数据的显示.有感官上需求的可以参考一下.

pangweishen 发表于 2014-6-18 12:55:30

MARK{:loveliness:}{:loveliness:}{:loveliness:}{:loveliness:}{:loveliness:}

tangcdong 发表于 2014-6-19 16:39:04

更新上位机软件升级完后出现异常的问题,并添加出错以及完成提示!

tangcdong 发表于 2014-6-19 16:39:42

pangweishen 发表于 2014-6-18 12:55
MARK

欢迎!{:smile:}

philix 发表于 2014-6-30 22:37:02

楼主真是有心人。

ranyanhao 发表于 2014-7-2 21:40:10

先MARK,楼主有心了

casn 发表于 2014-7-24 17:46:52

楼主是个热心人!

请问楼主,我在做IAP时,开机第一次进入IAP时,超时就进入APP,一点问题都没有,然后在APP里接收到CAN口命令,再次跳转到IAP也没有问题,于是在IAP里不断接收APP的bin文件,接收完成后程序软复位,再次进入IAP程序,到这里也一点问题都没有,可是无论我怎么调试,就是无法进入升级后的APP,哪怕重新开机也没有用(数据确保已经写入APP的FLASH首地址处,读出打印对比过)。只能再烧一遍APP,才会正常,也就是说IAP是没有成功的,我的APP程序是UCOS系统,是不是带系统和不带系统有什么讲究啊?郁闷中。。。。

zcbAzfl 发表于 2014-7-30 13:25:33

狂顶楼主,好样的,正好用到,研究研究……

tangcdong 发表于 2014-8-1 08:04:45

本帖最后由 tangcdong 于 2014-8-1 08:06 编辑

casn 发表于 2014-7-24 17:46
楼主是个热心人!

请问楼主,我在做IAP时,开机第一次进入IAP时,超时就进入APP,一点问题都没有,然后在A ...

你如果带操作系统的话,在跳转的时候加句__set_CONTROL(0);转到特权模式。同时把所有的外设中断屏蔽掉,在应用程序中再打开中断。

GunGun 发表于 2014-8-1 08:51:52

这个可以参考一下。

zdhxzy1981 发表于 2014-8-1 08:53:46

四个区大小可以自己调整吗?

tangcdong 发表于 2014-8-1 09:03:18

zdhxzy1981 发表于 2014-8-1 08:53
四个区大小可以自己调整吗?

随便设置!{:smile:}

zdhxzy1981 发表于 2014-8-1 09:09:10

赞一个!!!

casn 发表于 2014-8-1 12:02:20

tangcdong 发表于 2014-8-1 08:04
你如果带操作系统的话,在跳转的时候加句__set_CONTROL(0);转到特权模式。同时把所有的外设中断屏蔽掉, ...

再次谢谢楼主的热心!我解决了问题。

问题原因是在我的擦除函数里,APP的第一个2k区域没有擦除,第二个2k区域擦除了两次,也怪以前没弄过,所以很多技术节点都是匆匆写过,或者因为目标未知的原因,所以容易忽略一些细节。在后来的检查当中,偶尔发现了一个语句的问题。我在这上面耗费了很长时间,都以为是哪个地方少了一句语句或语句顺序有讲究,试了无数次,可还是没结果,解决后心情也是大好。至于断点续传这些都已经完成。现在烧写都是一个集中设备接收bin升级文件,然后通过CAN口统一升级各个子节点设备,比单独烧写子节点设备效率要高好几个数量级了。

coding2011 发表于 2014-8-3 09:05:42

赞一个,比官方的好用

nielili 发表于 2014-9-10 17:18:37

mark,学习了。最近也在弄IAP

xly2014 发表于 2014-11-5 08:59:25

STM32_IAP IAP_BOOT无ucos.rar

32MCU 发表于 2014-11-5 10:11:26

谢谢楼主分享!IAP+上位机 收藏。

dzf050727 发表于 2014-11-6 18:06:49

收藏   楼主好人      

卢台长 发表于 2014-11-6 18:18:45

围观围观

19711972f 发表于 2014-11-8 20:10:21

项目在用无线boot,谢谢分享。

tangcdong 发表于 2014-11-12 10:37:25

19711972f 发表于 2014-11-8 20:10
项目在用无线boot,谢谢分享。

共同研究!

dantes2014 发表于 2014-12-3 14:37:37

x谢谢分享 ,正需要

彼岸花开@ 发表于 2014-12-3 14:46:44

东西很好。。学stm32要学不到这部分,就呵呵了。。

1139193886 发表于 2014-12-3 21:19:27

学习了 谢谢楼主分享

tragedy 发表于 2014-12-3 21:29:15

谢谢楼主。
有点疑问:用户空间地址是:0x08002800,为啥跳转到 0x08002800+4.
还有我是不是可以开辟两个用户空间,放置两个不同的程序。在boot里面选择跳转到那个用户空间执行,这可行么?

tangcdong 发表于 2014-12-4 13:19:59

本帖最后由 tangcdong 于 2014-12-4 13:21 编辑

tragedy 发表于 2014-12-3 21:29
谢谢楼主。
有点疑问:用户空间地址是:0x08002800,为啥跳转到 0x08002800+4.
还有我是不是可以开辟两个用 ...

第一个问题:记得前一个字保存是堆栈栈顶地址   第二个字才是复位入口的地址
第二个问题:是完全可以的

闷鱼 发表于 2015-3-4 09:20:27

{:smile:}{:smile:}{:smile:}{:smile:}{:smile:} 不错

zqy517 发表于 2015-5-10 00:34:48


好东西。谢谢分享!

videofun 发表于 2015-5-21 21:59:37

学习了,谢谢楼主!   

eagle_avr 发表于 2016-8-19 15:16:47

本帖最后由 eagle_avr 于 2016-8-19 15:33 编辑

我用UCOS2.9.2,,也碰到了与77楼类似的问题,当从IAP跳转到app里是,就会进入HardFault_Handler,折磨了我两天没找到问题。
看到楼主说的特权模式,把“__set_CONTROL(0);”加进去,再跳转就OK了:
void CAN_BOOT_JumpToApplication(__IO uint32_t Addr)
{
    pFunction Jump_To_Application;
    __IO uint32_t JumpAddress;
    /检查栈顶地址是否合法(用户代码的第一个字存放的是栈顶地址,即检查此地址)
    //if (((*(__IO uint32_t*)Addr) & 0x2FFE0000 ) == 0x20000000) {        //SRAM=128K
    if (((*(__IO uint32_t*)Addr) & 0x2FFF0000 ) == 0x20000000) {        //SRAM=64K
               
        //用户代码区第二个字为程序开始地址(复位中断向量地址),
        //强制把该地址转化为iapfun类型的函数指针,再赋给函数指针jump2app
      JumpAddress = *(__IO uint32_t*) (Addr + 4);
      Jump_To_Application = (pFunction) JumpAddress;
               
      __set_PRIMASK(1);//关闭所有中断       
      __set_MSP(*(__IO uint32_t*)Addr);        //设置APP堆栈指针(用户代码区的第一个字用于存放栈顶地址)
        __set_CONTROL(0);
      Jump_To_Application();                                ////跳转到APP的复位中断,程序由此开始执行
    }
}
万分感谢!
另外我得去看看,关于特权模式这部分的内容了!!!

xaviersw 发表于 2020-10-24 11:27:54

楼主是个好人
页: [1]
查看完整版本: 基于STM32F103VE单片机IAP的实现