Xilinx AXI IIC Bus Interfaceを詳細に解説していきます。基本はデータシートの翻訳みたいなものですが、所々掘り下げて解説していきます。自分の理解もかねて。
今回自分はこのI2CのIPをslaveデバイスとして使ったので、slave寄りな内容になるかと思います。
まぁ、EEPROMや温度センサのコントロールとかは他の方が結構書いてくれてたりしますし。
- 1. Hardware
- 2. Register
- 2.1. Global Interrupt Enable(GIE)
- 2.2. Interrupt Status Register(ISR)
- 2.2.1. interrupt(0) – Arbitration Lost
- 2.2.2. interrupt(1) – Transmit Error/Slave Transmit Complete
- 2.2.3. interrupt(2) – Transmit FIFO Empty
- 2.2.4. interrupt(3) – Receive FIFO Full
- 2.2.5. interrupt(4) – IIC Bus is Not Busy
- 2.2.6. interrupt(5) – Addressed as Slave
- 2.2.7. interrupt(6) – Not Addressed as Slave
- 2.2.8. interrupt(7) – Transmit FIFO Half Empty
- 2.3. Interrupt Enable Register(IER)
- 2.4. Soft Reset Register(SOFTR)
- 2.5. Control Register(CR)
- 2.6. Status Register(SR)
- 2.7. Transmit FIFO(TX_FIFO)
- 2.8. Receive FIFO (RX_FIFO)
- 2.9. Slave Address Register(ADR)
- 2.10. Slave 10-Bit Address Register(TEN_ADR)
- 2.11. Transmit FIFO Occupancy Register(TX_FIFO_OCY)
- 2.12. Receive FIFO Occupancy Register(RX_FIFO_OCY)
- 2.13. Receive FIFO Programmable Depth Interrupt Register(RX_FIFO_PIRQ)
- 3. シーケンス
Hardware
受信データや送信データはFIFOに一度溜められて、送信命令や受信アクセスがきたらFIFOから読み出される仕組み。
Register
Global Interrupt Enable(GIE)
メインプロセッサ(microblaze)へ割り込み信号を伝えるかどうかをコントロールするレジスタ。
[30:0]はreserved, [31]がアクティブなbit。ちょっと変わってますね。
GIEをenableにすることでmicroblazeへの割り込み信号伝達を有効にすることができます。
0:すべての割り込みをdisable。後述のIERレジスタで有効にしている割り込み信号があっても、このbitをゼロにしている限りは割り込みはメインプロセッサに到達しない。
1: IERレジスタで有効にされている割り込み信号がmicroblazeにパスされる。
Interrupt Status Register(ISR)
割り込みステータスレジスタ。各割り込みの状態をモニタすることができる。基本的には各bitをreadして使用するが、bitにwriteすることで割り込みステータスをトグルすることができる。
interrupt(0) – Arbitration Lost
arbitration lost(バス競合負け)が発生したときにアサートされる割り込み。I2Cでは同一バス上に複数のマスタが存在することができるが、例えばマスタAがbusを支配している最中にマスタBが送信をしようとした場合、マスタAはbusの支配権をマスタBに奪われて処理を停止する。これが”arbitation lost”。つまり、他のマスタが邪魔してきたときにアサートされる割り込みがこのレジスタ。
コントロールレジスタ(CR)のMSMS bitを最初にクリアする際、この割り込みステータスをトグルするために1をwriteする必要がある。
interrupt(1) – Transmit Error/Slave Transmit Complete
この割り込みは、4パターンの事象によってアサートされる。
- master transmitterとして動作している時に、NACK(Not Acknowledge)が帰ってきたとき
- master receiverとして動作している時に、Control RegisterのTXAKが1にセットされたとき。
- slave transmitterとして動作している時に、masterデバイスが最後のbyteを送信し終えたとき
- slave receiverとして動作している時に、TXAKに1がセットされたとき
IICにおいて、masterとして動作しているときにNACKが帰ってくるのは指定したアドレスのslaveが存在していないか、指定したslaveがデータをもう受け取れないとき。
2つ目と4つ目はレシーバーとして動作させてる時にTXAK bitが1にsetされたとき、つまりackがdisableされたときに起こる。ackをアサートするのは「データを受け取った側」=receiverであるが、このreceiverがackを下げてしまうと送信側はデータが到達したかどうかを知る事ができずエラーとなってしまう。
interrupt(2) – Transmit FIFO Empty
これはあまり解説するまでもなく、送信fifoが空になったときにアサートされる割り込み。
interrupt(3) – Receive FIFO Full
受信fifoが一杯になったときにアサートされる割り込み・・・かと思いきや、単純に受信fifoがfullになったときにアサートされる割り込みではない。
RX_FIFO_PIRQレジスタの値とRX_FIFO_OCYの値が同じになった時にアサートされる。
RX_FIFO_PIRQによって、何byte分のデータがきたらfullとみなすのかを決めることができる。
interrupt(4) – IIC Bus is Not Busy
bus がbusy状態でないときにアサートされる割り込み。busy状態というのは、bus上のいずれかのIICデバイスがbusを支配している状態。もう少し具体的に言うと、Start Conditionが発行されているが、Stopコンディションが発行されていないとき。
interrupt(5) – Addressed as Slave
スレーブとしてアクセスされたときにアサートされる割り込み。
interrupt(6) – Not Addressed as Slave
repeated startを検出してアサートされる割り込み。
または、例えばmasterがbus上に存在しないslaveアドレスを指定して通信を開始したとき、Startコンディションが出てアドレスを送信した後Ackは永遠に帰ってこない。すると、Stopコンディションにならず状態が進まない。この割り込みレジスタは、このような状態を検出する。
interrupt(7) – Transmit FIFO Half Empty
TX_FIFO_OCYのMSBが0となっているときにアサートされる割り込み。
このIPでは送信fifoは16byte分のフィールドを持っている。この16byteのうちどのくらいが占有されているかを示すのがTX_FIFO_OCYレジスタだが、MSBが0ということは、少なくとも半分は送信fifoが空いているということ。
Interrupt Enable Register(IER)
先に述べた8種類の割り込みを個別に有効にするレジスタ。
対応するbitに1を書き込むことで、その割り込みを有効にできる。
ここで割り込みを有効にしても、GIEレジスタを有効にしていなければmicroblazeには割り込み信号はアサートされないので注意。
Soft Reset Register(SOFTR)
すべてのレジスタをリセットすることができるレジスタ。0xAを書き込む。
Control Register(CR)
Master/Slave Mode Select(MSMS)に1を書き込む前に、TX_FIFOレジスタにはアドレスを格納しておく必要がある。
AXI IIC Enable(EN)
これがなきゃ始まらない!AXI IICモジュールのenableレジスタ。
0 : AXI IICをリセットし、disableする。しかし、レジスタやFIFOの中身はリセットされない。あくまで、モジュールを動作しない状態にするだけ。
1 : AXI IICをenableにする。
Transmit FIFO reset(TX_FIFO Reset)
送信fifoをリセットする。arbitration lostが発生したり、送信エラーが発生したときは、必ずこのbitに1を書いて送信fifoをリセットする必要がある。
Master/Slave Mode Select(MSMS)
このbitが0から1にセットされたとき、本モジュールをmaster modeにしてSTARTコンディションを生成する。逆にこのbitが1から0にクリアされたとき、本モジュールはslave modeに戻り、STOPコンディションが生成される。ただし、arbitration lost(バス競合負け)が発生したことによって強制的にslave modeに戻った場合はSTOPコンディションは生成されない。
Transmit/Receive Mode Select(TX)
このモジュールを受信状態にするのか、送信状態にするのかを指定するレジスタ。
0 : 本モジュールをreceive modeにする
1 : 本モジュールをtransmit modeにする
このレジスタをセットしたからといって、アドレスと一緒に送信されるR/W bitがセットされる訳ではない。送信モードとして使用する場合は、送信アドレスをTX_FIFOに書き込む際にR/W bitをLSBに書き込んでおく必要があるので注意。
Transmit Acknowledge Enable(TX AK)
acknowledgeサイクルの時にAckを出力するかNACKを出力するかを選択する。
0 : ACKを出力
1 : NACKを出力
master側がslaveにリード要求をしてslaveから最後のbyteを受け取るときは、masterからslaveへNACKを出力する。このレジスタは、その最後のbyteを受けとってからNACKを出力するまでの間に1にsetしておく必要がある。
Repeated Start(RSTA)
本moduleがmasterとして動作しているとき、Repeated Start Conditionを発行するために使用するレジスタ。
通常はmasterが一つの通信を終了するときにSTOP Conditionを発行するが、Repeated Start Conditionを発行することで、連続して他のslaveデバイスへアクセスすることができる。
repeated START Conditionの発行タイミングを間違えるとbusの占有権が他のmasterに奪われてarbitration lostが発生する。このbitは、repeated STRAT Conditionが発行されたのち、TX_FIFOに次のslaveアドレスを書き込む前にクリアしておく必要がある。
General Call Enable(GC_EN)
General Callが来た時に応答するかどうかを設定するレジスタ。
通常、IICは特定のslaveのアドレスを指定して通信するが、General Call(address all 0x0)を使用することで、すべてのslaveに対して一斉にアクセスをすることができる。
Status Register(SR)
モジュールの状態を示すレジスタ。
Addressed By a General Call(ABGC)
General Callでアクセスされたときにアサートされるbit。
Addressed as Slave(AAS)
IIC busで指定されたアドレスが本モジュールのアドレス(ADRレジスタの値)と一致していたときにアサートされるbit。
Bus Busy(BB)
START Conditionが検出されているが、まだSTOP Conditionが検出されていないときにアサートされるbit。つまり、bus上のいずれかのmaster moduleがbusを占有しているときにアサートされる。
Slave Read/Write(SRW)
Slave deviceとしてアクセスされたとき、masterからwrite命令が来ているかread命令が来ているかを示すレジスタ。
0 : マスタからwrite命令を受信した
1 : マスタからread命令を受信した
Transmit FIFO full
送信FIFOがfullになったときにアサートされるレジスタ。
Receive FIFO full(RX_FIFO_Full)
受信FIFOがfullになったときにアサートされるレジスタ。少し紛らわしいのが、Receive FIFO Full割り込みレジスタとの関係。割り込みの方はRX_FIFO_PIRQで設定した分のバイトを受信したときにアサートされる。それに対して、このステータスレジスタは本当にRX_FIFOがfullになったとき(16Byte分のデータが受信されたとき)にアサートされる。
Receive FIFO empty(RX_FIFO_Empty)
受信FIFOが空のときにアサートされるレジスタ。
Transmit FIFO empty(TX_FIFO_Empty)
送信FIFOが空のときにアサートされるレジスタ。
Transmit FIFO(TX_FIFO)
AXI IIC Transmit Data
送信するデータを入力するbit。ここに書かれたデータは送信FIFOへスタックされる。
Start
startコンディションやrepeated startコンディションを発行する際に使用するレジスタ。
Stop
stopコンディションを発行する時に使用するレジスタ。最終byteを送信したとき、あるいは受信したときにstopコンディションが発行される。
Receive FIFO (RX_FIFO)
受信したデータを取り出すためのレジスタ。受信fifoに溜まったデータを1byteずつ取り出す。
Slave Address Register(ADR)
AXI IIC Interfaceをslaveとして使用するときのデバイスアドレスを定義する。
Slave 10-Bit Address Register(TEN_ADR)
10bit addressing modeで使用するときに設定するレジスタ。ADRの7bitの上にこのレジスタの3bitを組み合わせることで10bitのアドレスとなる。
Transmit FIFO Occupancy Register(TX_FIFO_OCY)
送信fifoにどれくらいデータが溜まっているかを示すレジスタ。ここで示される値+1をした値が送信fifoに溜まっているbyte数。つまり、fifoが空になっているかどうかは判別することができない。ここは注意が必要。
Receive FIFO Occupancy Register(RX_FIFO_OCY)
受信fifoにどれくらいのデータが溜まっているのかを示すレジスタ。ここで示される値+1をした値が受信fifoに溜まっているbyte数。つまり、fifoが空になっているかどうかは判別することができない。ここは注意が必要。
Receive FIFO Programmable Depth Interrupt Register(RX_FIFO_PIRQ)
これはAXI IIC Interfaceをslaveとして使う上で非常に重要なレジスタで、このレジスタを使うことで擬似的に受信FIFOの容量を変更することができる。
例えばこのレジスタに0x3を設定した場合、RX_FIFO_OCYの値が0x3となったときにReceive FIFO full割り込みがアサートされる。言い換えると、0x3を設定した場合は4byteのデータを受信したときに割り込みをアサートするように設定できる。
シーケンス
IIC Slave Receive
- enableレジスタを1にセット
- slave address レジスタに任意のアドレス値をセット
- EX_FIFO_PIRQレジスタに0x0をセット。こうすることで、1byteでもデータが受信されたときにRX_FIFO_FULLの割り込みがアサートされる。
ここでいう1byteはアドレスは含まない。 - AAS割り込みを待つ。
- AASの割り込みが入ったら、masterから送信されたR/W値を読み取る。
- NAS 割り込みレジスタをクリアする。
- Receive FIFO割り込みをクリアし、NAS割り込みか、RX_FIFO_PIRQ割り込みを待つ。byteのデータを受け取るごとにRX_FIFO_PIRQ割り込みが発生する。割り込みを受け取ったら、割り込みをクリアする。その後またRX_FIFO_PIRQ割り込みを受け取ったらクリアする事を繰り返す。
- NAS割り込みが発生したことを検出したら、Receive FIFOからデータを取り出し、AAS割り込み ステータス をクリアする。
NAS(Not Addressed as Slave)はデータの終わりを検出する割り込み。そのため、NAS割り込みを見ればいつデータ受け取りを終了するかがわかる。
IIC Slave Transmitter
- Transmit Error/Slave Transmit Complete interruptレジスタがクリアされていることを確認する。
- slaveとしてアクセスされた後、AXI IIC interfaceは送信fifoの最初のbyteをマスタへ送信する。
- 1byteずつ送信fifoへデータを書き込んでいく。transmit FIFO empty割り込みがアサートされるときは、マスターがまだデータを要求している。error/transmit complete割り込みがアサートされたらマスターが必要なデータを全て受け取った事になる。
- error/transmit complete割り込みがアサートされたらNASも一緒にアサートされていることを確認する。
- これがすんだら、AAS割り込みステータスをクリアする。