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

しかし、私は原則としてこのようなマクロの大ファンではありません。他の人のコードを読んでいるときにマクロを追いかけるのは嫌いです。他の人にそのような惨めさを与えることは私から遠く離れています。このオブジェクトの分割された性質をよりエレガントに(理想的にはオブジェクトの単純なメンバーとして)隠すために、構造体/ユニオン/何を持っているかを含む創造的なトリックがあることを望んでいました。

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 に答える