2011年1月11日火曜日

[STM32]USBダブルバッファエンドポイントの挙動

STマイクロエレクトロニクスSTM32シリーズのUSBドライバに関して、
ダブルバッファエンドポイントの挙動についてのまとめ。

リファレンスマニュアルRM008にはそこそこ説明があるものの、レジスタの詳しい挙動までは読み切れないので実機で調べてみた。

まずは、OUTパイプに関して。
USB_EPnRを以下のように設定してみる。


DTOG_RX : 0
STAT_RX : 10 [NAK]
EPTYPE : 00 [bulk]
EP_KIND : 1 [DBL_BUF]
DTOG_TX : 0 または 1
STAT_TX : 00 [DISABLED]
EA : 適宜

この状態でUSBホストからOUTトランザクションを発行すると、STAT_RXNAKに設定されているので当然NAK応答となり、パケットは受信されない。

続いて次のように設定。

DTOG_RX : 0
STAT_RX : 11 [VALID]
DTOG_TX(=SW_BUF) : 0

この設定でホストからOUTトランザクションを1つだけ送ると、そのパケットを受信してレジスタは以下のように変化した。これはリファレンスマニュアルから読み取れる範囲内の挙動。

DTOG_RX : 1
STAT_RX : 11 [VALID] =変化なし
DTOG_TX(=SW_BUF) : 0


ここでパケットの内容を読まずに、更にホストからOUTトランザクションをもう一つ送ってみる。

DTOG_RX : 0
STAT_RX : 11 [VALID] =変化なし
DTOG_TX(=SW_BUF) : 0

となった。特筆すべきは、このレジスタの状態は2つ前の状態と同じであることだ。
2つ前の状態はダブルバッファの両方が空の状態で2つのパケットを受信できる状態、そして現在の状態はダブルバッファが2つとも埋まっている状態。まったく異なる状態にあるにもかかわらずレジスタ上ではその違いを区別することができない。
リファレンスマニュアルでは明記されていないが、私はダブルバッファが両方とも埋まるとSTAT_RX10[NAK]に変わるものだと思っていた。実際、シングルバッファではNAKに変化する。
この状態でパケットの内容を読まずに、更にもう一つOUTトランザクションを送ってみる。当然だけど、ホストにはNAKで応答している。

ここで、DTOG_TX(=SW_BUF)に1を書いてみる。

DTOG_RX : 1
STAT_RX : 11 [VALID] =変化なし
DTOG_TX(=SW_BUF) : 1

これでSW_BUFがトグルされると同時に、3つ目のOUTトランザクションがNAK応答を繰り返していたのがACK応答を返して終了した(これに対応してDTOG_RXが再度に変化)。

これでようやく詳細な挙動が把握できた。まとめると以下のような感じ。

シングルバッファでOUTトランザクションを受け取る場合
○受信したくないときは、STAT_RX10=NAKに設定しておく。
○受信するときはSTAT_RX11=VALIDにする。
○OUTトランザクションが完了するとSTAT_RX10=NAKに自動的に変化する。次のパケットを受信するには、ソフトウェアでSTAT_RX01を書き込む(トグル動作に注意)。

ダブルバッファでOUTトランザクションを受け取る場合
○受信したくないときは、STAT_RX10=NAKにしておく。
○初めて受信させるときは、
    DTOG_RX=0
STAT_RX=11=VALID
DTOG_TX(=SW_BUF)=0
  とする。
○OUTトランザクションが完了するとDTOG_RXが自動的にトグルするが、パケットを2つ以上受け取っても今度はSTAT_RXは変化せずに、ただNAKを返すようになるだけ。受信割り込み(CTR_RX)を確認するなどしてパケットを受け取ったら、ソフトウェアでやるべきことはDTOG_TX=(SW_BUF)を書き込むことだけ(CTR_RXは適宜消すように)。DTOG_RXSTAT_RXの状態は気にする必要はなく、バッファ管理とNAK応答はハードウェア側で適宜処理されている。

0 件のコメント:

コメントを投稿