ソフトウェア処理の限界に挑む。AVR用高速I2Cライブラリを作ってみた。

マックスシリーズ?の最後はI2Cライブラリだ。シングルマスターモード専用ではあるが、その代わりにI2Cの全モード対応に加え、実転送速度は3M近くまで達する。以前に投稿した高速なI2Cライブラリだと受信が高速化できないが、今回は、送信と受信の転送速度を別々に設定できるようにすることで実質的な転送速度を高めることができるように工夫してみた。

【送受信速度とも1Mbps】

【送信速度は1Mbps、受信速度は0.5Mbps。受信時のLOW期間の幅が変化しているのがわかる】

ちなみにであるが、定電流ダイオードをプルアップ抵抗代わりに使うと立ち上がりが改善されるようだ。参考まで。

【5V、抵抗1Kでプルアップ(5mA)】

【5V、定電流ダイオードでプルアップ(5mA)】

最大速度であるが、HISPEEDモードに対応しているADS1015(ADC)で簡単に試してみたところ、16MHz/5Vシステムでプルアップ抵抗1Kのとき次のような結果になった。

・HISPEED … 送信3M/受信3M
・FAST(PLUS) … 送信3M/受信1M(※送信速度はI2C仕様から逸脱していることに注意)

【HISPEEDモードでの波形(前半はマスターコード)】

【対応している転送モード】
・STANDARD(Max100K)
・FAST(Max400K)
・FAST-PLUS(Max1M)
・HISPEED(Max3.4M)
・ULTRA-FAST(Max5M)

【対応している仕様】
・シングルマスターモード
・7ビットアドレス(1-bit左シフトしたアドレスを指定する)
・10ビットアドレス (アドレスに0x0100以上が指定されると10ビットアドレスモードになる)
・ゼネラルコール
・ソフトウェアリセット
・スタートバイト
・マスターコード
・デバイスID

【対応すると遅くなるのであえて対応してない仕様】
・同期化(マルチマスタでは必要)
・調停(マルチマスタでは必要)
・クロックストレッチ(マルチマスタかスレーブ側がCPUの場合は必要)

高速化のために通信中はクロックライン(SCL)をプッシュプル駆動している。そのため他のマスタやCPU内蔵のI2C機能のようなクロックストレッチが必要なスレーブを接続すると壊れてしまう可能性があることに注意してほしい。データライン(SDA)は送信時にプッシュプル駆動し、受信時に入力に切り替えている。可能な限りショート状態にはならないようにしたつもりだが何らかの原因によるスレーブの誤動作まで考慮するとかなりリスキーな実装だ。ULTRA-FASTモードであれば一方通行なので問題ないのだが...それ以外のモードではショート対策として保護抵抗経由でラインに接続したほうが良いのかもしれない。

これらの意味が理解できない、デバイスを壊したくない、デバイスを壊すリスクを負いたくない人は絶対利用しないでほしい。

【コンパイル環境】
Arduino-1.6.23では(一部を除き)正しくコード生成されるのだが、Arduino-1.8.X系ではコンパイルは通るものの理解不能な警告と完璧に間違ってるコードが生成され動作せず。ソースコードの問題なのかコンパイラの問題なのか...わかる人いたら教えて!!

【MaxTwiクラスの概要】

ライブラリを初期化する。

ライブラリを終了する。

ジェネラルソフトウェアリセットを行う。

デバイスIDを取得する。

送信を行う。※7-bitアドレスは1-bit左シフトしたアドレスを指定すること。10-bitアドレスはそのまま指定する。

受信を行う。※7-bitアドレスは1-bit左シフトしたアドレスを指定すること。10-bitアドレスはそのまま指定する。

【MaxWireクラスの概要(Arduino-Wire互換クラス)】

ライブラリを初期化する。

ライブラリを終了する。

ジェネラルソフトウェアリセットを行う。

デバイIDを取得する。

送信処理を開始する。※7-bitアドレスは1-bit左シフトしたアドレスを指定すること。10-bitアドレスはそのまま指定する。

送信を行う。

受信を行う。※7-bitアドレスは1-bit左シフトしたアドレスを指定すること。10-bitアドレスはそのまま指定する。

送信データを1バイト書き込む。

送信データを複数バイト書き込む。

受信済みのバイト数を取得する。

受信データを取得する。

受信データを調べる。

データバッファをクリアする。

【サンプルスケッチ】

【修正履歴】
2020-07-18
修正はないが...有名なライブラリを公開されている人がコンパイラが壊れていると言ってるのを見つけた。不正なコード生成はやはりコンパイラのバグということで間違いなさそうだが、いまのところボードバージョンが1.6.9か1.6.11であれば完全に正しいコードが出力されることは確認した。それ以外のバージョンは最新の1.8.xも含めて正しいコードを生成することができない。一部のコードが全く生成されないという現象もあるので最適化関連のコンパイラバグではないかと思うが、だとしたらコード修正に伴なって正しいコードが生成できるバージョンが変わる可能性もあるということだ。これは厄介な問題だ...

2020-07-17
ULTRA_FASTモードがバグっていたので修正。

2020-07-16
masterCode()とstartByte()の呼び出しを自動で行う改良。それと、かなりバグバグしてたのであちこち修正。
あいかわずArduinoのボードバージョンを変えるとコンパイルミス(不正なコード生成)してくれたり警告が出たり出なかったりする状況が続いている。コンパイルはArduinoボードバージョンは1.6.23で行っているが、1.6.x系の一部のバージョンでも動作しないものがあるようだ。

【ライブラリ】

【参照ライブラリ】
AVR用高速GPIOライブラリ