keil c51代码及RAM变量定址问题

iwillalwaysloveyou 2009-07-29 10:34:26
我想把部分模块的代码集中放到固定起始位置,

并且这部分代码所使用的RAM变量(包括全局变量和局部变量),放到其他模块RAM变量的前面,

能做到吗?
...全文
1758 34 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
34 条回复
切换为时间正序
请发表友善的回复…
发表回复
GC80 2009-08-18
  • 打赏
  • 举报
回复
to iwillalwaysloveyou,
我也有过这样的疑问,基本上在KEIL工具上,要想函数的临时变量不要采用固定的地址,只有可重入(reentrant),不过可重入后代码就变大许多,可以说keil没有考虑好把部分模块打包lib后时,采用堆栈这种模式来调用,或者是没有优化好吧。
IAR Embedded Workbench for MCS-51就基本可以解决这个问题,IAR编译出来的程序,局部变量采用的堆栈的模式,是完全可以满足你的要求。
只有写过一些MASKROM程序的人才有这样的体会,我们现在就在用IAR的模式,IAR就是入门难一点,IAR有点GCC的风格,程序的连接过程完全能有开发者自主控制住你的程序。
pigeon0411 2009-08-13
  • 打赏
  • 举报
回复
在KEIL FOR ARM中,我是用分散加载文件来做的,用分散加载文件可以任意分配指定你想要的变量,模块所处的位置。

KEIL C51可能也有这样的功能,你可以查查相关帮助文档。
LanceJin 2009-08-12
  • 打赏
  • 举报
回复
[Quote=引用 25 楼 iwillalwaysloveyou 的回复:]
引用 24 楼 jlctt 的回复:
重入函数非迫不得已不会用,说实话我写了C51的代码如果以行来计算的话,起码有个二三十万行吧,还没有用过reentrant,但是了解是必要的.还有局部变量是可以指到不同区域的,如XDATA, 固定地址你能确定吗?


局部变量是可以指到不同区域,这个没错。
我所说的固定,指的是芯片掩膜之后。

我需要把某些模块的全局变量和局部变量全部集中起来放到一个固定位置。

[/Quote]如果你指的变量是函数体内部的局部变量,通常是分配在RAM空间的,同样的函数如果在不同的地方调用,局部变量也不一定是固定的。如果你指的变量是说一个模块的变量,在函数体外声明,要固定地址还是有办法的,除了_at_外,还可以用以下(原文出自http://leency0000.spaces.live.com/default.aspx?_c02_owner=1)方式定位:

1、函数定位:
假如要把C源文件 tools.c 中的函数
int BIN2HEX(int xx)
{
...
}
放在CODE MEMORY的0x1000处,先编译该工程,然后打开该工程的M51文件,在
* * * C O D E M E M O R Y * * *
行下找出要定位的函数的名称,应该形如:
CODE xxxxH xxxxH UNIT ?PR?_BCD2HEX?TOOLS
然后在:
Project->Options for Target ...->BL51 Locate:Code
中填写如下内容:
?PR?_BCD2HEX?TOOLS(0x1000)
再次Build,在M51中会发现该函数已放在CODE MEMORY的0x1000处了

2、赋初值的变量定位:
要将某变量定位在一绝对位置且要赋初值,此时用 _at_ 不能完成,则如下操作:
在工程中建立一个新的文件,如InitVars.c,在其中对要处理的变量赋初值(假设是code变
量):
char code myVer = {"COPYRIGHT 2001-11"};
然后将该文件加入工程,编译,打开M51文件,若定义的是code型,则在
* * * C O D E M E M O R Y * * *
下可找到:
CODE xxxxH xxxxH UNIT ?CO?INITVARS
然后在:
Project->Options for Target ...->BL51 Locate:Code
中填入:
?CO?INITVARS(0x200)
再次编译即可。

相应地,如为xdata变量,则InitVars.c中写:
char xdata myVer = {"COPYRIGHT 2001-11"};
然后将该文件加入工程,编译,打开M51文件,在
* * * X D A T A M E M O R Y * * *
下可找到:
XDATA xxxxH xxxxH UNIT ?XD?INITVARS
然后在:
Project->Options for Target ...->BL51 Locate:Xdata
中填入:
?XD?INITVARS(0x200)
再次编译即可。相应地,若定义的是data/idata等变量,则相应处理即可。

3、若有多个变量或函数要进行绝对地址定位,则应按地址从低到高的顺序排列。
cokewei 2009-08-12
  • 打赏
  • 举报
回复
你看看我说的这种方式能不能解决你的问题:
1,你可以看一下bootload的初始化代码,中断函数入口地址都是定义在0地址开始的地方,你可以把你的模块函数入口地址放在接下去的地方就可以通过把绝对地址赋值给指向函数的指针来调用你的函数了。建议可以看下stm32 usb IAP的示例,里面是通过绝对地址跳转到真正的main()函数,你就能明白了。
2,keil中有个定义变量后面加上__at(地址)的方式把你的变量定义到指定的位置,你可以试一下定义在最前面。
iwillalwaysloveyou 2009-08-11
  • 打赏
  • 举报
回复
最好是能通过改编译选项解决问题
iwillalwaysloveyou 2009-08-11
  • 打赏
  • 举报
回复
不使用跟具体平台绑定的代码
schlafenhamster 2009-08-11
  • 打赏
  • 举报
回复
至于代码位置要从.map文件中得到。再利用函数指针写一个头文件给用户就可以了。
schlafenhamster 2009-08-11
  • 打赏
  • 举报
回复
Absolute Variable Location.
Variables may be located at absolute memory locations in your C program
source modules using the _at_ keyword. The usage for this feature is:
type memory_space variable_name _at_ constant;
where:
memory_space is the memory space for the variable. If missing from the
declaration, the default memory space is used. Refer to
“Memory Models” on page 94 for more information about
the default memory space.
type is the variable type.
variable_name is the variable name.
constant is the address at which to locate the variable.
The absolute address following _at_ must conform to the physical boundaries of
the memory space for the variable. The Cx51 compiler checks for invalid
address specifications.
//例子:
struct link
{
struct link idata *next;
char code *test;
};
struct link list idata _at_ 0x40; /* list at idata 0x40 */
char xdata text[256] _at_ 0xE000; /* array at xdata 0xE000 */
int xdata i1 _at_ 0x8000; /* int at xdata 0x8000 */
void main ( void ) {
link.next = (void *) 0;
i1 = 0x1234;
text [0] = 'a';
}
//但:
2. Functions and variables of type bit cannot be located at an absolute address
iwillalwaysloveyou 2009-08-11
  • 打赏
  • 举报
回复
我看了编译器手册,没有提供支持,应该是没什么好办法解决这个问题
iwillalwaysloveyou 2009-08-11
  • 打赏
  • 举报
回复
[Quote=引用 24 楼 jlctt 的回复:]
重入函数非迫不得已不会用,说实话我写了C51的代码如果以行来计算的话,起码有个二三十万行吧,还没有用过reentrant,但是了解是必要的.还有局部变量是可以指到不同区域的,如XDATA, 固定地址你能确定吗?
[/Quote]

局部变量是可以指到不同区域,这个没错。
我所说的固定,指的是芯片掩膜之后。

我需要把某些模块的全局变量和局部变量全部集中起来放到一个固定位置。
LanceJin 2009-08-01
  • 打赏
  • 举报
回复
重入函数非迫不得已不会用,说实话我写了C51的代码如果以行来计算的话,起码有个二三十万行吧,还没有用过reentrant,但是了解是必要的.还有局部变量是可以指到不同区域的,如XDATA, 固定地址你能确定吗?
shuiyan 2009-07-29
  • 打赏
  • 举报
回复
你用什么做开发?计算机的二进制码?还是汇编?

“需要把多个文件的变量地址集中到一起”,为什么?什么客户(项目)需求得出这样的设计要求的?
Great_Bug 2009-07-29
  • 打赏
  • 举报
回复
如果你喜欢用汇编语言,这些地址都可以明确指定....请参考KEIL的文档...
iwillalwaysloveyou 2009-07-29
  • 打赏
  • 举报
回复
我需要把多个文件的变量地址集中到一起
iwillalwaysloveyou 2009-07-29
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 shuiyan 的回复:]
只用过变量(全局或局部)定义时指定地址,但是没有专门限制一定要在最前面。

