宏GNU与VS2008中的匿名联合定义/声明

时间:2010-04-23 18:08:05

标签: c compiler-construction macros anonymous-types unions

我正在尝试更改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则不支持。

谢谢。

3 个答案:

答案 0 :(得分:1)

好的人在这里结束了为我工作的事情:

#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;

答案 1 :(得分:0)

执行此操作的常用方法是使用宏将所需地址强制转换为适当的类型:

#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冲突。你当然可以根据自己的喜好重命名。

答案 2 :(得分:0)

我知道这不是答案,但我没有足够的声誉来编辑这个问题。我希望这可能有助于澄清。如果你从图片中取出所有的宏,Alan_m想要最终得到的是一个匿名联盟,如下所示:

volatile union {
   u32 IO0PIN;
   u16 IO0PIN_bit;
};

可以像这样引用:

void test( void )
{
   IO0PIN = 0x0xAA55AA55;
   IO0PIN_bit.P0_5 = 0;
}

这适用于O.K.使用IAR编译器但在VC ++编译器上导致编译器错误

  

错误C2646:全球匿名联盟   必须声明为静态

请注意,这是来自VS2005,因此它可能与VS2008略有不同。

我认为所有Alan_m的代码都已写入IAR标准,并且必须进行修改才能使用他想要避免使用的命名联合。