多くの ARM プロセッサには、I/O や RAM でさまざまな形式の読み取り-変更-書き込み操作を可能にする特別な機能が含まれています。ただし、Cortex-M3 および Cortex-M0 デバイスのスペクトル全体で一貫して機能する単一のアプローチはないようです。
MaskedSet32(uint32_t *target, uint32_t mask, uint32_t newval)
Cortex-M3 デバイスを対象としていたとき、ロードリンク/比較排他を使用して 32 ビット数値の一部を割り込みセーフな方法でアトミックに変更するようなメソッドをいくつか書きました。ただし、Cortex M0 はこれらの命令を提供しません。コードで割り込み状態を保存し、割り込みを無効にし、読み取り-変更-書き込みを実行し、割り込みを再度有効にすることもできますが、それは少しぎこちないようです。一部の Cortex プロセッサはビット バンディングまたはその他の機能を提供するため、1 つのアトミック メモリ操作を使用して 1 つのビットをアトミックに設定するなどの処理を実行できますが、異なるプロセッサでは処理が異なるようです。さらに、どの抽象化が最高の移植性を可能にするかはわかりません。
MaskedSet32
RAM 内のものについては、速度が重要でない場合、最適なアプローチは, Increment
, BottomPegI32
(のアトミック バージョン)などのサブルーチンを用意することだと思い*dest = (*dest < limit) ? limit : *dest;
ます。このようなアプローチは I/O でも使用できますが、一部のプロセッサが提供する特殊なハードウェアを利用しないのは残念なことに思えます。たとえば、Freescale KL-25 は次のような操作を実行できます。
MaskedSet32(&IOWhatever, 0x0F00, 0x0500); // Update bits 8-11 with a value of 0101
特定の I/O アドレスに 5 の値を書き込むことによって。I/O アドレスと他の 2 つのパラメーターをロードしてから、サブルーチンを呼び出して、I/O アドレスと定数をロードし5
、単一のメモリ ストアを実行することによって実行できることを実行するのは無駄に思えます。
私が目にするプロセッサ用のデモ コードの多くは、通常のブール演算子を使用しているだけですが、
IoWhatever = (IoWhatever & ~0x0F00) | 0x0500;
メインラインコードが別の部分を書き込んでいる間に、割り込みが I/O アドレスの一部に書き込もうとする状況で。一般的な慣例としてアトミック操作を使用する方がより安全なアプローチのように思えますが、コードをできるだけ停止させないような方法で使用したいと考えています。
uint32_t*
アドレス (にキャストされる)、フィールド オフセット、フィールド幅、および新しいデータを受け取る SetIoBitField マクロを定義する必要があります。 (定数に基づいて事前に計算されたマスクを使用)、インラインのロードリンク/ストア排他ループ (同様)、またはプロセッサ固有の特別な I/O 空間への書き込み、または定義して使用する必要がありますそのようなプリミティブを持ち、他のプロセッサで MaskedSet32 を使用するプロセッサでのみそのようなマクロ [ビットフィールドをサポートしていないプロセッサでの I/O ビット割り当てはとにかく異なる傾向があることを理解する]、またはどのアプローチが最も明確で最も移植可能に見えるでしょうか?