goo blog サービス終了のお知らせ 

マイコン工作実験日記

Microcontroller を用いての工作、実験記録

OHCIでのアイソクロナス転送 - その2

2009-06-09 23:53:41 | USB
OHCI USBホストを使ってつないだUSBスピーカから、MP3再生ができるようになりました。すでに記事にしたとおりの簡略化した設計方針に基づいて実装したのですが、実際に音が出るまでに、2つの点でつまずいていました。

まずひとつめは、TDの設定。TDの内容が正しく設定されっていないと、OHCIはフレームの送受信をおこなってくれないのです。わかりやすいのはフレーム番号のフィールドで、現在のフレーム番号近くの値になっていないと、OHCIはすぐには送受信を開始してくれません。今回は、TDを設定する際に10ms後に送信するようにフレーム番号を設定したのですが、ちっとも送信してくれませんでした。



仕様書を読み直してわかったのは、CC (Condition Code)の必要性。この部分には転送結果が入るのですが、転送開始前にはまだHCに参照されていないことを示す値Not Accessedを設定しておく必要があったのでした。そして、さらにはCCの設定はTDの先頭部分だけではなく、PSW(Packet Status Word)の部分にも隠れているのが罠です。Offset/PSWの部分は、転送前には転送に使用するバッファの先頭へのオフセットを保持し、転送が終了するとホストコントローラ(HC)により転送結果を示すPSWに書き換えられます。



PSWは上図のようにCCとSIZEの部分からなるのですが、「このCCの部分がNot Accessedになっている場合に、コントローラはデータをOffsetとして解釈する」と規定されていたのです。この説明がOffsetの説明部分ではなくPSWの説明部分に出てくるというのが見落としてしまった原因です。

CCの設定もようやくとクリアしたのですが、まだ転送を開始してくれませんでした。2つめの問題個所はOHCIのレジスタのひとつ、HcPeriodicStartの設定値でした。このレジスタは1msのUSBフレームのうち、コントロールならびにアイソクロナス転送を開始するタイミングを指定するレジスタです。OHCIの仕様書には、「普通は3E67hを設定する」みたいな説明があるので、素直なわたしはそのとおりの値を設定していたのですが、これが罠でした。

USBは12MHzのクロックで動作するので、タイミングも12MHzのクロック数で数えます。1ms周期は12,000となり、16進数で表せば2EE0hです。コントローラは1ms周期が始まるとこのクロック数をカウントダウンしてゆき、HcPeriodicStartと一致するとインタラプト/アイソクロナス転送の処理を開始します。HcPeriodicStartとして3E67hを指定していては、1msよりも大きな値になっているので、いつまで待っても送信開始タイミングになりません!! つまり、OHCIの仕様書の明らかな間違いですね。試しに2000hを指定すると、無事に転送できるようになりました。

自分でも、典型的なハマリ易い罠に見事にはまってしまったと思います。どうにかこの罠から自力で這い出せて、喜んでいるところです。以下、再生実行の画面です。



host setupコマンドを実行することで、USB Hostの初期化処理をおこない、さらにUSBスピーカの音量設定とインターフェースの切り替えまでを実施しています。uplayコマンドによりSDカード上のファイル名(の最初の2文字)を指定して選曲するとともに、その再生を開始してUSBスピーカへ出力しています。

最新の画像もっと見る

2 コメント

コメント日が  古い順  |   新しい順
Unknown (Tsuneo)
2009-06-16 15:18:45
> 自分でも、典型的なハマリ易い罠に見事にはまってしまったと思います。

オリジナルのOHCI仕様書(hcir1_0a.pdf)は大変分かりにくいと定評があります。
これよりも、例えば、

SH7727 - 32 グループ USB ホストモジュール アプリケーションノート
http://documentation.renesas.com/jpn/products/mpumcu/apn/rjj05b0015_sh7727.pdf

などの方が良く書けています。こちらも参考にされると良いのではないでしょうか。

問題の箇所について見てみると、
オリジナルでは、
- Table 4-3: Field Definitions for Isochronous TD (p26)
- OffsetN: Used to determine size and starting address of an isochronous data
packet.

とあたかもレジスタの全てのbitをOffsetに使用するかのごとく書いてあるのに、実はOffsetを書き込む際に、NOT ACCESSEDを上位に埋め込まないとだめ、というのが少し後の方に出てきます。

4.3.2.3.1 Buffer Addressing (p27)
If the Host Controller supports checking of the Offsets, if either Offset[R] or Offset[R+1]does not have a ConditionCode of NOT ACCESSED or if the Offset[R+1] is not greater than or equal to Offset[R], then an Unrecoverable Error is indicated.

SH7727の方は、
- 表2.3 Field Definitions for Isochronous TD (p2-10)
- OffsetN bit15-13: 7 (111b), bit12-00, OFFSET
と、上位3ビットを111bとするよう明示しています。さらに、offset のbit12の意味についてもちゃんと書いてあります。
- 12ビット目で、上位20ビットの値の取得方法を選択します。0ならBufferPage0の値を、1ならBufferEndの上位20ビットの値を使用します。


HcPeriodicStart レジスタについては、
オリジナルでは、
- 7.3.4 HcPeriodicStart Register (p122)
- A typical value will be 3E67h.

ところが、別の章では FrameInterval の90%の値にするようにと書いていて、
- 5.1.1.4 Setup Host Controller (p42)
- Set HcPeriodicStart to a value that is 90% of the value in FrameInterval field of the HcFmInterval register.

FrameInterval の値は、
- 7.3.1 HcFmInterval Register (p120)
- FrameInterval: The nominal value is set to be 11,999 (= 2EDFh).

と、明らかに HcPeriodicStart の 3E67h は変です。

SH7727の方は、
- 表2.23 HcPeriodicStart Register (p2-34)
- 典型的な値はH'2A2F です。
と、順当な値を示しています。

Tsuneo
返信する
Re: Unknown (sirius506)
2009-06-17 00:16:25
>オリジナルのOHCI仕様(hcir1_0a.pdf)は大変分かりにくいと定評があります。

やっぱそうですよね。わたしも、以前ちょっと眺めて、その構成のわかりにくさからOHCIへの挑戦をためらっていました。某誌の解説記事に期待したのですが、アテがはずれて詳細に触れられなかったので、自力で取り組むことにした次第です。

>これよりも、例えば、
>SH7727 - 32 グループ USB ホストモジュール アプリケーションノート
>http://documentation.renesas.com/jpn/products/mpumcu/apn/rjj05b0015_sh7727.pdf
>などの方が良く書けています。こちらも参考にされると良いのではないでしょうか。

紹介ありがとうございます。たしかに、こちらの方がよく整理されていて読みやすいですね。図表も見つけやすいので、リファレンスとして使うのにも便利そうです。

>問題の箇所について見てみると、(以下略)

まさしくご指摘のとおりの箇所が、わたしのハマッタ箇所です。

おぉ、すばらしい。SHのマニュアルではちゃんと適切な場所で、適切な説明がなされており、設定値も正しくなっているのですね。

HcPeriodicStartの値については、FrameIntervalの90%という記述があることには、結構早くから気がついていたのですが、わたしはてっきり3E67hが90%相当の値なのだろうと思いこんでしまっていたため、時間を無駄にしてしまいました。
返信する

コメントを投稿

ブログ作成者から承認されるまでコメントは反映されません。