PR 記事には広告が含まれています
スポンサーリンク
Translate

ESP32をUSBメモリにしてダンプ結果をパソコンで確認できました

スポンサーリンク

ESP32をUSBメモリにしてダンプ内容をパソコンから確認

ESP32をUSBメモリとして動作させ、Padaukマイコンのダンプ結果をファイルにして、パソコン上で確認できるようにしたいと思います。

スポンサーリンク

ESP32 マスストレージクラス

スケッチ例にUSBメモリになれるプログラムがある

ESP32-S3は、USBメモリになることができます。サンプルプログラムが、スケッチ例のUSBの中のUSBMSCです。

このスケッチ例は、パソコンからESP32のメモリを読み書きすることを想定して作られているので、EPS32からファイルを操作することができません。そこで、ESP32からもファイルを操作できるように改造します。

FatFsでFATを操作

スケッチ例のFAT領域を自在に操作をしてくれる、FatFsという便利なプログラムを使います。

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を抜き差しすると追加したファイルが見えるようになる

ここでUSBを抜き、刺し直します。すると追加したファイル(DUMP.TXT)が見えるようになりました。

ESP32が生成したフラッシュROMのダンプファイル

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を強制的に切断する回路

ソフトウェアでできないのであれば、ハードウェアで切断しましょう。USBのスイッチICを使います。このスイッチをESP32のIOでON,OFFします。

USBの切替スイッチICを使って回路を作りました。/EN信号をHighにするとUSBのINとOUT間が切断されます。

スポンサーリンク

ESP32からファイルが思いのまま

USBスイッチでファイルを書き出すときに強制切断できるようになった

EN信号をHighにすると即USBドライブが切断され、ドライブが画面上から消えます。EN信号をLowにすると、即座にドライブがマウントされドライブが表示されます。macもwindowsも両方大丈夫です。

USBスイッチをつけることで、ESP32側が追加したファイルを、即座にドライブの表示に反映できるようになりました。

実験していると、ファイルの書き出しの際もUSBが切断されていないと、正常に書き出せないことがわかりました。このため、ファイルに書き出す前にUSBを切断し、書き終わったらUSBのスイッチをONする必要があります。

スポンサーリンク

さて次回は

フラッシュROMのダンプ機能が完成し、何を書いたのかわかるようになったので、フラッシュROMへプログラムデータを書き込む機能を追加したいと思います。