打印
[ZLG-ARM]

在同一ARM7芯片上建立两个工程的可行性讨论

[复制链接]
1814|8
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
pigeon0411|  楼主 | 2009-9-10 15:31 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
觉得还是发在周公的版块合适点。

一、资源:
    LPC2378(ARM7内核),
    IDE:KEIL,或者ADS

二、实现:
    建立两个工程,也就是说包含独立的MAIN函数,包含独立的中断向量表(地址不同),编译后烧录到指定的不重复的地址处。

这样可以实现任意升级功能,任意切换某一执行区,且互不依赖。

三、如何运行:
      通过烧录在0x0地址处的简单BOOTLOADER代码决定要启动哪个地址区域的代码。

四、BOOTLOADER要做的:
     在BOOTLOADER代码中将中断向量表得到到RAM,然后重新映射到RAM。然后通过指针跳转到需要等等的区域。

五、存在的问题:
     通过BOOTLOADER复制中断向量表并做重新映射再配合分散加载文件,可以实现不同区域的切换,可跳转到指定的地址处执行,但运行到某处就死掉,不能正常运行起来。

六、问题分析:
     估计还是因为中断向量表重映射的问题。

七、求助:
      请教高手:中断向量表的重映射和复制正确的做法是怎么样的?中断向量表复制后,中断处理程序的地址是否还要处理?

      下面是我写的中断向量表复制的代码以及RAM重映射,请大家指正。
      (代码思路来源于ZLG深圳分公司工程师的指导)

/******************************************************
* bootloader中检测试标志位决定启动哪个区域的代码
* 复制中断向量表并重新映射
*
*******************************************************/
typedef void (*func_t)(void);
func_t ptr;

void checkFlag(void)
{
   int i;
unsigned char *pc   =  (unsigned char *)0x0007d000;

unsigned int *pram   =  (unsigned int *)0x40000000;
unsigned int *webup  =   (unsigned int *)0x00003800;

unsigned int *uartaddr  =   (unsigned int *)0x00001000;

     if ((pc[0] == 0x02) &&
         (pc[1] == 0x02) &&
         (pc[2] == 0x09) &&
         (pc[3] == 0x20))
     {
          for(i=0;i<8;i++)
         {
              *(pram+i) = *(uartaddr+i);  //复制8*4字节的中断向量表

                                                      //到RAM:0x40000000
         }
         MEMMAP = 2;
         ptr = (func_t)uartaddr;      //跳转到uartaddr地址处运行这个区域的代码
        (*ptr)();
      
     }
    else if ((pc[0] == 0x01) &&
          (pc[1] == 0x01) &&
          (pc[2] == 0x09) &&
          (pc[3] == 0x20))
   {
        for(i=0;i<8;i++)
       {
             *(pram+i) = *(webup+i);
       }
       MEMMAP = 2;
       ptr = (func_t)0x00003800;
       (*ptr)();
   }


}


下面为第一个工程中的分散加载文件:
BOOT_LOAD 0x00000000  
{
BOOT 0x00000000
{        
        bootentry.o (BOOTS, +First) ;这部分为检测标志位,处理中断向量表复制
        boot.o(+RO)                       ;和重新映射并跳转的代码
}
}

OS_LOAD 0x00003800   
{
WEBUPGRADE_EXE 0x00003800 FIXED
{         ;这个工程的中断向量表,因为这个工程被放在0x3800处,所以它的中断向量         ;表放在这个区域的最开始处
        vectors.o (VECT, +First)
        init.o (INIT)
}
  
ROM2_EXE +0
{
   *(+RO)
  }

   RW_IRAM1 0x40000020 0x00007000
    {
  
  * (+RW,+ZI)

    }
ARM_LIB_HEAP  0x40007000 EMPTY  0x00000100   {}
    ARM_LIB_STACK 0x40008000 EMPTY -0x00000E00   {}
}   


;---------------------------------------------------------
下面为第二个工程的分散加载文件:

OS_LOAD 0x00030000   ;放在地址0x30000处的第二个工程的代码
{
WEBUPGRADE_EXE 0x00030000 FIXED
{         ;中断向量表
         vectors.o (VECT, +First)
        init.o (INIT)
}

ROM2_EXE +0
{
   *(+RO)
   }

   RW_IRAM1 0x40000020 0x00007000
    {
        * (+RW,+ZI)

    }
    ARM_LIB_HEAP  0x40007000 EMPTY  0x00000100   {}
    ARM_LIB_STACK 0x40008000 EMPTY -0x00000E00   {}
}


八、总结:

请大家在这里讨论一下,指点一下,谢谢。

相关帖子

沙发
pigeon0411|  楼主 | 2009-9-10 16:18 | 只看该作者
大家都不在啊?
我先顶一下。

使用特权

评论回复
板凳
xinlinhack| | 2009-9-10 22:50 | 只看该作者
我的做法是,直接把IAP功能和程序合一起,而IAP则运行在内存RAM里

使用特权

评论回复
地板
pigeon0411|  楼主 | 2009-9-11 08:34 | 只看该作者
我是用WEB升级的,这要用到UCOS,TCP/IP,IAP代码是可以放在RAM里,那升级过程中掉电了怎么办?

使用特权

评论回复
5
xinlinhack| | 2009-9-11 20:03 | 只看该作者
其实我先把代码放在一个储存器里面,再从储存器读取这些程序代码,用IAP写
这样比较安全

使用特权

评论回复
6
pigeon0411|  楼主 | 2009-9-12 08:41 | 只看该作者
其实我先把代码放在一个储存器里面,再从储存器读取这些程序代码,用IAP写
这样比较安全
xinlinhack 发表于 2009-9-11 20:03


你说的这种方法是最简单,最通用也最适用的方法。
但是公司又不愿另外多加一个颗外扩的芯片,又得用UCOS+TCP/IP实现升级功能,512KB的空间放400多KB的代码,还要升级整个系统,把人都搞疯了。还要节约使用32KB的RAM……

使用特权

评论回复
7
xinlinhack| | 2009-9-13 17:42 | 只看该作者
看来,你只能做个类Bootloader,做这个东西,要不断调试才行,祝你好运啦

使用特权

评论回复
8
pigeon0411|  楼主 | 2009-9-13 22:56 | 只看该作者
搞定啦。

动态配置中断向量表,多个工程代码独立运行,系统资源共享,一个芯片多个工程,多个区域切换运行,终于搞定,谢谢大家讨论。

结贴。

使用特权

评论回复
9
bigarmer| | 2009-9-14 09:19 | 只看该作者
虽然LZ已经结贴,但是我发现有两个问题LZ并没有讲清楚或在本贴没讲出来,一个是拷贝异常向量表应该是64个字节(32字节的异常向量和后32字节的跳转地址)而不是只有前32字节;第二个是,映射到RAM之后,不需要跳转到实际的代码起始地址,可以直接跳到RAM的首地址,也就是拷贝了异常向量表的RAM起始地址,因为它已经包含了所有的异常跳转地址(当然也可以直接跳转到实际地址,不过这样容易乱,直接跳到RAM,操作比较统一)。

使用特权

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

本版积分规则

42

主题

157

帖子

3

粉丝