打印
[ZLG-ARM]

IAP自升级功能,碰到一个关于常量在内部FLASH地址定位问题.

[复制链接]
2975|8
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
daixgen|  楼主 | 2009-8-15 14:19 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
在程序用IAP自升级时思路如下,上电后运行BOOT程序,先判断用户程序标志位是否有效,若有效则进入用户程序,若无效则在BOOT程序中。准备将这个标志位做在ARM的内部FLASH中,现在碰到的情况是在ADS中如何将这个标志位定位到FALSH的固定地址。如用户程序的起始地址或程序区的最后面的地址?

相关帖子

沙发
roger_lj| | 2009-8-15 19:53 | 只看该作者
回复楼主
好像可以用类似于_at之类的符号直接在程序里定位变量的绝对地址吧?
或者就使用分散加载文件.
另外, 因为IAP对内部FLASH的操作是以扇区为单位的, 所以, 即使要写FLASH中的一个字节, 也要擦除整个扇区的. 所以, 你要给这个标志位独立分配一个较小的扇区(比如4K的小扇区).
关于IAP, 可以参考http://www.standardics.nxp.com/support/documents/microcontrollers/zip/an10835.zip

使用特权

评论回复
板凳
daixgen|  楼主 | 2009-8-16 17:35 | 只看该作者
谢谢,这个标志位并不是用IAP进行专门写入。而是在程序的烧写文件中定位好的。这样即使用电脑直接将用户程序下载进去,用户程序有效的标志位仍旧存在。类似于用const 定义

使用特权

评论回复
地板
pigeon0411| | 2009-8-18 17:04 | 只看该作者
其实可以考虑用FLASH最后一个扇区做一些标志位的存储,像LPC2300没有页操作,使用最后4KB的扇区还是比较合适的。

你可以在IAP升级完成后,将一些标志位数据存储到FLASH某地址处,比如 0x0007D000,具体操作方法很简单:
void setFlag(void)  //设置标志位
{
   unsigned short *pc = (unsigned short *)0x0007D000;
    pc[0] = 0x2009;
    pc[0] = 0x0818;
}

void  checkFlag(void) //验证标志位
{
          unsigned short *pc = (unsigned short *)0x0007D000;

          if ((pc[0] != 0x2009) ||  (pc[1] != 0x0818) )
        {
             //自己添加
         }
         else
        {//自己添加}
}

使用特权

评论回复
5
pigeon0411| | 2009-8-18 17:05 | 只看该作者
当然也可以使用IAP更新标志位,但考虑到要选择扇区,还要擦除扇区,操作起来比较麻烦,没必要。

使用特权

评论回复
6
daixgen|  楼主 | 2009-8-20 19:35 | 只看该作者
感谢这么多热心人。
问题已经解决了,用分散加载可以实现了。生成BIN文件时会生成两个BIN,其中一个就是类似于用CONST定义的数据。我现在把用户程序有效标志通过中断向量表的累加和校验来判断是否有效。即在更新用户程序的时候选写后面的数据,到最后再回过头来写第一块数据。这样即使擦除到一半的时候,前面的累加和校验也会通不过。保证不会进入无效的用户程序

使用特权

评论回复
7
JunZe| | 2009-8-23 11:13 | 只看该作者
用外部的存储器来设置标志也可以啊,同时可以把程序数据存放到这个存储器中来,比如在GPRS自动升级时.

使用特权

评论回复
8
synics| | 2009-8-23 16:21 | 只看该作者
IAP实现要点分析

在嵌入式应用系统中,通常要求记录一些现场的传感、交互输入数据,通常把数据记录在Flash存储器中,以便下次上电能获得以前的数据。如果系统程序和数据分开存储。那么只要对存放数据的Flash器件进行编程即可。然而大多数嵌入式系统,程序和需保存的数据都共存于同一Flash存储器中,那么是否也如前所述,可对Flash存储器直接编程呢?理论和实践都表明不可以。

先从理论上计算:LPC2210允许的芯片核工作频率(CCLK)范围是10-60MHz,存储器读访问长度由存储器组配置寄存器BCFG中读访问的长度域控制WST1控制,其最大可用长度为35个CCLK,而SST39VF160的扇区擦除典型时间为18ms。下面是计算算式:

TRDmax=RDLenmax/CCLKmin=35/10×10-6=3.5μs
Tp=18ms>>3.5μs
其中:TRDmax--最大读访问的时间;
RDLenmax--最大读访问可用长度;
CCLKmin--最小核工作时钟频率;
Tp--扇区擦除典型时间。

算式得出扇区擦除典型时间远大于最大读访问时间。这样一来,如果再给某Flash写数据,同时于其中预取指,那么因Flash执行命令期间,对其他操作不响应,预取出的必定是其数据引脚上的不确定数据,预取指失败。实践也表现,如果在程序执行过程中,对同一Flash进行扇区擦除,必定引起预取指中断。

使用特权

评论回复
9
synics| | 2009-8-23 16:21 | 只看该作者
为了解决在同一Flash芯片存放程序并IAP这一问题,引进代码重映射的思想。所谓重映射就是代码先自复制到制定存储区,然后跳转到制定区的起点开始执行。这里,IAP程序先自复制到LPC2210片内SRAM中,然后跳转到SRAM执行IAP代码。前面过说,ARM7为冯·诺依曼结构,这就为IAP程序重映射提供了可能。

编写可重映射代码的关键是要解决程序中相对偏移的问题,ARM7指令系列中涉及相对偏移的指令主要有LDR/STR以跳转指令。这里的解决方案是:凡涉及偏移值的指令通通采用基址变址寻址方式,以PC寄存器作基址寄存器,以立即数为变址,这样当程序块整块移动时,要加载的数据或跳转的地址与当前PC值的偏移值固定,解决了相对偏移问题。

2.2 扇区擦除

事先编程在Flash中的程序前自复制到SRAM制定的位置,然后,赋PC为SRAM中扇区编程代码段的起点ERASEPART。程序于SRAM中的ERASEPART起点开始执行,按照SST39VF160扇区擦除的时序要求开始擦除。按照ARM公司提出的ATPCS规定,C语言程序调用汇编程序时,寄存器R0-R3传递参数,返回值由寄存器R0传递原则,扇区擦除程序的一个参数,要擦除的扇区号,由R0传递;返回参数置于R0,扇区擦除成功返回"1",否则返回"0"。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

3

主题

9

帖子

2

粉丝