【问题标题】:How to declare anonymously如何匿名申报
【发布时间】:2014-03-03 21:15:19
【问题描述】:

我有以下问题:我正在尝试定义一些基本结构,这有助于我映射控制器内存的一部分以更有效地使用它。让我给你举个例子:

typedef struct
{
    ICR1_t      ICR1_dByte;    /* 0x46 - 0x47  */
    OCR1B_t     OCR1B_dByte;   /* 0x4A - 0x4B  */
    OCR1A_t     OCR1A_dByte;   /* 0x48 - 0x49  */
    TCNT1_t     TCNT1_dByte;   /* 0x4C - 0x4D  */
    TCCR1B_t    TCCR1B_Byte;   /* 0x4E */
    TCCR1A_t    TCCR1A_Byte;   /* 0x4F */
    uint8_t     Filler[8];     /* 0x50-0x57 */
    TIFR1_t     TIFR1_Byte;    /* 0x58 */
    TIMSK1_t    TIMSK1_Byte;   /* 0x59 */
}Timer1_str;

用法定义:

#define TIMER1str (*(volatile Timer1_str *)(TIMER1_START_ADDRESS))

TIMER1_START_ADDRESS 定义为

(uint8_t *)&ICR1

(ICR1是基本定义的一部分,一些地址,没关系)

所以,我的特殊问题是如何填补位于 0x50-0x57 地址下的内存空白?在目前的解决方案中,变量“Filler”在所有自动补码工具下都是可见的,因此可以调用字段:

TIMER1str.Filler[0] = 0xAA;

我希望隐藏该填充程序的实现。我的第一个想法是将这个填充器实现为匿名联合,如下所示:

...
    TCCR1A_t    TCCR1A_Byte;   /* 0x4F */
    union { Filler[8]; };      /* 0x50-0x57 as anonymous */
    TIFR1_t     TIFR1_Byte;    /* 0x58 */
....

但是这个解决方案不起作用...

如何隐藏成员的结构?它应该设置内存,但不应该是可访问的。

【问题讨论】:

    标签: c struct embedded unions


    【解决方案1】:

    看起来您正在为 AVR 编写代码。

    不要这样做。使用编译器提供的这些寄存器的定义。

    正如所写,您的代码指定Timer1_str 结构将存在于系统内存中的某个位置,由链接器确定。如果没有任何额外的支持,此代码将无法工作,因为此结构将映射到 SRAM,导致对其进行写入没有特殊效果。即使您使用链接器将此结构映射到适当的地址(这可能会也可能不会),编译器生成的使用它的代码也不是最理想的,因为它将无法使用INOUT 操作这些寄存器的指令。 (要生成这些指令,必须在编译时知道要写入的地址。)此外,编译器可能会生成无法正确访问这些寄存器的代码 - 例如,它可能会以错误的顺序生成对 TCNT 的写入。

    【讨论】:

    • +1...例如 AVR libc 有 <avr\io.h>
    • 您好,事实上,您说这是针对 AVR 的说法是对的,但它只是 AVR 开发人员向我们介绍的解决方案的包装。事实上,这个问题更侧重于在其他结构中定义匿名联合/数组以便能够“跳过”某些地址的实用方法。
    【解决方案2】:

    C 不支持这个。匿名嵌套结构和联合不会隐藏成员,它们只是允许您访问该成员,就好像它们是包含类的成员一样。

    如果您的编译器支持,一种可能性是使用 C++ 编译:

    struct Timer1_str
    {
        public :
            ICR1_t      ICR1_dByte;    /* 0x46 - 0x47  */
            OCR1B_t     OCR1B_dByte;   /* 0x4A - 0x4B  */
            OCR1A_t     OCR1A_dByte;   /* 0x48 - 0x49  */
            TCNT1_t     TCNT1_dByte;   /* 0x4C - 0x4D  */
            TCCR1B_t    TCCR1B_Byte;   /* 0x4E */
            TCCR1A_t    TCCR1A_Byte;   /* 0x4F */
        private :
            uint8_t     Filler[8];     /* 0x50-0x57 */
        public :
            TIFR1_t     TIFR1_Byte;    /* 0x58 */
            TIMSK1_t    TIMSK1_Byte;   /* 0x59 */
    } ;
    

    【讨论】:

    • 所有 Cpp 编译器都保证,结构中的数据将按输入顺序直接定位吗?
    • @user2759473:好问题。是的,我相信是这样,但包装和对齐可能会有所不同。建议使用编译器的打包指令。最后,您的芯片或编译器供应商几乎肯定会提供定义外设寄存器访问的标头,并且正如duskwulf 指出的那样,这可能是一个更好的解决方案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-03
    • 2023-03-26
    • 2010-09-26
    • 2014-09-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多