CP2112をFreeBSDで使う

ArduinoでI2Cをいじって遊んでいたところ、そもそも最初のトリガーをEthernetかなにかで送らねばならず。
結局Raspberry Piにするか、もしくはArduino Yunにするのかと思っていたところ、いいものが見つかった。

サンハヤト: USB・I2C(SMBus)変換モジュール MM-CP2112B

CP2112というチップが載ったちんまいボードで、USBからI2C 1本とGPIO 8本が使える素敵な子。
しかもFreeBSDはCP2112のドライバを標準で積んでいて、kldloadするだけ。

買おうと思ったら、なぜか押し入れから発掘されたので、早速試してみた。(いつ買ったんだろうね??)

i2cデバイスは /dev/iic0 とかとして出現する。
制御には /usr/sbin/i2c コマンドが用意されている。(man i2c(8))
試してみよう。

# kldload cp2112
# kldload iic
# <ここでデバイスを挿す>
# dmesg
...
ugen0.6:  at usbus0
cp2112hid0 on uhub0
cp2112hid0:  on usbus0
cp2112hid0: part number 0x0c, version 0x03
gpio0:  on cp2112hid0
gpiobus0:  on gpio0
gpioc0:  on gpio0
iichb0:  on cp2112hid0
iicbus0:  on iichb0
iichb0: unsolicited interrupt, ignored
iic0:  on iicbus0
# i2c -s -f /dev/iic0
Hardware may not support START/STOP scanning; trying less-reliable read method.
Scanning I2C devices on /dev/iic0: 10 

アドレス 0x10 のデバイスがあっさり検出された。
データを書いてみる。が、世の中そう甘くない。

# printf "\000" | i2c -a 0x10 -d w -c 1
ioctl: error sending start condition

ちなみに -a 0x10 はアドレス指定、-d wは書き込みモード指定、-c 1 は書き込むバイト数、だ。

解決のヒントは先のスキャンで出ている Hardware may not support START/STOP scanning というメッセージで、CP2112のドライバが一部のIOCTLに対応していないことにある。
manによるところの、

Some I2C bus hardware does not provide control over the individual start, repeat-start, and stop operations.

というやつに該当するのだ。(該当部分の処理)
なので、これもmanの通りに tr モードを指定すればいい。

# printf "\000" | i2c -a 0x10 -d w -m tr -w 0 -c 1

これで成功。readも似たようなものなので、やりたい人はmanを読んでほしい。

※アドレスを間違えると i2c: ioctl(I2CRDWR) failed: No such file or directory と言われる。
FileでもDirectoryでも無いよ!と叫びたいが、エラーコードは ENOENT なので、メッセージが悪いと言えよう。

ちなみに。
CP2112さんを引っこ抜くと、panicする。とても辛い。


※これはVMware Fusionでの実験結果。実機でも同様。

本稿を書くにあたって、Vadim Zaigrin氏の Working with I2C in FreeBSD on Raspberry Pi を参考にさせてもらった。
実はこの方と同じ原因(ドライバが一部のIOCTLに非対応) なのだが、割と最近(May 2019)になってtr モードが追加されて、標準ツールでも使えるようになっていた。

もちろん、依然としてC言語で制御もできる。
i2cコマンドの実装や、Vadim Zaigrin氏の記事を参考にしてほしい。

Comments are closed.