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

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

P3OUT |= BIT1; 

我以为我的预处理器正在用这样的东西替换P3OUT:

 *((unsigned short *) 0x0222u) 

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

  volatile unsigned short P3OUT @ 0x0222u; 

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

我的假设是否适合大多数编译器的大部分时间? 这种方式或其他方面有关系吗? 那个@符号来自哪里,它是某种标准吗?

我正在使用IAR Embedded工作台。

这个问题类似于这个问题: 如何将变量放在内存中的给定绝对地址(使用GCC) 。 它符合我认为编译器正在做的事情。

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

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

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

 volatile unsigned short P3OUT @ 0x0222u; 

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

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

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

类似的领域宣称一个function是一个ISR。

本文档展示了我们考虑的方法之一