[ZLG-ARM] 在线升级IAP程序与应用程序编译问题!

[复制链接]
 楼主| liangzisen 发表于 2008-11-14 17:28 | 显示全部楼层 |阅读模式
IAP启动程序和应用程序一起编译或者分开编译!<br />一般编译程序的时候都是应用程序和启动程序一起编译,如果分开编译是不是会产生什么问题,比如两个程序接口问题,合起来编译的话,通过分散加载文件,可以把两部分程序的RO,RW,ZI&nbsp;段分开来吗?<br />如果一起编译,生成的两个映像文件会有关联吗??比如我IAP_CODE.bin负责在线升级和串口数据接收,这部分程序不会有改动,但应用程序是经常变化的,如果应用程序一旦变化,重新编译后,可以以前编译的在线升级程序兼容吗??
zlg_lly 发表于 2008-11-15 08:29 | 显示全部楼层

RE:liangzisen

您好!<br />IAP启动程序和应用程序可以分开编译,这也是通过分散加载文件实现的。我们SmartARM2300和SmartARM2400开发板有提供这种分开编译的模板。
 楼主| liangzisen 发表于 2008-11-15 10:48 | 显示全部楼层

可以给我发个模板吗?

可以给我发个模板吗?<br />liangzisen@yahoo.cn
 楼主| liangzisen 发表于 2008-11-15 10:53 | 显示全部楼层

可以说说你们的思路吗?

周工,可以说说你们的思路吗?
汽车电子 发表于 2008-11-17 10:28 | 显示全部楼层

把用户Boot程序放在main函数里即可

&nbsp;&nbsp;指定程序空间地址,使用1个4KB的块。<br /><br />&nbsp;&nbsp;这样程序每次启动的时候检测是否满足IAP条件,满足即执行IAP,否则执行其它任务程序。<br /><br />&nbsp;&nbsp;如果你的系统有足够的外部存储器,那就更方便了...<br /><br /><br /><br />
 楼主| liangzisen 发表于 2008-11-17 19:58 | 显示全部楼层

把用户Boot程序放在main函数里方法的疑问???

楼上说把用户Boot程序放在main函数里,这样有出现了一个问题!<br />如果程序的架构是BOOT+APP+IAP程序,其中BOOT和IAP程序是固化的!APP是待升级的用户程序,如果是通过分散加载程序来区分这三个程序段,即分三个加载执行区,main函数是绝对得包含在APP加载执行区的,原因如下:<br />楼上说的把用户Boot程序和main绑在一起,一旦APP有变化,BOOT区的里面的RO,RW,ZI部分地址就会有变动,这样程序升级的时候岂不是练BOOT都得重新烧写,那这样IAP远程在线升级就没意义了!
汽车电子 发表于 2008-11-18 12:47 | 显示全部楼层

怎么说呢,这样你应该很清楚了

int&nbsp;&nbsp;&nbsp;&nbsp;main(void)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;指定代码地址<br />{<br />&nbsp;&nbsp;&nbsp;if(需要升级)<br />&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;执行升级程序(可在这里写,也可调用函数,但注意代码地址)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;清除升级相关标志<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;关中断,死循环,让系统重启(需开启看门狗)<br />&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;启动多任务系统,执行用户各个任务<br />&nbsp;&nbsp;&nbsp;<br />}
 楼主| liangzisen 发表于 2008-11-18 15:12 | 显示全部楼层

那你这个软件肯定是通过多个工程分开写的!

我的意思是说你的BOOT和IAP程序写成一个工程,APP另写一个工程,也就是说在FALSH中有两个MAIN函数在跑,一个在BOOT&nbsp;,另一个在APP中!<br />我理解的对吗?因为APP和BOOT写在同一个工程中,共用一个main的话,ADS通过分散加载文件编译连时,当APP程序有所改动,先前固化的BOOT的BIN文件肯定也是有所变化,比如他里面指向APP部分变量和函数的地址就会有变动!<br /><br />楼上说的思路我清楚,我就是有编译连接方面的疑问!怎么让ADS编译时APP模块和BOOT模块完全独立,互补干扰,除了把两个工程分开做的方法(即跑两个main)!
pheavecn 发表于 2008-11-18 16:46 | 显示全部楼层

