大多数嵌入式C编译器如何为内存映射I / O定义符号?

时间:2014-12-15 23:10:30

标签: c macros c-preprocessor c99

我经常写这样的内存映射I / O引脚

P3OUT |= BIT1;

我认为P3OUT被我的预处理器替换为类似的东西:

*((unsigned short *) 0x0222u)

但我今天挖了一个H文件,看到了这些内容:

 volatile unsigned short P3OUT @ 0x0222u;

此前还有更多的扩张,但通常是这样。一个符号' @'正在使用。除此之外,还有一些#pragma关于使用扩展的 C 语言集。我假设这是链接器的某种指令,并且有效地将符号定义为存储器映射中的该位置。

我对大多数编译器中大多数时间发生的事情是否正确?这种方式或其他方面有关系吗?那个@符号来自哪里,它是某种标准吗?

我正在使用IAR Embedded工作台。

这个问题类似于这个问题:How to place a variable at a given absolute address in memory (with GCC)。 它符合我认为我的编译器正在做的事情。

2 个答案:

答案 0 :(得分:1)

标题中问题的简短回答是"不同"。更糟糕的是,来自不同供应商的针对同一目标处理器的编译器将使用不同的方法。这一个

volatile unsigned short P3OUT @ 0x0222u;

将变量放在固定地址的常用方法。但是你也会看到它用于识别存储器映射位置中的各个位=特别是对于像PIC系列那样具有位宽指令的微控制器。

这些是C标准没有解决的问题,恕我直言,因为小型嵌入式微控制器最终将成为C的主要市场(是的,我知道内核是用C语言编写的,但很多用户 - 太空东西正在转向C ++)。

我实际上加入了C委员会试图推动这一领域的变革,但我的赞助消失了,这是一个非常昂贵的爱好。

类似的区域宣称一个函数是一个ISR。

This document显示了我们考虑的方法之一

答案 1 :(得分:1)

虽然像(unsigned char *)0x1234这样的表达式会在许多编译器上产生一个指向硬件地址0x1234的指针,但标准中没有任何内容要求转换为指针的整数与结果地址之间存在任何特定关系。标准指定的唯一内容是,如果特定整数类型至少与intptr_t一样大,并且向该特定类型转换指针会产生一些值,那么将该特定值转换回原始指针类型将产生一个等于原始指针的指针。

IAR编译器提供非标准扩展,允许编译器请求将变量放在指定的硬编码地址。与使用宏创建指针表达式相比,这提供了一些优势。首先,它确保这些变量在语法上被视为变量;虽然指针 - kludge表达式通常在合法代码中使用时会被正确解释,但非法代码可能会因编译时错误而无法编译,但会生成除所需效果之外的其他内容。此外,IAR语法定义了链接器可用的符号,因此可以在汇编语言模块中使用。相比之下,定义指针 - kludge宏的.H文件在汇编语言模块中不可用;任何将在C和汇编代码中使用的硬件都需要在两个不同的地方指定其地址。