ルネサスのWebサイトにある、RX62NのUSBでXMODEMの
ソースを参考にしながらに、オリジナルのブートローダを開発する続きです。
「64バイトの整数倍のデータを受信すると固まる」問題に対処したいと思います。
まず、ソースコードをじっくり眺めてみると、RX62NのUSBはほとんど割り込みで動いているのがわかります。usb_hal.cの中のUSBHALInterruptHandler()という関数がそれで、この関数がやっていることを理解すれば、RX62NのUSBの全容が理解できます。
USBHALInterruptHandler()では5種類の割り込みを処理しています。それはVBus、DVST、CTRT、BEMP、BRDYです。
VBusはバスの電源状態が変化したときに発生します。DVSTはバスの状態が変化したとき、CTRTはコントロールパケットの受信時に、BEMPはバッファ(この場合は送信バッファ)が空になったとき、BRDYはバッファがレディ(この場合は受信バッファにデータが来た)になった場合に発生します。
これらのイベントの発生状況がわかるよう、発生したイベントを記録して、SCI0から出力させてみました。すると・・

最初にVBUS割り込みが発生して、その後、Suspend State→Default State→Suspend State→Default State→と遷移し、セットアップコマンドが送られてきているのがわかります。
bRequest=06となっているので、セットアップコマンドの大半はGET_Descriptorです。ホストは最初にいろいろなディスクリプタを読み出しています。最後にbRequest=09のSet Interfaceを設定して、初期化は終了します。
その次に来ているbRequest=21というのはクラスリクエスト(ここではCDC ACMクラス、つまり仮想COMポート)のSET_LINE_CODINGを示します。ボーレートやストップビットの有無を設定してきています。bRequest=22はSET_CONTROL_LINE_STATEといって、DSRなどの制御線の設定です。
こうして、デバイスドライバとRX62Nとの間で初期化のやりとりが行われています。
TeraTermでオープンすると、SET_LINE_CODINGなどのクラスリクエストが多発しますが、結局のところボーレートの設定くらいしかやっていません。オープンしたという情報は送られません。
TeraTermから文字を打つと、BRDY割り込みが発生します。1文字打つと1バイト長のパケットが生成されます。
では、本題に入りましょう。クリップボードに64文字をコピーしておいて張り付けると、64バイトのパケットに次いで0バイトのパケットが発生します。こうすると、このUSBプログラムはいとも簡単にフリーズします。
その理由がわかるまでかなり苦労しましたが、上のようなデバッグ用の出力を作ったことで問題解決できました。

この0バイト長パケットを受け取ったあとで、PIPE1CTRというレジスタの上位2ビットが"11"になっていました。INBUFMとBSTSというビットです。BSTSが鍵となりました。ハードウェアマニュアルでBSTSを検索してつぶさに調べていったら、1296ページに「ただし、Zero-Lengthパケット受信時は読み出し不可のためバッファクリアが必要」という記述がありました。USB XMODEMのサンプルソースではこの処理をやっていなかったため、0バイトのパケットを受信したときに固まってしまうのでした。
そこで、ReadBulkOUTPacket()関数の最後に
if(USBIO.D1FIFOCTR.BIT.DTLN == 0)
{
USBIO.D1FIFOCTR.BIT.BCLR = 1;
}
と付け加えてやることで、すべてうまくいきました。もう、何バイトのパケットを送ってもフリーズしません。
1048576バイトのパケットを送信してみたら約2秒かかっていたので、524kバイト/秒程度の速度で送れていることになります。
これでRX62N用のUSBブートローダを作成する下地ができました。
最近のコメント