建两个工程啦。

app对于Boot来说,就是一段存在flash里的数据.
汽车电子 发表于 2008-11-18 17:48 | 显示全部楼层

不用分开多个工程写呀

&nbsp;&nbsp;&nbsp;一个工程即可。<br />&nbsp;&nbsp;&nbsp;假如你main函数里面(包括调用函数)占X字节,那你其它程序代码就从X字节开始&nbsp;(总地址0开始)<br />&nbsp;&nbsp;&nbsp;一般取Flash的整块,2个块(8KB)就够IAP程序了。这部分一写好就不用修改了,永远不变。<br /><br />&nbsp;&nbsp;&nbsp;你要IAP的时候,就把整个Hex文件地址从地址X处开始IAP就可以了。
汽车电子 发表于 2008-11-18 17:56 | 显示全部楼层

不建议使用zlg教程里的方案

&nbsp;&nbsp;&nbsp;把MCU&nbsp;Flash分成两个块,轮流使用。这样会浪费一半的存储空间,MUC成本高,且IAP不方便。<br /><br />&nbsp;&nbsp;&nbsp;建议使用外部存储器,这样IAP简单,硬件成本也低。(可用IIC或SPI接口的)
 楼主| liangzisen 发表于 2008-11-18 18:50 | 显示全部楼层

回复楼上

楼上的思路我是有做过&nbsp;<br />即使IAP(BOOT)+APP&nbsp;&nbsp;&nbsp;&nbsp;IAP(包括MAIN函数)放在:0,1扇区&nbsp;&nbsp;APP放在2-N扇区,这样通过一个分散加载文件来区分这个区的文件连接。<br />这样就是有个问题,当APP改动时,重新编译整个工程后IAP(BOOT)&nbsp;这个区的二进制生成文件就和先前固化的二进制文件不同!&nbsp;这样如果不重新烧写IAP(BOOT)程序的话,单单升级APP程序后,系统重新执行,就会死机,因为先前IAP(BOOT)中对应的APP函数地址和RW,ZI变量地址都和升级后的APP不一样!<br /><br />我的理解系统重启后MAIN函数是负责整个系统环境的初始化的!比如RW,ZI变量的初始化!如下图:
 楼主| liangzisen 发表于 2008-11-18 19:01 | 显示全部楼层

回复楼上

目前我正在使用的方案是:<br />APP+IAP,&nbsp;其中APP放在0x00000000开始的几个扇区,IAP是放在最后一个扇区<br />,APP程序中包括main函数,这样就解决了我上述方案的问题!<br />原因如下:<br />关键点1:MAIN函数放在APP中,这样APP程序有变化,IAP不会改变,编译工程后,二进制对于IAP部分的描述不会改动,所以基本能满足在线升级的功能!&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />关键点2:因为这个方案需要涉及到第一扇区的擦除,所以在IAP程序中需要做中断映射,将第一扇区的前64字节映射到RAM中!<br /><br />我的QQ:273595501&nbsp;可以交流!<br /><br />
zjxzhxzh 发表于 2008-11-19 09:49 | 显示全部楼层

iap

IAP我也曾经遇到过累似的问题,搞了一个星期才搞定,IAP应放在开头0-1区,MAIN函数也要放在IAP中,只不过MAIN里调用了APP,APP从固定地址开始,RW,ZI变量除APP中的变量外全部放在IAP区,这点很重要
zhongyb 发表于 2008-11-19 09:58 | 显示全部楼层

8楼的思路是合理的

