当前位置:  开发笔记 > 人工智能 > 正文

修复了C中的地址变量

如何解决《修复了C中的地址变量》经验,为你挑选了2个好方法。

对于嵌入式应用,通常需要访问外设寄存器的固定存储器位置.我发现这样做的标准方法如下:

// access register 'foo_reg', which is located at address 0x100
#define foo_reg *(int *)0x100

foo_reg = 1;      // write to foo_reg
int x = foo_reg;  // read from foo_reg

我理解它是如何工作的,但我不明白的是foo_reg的空间是如何分配的(即什么使链接器不能将另一个变量放在0x100?).可以在C级别保留空间,还是必须有一个链接器选项,指定不应将任何内容放在0x100.我正在使用GNU工具(gcc,ld等),所以我最感兴趣的是该工具集的具体细节.

有关我的架构的一些其他信息,以澄清问题:

我的处理器通过一组寄存器连接到FPGA,这些寄存器映射到处理器的常规数据空间(其中存在变量).所以我需要指向那些寄存器并阻止相关的地址空间.在过去,我使用了一个编译器,它有一个扩展用于从C代码中定位变量.我会将寄存器分组到一个结构中,然后将结构放在适当的位置:

typedef struct
{ 
   BYTE reg1;
   BYTE reg2;
   ...
} Registers;

Registers regs _at_ 0x100;

regs.reg1 = 0;

实际上创建一个'Registers'结构保留了编译器/链接器眼中的空间.

现在,使用GNU工具,我显然没有扩展.使用指针方法:

#define reg1 *(BYTE*)0x100;
#define reg2 *(BYTE*)0x101;
reg1 = 0

// or
#define regs *(Registers*)0x100
regs->reg1 = 0;

这是一个没有操作系统且没有高级内存管理的简单应用程序.实质上:

void main()
{
    while(1){
        do_stuff();
    }
}

Johannes Sch.. 12

您的链接器和编译器不知道这一点(当然,没有您告诉它).您的平台的ABI设计者可以指定他们不在这些地址分配对象.

因此,有时(我工作的平台有)虚拟地址空间中的一个范围直接映射到物理地址,另一个范围可以被用户空间进程用来增长堆栈或分配堆内存.

您可以使用GNU ld的defsym选项在固定地址分配一些符号:

--defsym symbol=expression

或者,如果表达式比简单算法更复杂,请使用自定义链接描述文件.在这里您可以定义内存区域并告诉链接器应该为哪些区域/对象指定哪些区域.请看这里的解释.虽然这通常完全是您使用的工具链的作者的工作.他们采用ABI的规范,然后编写满足平台要求的链接器脚本和汇编器/编译器后端.

顺便说一下,GCC有一个属性section,您可以使用该属性将结构放入特定的部分.然后,您可以告诉链接器将该部分放入寄存器所在的区域.

Registers regs __attribute__((section("REGS")));


kgiannakakis.. 8

链接器通常使用链接描述文件来确定将分配变量的位置.这称为"数据"部分,当然应该指向RAM位置.因此,不能在不在RAM中的地址分配变量.

您可以阅读GCC更多关于连接器脚本这里.



1> Johannes Sch..:

您的链接器和编译器不知道这一点(当然,没有您告诉它).您的平台的ABI设计者可以指定他们不在这些地址分配对象.

因此,有时(我工作的平台有)虚拟地址空间中的一个范围直接映射到物理地址,另一个范围可以被用户空间进程用来增长堆栈或分配堆内存.

您可以使用GNU ld的defsym选项在固定地址分配一些符号:

--defsym symbol=expression

或者,如果表达式比简单算法更复杂,请使用自定义链接描述文件.在这里您可以定义内存区域并告诉链接器应该为哪些区域/对象指定哪些区域.请看这里的解释.虽然这通常完全是您使用的工具链的作者的工作.他们采用ABI的规范,然后编写满足平台要求的链接器脚本和汇编器/编译器后端.

顺便说一下,GCC有一个属性section,您可以使用该属性将结构放入特定的部分.然后,您可以告诉链接器将该部分放入寄存器所在的区域.

Registers regs __attribute__((section("REGS")));



2> kgiannakakis..:

链接器通常使用链接描述文件来确定将分配变量的位置.这称为"数据"部分,当然应该指向RAM位置.因此,不能在不在RAM中的地址分配变量.

您可以阅读GCC更多关于连接器脚本这里.

推荐阅读
牛尾巴2010
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有