我正在尝试更改 lpc2138 的 IAR 特定头文件,以便它可以使用 Visual Studio 2008 进行编译(以启用兼容的单元测试)。
我的问题涉及将寄存器定义转换为与硬件无关的(不在内存地址)
“IAR 安全宏”是:
#define __IO_REG32_BIT(NAME, ADDRESS, ATTRIBUTE, BIT_STRUCT) \
volatile __no_init ATTRIBUTE union \
{ \
unsigned long NAME; \
BIT_STRUCT NAME ## _bit; \
} @ ADDRESS
//declaration
//(where __gpio0_bits is a structure that names
//each of the 32 bits as P0_0, P0_1, etc)
__IO_REG32_BIT(IO0PIN,0xE0028000,__READ_WRITE,__gpio0_bits);
//usage
IO0PIN = 0x0xAA55AA55;
IO0PIN_bit.P0_5 = 0;
这是我的类似“硬件独立”代码:
#define __IO_REG32_BIT(NAME, BIT_STRUCT)\
volatile union \
{ \
unsigned long NAME; \
BIT_STRUCT NAME##_bit; \
} NAME;
//declaration
__IO_REG32_BIT(IO0PIN,__gpio0_bits);
//usage
IO0PIN.IO0PIN = 0xAA55AA55;
IO0PIN.IO0PIN_bit.P0_5 = 1;
这可以编译并工作,但很明显我的“硬件独立”用法与“IAR安全”用法不匹配。
如何更改宏以便可以像在 IAR 中一样使用 IO0PIN?我觉得这是一个简单的匿名工会问题,但多次尝试和变体都被证明是不成功的。 也许 IAR GNU 编译器支持匿名联合而 vs2008 不支持。
谢谢你。
好吧,伙计们,这就是最终对我有用的东西:
#define __IO_REG32_BIT(NAME, BIT_STRUCT)\
volatile union\
{\
unsigned long NAME;\
BIT_STRUCT NAME##_bit;\
} NAME##_type;
__IO_REG32_BIT(IO0PIN,__gpio0_bits);
#define IO0PIN IO0PIN_type.IO0PIN
#define IO0PIN_bit IO0PIN_type.IO0PIN_bit
现在我可以在代码中使用以下内容进行单元测试:
IO0PIN = 0xFFFFFFFF;
IO0PIN_bit.P0_5 = 1;
预处理器会将其替换为:
IO0PIN_type.IO0PIN = 0xFFFFFFFF;
IO0PIN_type.IO0PIN_bit.P0_5 = 1;
通常的方法是使用宏,将所需的地址转换为适当的类型:
#define __IO_REG32_BIT(NAME, BIT_STRUCT) \
typedef volatile union \
{ \
unsigned long NAME##_value: \
BIT_STRUCT NAME##_bit; \
} NAME##_type
__IO_REG32_BIT(IO0PIN, __gpio0_bits);
#define IO0PIN (*(IO0PIN_type *)0xE0028000)
现在
IO0PIN
可以按照您所描述的那样使用。 但是,请注意,我必须重命名内部字段和类型名称,以避免与宏名称冲突IO0PIN
。 您当然可以根据自己的喜好重命名。
我知道这不是答案,但我没有足够的声誉来编辑问题。 我希望这可能有助于澄清。 如果您将所有宏从图片中删除,Alan_m 最终想要得到的是如下所示的匿名联合:
volatile union {
u32 IO0PIN;
u16 IO0PIN_bit;
};
可以这样引用:
void test( void )
{
IO0PIN = 0x0xAA55AA55;
IO0PIN_bit.P0_5 = 0;
}
这工作正常。使用 IAR 编译器,但在 VC++ 编译器上会导致编译器错误
错误 C2646:全局匿名联合 必须声明为静态
请注意,这是来自 VS2005,因此可能与 VS2008 略有不同。
我想 Alan_m 的所有代码都已经按照 IAR 标准编写,并且必须进行修改才能使用他想要避免的命名联合。