13楼的做法有点不同意。<br />容易出现的问题是,如果固件升级过程中出现意外,比如断电,。。。<br /><br />所以还是按照8楼的思路做比较合理,可靠。系统一上点直接进入BOOT(带IAP),然后判断是否需要升级固件,即使APP固件区没有程序或者升级过程中失败也没有关系,重新上电后,BOOT区还在,而且还是可以进入BOOT区的。<br /><br />另外,我的做法也是BOOT和APP是分两个工程分别来编译的。APP里面需要将异常向量表(64个字节)REMAP到RAM,这样就产生中断就可以从APP中取中断跳转地址了。
zjxzhxzh 发表于 2008-11-19 10:17 | 显示全部楼层

IAP

断电没有关系的,重新上电可继续
汽车电子 发表于 2008-11-19 10:36 | 显示全部楼层

IAP放最后一个扇区是不现实的,有些型号最后是32KB

&nbsp;&nbsp;&nbsp;&nbsp;最简单的方法,往往最可靠。&nbsp;<br /><br />一个工程即可,不管你怎样编译,main函数的代码和地址都是不变的。<br /><br />&nbsp;int&nbsp;&nbsp;&nbsp;&nbsp;main(void)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;指定代码地址<br />{<br />&nbsp;&nbsp;&nbsp;if(需要升级)<br />&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;执行升级程序(可在这里写,也可调用函数,但注意代码地址)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;清除升级相关标志<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;关中断,死循环,让系统重启(需开启看门狗)<br />&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;启动多任务系统,执行用户各个任务&nbsp;(这里仅有一条语句,即调用固定代码地址的系统初始函数)<br />&nbsp;&nbsp;&nbsp;<br />}
 楼主| liangzisen 发表于 2008-11-20 00:20 | 显示全部楼层

有个疑问??

我想知道,下载到FLALSH中的BIN在执行阶段是如何初始化RW,ZI等?<br />比如IAP和APP这两个BIN文件(前提这两个文件是通过一个分散加载文件链接编译的,main函数在IAP中),当系统上电启动执行IAP程序中的B&nbsp;__main&nbsp;汇编指令并开始初始化系统RW,ZI,<br />我想问的是:这个时刻初始化的是动态搜索FLASH中IAP,APP代码中的RW,ZI,并进行初始化,还是说在系统编译链接的时候已经把这部分初始化信息全部都记录到IAP中(带有main函数的代码的BIN),小弟对程序的编译链接比较陌生!<br />如果是在编译链接时候已经记录到IAP中的话,14楼的APP变量还是地址是会改变的。<br />还有13楼所说的&quot;APP从固定地址开始&quot;,的实现方式是不是写个汇编程序段(带调用APP主函数),然后把这个程序段通过分散加载程序设为APP的首段执行代码!
caj73 发表于 2008-11-20 10:10 | 显示全部楼层

我说

分成IAP与APP两段,&nbsp;如果只刷APP段,&nbsp;必须要保证IAP段最终的HEX码是固定的,需要注意事项:<br />1.&nbsp;IAP段代码必须保持不变,<br />2.&nbsp;APP段数据不能使用自动清0,&nbsp;而得自己写代码清0<br />3.&nbsp;APP段增加任何全局变量都会导致IAP段的代码变动,&nbsp;但可以在已有的结构中增加<br />4.&nbsp;APP段的文件位置变动也会导致IAP变动<br />5.&nbsp;每次编译后得用ultracompare&nbsp;等文件比较器,&nbsp;比较生成的HEX码的IAP段是否有变动<br />如果不注意以上几点,&nbsp;程序崩溃是一定的<br /><br />如果只刷APP段,&nbsp;后续的的检查会让人崩溃<br /><br />如果同时刷IAP与APP段,&nbsp;得保证刷的过程不出问题,&nbsp;建议是同时刷整个代码,<br />
 楼主| liangzisen 发表于 2008-11-20 15:20 | 显示全部楼层

楼上,一针见血!

看来做IAP功能的,还是两个工程分开写好点~。一个工程有点拖泥带水!
您需要登录后才可以回帖 登录 | 注册

本版积分规则

20

主题

66

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部

20

主题

66

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部