Teensy (MXRT1062) では、Zephyr I2C ドライバをバイパスし、Zephyr SDK バージョン 0.17.4 (mcux-sdk-ng) が提供する NXP SDK を直接使用しています。つまり、以下の機能に実装されています。
modules/hal/nxp/mcux/mcux-sdk-ng/drivers/..:
.. /edma/fsl_edma.c
.. /dmamux/fsl_dmamux.c
.. /lpi2c/fsl_lpi2c.c
.. /lpi2c/fsl_lpi2c_edma.c
…など
Teensy LPI2Cマスターは、複数の(種類の)スレーブデバイスと通信します。
「ブロッキング」/「同期」モードでは、この設定を何日も問題なく実行できます。LPI2Cトランザクションは数百Hzの頻度で発生します。
同じ LPI2C トランザクション (および同じハードウェア) を使用して eDMA エンジンを設定すると、約 10 分から 1 時間ほどは正常に動作しますが、その後ハングアップします。
DMAのフレームレートを「同期」モードのレートのほんの一部まで下げても、バスは比較的短時間でハングアップしてしまう。
これは、バスが1つのスレーブデバイスのみに縮小された場合でも、複数の(種類の)スレーブデバイスを使用している場合に発生します。
ハングは、EdmaCompletionCallback (LPI2C_MasterCreateEDMAHandle(...) に登録) が受信した kStatus_LPI2C_PinLowTimeout イベントによって開始されます。
そうなると、システムを再起動する以外に正常に戻す方法はないようです。
ソフトリセットルーチンとは、以下の手順から構成されるものです。
* MIER、MDERのクリア
* LPI2C_MasterTransferAbortEDMA()、EDMA_AbortTransfer()、LPI2C_MasterReset()、LPI2C_MasterClearStatusFlags() を呼び出す
* MCRでFIFOをフラッシュする
* LPI2C_MasterInit() を使用して再初期化します
DMA完了コールバックが期限までに呼び出されなかった場合に呼び出されます。「ソフトリセット」の手順は全く効果がありません。
最初の kStatus_LPI2C_PinLowTimeout イベント以降は、完了イベントは発生しません。LPI2C.MSRでは、BBFビット(バスビジーフラグ)が常にセットされています。
Teensyのリセットボタンではこの状態はリセットされません。スレーブデバイスと再び通信するには、電源を入れ直す必要があります。
どなたかご意見をいただけると幸いです。
* mcux-sdk-ng SDKにバグがあり、誰かが修正パッチを提供している可能性はありますか?
* 同じ非常に安定した同期トランザクションが、eDMA制御下ではなぜ失敗するのか?
* kStatus_LPI2C_PinLowTimeoutが発生しないようにするためのeDMAの設定方法はありますか?(pinLowTimeout_nsを増やしても効果がありません)。クロックストレッチングは、すべてのスレーブで無効化されました。
* SDAラインを9回揺らすなどの方法以外で、すぐに回復できる方法はありますか?
サポートありがとうございます!
--ジョージ
こんにちは、 @zeebrog さん。
弊社製品にご関心をお寄せいただき、また弊社のコミュニティをご利用いただき、誠にありがとうございます。
Q1: mcux-sdk-ng SDKにバグがあり、誰かがパッチを作成した可能性はありますか?
A1:いいえ。入手可能なドキュメントに基づくと、RT1060上のLPI2C + eDMAに関するエラーは報告されていません。
Q2* 同じ非常に安定した同期トランザクションが、eDMA制御下で失敗する理由は何ですか?
A2:ブロッキングモードは、CPUがFIFOを直接処理するため、より堅牢です。eDMAモードでは、FIFOの処理はDMAのタイミングに依存するため、TXアンダーランやRXオーバーランが発生する可能性が高くなり、バスが停止する原因となることがあります。
Q3:* kStatus_LPI2C_PinLowTimeoutが発生しないようにするためのeDMAの設定方法はありますか?(pinLowTimeout_nsを増やしても効果はありません)クロックストレッチングは、すべてのスレーブで無効化されました。
A3:直接的には影響しません。PINLOWタイムアウトはタイムアウトフラグがトリガーされたときにのみ影響し、バスが停止する根本原因ではありません。
Q4* SDAラインを9回揺らすなどの方法以外で、すぐに回復できる方法はありますか?
A4:推奨される方法は、まずLPI2Cマスタを中止または無効にして、内部状態をリセットすることです(たとえば、MCR[MEN]をクリアするか、MCR[RST]をアサートすることによって)。
その後もバスが物理的にローレベルのままの場合、実際には、SDAを解放したままSCLを手動でパルスすることで、スレーブが未完了の転送を完了し、バスを解放するための一般的なI2Cバス復旧の回避策として使用できます。
よろしくお願いいたします。
5月