H8-3664で採用されているI2Cについて


全に旨くはいかないことはWebでも話題になっているようですし、
H8Sを始め殆どのH8系の CPUでこのI2Cインタフェースを採用
しているので何らかの方法で回避できれば良いという考えでソフトを書き始めました。

ソフト構成

1)マスターとスレーブのドライバは一本化して書き、スレーブもマスターにもなれる構成とする。 
従ってプログラムはマスタースレーブで同じ物(アドレスだけが違 う)です。

2)通信は割り込みチェインで動作するとして、メインのプログラムに対してバック グラウンドで自動的に動作するイメージとする

3)メインのプログラムが割り込みを禁止した状態が任意の時間あってもI2C割り 込み通信が滞り無く進む(遅くはなるが)構成とする。

4)スレーブはサブアドレスを複数持つ構成に作る マスターは必ずサブアドレス指定でバスアクセスする(I2C仕様)

さらにテストプログラム環境として --------

1)マスターは4つのサブアドレスに対して、1,2,4,8バイトの書き込み読み出しを連続して行い、
書いたデータと読み出したデータを比較して一致を調べる。それを何らかのエラーがあるまで永遠に繰り返す。

2)スレーブはメインルーチンで割り込み禁状態にし、一瞬割り込み許可にする動作 を時間インターバル10uSから10mSまでの
間連続的に可変してI2Cのスレー ブ側の通信処理を邪魔をした状態で動作させる。 
これによりメインルーチンがどの 様に重くてもI2Cの通信が正確に行えるかどうか評価することが目的。

評価結果 

(1)1バイト転送ではサブアドレススタイルは取れない。(スレーブ側)  1バイト転送でスレーブがNACKビットを正しく返す構成にすると、
再スタート の(Sr)後のアドレスセレクションでACKビットが直前のNACKをACKに改訂するチャンスが無くてサブアドレスフォームでの通信は出来ない。

解決方法  1バイトの通信時はNACKの変わりに必ずACKを返すようにし、問題を回避する。 
マスターは場合により2バイト目を送るかも知れないがその場合2バイト目は スレーブの中で破棄する。2バイト以上のサブアドレス転送は問題なくできる。

(2)時々本来無ければいけないI2Cユニットからの割り込みが無くなる。(スレーブ側)  これはCPUの実行スピードとの関連問題です。 
あるI2C割り込みでその割り 込み処理ルーチンが実行中とします。 その処理ルーチンで当然割り込み要因をクリ アする動作をします。 
しかし、上記の様な環境ではそもそもかなり遅れて割り込み ルーチンが起動しています。 そうして今まさに割り込みをクリアしようとする
寸前 に非同期に動作しているマスターによりI2Cバスは次のフェーズに移行される場合 があります。 この場合新しいフェーズに移行した
割り込みは発生するのですが、そ の割り込みも一緒にクリアされるので結果として新しい割り込みが発生しないことが 起きます。

解決方法  割り込みは紛失するが、I2Cの状態遷移をプログラム側も簡単なステートマシン で管理することにより、さらに次の割り込みがあった場合、
紛失した割り込み処理を リカバーする方法を採ることによりかなり回復できる。 しかし現在ある1要因だけ 解決策が見えていない。

(3)スレーブデバイスをマスターからアドレスするとNACKが返されるタイミン グがある。  
これは(1)の状態の後のマスターからのタイミングにより発生するごくまれなケー スです。 
この場合マスターはリトライすることにより復帰できるのでその様に解決 する。

考察

H8のIICインターフェースユニットの基本的問題点は

1)通信速度を速めるために今処理している割り込み要因より進んでI2Cの次のフ ェーズが受け付けられる構成になっている。 
これは一見良い工夫のように見えるが 特にI2Cサブアドレス付きのプロトコルを採用すると評価結果(2)の様な思わぬ 落とし穴に落ちます。

2)3664の様な実行スピードが遅いCPUでは特に顕著になりますが、割り込み 状態がスタックされない構成なので評価結果(2)の様にプロトコルがチェインしな い。  
さらにステータスは割り込みが発生したときの状態をラッチして記憶しているわけ でなくプログラムが読みに行ったときのI2Cのバス状態を示しているので、
CPU の読みに行ったタイミングにより、同じ割り込み要因が違うステータスで読めること になる。 結果としてステータスだけで状態管理は出来ない。  

例としてバスサイクルが終わったストップを検出したとします。 そのとき割り込 みが発生するのですが、マスターが直ぐまた新しくバススタートをすると、
割り込み ステータスはバスの終了と開始の両方のビットが立っていて、それだけではこれから バスが始まるのか、もう始まって終わったのか全く判断付かない。 
その様なことが 割り込み処理に入るタイミングで様々に発生します。

確定範囲 

上の結果からH8のI2Cインタフェースでの使用できる確定範囲は

1)マスタモードでシリアルPROM等完全なI2Cデバイスを相手に読み書きする処理

2)スレーブデバイスとして、割り込みなど複雑なことは行わずにI2C処理にぴっ たり張り付いているような単純なスレーブ処理、
かつサブアドレス等のプロトコルを 持ち込まない  上記のような限定した使い方なら問題なく動作する。 

そう言えば日立提供のサン プルプログラムも限定な処理を割り込みなしで書いていましたよね。 
単なる雛形でな く、その形でしか動作しないと言うことです。