把指定代码、常数或变量到某个特定地址的一个方法

描述

问:如何指定代码、常数或变量到某个特定的地址?

答:使用“#pragma psect”伪指令来把代码、常数或变量放到你定制的psect。于是你就可以使用链接器选项来把这个定制的psect放到你想要的地址。Pragma psect的语法是:

#pragma psect original_psect=new_psect

这里的“original_psect”是标准的code、constant或变量原来位于的psect名称,这个orignal psect名称可以从map文件的symbol table里找到。 一个symbol table的示例:

__Lstrings strings 0008 __Lstringtable stringtable 0008

__Lstruct struct 0020 __Ltemp temp 0070

__Ltext text 0190 __Lvectors vectors 000B

__S0 (abs) 0800 __S1 (abs) 0190

_exit init 0004 _main text0 07FD

_serial const1 0009 intlevel0 intentry 0004

_serial const1 0009 ; 这个变量是这样声明的“const int serial = 5621;”

_serial是变量名加前下划线,const1是psect名称

这里在“const”后面有一个数字,也即“const1”,这个数字可以是任何数字,也就是说,它不一定是1。你可以使用“%%u”来代替这个数字,对于大部分的后面带有数字的psect都可以这样,除了rbss_x和rdata_x。因为rbss_x和rdata_x是每个bank的RAM变量,rbss_0代表bank 0,rbss_1代表bank 1,依此类推……

“new_psect”是你要定制的psect的名称,可以使任意名称,但是不能和标准psect同名。

示例,声明把“serial”放到一个新的psect里去是这样做的:

#pragma psect const%%u=fixed_serial

const int serial = 5621;

每一个“#pragma psect”伪指令应该是在一个独立的文件中被声明,也就是说,所有的在“#pragma psect”下面声明的变量都会被放到新的定制psect中去。

// --File serial.c

#pragma psect const%%u=fixed_serial

const int serial = 5621;

// --End file

// --File serial.h

extern int serial;

// --End file

具体放置这个新的定制psect,你将需要加入一些额外的命令行选项。

-L-Pcustom_psect=addressh

这里'-L'是传递选项给链接器,'-P'是定位一个psect到特定的地址,'custom_psect'是你想要定位的psect的名称,'addressh'是你想要定位到的16进制地址。例如:

PICC -16f877 main.c serial.c -L-Pfixed_serial=50h

对于'text' psect有一些特殊问题。一个类似于'#pragma psect text%%u=myPsect'的伪指令会把所有的text psect放置到单个用户定制的psect里。而优化器一直认为每个psect只包含一个函数。这将会产生bank切换的错误。

要避免这个问题,可以对用户定制psect名称也使用'%%u'后缀,例如:

#pragma psect text%%u=myPsect%%u

这样多个用户定制的psect将被产生。

例如:

//file test.c

#pragma psect text%%u=myPsect%%u

void func()

{

}

void func2()

{

}

void main()

{

}

//end file

你可以从列表文件和map文件中看到下面这些信息。

'func()' is in psect 'myPsect0'

'func1()' is in psect 'myPsect1'

'main()' is in psect 'myPsect2'

你于是就可以用'-L-P'选项给每一个psect清楚地分配地址。

所以,要把这些函数放到500h地址,你可以使用下面的编译选项:

-L-PmyPsect0=500h,myPsect1,myPsect2

请注意-L-P 选项是没有ROM页边界的检查,你需要自己确保这个函数(psect)是不会超越页边界的,(译者注:PICC要求每个函数都必须是在同一个ROM页里的)。请查看使用说明书来得到更多关于'#pragma psect'的信息。

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分