VHDL で定義されている多数のレジスタとインターフェイスするアプリケーションを作成しています。レジスタは 32 ビット幅で、グループに割り当てられます。グループのベース アドレスと、グループの各メンバーの 32 ビット オフセットが提供されます。以下は、1 つのグループ、グループ内のレジスター、およびレジスターの構造の例です。
現在、I/O は次のビット フィールド構造体を使用して処理されます。
typedef struct
{
uint32_t data0 : 12;
uint32_t data1 : 1;
...
}volatile data_port;
アドレスへのポインタを使用してフィールドを変更し、
data_port *const p_data = (data_port *)0xc006380;
これはこのプラットフォームでは機能するかもしれませんが、現在のコンパイラでは移植性が心配です。これらの型にはまらないデータ型の使用を余儀なくされたときに、ハードウェアへのインターフェイスを処理するためのより良い方法があるかどうか疑問に思っていましたか?
私が考えることができる 1 つの代替手段は、ハードウェアとレジスタ構造の間に別の層、揮発性の unsigned int ポインターを作成し、アプリケーション層でビットフィールド構造を使用することです。問題は、別のプラットフォームでは異なる位置に配置されている可能性があるビットフィールドから、別のトピックである可能性がある int にデータをコピーする必要があることです。
編集:
私が本当に探しているのは、ビットフィールドの使用を排除する方法だと思います。ビットフィールドメンバーを持つ構造体をハードウェアにマッピングすることは、実際には悪いアプローチのようです。そのため、代わりに次のいずれかを揮発性メモリ アドレスへのポインタとして使用します。
#define PeripheralBase ((uint32_t volatile *)BASE)
また
uint32_t volatile *const peripheral_base = (uint32_t *) BASE;
ここまで来れば、すべてが 32 ビット内で適切に調整されていることを願っています。これを行うために私が考えていた1つの方法は、同じdata_port構造を作成することでしたが、ビットパッキングを削除し、次に各レジスタ専用の関数を右に動かしてビットをunsigned intにシフトし、それを使用してレジスタに渡すことができました揮発性ポインター。
何かのようなもの、
static inline uint32_t struct_to_uint(data_port *data)
{
return data->data0
+ ((uint32_t)data->data1 << 12)
+ ((uint32_t)data->data2 << 13)
+ .....;
}
構文が正しいかどうかはわかりませんが、コンパイラやプラットフォームを気にせずに値をシフトインするという考え方です。これはそれ以来作りますか?このアプローチには移植性の問題がありますか?