前言
前面的文章《使用ESP32S2开发板制作U盘,支持无线访问》讲述了如何将ESP32S2开发板制作成一个U盘。本文继续延伸,讲述如何把开发板制作成一个看起来容量远远大于flash实际大小的U盘。为方便起见,就叫它“虚拟U盘”吧。 本文用到的工具,附在了第七章。
一、背景
ESP32S2开发板flash只有4M,但出于某些目的,把它插到主机(PC、Android 手机、平板、电视、车机等)上时,需要识别成一个2G的U盘(也可以是4G、8G,大小可指定),并且里面存放大于4M的文件,比如一个长4小时的MP3文件。 ——这听起来很玄妙!但实现起来非常简单!
二、制作虚拟磁盘VHD
- PC打开“创建并格式化硬盘分区”工具(磁盘管理也可),菜单栏点击“操作”-“创建VHD”,位置自选比如放在桌面,命名为“fat32_2g.vhd”,点击“确定”。
- 看到创建好的磁盘,在1区域右击鼠标-“初始化磁盘”-点选“MBR”-“确定”。
- 在2区域右击鼠标-“新建简单卷”,继续下一步,在格式化分区时,选择“FAT32”。然后“下一步”-“完成”。
三、生成磁盘数据
-
使用“HxD”工具,打开前面创建的硬盘:“工具”-“读取硬盘”-“硬盘3”。 这里可能会有疑问:逻辑硬盘中的“新加卷E”和物理硬盘中的“硬盘3”,是不是一回事。其实不是,逻辑硬盘是物理硬盘的一部分,简单说下区别: 逻辑扇区0,对应的是DBR扇区。DBR分为两部分:DOS引导程序和BPB(BIOS参数块)。DBR的开头:EB 3C 90(FAT16),EB 58 90(FAT32)。 物理扇区0,对应的是MBR扇区。开头为:33 C0 8E。 -
打开之后,点击“文件”-“另存为”,命名为“fat32_2g.data”。
四、生成.h头文件
打开工具“FileToh.exe”-“Open”,选择上一步生成的“fat32_2g.data”,等计算完成后点击“Save”,会提示“fat32_2g.h”已经生成。
五、改造read10函数
- 将头文件“fat32_2g.h”加入到自己的工程中;
- 在tusb_msc.c中,引用头文件。
- 改造tud_msc_read10_cb()函数.
#include "fat32_2g.h"
#define SKY_DISK_BLOCK_NUM (2*1024*1024*1024/512)
#define SKY_DISK_BLOCK_SIZE (512)
int32_t IsInRomSector(uint32_t lba) {
for (int32_t i = 0; i < sizeof(Index)/sizeof(int); i++) {
if (lba == Index[i]) {
return i;
}
}
return 0xFFFFFFFF;
}
int32_t tud_msc_read10_cb(uint8_t lun, uint32_t lba, uint32_t offset, void *buffer, uint32_t bufsize)
{
ESP_LOGD(__func__, "lun=%d, lba=%d, offset=%d, bufsize=%d, s_disk_block_size=%d", lun, lba, offset, bufsize, s_disk_block_size);
if (lun >= LOGICAL_DISK_NUM) {
ESP_LOGE(__func__, "invalid lun number %u", lun);
return 0;
}
#ifdef 0
const uint32_t block_count = bufsize / s_disk_block_size;
disk_read(s_pdrv, buffer, lba, block_count);
return block_count * s_disk_block_size;
#else
if(lba >= SKY_DISK_BLOCK_NUM)
{
ESP_LOGE(__func__, "invalid lba number %u", lba);
return 0;
}
const uint32_t secCnt = bufsize / SKY_DISK_BLOCK_SIZE;
int32_t secIdx;
int32_t sector;
static int32_t t=0;
for(int32_t i= 0; i <secCnt; i++)
{
sector = lba+i;
secIdx = IsInRomSector(sector);
if(secIdx != 0xFFFFFFFF)
{
memcpy(buffer + (SKY_DISK_BLOCK_SIZE*i), &Sector[secIdx][0], SKY_DISK_BLOCK_SIZE);
ESP_LOGI(__func__, "sector = %d hit!! secIdx = %d", sector, secIdx);
}
else
{
memset(buffer + (SKY_DISK_BLOCK_SIZE*i), 0, SKY_DISK_BLOCK_SIZE);
ESP_LOGD(__func__, "sector = %d miss! reply all 0", sector);
}
}
return bufsize;
#endif
}
六、测试
编译、烧写后,将开发板插到PC上,可以看到有一个2G大小的U盘。
在U盘中存入超长的音频文件并能播放,放在下一篇中介绍。
七、工具
FileToh HxD
八、参考
[ESP8266/ESP32]ESP32 S2 做一个假U盘
|