C言語の問題であることがよく知られているビットフィールドは避けてください。信頼性が低く、移植性がなく、実装がいつでも変更される可能性があります。そしてとにかくこの問題であなたを助けません。
ユニオンも思い浮かびますが、C規格に従ってタイプを変更するためにユニオンを使用できないように、私はSOで十分な回数修正されました。他のポスターと同じように、ユニオンを使ってタイプを変更できないケースはまだ見たことがありません。壊れたビットフィールド、絶えず壊れたユニオンメモリ共有、これまでのところ痛みはありません。そして、組合はあなたにラムを救うことはないので、ここでは実際には機能しません。
なぜコンパイラに動作させようとしているのですか?コンパイル時に、マスク、シフト、読み取り-変更-書き込み、一部のアドレススペース、およびより自然な単語、ハーフワード、およびバイトアクセス。gccやC言語で、構文にそのようなコントロールがあることや、コンパイラスクリプトやある種の定義ファイルがあることは聞いたことがありません。そして、それが存在する場合、それが信頼できるほど広く使用されていない場合、私はコンパイラのバグを予期し、それを回避します。コンパイラがそれを実行しているのを見ていません。確かに構造体のような方法ではありません。
読み取りについては、幸運になるかもしれませんが、ハードウェアの人々に大きく依存しています。このnvramメモリインターフェイスは、あなたの会社、他の会社によって製造されたチップの内部、チップの端など、どこにありますか?あなたが部分的に説明するような制限は、アクセスサイズまたはバイトレーンを区別する制御信号が無視される可能性があることを意味する場合があります。したがって、ldrbはnvramを32ビットの読み取りとして認識し、アームは8ビットの読み取りであると見なすため、正しいバイトレーンを取得します。これを確認するためにいくつかの実験を行います。複数のアームメモリバスがあり、それぞれにさまざまな種類の転送があります。おそらく、ハードウェアの担当者に相談するか、アームが実際に何をしているのかを確認できる場合は、hdlシミュレーションを実行してください。このショートカットを使用できない場合は、
ワードサイズ以外の書き込みは、読み取り-変更-書き込みする必要があります。ldr、bic、shift、または、str。誰がそれをするかに関係なく、あなたかコンパイラー。
自分でやるだけです。コンパイラがどのようにやってくれるのかわかりません。gccを含むコンパイラは、あなたが言っていると思われる特定のアクセスを実行するのに十分な苦労をしています。
*(volatile unsigned int *)(SOME_ALIGNED_ADDRESS)= some_value;
何年も前にこれをあきらめたので、私の構文はおそらく間違っていますが、常にunsigned intサイズのストアを生成するとは限らず、コンパイラが生成したくない場合は生成しません。それが確実にできない場合、この変数または構造体に対して1つのフレーバーのロードとストアを作成し、その変数または構造体に対して別のフレーバーを作成することをどのように期待できますか?
したがって、コンパイラが生成する必要のある特定の命令がある場合、失敗します。アセンブラ、ピリオドを使用する必要があります。特に、ldm、ldrd、ldr、ldrh、ldrb、strd、str、strh、strb、およびstm。
あなたがどれだけのnvramを持っているかはわかりませんが、あなたの問題の解決策は、すべてをnvramで32ビットサイズにすることだと思います。チェックサムを実行するために数サイクル余分に書き込みますが、コードスペースと(揮発性の)RAMの使用量は最小限です。組み立てはほとんど必要ありません(または、それに慣れている場合は何も必要ありません)。
それほど多くの最適化が心配な場合は、他のコンパイラを試すこともお勧めします。少なくとも、gcc 3.x、gcc 4.x、llvm、およびrvctを試してください。Keilに付属しているバージョンがあると思います(ただし、実際のrvctコンパイラとの比較はわかりません)。
私はあなたのバイナリがどれほど小さくなければならないかについての感覚を持っていません。ものをnvramにパックする必要があり、すべての32ビットエントリを作成できない場合は、いくつかのアセンブラヘルパー関数、get32とput32の1つのフレーバー、get16とput16の2つのフレーバー、およびget8とput8の4つのフレーバーをお勧めします。物事が詰め込まれているコードを書いているときにわかるので、直接またはマクロを介してコーディングしたり、get16またはput8のフレーバーを定義したりできます。これらの関数は単一のパラメーターのみを持つ必要があるため、それらを使用するコードスペースのコストはゼロであり、パフォーマンスは、コアのフレーバーに応じて、ブランチでのパイプフラッシュの形式になります。私が知らないのは、この50または100のputおよびget関数の命令がコードサイズの予算を壊してしまうということですか?もしそうなら、あなたはCを使うべきかどうか疑問に思います。特にgcc。
また、サイズが非常に重要な場合は、腕の代わりに親指を使用することをお勧めします。サイズが重要な場合は、thumb2を使用します。
コンパイラにそれを実行させる方法がわかりません。コンパイラ固有のプラグマである必要があります。これは、めったに使用されず、存在する場合はバグがある可能性があります。
どのコアを使用していますか?私は最近、AXIバスを備えたarm 11ファミリーの何かを扱っていますが、armは、ldrs、ldrbs、ldrhsなどのシーケンスを個別の32ビットまたは64ビットの読み取りに変換するという非常に優れた仕事をしています(はい、いくつかの個別の命令が単一のメモリサイクル)。コアと、このアームからnvramメモリへのインターフェイスがどこにあるかに応じて、コアの機能に合わせてコードを調整するだけで済む場合があります。しかし、これにはたくさんのシムをしなければならないでしょう、私はこれを知っているのは、アームのドキュメントからではなく、バスを見ることだけです。