SETレジスタとCLRレジスタ

新製品のマイコンのプログラムを本格的に書き始めた。

今までテスト用のプログラムをメーカーのライブラリを使って作っていたが、

うまく設定できてない部分があるのは把握していたので、レジスタを直接操作してあれこれやっていた。


このマイコンのレジスタ構成は面白いところがあり、

各種のフラグについて、値を読み書きできるレジスタとは別に、

SETレジスタとCLRレジスタというのが存在する。

INTENSET = 0x100; というのは INTEN |= 0x100; とほぼ同じで、

INTENCLR = 0x100; というのは INTEN &= ~0x100;とほぼ同じである。

割り込み有効フラグまでこんな方法で管理しているのは珍しい気がする。


この方法のメリットは割り込みなどで処理が競合しても影響を受けないことである。

INTEN |= 0x100; というのは INTENをリードして、0x100とのORをとって、ライトするという処理である。

このリードとライトの間に割り込みが入り INTEN &= ~0x20; が挟まったとする。

仮に最初のINTENが 0x20 だったとする。

0x120を書き込む直前で、割り込みでINTENが0x20→0x00と変化するも、

割り込み処理から戻ると 0x120となり 割り込み処理で消したフラグが復活してしまう。

こうならないように割り込み無効化して、書換を行いましょうという話である。

同じフラグをこうして競合して書き換えることがなければ問題ないのだが。


こういうことが比較的発生しやすいGPIOは対策されていることが多い。

1つはSETレジスタとCLRレジスタを用意するという方法。

もう1つはビット単位で操作出来るレジスタを用意することである。

32bitとか一括して操作出来るレジスタとは別に、1ビットずつリード・ライトできるレジスタもあると。

PORT ^= 0x10; のリード・ライトの間に PORT ^= 0x01; が挟まると、後者のビット反転が効かなくなるが、

PIN[4] ^= 1; と PIN[0] ^= 1; という形であれば、2つの書換は干渉しない。

PIN[4]のリード・ライトはその1ピンにしか影響しないためである。

両方用意しているのはそれはそれで珍しい気がするが、このマイコンは両方いけるみたいですね。


独特ではあるが、よくできた仕組みではあるのかな。

一般的なメモリとはだいぶ違うので戸惑いはありそうですけどね。

まぁマイコンってそんなもんだ。