什么样的需求会有这样的奇怪的限制?

模块代码的指定位置没用过。
[/Quote]

之所以放在前面是为了方便,不一定要放到最前。
iwillalwaysloveyou 2009-07-29
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 great_bug 的回复:]
全局变量容易控制,局部变量由编译器自动分配,不好控制.....好像也不用费事去控制它...
[/Quote]

我现在就是需要去控制
shuiyan 2009-07-29
  • 打赏
  • 举报
回复
只用过变量(全局或局部)定义时指定地址,但是没有专门限制一定要在最前面。

什么样的需求会有这样的奇怪的限制?

模块代码的指定位置没用过。
iwillalwaysloveyou 2009-07-29
  • 打赏
  • 举报
回复
考虑到空间及效率问题,不使用重入函数。

楼上你用Keil C51开发过程序吗?
C51的非重入函数局部变量的地址是固定的。
LanceJin 2009-07-29
  • 打赏
  • 举报
回复
[Quote=引用 17 楼 iwillalwaysloveyou 的回复:]
掩膜芯片,同时提供ROM和EEPROM,

我的cos代码最终是要放到ROM里,

现在想支持后下载cos替换ROM里的cos,

并且后下载的cos能重用ROM里的部分代码
[/Quote]

这个也不用这么复杂吧,你要重用的那些代码是不会再修改的吧,直接将这些代码放到ROM中指定位置直接调用不就行了。一个芯片有很多应用,芯片不可能提供所有应用代码,将固定的模块功能打包成lib就行了。用户应用代码可以放在外部存储芯片上,Mask ROM提供基本应用的Code.
LanceJin 2009-07-29
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 iwillalwaysloveyou 的回复:]
我想重用ROM里的代码
[/Quote]


keil支持重入函数

重入函数,又叫再入函数,是一种可以在函数体内不直接或间接调用其自身的一种函数。
再入函数可被递归调用,无论何时,包括中断函数在内的任何函数都可以调入。再入函数在
C51编译时使用的是模拟栈。
函数说明: 函数名(形式参数表) reentrant
注意事项:
1、再入函数不能传递bit类型参数。
2、与PL/M51兼容的函数不能具有reentrant,这样也不能调用再入函数。
3、在编译时:再入函数建立的是模拟堆栈区,small模式下模拟堆栈区位于idata
区,compact模式下模拟堆栈区位于pdata区,large模式下模拟堆栈区位于xdata区.
4、在同一程序中可以定义和使用不同存储器模式的再入函数,任意模式的再入函数不能调
用不同存储器模式的再入函数,但可以调用普通函数。
5、实际参数可以传递给间接调用的再入函数。无再入属性的间接调用函数不能包含调用参
加载更多回复(14)

27,511

社区成员

发帖
与我相关
我的任务
社区描述
硬件/嵌入开发 单片机/工控
社区管理员
  • 单片机/工控社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