这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 嵌入式开发 » MCU » 请再解释一个关于ADS中ro/rw base的疑惑(已查阅资料)!

共11条 1/2 1 2 跳转至

请再解释一个关于ADS中ro/rw base的疑惑(已查阅资料)!

菜鸟
2005-08-26 06:50:24     打赏


首先说一下,我认为我还是看了不少的资料,然后再来问这个问题的,看起来下面我写的很多,其实我只是想把问题描述清楚一点,我认为我已经写的比较详细了,所以应该不会耽误各位大侠多少时间,所以希望能耐心看完,谢谢 !

我的CPU是4510,我在各种资料上都看过相关的解释:
-ro-base address(即设定Image$$RO$$Base--我的理解)
这个选项将包含有RO(Read-Only属性)输出段的加载地址和运行地址设置为address,
该地址必须是字对齐的,如果没有指定这个选项,则默认的RO基地址值为0x8000。
-rw-base address
这个选项设置包含RW(Read/Write属性)输出段的域的运行时地址,该地址必须是字对
齐的。

Image$$RO$$Base is the address of the read-only execution region (usually
contains code and read-only data).--ro运行时地址

Image$$RW$$Base is the address of the read-write execution region (usually
contains data).--rw运行时地址

所以大致意思,我是知道的,不过在还是在有几个问题想不明白:

问题1、就是这个设定的Image$$RO$$Base与我们复位时CPU读取第一条指令的 0x0 地址有什么关系?这个“Image$$RO$$Base”到底又设定了那些源代码的运行起始地址?比如在一个Bootloader中,往往包含同时包含汇编代码和C语言代码两部分,这个“Image$$RO$$Base”只设定了C语言中RO段的运行地址 ?(拷贝RO RW段代码到Image$$RO$$Base,Image$$RW$$Base标识的位置是我的bootloader 汇编代码进入C前做的最后一件事)
如果说也设定了汇编中ro部分代码的运行地址,那问题2又怎么解释 ?

问题2、有人说“请注意,将工程编译为烧入Flash的二进制代码时,需要将链接器重新设置,将调试时程序空间定位地址(RO Base地址)改为0x00000000”,但我明明刚刚编译的Bootloader就将ro base设为了0xf00000,现在我已将其烧写入Flash中测试过,Bootloader运行良好,而且在上电时Flash首先被映射到0地址开始的地方,这与设定的0xf00000差的很远,当然在程序将进入C语言前,会remap SDRAM到0~16M空间,并将RO RW段拷贝到Image$$RO$$Base,Image$$RW$$Base标识的位置,问题是这个拷贝之前我的所有代码(比如SDRAM初始化,remap,堆栈初始化等)都运行的很正常,这又怎么解释呢?
这样一来我到有个奇怪的想法就是,如果我的程序没有C语言代码,岂不是就可以不用管这个ro base的设置?因为从一开机到拷贝ro/rw段前,我所有的汇编代码执行良好。

问题3、我的vector.S中复位入口“ResetEntry”的部分代码如下,用AXD载入ADS编译的这个.bin文件的时候可以看到,这个“ResetEntry”标号开始的代码被编译到了.bin文件的最前面,因为我在链接设置里面把reset section放在了img的最前面。我有点不明白就是这个“ResetEntry”标号代表着的一个地址与Image$$RO$$Base又有什么关系 ?与复位时CPU读取第一条指令的 0x0 地址又有什么关系?因为我的Bootloader在拷贝ro段代码时用到了这个标号,同时我的Bootloader代码也并不是真正放在Flash的起始部分(即开机的0地址处),只是在0地址处放了一条跳转到Flash的高端,再执行哪里存放的Bootloader代码。

AREA reset, CODE, READONLY
ENTRY
;复位和上电启动的入口
ResetEntry
b SYS_RST_HANDLER
b UDF_INS_HANDLER
.........................................


4、我在AXD调试程序时还发现,调试过程中我可以把ADS生成的.bin文件载入SDRAM中任何位置,然后修改pc值执行之,不论你的Image$$RO$$Base,Image$$ROW$$Base设定在什么地方,当然我的这个调试的程序肯定没有对ro/rw段做任何的拷贝操作。这让我更对RW段运行时地址和Image$$ROW$$Base的关系感到疑惑,因为rw段中不是保存有程序需要的变量或数据么?Image$$ROW$$Base设定了rw段的运行地址,那岂不是也就设定了运行时变量或数据在内存中的存在位置?那我用AXD加载的这个程序又在哪里获得的程序运行需要的变量和数据呢 ?

上面的问题其实一直就困扰了我好久,不过因为项目方面比较急,所以也就一直放在哪里没有对其深究,现在稍微有点空,才放到网上来,请各位解惑,非常感谢 !
我的表达能力也不怎么好,上面的问题也许有点罗嗦,如果还有什么没有说清楚的也希望能提出来,3KS ag !

