ESP32をUSBメモリとして動作させ、Padaukマイコンのダンプ結果をファイルにして、パソコン上で確認できるようにしたいと思います。
ESP32 マスストレージクラス
ESP32-S3は、USBメモリになることができます。サンプルプログラムが、スケッチ例のUSBの中のUSBMSCです。
このスケッチ例は、パソコンからESP32のメモリを読み書きすることを想定して作られているので、EPS32からファイルを操作することができません。そこで、ESP32からもファイルを操作できるように改造します。
FatFsでFATを操作
スケッチ例のFAT領域を自在に操作をしてくれる、FatFsという便利なプログラムを使います。
FatFsはFATの操作をしてくれますが、メモリへの読み書きの部分は自分で処理を書く必要があります。上記の上5つが最低限必要な関数です。
ff::DSTATUS ff::disk_initialize( BYTE drv /* Physical drive nmuber (0) */ ) { ff::DSTATUS s = 0; return s; } ff::DSTATUS ff::disk_status ( BYTE drv /* Drive number (always 0) */ ) { if (drv) return STA_NOINIT; return 0; } ff::DRESULT ff::disk_read ( BYTE drv, /* Physical drive nmuber (0) */ BYTE *buff, /* Pointer to the data buffer to store read data */ LBA_t sector, /* Start sector number (LBA) */ UINT count /* Sector count (1..128) */ ) { BYTE cmd; Serial.printf("disk_read drv:%d sector:%d count:%d\n", drv, sector, count); for(int i = 0; i < count; i++) { if(sector + i >= DISK_SECTOR_COUNT) { Serial.printf("disk_read RES_ERROR\n"); return RES_ERROR; } for(int f = 0; f < DISK_SECTOR_SIZE; f++) { buff[f] = msc_disk[sector + i][f]; } buff += DISK_SECTOR_SIZE; } return RES_OK; } ff::DRESULT ff::disk_write ( BYTE drv, /* Physical drive nmuber (0) */ const BYTE *buff, /* Pointer to the data to be written */ LBA_t sector, /* Start sector number (LBA) */ UINT count /* Sector count (1..128) */ ) { Serial.printf("disk_write drv:%d sector:%d count:%d\n", drv, sector, count); for(int i = 0; i < count; i++) { if(sector + i >= DISK_SECTOR_COUNT) { Serial.printf("disk_read RES_ERROR\n"); return RES_ERROR; } for(int f = 0; f < DISK_SECTOR_SIZE; f++) { msc_disk[sector + i][f] = buff[f]; } buff += DISK_SECTOR_SIZE; } return RES_OK; } ff::DRESULT ff::disk_ioctl ( BYTE drv, /* Physical drive nmuber (0) */ BYTE ctrl, /* Control code */ void *buff /* Buffer to send/receive control data */ ) { Serial.printf("disk_ioctl drv:%d ctrl:%d\n", drv, ctrl); ff::DRESULT res; BYTE n, csd[16]; DWORD cs; res = RES_ERROR; switch (ctrl) { case CTRL_SYNC : /* Make sure that no pending write process */ res = RES_OK; break; case GET_SECTOR_COUNT : /* Get number of sectors on the disk (DWORD) */ cs = DISK_SECTOR_COUNT; *(LBA_t*)buff = cs; res = RES_OK; break; case GET_BLOCK_SIZE : /* Get erase block size in unit of sector (DWORD) */ *(DWORD*)buff = DISK_SECTOR_SIZE; res = RES_OK; break; default: res = RES_PARERR; } return res; } ff::DWORD ff::get_fattime () { return ((DWORD)(2024 - 1980) << 25) | ((DWORD)8 << 21) | ((DWORD)21 << 16) | ((DWORD)13 << 11) | ((DWORD)46 << 5) | ((DWORD)(50 / 2) << 0); }
FatFsのホームページある、各マイコン向けのプログラムを参考に、必要な関数を書きました。
全ての関数をffというネームスペースの中に入れていますが、これは普通にコンパイルするとESP32のライブラリに既に入っているFatFsと関数名が被ってしまい、コンパイルできないためです。
#define FF_USE_STRFUNC 2 #define FF_PRINT_LLI 1 #define FF_PRINT_FLOAT 0 #define FF_STRF_ENCODE 3
また、ffconf.hの59行目以降を上記のように変更し、f_printfを使えるようにします。
これで、ff::f_openでファイルをオープンし、ff::f_printfでファイルの内容を書き出して、ff::f_closeでファイルをクローズするという、一般的はファイルの操作ができるようになります。
ダンプ結果をファイルに出力してみる
ファイルが追加されない
これまでシリアルモニターへ出力していたフラッシュROMの内容を、ファイルへ書き出すよう機能を追加します。
ダンププログラムは、スイッチを押すと実行するようにしました。
スイッチを押します。
ファイルは書かれているはずなのですが、ドライブの中にファイルが追加され表示されません。(README.TXTファイルは、サンプルにもともとあるファイルです。)
ここでUSBを抜き、刺し直します。すると追加したファイル(DUMP.TXT)が見えるようになりました。
DUMP.TXTを開くと、ダンプした内容が表示されました。ファイルの書き込みプログラムは正常に動作しているようです。
しかしUSBを抜き差ししないと追加したファイルが見えません。どうしたものか...。
USBメモリをイジェクトしたい
ESPUSB *myUSB; ... MSC.end(); delete myUSB;
ESP32からUSBメモリを切断(イジェクト)したいです。色々調べたのですが、その方法がわかりません。
MSC(Mass Storage class)はend()を呼ぶことで、MSCの処理を停止できるようです。これを試してみます。windowsの場合、MSC.end()を実行して1秒くらいすると、USBメモリのドライブが画面から消えて、切断されることがわかりました。しかしmacではドライブが表示され続けます。厄介なことに、ここでドライブを開こうとするとファインダーがフリーズします。
MSCのさらに上位のUSBクラスをdeleteして、USBの機能そのものを止めてみましたが、ドライブが画面上から消えることはありませんでした。
一度開始されたUSBの機能は、停止できないのでしょうか???
1日試行錯誤しましたが、USBドライブをESP32から切断する方法が見つかりませんでした。
回路的に強制切断
ソフトウェアでできないのであれば、ハードウェアで切断しましょう。USBのスイッチICを使います。このスイッチをESP32のIOでON,OFFします。
USBの切替スイッチICを使って回路を作りました。/EN信号をHighにするとUSBのINとOUT間が切断されます。
ESP32からファイルが思いのまま
EN信号をHighにすると即USBドライブが切断され、ドライブが画面上から消えます。EN信号をLowにすると、即座にドライブがマウントされドライブが表示されます。macもwindowsも両方大丈夫です。
USBスイッチをつけることで、ESP32側が追加したファイルを、即座にドライブの表示に反映できるようになりました。
実験していると、ファイルの書き出しの際もUSBが切断されていないと、正常に書き出せないことがわかりました。このため、ファイルに書き出す前にUSBを切断し、書き終わったらUSBのスイッチをONする必要があります。
さて次回は
フラッシュROMのダンプ機能が完成し、何を書いたのかわかるようになったので、フラッシュROMへプログラムデータを書き込む機能を追加したいと思います。
コメント