5

我正在寻找最优雅的界面上的输入,以放置一个内存映射寄存器接口,其中目标对象在寄存器中被拆分:

union __attribute__ ((__packed__)) epsr_t {
    uint32_t storage;
    struct {
        unsigned reserved0    : 10;
        unsigned ICI_IT_2to7  :  6; // TOP HALF
        unsigned reserved1    :  8;
        unsigned T            :  1;
        unsigned ICI_IT_0to1  :  2; // BOTTOM HALF
        unsigned reserved2    :  5;
    } bits;
};

在这种情况下,访问单个位T或任何reserved字段都可以正常工作,但读取或写入ICI_IT需要的代码更像:

union epsr_t epsr;
// Reading:
uint8_t ici_it = (epsr.bits.ICI_IT_2to7 << 2) | epsr.bits.ICI_IT_0to1;
// Writing:
epsr.bits.ICI_IT_2to7 = ici_it >> 2;
epsr.bits.ICI_IT_0to1 = ici_it & 0x3;

在这一点上,我已经失去了位域抽象试图提供的简单性/便利性。我考虑了宏观解决方案:

#define GET_ICI_IT(_e)      ((_e.bits.ICI_IT_2to7 << 2) | _e.bits.ICI_IT_0to1)
#define SET_ICI_IT(_e, _i)  do {\
    _e.bits.ICI_IT_2to7 = _i >> 2;\
    _e.bits.ICI_IT_0to1 = _i & 0x3;\
    while (0);

但作为一般规则,我不是这样的宏的超级粉丝,我讨厌在阅读别人的代码时追逐它们,而且我绝不会给别人造成这样的痛苦。我希望有一个涉及结构/联合/what-have-you 的创意技巧来更优雅地隐藏这个对象的拆分性质(理想情况下作为对象的简单成员)。

4

3 回答 3

8

我不认为有任何“好”的方式,实际上我不会依赖位域......有时最好有一堆详尽的宏来做你想做的一切,把它们记录好,然后依靠他们封装你的问题......

#define ICI_IT_HI_SHIFT   14
#define ICI_IT_HI_MASK    0xfc
#define ICI_IT_LO_SHIFT   5
#define ICI_IT_LO_MASK    0x02

// Bits containing the ICI_IT value split in the 32-bit EPSR
#define ICI_IT_PACKED_MASK  ((ICI_IT_HI_MASK << ICI_IT_HI_SHIFT) |     \
                             (ICI_IT_LO_MASK << ICI_IT_LO_SHIFT))

// Packs a single 8-bit ICI_IT value x into a 32-bit EPSR e
#define PACK_ICI_IT(e,x)  ((e & ~ICI_IT_PACKED_MASK) |                 \
                           ((x & ICI_IT_HI_MASK) << ICI_IT_HI_SHIFT) | \
                           ((x & ICI_IT_LO_MASK) << ICI_IT_LO_SHIFT)))

// Unpacks a split 8-bit ICI_IT value from a 32-bit EPSR e
#define UNPACK_ICI_IT(e)  (((e >> ICI_IT_HI_SHIFT) & ICI_IT_HI_MASK) | \
                           ((e >> ICI_IT_LO_SHIFT) & ICI_IT_LO_MASK)))

请注意,为了便于阅读,我没有放入类型转换和普通宏的内容。是的,我在提到可读性时得到了讽刺......

于 2013-01-14T04:05:51.733 回答
0

如果您非常不喜欢宏,请使用内联函数,但是您拥有的宏解决方案很好。

于 2013-01-14T03:51:32.973 回答
0

您的编译器是否支持匿名联合

我发现它是一个优雅的解决方案,可以摆脱你的.bits部分。它不符合 C99,但大多数编译器都支持它。它成为 C11 中的标准。

另请参阅此问题:结构中的匿名联合不在 c99 中?.

于 2013-01-14T13:03:26.640 回答