|
本帖最后由 topdog 于 2021-2-21 12:48 编辑
ESP32-S2 是乐鑫生产的一款高度集成、高性价比、低功耗、主打安全的单核 Wi-Fi SoC,具备强大的功能和丰富的 IO 接口。ESP32-S2 集成了丰富的外围设备,有 43 个可编程 GPIO,可以灵活配置为 USB OTG、LCD 接口、摄像头接口、SPI、I2S、UART、ADC、DAC 等常用功能。ESP32-S2 具有 LCD 接口和 14 个可配置的电容触摸 GPIO,可为基于触摸屏和触摸板的设备提供良好的 HMI 解决方案。建议购买双type-c的版本,左侧是烧录程序的串口UART0,右侧是实现TinyUSB 功能的USB CDC。
第一:安装开发环境
1,下载安装Arduino IDE下载地址:
https://downloads.arduino.cc/arduino-1.8.13-windows.exe
2,首选项添加板型管理器(BoardsManager)的网址 :
https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_dev_index.json
3,在工具栏开发管理器中在线安装支持esp32 Arduino SDK 版本号1.0.5 rc7
4,下载支持ESP32 S2分支的arduino esp32 sdk文件,下载地址:
https://github.com/espressif/arduino-esp32/archive/esp32s2.zip
5,覆盖相应的文件
解压ESP32 S2分支文件按照下图选择文件或者文件夹,
复制黏贴到C:\Users\xxx\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.5-rc7文件夹中。(xxx是你电脑的用户名)
还有一种快捷到达该文件夹的技巧,打开Arduino IDE-->文件->首选项,点下图红笔笔迹处。
6,下载开发工具解压到tools文件夹
开发ESP32-S2需要esptool 3.0版本,下载地址:https://dl.espressif.com/dl/esptool-3.0.0-windows.zip
xtensa-esp32s2-elf的下载地址:https://dl.espressif.com/dl/xtensa-esp32s2-elf-gcc8_4_0-esp-2020r3-win64.zip
两个文件解压以后,复制黏贴到C:\Users\xxx\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.5-rc7\tools
第二:实现TinyUSB
Hathach的TinyUSB 库是用于嵌入式系统的开源跨平台 USB 主机设备堆栈,旨在内存安全,无需动态分配,所有中断事件的线程安全可延迟,然后在非 ISR 任务函数中处理。
Chegewara的EspTinyUSB是ESP32-S2的简单且静止的WiP库为了锻炼学习TinyUSB。两个库结合起来可以让ESP32 S2实现以下功能:CDC,通信设备类;MSC,大规模存储类;HID,人界面设备类:键盘,鼠标,游戏板,通用的进出;MIDI,乐器数字界面类;DFU,设备固件更新类;WebUSB,它使用供应商类来显示webusb的使用情况。
1,下载Chegewara的EspTinyUSB之sd_msc分支,下载地址:https://github.com/chegewara/EspTinyUSB/archive/sd_msc.zip 解压到C:\Users\xxx\Documents\Arduino\libraries\文件夹下。
2,用Hathach的TinyUSB 库中的msc_disk.c替换示例中的msc_disk.c 下面修改过的代码源于:
https://github.com/hathach/tinyusb/blob/master/examples/device/cdc_msc_freertos/src/msc_disk.c
[pre]#include "tusb.h"
#if CFG_TUD_MSC
// Some MCU doesn't have enough 8KB SRAM to store the whole disk
// We will use Flash as read-only disk with board that has
// CFG_EXAMPLE_MSC_READONLY defined
#define README_CONTENTS \
"This is tinyusb's MassStorage Class demo.\r\n\r\n\
If you find any bugs or get any questions, feel free to file an\r\n\
issue at github.com/hathach/tinyusb"
enum
{
DISK_BLOCK_NUM = 16, // 8KB is the smallest size that windows allow to mount
DISK_BLOCK_SIZE = 512
};
#ifdef CFG_EXAMPLE_MSC_READONLY
const
#endif
uint8_t msc_disk[DISK_BLOCK_NUM][DISK_BLOCK_SIZE] =
{
//------------- Block0: Boot Sector -------------//
// byte_per_sector = DISK_BLOCK_SIZE; fat12_sector_num_16 = DISK_BLOCK_NUM;
// sector_per_cluster = 1; reserved_sectors = 1;
// fat_num = 1; fat12_root_entry_num = 16;
// sector_per_fat = 1; sector_per_track = 1; head_num = 1; hidden_sectors = 0;
// drive_number = 0x80; media_type = 0xf8; extended_boot_signature = 0x29;
// filesystem_type = "FAT12 "; volume_serial_number = 0x1234; volume_label = "TinyUSB MSC";
// FAT magic code at offset 510-511
{
0xEB, 0x3C, 0x90, 0x4D, 0x53, 0x44, 0x4F, 0x53, 0x35, 0x2E, 0x30, 0x00, 0x02, 0x01, 0x01, 0x00,
0x01, 0x10, 0x00, 0x10, 0x00, 0xF8, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x29, 0x34, 0x12, 0x00, 0x00, 'T' , 'i' , 'n' , 'y' , 'U' ,
'S' , 'B' , ' ' , 'M' , 'S' , 'C' , 0x46, 0x41, 0x54, 0x31, 0x32, 0x20, 0x20, 0x20, 0x00, 0x00,
// Zero up to 2 last bytes of FAT magic code
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xAA
},
//------------- Block1: FAT12 Table -------------//
{
0xF8, 0xFF, 0xFF, 0xFF, 0x0F // // first 2 entries must be F8FF, third entry is cluster end of readme file
},
//------------- Block2: Root Directory -------------//
{
// first entry is volume label
'T' , 'i' , 'n' , 'y' , 'U' , 'S' , 'B' , ' ' , 'M' , 'S' , 'C' , 0x08, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4F, 0x6D, 0x65, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// second entry is readme file
'R' , 'E' , 'A' , 'D' , 'M' , 'E' , ' ' , ' ' , 'T' , 'X' , 'T' , 0x20, 0x00, 0xC6, 0x52, 0x6D,
0x65, 0x43, 0x65, 0x43, 0x00, 0x00, 0x88, 0x6D, 0x65, 0x43, 0x02, 0x00,
sizeof(README_CONTENTS)-1, 0x00, 0x00, 0x00 // readme's files size (4 Bytes)
},
//------------- Block3: Readme Content -------------//
README_CONTENTS
};
// Invoked when received SCSI_CMD_INQUIRY
// Application fill vendor id, product id and revision with string up to 8, 16, 4 characters respectively
void tud_msc_inquiry_cb(uint8_t lun, uint8_t vendor_id[8], uint8_t product_id[16], uint8_t product_rev[4])
{
(void) lun;
const char vid[] = "TinyUSB";
const char pid[] = "Mass Storage";
const char rev[] = "1.0";
memcpy(vendor_id , vid, strlen(vid));
memcpy(product_id , pid, strlen(pid));
memcpy(product_rev, rev, strlen(rev));
}
// Invoked when received Test Unit Ready command.
// return true allowing host to read/write this LUN e.g SD card inserted
bool tud_msc_test_unit_ready_cb(uint8_t lun)
{
(void) lun;
return true; // RAM disk is always ready
}
// Invoked when received SCSI_CMD_READ_CAPACITY_10 and SCSI_CMD_READ_FORMAT_CAPACITY to determine the disk size
// Application update block count and block size
void tud_msc_capacity_cb(uint8_t lun, uint32_t* block_count, uint16_t* block_size)
{
(void) lun;
*block_count = DISK_BLOCK_NUM;
*block_size = DISK_BLOCK_SIZE;
}
// Invoked when received Start Stop Unit command
// - Start = 0 : stopped power mode, if load_eject = 1 : unload disk storage
// - Start = 1 : active mode, if load_eject = 1 : load disk storage
bool tud_msc_start_stop_cb(uint8_t lun, uint8_t power_condition, bool start, bool load_eject)
{
(void) lun;
(void) power_condition;
if ( load_eject )
{
if (start)
{
// load disk storage
}else
{
// unload disk storage
}
}
return true;
}
// Callback invoked when received READ10 command.
// Copy disk's data to buffer (up to bufsize) and return number of copied bytes.
int32_t tud_msc_read10_cb(uint8_t lun, uint32_t lba, uint32_t offset, void* buffer, uint32_t bufsize)
{
(void) lun;
uint8_t const* addr = msc_disk[lba] + offset;
memcpy(buffer, addr, bufsize);
return bufsize;
}
// Callback invoked when received WRITE10 command.
// Process data in buffer to disk's storage and return number of written bytes
int32_t tud_msc_write10_cb(uint8_t lun, uint32_t lba, uint32_t offset, uint8_t* buffer, uint32_t bufsize)
{
(void) lun;
#ifndef CFG_EXAMPLE_MSC_READONLY
uint8_t* addr = msc_disk[lba] + offset;
memcpy(addr, buffer, bufsize);
#else
(void) lba; (void) offset; (void) buffer;
#endif
return bufsize;
}
// Callback invoked when received an SCSI command not in built-in list below
// - READ_CAPACITY10, READ_FORMAT_CAPACITY, INQUIRY, MODE_SENSE6, REQUEST_SENSE
// - READ10 and WRITE10 has their own callbacks
int32_t tud_msc_scsi_cb (uint8_t lun, uint8_t const scsi_cmd[16], void* buffer, uint16_t bufsize)
{
// read10 & write10 has their own callback and MUST not be handled here
void const* response = NULL;
uint16_t resplen = 0;
// most scsi handled is input
bool in_xfer = true;
switch (scsi_cmd[0])
{
case SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL:
// Host is about to read/write etc ... better not to disconnect disk
resplen = 0;
break;
default:
// Set Sense = Invalid Command Operation
tud_msc_set_sense(lun, SCSI_SENSE_ILLEGAL_REQUEST, 0x20, 0x00);
// negative means error -> tinyusb could stall and/or response with failed status
resplen = -1;
break;
}
// return resplen must not larger than bufsize
if ( resplen > bufsize ) resplen = bufsize;
if ( response && (resplen > 0) )
{
if(in_xfer)
{
memcpy(buffer, response, resplen);
}else
{
// SCSI output
}
}
return resplen;
}
#endif[/pre]
3,安装windows 10支持的驱动的准备工作。
Zadig是一款 Windows 应用程序,可安装通用 USB 驱动程序。下载地址:https://github.com/pbatard/libwd ... /b730/zadig-2.5.exe
4,EspTinyUSB 全家桶的效果
把all in one 烧录到开发板上,再把 USB CDC接入计算机,使用Zadig自动安装Ting USB各协议需要的支持Windows10的驱动。
[pre]#include "Arduino.h"
#include "webusb.h"
#include "cdcusb.h"
#include "mscusb.h"
#include "dfuusb.h"
extern "C" void init_disk();
WebUSB USBSerial;
CDCusb USBSerial1;
MSCusb msc;
DFUusb dfu;
void conCB(bool isCon)
{
Serial.printf("connection state changed, new state %s\n", isCon ? "connected" : "disconnected");
}
void mount_cb()
{
Serial.println("Mount");
}
void umount_cb()
{
Serial.println("Unmount");
}
void resume_cb()
{
Serial.println("Resume");
}
void suspend_cb(bool remote_wakeup_en)
{
Serial.println("Suspend");
}
void setup()
{
Serial.begin(115200);
msc.deviceID(0x303a, 0x0002);
if (!USBSerial.begin())
Serial.println("Failed to start webUSB stack");
if (!USBSerial1.begin())
Serial.println("Failed to start CDC USB stack");
dfu.begin();
msc.begin();
USBSerial.onConnect(conCB);
USBSerial1.onConnect(conCB);
EspTinyUSB::registerDeviceCallbacks(mount_cb, umount_cb, suspend_cb, resume_cb);
}
void echo_all(char c)
{
USBSerial.write(c);
USBSerial1.write(c);
Serial.write(c);
}
void loop()
{
while (USBSerial.available())
{
echo_all(USBSerial.read());
}
while (USBSerial1.available())
{
echo_all(USBSerial1.read());
}
while (Serial.available())
{
echo_all(Serial.read());
}
}[/pre]
TingUSB的全家桶就安装好了 :)计算机设备管理器显示的驱动协议。原来USB不仅仅是一种功能,大家有了感性认识了吧!
5,开启WebUSB效果的钥匙。
在Microsoft Edge浏览器地址栏输入edge://flags/ 启用 Experimental Web Platform features ,它是实验性Web平台功能,支持正在开发中的实验性Web平台的功能。
6,Arduino IDE先连接UART0烧录示例WebUSB,再把 USB CDC接入计算机,Microsoft Edge浏览器打开 https://www.tinyusb.org/examples/webusb-serial/
点击网页上的connect,选择ESP32 arduino device - 已配对,双击连接,在左侧sender区逐个输入Hello WebUSB! 右侧 receiver区也会有反馈出现。
7,另外,用两根usb连接线分别接左侧烧录程序的串口UART0和右侧TinyUSB 功能USB CDC。打开Arduino IDE的串口监视器的同时,用Microsoft Edge浏览器打开 https://www.tinyusb.org/examples/webusb-serial/ ,当连接ESP32 arduino device后,串口监视器马上显示回文:connection state changed, new state connected ,右下侧选择NL和CR,波特率115200,在输入栏输入一段英文文字,按发送,浏览器receiver区会有反馈出现。
(结束)
|
|