AXI IICの使い方
概要
XilinxのAXI IICの使い方について書いていこうと思います。
今回はZYNQでAXI IICを制御する方法について書きます。
AXI IICの接続と設定
AXI IICとの接続は次のようになっています。
AXIバスでZYNQと接続しています。
IICポートは外部のピンと接続されており、IIC接続するデバイスと繋がっています。
IPコアの設定は次のようになっています。
デバイスドライバの使い方
次にXilinx SDKでCPUのプログラムを書いていきます。
ソースコードは次の通りです。
#include <stdio.h> #include "platform.h" #include "xil_printf.h" #include "xiic.h" // 接続するIICデバイスのアドレス #define LCD_DEVICE_ADDRESS 0x3E int WriteData(u16 ByteCount, u8 *WriteBuffer); XIic xiic; int main() { int Status; XIic_Config *ConfigPtr; u8 WriteBuffer[16]; init_platform(); // AXI IICの初期化 ConfigPtr = XIic_LookupConfig(XPAR_IIC_0_DEVICE_ID); if (ConfigPtr == NULL) { return XST_FAILURE; } Status = XIic_CfgInitialize(&xiic, ConfigPtr, ConfigPtr->BaseAddress); if (Status != XST_SUCCESS) { return XST_FAILURE; } // 送信するデータ (今回はアドレス+データで、合計3byte送信) WriteBuffer[0] = 0x00; WriteBuffer[1] = 0x38; Status = WriteData(2, WriteBuffer); if (Status != XST_SUCCESS) { return XST_FAILURE; } cleanup_platform(); return 0; } int WriteData(u16 ByteCount, u8 *WriteBuffer) { int Status; Status = XIic_Start(&xiic); if (Status != XST_SUCCESS) { return XST_FAILURE; } // STOP conditionを発行するためにXIic_DynSendを使っている Status = XIic_DynSend(xiic.BaseAddress, LCD_DEVICE_ADDRESS, WriteBuffer, ByteCount, XIIC_STOP); if (Status != XST_SUCCESS) { return XST_FAILURE; } Status = XIic_Stop(&xiic); if (Status != XST_SUCCESS) { return XST_FAILURE; } return XST_SUCCESS; }
実行結果
ロジック・アナライザを使って出力波形を見た結果がこちらです。
START → ADDRESS → DATA → DATA → STOP
の順に出力されていることが確認できました。
XIic_MasterSendでSTOP conditionにならない?
今回データの送信にはXIic_DynSendという関数を使っています。
普通このデバイスドライバではXIic_MasterSendや、XIic_DynMasterSendを使って送信するはずです。
しかし、これらを使って記述したとろ、STOPビットが発行されず、うまく通信が行えませんでした。(下図参考)
データシートをよく読んでみたところ、AXI IICのレジスタ Transmit FIFO (Address: 0x108) の
8bit目と9bit目にそれぞれStartとStop Conditionを発行するためのレジスタがありました。
これらを1にしてあげればよいのですが、XIic_MasterSendや、XIic_DynMasterSendにはその記述が見当たりませんでした。
一方で、XIic_DynSendの中身を見てみると、DynSendDataという関数を呼び出しており、
XIic_WriteReg(BaseAddress, XIIC_DTR_REG_OFFSET, XIIC_TX_DYN_STOP_MASK | *BufferPtr++);
という記述があります。
XIIC_TX_DYN_STOP_MASK によってTransmit FIFOレジスタの9bit目をセットしているようです。
以上の理由により、今回はXIic_DynSendという関数を使っていますが、
このコードでも割り込みが正しく動作するのかなどは未確認です。