Chinaunix首页 | 论坛 | 博客
  • 博客访问: 15502775
  • 博文数量: 2005
  • 博客积分: 11986
  • 博客等级: 上将
  • 技术积分: 22535
  • 用 户 组: 普通用户
  • 注册时间: 2007-05-17 13:56
文章分类

全部博文(2005)

文章存档

2014年(2)

2013年(2)

2012年(16)

2011年(66)

2010年(368)

2009年(743)

2008年(491)

2007年(317)

分类:

2007-05-17 16:18:38

ARM中的跳转地址是怎么回事!(作者:gliethttp)

  跳转指令用于实现程序顺序执行时的函数跳转,在ARM程序中有两种方法可以实现程序流程的跳转:
<1>使用专门的跳转指令
<2>直接向当前地址计数器PC写入预跳转的绝对地址值
通过向当前地址计数器PC写入预跳转的绝对地址值,可以实现在4GB连续的线性地址空间中的任意子程序调用跳转
ARM专用的跳转指令可以完成从当前指令向前或向后的32MB的地址空间的跳转,一共有4个:
<1> B    跳转指令
<2> BL   带返回的跳转指令,子程序执行完成后会有mov pr,lr指令,以便返回到函数调用处继续执行
<3> BLX  带返回和状态切换的跳转指令,跳转的同时实现ARM态和Thumb态的切换,并且返回地址入lr(C程序子函数调用时)
<4> BX   带状态切换的跳转指令,跳转的同时实现ARM态和Thumb态的切换
可以看到“ARM专门的跳转指令”均是进行相对地址跳转(即:相对于当前执行处PC地址,向前、向后跳),因此,可以使用这一
特性完成程序自己在Flash中将自己拷贝到SDRAM然后运行的自启动工作。

开发环境:ADS1.2
硬件环境:
   CPU   - at91rm9200
   Flash - 0x10000000 (程序存储地址)
   SDRAM - 0x20000000 (SDRAM起始地址)
ADS配置:
   ARM Linker->Output/RO Base
   将RO Base设置成0x20000000,RW Base空着不管,
   那么编译器会把RO和RW段均以0x20000000为起始地址进行程序链接

记得前面的“ARM专门的跳转指令”吧,虽然我们这里编译地址为0x20000000,但是当我们把编译好的bin文件下载到0x10000000地址(启动后,未Remap前,被CPU认成0x0地址)Init.s中的B、BL相对地址跳转均还能够正常运行,所以我们就可以很安全的在Init.s中实现将Flash中运行的自身拷贝到SDRAM中,然后继续运行!最后使用ldr pc,=0xabcdefgh就可以跳转到SDRAM内存中执行刚才拷贝的自身程序了!

 参考代码:
#define xsrc_base 0x10000000
#define xdst_base 0x20000000
extern uint32 Image$$RO$$Base;
extern uint32 Image$$ZI$$Limit;
void xCopy2SDRAM(void)
{uint32 *src,*dst;
 uint32 i;
 uint32 dot;
 uint32 xcode_size = (uint32)&Image$$ZI$$Limit - (uint32)&Image$$RO$$Base;
 uint32 xdot_size;
    src = (uint32*)xsrc_base;
    dst = (uint32*)xdst_base;
    xcode_size /= 4;
    xcode_size += 1;
    xdot_size   = (xcode_size/10);
    for(i = 0,dot = 0;i < xcode_size;i++)
    {
        *dst++ = *src++;
        dot++;
        if(dot >= xdot_size)
        {
            dot = 0;
            xxxdprintf(".");
        }
    }
}

阅读(6896) | 评论(20) | 转发(0) |
给主人留下些什么吧!~~

chinaunix网友2009-08-19 09:53:04

将ro设置成为0x20000000,不是指定了程序的运行地址为RAM(也包括xCopy2SDRAM),是这样吗?如果在我写的scatter中的abc.c,我写的函数也都是没有使用全局变量之类的,应该也是地址无关的阿,为什么用scatter指定的运行地址,使用BL就会跳转到ram中运行呢?

gliethttp2009-08-19 09:52:41

没有引用全局变量的函数就是可以使用相对地址进行引用的函数,这是编译器决定的,如果像你描述的,将Main函数加载到什么地址都可以直接跳过去正常执行Main函数.

chinaunix网友2009-08-19 09:47:36

这个我清楚,我不清楚的是xCopy2SDRAM为什么是地址无关的?它为什么用BL调用还是在flash中运行?它怎么不用复制到RAM中才能运行?如果Main函数也不用全局变量之类的,虽然设置0x20000000,是不是也可以直接调用,还是会在FLASH中运行?

gliethttp2009-08-19 09:13:14

程序运行有2中地址,一个是load加载地址,该地址对应存储到flash中的地址,灵感一个是运行地址,即程序真正会运行的地址,这就是你编译时设置的地址,如果设置成0x20000000,那么程序就需要在0x20000000中运行,但是运行在0x20000000的程序需要一段代码将它拷贝到0x20000000地址才行,因为程序存储在地址为0x10000000的flash中,不知道你能不能清楚.

chinaunix网友2009-08-19 08:57:38

原来博主在线,感谢您的不吝赐教!!不过我还是有点不明白,ro为0x20000000,所有的函数链接地址不是都是以 0x20000000为基址,怎么说是地址无关呢?上面两种情况有什么区别?希望您能解释的详细些,这个问题困扰了我很久,我将不胜感激!