2018年8月13日月曜日

USB Dev MSC

 CubeでUSB DeviceのMSCのコードを出して試してる。

 [メモ] STM32CubeMX: USB MassStorageデバイス - Qiita

 とりあえずSDカードをSPIで初期化して、セクタ数を返すのと、読み出しリクエストでSDカードから読み出す機能を作ってみた。

 いちおう、デバイスの認識とかはできたが、ファイルがデータ化けしてしまう。一部のファイルは問題ないのだが。

 あと、転送要求はUSBのISRから投げられるので、SDカードの転送とかをISRの中で処理しなければいけない。
 SDカードのアクセスは頑張っても600usecくらいかかってるので、かなり大変。


 ISRの中だと都合が悪いし、ということで、なんとかできないかと思ったのだが。

 方法としては、転送要求を一旦FAILで返し、要求されたアドレスを記録しておき、メインループで読み込み、次にそのアドレスの要求が来たときに返す、という方法を考えてみた。しかし、1回FAILしてしまうと、そのアドレスはしばらく読まれないようだ。
 メモリを潤沢に使えるなら10KiBくらいバッファを確保しておき、そこに読んでおくという方法もあるだろうが、なんかもったいない。
 CCMからなら20KiBくらい割いてもいいけど、CCMだとDMA転送できない(SPIはDMA転送したい)。

 ままならんものだな。
 というか、普通のカードリーダーってどういうアルゴリズムで動いてるんだろうか。
 毎回転送要求が来たらそれを拒否れないわけで、となるとUSB Phyの割り込みからデータを読んで、とかする必要があるだろうけど、そうなるとOS上で処理できない。

 USBはかなり謎い。


 とりあえず、カードリーダーを作りたいわけじゃないので、とりあえずマイコンのFlashを使えるようにしてみるかな? 10KiBくらいあればいいし。って、なんか話が再起してる気がする。

 あと、今回、デバッグ用にUSB FSでDev CDC、USB HS(internal FS Phy)でDev MSCを試してみたのだけど、HS側がうごかなかった。うんともすんとも言わないし、Winのデバイスマネージャでも何も変化ないし、オシロでPD/PMを見てもGNDにプルダウンされたままだった。
 以前、USB FSでDev CDC、USB HS(intr FS Phy)でHost MSCを試したときはちゃんと動いたので、同時にDevを2本、とかはできないのかも。


 USB複合デバイスが使えればそれが一番楽なんだけど、Cubeだと生成できないい。
 USBで好きなデバイスを作れればいろいろ便利だろうけど、USBはかなり大変そう。USBカメラで缶サット的なモノを作るとか、USBモニタとしてHUB75に転送したり、できたら面白そうなんだけど。


追記:2018/08/14
 マイコンのFlashをMSCのストレージとして使えないか、と思っているのだけど、そうするとSDカードのような寿命の平均化ができない。
 あと、STM32F405は後半のセクタは1セクタあたり128KBなので、512バイトとか4KiBの書き換えが発生すると、一旦128KB分のメモリを確保してバックアップする必要がある。RAMが128K+CCMなので、どう考えても無理。
 他に取れる方法は、1) Flashの先頭領域をMSCに使う 2) 複数のセクタを使用する あたりか。
 前者の場合、最初の64KiBは16KBのセクタ4個なので、ギリギリでRAM退避ができそう(同時に動いてるプログラムに依存)。
 後者は、Flashは新規書き込みはFlash削除操作が不要で、書き換え時のみFlash削除操作が必要なので、例えばMSCを32KiBにすれば、丸々4回分はFlash削除が必要ない。そして1つ目のセクタが一杯になったら2つ目のセクタに必要なデータと新しいデータを退避して使用しつつ、2つ目が一杯になる前に1つ目のデータをすべて2つ目に移動しておいて、2つ目がいっぱいになったときは1つ目を削除して、みたいにする。自然とすべての領域が均等に使用されるので、寿命の平均化は考えなくていい。ただしデータのブロック番号とFlashのアドレスが一対一にならないので、これをどこに置くか、という問題が発生する。シークが極端に遅くなるだろうし、アドレステーブルをおいたセクタの消耗が激しくなる、という問題が残る。
 前途多難だなぁ。

 MSCを使用しないで、必要なデータは書き換え毎に都度全体をPCから512バイトずつ転送させる、みたいな方法が一番カンタンだし、自分で使うなら絶対そうするのだけど。他人に使わせるとか考えると、OS標準で使えるMSCは魅力的。

0 件のコメント:

コメントを投稿