OHCI USBホストを使ってつないだUSBスピーカから、MP3再生ができるようになりました。すでに記事にしたとおりの簡略化した設計方針に基づいて実装したのですが、実際に音が出るまでに、2つの点でつまずいていました。
まずひとつめは、TDの設定。TDの内容が正しく設定されっていないと、OHCIはフレームの送受信をおこなってくれないのです。わかりやすいのはフレーム番号のフィールドで、現在のフレーム番号近くの値になっていないと、OHCIはすぐには送受信を開始してくれません。今回は、TDを設定する際に10ms後に送信するようにフレーム番号を設定したのですが、ちっとも送信してくれませんでした。

仕様書を読み直してわかったのは、CC (Condition Code)の必要性。この部分には転送結果が入るのですが、転送開始前にはまだHCに参照されていないことを示す値

PSWは上図のようにCCとSIZEの部分からなるのですが、「このCCの部分が
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スピーカへ出力しています。
まずひとつめは、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スピーカへ出力しています。