組み込みソフトは、各ペリフェラルデバイスのレジスタの値を操作することでハードウェアを制御し、様々な動作を実現します。
このとき、
- あるレジスタの特定のbitだけ変更したい
- あるレジスタの特定のフィールドだけ変更したい
というときがある。
例として、Xilinx のUART transmitterのコントロールレジスタを見てみます。
受信FIFOのリセットをしたいとき、コントロールレジスタの2bit目だけを1にセットし、その他のレジスタはそのままの値にしておく必要がある。
ここで、単純に0x02(0000_0010)と書き込むと2bit以外の他のbitは0にセットされてしまい、意図しない動作になってしまう。
ここでRead-Modify-Writeが登場する。
Read-Modify-Writeとは
特定のビットだけ操作するためには、
- レジスタの現在の値を読み取り(READ)
- 読み取った値の特定ビットを変更し(MODIFY)
- 変更後の値を書き込む(WRITE)
を行う。このことをRead Modify Write(リード モディファイ ライト)という。
例:特定のbitを1にする
例として、特定のbitを1にセットする関数を示す。
1 2 3 4 5 6 7 8 |
void reg_bitset(uint32_t addr, uint32_t bitmask){ uint32_t regval = reg_read32(addr);//READ regval |= bitmask;//MODIFY reg_write32(addr, regval);//WRITE return; } |
ここで、reg_read32()
はモジュールのレジスタの値を読み出す関数とする。reg_write32()
は書き込み。
Read
まず、reg_read32()
でaddr
で指定したレジスタの値を読み出す。
Modify
次に、読み出した値regval
に対してbitmask
で1が立っているbitを1にセットします。例えば、bitmask
に0x0020が入力された場合はregval
の6bit目が1にセットされる。
Write
最後に、addr
へregval
の値を書き込みします。