No.340
RaspberryPiのハードウェアI2Cをマスタにしてどうにかならないかと考えてみました。
BFで送受信の終了を監視し、SSPIF(ACKの終了)を監視してCKPをセットすれば良いっちゃ良いのだけど、不可能ではないけど面倒くさい処理の典型と化します。
クロックストレッチングを使わなくても(ACKの直後に次の送受信が始まっても)動く様にしておけばよいのはわかっていますが、PICのI2Cはクロックストレッチングが前提の構成(特にスレーブ送信)だし、RaspberryPiに限った問題なのでi2c-gpioを使ってクロックストレッチングを用いた方が素直な気がします。i2c-gpioが凄い足かせになるワケでもないようですし。
追記
どうにもモヤモヤするのでクロックストレッチングを使わない方法を考え続けてみました。帰りの車中は考え事に最適です。
条件を整理します。RaspberryPiのI2CがクロックストレッチングをしてくれないのですからPIC側の条件です。
タイミングチャートを読みますと、ACKのクロック(ワードの9クロック目)の立下りで割り込みフラグSSPIFがアクティブになった後、次のワードの最初のクロックの立ち上がりまでに送受信のコンディションを整えられれば何事もなく次のワードが扱えるようです。これはSSPIFで割り込みが発生してから半クロック分の時間が使えるとも言えます。I2Cのビットレートは一意ではありませんが、標準的なビットレートである100kbpsに限って考えるなら半クロックは5usec。32MHz動作のPICなら40命令ステップに相当する時間です。
PICは割り込みの入りと出にパイプラインロスが発生するのでそれぞれ1命令ステップが消費され、I2CのクロックとPICの動作クロックは同期していないし信号の立ち上がり立下り時間もあるので2命令ステップくらいの誤差は起こりえます。となると実処理のために使える命令ステップ数は最大で36程度です。
ザックリと考えるならSSPIFで割り込みに入ってから30命令ステップ以内に送受信コンディションを整えて割り込みから抜ければよいのでは?となる。
30命令ステップあれば書き込み(RaspberryPi→PIC)は間に合いそうです。
I2Cは1フェーズ内では読み出しか書き込みかどちらかしか出来ませんので、Pythonの読み出しコマンド(PIC→RaspberryPi)はI2Cにおいて2フェーズ(1つ目のフェーズでコマンドや読み出すアドレスを書き込み、2つ目のフェーズでデータを読み出す)で実行されます。すなわち、PICが受け取ったワードをキーに処理して次のワードで即応する必要はありません。受け取るだけ受け取ってから処理をし、次の返信フェーズに備えればいいのです。もし鬼連続でコールされても2つ目の読み出しフェーズでデバイスアドレスを送受信する時間は返信データを作るのに使えます。1ワードは9bit分ですから100kbpsなら720usecです。足りる足りないではなくこの時間で済むように作ればいいのです。つか、PICにとっては5,760命令ステップに相当する時間です。私はPIC16をアセンブラで書きますが、5000ステップ以上の処理など書きたくもない・・・。
割り込みベクタが一つしかないPIC16系で多重割り込みをするとI2Cのタイミングを外す可能性があります。他の処理はポーリングとなりますが、DMX512の送受信や位相制御のトリガー処理もポーリングで十分間に合っているので問題ないっしょ。むしろPIC1個にそんな沢山の仕事させるなってね(笑
あれ?クロックストレッチングを使わないで組めそうな気がしてきた。
なんのことやらオレメモ暴走独り言ですみません。
#RaspberryPi #電子工作
BFで送受信の終了を監視し、SSPIF(ACKの終了)を監視してCKPをセットすれば良いっちゃ良いのだけど、不可能ではないけど面倒くさい処理の典型と化します。
クロックストレッチングを使わなくても(ACKの直後に次の送受信が始まっても)動く様にしておけばよいのはわかっていますが、PICのI2Cはクロックストレッチングが前提の構成(特にスレーブ送信)だし、RaspberryPiに限った問題なのでi2c-gpioを使ってクロックストレッチングを用いた方が素直な気がします。i2c-gpioが凄い足かせになるワケでもないようですし。
追記
どうにもモヤモヤするのでクロックストレッチングを使わない方法を考え続けてみました。帰りの車中は考え事に最適です。
条件を整理します。RaspberryPiのI2CがクロックストレッチングをしてくれないのですからPIC側の条件です。
タイミングチャートを読みますと、ACKのクロック(ワードの9クロック目)の立下りで割り込みフラグSSPIFがアクティブになった後、次のワードの最初のクロックの立ち上がりまでに送受信のコンディションを整えられれば何事もなく次のワードが扱えるようです。これはSSPIFで割り込みが発生してから半クロック分の時間が使えるとも言えます。I2Cのビットレートは一意ではありませんが、標準的なビットレートである100kbpsに限って考えるなら半クロックは5usec。32MHz動作のPICなら40命令ステップに相当する時間です。
PICは割り込みの入りと出にパイプラインロスが発生するのでそれぞれ1命令ステップが消費され、I2CのクロックとPICの動作クロックは同期していないし信号の立ち上がり立下り時間もあるので2命令ステップくらいの誤差は起こりえます。となると実処理のために使える命令ステップ数は最大で36程度です。
ザックリと考えるならSSPIFで割り込みに入ってから30命令ステップ以内に送受信コンディションを整えて割り込みから抜ければよいのでは?となる。
30命令ステップあれば書き込み(RaspberryPi→PIC)は間に合いそうです。
I2Cは1フェーズ内では読み出しか書き込みかどちらかしか出来ませんので、Pythonの読み出しコマンド(PIC→RaspberryPi)はI2Cにおいて2フェーズ(1つ目のフェーズでコマンドや読み出すアドレスを書き込み、2つ目のフェーズでデータを読み出す)で実行されます。すなわち、PICが受け取ったワードをキーに処理して次のワードで即応する必要はありません。受け取るだけ受け取ってから処理をし、次の返信フェーズに備えればいいのです。もし鬼連続でコールされても2つ目の読み出しフェーズでデバイスアドレスを送受信する時間は返信データを作るのに使えます。1ワードは9bit分ですから100kbpsなら720usecです。足りる足りないではなくこの時間で済むように作ればいいのです。つか、PICにとっては5,760命令ステップに相当する時間です。私はPIC16をアセンブラで書きますが、5000ステップ以上の処理など書きたくもない・・・。
割り込みベクタが一つしかないPIC16系で多重割り込みをするとI2Cのタイミングを外す可能性があります。他の処理はポーリングとなりますが、DMX512の送受信や位相制御のトリガー処理もポーリングで十分間に合っているので問題ないっしょ。むしろPIC1個にそんな沢山の仕事させるなってね(笑
あれ?クロックストレッチングを使わないで組めそうな気がしてきた。
なんのことやらオレメモ暴走独り言ですみません。
#RaspberryPi #電子工作