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 件のコメント:
コメントを投稿