[align=right][color=#000066][此贴子已经被作者于2005-8-26 9:54:41编辑过][/color][/align]



关键词: 请再     解释     一个     关于     疑惑     查阅     资料     这个         

菜鸟
2005-08-26 19:25:00     打赏
2楼

四个问题其实就是一个,即链接器到底指定了什么东西。简单地说,linker把对函数的调用转化成向某一地址的跳转,把对变量的读写转化成对某一地址的访问。

但是,一段正在执行的代码本身,从本质上来说,并不需要知道自己运行在什么地址。只要PC指针有一个初值(比如0x0),然后每次加4之后,能取到下一条指令就行了。与此相关的另一个概念就是PIC(Position Independent Code,与位置无关的代码)。

只有当代码中调用了函数,向某个symbol跳转或访问了变量,才需要知道真实的地址。所以Image$$RO$$Base是否起作用,并不取决于C代码和汇编代码的区别,而在于PIC与PDC的区别。


菜鸟
2005-09-05 20:16:00     打赏
3楼
版主和TALISKER已经回答了楼主的问题。我也说说自己的看法,希望对你有帮助。
1. Image$$RO$$Base is the address of the read-only execution region
你仔细琢磨RO BASE的意思,RO BASE指定的只是RO段的起始地址,注意:并没
有说始第一条指令的地址。所以,如果你的程序包括多个段的时候,有可能别
的段放到了RO BASE指定的地址上,而并不是期望执行的第一条指令。在调试
的时候,这不会造成什么问题,因为DEBUGGER会把PC指向程序的第一条指令。
如果你把程序烧写到FLASH里面后,这可能会造成问题,因为CPU在RESET后只
从地址0x0处开始取指令。所以,如果你写一个程序,期望程序从地址0x0开始
执行,要满足两个条件:1-RO BASE要为0x0,2-告诉linker,把包括你希望
执行的第一天指令SECTION链接到RO段的最前面。

2. 对于你说到的第二个问题,为什么你把RO BASE设置为0xF0000000还能从地址
0x0开始执行?这是因为4510的地址绕卷问题造成的,其实地址0xF0000000就是
地址0x0,不信你可以自己测试一下,从地址0xF00000读出来的指令和地址0x0
的指令一样。所以,你的第二个问题不是问题,这和RO BASE没什么关系。

3. 前面说过了,一个程序包括了RO段,但程序可能包括了很多个SECTION,在编译
的时候,各个section的RO段都是被链接到你指定的RO BASE开始的地方的,这
就涉及到另外一个问题:在RO段里面,你怎么安排各个sedtion在RO段的顺序?
如果你写的是BOOTLOADER的话,你必须要把包括你要执行的第一条指令的段放
在最前面,这样才能保证板子上电后能正常运行。

4. 我不知道你的程序里面是否有RW段?程序分为RO段和RW段,但并不是每个程序
都一定有RW段,如果你的程序里面没有全局变量等,那编译后,肯定是没有RW
段的,在这种情况下,你不进行RW段的拷贝,程序也能正常运行的。OK,在来
看看你的问题,你说在编译生成bin文件后,在bin文件里如何定位RW段?答案
是:单单依赖bin文件是无法定位RW段的。所以 - 如果你的程序有RW段的话,
你必须在自己程序里面处理RW段的拷贝。






菜鸟
2005-09-06 17:51:00     打赏
4楼

首先谢谢各位兄弟、大哥的回复,非常感谢 !

其次针对各位的回复,再综合我所知道的别人给的解释,我想再谈一下我自己现在的想法:
to Talisker:我不知道你想设定ro base在0x04的意思是什么?

to Twentyone:
针对你的回答1:
“在调试的时候,这不会造成什么问题,因为DEBUGGER会把PC指向程序的第一条指令。”---我调试的时候采用的是ADW载入ADS编译的二进制bin文件的方式,所以pc值或bin文件载入地址都是由我指定的,但都与ro base设定的值不同。
针对你的回答2:“对于你说到的第二个问题,为什么你把RO BASE设置为0xF0000000还能从地址0x0开始执行?这是因为4510的地址绕卷问题造成的,其实地址0xF0000000就是地址0x0”---你说的没错,0xF0000000地址最终会对应到0地址,不过我是将ro base设在了0xf00000,即15M内存的地方,而调试使用的obey xxx.ini命令将0~16M的内存都分配给了SDRAM,所以将ro base 设在0xf00000,还没有到地址卷绕的地方。
针对你的回答4:
我调试的程序首先是比较简单,那是不错,不过变量肯定是有的,不论全局、局部变量,都有 !是一个同时包含串口和IO口简单测试的程序。


菜鸟
2005-09-06 18:15:00     打赏
5楼

另外有人回答说:

解答问题1&2:这说明你的bootloader是基于相对地址的,也就是说与地址无关,而这也是对bootloader的一个基本要求。一般的bootloader都设计成地址无关的。

解答问题4:这说明你的程序比较小,或者函数调用不复杂,堆栈操作不频繁等。也就是说,不按照你的设置的ro和rw基址调入程序,有可能数据空间不够,或者代码和数据重叠,程序执行就可能出错。

------我看这个回答好像是对的,不知道各位对此有什么理解或看法 ?

[align=right][color=#000066][此贴子已经被作者于2005-9-6 10:16:36编辑过][/color][/align]

菜鸟
2005-09-06 20:01:00     打赏
6楼
如果你下载的是bin文件,你怎么调试的?怎么知道你的程序是正确运行的?

菜鸟
2005-09-07 17:38:00     打赏
7楼
以下是引用twentyone在2005-9-5 12:16:00的发言:
如果你的程序有RW段的话,
你必须在自己程序里面处理RW段的拷贝。

这个应该有链接的时候分散加载文件来做吧。


菜鸟
2005-09-21 17:31:00     打赏
8楼

首先,感谢twentyone大侠的大力协助,在他的帮助下,我对这个问题基本上比较清楚了,下面是我和他交流的部分日志,有需要的兄弟,可以参考参考:

Twentyone:

文后附的是一个测试程序,这个程序可以验证RW的影响。
测试的之前,你把你的板子的MEMORY给配置好,把SDRAM配置到地址0X0开始的地方。

测试1:程序的RO_BASE = 0x0,RW_BASE不设置,你用仿真器单步运行程序,然后观察
内存0x800的内容变化,变化顺序应该是0x0 -> 0x1 -> 0x2 ... -> 0x9

测试2:程序的R0_BASE不变,还是RO_BASE = 0x0,RW_BASE设置为0x400,单步运行程
序,观察内存0x800的内容变化,看看结果和第一次测试的是否一样

我:

我试过了,也基本上清楚了,按照你的实验设定测试2会看到0x800地址的数据不规则的变化,我又看了一下对应的汇编代码(我是指编译后的汇编代码),发现程序在读取array数组值时,是从rw base开始的地方读取数据的,因此如果一开始没有将rw段放到rw base开始的地方,则程序执行后读取的数据肯定是不对的,这也符合rw base本身的意思,现在我应该说是彻底的清楚了,谢谢 !
我以前的问题是:我在程序中使用变量前首先就先改变了变量的值,因此RW段首先就被我程序先修改了,也就是说虽然我没有搬移RW 段的操作,但是我重新修改了rw base开始的数据的值,对应到你的这个测试程序,也就是说本来我没做搬移RW段的操作,则0x400地址开始的数据(在你这个测试程序中存放的是array数组的值)是不确定的,但后来程序一开始我就修改了array数组的数据,也即修改了0x400开始的数据,因此RW段虽然我没有搬移操作,但其实也就被我重新设定正确了,然后再读取使用,当然执行起来,当然就没有什么问题了,不过这里有一点:就是我的程序本来就比较小,RW段也很小,所以没有什么问题,但如果程序大一点,RW段太大,我不能够一一重新指定,那程序就会出错了,问题解决,非常感谢 !
不过关于RO段的问题:RO base 设定值与bin程序载入值不同,但程序仍能正确执行的问题 。
我想可能只能用我得代码都是“地址无关”的这个来解释了,对吧 ?
这东西有点绞,不知道我上面的表达清楚没? 呵呵,如果没什么问题,我想就把上面这段话转到电子产品世界去了,然后我那个帖子也就可以方封贴了,呵呵,不过真的非常感谢你的帮助,谢谢 !

Twentyone:

不用客气!

你说的很清楚,你的理解是正确的,关于RO_BASE的问题,如果程序完全运行正确的话
,只能用与地址无关来解释。

如果你想做一个RO_BASE的测试的话,你可以写一个测试程序,在程序里面包括一些绝
对寻址的指令,你就会发现程序运行时用不同的RO_BASE的话,运行会有问题的(可能
不影响结果,但中间肯定是有地方和你期望的不一样的)。


菜鸟
2005-09-21 17:37:00     打赏
9楼

ft,忘了贴代码了,Twentyone大侠的测试程序如下:

init.s:

AREA Init, CODE, READONLY
CODE32
ENTRY
ARM
LDR SP, =0xC00
IMPORT CTEST
B CTEST
END

test.c:

unsigned int array[] = {0,1,2,3,4,5,6,7,8,9};

int CTEST(void)
{
int i;
unsigned int base;
i = 0;
base = 0x800;
for(i = 0; i < 10; i++){
*((unsigned int*)(base)) = array[i];
}
return 0;
}


菜鸟
2005-09-21 18:18:00     打赏
10楼

不错,鼓励交流,也欢迎贴出自己的心得!


共11条 1/2 1 2 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]