こんにちは、
S32K344のFlexIO I2C DMAに関していくつか質問がありますので、ご意見をいただければ幸いです。
1. FlexIOを使用してI2Cをエミュレートする場合、Txの長さは次のように設定されます。 サイズ+1 。これは 「送信シフターは、SCLピンの最後の立ち下がりエッジで追加のワードを1つロードします」 ? 1.png1.png1.png1.png
2.png2.png2.png2.png
2. DMAを使用してデータを送信する場合、 メジャーループ数 また、 サイズ + 1。これは同じ理由ですか? DMA を使用する場合、送信されるすべてのデータは Master->TxDataを呼び出すとき Flexio_I2c_Ip_MasterSendData 、 送信バッファ 長さは サイズ + 1 、最後のバイトは 0xFF または 0x00 ?
3.png3.png3.png3.png
3. データを受信するには、 メジャーループ数 設定されています サイズ – 1。なぜでしょうか?
4. S32K344でこれをテストしたところ、FlexIO I2CでDMAを使用してデータを受信すると、受信データが予想より1バイト少ないことがわかりました。オシロスコープで観測すると、最後のバイトのクロック信号には、わずか5~6ビット程度の波形しか見られない。S32K312での同じテストは問題なく動作します。
S32K344
S32DS3.6.4
RTD700
BR、
ジェイソン
こんにちは、 @Jason07さん
FlexIOは専用のI2Cペリフェラルではないため、その実装にはI2Cバスシーケンスを正しく完成させるための追加の内部手順が必要です。
伝送における「サイズ + 1U」は、FlexIOがI2Cフレームシーケンスを完了するために必要な最終的なシフター負荷に関連しています。この追加転送は、追加のペイロードバイトを表すものではありません。その代わりに、FlexIOハードウェア内部で最終的なクロックパルスを生成し、バスを正しく転送終了状態に移行させるために使用されます。
受信時のサイズ指定(-1U)が必要なのは、最後に受信したバイトが個別に処理されるためです。これにより、運転者は必要なNACKおよびSTOP条件を適切なタイミングで生成できます。
また、DMA転送モードを使用する場合、データ転送はキャッシュの一貫性の問題によって影響を受ける可能性があることを考慮してください。Dキャッシュが有効になっている場合に発生する可能性のある問題を回避するため、DMA TCDの送信元および送信先として使用されるバッファは、キャッシュ不可能なメモリ領域に割り当てられていることを確認してください。
Flexio_I2c_Ip_MasterReceiveData() 関数を呼び出す際に、TRANSFER_SIZE パラメータを増やす必要はありません。ドライバーは受信シーケンスの必要な内部調整をすでに処理しています。
最後に、あなたの設定を確認していると、両方のDMAチャネルに同じDMA割り込みコールバックが割り当てられていることに気づきました。Flexio_I2c_Ip.cに記載されている説明によると、送信と受信には異なるコールバック関数を使用する必要があります。
BR、VaneB
こんにちは、@ VaneBさん
「最後に受信したバイトは個別に処理される」というコードを見つけました。
しかし、送信に関してまだ疑問があります。割り込み駆動送信を使用する場合、長さはサイズ+1に設定されます。送信時にコードはそれが最後のバイトかどうかをチェックします。もしそうなら、0xFFか0x00を送ります。実際に送信されるデータの長さは依然としてサイズです。しかしDMAで送信を行う場合、DMAは送信バッファからサイズ+1バイトをコピーし、Flexio_I2c_Ip_MasterEndDmaTransfer関数ではShiftBufferに0xFFまたは0x00も埋めます。つまり、実際に送信されるデータ長はサイズではなくサイズ+1です。なぜでしょうか?
1.png1.png1.png
2.png2.png2.png
添付のプロジェクト内のTRANSFER_SIZE + 1のすべての箇所をTRANSFER_SIZE (8)に変更し、説明されているとおりDMA割り込みコールバックも変更しました。また、Dキャッシュも無効にしました。
FlexIO I2C送信にDMAを使用する際、オシロスコープで観察したところ、-Os最適化レベルではクロック信号は8バイトのみで正常でした。しかし、-O0最適化レベルでは、最初の8バイトのクロックは正常でしたが、ACK送信後に期待どおりストップ信号が生成されず、代わりに1ビットの余分なクロックパルスが現れました。
3.jpg3.jpg3.jpg
FlexIO I2C を DMA 経由で受信する場合、LPI2C0 はスレーブとして使用され、8 バイト (0x10~0x17) を送信します。-O0最適化レベルでは、7バイト目の送信中にクロック信号が異常になり、FlexIO受信バッファには6バイト(0x10~0x15)しか含まれません。
4.jpg4.jpg4.jpg
-Os最適化レベルでは、8バイト目の送信中にクロック信号が異常になり、FlexIO受信バッファには7バイト(0x10~0x16)しか含まれません。
5.jpg5.jpg5.jpg
上記の問題はすべて確実に再現可能です。
こんにちは、 @Jason07さん
重要な点は、I2Cがオープンドレイン信号方式を採用していることだと思います。
FlexIOは専用のI2Cコントローラではなくプログラム可能な周辺機器であるため、ドライバはシフターに読み込まれるビットパターンを制御してI2Cプロトコルイベントを生成しなければなりません。
このため、末尾の0x00と0xFFの値は、必ずしも追加のペイロードバイトとみなすべきではありません。むしろ、それらはSDAを適切な状態に配置し、ルーチンを完了させるために使用される。
Master->SendStop == TRUEの場合、ドライバーは0x00をロードし、SDAを強制的に低くなります。シフターの処理が完了し、FlexIOがラインを解放すると、プルアップによってSDAがハイになり、SCLは既にハイになっているため、必要な停止条件(SDA:LOW → HIGH、SCLはHIGH)が生成されます。
Master->SendStop == FALSEの場合、ドライバーは0xFFをロードし、SDAは解放されたままになります。プルアップによりSDAがハイレベルに維持され、停止状態が防止され、バスは繰り返し始動(SCLがハイレベルの間、SDA:ハイレベル→ローレベル)の準備が整います。
また、DMA最適化モードを有効にすることをお勧めします。例はスレッドにあります: S32K344 DMA Optimize オプション S32DS 3.6.0 RTD 6.0.0 を用いた FlexIO I2C の例。
最後に、カスタムボードを使用していますか、それともEVB/FRDMを使用していますか?