I2Cクラスにレジスタ読み書きメソッドを追加(RPiベアメタルMicroPython)

サーバの移転もどうやらうまく行ったようなので、ベアメタルRaspberry Pi版MicroPythonの続きです。

前回、I2Cのクラスを作成した際、スレーブデバイスのレジスタのアドレスを指定して読み書きする高レイヤのメソッドについては

高レイヤは中レイヤの機能を用いて実装可能ですが、私自身のハードウェアにない機能の実装はなるべく後回しという方針に則り、見送ることにしました。

と書きましたが、その後、I2C接続デバイスのMicroPython用デバイスドライバを調べていると、高レイヤのメソッドを使っている例も結構あったので、既存のデバイスドライバとの互換性のため、方針変更して高レイヤのメソッドを実装しました。

その過程で、「stopビット無しのwriteの直後にwriteやreadを呼ぶと、最初のwriteが実行されない」というバグも見つかりました。
これは、最初のwriteの実際のI2C通信が始まる前に次のwriteやreadを行うと、最初のwriteが上書きされてしまうためだと思われます。
MicroPythonから実行する場合には、処理が遅いためにこのバグは起こらないのですが、Cのプログラムの中でwriteの後に続けてwriteやreadを呼ぶと発現しました。
そのため、stopビット無しのwriteコールから抜ける前に、実際にI2C通信が始まったことをステータスレジスタのTAビットで確認するようにしました。

今回追加したメソッドは、

readfrom_mem(slave_addr, register_addr, n_bytes, addrsize=8)
readfrom_mem_into(slave_addr, register_addr, readbuf, addrsize=8)
writeto_mem(slave_addr, register_addr, writebuf, addrsize=8)

の3つです。

これで、例えばレジスタを読むのに

i2c.writeto(addr, bytearray([register_addr]), False)
data = i2c.readfrom(addr, n_bytes)

というように行っていた処理が、

data = i2c.readfrom_mem(addr, register_addr, n_bytes)

と書けるようになりました。

また、I2Cオブジェクトのコンストラクタの仕様を変更し、生成時点でGPIOのAlternate Functionの設定やI2Cコントローラの初期化をするようにしました。
当初はコンストラクタはオブジェクトを割り当てるだけで、GPIOやコントローラの操作はinitメソッドの中で行う仕様でしたが、実際の使われ方ではinitせずに使い始める事例があったためです。

コメント