Add initial support for USB MSC (#5466)
* Add initial support for USB MSC * Add Firmware Upload/Download With MSC Current running firmware is available as file inside the MSC Disk. To update the firmware on the ESP, just copy a regular firmware bin into the drive * Support overwriting of the firmware file Overwriting a file is done totally differently on MacOS, Windows and Linux. This change supports it on all of them. * Allow CDC, FirmwareMSC and DFU to be enabled on boot * Add example ESP32-S2 USB-ONLY board * Various device code optimizations Added `end()` methods to MSC classes Made begin() methods safe to be called multiple times Optimized CDC class * Fix CDC Connect/Disconnect detection in Arduino IDE on Windows * Rework cdc_write * Update ESP32-S2 board configs
This commit is contained in:
parent
be84c8219c
commit
5bb8177aa1
@ -34,6 +34,9 @@ set(CORE_SRCS
|
|||||||
cores/esp32/StreamString.cpp
|
cores/esp32/StreamString.cpp
|
||||||
cores/esp32/USB.cpp
|
cores/esp32/USB.cpp
|
||||||
cores/esp32/USBCDC.cpp
|
cores/esp32/USBCDC.cpp
|
||||||
|
cores/esp32/USBMSC.cpp
|
||||||
|
cores/esp32/FirmwareMSC.cpp
|
||||||
|
cores/esp32/firmware_msc_fat.c
|
||||||
cores/esp32/wiring_pulse.c
|
cores/esp32/wiring_pulse.c
|
||||||
cores/esp32/wiring_shift.c
|
cores/esp32/wiring_shift.c
|
||||||
cores/esp32/WMath.cpp
|
cores/esp32/WMath.cpp
|
||||||
@ -151,6 +154,7 @@ set(includedirs
|
|||||||
libraries/SPI/src
|
libraries/SPI/src
|
||||||
libraries/Ticker/src
|
libraries/Ticker/src
|
||||||
libraries/Update/src
|
libraries/Update/src
|
||||||
|
libraries/USB/src
|
||||||
libraries/WebServer/src
|
libraries/WebServer/src
|
||||||
libraries/WiFiClientSecure/src
|
libraries/WiFiClientSecure/src
|
||||||
libraries/WiFi/src
|
libraries/WiFi/src
|
||||||
|
303
boards.txt
303
boards.txt
@ -1,5 +1,7 @@
|
|||||||
menu.UploadSpeed=Upload Speed
|
menu.UploadSpeed=Upload Speed
|
||||||
menu.SerialMode=Serial Connected To
|
menu.CDCOnBoot=USB CDC On Boot
|
||||||
|
menu.MSCOnBoot=USB Firmware MSC On Boot
|
||||||
|
menu.DFUOnBoot=USB DFU On Boot
|
||||||
menu.UploadMode=Upload Mode
|
menu.UploadMode=Upload Mode
|
||||||
menu.CPUFreq=CPU Frequency
|
menu.CPUFreq=CPU Frequency
|
||||||
menu.FlashFreq=Flash Frequency
|
menu.FlashFreq=Flash Frequency
|
||||||
@ -37,7 +39,7 @@ esp32c3.build.variant=esp32c3
|
|||||||
esp32c3.build.board=ESP32C3_DEV
|
esp32c3.build.board=ESP32C3_DEV
|
||||||
esp32c3.build.bootloader_addr=0x0
|
esp32c3.build.bootloader_addr=0x0
|
||||||
|
|
||||||
esp32c3.build.serial=0
|
esp32c3.build.cdc_on_boot=0
|
||||||
esp32c3.build.f_cpu=160000000L
|
esp32c3.build.f_cpu=160000000L
|
||||||
esp32c3.build.flash_size=4MB
|
esp32c3.build.flash_size=4MB
|
||||||
esp32c3.build.flash_freq=80m
|
esp32c3.build.flash_freq=80m
|
||||||
@ -173,19 +175,31 @@ esp32s2.build.core=esp32
|
|||||||
esp32s2.build.variant=esp32s2
|
esp32s2.build.variant=esp32s2
|
||||||
esp32s2.build.board=ESP32S2_DEV
|
esp32s2.build.board=ESP32S2_DEV
|
||||||
|
|
||||||
esp32s2.build.serial=0
|
esp32s2.build.cdc_on_boot=0
|
||||||
|
esp32s2.build.msc_on_boot=0
|
||||||
|
esp32s2.build.dfu_on_boot=0
|
||||||
esp32s2.build.f_cpu=240000000L
|
esp32s2.build.f_cpu=240000000L
|
||||||
esp32s2.build.flash_size=4MB
|
esp32s2.build.flash_size=4MB
|
||||||
esp32s2.build.flash_freq=80m
|
esp32s2.build.flash_freq=80m
|
||||||
esp32s2.build.flash_mode=qio
|
esp32s2.build.flash_mode=dio
|
||||||
esp32s2.build.boot=qio
|
esp32s2.build.boot=qio
|
||||||
esp32s2.build.partitions=default
|
esp32s2.build.partitions=default
|
||||||
esp32s2.build.defines=
|
esp32s2.build.defines=
|
||||||
|
|
||||||
esp32s2.menu.SerialMode.default=UART0
|
esp32s2.menu.CDCOnBoot.default=Disabled
|
||||||
esp32s2.menu.SerialMode.default.build.serial=0
|
esp32s2.menu.CDCOnBoot.default.build.cdc_on_boot=0
|
||||||
esp32s2.menu.SerialMode.cdc=USB CDC
|
esp32s2.menu.CDCOnBoot.cdc=Enabled
|
||||||
esp32s2.menu.SerialMode.cdc.build.serial=1
|
esp32s2.menu.CDCOnBoot.cdc.build.cdc_on_boot=1
|
||||||
|
|
||||||
|
esp32s2.menu.MSCOnBoot.default=Disabled
|
||||||
|
esp32s2.menu.MSCOnBoot.default.build.msc_on_boot=0
|
||||||
|
esp32s2.menu.MSCOnBoot.msc=Enabled
|
||||||
|
esp32s2.menu.MSCOnBoot.msc.build.msc_on_boot=1
|
||||||
|
|
||||||
|
esp32s2.menu.DFUOnBoot.default=Disabled
|
||||||
|
esp32s2.menu.DFUOnBoot.default.build.dfu_on_boot=0
|
||||||
|
esp32s2.menu.DFUOnBoot.dfu=Enabled
|
||||||
|
esp32s2.menu.DFUOnBoot.dfu.build.dfu_on_boot=1
|
||||||
|
|
||||||
esp32s2.menu.UploadMode.default=UART0
|
esp32s2.menu.UploadMode.default=UART0
|
||||||
esp32s2.menu.UploadMode.default.upload.use_1200bps_touch=false
|
esp32s2.menu.UploadMode.default.upload.use_1200bps_touch=false
|
||||||
@ -635,6 +649,103 @@ pico32.menu.DebugLevel.verbose.build.code_debug=5
|
|||||||
|
|
||||||
##############################################################
|
##############################################################
|
||||||
|
|
||||||
|
esp32s2usb.name=ESP32S2 Native USB
|
||||||
|
esp32s2usb.vid.0=0x303a
|
||||||
|
esp32s2usb.pid.0=0x0003
|
||||||
|
|
||||||
|
esp32s2usb.upload.tool=esptool_py
|
||||||
|
esp32s2usb.upload.maximum_size=1310720
|
||||||
|
esp32s2usb.upload.maximum_data_size=327680
|
||||||
|
esp32s2usb.upload.flags=
|
||||||
|
esp32s2usb.upload.extra_flags=
|
||||||
|
esp32s2usb.upload.use_1200bps_touch=true
|
||||||
|
esp32s2usb.upload.wait_for_upload_port=true
|
||||||
|
esp32s2usb.upload.speed=921600
|
||||||
|
|
||||||
|
esp32s2usb.serial.disableDTR=false
|
||||||
|
esp32s2usb.serial.disableRTS=false
|
||||||
|
|
||||||
|
esp32s2usb.build.tarch=xtensa
|
||||||
|
esp32s2usb.build.bootloader_addr=0x1000
|
||||||
|
esp32s2usb.build.target=esp32s2
|
||||||
|
esp32s2usb.build.mcu=esp32s2
|
||||||
|
esp32s2usb.build.core=esp32
|
||||||
|
esp32s2usb.build.variant=esp32s2usb
|
||||||
|
esp32s2usb.build.board=ESP32S2_USB
|
||||||
|
|
||||||
|
esp32s2usb.build.cdc_on_boot=1
|
||||||
|
esp32s2usb.build.msc_on_boot=1
|
||||||
|
esp32s2usb.build.dfu_on_boot=1
|
||||||
|
esp32s2usb.build.f_cpu=240000000L
|
||||||
|
esp32s2usb.build.flash_size=4MB
|
||||||
|
esp32s2usb.build.flash_freq=80m
|
||||||
|
esp32s2usb.build.flash_mode=dio
|
||||||
|
esp32s2usb.build.boot=qio
|
||||||
|
esp32s2usb.build.partitions=default
|
||||||
|
esp32s2usb.build.defines=
|
||||||
|
|
||||||
|
esp32s2usb.menu.PSRAM.disabled=Disabled
|
||||||
|
esp32s2usb.menu.PSRAM.disabled.build.defines=
|
||||||
|
esp32s2usb.menu.PSRAM.enabled=Enabled
|
||||||
|
esp32s2usb.menu.PSRAM.enabled.build.defines=-DBOARD_HAS_PSRAM
|
||||||
|
|
||||||
|
esp32s2usb.menu.FlashSize.4M=4MB (32Mb)
|
||||||
|
esp32s2usb.menu.FlashSize.4M.build.flash_size=4MB
|
||||||
|
esp32s2usb.menu.FlashSize.8M=8MB (64Mb)
|
||||||
|
esp32s2usb.menu.FlashSize.8M.build.flash_size=8MB
|
||||||
|
esp32s2usb.menu.FlashSize.8M.build.partitions=default_8MB
|
||||||
|
esp32s2usb.menu.FlashSize.16M=16MB (128Mb)
|
||||||
|
esp32s2usb.menu.FlashSize.16M.build.flash_size=16MB
|
||||||
|
|
||||||
|
esp32s2usb.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS)
|
||||||
|
esp32s2usb.menu.PartitionScheme.default.build.partitions=default
|
||||||
|
esp32s2usb.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS)
|
||||||
|
esp32s2usb.menu.PartitionScheme.defaultffat.build.partitions=default_ffat
|
||||||
|
esp32s2usb.menu.PartitionScheme.default_8MB=8M Flash (3MB APP/1.5MB FAT)
|
||||||
|
esp32s2usb.menu.PartitionScheme.default_8MB.build.partitions=default_8MB
|
||||||
|
esp32s2usb.menu.PartitionScheme.default_8MB.upload.maximum_size=3342336
|
||||||
|
esp32s2usb.menu.PartitionScheme.minimal=Minimal (1.3MB APP/700KB SPIFFS)
|
||||||
|
esp32s2usb.menu.PartitionScheme.minimal.build.partitions=minimal
|
||||||
|
esp32s2usb.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS)
|
||||||
|
esp32s2usb.menu.PartitionScheme.no_ota.build.partitions=no_ota
|
||||||
|
esp32s2usb.menu.PartitionScheme.no_ota.upload.maximum_size=2097152
|
||||||
|
esp32s2usb.menu.PartitionScheme.noota_3g=No OTA (1MB APP/3MB SPIFFS)
|
||||||
|
esp32s2usb.menu.PartitionScheme.noota_3g.build.partitions=noota_3g
|
||||||
|
esp32s2usb.menu.PartitionScheme.noota_3g.upload.maximum_size=1048576
|
||||||
|
esp32s2usb.menu.PartitionScheme.noota_ffat=No OTA (2MB APP/2MB FATFS)
|
||||||
|
esp32s2usb.menu.PartitionScheme.noota_ffat.build.partitions=noota_ffat
|
||||||
|
esp32s2usb.menu.PartitionScheme.noota_ffat.upload.maximum_size=2097152
|
||||||
|
esp32s2usb.menu.PartitionScheme.noota_3gffat=No OTA (1MB APP/3MB FATFS)
|
||||||
|
esp32s2usb.menu.PartitionScheme.noota_3gffat.build.partitions=noota_3gffat
|
||||||
|
esp32s2usb.menu.PartitionScheme.noota_3gffat.upload.maximum_size=1048576
|
||||||
|
esp32s2usb.menu.PartitionScheme.huge_app=Huge APP (3MB No OTA/1MB SPIFFS)
|
||||||
|
esp32s2usb.menu.PartitionScheme.huge_app.build.partitions=huge_app
|
||||||
|
esp32s2usb.menu.PartitionScheme.huge_app.upload.maximum_size=3145728
|
||||||
|
esp32s2usb.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS)
|
||||||
|
esp32s2usb.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs
|
||||||
|
esp32s2usb.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080
|
||||||
|
esp32s2usb.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FAT)
|
||||||
|
esp32s2usb.menu.PartitionScheme.fatflash.build.partitions=ffat
|
||||||
|
esp32s2usb.menu.PartitionScheme.fatflash.upload.maximum_size=2097152
|
||||||
|
esp32s2usb.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9MB FATFS)
|
||||||
|
esp32s2usb.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB
|
||||||
|
esp32s2usb.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728
|
||||||
|
|
||||||
|
esp32s2usb.menu.DebugLevel.none=None
|
||||||
|
esp32s2usb.menu.DebugLevel.none.build.code_debug=0
|
||||||
|
esp32s2usb.menu.DebugLevel.error=Error
|
||||||
|
esp32s2usb.menu.DebugLevel.error.build.code_debug=1
|
||||||
|
esp32s2usb.menu.DebugLevel.warn=Warn
|
||||||
|
esp32s2usb.menu.DebugLevel.warn.build.code_debug=2
|
||||||
|
esp32s2usb.menu.DebugLevel.info=Info
|
||||||
|
esp32s2usb.menu.DebugLevel.info.build.code_debug=3
|
||||||
|
esp32s2usb.menu.DebugLevel.debug=Debug
|
||||||
|
esp32s2usb.menu.DebugLevel.debug.build.code_debug=4
|
||||||
|
esp32s2usb.menu.DebugLevel.verbose=Verbose
|
||||||
|
esp32s2usb.menu.DebugLevel.verbose.build.code_debug=5
|
||||||
|
|
||||||
|
##############################################################
|
||||||
|
|
||||||
esp32wroverkit.name=ESP32 Wrover Kit (all versions)
|
esp32wroverkit.name=ESP32 Wrover Kit (all versions)
|
||||||
esp32wroverkit.upload.tool=esptool_py
|
esp32wroverkit.upload.tool=esptool_py
|
||||||
esp32wroverkit.upload.maximum_size=1310720
|
esp32wroverkit.upload.maximum_size=1310720
|
||||||
@ -865,7 +976,9 @@ feathers2.build.core=esp32
|
|||||||
feathers2.build.variant=um_feathers2
|
feathers2.build.variant=um_feathers2
|
||||||
feathers2.build.board=FEATHERS2
|
feathers2.build.board=FEATHERS2
|
||||||
|
|
||||||
feathers2.build.serial=1
|
feathers2.build.cdc_on_boot=1
|
||||||
|
feathers2.build.msc_on_boot=1
|
||||||
|
feathers2.build.dfu_on_boot=0
|
||||||
feathers2.build.f_cpu=240000000L
|
feathers2.build.f_cpu=240000000L
|
||||||
feathers2.build.flash_size=16MB
|
feathers2.build.flash_size=16MB
|
||||||
feathers2.build.flash_freq=80m
|
feathers2.build.flash_freq=80m
|
||||||
@ -874,10 +987,20 @@ feathers2.build.boot=qio
|
|||||||
feathers2.build.partitions=fatflash
|
feathers2.build.partitions=fatflash
|
||||||
feathers2.build.defines=
|
feathers2.build.defines=
|
||||||
|
|
||||||
feathers2.menu.SerialMode.cdc=USB CDC
|
feathers2.menu.CDCOnBoot.cdc=Enabled
|
||||||
feathers2.menu.SerialMode.cdc.build.serial=1
|
feathers2.menu.CDCOnBoot.cdc.build.cdc_on_boot=1
|
||||||
feathers2.menu.SerialMode.default=UART0
|
feathers2.menu.CDCOnBoot.default=Disabled
|
||||||
feathers2.menu.SerialMode.default.build.serial=0
|
feathers2.menu.CDCOnBoot.default.build.cdc_on_boot=0
|
||||||
|
|
||||||
|
feathers2.menu.MSCOnBoot.msc=Enabled
|
||||||
|
feathers2.menu.MSCOnBoot.msc.build.msc_on_boot=1
|
||||||
|
feathers2.menu.MSCOnBoot.default=Disabled
|
||||||
|
feathers2.menu.MSCOnBoot.default.build.msc_on_boot=0
|
||||||
|
|
||||||
|
feathers2.menu.DFUOnBoot.default=Disabled
|
||||||
|
feathers2.menu.DFUOnBoot.default.build.dfu_on_boot=0
|
||||||
|
feathers2.menu.DFUOnBoot.dfu=Enabled
|
||||||
|
feathers2.menu.DFUOnBoot.dfu.build.dfu_on_boot=1
|
||||||
|
|
||||||
feathers2.menu.PSRAM.enabled=Enabled
|
feathers2.menu.PSRAM.enabled=Enabled
|
||||||
feathers2.menu.PSRAM.enabled.build.defines=-DBOARD_HAS_PSRAM
|
feathers2.menu.PSRAM.enabled.build.defines=-DBOARD_HAS_PSRAM
|
||||||
@ -993,7 +1116,9 @@ tinys2.build.core=esp32
|
|||||||
tinys2.build.variant=um_tinys2
|
tinys2.build.variant=um_tinys2
|
||||||
tinys2.build.board=TINYS2
|
tinys2.build.board=TINYS2
|
||||||
|
|
||||||
tinys2.build.serial=1
|
tinys2.build.cdc_on_boot=1
|
||||||
|
tinys2.build.msc_on_boot=1
|
||||||
|
tinys2.build.dfu_on_boot=0
|
||||||
tinys2.build.f_cpu=240000000L
|
tinys2.build.f_cpu=240000000L
|
||||||
tinys2.build.flash_size=4MB
|
tinys2.build.flash_size=4MB
|
||||||
tinys2.build.flash_freq=80m
|
tinys2.build.flash_freq=80m
|
||||||
@ -1002,10 +1127,20 @@ tinys2.build.boot=qio
|
|||||||
tinys2.build.partitions=default
|
tinys2.build.partitions=default
|
||||||
tinys2.build.defines=
|
tinys2.build.defines=
|
||||||
|
|
||||||
tinys2.menu.SerialMode.cdc=USB CDC
|
tinys2.menu.CDCOnBoot.cdc=Enabled
|
||||||
tinys2.menu.SerialMode.cdc.build.serial=1
|
tinys2.menu.CDCOnBoot.cdc.build.cdc_on_boot=1
|
||||||
tinys2.menu.SerialMode.default=UART0
|
tinys2.menu.CDCOnBoot.default=Disabled
|
||||||
tinys2.menu.SerialMode.default.build.serial=0
|
tinys2.menu.CDCOnBoot.default.build.cdc_on_boot=0
|
||||||
|
|
||||||
|
tinys2.menu.MSCOnBoot.msc=Enabled
|
||||||
|
tinys2.menu.MSCOnBoot.msc.build.msc_on_boot=1
|
||||||
|
tinys2.menu.MSCOnBoot.default=Disabled
|
||||||
|
tinys2.menu.MSCOnBoot.default.build.msc_on_boot=0
|
||||||
|
|
||||||
|
tinys2.menu.DFUOnBoot.default=Disabled
|
||||||
|
tinys2.menu.DFUOnBoot.default.build.dfu_on_boot=0
|
||||||
|
tinys2.menu.DFUOnBoot.dfu=Enabled
|
||||||
|
tinys2.menu.DFUOnBoot.dfu.build.dfu_on_boot=1
|
||||||
|
|
||||||
tinys2.menu.PSRAM.enabled=Enabled
|
tinys2.menu.PSRAM.enabled=Enabled
|
||||||
tinys2.menu.PSRAM.enabled.build.defines=-DBOARD_HAS_PSRAM
|
tinys2.menu.PSRAM.enabled.build.defines=-DBOARD_HAS_PSRAM
|
||||||
@ -1166,7 +1301,9 @@ micros2.build.core=esp32
|
|||||||
micros2.build.variant=micro_s2
|
micros2.build.variant=micro_s2
|
||||||
micros2.build.board=MICROS2
|
micros2.build.board=MICROS2
|
||||||
|
|
||||||
micros2.build.serial=1
|
micros2.build.cdc_on_boot=1
|
||||||
|
micros2.build.msc_on_boot=1
|
||||||
|
micros2.build.dfu_on_boot=0
|
||||||
micros2.build.f_cpu=240000000L
|
micros2.build.f_cpu=240000000L
|
||||||
micros2.build.flash_size=16MB
|
micros2.build.flash_size=16MB
|
||||||
micros2.build.flash_freq=80m
|
micros2.build.flash_freq=80m
|
||||||
@ -1175,10 +1312,20 @@ micros2.build.boot=qio
|
|||||||
micros2.build.partitions=fatflash
|
micros2.build.partitions=fatflash
|
||||||
micros2.build.defines=
|
micros2.build.defines=
|
||||||
|
|
||||||
micros2.menu.SerialMode.cdc=USB CDC
|
micros2.menu.CDCOnBoot.cdc=Enabled
|
||||||
micros2.menu.SerialMode.cdc.build.serial=1
|
micros2.menu.CDCOnBoot.cdc.build.cdc_on_boot=1
|
||||||
micros2.menu.SerialMode.default=UART0
|
micros2.menu.CDCOnBoot.default=Disabled
|
||||||
micros2.menu.SerialMode.default.build.serial=0
|
micros2.menu.CDCOnBoot.default.build.cdc_on_boot=0
|
||||||
|
|
||||||
|
micros2.menu.MSCOnBoot.msc=Enabled
|
||||||
|
micros2.menu.MSCOnBoot.msc.build.msc_on_boot=1
|
||||||
|
micros2.menu.MSCOnBoot.default=Disabled
|
||||||
|
micros2.menu.MSCOnBoot.default.build.msc_on_boot=0
|
||||||
|
|
||||||
|
micros2.menu.DFUOnBoot.default=Disabled
|
||||||
|
micros2.menu.DFUOnBoot.default.build.dfu_on_boot=0
|
||||||
|
micros2.menu.DFUOnBoot.dfu=Enabled
|
||||||
|
micros2.menu.DFUOnBoot.dfu.build.dfu_on_boot=1
|
||||||
|
|
||||||
micros2.menu.PSRAM.enabled=Enabled
|
micros2.menu.PSRAM.enabled=Enabled
|
||||||
micros2.menu.PSRAM.enabled.build.defines=-DBOARD_HAS_PSRAM
|
micros2.menu.PSRAM.enabled.build.defines=-DBOARD_HAS_PSRAM
|
||||||
@ -2025,7 +2172,9 @@ sparkfun_esp32s2_thing_plus.build.core=esp32
|
|||||||
sparkfun_esp32s2_thing_plus.build.variant=esp32s2thing_plus
|
sparkfun_esp32s2_thing_plus.build.variant=esp32s2thing_plus
|
||||||
sparkfun_esp32s2_thing_plus.build.board=ESP32S2_THING_PLUS
|
sparkfun_esp32s2_thing_plus.build.board=ESP32S2_THING_PLUS
|
||||||
|
|
||||||
sparkfun_esp32s2_thing_plus.build.serial=0
|
sparkfun_esp32s2_thing_plus.build.cdc_on_boot=0
|
||||||
|
sparkfun_esp32s2_thing_plus.build.msc_on_boot=0
|
||||||
|
sparkfun_esp32s2_thing_plus.build.dfu_on_boot=0
|
||||||
sparkfun_esp32s2_thing_plus.build.f_cpu=240000000L
|
sparkfun_esp32s2_thing_plus.build.f_cpu=240000000L
|
||||||
sparkfun_esp32s2_thing_plus.build.flash_size=4MB
|
sparkfun_esp32s2_thing_plus.build.flash_size=4MB
|
||||||
sparkfun_esp32s2_thing_plus.build.flash_freq=80m
|
sparkfun_esp32s2_thing_plus.build.flash_freq=80m
|
||||||
@ -2034,10 +2183,20 @@ sparkfun_esp32s2_thing_plus.build.boot=qio
|
|||||||
sparkfun_esp32s2_thing_plus.build.partitions=default
|
sparkfun_esp32s2_thing_plus.build.partitions=default
|
||||||
sparkfun_esp32s2_thing_plus.build.defines=
|
sparkfun_esp32s2_thing_plus.build.defines=
|
||||||
|
|
||||||
sparkfun_esp32s2_thing_plus.menu.SerialMode.default=UART0
|
sparkfun_esp32s2_thing_plus.menu.CDCOnBoot.default=Disabled
|
||||||
sparkfun_esp32s2_thing_plus.menu.SerialMode.default.build.serial=0
|
sparkfun_esp32s2_thing_plus.menu.CDCOnBoot.default.build.cdc_on_boot=0
|
||||||
sparkfun_esp32s2_thing_plus.menu.SerialMode.cdc=USB CDC
|
sparkfun_esp32s2_thing_plus.menu.CDCOnBoot.cdc=Enabled
|
||||||
sparkfun_esp32s2_thing_plus.menu.SerialMode.cdc.build.serial=1
|
sparkfun_esp32s2_thing_plus.menu.CDCOnBoot.cdc.build.cdc_on_boot=1
|
||||||
|
|
||||||
|
sparkfun_esp32s2_thing_plus.menu.MSCOnBoot.default=Disabled
|
||||||
|
sparkfun_esp32s2_thing_plus.menu.MSCOnBoot.default.build.msc_on_boot=0
|
||||||
|
sparkfun_esp32s2_thing_plus.menu.MSCOnBoot.msc=Enabled
|
||||||
|
sparkfun_esp32s2_thing_plus.menu.MSCOnBoot.msc.build.msc_on_boot=1
|
||||||
|
|
||||||
|
sparkfun_esp32s2_thing_plus.menu.DFUOnBoot.default=Disabled
|
||||||
|
sparkfun_esp32s2_thing_plus.menu.DFUOnBoot.default.build.dfu_on_boot=0
|
||||||
|
sparkfun_esp32s2_thing_plus.menu.DFUOnBoot.dfu=Enabled
|
||||||
|
sparkfun_esp32s2_thing_plus.menu.DFUOnBoot.dfu.build.dfu_on_boot=1
|
||||||
|
|
||||||
sparkfun_esp32s2_thing_plus.menu.PSRAM.disabled=Disabled
|
sparkfun_esp32s2_thing_plus.menu.PSRAM.disabled=Disabled
|
||||||
sparkfun_esp32s2_thing_plus.menu.PSRAM.disabled.build.defines=
|
sparkfun_esp32s2_thing_plus.menu.PSRAM.disabled.build.defines=
|
||||||
@ -3334,7 +3493,9 @@ adafruit_metro_esp32s2.build.core=esp32
|
|||||||
adafruit_metro_esp32s2.build.variant=adafruit_metro_esp32s2
|
adafruit_metro_esp32s2.build.variant=adafruit_metro_esp32s2
|
||||||
adafruit_metro_esp32s2.build.board=METRO_ESP32S2
|
adafruit_metro_esp32s2.build.board=METRO_ESP32S2
|
||||||
|
|
||||||
adafruit_metro_esp32s2.build.serial=0
|
adafruit_metro_esp32s2.build.cdc_on_boot=1
|
||||||
|
adafruit_metro_esp32s2.build.msc_on_boot=0
|
||||||
|
adafruit_metro_esp32s2.build.dfu_on_boot=0
|
||||||
adafruit_metro_esp32s2.build.f_cpu=240000000L
|
adafruit_metro_esp32s2.build.f_cpu=240000000L
|
||||||
adafruit_metro_esp32s2.build.flash_size=4MB
|
adafruit_metro_esp32s2.build.flash_size=4MB
|
||||||
adafruit_metro_esp32s2.build.flash_freq=80m
|
adafruit_metro_esp32s2.build.flash_freq=80m
|
||||||
@ -3343,10 +3504,20 @@ adafruit_metro_esp32s2.build.boot=qio
|
|||||||
adafruit_metro_esp32s2.build.partitions=default
|
adafruit_metro_esp32s2.build.partitions=default
|
||||||
adafruit_metro_esp32s2.build.defines=
|
adafruit_metro_esp32s2.build.defines=
|
||||||
|
|
||||||
adafruit_metro_esp32s2.menu.SerialMode.cdc=USB CDC
|
adafruit_metro_esp32s2.menu.CDCOnBoot.cdc=Enabled
|
||||||
adafruit_metro_esp32s2.menu.SerialMode.cdc.build.serial=1
|
adafruit_metro_esp32s2.menu.CDCOnBoot.cdc.build.cdc_on_boot=1
|
||||||
adafruit_metro_esp32s2.menu.SerialMode.default=UART0
|
adafruit_metro_esp32s2.menu.CDCOnBoot.default=Disabled
|
||||||
adafruit_metro_esp32s2.menu.SerialMode.default.build.serial=0
|
adafruit_metro_esp32s2.menu.CDCOnBoot.default.build.cdc_on_boot=0
|
||||||
|
|
||||||
|
adafruit_metro_esp32s2.menu.MSCOnBoot.default=Disabled
|
||||||
|
adafruit_metro_esp32s2.menu.MSCOnBoot.default.build.msc_on_boot=0
|
||||||
|
adafruit_metro_esp32s2.menu.MSCOnBoot.msc=Enabled
|
||||||
|
adafruit_metro_esp32s2.menu.MSCOnBoot.msc.build.msc_on_boot=1
|
||||||
|
|
||||||
|
adafruit_metro_esp32s2.menu.DFUOnBoot.default=Disabled
|
||||||
|
adafruit_metro_esp32s2.menu.DFUOnBoot.default.build.dfu_on_boot=0
|
||||||
|
adafruit_metro_esp32s2.menu.DFUOnBoot.dfu=Enabled
|
||||||
|
adafruit_metro_esp32s2.menu.DFUOnBoot.dfu.build.dfu_on_boot=1
|
||||||
|
|
||||||
adafruit_metro_esp32s2.menu.PSRAM.enabled=Enabled
|
adafruit_metro_esp32s2.menu.PSRAM.enabled=Enabled
|
||||||
adafruit_metro_esp32s2.menu.PSRAM.enabled.build.defines=-DBOARD_HAS_PSRAM
|
adafruit_metro_esp32s2.menu.PSRAM.enabled.build.defines=-DBOARD_HAS_PSRAM
|
||||||
@ -3487,7 +3658,9 @@ adafruit_magtag29_esp32s2.build.core=esp32
|
|||||||
adafruit_magtag29_esp32s2.build.variant=adafruit_magtag29_esp32s2
|
adafruit_magtag29_esp32s2.build.variant=adafruit_magtag29_esp32s2
|
||||||
adafruit_magtag29_esp32s2.build.board=MAGTAG29_ESP32S2
|
adafruit_magtag29_esp32s2.build.board=MAGTAG29_ESP32S2
|
||||||
|
|
||||||
adafruit_magtag29_esp32s2.build.serial=0
|
adafruit_magtag29_esp32s2.build.cdc_on_boot=1
|
||||||
|
adafruit_magtag29_esp32s2.build.msc_on_boot=0
|
||||||
|
adafruit_magtag29_esp32s2.build.dfu_on_boot=0
|
||||||
adafruit_magtag29_esp32s2.build.f_cpu=240000000L
|
adafruit_magtag29_esp32s2.build.f_cpu=240000000L
|
||||||
adafruit_magtag29_esp32s2.build.flash_size=4MB
|
adafruit_magtag29_esp32s2.build.flash_size=4MB
|
||||||
adafruit_magtag29_esp32s2.build.flash_freq=80m
|
adafruit_magtag29_esp32s2.build.flash_freq=80m
|
||||||
@ -3496,10 +3669,20 @@ adafruit_magtag29_esp32s2.build.boot=qio
|
|||||||
adafruit_magtag29_esp32s2.build.partitions=default
|
adafruit_magtag29_esp32s2.build.partitions=default
|
||||||
adafruit_magtag29_esp32s2.build.defines=
|
adafruit_magtag29_esp32s2.build.defines=
|
||||||
|
|
||||||
adafruit_magtag29_esp32s2.menu.SerialMode.cdc=USB CDC
|
adafruit_magtag29_esp32s2.menu.CDCOnBoot.cdc=Enabled
|
||||||
adafruit_magtag29_esp32s2.menu.SerialMode.cdc.build.serial=1
|
adafruit_magtag29_esp32s2.menu.CDCOnBoot.cdc.build.cdc_on_boot=1
|
||||||
adafruit_magtag29_esp32s2.menu.SerialMode.default=UART0
|
adafruit_magtag29_esp32s2.menu.CDCOnBoot.default=Disabled
|
||||||
adafruit_magtag29_esp32s2.menu.SerialMode.default.build.serial=0
|
adafruit_magtag29_esp32s2.menu.CDCOnBoot.default.build.cdc_on_boot=0
|
||||||
|
|
||||||
|
adafruit_magtag29_esp32s2.menu.MSCOnBoot.default=Disabled
|
||||||
|
adafruit_magtag29_esp32s2.menu.MSCOnBoot.default.build.msc_on_boot=0
|
||||||
|
adafruit_magtag29_esp32s2.menu.MSCOnBoot.msc=Enabled
|
||||||
|
adafruit_magtag29_esp32s2.menu.MSCOnBoot.msc.build.msc_on_boot=1
|
||||||
|
|
||||||
|
adafruit_magtag29_esp32s2.menu.DFUOnBoot.default=Disabled
|
||||||
|
adafruit_magtag29_esp32s2.menu.DFUOnBoot.default.build.dfu_on_boot=0
|
||||||
|
adafruit_magtag29_esp32s2.menu.DFUOnBoot.dfu=Enabled
|
||||||
|
adafruit_magtag29_esp32s2.menu.DFUOnBoot.dfu.build.dfu_on_boot=1
|
||||||
|
|
||||||
adafruit_magtag29_esp32s2.menu.PSRAM.enabled=Enabled
|
adafruit_magtag29_esp32s2.menu.PSRAM.enabled=Enabled
|
||||||
adafruit_magtag29_esp32s2.menu.PSRAM.enabled.build.defines=-DBOARD_HAS_PSRAM
|
adafruit_magtag29_esp32s2.menu.PSRAM.enabled.build.defines=-DBOARD_HAS_PSRAM
|
||||||
@ -3640,7 +3823,9 @@ adafruit_funhouse_esp32s2.build.core=esp32
|
|||||||
adafruit_funhouse_esp32s2.build.variant=adafruit_funhouse_esp32s2
|
adafruit_funhouse_esp32s2.build.variant=adafruit_funhouse_esp32s2
|
||||||
adafruit_funhouse_esp32s2.build.board=FUNHOUSE_ESP32S2
|
adafruit_funhouse_esp32s2.build.board=FUNHOUSE_ESP32S2
|
||||||
|
|
||||||
adafruit_funhouse_esp32s2.build.serial=0
|
adafruit_funhouse_esp32s2.build.cdc_on_boot=1
|
||||||
|
adafruit_funhouse_esp32s2.build.msc_on_boot=0
|
||||||
|
adafruit_funhouse_esp32s2.build.dfu_on_boot=0
|
||||||
adafruit_funhouse_esp32s2.build.f_cpu=240000000L
|
adafruit_funhouse_esp32s2.build.f_cpu=240000000L
|
||||||
adafruit_funhouse_esp32s2.build.flash_size=4MB
|
adafruit_funhouse_esp32s2.build.flash_size=4MB
|
||||||
adafruit_funhouse_esp32s2.build.flash_freq=80m
|
adafruit_funhouse_esp32s2.build.flash_freq=80m
|
||||||
@ -3649,10 +3834,20 @@ adafruit_funhouse_esp32s2.build.boot=qio
|
|||||||
adafruit_funhouse_esp32s2.build.partitions=default
|
adafruit_funhouse_esp32s2.build.partitions=default
|
||||||
adafruit_funhouse_esp32s2.build.defines=
|
adafruit_funhouse_esp32s2.build.defines=
|
||||||
|
|
||||||
adafruit_funhouse_esp32s2.menu.SerialMode.cdc=USB CDC
|
adafruit_funhouse_esp32s2.menu.CDCOnBoot.cdc=Enabled
|
||||||
adafruit_funhouse_esp32s2.menu.SerialMode.cdc.build.serial=1
|
adafruit_funhouse_esp32s2.menu.CDCOnBoot.cdc.build.cdc_on_boot=1
|
||||||
adafruit_funhouse_esp32s2.menu.SerialMode.default=UART0
|
adafruit_funhouse_esp32s2.menu.CDCOnBoot.default=Disabled
|
||||||
adafruit_funhouse_esp32s2.menu.SerialMode.default.build.serial=0
|
adafruit_funhouse_esp32s2.menu.CDCOnBoot.default.build.cdc_on_boot=0
|
||||||
|
|
||||||
|
adafruit_funhouse_esp32s2.menu.MSCOnBoot.default=Disabled
|
||||||
|
adafruit_funhouse_esp32s2.menu.MSCOnBoot.default.build.msc_on_boot=0
|
||||||
|
adafruit_funhouse_esp32s2.menu.MSCOnBoot.msc=Enabled
|
||||||
|
adafruit_funhouse_esp32s2.menu.MSCOnBoot.msc.build.msc_on_boot=1
|
||||||
|
|
||||||
|
adafruit_funhouse_esp32s2.menu.DFUOnBoot.default=Disabled
|
||||||
|
adafruit_funhouse_esp32s2.menu.DFUOnBoot.default.build.dfu_on_boot=0
|
||||||
|
adafruit_funhouse_esp32s2.menu.DFUOnBoot.dfu=Enabled
|
||||||
|
adafruit_funhouse_esp32s2.menu.DFUOnBoot.dfu.build.dfu_on_boot=1
|
||||||
|
|
||||||
adafruit_funhouse_esp32s2.menu.PSRAM.enabled=Enabled
|
adafruit_funhouse_esp32s2.menu.PSRAM.enabled=Enabled
|
||||||
adafruit_funhouse_esp32s2.menu.PSRAM.enabled.build.defines=-DBOARD_HAS_PSRAM
|
adafruit_funhouse_esp32s2.menu.PSRAM.enabled.build.defines=-DBOARD_HAS_PSRAM
|
||||||
@ -3793,7 +3988,9 @@ adafruit_feather_esp32s2_nopsram.build.core=esp32
|
|||||||
adafruit_feather_esp32s2_nopsram.build.variant=adafruit_feather_esp32s2
|
adafruit_feather_esp32s2_nopsram.build.variant=adafruit_feather_esp32s2
|
||||||
adafruit_feather_esp32s2_nopsram.build.board=ADAFRUIT_FEATHER_ESP32S2_NOPSRAM
|
adafruit_feather_esp32s2_nopsram.build.board=ADAFRUIT_FEATHER_ESP32S2_NOPSRAM
|
||||||
|
|
||||||
adafruit_feather_esp32s2_nopsram.build.serial=0
|
adafruit_feather_esp32s2_nopsram.build.cdc_on_boot=0
|
||||||
|
adafruit_feather_esp32s2_nopsram.build.msc_on_boot=0
|
||||||
|
adafruit_feather_esp32s2_nopsram.build.dfu_on_boot=0
|
||||||
adafruit_feather_esp32s2_nopsram.build.f_cpu=240000000L
|
adafruit_feather_esp32s2_nopsram.build.f_cpu=240000000L
|
||||||
adafruit_feather_esp32s2_nopsram.build.flash_size=4MB
|
adafruit_feather_esp32s2_nopsram.build.flash_size=4MB
|
||||||
adafruit_feather_esp32s2_nopsram.build.flash_freq=80m
|
adafruit_feather_esp32s2_nopsram.build.flash_freq=80m
|
||||||
@ -3802,10 +3999,20 @@ adafruit_feather_esp32s2_nopsram.build.boot=qio
|
|||||||
adafruit_feather_esp32s2_nopsram.build.partitions=default
|
adafruit_feather_esp32s2_nopsram.build.partitions=default
|
||||||
adafruit_feather_esp32s2_nopsram.build.defines=
|
adafruit_feather_esp32s2_nopsram.build.defines=
|
||||||
|
|
||||||
adafruit_feather_esp32s2_nopsram.menu.SerialMode.cdc=USB CDC
|
adafruit_feather_esp32s2_nopsram.menu.CDCOnBoot.cdc=Enabled
|
||||||
adafruit_feather_esp32s2_nopsram.menu.SerialMode.cdc.build.serial=1
|
adafruit_feather_esp32s2_nopsram.menu.CDCOnBoot.cdc.build.cdc_on_boot=1
|
||||||
adafruit_feather_esp32s2_nopsram.menu.SerialMode.default=UART0
|
adafruit_feather_esp32s2_nopsram.menu.CDCOnBoot.default=Disabled
|
||||||
adafruit_feather_esp32s2_nopsram.menu.SerialMode.default.build.serial=0
|
adafruit_feather_esp32s2_nopsram.menu.CDCOnBoot.default.build.cdc_on_boot=0
|
||||||
|
|
||||||
|
adafruit_feather_esp32s2_nopsram.menu.MSCOnBoot.default=Disabled
|
||||||
|
adafruit_feather_esp32s2_nopsram.menu.MSCOnBoot.default.build.msc_on_boot=0
|
||||||
|
adafruit_feather_esp32s2_nopsram.menu.MSCOnBoot.msc=Enabled
|
||||||
|
adafruit_feather_esp32s2_nopsram.menu.MSCOnBoot.msc.build.msc_on_boot=1
|
||||||
|
|
||||||
|
adafruit_feather_esp32s2_nopsram.menu.DFUOnBoot.default=Disabled
|
||||||
|
adafruit_feather_esp32s2_nopsram.menu.DFUOnBoot.default.build.dfu_on_boot=0
|
||||||
|
adafruit_feather_esp32s2_nopsram.menu.DFUOnBoot.dfu=Enabled
|
||||||
|
adafruit_feather_esp32s2_nopsram.menu.DFUOnBoot.dfu.build.dfu_on_boot=1
|
||||||
|
|
||||||
adafruit_feather_esp32s2_nopsram.menu.PSRAM.disabled=Disabled
|
adafruit_feather_esp32s2_nopsram.menu.PSRAM.disabled=Disabled
|
||||||
adafruit_feather_esp32s2_nopsram.menu.PSRAM.disabled.build.defines=
|
adafruit_feather_esp32s2_nopsram.menu.PSRAM.disabled.build.defines=
|
||||||
|
423
cores/esp32/FirmwareMSC.cpp
Normal file
423
cores/esp32/FirmwareMSC.cpp
Normal file
@ -0,0 +1,423 @@
|
|||||||
|
// Copyright 2015-2021 Espressif Systems (Shanghai) PTE LTD
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
#include "FirmwareMSC.h"
|
||||||
|
#include "esp_partition.h"
|
||||||
|
#include "esp_ota_ops.h"
|
||||||
|
#include "esp32-hal.h"
|
||||||
|
#include "pins_arduino.h"
|
||||||
|
#include "firmware_msc_fat.h"
|
||||||
|
|
||||||
|
#if CONFIG_TINYUSB_MSC_ENABLED
|
||||||
|
|
||||||
|
#ifndef USB_FW_MSC_VENDOR_ID
|
||||||
|
#define USB_FW_MSC_VENDOR_ID "ESP32" //max 8 chars
|
||||||
|
#endif
|
||||||
|
#ifndef USB_FW_MSC_PRODUCT_ID
|
||||||
|
#define USB_FW_MSC_PRODUCT_ID "Firmware MSC"//max 16 chars
|
||||||
|
#endif
|
||||||
|
#ifndef USB_FW_MSC_PRODUCT_REVISION
|
||||||
|
#define USB_FW_MSC_PRODUCT_REVISION "1.0" //max 4 chars
|
||||||
|
#endif
|
||||||
|
#ifndef USB_FW_MSC_VOLUME_NAME
|
||||||
|
#define USB_FW_MSC_VOLUME_NAME "ESP32-FWMSC" //max 11 chars
|
||||||
|
#endif
|
||||||
|
#ifndef USB_FW_MSC_SERIAL_NUMBER
|
||||||
|
#define USB_FW_MSC_SERIAL_NUMBER 0x00000000
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ESP_EVENT_DEFINE_BASE(ARDUINO_FIRMWARE_MSC_EVENTS);
|
||||||
|
esp_err_t arduino_usb_event_post(esp_event_base_t event_base, int32_t event_id, void *event_data, size_t event_data_size, TickType_t ticks_to_wait);
|
||||||
|
esp_err_t arduino_usb_event_handler_register_with(esp_event_base_t event_base, int32_t event_id, esp_event_handler_t event_handler, void *event_handler_arg);
|
||||||
|
|
||||||
|
//General Variables
|
||||||
|
static uint8_t * msc_ram_disk = NULL;
|
||||||
|
static fat_boot_sector_t * msc_boot = NULL;
|
||||||
|
static uint8_t * msc_table = NULL;
|
||||||
|
static uint16_t msc_table_sectors = 0;
|
||||||
|
static uint16_t msc_total_sectors = 0;
|
||||||
|
static bool mcs_is_fat16 = false;
|
||||||
|
|
||||||
|
//Firmware Read
|
||||||
|
static const esp_partition_t* msc_run_partition = NULL;
|
||||||
|
static uint16_t fw_start_sector = 0;
|
||||||
|
static uint16_t fw_end_sector = 0;
|
||||||
|
static size_t fw_size = 0;
|
||||||
|
static fat_dir_entry_t * fw_entry = NULL;
|
||||||
|
|
||||||
|
//Firmware Write
|
||||||
|
typedef enum {
|
||||||
|
MSC_UPDATE_IDLE,
|
||||||
|
MSC_UPDATE_STARTING,
|
||||||
|
MSC_UPDATE_RUNNING,
|
||||||
|
MSC_UPDATE_END
|
||||||
|
} msc_update_state_t;
|
||||||
|
|
||||||
|
static const esp_partition_t* msc_ota_partition = NULL;
|
||||||
|
static msc_update_state_t msc_update_state = MSC_UPDATE_IDLE;
|
||||||
|
static uint16_t msc_update_start_sector = 0;
|
||||||
|
static uint32_t msc_update_bytes_written = 0;
|
||||||
|
static fat_dir_entry_t * msc_update_entry = NULL;
|
||||||
|
|
||||||
|
static uint32_t get_firmware_size(const esp_partition_t* partition){
|
||||||
|
esp_image_metadata_t data;
|
||||||
|
const esp_partition_pos_t running_pos = {
|
||||||
|
.offset = partition->address,
|
||||||
|
.size = partition->size,
|
||||||
|
};
|
||||||
|
data.start_addr = running_pos.offset;
|
||||||
|
esp_image_verify(ESP_IMAGE_VERIFY, &running_pos, &data);
|
||||||
|
return data.image_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Get number of sectors required based on the size of the firmware and OTA partition
|
||||||
|
static size_t msc_update_get_required_disk_sectors(){
|
||||||
|
size_t data_sectors = 16;
|
||||||
|
size_t total_sectors = 0;
|
||||||
|
msc_run_partition = esp_ota_get_running_partition();
|
||||||
|
msc_ota_partition = esp_ota_get_next_update_partition(NULL);
|
||||||
|
if(msc_run_partition){
|
||||||
|
fw_size = get_firmware_size(msc_run_partition);
|
||||||
|
data_sectors += FAT_SIZE_TO_SECTORS(fw_size);
|
||||||
|
log_d("APP size: %u (%u sectors)", fw_size, FAT_SIZE_TO_SECTORS(fw_size));
|
||||||
|
} else {
|
||||||
|
log_w("APP partition not found. Reading disabled");
|
||||||
|
}
|
||||||
|
if(msc_ota_partition){
|
||||||
|
data_sectors += FAT_SIZE_TO_SECTORS(msc_ota_partition->size);
|
||||||
|
log_d("OTA size: %u (%u sectors)", msc_ota_partition->size, FAT_SIZE_TO_SECTORS(msc_ota_partition->size));
|
||||||
|
} else {
|
||||||
|
log_w("OTA partition not found. Writing disabled");
|
||||||
|
}
|
||||||
|
msc_table_sectors = fat_sectors_per_alloc_table(data_sectors, false);
|
||||||
|
total_sectors = data_sectors + msc_table_sectors + 2;
|
||||||
|
if(total_sectors > 0xFF4){
|
||||||
|
log_d("USING FAT16");
|
||||||
|
mcs_is_fat16 = true;
|
||||||
|
total_sectors -= msc_table_sectors;
|
||||||
|
msc_table_sectors = fat_sectors_per_alloc_table(data_sectors, true);
|
||||||
|
total_sectors += msc_table_sectors;
|
||||||
|
} else {
|
||||||
|
log_d("USING FAT12");
|
||||||
|
mcs_is_fat16 = false;
|
||||||
|
}
|
||||||
|
log_d("FAT data sectors: %u", data_sectors);
|
||||||
|
log_d("FAT table sectors: %u", msc_table_sectors);
|
||||||
|
log_d("FAT total sectors: %u (%uKB)", total_sectors, (total_sectors * DISK_SECTOR_SIZE) / 1024);
|
||||||
|
return total_sectors;
|
||||||
|
}
|
||||||
|
|
||||||
|
//setup the ramdisk and add the firmware download file
|
||||||
|
static bool msc_update_setup_disk(const char * volume_label, uint32_t serial_number){
|
||||||
|
msc_total_sectors = msc_update_get_required_disk_sectors();
|
||||||
|
uint8_t ram_sectors = msc_table_sectors + 2;
|
||||||
|
msc_ram_disk = (uint8_t*)calloc(ram_sectors, DISK_SECTOR_SIZE);
|
||||||
|
if(!msc_ram_disk){
|
||||||
|
log_e("Failed to allocate RAM Disk: %u bytes", ram_sectors * DISK_SECTOR_SIZE);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
fw_start_sector = ram_sectors;
|
||||||
|
fw_end_sector = fw_start_sector;
|
||||||
|
msc_boot = fat_add_boot_sector(msc_ram_disk, msc_total_sectors, msc_table_sectors, fat_file_system_type(mcs_is_fat16), volume_label, serial_number);
|
||||||
|
msc_table = fat_add_table(msc_ram_disk, msc_boot, mcs_is_fat16);
|
||||||
|
//fat_dir_entry_t * label = fat_add_label(msc_ram_disk, volume_label);
|
||||||
|
if(msc_run_partition){
|
||||||
|
fw_entry = fat_add_root_file(msc_ram_disk, 0, "FIRMWARE", "BIN", fw_size, 2, mcs_is_fat16);
|
||||||
|
fw_end_sector = FAT_SIZE_TO_SECTORS(fw_size) + fw_start_sector;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void msc_update_delete_disk(){
|
||||||
|
fw_entry = NULL;
|
||||||
|
fw_size = 0;
|
||||||
|
fw_end_sector = 0;
|
||||||
|
fw_start_sector = 0;
|
||||||
|
msc_table = NULL;
|
||||||
|
msc_boot = NULL;
|
||||||
|
msc_table_sectors = 0;
|
||||||
|
msc_total_sectors = 0;
|
||||||
|
msc_run_partition = NULL;
|
||||||
|
msc_ota_partition = NULL;
|
||||||
|
msc_update_state = MSC_UPDATE_IDLE;
|
||||||
|
msc_update_start_sector = 0;
|
||||||
|
msc_update_bytes_written = 0;
|
||||||
|
msc_update_entry = NULL;
|
||||||
|
free(msc_ram_disk);
|
||||||
|
msc_ram_disk = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
//filter out entries to only include BINs in the root folder
|
||||||
|
static fat_dir_entry_t * msc_update_get_root_bin_entry(uint8_t index){
|
||||||
|
fat_dir_entry_t * entry = (fat_dir_entry_t *)(msc_ram_disk + ((msc_boot->sectors_per_alloc_table+1) * DISK_SECTOR_SIZE) + (index * sizeof(fat_dir_entry_t)));
|
||||||
|
fat_lfn_entry_t * lfn = (fat_lfn_entry_t*)entry;
|
||||||
|
|
||||||
|
//empty entry
|
||||||
|
if(entry->file_magic == 0){
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
//long file name
|
||||||
|
if(lfn->attr == 0x0F && lfn->type == 0x00 && lfn->first_cluster == 0x0000){
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
//only files marked as archives
|
||||||
|
if(entry->file_attr != FAT_FILE_ATTR_ARCHIVE){
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
//deleted
|
||||||
|
if(entry->file_magic == 0xE5 || entry->file_magic == 0x05){
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
//not bins
|
||||||
|
if(memcmp("BIN", entry->file_extension, 3)){
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
//get an empty bin (the host will add an entry for file about to be written with size of zero)
|
||||||
|
static fat_dir_entry_t * msc_update_find_new_bin(){
|
||||||
|
for(uint8_t i=16; i;){
|
||||||
|
i--;
|
||||||
|
fat_dir_entry_t * entry = msc_update_get_root_bin_entry(i);
|
||||||
|
if(entry && entry->file_size == 0){
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
//get a bin starting from particular sector
|
||||||
|
static fat_dir_entry_t * msc_update_find_bin(uint16_t sector){
|
||||||
|
for(uint8_t i=16; i; ){
|
||||||
|
i--;
|
||||||
|
fat_dir_entry_t * entry = msc_update_get_root_bin_entry(i);
|
||||||
|
if(entry && entry->data_start_sector == (sector - msc_boot->sectors_per_alloc_table)){
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
//write the new data and erase the flash blocks when necessary
|
||||||
|
static esp_err_t msc_update_write(const esp_partition_t *partition, uint32_t offset, void *data, size_t size){
|
||||||
|
esp_err_t err = ESP_OK;
|
||||||
|
if((offset & (SPI_FLASH_SEC_SIZE-1)) == 0){
|
||||||
|
err = esp_partition_erase_range(partition, offset, SPI_FLASH_SEC_SIZE);
|
||||||
|
log_v("ERASE[0x%08X]: %s", offset, (err != ESP_OK)?"FAIL":"OK");
|
||||||
|
if(err != ESP_OK){
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return esp_partition_write(partition, offset, data, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
//called when error was encountered while updating
|
||||||
|
static void msc_update_error(){
|
||||||
|
log_e("UPDATE_ERROR: %u", msc_update_bytes_written);
|
||||||
|
arduino_firmware_msc_event_data_t p = {0};
|
||||||
|
p.error.size = msc_update_bytes_written;
|
||||||
|
arduino_usb_event_post(ARDUINO_FIRMWARE_MSC_EVENTS, ARDUINO_FIRMWARE_MSC_ERROR_EVENT, &p, sizeof(arduino_firmware_msc_event_data_t), portMAX_DELAY);
|
||||||
|
msc_update_state = MSC_UPDATE_IDLE;
|
||||||
|
msc_update_entry = NULL;
|
||||||
|
msc_update_bytes_written = 0;
|
||||||
|
msc_update_start_sector = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//called when all firmware bytes have been received
|
||||||
|
static void msc_update_end(){
|
||||||
|
log_d("UPDATE_END: %u", msc_update_entry->file_size);
|
||||||
|
msc_update_state = MSC_UPDATE_END;
|
||||||
|
size_t ota_size = get_firmware_size(msc_ota_partition);
|
||||||
|
if(ota_size != msc_update_entry->file_size){
|
||||||
|
log_e("OTA SIZE MISMATCH %u != %u", ota_size, msc_update_entry->file_size);
|
||||||
|
msc_update_error();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(!ota_size || esp_ota_set_boot_partition(msc_ota_partition) != ESP_OK){
|
||||||
|
log_e("ENABLING OTA PARTITION FAILED");
|
||||||
|
msc_update_error();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
arduino_firmware_msc_event_data_t p = {0};
|
||||||
|
p.end.size = msc_update_entry->file_size;
|
||||||
|
arduino_usb_event_post(ARDUINO_FIRMWARE_MSC_EVENTS, ARDUINO_FIRMWARE_MSC_END_EVENT, &p, sizeof(arduino_firmware_msc_event_data_t), portMAX_DELAY);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int32_t msc_write(uint32_t lba, uint32_t offset, uint8_t* buffer, uint32_t bufsize){
|
||||||
|
//log_d("lba: %u, offset: %u, bufsize: %u", lba, offset, bufsize);
|
||||||
|
if(lba < fw_start_sector){
|
||||||
|
//write to sectors that are in RAM
|
||||||
|
memcpy(msc_ram_disk + (lba * DISK_SECTOR_SIZE) + offset, buffer, bufsize);
|
||||||
|
if(msc_ota_partition && lba == (fw_start_sector - 1)){
|
||||||
|
//monitor the root folder table
|
||||||
|
if(msc_update_state <= MSC_UPDATE_RUNNING){
|
||||||
|
fat_dir_entry_t * update_entry = msc_update_find_new_bin();
|
||||||
|
if(update_entry) {
|
||||||
|
if(msc_update_entry) {
|
||||||
|
log_v("REPLACING ENTRY");
|
||||||
|
} else {
|
||||||
|
log_v("ASSIGNING ENTRY");
|
||||||
|
}
|
||||||
|
if(msc_update_state <= MSC_UPDATE_STARTING){
|
||||||
|
msc_update_state = MSC_UPDATE_STARTING;
|
||||||
|
msc_update_bytes_written = 0;
|
||||||
|
msc_update_start_sector = 0;
|
||||||
|
}
|
||||||
|
msc_update_entry = update_entry;
|
||||||
|
} else if(msc_update_state == MSC_UPDATE_RUNNING){
|
||||||
|
if(!msc_update_entry && msc_update_start_sector){
|
||||||
|
msc_update_entry = msc_update_find_bin(msc_update_start_sector);
|
||||||
|
}
|
||||||
|
if(msc_update_entry && msc_update_bytes_written >= msc_update_entry->file_size){
|
||||||
|
msc_update_end();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if(msc_ota_partition && lba >= msc_update_start_sector){
|
||||||
|
//handle writes to the region where the new firmware will be uploaded
|
||||||
|
arduino_firmware_msc_event_data_t p = {0};
|
||||||
|
if(msc_update_state <= MSC_UPDATE_STARTING && buffer[0] == 0xE9){
|
||||||
|
msc_update_state = MSC_UPDATE_RUNNING;
|
||||||
|
msc_update_start_sector = lba;
|
||||||
|
msc_update_bytes_written = 0;
|
||||||
|
log_d("UPDATE_START: %u (0x%02X)", lba, lba - msc_boot->sectors_per_alloc_table);
|
||||||
|
arduino_usb_event_post(ARDUINO_FIRMWARE_MSC_EVENTS, ARDUINO_FIRMWARE_MSC_START_EVENT, &p, sizeof(arduino_firmware_msc_event_data_t), portMAX_DELAY);
|
||||||
|
if(msc_update_write(msc_ota_partition, ((lba - msc_update_start_sector) * DISK_SECTOR_SIZE) + offset, buffer, bufsize) == ESP_OK){
|
||||||
|
log_v("UPDATE_WRITE: %u %u", ((lba - msc_update_start_sector) * DISK_SECTOR_SIZE) + offset, bufsize);
|
||||||
|
msc_update_bytes_written = ((lba - msc_update_start_sector) * DISK_SECTOR_SIZE) + offset + bufsize;
|
||||||
|
p.write.offset = ((lba - msc_update_start_sector) * DISK_SECTOR_SIZE) + offset;
|
||||||
|
p.write.size = bufsize;
|
||||||
|
arduino_usb_event_post(ARDUINO_FIRMWARE_MSC_EVENTS, ARDUINO_FIRMWARE_MSC_WRITE_EVENT, &p, sizeof(arduino_firmware_msc_event_data_t), portMAX_DELAY);
|
||||||
|
} else {
|
||||||
|
msc_update_error();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
} else if(msc_update_state == MSC_UPDATE_RUNNING){
|
||||||
|
if(msc_update_entry && msc_update_entry->file_size && msc_update_bytes_written < msc_update_entry->file_size && (msc_update_bytes_written + bufsize) >= msc_update_entry->file_size){
|
||||||
|
bufsize = msc_update_entry->file_size - msc_update_bytes_written;
|
||||||
|
}
|
||||||
|
if(msc_update_write(msc_ota_partition, ((lba - msc_update_start_sector) * DISK_SECTOR_SIZE) + offset, buffer, bufsize) == ESP_OK){
|
||||||
|
log_v("UPDATE_WRITE: %u %u", ((lba - msc_update_start_sector) * DISK_SECTOR_SIZE) + offset, bufsize);
|
||||||
|
msc_update_bytes_written = ((lba - msc_update_start_sector) * DISK_SECTOR_SIZE) + offset + bufsize;
|
||||||
|
p.write.offset = ((lba - msc_update_start_sector) * DISK_SECTOR_SIZE) + offset;
|
||||||
|
p.write.size = bufsize;
|
||||||
|
arduino_usb_event_post(ARDUINO_FIRMWARE_MSC_EVENTS, ARDUINO_FIRMWARE_MSC_WRITE_EVENT, &p, sizeof(arduino_firmware_msc_event_data_t), portMAX_DELAY);
|
||||||
|
if(msc_update_entry && msc_update_entry->file_size && msc_update_bytes_written >= msc_update_entry->file_size){
|
||||||
|
msc_update_end();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
msc_update_error();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return bufsize;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int32_t msc_read(uint32_t lba, uint32_t offset, void* buffer, uint32_t bufsize){
|
||||||
|
//log_d("lba: %u, offset: %u, bufsize: %u", lba, offset, bufsize);
|
||||||
|
if(lba < fw_start_sector){
|
||||||
|
memcpy(buffer, msc_ram_disk + (lba * DISK_SECTOR_SIZE) + offset, bufsize);
|
||||||
|
} else if(msc_run_partition && lba < fw_end_sector){
|
||||||
|
//read the currently running firmware
|
||||||
|
if(esp_partition_read(msc_run_partition, ((lba - fw_start_sector) * DISK_SECTOR_SIZE) + offset, buffer, bufsize) != ESP_OK){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
memset(buffer, 0, bufsize);
|
||||||
|
}
|
||||||
|
return bufsize;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool msc_start_stop(uint8_t power_condition, bool start, bool load_eject){
|
||||||
|
//log_d("power: %u, start: %u, eject: %u", power_condition, start, load_eject);
|
||||||
|
arduino_firmware_msc_event_data_t p = {0};
|
||||||
|
p.power.power_condition = power_condition;
|
||||||
|
p.power.start = start;
|
||||||
|
p.power.load_eject = load_eject;
|
||||||
|
arduino_usb_event_post(ARDUINO_FIRMWARE_MSC_EVENTS, ARDUINO_FIRMWARE_MSC_POWER_EVENT, &p, sizeof(arduino_firmware_msc_event_data_t), portMAX_DELAY);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static volatile TaskHandle_t msc_task_handle = NULL;
|
||||||
|
static void msc_task(void *pvParameters){
|
||||||
|
for (;;) {
|
||||||
|
if(msc_update_state == MSC_UPDATE_END){
|
||||||
|
delay(100);
|
||||||
|
esp_restart();
|
||||||
|
}
|
||||||
|
delay(100);
|
||||||
|
}
|
||||||
|
msc_task_handle = NULL;
|
||||||
|
vTaskDelete(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
FirmwareMSC::FirmwareMSC():msc(){}
|
||||||
|
|
||||||
|
FirmwareMSC::~FirmwareMSC(){
|
||||||
|
end();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FirmwareMSC::begin(){
|
||||||
|
if(msc_ram_disk){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!msc_update_setup_disk(USB_FW_MSC_VOLUME_NAME, USB_FW_MSC_SERIAL_NUMBER)){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!msc_task_handle){
|
||||||
|
xTaskCreateUniversal(msc_task, "msc_disk", 1024, NULL, 2, (TaskHandle_t*)&msc_task_handle, 0);
|
||||||
|
if(!msc_task_handle){
|
||||||
|
msc_update_delete_disk();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
msc.vendorID(USB_FW_MSC_VENDOR_ID);
|
||||||
|
msc.productID(USB_FW_MSC_PRODUCT_ID);
|
||||||
|
msc.productRevision(USB_FW_MSC_PRODUCT_REVISION);
|
||||||
|
msc.onStartStop(msc_start_stop);
|
||||||
|
msc.onRead(msc_read);
|
||||||
|
msc.onWrite(msc_write);
|
||||||
|
msc.mediaPresent(true);
|
||||||
|
msc.begin(msc_boot->fat12_sector_num, DISK_SECTOR_SIZE);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FirmwareMSC::end(){
|
||||||
|
msc.end();
|
||||||
|
if(msc_task_handle){
|
||||||
|
vTaskDelete(msc_task_handle);
|
||||||
|
msc_task_handle = NULL;
|
||||||
|
}
|
||||||
|
msc_update_delete_disk();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FirmwareMSC::onEvent(esp_event_handler_t callback){
|
||||||
|
onEvent(ARDUINO_FIRMWARE_MSC_ANY_EVENT, callback);
|
||||||
|
}
|
||||||
|
void FirmwareMSC::onEvent(arduino_firmware_msc_event_t event, esp_event_handler_t callback){
|
||||||
|
arduino_usb_event_handler_register_with(ARDUINO_FIRMWARE_MSC_EVENTS, event, callback, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if ARDUINO_USB_MSC_ON_BOOT
|
||||||
|
FirmwareMSC MSC_Update;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* CONFIG_USB_MSC_ENABLED */
|
69
cores/esp32/FirmwareMSC.h
Normal file
69
cores/esp32/FirmwareMSC.h
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
// Copyright 2015-2021 Espressif Systems (Shanghai) PTE LTD
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include "USBMSC.h"
|
||||||
|
#if CONFIG_TINYUSB_MSC_ENABLED
|
||||||
|
|
||||||
|
#include "esp_event.h"
|
||||||
|
|
||||||
|
ESP_EVENT_DECLARE_BASE(ARDUINO_FIRMWARE_MSC_EVENTS);
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
ARDUINO_FIRMWARE_MSC_ANY_EVENT = ESP_EVENT_ANY_ID,
|
||||||
|
ARDUINO_FIRMWARE_MSC_START_EVENT = 0,
|
||||||
|
ARDUINO_FIRMWARE_MSC_WRITE_EVENT,
|
||||||
|
ARDUINO_FIRMWARE_MSC_END_EVENT,
|
||||||
|
ARDUINO_FIRMWARE_MSC_ERROR_EVENT,
|
||||||
|
ARDUINO_FIRMWARE_MSC_POWER_EVENT,
|
||||||
|
ARDUINO_FIRMWARE_MSC_MAX_EVENT,
|
||||||
|
} arduino_firmware_msc_event_t;
|
||||||
|
|
||||||
|
typedef union {
|
||||||
|
struct {
|
||||||
|
size_t offset;
|
||||||
|
size_t size;
|
||||||
|
} write;
|
||||||
|
struct {
|
||||||
|
uint8_t power_condition;
|
||||||
|
bool start;
|
||||||
|
bool load_eject;
|
||||||
|
} power;
|
||||||
|
struct {
|
||||||
|
size_t size;
|
||||||
|
} end;
|
||||||
|
struct {
|
||||||
|
size_t size;
|
||||||
|
} error;
|
||||||
|
} arduino_firmware_msc_event_data_t;
|
||||||
|
|
||||||
|
class FirmwareMSC {
|
||||||
|
private:
|
||||||
|
USBMSC msc;
|
||||||
|
|
||||||
|
public:
|
||||||
|
FirmwareMSC();
|
||||||
|
~FirmwareMSC();
|
||||||
|
bool begin();
|
||||||
|
void end();
|
||||||
|
void onEvent(esp_event_handler_t callback);
|
||||||
|
void onEvent(arduino_firmware_msc_event_t event, esp_event_handler_t callback);
|
||||||
|
};
|
||||||
|
|
||||||
|
#if ARDUINO_USB_MSC_ON_BOOT
|
||||||
|
extern FirmwareMSC MSC_Update;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* CONFIG_TINYUSB_MSC_ENABLED */
|
@ -37,7 +37,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_SERIAL)
|
#if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_SERIAL)
|
||||||
#if ARDUINO_SERIAL_PORT //Serial used for USB CDC
|
#if ARDUINO_USB_CDC_ON_BOOT //Serial used for USB CDC
|
||||||
HardwareSerial Serial0(0);
|
HardwareSerial Serial0(0);
|
||||||
#else
|
#else
|
||||||
HardwareSerial Serial(0);
|
HardwareSerial Serial(0);
|
||||||
|
@ -113,10 +113,10 @@ protected:
|
|||||||
extern void serialEventRun(void) __attribute__((weak));
|
extern void serialEventRun(void) __attribute__((weak));
|
||||||
|
|
||||||
#if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_SERIAL)
|
#if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_SERIAL)
|
||||||
#ifndef ARDUINO_SERIAL_PORT
|
#ifndef ARDUINO_USB_CDC_ON_BOOT
|
||||||
#define ARDUINO_SERIAL_PORT 0
|
#define ARDUINO_USB_CDC_ON_BOOT 0
|
||||||
#endif
|
#endif
|
||||||
#if ARDUINO_SERIAL_PORT //Serial used for USB CDC
|
#if ARDUINO_USB_CDC_ON_BOOT //Serial used for USB CDC
|
||||||
#include "USB.h"
|
#include "USB.h"
|
||||||
#include "USBCDC.h"
|
#include "USBCDC.h"
|
||||||
extern HardwareSerial Serial0;
|
extern HardwareSerial Serial0;
|
||||||
|
@ -31,14 +31,16 @@
|
|||||||
#ifndef USB_SERIAL
|
#ifndef USB_SERIAL
|
||||||
#define USB_SERIAL "0"
|
#define USB_SERIAL "0"
|
||||||
#endif
|
#endif
|
||||||
|
#ifndef USB_WEBUSB_ENABLED
|
||||||
|
#define USB_WEBUSB_ENABLED false
|
||||||
|
#endif
|
||||||
|
#ifndef USB_WEBUSB_URL
|
||||||
|
#define USB_WEBUSB_URL "https://espressif.github.io/arduino-esp32/webusb.html"
|
||||||
|
#endif
|
||||||
|
|
||||||
#if CFG_TUD_DFU_RUNTIME
|
#if CFG_TUD_DFU_RUNTIME
|
||||||
static uint16_t load_dfu_descriptor(uint8_t * dst, uint8_t * itf)
|
static uint16_t load_dfu_descriptor(uint8_t * dst, uint8_t * itf)
|
||||||
{
|
{
|
||||||
#define DFU_ATTR_CAN_DOWNLOAD 1
|
|
||||||
#define DFU_ATTR_CAN_UPLOAD 2
|
|
||||||
#define DFU_ATTR_MANIFESTATION_TOLERANT 4
|
|
||||||
#define DFU_ATTR_WILL_DETACH 8
|
|
||||||
#define DFU_ATTRS (DFU_ATTR_CAN_DOWNLOAD | DFU_ATTR_CAN_UPLOAD | DFU_ATTR_MANIFESTATION_TOLERANT)
|
#define DFU_ATTRS (DFU_ATTR_CAN_DOWNLOAD | DFU_ATTR_CAN_UPLOAD | DFU_ATTR_MANIFESTATION_TOLERANT)
|
||||||
|
|
||||||
uint8_t str_index = tinyusb_add_string_descriptor("TinyUSB DFU_RT");
|
uint8_t str_index = tinyusb_add_string_descriptor("TinyUSB DFU_RT");
|
||||||
@ -120,8 +122,8 @@ ESPUSB::ESPUSB(size_t task_stack_size, uint8_t event_task_priority)
|
|||||||
,usb_protocol(MISC_PROTOCOL_IAD)
|
,usb_protocol(MISC_PROTOCOL_IAD)
|
||||||
,usb_attributes(TUSB_DESC_CONFIG_ATT_SELF_POWERED)
|
,usb_attributes(TUSB_DESC_CONFIG_ATT_SELF_POWERED)
|
||||||
,usb_power_ma(500)
|
,usb_power_ma(500)
|
||||||
,webusb_enabled(false)
|
,webusb_enabled(USB_WEBUSB_ENABLED)
|
||||||
,webusb_url("https://espressif.github.io/arduino-esp32/webusb.html")
|
,webusb_url(USB_WEBUSB_URL)
|
||||||
,_started(false)
|
,_started(false)
|
||||||
,_task_stack_size(task_stack_size)
|
,_task_stack_size(task_stack_size)
|
||||||
,_event_task_priority(event_task_priority)
|
,_event_task_priority(event_task_priority)
|
||||||
|
@ -18,9 +18,11 @@
|
|||||||
|
|
||||||
#include "Arduino.h"
|
#include "Arduino.h"
|
||||||
#include "USBCDC.h"
|
#include "USBCDC.h"
|
||||||
|
#include "common/tusb_common.h"
|
||||||
#include "esp_event.h"
|
#include "esp_event.h"
|
||||||
|
|
||||||
|
#define ARDUINO_USB_ON_BOOT (ARDUINO_USB_CDC_ON_BOOT|ARDUINO_USB_MSC_ON_BOOT|ARDUINO_USB_DFU_ON_BOOT)
|
||||||
|
|
||||||
ESP_EVENT_DECLARE_BASE(ARDUINO_USB_EVENTS);
|
ESP_EVENT_DECLARE_BASE(ARDUINO_USB_EVENTS);
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
@ -28,7 +28,6 @@ USBCDC * devices[MAX_USB_CDC_DEVICES] = {NULL, NULL};
|
|||||||
static uint16_t load_cdc_descriptor(uint8_t * dst, uint8_t * itf)
|
static uint16_t load_cdc_descriptor(uint8_t * dst, uint8_t * itf)
|
||||||
{
|
{
|
||||||
uint8_t str_index = tinyusb_add_string_descriptor("TinyUSB CDC");
|
uint8_t str_index = tinyusb_add_string_descriptor("TinyUSB CDC");
|
||||||
// Interface number, string index, attributes, detach timeout, transfer size */
|
|
||||||
uint8_t descriptor[TUD_CDC_DESC_LEN] = {
|
uint8_t descriptor[TUD_CDC_DESC_LEN] = {
|
||||||
// Interface number, string index, EP notification address and size, EP data address (out, in) and size.
|
// Interface number, string index, EP notification address and size, EP data address (out, in) and size.
|
||||||
TUD_CDC_DESCRIPTOR(*itf, str_index, 0x85, 64, 0x03, 0x84, 64)
|
TUD_CDC_DESCRIPTOR(*itf, str_index, 0x85, 64, 0x03, 0x84, 64)
|
||||||
@ -41,7 +40,6 @@ static uint16_t load_cdc_descriptor(uint8_t * dst, uint8_t * itf)
|
|||||||
// Invoked when line state DTR & RTS are changed via SET_CONTROL_LINE_STATE
|
// Invoked when line state DTR & RTS are changed via SET_CONTROL_LINE_STATE
|
||||||
void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts)
|
void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts)
|
||||||
{
|
{
|
||||||
//isr_log_v("itf: %u, dtr: %u, rts: %u", itf, dtr, rts);
|
|
||||||
if(itf < MAX_USB_CDC_DEVICES && devices[itf] != NULL){
|
if(itf < MAX_USB_CDC_DEVICES && devices[itf] != NULL){
|
||||||
devices[itf]->_onLineState(dtr, rts);
|
devices[itf]->_onLineState(dtr, rts);
|
||||||
}
|
}
|
||||||
@ -50,7 +48,6 @@ void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts)
|
|||||||
// Invoked when line coding is change via SET_LINE_CODING
|
// Invoked when line coding is change via SET_LINE_CODING
|
||||||
void tud_cdc_line_coding_cb(uint8_t itf, cdc_line_coding_t const* p_line_coding)
|
void tud_cdc_line_coding_cb(uint8_t itf, cdc_line_coding_t const* p_line_coding)
|
||||||
{
|
{
|
||||||
//isr_log_v("itf: %u, bit_rate: %u, data_bits: %u, stop_bits: %u, parity: %u", itf, p_line_coding->bit_rate, p_line_coding->data_bits, p_line_coding->stop_bits, p_line_coding->parity);
|
|
||||||
if(itf < MAX_USB_CDC_DEVICES && devices[itf] != NULL){
|
if(itf < MAX_USB_CDC_DEVICES && devices[itf] != NULL){
|
||||||
devices[itf]->_onLineCoding(p_line_coding->bit_rate, p_line_coding->stop_bits, p_line_coding->parity, p_line_coding->data_bits);
|
devices[itf]->_onLineCoding(p_line_coding->bit_rate, p_line_coding->stop_bits, p_line_coding->parity, p_line_coding->data_bits);
|
||||||
}
|
}
|
||||||
@ -59,7 +56,6 @@ void tud_cdc_line_coding_cb(uint8_t itf, cdc_line_coding_t const* p_line_coding)
|
|||||||
// Invoked when received new data
|
// Invoked when received new data
|
||||||
void tud_cdc_rx_cb(uint8_t itf)
|
void tud_cdc_rx_cb(uint8_t itf)
|
||||||
{
|
{
|
||||||
//isr_log_v("itf: %u", itf);
|
|
||||||
if(itf < MAX_USB_CDC_DEVICES && devices[itf] != NULL){
|
if(itf < MAX_USB_CDC_DEVICES && devices[itf] != NULL){
|
||||||
devices[itf]->_onRX();
|
devices[itf]->_onRX();
|
||||||
}
|
}
|
||||||
@ -72,15 +68,14 @@ void tud_cdc_send_break_cb(uint8_t itf, uint16_t duration_ms){
|
|||||||
|
|
||||||
// Invoked when space becomes available in TX buffer
|
// Invoked when space becomes available in TX buffer
|
||||||
void tud_cdc_tx_complete_cb(uint8_t itf){
|
void tud_cdc_tx_complete_cb(uint8_t itf){
|
||||||
//isr_log_v("itf: %u", itf);
|
if(itf < MAX_USB_CDC_DEVICES && devices[itf] != NULL && devices[itf]->tx_sem != NULL){
|
||||||
if(itf < MAX_USB_CDC_DEVICES && devices[itf] != NULL){
|
|
||||||
xSemaphoreGive(devices[itf]->tx_sem);
|
xSemaphoreGive(devices[itf]->tx_sem);
|
||||||
devices[itf]->_onTX();
|
devices[itf]->_onTX();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static size_t tinyusb_cdc_write(uint8_t itf, const uint8_t *buffer, size_t size){
|
static size_t tinyusb_cdc_write(uint8_t itf, const uint8_t *buffer, size_t size){
|
||||||
if(itf >= MAX_USB_CDC_DEVICES){
|
if(itf >= MAX_USB_CDC_DEVICES || devices[itf] == NULL || devices[itf]->tx_sem == NULL){
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if(!tud_cdc_n_connected(itf)){
|
if(!tud_cdc_n_connected(itf)){
|
||||||
@ -90,8 +85,15 @@ static size_t tinyusb_cdc_write(uint8_t itf, const uint8_t *buffer, size_t size)
|
|||||||
while(tosend){
|
while(tosend){
|
||||||
uint32_t space = tud_cdc_n_write_available(itf);
|
uint32_t space = tud_cdc_n_write_available(itf);
|
||||||
if(!space){
|
if(!space){
|
||||||
delay(1);
|
//make sure that we do not get previous semaphore
|
||||||
continue;
|
xSemaphoreTake(devices[itf]->tx_sem, 0);
|
||||||
|
//wait for tx_complete
|
||||||
|
if(xSemaphoreTake(devices[itf]->tx_sem, 200 / portTICK_PERIOD_MS) == pdTRUE){
|
||||||
|
space = tud_cdc_n_write_available(itf);
|
||||||
|
}
|
||||||
|
if(!space){
|
||||||
|
return sofar;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if(tosend < space){
|
if(tosend < space){
|
||||||
space = tosend;
|
space = tosend;
|
||||||
@ -103,7 +105,7 @@ static size_t tinyusb_cdc_write(uint8_t itf, const uint8_t *buffer, size_t size)
|
|||||||
sofar += sent;
|
sofar += sent;
|
||||||
tosend -= sent;
|
tosend -= sent;
|
||||||
tud_cdc_n_write_flush(itf);
|
tud_cdc_n_write_flush(itf);
|
||||||
xSemaphoreTake(devices[itf]->tx_sem, portMAX_DELAY);
|
//xSemaphoreTake(devices[itf]->tx_sem, portMAX_DELAY);
|
||||||
}
|
}
|
||||||
return sofar;
|
return sofar;
|
||||||
}
|
}
|
||||||
@ -113,21 +115,21 @@ static void ARDUINO_ISR_ATTR cdc0_write_char(char c)
|
|||||||
tinyusb_cdc_write(0, (const uint8_t *)&c, 1);
|
tinyusb_cdc_write(0, (const uint8_t *)&c, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
//void tud_cdc_rx_wanted_cb(uint8_t itf, char wanted_char);
|
|
||||||
|
|
||||||
static void usb_unplugged_cb(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data){
|
static void usb_unplugged_cb(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data){
|
||||||
((USBCDC*)arg)->_onUnplugged();
|
((USBCDC*)arg)->_onUnplugged();
|
||||||
}
|
}
|
||||||
|
|
||||||
USBCDC::USBCDC(uint8_t itfn) : itf(itfn), bit_rate(0), stop_bits(0), parity(0), data_bits(0), dtr(false), rts(false), connected(false), reboot_enable(true), rx_queue(NULL) {
|
USBCDC::USBCDC(uint8_t itfn) : itf(itfn), bit_rate(0), stop_bits(0), parity(0), data_bits(0), dtr(false), rts(false), connected(false), reboot_enable(true), rx_queue(NULL), tx_sem(NULL) {
|
||||||
tinyusb_enable_interface(USB_INTERFACE_CDC, TUD_CDC_DESC_LEN, load_cdc_descriptor);
|
tinyusb_enable_interface(USB_INTERFACE_CDC, TUD_CDC_DESC_LEN, load_cdc_descriptor);
|
||||||
if(itf < MAX_USB_CDC_DEVICES){
|
if(itf < MAX_USB_CDC_DEVICES){
|
||||||
devices[itf] = this;
|
|
||||||
tx_sem = NULL;
|
|
||||||
arduino_usb_event_handler_register_with(ARDUINO_USB_EVENTS, ARDUINO_USB_STOPPED_EVENT, usb_unplugged_cb, this);
|
arduino_usb_event_handler_register_with(ARDUINO_USB_EVENTS, ARDUINO_USB_STOPPED_EVENT, usb_unplugged_cb, this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
USBCDC::~USBCDC(){
|
||||||
|
end();
|
||||||
|
}
|
||||||
|
|
||||||
void USBCDC::onEvent(esp_event_handler_t callback){
|
void USBCDC::onEvent(esp_event_handler_t callback){
|
||||||
onEvent(ARDUINO_USB_CDC_ANY_EVENT, callback);
|
onEvent(ARDUINO_USB_CDC_ANY_EVENT, callback);
|
||||||
}
|
}
|
||||||
@ -137,6 +139,10 @@ void USBCDC::onEvent(arduino_usb_cdc_event_t event, esp_event_handler_t callback
|
|||||||
|
|
||||||
size_t USBCDC::setRxBufferSize(size_t rx_queue_len){
|
size_t USBCDC::setRxBufferSize(size_t rx_queue_len){
|
||||||
if(rx_queue){
|
if(rx_queue){
|
||||||
|
if(!rx_queue_len){
|
||||||
|
vQueueDelete(rx_queue);
|
||||||
|
rx_queue = NULL;
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
rx_queue = xQueueCreate(rx_queue_len, sizeof(uint8_t));
|
rx_queue = xQueueCreate(rx_queue_len, sizeof(uint8_t));
|
||||||
@ -148,15 +154,19 @@ size_t USBCDC::setRxBufferSize(size_t rx_queue_len){
|
|||||||
|
|
||||||
void USBCDC::begin(unsigned long baud)
|
void USBCDC::begin(unsigned long baud)
|
||||||
{
|
{
|
||||||
setRxBufferSize(256);//default if not preset
|
|
||||||
if(tx_sem == NULL){
|
if(tx_sem == NULL){
|
||||||
tx_sem = xSemaphoreCreateBinary();
|
tx_sem = xSemaphoreCreateBinary();
|
||||||
xSemaphoreTake(tx_sem, 0);
|
xSemaphoreTake(tx_sem, 0);
|
||||||
}
|
}
|
||||||
|
setRxBufferSize(256);//default if not preset
|
||||||
|
devices[itf] = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
void USBCDC::end()
|
void USBCDC::end()
|
||||||
{
|
{
|
||||||
|
connected = false;
|
||||||
|
devices[itf] = NULL;
|
||||||
|
setRxBufferSize(0);
|
||||||
if (tx_sem != NULL) {
|
if (tx_sem != NULL) {
|
||||||
vSemaphoreDelete(tx_sem);
|
vSemaphoreDelete(tx_sem);
|
||||||
tx_sem = NULL;
|
tx_sem = NULL;
|
||||||
@ -176,6 +186,11 @@ void USBCDC::_onUnplugged(void){
|
|||||||
enum { CDC_LINE_IDLE, CDC_LINE_1, CDC_LINE_2, CDC_LINE_3 };
|
enum { CDC_LINE_IDLE, CDC_LINE_1, CDC_LINE_2, CDC_LINE_3 };
|
||||||
void USBCDC::_onLineState(bool _dtr, bool _rts){
|
void USBCDC::_onLineState(bool _dtr, bool _rts){
|
||||||
static uint8_t lineState = CDC_LINE_IDLE;
|
static uint8_t lineState = CDC_LINE_IDLE;
|
||||||
|
|
||||||
|
if(dtr == _dtr && rts == _rts){
|
||||||
|
return; // Skip duplicate events
|
||||||
|
}
|
||||||
|
|
||||||
dtr = _dtr;
|
dtr = _dtr;
|
||||||
rts = _rts;
|
rts = _rts;
|
||||||
|
|
||||||
@ -183,6 +198,11 @@ void USBCDC::_onLineState(bool _dtr, bool _rts){
|
|||||||
if(!dtr && rts){
|
if(!dtr && rts){
|
||||||
if(lineState == CDC_LINE_IDLE){
|
if(lineState == CDC_LINE_IDLE){
|
||||||
lineState++;
|
lineState++;
|
||||||
|
if(connected){
|
||||||
|
connected = false;
|
||||||
|
arduino_usb_cdc_event_data_t p = {0};
|
||||||
|
arduino_usb_event_post(ARDUINO_USB_CDC_EVENTS, ARDUINO_USB_CDC_DISCONNECTED_EVENT, &p, sizeof(arduino_usb_cdc_event_data_t), portMAX_DELAY);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
lineState = CDC_LINE_IDLE;
|
lineState = CDC_LINE_IDLE;
|
||||||
}
|
}
|
||||||
@ -212,7 +232,7 @@ void USBCDC::_onLineState(bool _dtr, bool _rts){
|
|||||||
connected = true;
|
connected = true;
|
||||||
arduino_usb_cdc_event_data_t p = {0};
|
arduino_usb_cdc_event_data_t p = {0};
|
||||||
arduino_usb_event_post(ARDUINO_USB_CDC_EVENTS, ARDUINO_USB_CDC_CONNECTED_EVENT, &p, sizeof(arduino_usb_cdc_event_data_t), portMAX_DELAY);
|
arduino_usb_event_post(ARDUINO_USB_CDC_EVENTS, ARDUINO_USB_CDC_CONNECTED_EVENT, &p, sizeof(arduino_usb_cdc_event_data_t), portMAX_DELAY);
|
||||||
} else if(!dtr && !rts && connected){
|
} else if(!dtr && connected){
|
||||||
connected = false;
|
connected = false;
|
||||||
arduino_usb_cdc_event_data_t p = {0};
|
arduino_usb_cdc_event_data_t p = {0};
|
||||||
arduino_usb_event_post(ARDUINO_USB_CDC_EVENTS, ARDUINO_USB_CDC_DISCONNECTED_EVENT, &p, sizeof(arduino_usb_cdc_event_data_t), portMAX_DELAY);
|
arduino_usb_event_post(ARDUINO_USB_CDC_EVENTS, ARDUINO_USB_CDC_DISCONNECTED_EVENT, &p, sizeof(arduino_usb_cdc_event_data_t), portMAX_DELAY);
|
||||||
@ -228,7 +248,7 @@ void USBCDC::_onLineState(bool _dtr, bool _rts){
|
|||||||
void USBCDC::_onLineCoding(uint32_t _bit_rate, uint8_t _stop_bits, uint8_t _parity, uint8_t _data_bits){
|
void USBCDC::_onLineCoding(uint32_t _bit_rate, uint8_t _stop_bits, uint8_t _parity, uint8_t _data_bits){
|
||||||
if(bit_rate != _bit_rate || data_bits != _data_bits || stop_bits != _stop_bits || parity != _parity){
|
if(bit_rate != _bit_rate || data_bits != _data_bits || stop_bits != _stop_bits || parity != _parity){
|
||||||
// ArduinoIDE sends LineCoding with 1200bps baud to reset the device
|
// ArduinoIDE sends LineCoding with 1200bps baud to reset the device
|
||||||
if(_bit_rate == 1200){
|
if(reboot_enable && _bit_rate == 1200){
|
||||||
usb_persist_restart(RESTART_BOOTLOADER);
|
usb_persist_restart(RESTART_BOOTLOADER);
|
||||||
} else {
|
} else {
|
||||||
bit_rate = _bit_rate;
|
bit_rate = _bit_rate;
|
||||||
@ -317,7 +337,7 @@ size_t USBCDC::read(uint8_t *buffer, size_t size)
|
|||||||
|
|
||||||
void USBCDC::flush(void)
|
void USBCDC::flush(void)
|
||||||
{
|
{
|
||||||
if(itf >= MAX_USB_CDC_DEVICES){
|
if(itf >= MAX_USB_CDC_DEVICES || tx_sem == NULL){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
tud_cdc_n_write_flush(itf);
|
tud_cdc_n_write_flush(itf);
|
||||||
@ -325,7 +345,7 @@ void USBCDC::flush(void)
|
|||||||
|
|
||||||
int USBCDC::availableForWrite(void)
|
int USBCDC::availableForWrite(void)
|
||||||
{
|
{
|
||||||
if(itf >= MAX_USB_CDC_DEVICES){
|
if(itf >= MAX_USB_CDC_DEVICES || tx_sem == NULL){
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return tud_cdc_n_write_available(itf);
|
return tud_cdc_n_write_available(itf);
|
||||||
@ -364,7 +384,7 @@ USBCDC::operator bool() const
|
|||||||
return connected;
|
return connected;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ARDUINO_SERIAL_PORT //Serial used for USB CDC
|
#if ARDUINO_USB_CDC_ON_BOOT //Serial used for USB CDC
|
||||||
USBCDC Serial(0);
|
USBCDC Serial(0);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -54,6 +54,7 @@ class USBCDC: public Stream
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
USBCDC(uint8_t itf=0);
|
USBCDC(uint8_t itf=0);
|
||||||
|
~USBCDC();
|
||||||
|
|
||||||
void onEvent(esp_event_handler_t callback);
|
void onEvent(esp_event_handler_t callback);
|
||||||
void onEvent(arduino_usb_cdc_event_t event, esp_event_handler_t callback);
|
void onEvent(arduino_usb_cdc_event_t event, esp_event_handler_t callback);
|
||||||
@ -129,7 +130,7 @@ protected:
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#if ARDUINO_SERIAL_PORT //Serial used for USB CDC
|
#if ARDUINO_USB_CDC_ON_BOOT //Serial used for USB CDC
|
||||||
extern USBCDC Serial;
|
extern USBCDC Serial;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
260
cores/esp32/USBMSC.cpp
Normal file
260
cores/esp32/USBMSC.cpp
Normal file
@ -0,0 +1,260 @@
|
|||||||
|
// Copyright 2015-2021 Espressif Systems (Shanghai) PTE LTD
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
#include "esp32-hal.h"
|
||||||
|
#include "esp32-hal-tinyusb.h"
|
||||||
|
#include "USBMSC.h"
|
||||||
|
|
||||||
|
#if CFG_TUD_MSC
|
||||||
|
extern "C" uint16_t tusb_msc_load_descriptor(uint8_t * dst, uint8_t * itf)
|
||||||
|
{
|
||||||
|
uint8_t str_index = tinyusb_add_string_descriptor("TinyUSB MSC");
|
||||||
|
uint8_t ep_num = tinyusb_get_free_duplex_endpoint();
|
||||||
|
TU_VERIFY (ep_num != 0);
|
||||||
|
uint8_t descriptor[TUD_MSC_DESC_LEN] = {
|
||||||
|
// Interface number, string index, EP Out & EP In address, EP size
|
||||||
|
TUD_MSC_DESCRIPTOR(*itf, str_index, ep_num, (uint8_t)(0x80 | ep_num), 64)
|
||||||
|
};
|
||||||
|
*itf+=1;
|
||||||
|
memcpy(dst, descriptor, TUD_MSC_DESC_LEN);
|
||||||
|
return TUD_MSC_DESC_LEN;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
bool media_present;
|
||||||
|
uint8_t vendor_id[8];
|
||||||
|
uint8_t product_id[16];
|
||||||
|
uint8_t product_rev[4];
|
||||||
|
uint16_t block_size;
|
||||||
|
uint32_t block_count;
|
||||||
|
bool (*start_stop)(uint8_t power_condition, bool start, bool load_eject);
|
||||||
|
int32_t (*read)(uint32_t lba, uint32_t offset, void* buffer, uint32_t bufsize);
|
||||||
|
int32_t (*write)(uint32_t lba, uint32_t offset, uint8_t* buffer, uint32_t bufsize);
|
||||||
|
} msc_lun_t;
|
||||||
|
|
||||||
|
static const uint8_t MSC_MAX_LUN = 3;
|
||||||
|
static uint8_t MSC_ACTIVE_LUN = 0;
|
||||||
|
static msc_lun_t msc_luns[MSC_MAX_LUN];
|
||||||
|
|
||||||
|
static void cplstr(void *dst, const void * src, size_t max_len){
|
||||||
|
if(!src || !dst || !max_len){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
size_t l = strlen((const char *)src);
|
||||||
|
if(l > max_len){
|
||||||
|
l = max_len;
|
||||||
|
}
|
||||||
|
memcpy(dst, src, l);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Invoked when received GET_MAX_LUN request, required for multiple LUNs implementation
|
||||||
|
uint8_t tud_msc_get_maxlun_cb(void)
|
||||||
|
{
|
||||||
|
log_v("%u", MSC_ACTIVE_LUN);
|
||||||
|
return MSC_ACTIVE_LUN;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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])
|
||||||
|
{
|
||||||
|
log_v("[%u]", lun);
|
||||||
|
cplstr(vendor_id , msc_luns[lun].vendor_id, 8);
|
||||||
|
cplstr(product_id , msc_luns[lun].product_id, 16);
|
||||||
|
cplstr(product_rev, msc_luns[lun].product_rev, 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
{
|
||||||
|
log_v("[%u]: %u", lun, msc_luns[lun].media_present);
|
||||||
|
return msc_luns[lun].media_present; // 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)
|
||||||
|
{
|
||||||
|
log_v("[%u]", lun);
|
||||||
|
if(!msc_luns[lun].media_present){
|
||||||
|
*block_count = 0;
|
||||||
|
*block_size = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
*block_count = msc_luns[lun].block_count;
|
||||||
|
*block_size = msc_luns[lun].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)
|
||||||
|
{
|
||||||
|
log_v("[%u] power: %u, start: %u, eject: %u", lun, power_condition, start, load_eject);
|
||||||
|
if(msc_luns[lun].start_stop){
|
||||||
|
return msc_luns[lun].start_stop(power_condition, start, load_eject);
|
||||||
|
}
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
log_v("[%u], lba: %u, offset: %u, bufsize: %u", lun, lba, offset, bufsize);
|
||||||
|
if(!msc_luns[lun].media_present){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(msc_luns[lun].read){
|
||||||
|
return msc_luns[lun].read(lba, offset, buffer, bufsize);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
{
|
||||||
|
log_v("[%u], lba: %u, offset: %u, bufsize: %u", lun, lba, offset, bufsize);
|
||||||
|
if(!msc_luns[lun].media_present){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(msc_luns[lun].write){
|
||||||
|
return msc_luns[lun].write(lba, offset, buffer, bufsize);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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
|
||||||
|
log_v("[%u] cmd: %u, bufsize: %u", lun, scsi_cmd[0], bufsize);
|
||||||
|
|
||||||
|
void const* response = NULL;
|
||||||
|
uint16_t resplen = 0;
|
||||||
|
|
||||||
|
// most scsi handled is input
|
||||||
|
bool in_xfer = true;
|
||||||
|
|
||||||
|
if(!msc_luns[lun].media_present){
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
USBMSC::USBMSC(){
|
||||||
|
if(MSC_ACTIVE_LUN < MSC_MAX_LUN){
|
||||||
|
_lun = MSC_ACTIVE_LUN;
|
||||||
|
MSC_ACTIVE_LUN++;
|
||||||
|
msc_luns[_lun].media_present = false;
|
||||||
|
msc_luns[_lun].vendor_id[0] = 0;
|
||||||
|
msc_luns[_lun].product_id[0] = 0;
|
||||||
|
msc_luns[_lun].product_rev[0] = 0;
|
||||||
|
msc_luns[_lun].block_size = 0;
|
||||||
|
msc_luns[_lun].block_count = 0;
|
||||||
|
msc_luns[_lun].start_stop = NULL;
|
||||||
|
msc_luns[_lun].read = NULL;
|
||||||
|
msc_luns[_lun].write = NULL;
|
||||||
|
}
|
||||||
|
if(_lun == 0){
|
||||||
|
tinyusb_enable_interface(USB_INTERFACE_MSC, TUD_MSC_DESC_LEN, tusb_msc_load_descriptor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
USBMSC::~USBMSC(){
|
||||||
|
end();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool USBMSC::begin(uint32_t block_count, uint16_t block_size){
|
||||||
|
msc_luns[_lun].block_size = block_size;
|
||||||
|
msc_luns[_lun].block_count = block_count;
|
||||||
|
if(!msc_luns[_lun].block_size || !msc_luns[_lun].block_count || !msc_luns[_lun].read || !msc_luns[_lun].write){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void USBMSC::end(){
|
||||||
|
msc_luns[_lun].media_present = false;
|
||||||
|
msc_luns[_lun].vendor_id[0] = 0;
|
||||||
|
msc_luns[_lun].product_id[0] = 0;
|
||||||
|
msc_luns[_lun].product_rev[0] = 0;
|
||||||
|
msc_luns[_lun].block_size = 0;
|
||||||
|
msc_luns[_lun].block_count = 0;
|
||||||
|
msc_luns[_lun].start_stop = NULL;
|
||||||
|
msc_luns[_lun].read = NULL;
|
||||||
|
msc_luns[_lun].write = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void USBMSC::vendorID(const char * vid){
|
||||||
|
cplstr(msc_luns[_lun].vendor_id, vid, 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
void USBMSC::productID(const char * pid){
|
||||||
|
cplstr(msc_luns[_lun].product_id, pid, 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
void USBMSC::productRevision(const char * rev){
|
||||||
|
cplstr(msc_luns[_lun].product_rev, rev, 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
void USBMSC::onStartStop(msc_start_stop_cb cb){
|
||||||
|
msc_luns[_lun].start_stop = cb;
|
||||||
|
}
|
||||||
|
|
||||||
|
void USBMSC::onRead(msc_read_cb cb){
|
||||||
|
msc_luns[_lun].read = cb;
|
||||||
|
}
|
||||||
|
|
||||||
|
void USBMSC::onWrite(msc_write_cb cb){
|
||||||
|
msc_luns[_lun].write = cb;
|
||||||
|
}
|
||||||
|
|
||||||
|
void USBMSC::mediaPresent(bool media_present){
|
||||||
|
msc_luns[_lun].media_present = media_present;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* CONFIG_USB_MSC_ENABLED */
|
49
cores/esp32/USBMSC.h
Normal file
49
cores/esp32/USBMSC.h
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
// Copyright 2015-2021 Espressif Systems (Shanghai) PTE LTD
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include "esp32-hal.h"
|
||||||
|
#if CONFIG_TINYUSB_MSC_ENABLED
|
||||||
|
|
||||||
|
// 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
|
||||||
|
typedef bool (*msc_start_stop_cb)(uint8_t power_condition, bool start, bool load_eject);
|
||||||
|
|
||||||
|
// Copy disk's data to buffer (up to bufsize) and return number of copied bytes.
|
||||||
|
typedef int32_t (*msc_read_cb)(uint32_t lba, uint32_t offset, void* buffer, uint32_t bufsize);
|
||||||
|
|
||||||
|
// Process data in buffer to disk's storage and return number of written bytes
|
||||||
|
typedef int32_t (*msc_write_cb)(uint32_t lba, uint32_t offset, uint8_t* buffer, uint32_t bufsize);
|
||||||
|
|
||||||
|
class USBMSC
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
USBMSC();
|
||||||
|
~USBMSC();
|
||||||
|
bool begin(uint32_t block_count, uint16_t block_size);
|
||||||
|
void end();
|
||||||
|
void vendorID(const char * vid);//max 8 chars
|
||||||
|
void productID(const char * pid);//max 16 chars
|
||||||
|
void productRevision(const char * ver);//max 4 chars
|
||||||
|
void mediaPresent(bool media_present);
|
||||||
|
void onStartStop(msc_start_stop_cb cb);
|
||||||
|
void onRead(msc_read_cb cb);
|
||||||
|
void onWrite(msc_write_cb cb);
|
||||||
|
private:
|
||||||
|
uint8_t _lun;
|
||||||
|
};
|
||||||
|
#endif
|
@ -72,20 +72,15 @@ static void configure_pins(usb_hal_context_t *usb)
|
|||||||
|
|
||||||
esp_err_t tinyusb_driver_install(const tinyusb_config_t *config)
|
esp_err_t tinyusb_driver_install(const tinyusb_config_t *config)
|
||||||
{
|
{
|
||||||
log_i("Driver installation...");
|
|
||||||
|
|
||||||
// Hal init
|
|
||||||
usb_hal_context_t hal = {
|
usb_hal_context_t hal = {
|
||||||
.use_external_phy = config->external_phy
|
.use_external_phy = config->external_phy
|
||||||
};
|
};
|
||||||
usb_hal_init(&hal);
|
usb_hal_init(&hal);
|
||||||
configure_pins(&hal);
|
configure_pins(&hal);
|
||||||
|
|
||||||
if (!tusb_init()) {
|
if (!tusb_init()) {
|
||||||
log_e("Can't initialize the TinyUSB stack.");
|
log_e("Can't initialize the TinyUSB stack.");
|
||||||
return ESP_FAIL;
|
return ESP_FAIL;
|
||||||
}
|
}
|
||||||
log_i("Driver installed");
|
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -106,6 +101,7 @@ static tusb_str_t WEBUSB_URL = "";
|
|||||||
static tusb_str_t USB_DEVICE_PRODUCT = "";
|
static tusb_str_t USB_DEVICE_PRODUCT = "";
|
||||||
static tusb_str_t USB_DEVICE_MANUFACTURER = "";
|
static tusb_str_t USB_DEVICE_MANUFACTURER = "";
|
||||||
static tusb_str_t USB_DEVICE_SERIAL = "";
|
static tusb_str_t USB_DEVICE_SERIAL = "";
|
||||||
|
static tusb_str_t USB_DEVICE_LANGUAGE = "\x09\x04";//English (0x0409)
|
||||||
|
|
||||||
static uint8_t USB_DEVICE_ATTRIBUTES = 0;
|
static uint8_t USB_DEVICE_ATTRIBUTES = 0;
|
||||||
static uint16_t USB_DEVICE_POWER = 0;
|
static uint16_t USB_DEVICE_POWER = 0;
|
||||||
@ -140,7 +136,7 @@ static tusb_desc_device_t tinyusb_device_descriptor = {
|
|||||||
static uint32_t tinyusb_string_descriptor_len = 4;
|
static uint32_t tinyusb_string_descriptor_len = 4;
|
||||||
static char * tinyusb_string_descriptor[MAX_STRING_DESCRIPTORS] = {
|
static char * tinyusb_string_descriptor[MAX_STRING_DESCRIPTORS] = {
|
||||||
// array of pointer to string descriptors
|
// array of pointer to string descriptors
|
||||||
"\x09\x04", // 0: is supported language is English (0x0409)
|
USB_DEVICE_LANGUAGE, // 0: is supported language
|
||||||
USB_DEVICE_MANUFACTURER,// 1: Manufacturer
|
USB_DEVICE_MANUFACTURER,// 1: Manufacturer
|
||||||
USB_DEVICE_PRODUCT, // 2: Product
|
USB_DEVICE_PRODUCT, // 2: Product
|
||||||
USB_DEVICE_SERIAL, // 3: Serials, should use chip ID
|
USB_DEVICE_SERIAL, // 3: Serials, should use chip ID
|
||||||
@ -563,31 +559,37 @@ static void usb_device_task(void *param) {
|
|||||||
/*
|
/*
|
||||||
* PUBLIC API
|
* PUBLIC API
|
||||||
* */
|
* */
|
||||||
|
static const char *tinyusb_interface_names[USB_INTERFACE_MAX] = {"MSC", "DFU", "HID", "VENDOR", "CDC", "MIDI", "CUSTOM"};
|
||||||
|
|
||||||
|
static bool tinyusb_is_initialized = false;
|
||||||
|
|
||||||
esp_err_t tinyusb_enable_interface(tinyusb_interface_t interface, uint16_t descriptor_len, tinyusb_descriptor_cb_t cb)
|
esp_err_t tinyusb_enable_interface(tinyusb_interface_t interface, uint16_t descriptor_len, tinyusb_descriptor_cb_t cb)
|
||||||
{
|
{
|
||||||
|
if(tinyusb_is_initialized){
|
||||||
|
log_e("TinyUSB has already started! Interface %s not enabled", (interface >= USB_INTERFACE_MAX)?"":tinyusb_interface_names[interface]);
|
||||||
|
return ESP_FAIL;
|
||||||
|
}
|
||||||
if((interface >= USB_INTERFACE_MAX) || (tinyusb_loaded_interfaces_mask & (1U << interface))){
|
if((interface >= USB_INTERFACE_MAX) || (tinyusb_loaded_interfaces_mask & (1U << interface))){
|
||||||
log_e("Interface %u not enabled", interface);
|
log_e("Interface %s invalid or already enabled", (interface >= USB_INTERFACE_MAX)?"":tinyusb_interface_names[interface]);
|
||||||
return ESP_FAIL;
|
return ESP_FAIL;
|
||||||
}
|
}
|
||||||
tinyusb_loaded_interfaces_mask |= (1U << interface);
|
tinyusb_loaded_interfaces_mask |= (1U << interface);
|
||||||
tinyusb_config_descriptor_len += descriptor_len;
|
tinyusb_config_descriptor_len += descriptor_len;
|
||||||
tinyusb_loaded_interfaces_callbacks[interface] = cb;
|
tinyusb_loaded_interfaces_callbacks[interface] = cb;
|
||||||
log_d("Interface %u enabled", interface);
|
log_d("Interface %s enabled", tinyusb_interface_names[interface]);
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
esp_err_t tinyusb_init(tinyusb_device_config_t *config) {
|
esp_err_t tinyusb_init(tinyusb_device_config_t *config) {
|
||||||
static bool initialized = false;
|
if(tinyusb_is_initialized){
|
||||||
if(initialized){
|
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
initialized = true;
|
tinyusb_is_initialized = true;
|
||||||
|
|
||||||
tinyusb_endpoints.val = 0;
|
tinyusb_endpoints.val = 0;
|
||||||
tinyusb_apply_device_config(config);
|
tinyusb_apply_device_config(config);
|
||||||
if (!tinyusb_load_enabled_interfaces()) {
|
if (!tinyusb_load_enabled_interfaces()) {
|
||||||
initialized = false;
|
tinyusb_is_initialized = false;
|
||||||
return ESP_FAIL;
|
return ESP_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -605,7 +607,7 @@ esp_err_t tinyusb_init(tinyusb_device_config_t *config) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (esp_register_shutdown_handler(usb_persist_shutdown_handler) != ESP_OK) {
|
if (esp_register_shutdown_handler(usb_persist_shutdown_handler) != ESP_OK) {
|
||||||
initialized = false;
|
tinyusb_is_initialized = false;
|
||||||
return ESP_FAIL;
|
return ESP_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -614,7 +616,7 @@ esp_err_t tinyusb_init(tinyusb_device_config_t *config) {
|
|||||||
};
|
};
|
||||||
esp_err_t err = tinyusb_driver_install(&tusb_cfg);
|
esp_err_t err = tinyusb_driver_install(&tusb_cfg);
|
||||||
if (err != ESP_OK) {
|
if (err != ESP_OK) {
|
||||||
initialized = false;
|
tinyusb_is_initialized = false;
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
xTaskCreate(usb_device_task, "usbd", 4096, NULL, configMAX_PRIORITIES - 1, NULL);
|
xTaskCreate(usb_device_task, "usbd", 4096, NULL, configMAX_PRIORITIES - 1, NULL);
|
||||||
@ -690,84 +692,4 @@ uint8_t tinyusb_get_free_out_endpoint(void){
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
void usb_dw_reg_dump(void)
|
|
||||||
{
|
|
||||||
#define USB_PRINT_REG(r) printf("USB0." #r " = 0x%x;\n", USB0.r)
|
|
||||||
#define USB_PRINT_IREG(i, r) printf("USB0.in_ep_reg[%u]." #r " = 0x%x;\n", i, USB0.in_ep_reg[i].r)
|
|
||||||
#define USB_PRINT_OREG(i, r) printf("USB0.out_ep_reg[%u]." #r " = 0x%x;\n", i, USB0.out_ep_reg[i].r)
|
|
||||||
uint8_t i;
|
|
||||||
USB_PRINT_REG(gotgctl);
|
|
||||||
USB_PRINT_REG(gotgint);
|
|
||||||
USB_PRINT_REG(gahbcfg);
|
|
||||||
USB_PRINT_REG(gusbcfg);
|
|
||||||
USB_PRINT_REG(grstctl);
|
|
||||||
USB_PRINT_REG(gintsts);
|
|
||||||
USB_PRINT_REG(gintmsk);
|
|
||||||
USB_PRINT_REG(grxstsr);
|
|
||||||
USB_PRINT_REG(grxstsp);
|
|
||||||
USB_PRINT_REG(grxfsiz);
|
|
||||||
USB_PRINT_REG(gnptxsts);
|
|
||||||
USB_PRINT_REG(gpvndctl);
|
|
||||||
USB_PRINT_REG(ggpio);
|
|
||||||
USB_PRINT_REG(guid);
|
|
||||||
USB_PRINT_REG(gsnpsid);
|
|
||||||
USB_PRINT_REG(ghwcfg1);
|
|
||||||
USB_PRINT_REG(ghwcfg2);
|
|
||||||
USB_PRINT_REG(ghwcfg3);
|
|
||||||
USB_PRINT_REG(ghwcfg4);
|
|
||||||
USB_PRINT_REG(glpmcfg);
|
|
||||||
USB_PRINT_REG(gpwrdn);
|
|
||||||
USB_PRINT_REG(gdfifocfg);
|
|
||||||
USB_PRINT_REG(gadpctl);
|
|
||||||
USB_PRINT_REG(hptxfsiz);
|
|
||||||
USB_PRINT_REG(hcfg);
|
|
||||||
USB_PRINT_REG(hfir);
|
|
||||||
USB_PRINT_REG(hfnum);
|
|
||||||
USB_PRINT_REG(hptxsts);
|
|
||||||
USB_PRINT_REG(haint);
|
|
||||||
USB_PRINT_REG(haintmsk);
|
|
||||||
USB_PRINT_REG(hflbaddr);
|
|
||||||
USB_PRINT_REG(hprt);
|
|
||||||
USB_PRINT_REG(dcfg);
|
|
||||||
USB_PRINT_REG(dctl);
|
|
||||||
USB_PRINT_REG(dsts);
|
|
||||||
USB_PRINT_REG(diepmsk);
|
|
||||||
USB_PRINT_REG(doepmsk);
|
|
||||||
USB_PRINT_REG(daint);
|
|
||||||
USB_PRINT_REG(daintmsk);
|
|
||||||
USB_PRINT_REG(dtknqr1);
|
|
||||||
USB_PRINT_REG(dtknqr2);
|
|
||||||
USB_PRINT_REG(dvbusdis);
|
|
||||||
USB_PRINT_REG(dvbuspulse);
|
|
||||||
USB_PRINT_REG(dtknqr3_dthrctl);
|
|
||||||
USB_PRINT_REG(dtknqr4_fifoemptymsk);
|
|
||||||
USB_PRINT_REG(deachint);
|
|
||||||
USB_PRINT_REG(deachintmsk);
|
|
||||||
USB_PRINT_REG(pcgctrl);
|
|
||||||
USB_PRINT_REG(pcgctrl1);
|
|
||||||
USB_PRINT_REG(gnptxfsiz);
|
|
||||||
for (i = 0; i < 4; i++) {
|
|
||||||
printf("USB0.dieptxf[%u] = 0x%x;\n", i, USB0.dieptxf[i]);
|
|
||||||
}
|
|
||||||
// for (i = 0; i < 16; i++) {
|
|
||||||
// printf("USB0.diepeachintmsk[%u] = 0x%x;\n", i, USB0.diepeachintmsk[i]);
|
|
||||||
// }
|
|
||||||
// for (i = 0; i < 16; i++) {
|
|
||||||
// printf("USB0.doepeachintmsk[%u] = 0x%x;\n", i, USB0.doepeachintmsk[i]);
|
|
||||||
// }
|
|
||||||
for (i = 0; i < 7; i++) {
|
|
||||||
printf("// EP %u:\n", i);
|
|
||||||
USB_PRINT_IREG(i, diepctl);
|
|
||||||
USB_PRINT_IREG(i, diepint);
|
|
||||||
USB_PRINT_IREG(i, dieptsiz);
|
|
||||||
USB_PRINT_IREG(i, diepdma);
|
|
||||||
USB_PRINT_IREG(i, dtxfsts);
|
|
||||||
USB_PRINT_OREG(i, doepctl);
|
|
||||||
USB_PRINT_OREG(i, doepint);
|
|
||||||
USB_PRINT_OREG(i, doeptsiz);
|
|
||||||
USB_PRINT_OREG(i, doepdma);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
#endif /* CONFIG_TINYUSB_ENABLED */
|
#endif /* CONFIG_TINYUSB_ENABLED */
|
||||||
|
@ -82,11 +82,11 @@ void usb_persist_restart(restart_type_t mode);
|
|||||||
|
|
||||||
// The following definitions and functions are to be used only by the drivers
|
// The following definitions and functions are to be used only by the drivers
|
||||||
typedef enum {
|
typedef enum {
|
||||||
USB_INTERFACE_CDC,
|
USB_INTERFACE_MSC,
|
||||||
USB_INTERFACE_DFU,
|
USB_INTERFACE_DFU,
|
||||||
USB_INTERFACE_HID,
|
USB_INTERFACE_HID,
|
||||||
USB_INTERFACE_VENDOR,
|
USB_INTERFACE_VENDOR,
|
||||||
USB_INTERFACE_MSC,
|
USB_INTERFACE_CDC,
|
||||||
USB_INTERFACE_MIDI,
|
USB_INTERFACE_MIDI,
|
||||||
USB_INTERFACE_CUSTOM,
|
USB_INTERFACE_CUSTOM,
|
||||||
USB_INTERFACE_MAX
|
USB_INTERFACE_MAX
|
||||||
|
204
cores/esp32/firmware_msc_fat.c
Normal file
204
cores/esp32/firmware_msc_fat.c
Normal file
@ -0,0 +1,204 @@
|
|||||||
|
// Copyright 2015-2021 Espressif Systems (Shanghai) PTE LTD
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
#include "firmware_msc_fat.h"
|
||||||
|
//copy up to max_len chars from src to dst and do not terminate
|
||||||
|
static size_t cplstr(void *dst, const void * src, size_t max_len){
|
||||||
|
if(!src || !dst || !max_len){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
size_t l = strlen((const char *)src);
|
||||||
|
if(l > max_len){
|
||||||
|
l = max_len;
|
||||||
|
}
|
||||||
|
memcpy(dst, src, l);
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
|
||||||
|
//copy up to max_len chars from src to dst, adding spaces up to max_len. do not terminate
|
||||||
|
static void cplstrsp(void *dst, const void * src, size_t max_len){
|
||||||
|
size_t l = cplstr(dst, src, max_len);
|
||||||
|
for(l; l < max_len; l++){
|
||||||
|
((uint8_t*)dst)[l] = 0x20;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FAT12
|
||||||
|
static const char * FAT12_FILE_SYSTEM_TYPE = "FAT12";
|
||||||
|
|
||||||
|
static uint16_t fat12_sectors_per_alloc_table(uint32_t sector_num){
|
||||||
|
uint32_t required_bytes = (((sector_num * 3)+1)/2);
|
||||||
|
return (required_bytes / DISK_SECTOR_SIZE) + ((required_bytes & DISK_SECTOR_SIZE)?1:0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8_t * fat12_add_table(uint8_t * dst, fat_boot_sector_t * boot){
|
||||||
|
memset(dst+DISK_SECTOR_SIZE, 0, boot->sectors_per_alloc_table * DISK_SECTOR_SIZE);
|
||||||
|
uint8_t * d = dst + DISK_SECTOR_SIZE;
|
||||||
|
d[0] = 0xF8;
|
||||||
|
d[1] = 0xFF;
|
||||||
|
d[2] = 0xFF;
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void fat12_set_table_index(uint8_t * table, uint16_t index, uint16_t value){
|
||||||
|
uint16_t offset = (index >> 1) * 3;
|
||||||
|
uint8_t * data = table + offset;
|
||||||
|
if(index & 1){
|
||||||
|
data[2] = (value >> 4) & 0xFF;
|
||||||
|
data[1] = (data[1] & 0xF) | ((value & 0xF) << 4);
|
||||||
|
} else {
|
||||||
|
data[0] = value & 0xFF;
|
||||||
|
data[1] = (data[1] & 0xF0) | ((value >> 8) & 0xF);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//FAT16
|
||||||
|
static const char * FAT16_FILE_SYSTEM_TYPE = "FAT16";
|
||||||
|
|
||||||
|
static uint16_t fat16_sectors_per_alloc_table(uint32_t sector_num){
|
||||||
|
uint32_t required_bytes = sector_num * 2;
|
||||||
|
return (required_bytes / DISK_SECTOR_SIZE) + ((required_bytes & DISK_SECTOR_SIZE)?1:0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8_t * fat16_add_table(uint8_t * dst, fat_boot_sector_t * boot){
|
||||||
|
memset(dst+DISK_SECTOR_SIZE, 0, boot->sectors_per_alloc_table * DISK_SECTOR_SIZE);
|
||||||
|
uint16_t * d = (uint16_t *)(dst + DISK_SECTOR_SIZE);
|
||||||
|
d[0] = 0xFFF8;
|
||||||
|
d[1] = 0xFFFF;
|
||||||
|
return (uint8_t *)d;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void fat16_set_table_index(uint8_t * table, uint16_t index, uint16_t value){
|
||||||
|
uint16_t offset = index * 2;
|
||||||
|
*(uint16_t *)(table + offset) = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Interface
|
||||||
|
const char * fat_file_system_type(bool fat16) {
|
||||||
|
return ((fat16)?FAT16_FILE_SYSTEM_TYPE:FAT12_FILE_SYSTEM_TYPE);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t fat_sectors_per_alloc_table(uint32_t sector_num, bool fat16){
|
||||||
|
if(fat16){
|
||||||
|
return fat16_sectors_per_alloc_table(sector_num);
|
||||||
|
}
|
||||||
|
return fat12_sectors_per_alloc_table(sector_num);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t * fat_add_table(uint8_t * dst, fat_boot_sector_t * boot, bool fat16){
|
||||||
|
if(fat16){
|
||||||
|
return fat16_add_table(dst, boot);
|
||||||
|
}
|
||||||
|
return fat12_add_table(dst, boot);
|
||||||
|
}
|
||||||
|
|
||||||
|
void fat_set_table_index(uint8_t * table, uint16_t index, uint16_t value, bool fat16){
|
||||||
|
if(fat16){
|
||||||
|
fat16_set_table_index(table, index, value);
|
||||||
|
} else {
|
||||||
|
fat12_set_table_index(table, index, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fat_boot_sector_t * fat_add_boot_sector(uint8_t * dst, uint16_t sector_num, uint16_t table_sectors, const char * file_system_type, const char * volume_label, uint32_t serial_number){
|
||||||
|
fat_boot_sector_t *boot = (fat_boot_sector_t*)dst;
|
||||||
|
boot->jump_instruction[0] = 0xEB;
|
||||||
|
boot->jump_instruction[1] = 0x3C;
|
||||||
|
boot->jump_instruction[2] = 0x90;
|
||||||
|
cplstr(boot->oem_name, "MSDOS5.0", 8);
|
||||||
|
boot->bytes_per_sector = DISK_SECTOR_SIZE;
|
||||||
|
boot->sectors_per_cluster = 1;
|
||||||
|
boot->reserved_sectors_count = 1;
|
||||||
|
boot->file_alloc_tables_num = 1;
|
||||||
|
boot->max_root_dir_entries = 16;
|
||||||
|
boot->fat12_sector_num = sector_num;
|
||||||
|
boot->media_descriptor = 0xF8;
|
||||||
|
boot->sectors_per_alloc_table = table_sectors;
|
||||||
|
boot->sectors_per_track = 1;
|
||||||
|
boot->num_heads = 1;
|
||||||
|
boot->hidden_sectors_count = 0;
|
||||||
|
boot->total_sectors_32 = 0;
|
||||||
|
boot->physical_drive_number = 0x00;
|
||||||
|
boot->reserved0 = 0x00;
|
||||||
|
boot->extended_boot_signature = 0x29;
|
||||||
|
boot->serial_number = serial_number;
|
||||||
|
cplstrsp(boot->volume_label, volume_label, 11);
|
||||||
|
memset(boot->reserved, 0, 448);
|
||||||
|
cplstrsp(boot->file_system_type, file_system_type, 8);
|
||||||
|
boot->signature = 0xAA55;
|
||||||
|
return boot;
|
||||||
|
}
|
||||||
|
|
||||||
|
fat_dir_entry_t * fat_add_label(uint8_t * dst, const char * volume_label){
|
||||||
|
fat_boot_sector_t * boot = (fat_boot_sector_t *)dst;
|
||||||
|
fat_dir_entry_t * entry = (fat_dir_entry_t *)(dst + ((boot->sectors_per_alloc_table+1) * DISK_SECTOR_SIZE));
|
||||||
|
memset(entry, 0, sizeof(fat_dir_entry_t));
|
||||||
|
cplstrsp(entry->volume_label, volume_label, 11);
|
||||||
|
entry->file_attr = FAT_FILE_ATTR_VOLUME_LABEL;
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
fat_dir_entry_t * fat_add_root_file(uint8_t * dst, uint8_t index, const char * file_name, const char * file_extension, size_t file_size, uint16_t data_start_sector, bool is_fat16){
|
||||||
|
fat_boot_sector_t * boot = (fat_boot_sector_t *)dst;
|
||||||
|
uint8_t * table = dst + DISK_SECTOR_SIZE;
|
||||||
|
fat_dir_entry_t * entry = (fat_dir_entry_t *)(dst + ((boot->sectors_per_alloc_table+1) * DISK_SECTOR_SIZE) + (index * sizeof(fat_dir_entry_t)));
|
||||||
|
memset(entry, 0, sizeof(fat_dir_entry_t));
|
||||||
|
cplstrsp(entry->file_name, file_name, 8);
|
||||||
|
cplstrsp(entry->file_extension, file_extension, 3);
|
||||||
|
entry->file_attr = FAT_FILE_ATTR_ARCHIVE;
|
||||||
|
entry->file_size = file_size;
|
||||||
|
entry->data_start_sector = data_start_sector;
|
||||||
|
entry->extended_attr = 0;
|
||||||
|
|
||||||
|
uint16_t file_sectors = file_size / DISK_SECTOR_SIZE;
|
||||||
|
if(file_size % DISK_SECTOR_SIZE){
|
||||||
|
file_sectors++;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t data_end_sector = data_start_sector + file_sectors;
|
||||||
|
for(uint16_t i=data_start_sector; i<(data_end_sector-1); i++){
|
||||||
|
fat_set_table_index(table, i, i+1, is_fat16);
|
||||||
|
}
|
||||||
|
fat_set_table_index(table, data_end_sector-1, 0xFFFF, is_fat16);
|
||||||
|
|
||||||
|
//Set Firmware Date based on the build time
|
||||||
|
static const char * month_names_short[12] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
|
||||||
|
char mstr[8] = {'\0',};
|
||||||
|
const char *str = __DATE__ " " __TIME__;
|
||||||
|
int ms=0, seconds=0, minutes=0, hours=0, year=0, date=0, month=0;
|
||||||
|
int r = sscanf(str,"%s %d %d %d:%d:%d", mstr, &date, &year, &hours, &minutes, &seconds);
|
||||||
|
if(r >= 0){
|
||||||
|
for(int i=0; i<12; i++){
|
||||||
|
if(!strcmp(mstr, month_names_short[i])){
|
||||||
|
month = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
entry->creation_time_ms = FAT_MS2V(seconds, ms);
|
||||||
|
entry->creation_time_hms = FAT_HMS2V(hours, minutes, seconds);
|
||||||
|
entry->creation_time_ymd = FAT_YMD2V(year, month, date);
|
||||||
|
entry->last_access_ymd = entry->creation_time_ymd;
|
||||||
|
entry->last_modified_hms = entry->creation_time_hms;
|
||||||
|
entry->last_modified_ymd = entry->creation_time_ymd;
|
||||||
|
}
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t fat_lfn_checksum(const uint8_t *short_filename){
|
||||||
|
uint8_t sum = 0;
|
||||||
|
for (uint8_t i = 11; i; i--) {
|
||||||
|
sum = ((sum & 1) << 7) + (sum >> 1) + *short_filename++;
|
||||||
|
}
|
||||||
|
return sum;
|
||||||
|
}
|
141
cores/esp32/firmware_msc_fat.h
Normal file
141
cores/esp32/firmware_msc_fat.h
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
// Copyright 2015-2021 Espressif Systems (Shanghai) PTE LTD
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define FAT_U8(v) ((v) & 0xFF)
|
||||||
|
#define FAT_U16(v) FAT_U8(v), FAT_U8((v) >> 8)
|
||||||
|
#define FAT_U32(v) FAT_U8(v), FAT_U8((v) >> 8), FAT_U8((v) >> 16), FAT_U8((v) >> 24)
|
||||||
|
|
||||||
|
#define FAT12_TBL2B(l,h) FAT_U8(l), FAT_U8(((l >> 8) & 0xF) | ((h << 4) & 0xF0)), FAT_U8(h >> 4)
|
||||||
|
|
||||||
|
#define FAT_MS2B(s,ms) FAT_U8(((((s) & 0x1) * 1000) + (ms)) / 10)
|
||||||
|
#define FAT_HMS2B(h,m,s) FAT_U8(((s) >> 1)|(((m) & 0x7) << 5)), FAT_U8((((m) >> 3) & 0x7)|((h) << 3))
|
||||||
|
#define FAT_YMD2B(y,m,d) FAT_U8(((d) & 0x1F)|(((m) & 0x7) << 5)), FAT_U8((((m) >> 3) & 0x1)|((((y) - 1980) & 0x7F) << 1))
|
||||||
|
|
||||||
|
#define FAT_MS2V(s,ms) FAT_U8(((((s) & 0x1) * 1000) + (ms)) / 10)
|
||||||
|
#define FAT_HMS2V(h,m,s) (FAT_U8(((s) >> 1)|(((m) & 0x7) << 5)) | (FAT_U8((((m) >> 3) & 0x7)|((h) << 3)) << 8))
|
||||||
|
#define FAT_YMD2V(y,m,d) (FAT_U8(((d) & 0x1F)|(((m) & 0x7) << 5)) | (FAT_U8((((m) >> 3) & 0x1)|((((y) - 1980) & 0x7F) << 1)) << 8))
|
||||||
|
|
||||||
|
#define FAT_B2HMS(hms) ((hms >> 11) & 0x1F), ((hms >> 5) & 0x3F), ((hms & 0x1F) << 1)
|
||||||
|
#define FAT_B2YMD(ymd) (((ymd >> 9) & 0x7F) + 1980), ((ymd >> 5) & 0x0F), (ymd & 0x1F)
|
||||||
|
|
||||||
|
#define FAT_FILE_ATTR_READ_ONLY 0x01
|
||||||
|
#define FAT_FILE_ATTR_HIDDEN 0x02
|
||||||
|
#define FAT_FILE_ATTR_SYSTEM 0x04
|
||||||
|
#define FAT_FILE_ATTR_VOLUME_LABEL 0x08
|
||||||
|
#define FAT_FILE_ATTR_SUBDIRECTORY 0x10
|
||||||
|
#define FAT_FILE_ATTR_ARCHIVE 0x20
|
||||||
|
#define FAT_FILE_ATTR_DEVICE 0x40
|
||||||
|
|
||||||
|
static const uint16_t DISK_SECTOR_SIZE = 512;
|
||||||
|
|
||||||
|
#define FAT_SIZE_TO_SECTORS(bytes) ((bytes) / DISK_SECTOR_SIZE) + (((bytes) % DISK_SECTOR_SIZE)?1:0)
|
||||||
|
|
||||||
|
typedef struct __attribute__ ((packed)) {
|
||||||
|
uint8_t jump_instruction[3];
|
||||||
|
char oem_name[8];//padded with spaces (0x20)
|
||||||
|
uint16_t bytes_per_sector;//DISK_SECTOR_SIZE usually 512
|
||||||
|
uint8_t sectors_per_cluster;//Allowed values are 1, 2, 4, 8, 16, 32, 64, and 128
|
||||||
|
uint16_t reserved_sectors_count;//At least 1 for this sector, usually 32 for FAT32
|
||||||
|
uint8_t file_alloc_tables_num;//Almost always 2; RAM disks might use 1
|
||||||
|
uint16_t max_root_dir_entries;//FAT12 and FAT16
|
||||||
|
uint16_t fat12_sector_num;//DISK_SECTOR_NUM FAT12 and FAT16
|
||||||
|
uint8_t media_descriptor;
|
||||||
|
uint16_t sectors_per_alloc_table;//FAT12 and FAT16
|
||||||
|
uint16_t sectors_per_track;//A value of 0 may indicate LBA-only access
|
||||||
|
uint16_t num_heads;
|
||||||
|
uint32_t hidden_sectors_count;
|
||||||
|
uint32_t total_sectors_32;
|
||||||
|
uint8_t physical_drive_number;//0x00 for (first) removable media, 0x80 for (first) fixed disk
|
||||||
|
uint8_t reserved0;
|
||||||
|
uint8_t extended_boot_signature;//should be 0x29
|
||||||
|
uint32_t serial_number;//0x1234 => 1234
|
||||||
|
char volume_label[11];//padded with spaces (0x20)
|
||||||
|
char file_system_type[8];//padded with spaces (0x20)
|
||||||
|
uint8_t reserved[448];
|
||||||
|
uint16_t signature;//should be 0xAA55
|
||||||
|
} fat_boot_sector_t;
|
||||||
|
|
||||||
|
typedef struct __attribute__ ((packed)) {
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
char file_name[8];//padded with spaces (0x20)
|
||||||
|
char file_extension[3];//padded with spaces (0x20)
|
||||||
|
};
|
||||||
|
struct {
|
||||||
|
uint8_t file_magic;// 0xE5:deleted, 0x05:will_be_deleted, 0x00:end_marker, 0x2E:dot_marker(. or ..)
|
||||||
|
char file_magic_data[10];
|
||||||
|
};
|
||||||
|
char volume_label[11];//padded with spaces (0x20)
|
||||||
|
};
|
||||||
|
uint8_t file_attr;//mask of FAT_FILE_ATTR_*
|
||||||
|
uint8_t reserved;//always 0
|
||||||
|
uint8_t creation_time_ms;//ms * 10; max 1990 (1s 990ms)
|
||||||
|
uint16_t creation_time_hms; // [5:6:5] => h:m:(s/2)
|
||||||
|
uint16_t creation_time_ymd; // [7:4:5] => (y+1980):m:d
|
||||||
|
uint16_t last_access_ymd;
|
||||||
|
uint16_t extended_attr;
|
||||||
|
uint16_t last_modified_hms;
|
||||||
|
uint16_t last_modified_ymd;
|
||||||
|
uint16_t data_start_sector;
|
||||||
|
uint32_t file_size;
|
||||||
|
} fat_dir_entry_t;
|
||||||
|
|
||||||
|
typedef struct __attribute__ ((packed)) {
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
uint8_t number:5;
|
||||||
|
uint8_t reserved0:1;
|
||||||
|
uint8_t llfp:1;
|
||||||
|
uint8_t reserved1:1;
|
||||||
|
} seq;
|
||||||
|
uint8_t seq_num; //0xE5: Deleted Entry
|
||||||
|
};
|
||||||
|
uint16_t name0[5];
|
||||||
|
uint8_t attr; //ALWAYS 0x0F
|
||||||
|
uint8_t type; //ALWAYS 0x00
|
||||||
|
uint8_t dos_checksum;
|
||||||
|
uint16_t name1[6];
|
||||||
|
uint16_t first_cluster; //ALWAYS 0x0000
|
||||||
|
uint16_t name2[2];
|
||||||
|
} fat_lfn_entry_t;
|
||||||
|
|
||||||
|
typedef union {
|
||||||
|
fat_dir_entry_t dir;
|
||||||
|
fat_lfn_entry_t lfn;
|
||||||
|
} fat_entry_t;
|
||||||
|
|
||||||
|
const char * fat_file_system_type(bool fat16);
|
||||||
|
uint16_t fat_sectors_per_alloc_table(uint32_t sector_num, bool fat16);
|
||||||
|
uint8_t * fat_add_table(uint8_t * dst, fat_boot_sector_t * boot, bool fat16);
|
||||||
|
void fat_set_table_index(uint8_t * table, uint16_t index, uint16_t value, bool fat16);
|
||||||
|
fat_boot_sector_t * fat_add_boot_sector(uint8_t * dst, uint16_t sector_num, uint16_t table_sectors, const char * file_system_type, const char * volume_label, uint32_t serial_number);
|
||||||
|
fat_dir_entry_t * fat_add_label(uint8_t * dst, const char * volume_label);
|
||||||
|
fat_dir_entry_t * fat_add_root_file(uint8_t * dst, uint8_t index, const char * file_name, const char * file_extension, size_t file_size, uint16_t data_start_sector, bool is_fat16);
|
||||||
|
uint8_t fat_lfn_checksum(const uint8_t *short_filename);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
@ -2,8 +2,11 @@
|
|||||||
#include "freertos/task.h"
|
#include "freertos/task.h"
|
||||||
#include "esp_task_wdt.h"
|
#include "esp_task_wdt.h"
|
||||||
#include "Arduino.h"
|
#include "Arduino.h"
|
||||||
#if ARDUINO_SERIAL_PORT //Serial used for USB CDC
|
#if (ARDUINO_USB_CDC_ON_BOOT|ARDUINO_USB_MSC_ON_BOOT|ARDUINO_USB_DFU_ON_BOOT)
|
||||||
#include "USB.h"
|
#include "USB.h"
|
||||||
|
#if ARDUINO_USB_MSC_ON_BOOT
|
||||||
|
#include "FirmwareMSC.h"
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef ARDUINO_LOOP_STACK_SIZE
|
#ifndef ARDUINO_LOOP_STACK_SIZE
|
||||||
@ -47,9 +50,17 @@ void loopTask(void *pvParameters)
|
|||||||
|
|
||||||
extern "C" void app_main()
|
extern "C" void app_main()
|
||||||
{
|
{
|
||||||
#if ARDUINO_SERIAL_PORT //Serial used for USB CDC
|
#if ARDUINO_USB_CDC_ON_BOOT
|
||||||
USB.begin();
|
|
||||||
Serial.begin();
|
Serial.begin();
|
||||||
|
#endif
|
||||||
|
#if ARDUINO_USB_MSC_ON_BOOT
|
||||||
|
MSC_Update.begin();
|
||||||
|
#endif
|
||||||
|
#if ARDUINO_USB_DFU_ON_BOOT
|
||||||
|
USB.enableDFU();
|
||||||
|
#endif
|
||||||
|
#if ARDUINO_USB_ON_BOOT
|
||||||
|
USB.begin();
|
||||||
#endif
|
#endif
|
||||||
loopTaskWDTEnabled = false;
|
loopTaskWDTEnabled = false;
|
||||||
initArduino();
|
initArduino();
|
||||||
|
0
libraries/USB/examples/FirmwareMSC/.skip.esp32
Normal file
0
libraries/USB/examples/FirmwareMSC/.skip.esp32
Normal file
0
libraries/USB/examples/FirmwareMSC/.skip.esp32c3
Normal file
0
libraries/USB/examples/FirmwareMSC/.skip.esp32c3
Normal file
74
libraries/USB/examples/FirmwareMSC/FirmwareMSC.ino
Normal file
74
libraries/USB/examples/FirmwareMSC/FirmwareMSC.ino
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
#include "USB.h"
|
||||||
|
#include "FirmwareMSC.h"
|
||||||
|
|
||||||
|
#if !ARDUINO_USB_MSC_ON_BOOT
|
||||||
|
FirmwareMSC MSC_Update;
|
||||||
|
#endif
|
||||||
|
#if ARDUINO_USB_CDC_ON_BOOT
|
||||||
|
#define HWSerial Serial0
|
||||||
|
#define USBSerial Serial
|
||||||
|
#else
|
||||||
|
#define HWSerial Serial
|
||||||
|
USBCDC USBSerial;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void usbEventCallback(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data){
|
||||||
|
if(event_base == ARDUINO_USB_EVENTS){
|
||||||
|
arduino_usb_event_data_t * data = (arduino_usb_event_data_t*)event_data;
|
||||||
|
switch (event_id){
|
||||||
|
case ARDUINO_USB_STARTED_EVENT:
|
||||||
|
HWSerial.println("USB PLUGGED");
|
||||||
|
break;
|
||||||
|
case ARDUINO_USB_STOPPED_EVENT:
|
||||||
|
HWSerial.println("USB UNPLUGGED");
|
||||||
|
break;
|
||||||
|
case ARDUINO_USB_SUSPEND_EVENT:
|
||||||
|
HWSerial.printf("USB SUSPENDED: remote_wakeup_en: %u\n", data->suspend.remote_wakeup_en);
|
||||||
|
break;
|
||||||
|
case ARDUINO_USB_RESUME_EVENT:
|
||||||
|
HWSerial.println("USB RESUMED");
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else if(event_base == ARDUINO_FIRMWARE_MSC_EVENTS){
|
||||||
|
arduino_firmware_msc_event_data_t * data = (arduino_firmware_msc_event_data_t*)event_data;
|
||||||
|
switch (event_id){
|
||||||
|
case ARDUINO_FIRMWARE_MSC_START_EVENT:
|
||||||
|
HWSerial.println("MSC Update Start");
|
||||||
|
break;
|
||||||
|
case ARDUINO_FIRMWARE_MSC_WRITE_EVENT:
|
||||||
|
//HWSerial.printf("MSC Update Write %u bytes at offset %u\n", data->write.size, data->write.offset);
|
||||||
|
HWSerial.print(".");
|
||||||
|
break;
|
||||||
|
case ARDUINO_FIRMWARE_MSC_END_EVENT:
|
||||||
|
HWSerial.printf("\nMSC Update End: %u bytes\n", data->end.size);
|
||||||
|
break;
|
||||||
|
case ARDUINO_FIRMWARE_MSC_ERROR_EVENT:
|
||||||
|
HWSerial.printf("MSC Update ERROR! Progress: %u bytes\n", data->error.size);
|
||||||
|
break;
|
||||||
|
case ARDUINO_FIRMWARE_MSC_POWER_EVENT:
|
||||||
|
HWSerial.printf("MSC Update Power: power: %u, start: %u, eject: %u", data->power.power_condition, data->power.start, data->power.load_eject);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
HWSerial.begin(115200);
|
||||||
|
HWSerial.setDebugOutput(true);
|
||||||
|
|
||||||
|
USB.onEvent(usbEventCallback);
|
||||||
|
MSC_Update.onEvent(usbEventCallback);
|
||||||
|
MSC_Update.begin();
|
||||||
|
USBSerial.begin();
|
||||||
|
USB.begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
// put your main code here, to run repeatedly
|
||||||
|
}
|
0
libraries/USB/examples/USBMSC/.skip.esp32
Normal file
0
libraries/USB/examples/USBMSC/.skip.esp32
Normal file
0
libraries/USB/examples/USBMSC/.skip.esp32c3
Normal file
0
libraries/USB/examples/USBMSC/.skip.esp32c3
Normal file
192
libraries/USB/examples/USBMSC/USBMSC.ino
Normal file
192
libraries/USB/examples/USBMSC/USBMSC.ino
Normal file
@ -0,0 +1,192 @@
|
|||||||
|
#include "USB.h"
|
||||||
|
#include "USBMSC.h"
|
||||||
|
|
||||||
|
#if ARDUINO_USB_CDC_ON_BOOT
|
||||||
|
#define HWSerial Serial0
|
||||||
|
#define USBSerial Serial
|
||||||
|
#else
|
||||||
|
#define HWSerial Serial
|
||||||
|
USBCDC USBSerial;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
USBMSC MSC;
|
||||||
|
|
||||||
|
#define FAT_U8(v) ((v) & 0xFF)
|
||||||
|
#define FAT_U16(v) FAT_U8(v), FAT_U8((v) >> 8)
|
||||||
|
#define FAT_U32(v) FAT_U8(v), FAT_U8((v) >> 8), FAT_U8((v) >> 16), FAT_U8((v) >> 24)
|
||||||
|
#define FAT_MS2B(s,ms) FAT_U8(((((s) & 0x1) * 1000) + (ms)) / 10)
|
||||||
|
#define FAT_HMS2B(h,m,s) FAT_U8(((s) >> 1)|(((m) & 0x7) << 5)), FAT_U8((((m) >> 3) & 0x7)|((h) << 3))
|
||||||
|
#define FAT_YMD2B(y,m,d) FAT_U8(((d) & 0x1F)|(((m) & 0x7) << 5)), FAT_U8((((m) >> 3) & 0x1)|((((y) - 1980) & 0x7F) << 1))
|
||||||
|
#define FAT_TBL2B(l,h) FAT_U8(l), FAT_U8(((l >> 8) & 0xF) | ((h << 4) & 0xF0)), FAT_U8(h >> 4)
|
||||||
|
|
||||||
|
#define README_CONTENTS "This is tinyusb's MassStorage Class demo.\r\n\r\nIf you find any bugs or get any questions, feel free to file an\r\nissue at github.com/hathach/tinyusb"
|
||||||
|
|
||||||
|
static const uint32_t DISK_SECTOR_COUNT = 2 * 8; // 8KB is the smallest size that windows allow to mount
|
||||||
|
static const uint16_t DISK_SECTOR_SIZE = 512; // Should be 512
|
||||||
|
static const uint16_t DISC_SECTORS_PER_TABLE = 1; //each table sector can fit 170KB (340 sectors)
|
||||||
|
|
||||||
|
static uint8_t msc_disk[DISK_SECTOR_COUNT][DISK_SECTOR_SIZE] =
|
||||||
|
{
|
||||||
|
//------------- Block0: Boot Sector -------------//
|
||||||
|
{
|
||||||
|
// Header (62 bytes)
|
||||||
|
0xEB, 0x3C, 0x90, //jump_instruction
|
||||||
|
'M' , 'S' , 'D' , 'O' , 'S' , '5' , '.' , '0' , //oem_name
|
||||||
|
FAT_U16(DISK_SECTOR_SIZE), //bytes_per_sector
|
||||||
|
FAT_U8(1), //sectors_per_cluster
|
||||||
|
FAT_U16(1), //reserved_sectors_count
|
||||||
|
FAT_U8(1), //file_alloc_tables_num
|
||||||
|
FAT_U16(16), //max_root_dir_entries
|
||||||
|
FAT_U16(DISK_SECTOR_COUNT), //fat12_sector_num
|
||||||
|
0xF8, //media_descriptor
|
||||||
|
FAT_U16(DISC_SECTORS_PER_TABLE), //sectors_per_alloc_table;//FAT12 and FAT16
|
||||||
|
FAT_U16(1), //sectors_per_track;//A value of 0 may indicate LBA-only access
|
||||||
|
FAT_U16(1), //num_heads
|
||||||
|
FAT_U32(0), //hidden_sectors_count
|
||||||
|
FAT_U32(0), //total_sectors_32
|
||||||
|
0x00, //physical_drive_number;0x00 for (first) removable media, 0x80 for (first) fixed disk
|
||||||
|
0x00, //reserved
|
||||||
|
0x29, //extended_boot_signature;//should be 0x29
|
||||||
|
FAT_U32(0x1234), //serial_number: 0x1234 => 1234
|
||||||
|
'T' , 'i' , 'n' , 'y' , 'U' , 'S' , 'B' , ' ' , 'M' , 'S' , 'C' , //volume_label padded with spaces (0x20)
|
||||||
|
'F' , 'A' , 'T' , '1' , '2' , ' ' , ' ' , ' ' , //file_system_type padded with spaces (0x20)
|
||||||
|
|
||||||
|
// Zero up to 2 last bytes of FAT magic code (448 bytes)
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
|
||||||
|
//boot signature (2 bytes)
|
||||||
|
0x55, 0xAA
|
||||||
|
},
|
||||||
|
|
||||||
|
//------------- Block1: FAT12 Table -------------//
|
||||||
|
{
|
||||||
|
FAT_TBL2B(0xFF8, 0xFFF), FAT_TBL2B(0xFFF, 0x000) // first 2 entries must be 0xFF8 0xFFF, third entry is cluster end of readme file
|
||||||
|
},
|
||||||
|
|
||||||
|
//------------- Block2: Root Directory -------------//
|
||||||
|
{
|
||||||
|
// first entry is volume label
|
||||||
|
'E' , 'S' , 'P' , '3' , '2' , 'S' , '2' , ' ' ,
|
||||||
|
'M' , 'S' , 'C' ,
|
||||||
|
0x08, //FILE_ATTR_VOLUME_LABEL
|
||||||
|
0x00,
|
||||||
|
FAT_MS2B(0,0),
|
||||||
|
FAT_HMS2B(0,0,0),
|
||||||
|
FAT_YMD2B(0,0,0),
|
||||||
|
FAT_YMD2B(0,0,0),
|
||||||
|
FAT_U16(0),
|
||||||
|
FAT_HMS2B(13,42,30), //last_modified_hms
|
||||||
|
FAT_YMD2B(2018,11,5), //last_modified_ymd
|
||||||
|
FAT_U16(0),
|
||||||
|
FAT_U32(0),
|
||||||
|
|
||||||
|
// second entry is readme file
|
||||||
|
'R' , 'E' , 'A' , 'D' , 'M' , 'E' , ' ' , ' ' ,//file_name[8]; padded with spaces (0x20)
|
||||||
|
'T' , 'X' , 'T' , //file_extension[3]; padded with spaces (0x20)
|
||||||
|
0x20, //file attributes: FILE_ATTR_ARCHIVE
|
||||||
|
0x00, //ignore
|
||||||
|
FAT_MS2B(1,980), //creation_time_10_ms (max 199x10 = 1s 990ms)
|
||||||
|
FAT_HMS2B(13,42,36), //create_time_hms [5:6:5] => h:m:(s/2)
|
||||||
|
FAT_YMD2B(2018,11,5), //create_time_ymd [7:4:5] => (y+1980):m:d
|
||||||
|
FAT_YMD2B(2020,11,5), //last_access_ymd
|
||||||
|
FAT_U16(0), //extended_attributes
|
||||||
|
FAT_HMS2B(13,44,16), //last_modified_hms
|
||||||
|
FAT_YMD2B(2019,11,5), //last_modified_ymd
|
||||||
|
FAT_U16(2), //start of file in cluster
|
||||||
|
FAT_U32(sizeof(README_CONTENTS) - 1) //file size
|
||||||
|
},
|
||||||
|
|
||||||
|
//------------- Block3: Readme Content -------------//
|
||||||
|
README_CONTENTS
|
||||||
|
};
|
||||||
|
|
||||||
|
static int32_t onWrite(uint32_t lba, uint32_t offset, uint8_t* buffer, uint32_t bufsize){
|
||||||
|
HWSerial.printf("MSC WRITE: lba: %u, offset: %u, bufsize: %u\n", lba, offset, bufsize);
|
||||||
|
memcpy(msc_disk[lba] + offset, buffer, bufsize);
|
||||||
|
return bufsize;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int32_t onRead(uint32_t lba, uint32_t offset, void* buffer, uint32_t bufsize){
|
||||||
|
HWSerial.printf("MSC READ: lba: %u, offset: %u, bufsize: %u\n", lba, offset, bufsize);
|
||||||
|
memcpy(buffer, msc_disk[lba] + offset, bufsize);
|
||||||
|
return bufsize;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool onStartStop(uint8_t power_condition, bool start, bool load_eject){
|
||||||
|
HWSerial.printf("MSC START/STOP: power: %u, start: %u, eject: %u\n", power_condition, start, load_eject);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void usbEventCallback(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data){
|
||||||
|
if(event_base == ARDUINO_USB_EVENTS){
|
||||||
|
arduino_usb_event_data_t * data = (arduino_usb_event_data_t*)event_data;
|
||||||
|
switch (event_id){
|
||||||
|
case ARDUINO_USB_STARTED_EVENT:
|
||||||
|
HWSerial.println("USB PLUGGED");
|
||||||
|
break;
|
||||||
|
case ARDUINO_USB_STOPPED_EVENT:
|
||||||
|
HWSerial.println("USB UNPLUGGED");
|
||||||
|
break;
|
||||||
|
case ARDUINO_USB_SUSPEND_EVENT:
|
||||||
|
HWSerial.printf("USB SUSPENDED: remote_wakeup_en: %u\n", data->suspend.remote_wakeup_en);
|
||||||
|
break;
|
||||||
|
case ARDUINO_USB_RESUME_EVENT:
|
||||||
|
HWSerial.println("USB RESUMED");
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
HWSerial.begin(115200);
|
||||||
|
HWSerial.setDebugOutput(true);
|
||||||
|
|
||||||
|
USB.onEvent(usbEventCallback);
|
||||||
|
MSC.vendorID("ESP32");//max 8 chars
|
||||||
|
MSC.productID("USB_MSC");//max 16 chars
|
||||||
|
MSC.productRevision("1.0");//max 4 chars
|
||||||
|
MSC.onStartStop(onStartStop);
|
||||||
|
MSC.onRead(onRead);
|
||||||
|
MSC.onWrite(onWrite);
|
||||||
|
MSC.mediaPresent(true);
|
||||||
|
MSC.begin(DISK_SECTOR_COUNT, DISK_SECTOR_SIZE);
|
||||||
|
USBSerial.begin();
|
||||||
|
USB.begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
// put your main code here, to run repeatedly:
|
||||||
|
}
|
@ -1,6 +1,6 @@
|
|||||||
#include "USB.h"
|
#include "USB.h"
|
||||||
|
|
||||||
#if ARDUINO_SERIAL_PORT
|
#if ARDUINO_USB_CDC_ON_BOOT
|
||||||
#define HWSerial Serial0
|
#define HWSerial Serial0
|
||||||
#define USBSerial Serial
|
#define USBSerial Serial
|
||||||
#else
|
#else
|
||||||
@ -66,14 +66,8 @@ void setup() {
|
|||||||
USB.onEvent(usbEventCallback);
|
USB.onEvent(usbEventCallback);
|
||||||
USBSerial.onEvent(usbEventCallback);
|
USBSerial.onEvent(usbEventCallback);
|
||||||
|
|
||||||
#if !ARDUINO_SERIAL_PORT
|
|
||||||
USB.enableDFU();
|
|
||||||
USB.webUSB(true);
|
|
||||||
USB.webUSBURL("http://localhost/webusb");
|
|
||||||
USB.productName("ESP32S2-USB");
|
|
||||||
USB.begin();
|
|
||||||
USBSerial.begin();
|
USBSerial.begin();
|
||||||
#endif
|
USB.begin();
|
||||||
}
|
}
|
||||||
|
|
||||||
void loop() {
|
void loop() {
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
USB KEYWORD1
|
USB KEYWORD1
|
||||||
USBCDC KEYWORD1
|
USBCDC KEYWORD1
|
||||||
|
USBMSC KEYWORD1
|
||||||
|
|
||||||
#######################################
|
#######################################
|
||||||
# Methods and Functions (KEYWORD2)
|
# Methods and Functions (KEYWORD2)
|
||||||
@ -18,6 +19,14 @@ end KEYWORD2
|
|||||||
onEvent KEYWORD2
|
onEvent KEYWORD2
|
||||||
enableReset KEYWORD2
|
enableReset KEYWORD2
|
||||||
|
|
||||||
|
vendorID KEYWORD2
|
||||||
|
productID KEYWORD2
|
||||||
|
productRevision KEYWORD2
|
||||||
|
mediaPresent KEYWORD2
|
||||||
|
onStartStop KEYWORD2
|
||||||
|
onRead KEYWORD2
|
||||||
|
onWrite KEYWORD2
|
||||||
|
|
||||||
#######################################
|
#######################################
|
||||||
# Constants (LITERAL1)
|
# Constants (LITERAL1)
|
||||||
#######################################
|
#######################################
|
||||||
|
@ -0,0 +1,15 @@
|
|||||||
|
// Copyright 2015-2021 Espressif Systems (Shanghai) PTE LTD
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
#pragma once
|
@ -30,7 +30,7 @@ compiler.cpp.flags.esp32=-mlongcalls -Wno-frame-address -ffunction-sections -fda
|
|||||||
compiler.S.flags.esp32=-ffunction-sections -fdata-sections -Wno-error=unused-function -Wno-error=unused-variable -Wno-error=deprecated-declarations -Wno-unused-parameter -Wno-sign-compare -ggdb -O2 -Wwrite-strings -fstack-protector -fstrict-volatile-bitfields -Wno-error=unused-but-set-variable -fno-jump-tables -fno-tree-switch-conversion -x assembler-with-cpp -MMD -c
|
compiler.S.flags.esp32=-ffunction-sections -fdata-sections -Wno-error=unused-function -Wno-error=unused-variable -Wno-error=deprecated-declarations -Wno-unused-parameter -Wno-sign-compare -ggdb -O2 -Wwrite-strings -fstack-protector -fstrict-volatile-bitfields -Wno-error=unused-but-set-variable -fno-jump-tables -fno-tree-switch-conversion -x assembler-with-cpp -MMD -c
|
||||||
compiler.c.elf.flags.esp32=-T esp32.rom.redefined.ld -T memory.ld -T sections.ld -T esp32.rom.ld -T esp32.rom.api.ld -T esp32.rom.libgcc.ld -T esp32.rom.newlib-data.ld -T esp32.rom.syscalls.ld -T esp32.peripherals.ld -mlongcalls -Wno-frame-address -Wl,--cref -Wl,--gc-sections -fno-rtti -fno-lto -u _Z5setupv -u _Z4loopv -Wl,--wrap=mbedtls_mpi_exp_mod -u esp_app_desc -u pthread_include_pthread_impl -u pthread_include_pthread_cond_impl -u pthread_include_pthread_local_storage_impl -u ld_include_panic_highint_hdl -u start_app -u start_app_other_cores -u __ubsan_include -Wl,--wrap=longjmp -u __assert_func -u vfs_include_syscalls_impl -Wl,--undefined=uxTopUsedPriority -u app_main -u newlib_include_heap_impl -u newlib_include_syscalls_impl -u newlib_include_pthread_impl -u __cxa_guard_dummy
|
compiler.c.elf.flags.esp32=-T esp32.rom.redefined.ld -T memory.ld -T sections.ld -T esp32.rom.ld -T esp32.rom.api.ld -T esp32.rom.libgcc.ld -T esp32.rom.newlib-data.ld -T esp32.rom.syscalls.ld -T esp32.peripherals.ld -mlongcalls -Wno-frame-address -Wl,--cref -Wl,--gc-sections -fno-rtti -fno-lto -u _Z5setupv -u _Z4loopv -Wl,--wrap=mbedtls_mpi_exp_mod -u esp_app_desc -u pthread_include_pthread_impl -u pthread_include_pthread_cond_impl -u pthread_include_pthread_local_storage_impl -u ld_include_panic_highint_hdl -u start_app -u start_app_other_cores -u __ubsan_include -Wl,--wrap=longjmp -u __assert_func -u vfs_include_syscalls_impl -Wl,--undefined=uxTopUsedPriority -u app_main -u newlib_include_heap_impl -u newlib_include_syscalls_impl -u newlib_include_pthread_impl -u __cxa_guard_dummy
|
||||||
compiler.ar.flags.esp32=cr
|
compiler.ar.flags.esp32=cr
|
||||||
build.extra_flags.esp32=-DARDUINO_SERIAL_PORT=0
|
build.extra_flags.esp32=-DARDUINO_USB_CDC_ON_BOOT=0
|
||||||
#
|
#
|
||||||
# ESP32 Support End
|
# ESP32 Support End
|
||||||
#
|
#
|
||||||
@ -45,7 +45,7 @@ compiler.cpp.flags.esp32s2=-mlongcalls -ffunction-sections -fdata-sections -Wno-
|
|||||||
compiler.S.flags.esp32s2=-ffunction-sections -fdata-sections -Wno-error=unused-function -Wno-error=unused-variable -Wno-error=deprecated-declarations -Wno-unused-parameter -Wno-sign-compare -ggdb -O2 -Wwrite-strings -fstack-protector -fstrict-volatile-bitfields -Wno-error=unused-but-set-variable -fno-jump-tables -fno-tree-switch-conversion -x assembler-with-cpp -MMD -c
|
compiler.S.flags.esp32s2=-ffunction-sections -fdata-sections -Wno-error=unused-function -Wno-error=unused-variable -Wno-error=deprecated-declarations -Wno-unused-parameter -Wno-sign-compare -ggdb -O2 -Wwrite-strings -fstack-protector -fstrict-volatile-bitfields -Wno-error=unused-but-set-variable -fno-jump-tables -fno-tree-switch-conversion -x assembler-with-cpp -MMD -c
|
||||||
compiler.c.elf.flags.esp32s2=-T memory.ld -T sections.ld -T esp32s2.rom.ld -T esp32s2.rom.api.ld -T esp32s2.rom.libgcc.ld -T esp32s2.rom.newlib-funcs.ld -T esp32s2.rom.newlib-data.ld -T esp32s2.rom.spiflash.ld -T esp32s2.peripherals.ld -mlongcalls -Wl,--cref -Wl,--gc-sections -fno-rtti -fno-lto -u _Z5setupv -u _Z4loopv -u esp_app_desc -u pthread_include_pthread_impl -u pthread_include_pthread_cond_impl -u pthread_include_pthread_local_storage_impl -u ld_include_panic_highint_hdl -u start_app -u __ubsan_include -Wl,--wrap=longjmp -u __assert_func -u vfs_include_syscalls_impl -Wl,--undefined=uxTopUsedPriority -u app_main -u newlib_include_heap_impl -u newlib_include_syscalls_impl -u newlib_include_pthread_impl -u __cxa_guard_dummy
|
compiler.c.elf.flags.esp32s2=-T memory.ld -T sections.ld -T esp32s2.rom.ld -T esp32s2.rom.api.ld -T esp32s2.rom.libgcc.ld -T esp32s2.rom.newlib-funcs.ld -T esp32s2.rom.newlib-data.ld -T esp32s2.rom.spiflash.ld -T esp32s2.peripherals.ld -mlongcalls -Wl,--cref -Wl,--gc-sections -fno-rtti -fno-lto -u _Z5setupv -u _Z4loopv -u esp_app_desc -u pthread_include_pthread_impl -u pthread_include_pthread_cond_impl -u pthread_include_pthread_local_storage_impl -u ld_include_panic_highint_hdl -u start_app -u __ubsan_include -Wl,--wrap=longjmp -u __assert_func -u vfs_include_syscalls_impl -Wl,--undefined=uxTopUsedPriority -u app_main -u newlib_include_heap_impl -u newlib_include_syscalls_impl -u newlib_include_pthread_impl -u __cxa_guard_dummy
|
||||||
compiler.ar.flags.esp32s2=cr
|
compiler.ar.flags.esp32s2=cr
|
||||||
build.extra_flags.esp32s2=-DARDUINO_SERIAL_PORT={build.serial}
|
build.extra_flags.esp32s2=-DARDUINO_USB_CDC_ON_BOOT={build.cdc_on_boot} -DARDUINO_USB_MSC_ON_BOOT={build.msc_on_boot} -DARDUINO_USB_DFU_ON_BOOT={build.dfu_on_boot}
|
||||||
#
|
#
|
||||||
# ESP32S2 Support End
|
# ESP32S2 Support End
|
||||||
#
|
#
|
||||||
@ -60,7 +60,7 @@ compiler.cpp.flags.esp32c3=-march=rv32imc -ffunction-sections -fdata-sections -W
|
|||||||
compiler.S.flags.esp32c3=-ffunction-sections -fdata-sections -Wno-error=unused-function -Wno-error=unused-variable -Wno-error=deprecated-declarations -Wno-unused-parameter -Wno-sign-compare -ggdb -Wno-error=format= -nostartfiles -Wno-format -Og -fstrict-volatile-bitfields -Wno-error=unused-but-set-variable -fno-jump-tables -fno-tree-switch-conversion -x assembler-with-cpp -MMD -c
|
compiler.S.flags.esp32c3=-ffunction-sections -fdata-sections -Wno-error=unused-function -Wno-error=unused-variable -Wno-error=deprecated-declarations -Wno-unused-parameter -Wno-sign-compare -ggdb -Wno-error=format= -nostartfiles -Wno-format -Og -fstrict-volatile-bitfields -Wno-error=unused-but-set-variable -fno-jump-tables -fno-tree-switch-conversion -x assembler-with-cpp -MMD -c
|
||||||
compiler.c.elf.flags.esp32c3=-T memory.ld -T sections.ld -T esp32c3.rom.ld -T esp32c3.rom.api.ld -T esp32c3.rom.libgcc.ld -T esp32c3.rom.newlib.ld -T esp32c3.rom.version.ld -T esp32c3.peripherals.ld -nostartfiles -march=rv32imc --specs=nosys.specs -Wl,--cref -Wl,--gc-sections -fno-rtti -fno-lto -u _Z5setupv -u _Z4loopv -Wl,--wrap=mbedtls_mpi_exp_mod -u esp_app_desc -u pthread_include_pthread_impl -u pthread_include_pthread_cond_impl -u pthread_include_pthread_local_storage_impl -u start_app -u __ubsan_include -u __assert_func -u vfs_include_syscalls_impl -Wl,--undefined=uxTopUsedPriority -u app_main -u newlib_include_heap_impl -u newlib_include_syscalls_impl -u newlib_include_pthread_impl -Wl,--wrap=_Unwind_SetEnableExceptionFdeSorting -Wl,--wrap=__register_frame_info_bases -Wl,--wrap=__register_frame_info -Wl,--wrap=__register_frame -Wl,--wrap=__register_frame_info_table_bases -Wl,--wrap=__register_frame_info_table -Wl,--wrap=__register_frame_table -Wl,--wrap=__deregister_frame_info_bases -Wl,--wrap=__deregister_frame_info -Wl,--wrap=_Unwind_Find_FDE -Wl,--wrap=_Unwind_GetGR -Wl,--wrap=_Unwind_GetCFA -Wl,--wrap=_Unwind_GetIP -Wl,--wrap=_Unwind_GetIPInfo -Wl,--wrap=_Unwind_GetRegionStart -Wl,--wrap=_Unwind_GetDataRelBase -Wl,--wrap=_Unwind_GetTextRelBase -Wl,--wrap=_Unwind_SetIP -Wl,--wrap=_Unwind_SetGR -Wl,--wrap=_Unwind_GetLanguageSpecificData -Wl,--wrap=_Unwind_FindEnclosingFunction -Wl,--wrap=_Unwind_Resume -Wl,--wrap=_Unwind_RaiseException -Wl,--wrap=_Unwind_DeleteException -Wl,--wrap=_Unwind_ForcedUnwind -Wl,--wrap=_Unwind_Resume_or_Rethrow -Wl,--wrap=_Unwind_Backtrace -Wl,--wrap=__cxa_call_unexpected -Wl,--wrap=__gxx_personality_v0 -u __cxa_guard_dummy -u __cxx_fatal_exception
|
compiler.c.elf.flags.esp32c3=-T memory.ld -T sections.ld -T esp32c3.rom.ld -T esp32c3.rom.api.ld -T esp32c3.rom.libgcc.ld -T esp32c3.rom.newlib.ld -T esp32c3.rom.version.ld -T esp32c3.peripherals.ld -nostartfiles -march=rv32imc --specs=nosys.specs -Wl,--cref -Wl,--gc-sections -fno-rtti -fno-lto -u _Z5setupv -u _Z4loopv -Wl,--wrap=mbedtls_mpi_exp_mod -u esp_app_desc -u pthread_include_pthread_impl -u pthread_include_pthread_cond_impl -u pthread_include_pthread_local_storage_impl -u start_app -u __ubsan_include -u __assert_func -u vfs_include_syscalls_impl -Wl,--undefined=uxTopUsedPriority -u app_main -u newlib_include_heap_impl -u newlib_include_syscalls_impl -u newlib_include_pthread_impl -Wl,--wrap=_Unwind_SetEnableExceptionFdeSorting -Wl,--wrap=__register_frame_info_bases -Wl,--wrap=__register_frame_info -Wl,--wrap=__register_frame -Wl,--wrap=__register_frame_info_table_bases -Wl,--wrap=__register_frame_info_table -Wl,--wrap=__register_frame_table -Wl,--wrap=__deregister_frame_info_bases -Wl,--wrap=__deregister_frame_info -Wl,--wrap=_Unwind_Find_FDE -Wl,--wrap=_Unwind_GetGR -Wl,--wrap=_Unwind_GetCFA -Wl,--wrap=_Unwind_GetIP -Wl,--wrap=_Unwind_GetIPInfo -Wl,--wrap=_Unwind_GetRegionStart -Wl,--wrap=_Unwind_GetDataRelBase -Wl,--wrap=_Unwind_GetTextRelBase -Wl,--wrap=_Unwind_SetIP -Wl,--wrap=_Unwind_SetGR -Wl,--wrap=_Unwind_GetLanguageSpecificData -Wl,--wrap=_Unwind_FindEnclosingFunction -Wl,--wrap=_Unwind_Resume -Wl,--wrap=_Unwind_RaiseException -Wl,--wrap=_Unwind_DeleteException -Wl,--wrap=_Unwind_ForcedUnwind -Wl,--wrap=_Unwind_Resume_or_Rethrow -Wl,--wrap=_Unwind_Backtrace -Wl,--wrap=__cxa_call_unexpected -Wl,--wrap=__gxx_personality_v0 -u __cxa_guard_dummy -u __cxx_fatal_exception
|
||||||
compiler.ar.flags.esp32c3=cr
|
compiler.ar.flags.esp32c3=cr
|
||||||
build.extra_flags.esp32c3=-DARDUINO_SERIAL_PORT=0
|
build.extra_flags.esp32c3=-DARDUINO_USB_CDC_ON_BOOT=0
|
||||||
#
|
#
|
||||||
# ESP32C3 Support End
|
# ESP32C3 Support End
|
||||||
#
|
#
|
||||||
|
81
variants/esp32s2usb/pins_arduino.h
Normal file
81
variants/esp32s2usb/pins_arduino.h
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
#ifndef Pins_Arduino_h
|
||||||
|
#define Pins_Arduino_h
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
// Default USB Settings
|
||||||
|
#define USB_VID 0x303A
|
||||||
|
#define USB_PID 0x0003
|
||||||
|
#define USB_MANUFACTURER "Espressif Systems"
|
||||||
|
#define USB_PRODUCT "ESP32-S2-USB"
|
||||||
|
#define USB_SERIAL "0"
|
||||||
|
#define USB_WEBUSB_ENABLED false
|
||||||
|
#define USB_WEBUSB_URL "https://espressif.github.io/arduino-esp32/webusb.html"
|
||||||
|
|
||||||
|
// Default USB FirmwareMSC Settings
|
||||||
|
#define USB_FW_MSC_VENDOR_ID "ESP32-S2" //max 8 chars
|
||||||
|
#define USB_FW_MSC_PRODUCT_ID "Firmware MSC" //max 16 chars
|
||||||
|
#define USB_FW_MSC_PRODUCT_REVISION "1.23" //max 4 chars
|
||||||
|
#define USB_FW_MSC_VOLUME_NAME "S2-Firmware" //max 11 chars
|
||||||
|
#define USB_FW_MSC_SERIAL_NUMBER 0x00000000
|
||||||
|
|
||||||
|
|
||||||
|
#define EXTERNAL_NUM_INTERRUPTS 46
|
||||||
|
#define NUM_DIGITAL_PINS 48
|
||||||
|
#define NUM_ANALOG_INPUTS 20
|
||||||
|
|
||||||
|
#define analogInputToDigitalPin(p) (((p)<20)?(esp32_adc2gpio[(p)]):-1)
|
||||||
|
#define digitalPinToInterrupt(p) (((p)<48)?(p):-1)
|
||||||
|
#define digitalPinHasPWM(p) (p < 46)
|
||||||
|
|
||||||
|
static const uint8_t TX = 43;
|
||||||
|
static const uint8_t RX = 44;
|
||||||
|
|
||||||
|
static const uint8_t SDA = 8;
|
||||||
|
static const uint8_t SCL = 9;
|
||||||
|
|
||||||
|
static const uint8_t SS = 34;
|
||||||
|
static const uint8_t MOSI = 35;
|
||||||
|
static const uint8_t MISO = 37;
|
||||||
|
static const uint8_t SCK = 36;
|
||||||
|
|
||||||
|
static const uint8_t A0 = 1;
|
||||||
|
static const uint8_t A1 = 2;
|
||||||
|
static const uint8_t A2 = 3;
|
||||||
|
static const uint8_t A3 = 4;
|
||||||
|
static const uint8_t A4 = 5;
|
||||||
|
static const uint8_t A5 = 6;
|
||||||
|
static const uint8_t A6 = 7;
|
||||||
|
static const uint8_t A7 = 8;
|
||||||
|
static const uint8_t A8 = 9;
|
||||||
|
static const uint8_t A9 = 10;
|
||||||
|
static const uint8_t A10 = 11;
|
||||||
|
static const uint8_t A11 = 12;
|
||||||
|
static const uint8_t A12 = 13;
|
||||||
|
static const uint8_t A13 = 14;
|
||||||
|
static const uint8_t A14 = 15;
|
||||||
|
static const uint8_t A15 = 16;
|
||||||
|
static const uint8_t A16 = 17;
|
||||||
|
static const uint8_t A17 = 18;
|
||||||
|
static const uint8_t A18 = 19;
|
||||||
|
static const uint8_t A19 = 20;
|
||||||
|
|
||||||
|
static const uint8_t T1 = 1;
|
||||||
|
static const uint8_t T2 = 2;
|
||||||
|
static const uint8_t T3 = 3;
|
||||||
|
static const uint8_t T4 = 4;
|
||||||
|
static const uint8_t T5 = 5;
|
||||||
|
static const uint8_t T6 = 6;
|
||||||
|
static const uint8_t T7 = 7;
|
||||||
|
static const uint8_t T8 = 8;
|
||||||
|
static const uint8_t T9 = 9;
|
||||||
|
static const uint8_t T10 = 10;
|
||||||
|
static const uint8_t T11 = 11;
|
||||||
|
static const uint8_t T12 = 12;
|
||||||
|
static const uint8_t T13 = 13;
|
||||||
|
static const uint8_t T14 = 14;
|
||||||
|
|
||||||
|
static const uint8_t DAC1 = 17;
|
||||||
|
static const uint8_t DAC2 = 18;
|
||||||
|
|
||||||
|
#endif /* Pins_Arduino_h */
|
Loading…
Reference in New Issue
Block a user