mirror of
https://github.com/hathach/tinyusb.git
synced 2026-02-07 16:35:33 +00:00
Merge remote-tracking branch 'tinyusb/master' into dwc2_ep0
This commit is contained in:
@ -67,3 +67,12 @@ Before building, it's recommended to run pre-commit to ensure code quality:
|
||||
- hw/: Board support packages and MCU drivers
|
||||
- examples/: Reference examples for device/host/dual
|
||||
- test/: Unit tests and hardware integration tests
|
||||
|
||||
## Release Process
|
||||
To prepare a new release:
|
||||
1. Update the `version` variable in `tools/make_release.py` to the new version number
|
||||
2. Run the release script: `python tools/make_release.py`
|
||||
- This will update version numbers in `src/tusb_option.h`, `repository.yml`, and `library.json`
|
||||
- It will also regenerate documentation
|
||||
3. Update `docs/info/changelog.rst` with release notes
|
||||
4. Commit changes and create release tag
|
||||
|
||||
@ -122,7 +122,7 @@ Supported CPUs
|
||||
+--------------+-----------------------------+--------+------+-----------+------------------------+-------------------+
|
||||
| Dialog | DA1469x | ✔ | ✖ | ✖ | da146xx | |
|
||||
+--------------+-----------------------------+--------+------+-----------+------------------------+-------------------+
|
||||
| Espressif | S2, S3 | ✔ | ✔ | ✖ | dwc2 or esp32sx | |
|
||||
| Espressif | S2, S3 | ✔ | ✔ | ✖ | dwc2 | |
|
||||
| ESP32 +-----------------------------+--------+------+-----------+------------------------+-------------------+
|
||||
| | P4 | ✔ | ✔ | ✔ | dwc2 | |
|
||||
| +-----------------------------+--------+------+-----------+------------------------+-------------------+
|
||||
|
||||
@ -2,6 +2,198 @@
|
||||
Changelog
|
||||
*********
|
||||
|
||||
0.19.0
|
||||
======
|
||||
|
||||
General
|
||||
-------
|
||||
|
||||
- New MCUs and Boards:
|
||||
|
||||
- Add ESP32-H4, ESP32-C5, ESP32-C61 support
|
||||
- Add STM32U0, STM32WBA, STM32N6
|
||||
- Add AT32F405, AT32F403A, AT32F415, AT32F423 support
|
||||
- Add CH32V305 support and CH32V20x USB host support
|
||||
- Add MCXA156 SDK 2.16 support and FRDM-MCXA156 board
|
||||
|
||||
API Changes
|
||||
-----------
|
||||
|
||||
- Core APIs
|
||||
- Add weak callbacks with new syntax for better compiler compatibility
|
||||
- Add ``tusb_deinit()`` to cleanup stack
|
||||
- Add time functions: ``tusb_time_millis_api()`` and ``tusb_time_delay_ms_api()``
|
||||
- Add ``osal_critical`` APIs for critical section handling
|
||||
- Introduce ``xfer_isr()`` callback for ISO transfer optimization in device classes
|
||||
|
||||
- Device APIs
|
||||
- CDC: Add notification support ``tud_cdc_configure()``, ``tud_cdc_n_notify_uart_state()``,
|
||||
``tud_cdc_n_notify_conn_speed_change()``, ``tud_cdc_notify_complete_cb()``
|
||||
- MSC: Add ``tud_msc_inquiry2_cb()`` with bufsize parameter, update ``tud_msc_async_io_done()``
|
||||
with ``in_isr`` parameter
|
||||
- Audio: Add ``tud_audio_n_mounted()`` and various FIFO access functions
|
||||
- MTP: Add ``tud_mtp_mounted()``, ``tud_mtp_data_send()``, ``tud_mtp_data_receive()``,
|
||||
``tud_mtp_response_send()``, ``tud_mtp_event_send()``
|
||||
|
||||
- Host APIs
|
||||
- Core: Add ``tuh_edpt_close()``, ``tuh_address_set()``, ``tuh_descriptor_get_device_local()``,
|
||||
``tuh_descriptor_get_string_langid()``, ``tuh_connected()``, ``tuh_bus_info_get()``
|
||||
- Add enumeration callbacks: ``tuh_enum_descriptor_device_cb()``,
|
||||
``tuh_enum_descriptor_configuration_cb()``
|
||||
- CDC: Add ``tuh_cdc_get_control_line_state_local()``, ``tuh_cdc_get/set_dtr/rts()``,
|
||||
``tuh_cdc_connect/disconnect()`` and sync versions of all control APIs
|
||||
- MIDI: Add ``tuh_midi_itf_get_info()``, ``tuh_midi_packet_read_n()``,
|
||||
``tuh_midi_packet_write_n()``, ``tuh_midi_read_available()``, ``tuh_midi_write_flush()``,
|
||||
``tuh_midi_descriptor_cb()``
|
||||
|
||||
Controller Driver (DCD & HCD)
|
||||
-----------------------------
|
||||
|
||||
- DWC2
|
||||
- Support DWC2 v4.30a with improved reset procedure
|
||||
- Fix core reset: wait for AHB idle before reset
|
||||
- Add STM32 DWC2 data cache support with proper alignment
|
||||
- Host improvements:
|
||||
- Fix disconnect detection and SOF flag handling
|
||||
- Fix HFIR timing off-by-one error
|
||||
- Retry IN token immediately for bInterval=1
|
||||
- Proper attach debouncing (200ms)
|
||||
- Fix all retry intervals
|
||||
- Resume OUT transfer when PING ACKed
|
||||
- Fix enumeration racing conditions
|
||||
- Refactor bitfields for better code generation
|
||||
|
||||
- FSDEV (STM32)
|
||||
- Fix AT32 compile issues after single-buffered endpoint changes
|
||||
- Add configurable single-buffered isochronous endpoints
|
||||
- Fix STM32H7 recurrent suspend ISR
|
||||
- Fix STM32L4 GPIOD clock enable for variants without GPIOD
|
||||
- Fix STM32 PHYC PLL stability wait
|
||||
- Improve PMA size handling for STM32U0
|
||||
|
||||
- EHCI
|
||||
- Fix removed QHD getting reused
|
||||
- Fix NXP USBPHY disconnection detection
|
||||
|
||||
- Chipidea/NXP
|
||||
- Fix race condition with spinlock
|
||||
- Improve iMXRT support: fix build, disable BOARD_ConfigMPU, fix attach debouncing on port1 highspeed
|
||||
- Fix iMXRT1064 and add to HIL test pool
|
||||
|
||||
- MAX3421E
|
||||
- Use spinlock for thread safety instead of atomic flag
|
||||
- Implement ``hcd_edpt_close()``
|
||||
|
||||
- RP2040
|
||||
- Fix audio ISO transfer: reset state before notifying stack
|
||||
- Fix CMake RTOS cache variable
|
||||
- Abort transfer if active in ``iso_activate()``
|
||||
|
||||
- SAMD
|
||||
- Add host controller driver support
|
||||
|
||||
Device Stack
|
||||
------------
|
||||
|
||||
- USBD Core
|
||||
- Introduce ``xfer_isr()`` callback for interrupt-time transfer handling
|
||||
- Add ``usbd_edpt_xfer_fifo()`` stub
|
||||
- Revert endpoint busy/claim status if ``xfer_isr()`` defers to ``xfer_cb()``
|
||||
|
||||
- Audio
|
||||
- Major simplification of UAC driver and alt settings management
|
||||
- Move ISO transfers into ``xfer_isr()`` for better performance
|
||||
- Remove FIFO mutex (single producer/consumer optimization)
|
||||
- Add implicit feedback support for data IN endpoints
|
||||
- Fix alignment issues
|
||||
- Update buffer macros with cache line size alignment
|
||||
|
||||
- CDC
|
||||
- Add notification support: ``CFG_TUD_CDC_NOTIFY``, ``tud_cdc_n_notify_conn_speed_change()``, ``tud_cdc_notify_complete_cb()``
|
||||
- Reduce default bInterval from 16ms to 1ms for better responsiveness
|
||||
- Rename ``tud_cdc_configure_fifo()`` to ``tud_cdc_configure()`` and add ``tx_overwritable_if_not_connected`` option
|
||||
- Fix web serial robustness with major overhaul and logic cleanup
|
||||
|
||||
- HID
|
||||
- Add Usage Page and Table for Power Devices (0x84 - 0x85)
|
||||
- Fix HID descriptor parser variable size and 4-byte item handling
|
||||
- Add consumer page configurations
|
||||
|
||||
- MIDI
|
||||
- Fix MIDI interface descriptor handling after audio streaming interface
|
||||
- Skip RX data with all zeroes
|
||||
|
||||
- MSC
|
||||
- Add async I/O support for MSC using ``tud_msc_async_io_done()``
|
||||
- Add ``tud_msc_inquiry2_cb()`` with bufsize for full inquiry response
|
||||
|
||||
- MTP
|
||||
- Add new Media Transfer Protocol (MTP) device class driver
|
||||
- Support MTP operations: GetDeviceInfo, SendObjectInfo, SendObject
|
||||
- Add MTP event support with ``tud_mtp_event_send()``
|
||||
- Implement filesystem example with callbacks
|
||||
- Add hardware-in-the-loop testing support
|
||||
|
||||
- NCM
|
||||
- Add USB NCM link state control support
|
||||
- Fix DHCP offer/ACK destination
|
||||
|
||||
- USBTMC
|
||||
- Add vendor-specific message support
|
||||
|
||||
- Vendor
|
||||
- Fix vendor device reset and open issues
|
||||
- Fix descriptor parsing for ``CFG_TUD_VENDOR > 1``
|
||||
- Fix vendor FIFO argument calculation
|
||||
|
||||
Host Stack
|
||||
----------
|
||||
|
||||
- USBH Core
|
||||
- Major enumeration improvements:
|
||||
- Fix enumeration racing conditions
|
||||
- Add proper attach debouncing with hub/rootport handling (200ms delay)
|
||||
- Reduce ``ENUM_DEBOUNCING_DELAY_MS`` to 200ms
|
||||
- Always get language ID, manufacturer, product, and serial strings during enumeration
|
||||
- Always get first 2 bytes of string descriptor to determine length (prevents buffer overflow)
|
||||
- Support devices with multiple configurations
|
||||
- Add ``tuh_enum_descriptor_device_cb()`` and ``tuh_enum_descriptor_configuration_cb()`` callbacks
|
||||
- Add ``tuh_descriptor_get_string_langid()`` API
|
||||
- Hub improvements:
|
||||
- Check status before getting first device descriptor
|
||||
- Properly handle port status and change detection
|
||||
- Queue status endpoint for detach/remove events
|
||||
- Fix hub status change endpoint handling
|
||||
- Fix endpoint management:
|
||||
- ``hcd_edpt_open()`` returns false if endpoint already opened
|
||||
- Add ``hcd_edpt_close()`` implementation
|
||||
- Abort pending transfers on close
|
||||
- Add roothub debouncing flag to ignore attach/remove during debouncing
|
||||
- Move address setting and bus info management to separate structures
|
||||
- Force removed devices in same bus info before setting address
|
||||
|
||||
- CDC Serial Host
|
||||
- Major refactor to generalize CDC serial drivers (FTDI, CP210x, CH34x, PL2303, ACM)
|
||||
- Add explicit ``sync()`` API with ``TU_API_SYNC()`` returning ``tusb_xfer_result_t``
|
||||
- Rename ``tuh_cdc_get_local_line_coding()`` to ``tuh_cdc_get_line_coding_local()``
|
||||
- Add ``tuh_cdc_get_control_line_state_local()``
|
||||
- Implement ``tuh_cdc_get/set_dtr/rts()`` as inline functions
|
||||
|
||||
- MIDI Host
|
||||
- Major API changes:
|
||||
- Rename ``tuh_midi_stream_flush()`` to ``tuh_midi_write_flush()``
|
||||
- Add ``tuh_midi_packet_read_n()`` and ``tuh_midi_packet_write_n()``
|
||||
- Add ``CFG_TUH_MIDI_STREAM_API`` to opt out of stream API
|
||||
- Change API to use index instead of device address (supports multiple MIDI per device)
|
||||
- Rename ``tuh_midi_get_num_rx/tx_cables()`` to ``tuh_midi_get_rx/tx_cable_count()``
|
||||
- Add ``tuh_midi_descriptor_cb()`` and ``tuh_midi_itf_get_info()``
|
||||
|
||||
- MSC Host
|
||||
- Continue async I/O improvements
|
||||
|
||||
- HID Host
|
||||
- Fix version string to actually show version
|
||||
|
||||
0.18.0
|
||||
======
|
||||
|
||||
|
||||
@ -4,9 +4,9 @@ Dependencies
|
||||
|
||||
MCU low-level peripheral driver and external libraries for building TinyUSB examples
|
||||
|
||||
======================================== ================================================================ ======================================== ======================================================================================================================================================================================================================================================================================================================================================
|
||||
======================================== ================================================================ ======================================== ======================================================================================================================================================================================================================================================================================================================================================================
|
||||
Local Path Repo Commit Required by
|
||||
======================================== ================================================================ ======================================== ======================================================================================================================================================================================================================================================================================================================================================
|
||||
======================================== ================================================================ ======================================== ======================================================================================================================================================================================================================================================================================================================================================================
|
||||
hw/mcu/allwinner https://github.com/hathach/allwinner_driver.git 8e5e89e8e132c0fd90e72d5422e5d3d68232b756 fc100s
|
||||
hw/mcu/analog/msdk https://github.com/analogdevicesinc/msdk.git b20b398d3e5e2007594e54a74ba3d2a2e50ddd75 maxim
|
||||
hw/mcu/artery/at32f402_405 https://github.com/ArteryTek/AT32F402_405_Firmware_Library.git 4424515c2663e82438654e0947695295df2abdfe at32f402_405
|
||||
@ -31,6 +31,7 @@ hw/mcu/renesas/fsp https://github.com/renesas/fsp.git
|
||||
hw/mcu/renesas/rx https://github.com/kkitayam/rx_device.git 706b4e0cf485605c32351e2f90f5698267996023 rx
|
||||
hw/mcu/silabs/cmsis-dfp-efm32gg12b https://github.com/cmsis-packs/cmsis-dfp-efm32gg12b.git f1c31b7887669cb230b3ea63f9b56769078960bc efm32
|
||||
hw/mcu/sony/cxd56/spresense-exported-sdk https://github.com/sonydevworld/spresense-exported-sdk.git 2ec2a1538362696118dc3fdf56f33dacaf8f4067 spresense
|
||||
hw/mcu/st/cmsis-device-u0 https://github.com/STMicroelectronics/cmsis-device-u0.git e3a627c6a5bc4eb2388e1885a95cc155e1672253 stm32u0
|
||||
hw/mcu/st/cmsis-device-wba https://github.com/STMicroelectronics/cmsis-device-wba.git 647d8522e5fd15049e9a1cc30ed19d85e5911eaf stm32wba
|
||||
hw/mcu/st/cmsis_device_c0 https://github.com/STMicroelectronics/cmsis_device_c0.git 517611273f835ffe95318947647bc1408f69120d stm32c0
|
||||
hw/mcu/st/cmsis_device_f0 https://github.com/STMicroelectronics/cmsis_device_f0.git cbb5da5d48b4b5f2efacdc2f033be30f9d29889f stm32f0
|
||||
@ -70,6 +71,7 @@ hw/mcu/st/stm32l1xx_hal_driver https://github.com/STMicroelectronics/
|
||||
hw/mcu/st/stm32l4xx_hal_driver https://github.com/STMicroelectronics/stm32l4xx_hal_driver.git 3e039bbf62f54bbd834d578185521cff80596efe stm32l4
|
||||
hw/mcu/st/stm32l5xx_hal_driver https://github.com/STMicroelectronics/stm32l5xx_hal_driver.git 3340b9a597bcf75cc173345a90a74aa2a4a37510 stm32l5
|
||||
hw/mcu/st/stm32n6xx_hal_driver https://github.com/STMicroelectronics/stm32n6xx-hal-driver.git bc6c41f8f67d61b47af26695d0bf67762a000666 stm32n6
|
||||
hw/mcu/st/stm32u0xx_hal_driver https://github.com/STMicroelectronics/stm32u0xx-hal-driver.git cbfb5ac654256445237fd32b3587ac6a238d24f1 stm32u0
|
||||
hw/mcu/st/stm32u5xx_hal_driver https://github.com/STMicroelectronics/stm32u5xx_hal_driver.git 2c5e2568fbdb1900a13ca3b2901fdd302cac3444 stm32u5
|
||||
hw/mcu/st/stm32wbaxx_hal_driver https://github.com/STMicroelectronics/stm32wbaxx_hal_driver.git 9442fbb71f855ff2e64fbf662b7726beba511a24 stm32wba
|
||||
hw/mcu/st/stm32wbxx_hal_driver https://github.com/STMicroelectronics/stm32wbxx_hal_driver.git d60dd46996876506f1d2e9abd6b1cc110c8004cd stm32wb
|
||||
@ -78,10 +80,10 @@ hw/mcu/wch/ch32f20x https://github.com/openwch/ch32f20x.gi
|
||||
hw/mcu/wch/ch32v103 https://github.com/openwch/ch32v103.git 7578cae0b21f86dd053a1f781b2fc6ab99d0ec17 ch32v10x
|
||||
hw/mcu/wch/ch32v20x https://github.com/openwch/ch32v20x.git c4c38f507e258a4e69b059ccc2dc27dde33cea1b ch32v20x
|
||||
hw/mcu/wch/ch32v307 https://github.com/openwch/ch32v307.git 184f21b852cb95eed58e86e901837bc9fff68775 ch32v30x
|
||||
lib/CMSIS_5 https://github.com/ARM-software/CMSIS_5.git 2b7495b8535bdcb306dac29b9ded4cfb679d7e5c imxrt kinetis_k32l2 kinetis_kl lpc51 lpc54 lpc55 mcx mm32 msp432e4 nrf saml2x lpc11 lpc13 lpc15 lpc17 lpc18 lpc40 lpc43 stm32c0 stm32f0 stm32f1 stm32f2 stm32f3 stm32f4 stm32f7 stm32g0 stm32g4 stm32h5 stm32h7 stm32h7rs stm32l0 stm32l1 stm32l4 stm32l5 stm32n6 stm32u5 stm32wb sam3x samd11 samd21 samd51 samd5x_e5x same5x same7x saml2x samg tm4c
|
||||
lib/CMSIS_5 https://github.com/ARM-software/CMSIS_5.git 2b7495b8535bdcb306dac29b9ded4cfb679d7e5c imxrt kinetis_k32l2 kinetis_kl lpc51 lpc54 lpc55 mcx mm32 msp432e4 nrf saml2x lpc11 lpc13 lpc15 lpc17 lpc18 lpc40 lpc43 stm32c0 stm32f0 stm32f1 stm32f2 stm32f3 stm32f4 stm32f7 stm32g0 stm32g4 stm32h5 stm32h7 stm32h7rs stm32l0 stm32l1 stm32l4 stm32l5 stm32n6 stm32u0 stm32u5 stm32wb stm32wbasam3x samd11 samd21 samd51 samd5x_e5x same5x same7x saml2x samg tm4c
|
||||
lib/CMSIS_6 https://github.com/ARM-software/CMSIS_6.git b0bbb0423b278ca632cfe1474eb227961d835fd2 ra
|
||||
lib/FreeRTOS-Kernel https://github.com/FreeRTOS/FreeRTOS-Kernel.git cc0e0707c0c748713485b870bb980852b210877f all
|
||||
lib/lwip https://github.com/lwip-tcpip/lwip.git 159e31b689577dbf69cf0683bbaffbd71fa5ee10 all
|
||||
lib/sct_neopixel https://github.com/gsteiert/sct_neopixel.git e73e04ca63495672d955f9268e003cffe168fcd8 lpc55
|
||||
tools/uf2 https://github.com/microsoft/uf2.git c594542b2faa01cc33a2b97c9fbebc38549df80a all
|
||||
======================================== ================================================================ ======================================== ======================================================================================================================================================================================================================================================================================================================================================
|
||||
======================================== ================================================================ ======================================== ======================================================================================================================================================================================================================================================================================================================================================================
|
||||
|
||||
@ -195,43 +195,32 @@ static void send_hid_report(uint8_t report_id, uint32_t btn)
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case REPORT_ID_STYLUS_PEN: {
|
||||
static bool touch_state = false;
|
||||
hid_stylus_report_t report = {
|
||||
.attr = 0,
|
||||
.x = 0,
|
||||
.y = 0
|
||||
};
|
||||
|
||||
if (btn) {
|
||||
report.attr = STYLUS_ATTR_TIP_SWITCH | STYLUS_ATTR_IN_RANGE;
|
||||
report.x = 100;
|
||||
report.y = 100;
|
||||
tud_hid_report(REPORT_ID_STYLUS_PEN, &report, sizeof(report));
|
||||
touch_state = true;
|
||||
} else {
|
||||
report.attr = 0;
|
||||
if (touch_state) tud_hid_report(REPORT_ID_STYLUS_PEN, &report, sizeof(report));
|
||||
touch_state = false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
/* use this to send stylus touch signal through USB. */
|
||||
static void send_stylus_touch(uint16_t x, uint16_t y, bool state)
|
||||
{
|
||||
// skip if hid is not ready yet
|
||||
if ( !tud_hid_ready() ) return;
|
||||
|
||||
static bool has_stylus_pen = false;
|
||||
|
||||
hid_stylus_report_t report =
|
||||
{
|
||||
.attr = 0,
|
||||
.x = 0,
|
||||
.y = 0
|
||||
};
|
||||
|
||||
report.x = x;
|
||||
report.y = y;
|
||||
|
||||
if (state)
|
||||
{
|
||||
report.attr = STYLUS_ATTR_TIP_SWITCH | STYLUS_ATTR_IN_RANGE;
|
||||
tud_hid_report(REPORT_ID_STYLUS_PEN, &report, sizeof(report));
|
||||
|
||||
has_stylus_pen = true;
|
||||
}else
|
||||
{
|
||||
report.attr = 0;
|
||||
if (has_stylus_pen) tud_hid_report(REPORT_ID_STYLUS_PEN, &report, sizeof(report));
|
||||
has_stylus_pen = false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Every 10ms, we will sent 1 report for each HID profile (keyboard, mouse etc ..)
|
||||
// tud_hid_report_complete_cb() is used to send the next report after previous one is complete
|
||||
void hid_task(void)
|
||||
@ -239,14 +228,6 @@ void hid_task(void)
|
||||
// Poll every 10ms
|
||||
const uint32_t interval_ms = 10;
|
||||
static uint32_t start_ms = 0;
|
||||
static uint32_t touch_ms = 0;
|
||||
static bool touch_state = false;
|
||||
|
||||
if (board_millis() - touch_ms < 100) {
|
||||
touch_ms = board_millis();
|
||||
send_stylus_touch(0, 0, touch_state = !touch_state);
|
||||
return;
|
||||
}
|
||||
|
||||
if ( board_millis() - start_ms < interval_ms) return; // not enough time
|
||||
start_ms += interval_ms;
|
||||
|
||||
@ -59,11 +59,11 @@ storage_info_t storage_info = {
|
||||
.free_space_in_bytes = 0, // calculated at runtime
|
||||
.free_space_in_objects = 0, // calculated at runtime
|
||||
.storage_description = {
|
||||
.count = (TU_FIELD_SZIE(storage_info_t, storage_description)-1) / sizeof(uint16_t),
|
||||
.count = (TU_FIELD_SIZE(storage_info_t, storage_description)-1) / sizeof(uint16_t),
|
||||
.utf16 = STORAGE_DESCRIPTRION
|
||||
},
|
||||
.volume_identifier = {
|
||||
.count = (TU_FIELD_SZIE(storage_info_t, volume_identifier)-1) / sizeof(uint16_t),
|
||||
.count = (TU_FIELD_SIZE(storage_info_t, volume_identifier)-1) / sizeof(uint16_t),
|
||||
.utf16 = VOLUME_IDENTIFIER
|
||||
}
|
||||
};
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "TinyUSB",
|
||||
"version": "0.18.0",
|
||||
"version": "0.19.0",
|
||||
"description": "TinyUSB is an open-source cross-platform USB Host/Device stack for embedded system, designed to be memory-safe with no dynamic allocation and thread-safe with all interrupt events are deferred then handled in the non-ISR task function.",
|
||||
"keywords": "usb, host, device",
|
||||
"repository":
|
||||
|
||||
@ -16,5 +16,6 @@ repo.versions:
|
||||
"0.16.0": "0.16.0"
|
||||
"0.17.0": "0.17.0"
|
||||
"0.18.0": "0.18.0"
|
||||
"0-latest": "0.18.0"
|
||||
"0.19.0": "0.19.0"
|
||||
"0-latest": "0.19.0"
|
||||
"0-dev": "0.0.0"
|
||||
|
||||
@ -79,10 +79,9 @@
|
||||
// Linear buffer in case target MCU is not capable of handling a ring buffer FIFO e.g. no hardware buffer
|
||||
// is available or driver is would need to be changed dramatically
|
||||
|
||||
// Only STM32 and dcd_transdimension use non-linear buffer for now
|
||||
// dwc2 except esp32sx (since it may use dcd_esp32sx)
|
||||
// Only STM32 and ChipIdea HS use non-linear buffer for now
|
||||
// Ring buffer is incompatible with dcache, since neither address nor size is aligned to cache line
|
||||
#if (defined(TUP_USBIP_DWC2) && !TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3)) || \
|
||||
#if defined(TUP_USBIP_DWC2) || \
|
||||
defined(TUP_USBIP_FSDEV) || \
|
||||
CFG_TUSB_MCU == OPT_MCU_RX63X || \
|
||||
CFG_TUSB_MCU == OPT_MCU_RX65X || \
|
||||
|
||||
@ -267,14 +267,14 @@ void tud_hid_report_failed_cb(uint8_t instance, hid_report_type_t report_type, u
|
||||
// Stylus Pen Report Descriptor Template
|
||||
#define TUD_HID_REPORT_DESC_STYLUS_PEN(...) \
|
||||
HID_USAGE_PAGE ( HID_USAGE_PAGE_DIGITIZER ) , \
|
||||
HID_USAGE ( HID_USAGE_DIGITIZER_TOUCH_SCREEN ) , \
|
||||
HID_USAGE ( HID_USAGE_DIGITIZER_PEN ) , \
|
||||
HID_COLLECTION ( HID_COLLECTION_APPLICATION ) , \
|
||||
/* Report ID if any */\
|
||||
__VA_ARGS__ \
|
||||
HID_USAGE ( HID_USAGE_DIGITIZER_STYLUS ) , \
|
||||
HID_COLLECTION ( HID_COLLECTION_PHYSICAL ) , \
|
||||
HID_USAGE_PAGE ( HID_USAGE_DIGITIZER_TIP_SWITCH ) , \
|
||||
HID_USAGE_PAGE ( HID_USAGE_DIGITIZER_IN_RANGE ) , \
|
||||
HID_USAGE ( HID_USAGE_DIGITIZER_STYLUS ), \
|
||||
HID_COLLECTION ( HID_COLLECTION_PHYSICAL ), \
|
||||
HID_USAGE ( HID_USAGE_DIGITIZER_TIP_SWITCH ), \
|
||||
HID_USAGE ( HID_USAGE_DIGITIZER_IN_RANGE ), \
|
||||
HID_LOGICAL_MIN ( 0 ), \
|
||||
HID_LOGICAL_MAX ( 1 ), \
|
||||
HID_REPORT_SIZE ( 1 ), \
|
||||
|
||||
@ -35,7 +35,7 @@
|
||||
// Macros Helper
|
||||
//--------------------------------------------------------------------+
|
||||
#define TU_ARRAY_SIZE(_arr) ( sizeof(_arr) / sizeof(_arr[0]) )
|
||||
#define TU_FIELD_SZIE(_type, _field) (sizeof(((_type *)0)->_field))
|
||||
#define TU_FIELD_SIZE(_type, _field) (sizeof(((_type *)0)->_field))
|
||||
#define TU_MIN(_x, _y) ( ( (_x) < (_y) ) ? (_x) : (_y) )
|
||||
#define TU_MAX(_x, _y) ( ( (_x) > (_y) ) ? (_x) : (_y) )
|
||||
#define TU_DIV_CEIL(n, d) (((n) + (d) - 1) / (d))
|
||||
|
||||
@ -1,889 +0,0 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018 Scott Shawcroft, 2019 William D. Jones for Adafruit Industries
|
||||
* Copyright (c) 2019 Ha Thach (tinyusb.org)
|
||||
* Additions Copyright (c) 2020, Espressif Systems (Shanghai) Co. Ltd.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* This file is part of the TinyUSB stack.
|
||||
*/
|
||||
|
||||
#include "tusb_option.h"
|
||||
|
||||
#if (((CFG_TUSB_MCU == OPT_MCU_ESP32S2) || (CFG_TUSB_MCU == OPT_MCU_ESP32S3)) && CFG_TUD_ENABLED)
|
||||
|
||||
// Espressif
|
||||
#include "xtensa/xtensa_api.h"
|
||||
|
||||
#include "esp_intr_alloc.h"
|
||||
#include "esp_log.h"
|
||||
#include "soc/dport_reg.h"
|
||||
#include "soc/gpio_sig_map.h"
|
||||
#include "soc/usb_periph.h"
|
||||
#include "soc/usb_reg.h"
|
||||
#include "soc/usb_struct.h"
|
||||
#include "soc/periph_defs.h" // for interrupt source
|
||||
|
||||
#include "device/dcd.h"
|
||||
|
||||
#ifndef USB_OUT_EP_NUM
|
||||
#define USB_OUT_EP_NUM ((int) (sizeof(USB0.out_ep_reg) / sizeof(USB0.out_ep_reg[0])))
|
||||
#endif
|
||||
|
||||
#ifndef USB_IN_EP_NUM
|
||||
#define USB_IN_EP_NUM ((int) (sizeof(USB0.in_ep_reg) / sizeof(USB0.in_ep_reg[0])))
|
||||
#endif
|
||||
|
||||
// Max number of bi-directional endpoints including EP0
|
||||
// Note: ESP32S2 specs say there are only up to 5 IN active endpoints include EP0
|
||||
// We should probably prohibit enabling Endpoint IN > 4 (not done yet)
|
||||
#define EP_MAX USB_OUT_EP_NUM
|
||||
|
||||
// FIFO size in bytes
|
||||
#define EP_FIFO_SIZE 1024
|
||||
|
||||
// Max number of IN EP FIFOs
|
||||
#define EP_FIFO_NUM 5
|
||||
|
||||
typedef struct {
|
||||
uint8_t *buffer;
|
||||
// tu_fifo_t * ff; // TODO support dcd_edpt_xfer_fifo API
|
||||
uint16_t total_len;
|
||||
uint16_t queued_len;
|
||||
uint16_t max_size;
|
||||
bool short_packet;
|
||||
uint8_t interval;
|
||||
} xfer_ctl_t;
|
||||
|
||||
static const char *TAG = "TUSB:DCD";
|
||||
static intr_handle_t usb_ih;
|
||||
|
||||
|
||||
static uint32_t _setup_packet[2];
|
||||
|
||||
#define XFER_CTL_BASE(_ep, _dir) &xfer_status[_ep][_dir]
|
||||
static xfer_ctl_t xfer_status[EP_MAX][2];
|
||||
|
||||
// Keep count of how many FIFOs are in use
|
||||
static uint8_t _allocated_fifos = 1; //FIFO0 is always in use
|
||||
|
||||
// Will either return an unused FIFO number, or 0 if all are used.
|
||||
static uint8_t get_free_fifo(void)
|
||||
{
|
||||
if (_allocated_fifos < EP_FIFO_NUM) return _allocated_fifos++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Setup the control endpoint 0.
|
||||
static void bus_reset(void)
|
||||
{
|
||||
for (int ep_num = 0; ep_num < USB_OUT_EP_NUM; ep_num++) {
|
||||
USB0.out_ep_reg[ep_num].doepctl |= USB_DO_SNAK0_M; // DOEPCTL0_SNAK
|
||||
}
|
||||
|
||||
// clear device address
|
||||
USB0.dcfg &= ~USB_DEVADDR_M;
|
||||
|
||||
USB0.daintmsk = USB_OUTEPMSK0_M | USB_INEPMSK0_M;
|
||||
USB0.doepmsk = USB_SETUPMSK_M | USB_XFERCOMPLMSK;
|
||||
USB0.diepmsk = USB_TIMEOUTMSK_M | USB_DI_XFERCOMPLMSK_M /*| USB_INTKNTXFEMPMSK_M*/;
|
||||
|
||||
// "USB Data FIFOs" section in reference manual
|
||||
// Peripheral FIFO architecture
|
||||
//
|
||||
// --------------- 320 or 1024 ( 1280 or 4096 bytes )
|
||||
// | IN FIFO MAX |
|
||||
// ---------------
|
||||
// | ... |
|
||||
// --------------- y + x + 16 + GRXFSIZ
|
||||
// | IN FIFO 2 |
|
||||
// --------------- x + 16 + GRXFSIZ
|
||||
// | IN FIFO 1 |
|
||||
// --------------- 16 + GRXFSIZ
|
||||
// | IN FIFO 0 |
|
||||
// --------------- GRXFSIZ
|
||||
// | OUT FIFO |
|
||||
// | ( Shared ) |
|
||||
// --------------- 0
|
||||
//
|
||||
// According to "FIFO RAM allocation" section in RM, FIFO RAM are allocated as follows (each word 32-bits):
|
||||
// - Each EP IN needs at least max packet size, 16 words is sufficient for EP0 IN
|
||||
//
|
||||
// - All EP OUT shared a unique OUT FIFO which uses
|
||||
// * 10 locations in hardware for setup packets + setup control words (up to 3 setup packets).
|
||||
// * 2 locations for OUT endpoint control words.
|
||||
// * 16 for largest packet size of 64 bytes. ( TODO Highspeed is 512 bytes)
|
||||
// * 1 location for global NAK (not required/used here).
|
||||
// * It is recommended to allocate 2 times the largest packet size, therefore
|
||||
// Recommended value = 10 + 1 + 2 x (16+2) = 47 --> Let's make it 52
|
||||
USB0.grstctl |= 0x10 << USB_TXFNUM_S; // fifo 0x10,
|
||||
USB0.grstctl |= USB_TXFFLSH_M; // Flush fifo
|
||||
USB0.grxfsiz = 52;
|
||||
|
||||
// Control IN uses FIFO 0 with 64 bytes ( 16 32-bit word )
|
||||
USB0.gnptxfsiz = (16 << USB_NPTXFDEP_S) | (USB0.grxfsiz & 0x0000ffffUL);
|
||||
|
||||
// Ready to receive SETUP packet
|
||||
USB0.out_ep_reg[0].doeptsiz |= USB_SUPCNT0_M;
|
||||
|
||||
USB0.gintmsk |= USB_IEPINTMSK_M | USB_OEPINTMSK_M;
|
||||
}
|
||||
|
||||
static void enum_done_processing(void)
|
||||
{
|
||||
ESP_EARLY_LOGV(TAG, "dcd_int_handler - Speed enumeration done! Sending DCD_EVENT_BUS_RESET then");
|
||||
// On current silicon on the Full Speed core, speed is fixed to Full Speed.
|
||||
// However, keep for debugging and in case Low Speed is ever supported.
|
||||
uint32_t enum_spd = (USB0.dsts >> USB_ENUMSPD_S) & (USB_ENUMSPD_V);
|
||||
|
||||
// Maximum packet size for EP 0 is set for both directions by writing DIEPCTL
|
||||
if (enum_spd == 0x03) { // Full-Speed (PHY on 48 MHz)
|
||||
USB0.in_ep_reg[0].diepctl &= ~USB_D_MPS0_V; // 64 bytes
|
||||
USB0.in_ep_reg[0].diepctl &= ~USB_D_STALL0_M; // clear Stall
|
||||
xfer_status[0][TUSB_DIR_OUT].max_size = 64;
|
||||
xfer_status[0][TUSB_DIR_IN].max_size = 64;
|
||||
} else {
|
||||
USB0.in_ep_reg[0].diepctl |= USB_D_MPS0_V; // 8 bytes
|
||||
USB0.in_ep_reg[0].diepctl &= ~USB_D_STALL0_M; // clear Stall
|
||||
xfer_status[0][TUSB_DIR_OUT].max_size = 8;
|
||||
xfer_status[0][TUSB_DIR_IN].max_size = 8;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*------------------------------------------------------------------*/
|
||||
/* Controller API
|
||||
*------------------------------------------------------------------*/
|
||||
bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) {
|
||||
(void) rh_init;
|
||||
ESP_LOGV(TAG, "DCD init - Start");
|
||||
|
||||
// A. Disconnect
|
||||
ESP_LOGV(TAG, "DCD init - Soft DISCONNECT and Setting up");
|
||||
USB0.dctl |= USB_SFTDISCON_M; // Soft disconnect
|
||||
|
||||
// B. Programming DCFG
|
||||
/* If USB host misbehaves during status portion of control xfer
|
||||
(non zero-length packet), send STALL back and discard. Full speed. */
|
||||
USB0.dcfg |= USB_NZSTSOUTHSHK_M | // NonZero .... STALL
|
||||
(3 << 0); // dev speed: fullspeed 1.1 on 48 mhz // TODO no value in usb_reg.h (IDF-1476)
|
||||
|
||||
USB0.gahbcfg |= USB_NPTXFEMPLVL_M | USB_GLBLLNTRMSK_M; // Global interruptions ON
|
||||
USB0.gusbcfg |= USB_FORCEDEVMODE_M; // force devmode
|
||||
USB0.gotgctl &= ~(USB_BVALIDOVVAL_M | USB_BVALIDOVEN_M | USB_VBVALIDOVVAL_M); //no overrides
|
||||
|
||||
// C. Setting SNAKs, then connect
|
||||
for (int n = 0; n < USB_OUT_EP_NUM; n++) {
|
||||
USB0.out_ep_reg[n].doepctl |= USB_DO_SNAK0_M; // DOEPCTL0_SNAK
|
||||
}
|
||||
|
||||
// D. Interruption masking
|
||||
USB0.gintmsk = 0; //mask all
|
||||
USB0.gotgint = ~0U; //clear OTG ints
|
||||
USB0.gintsts = ~0U; //clear pending ints
|
||||
USB0.gintmsk = USB_OTGINTMSK_M |
|
||||
USB_MODEMISMSK_M |
|
||||
USB_RXFLVIMSK_M |
|
||||
USB_ERLYSUSPMSK_M |
|
||||
USB_USBSUSPMSK_M |
|
||||
USB_USBRSTMSK_M |
|
||||
USB_ENUMDONEMSK_M |
|
||||
USB_RESETDETMSK_M |
|
||||
USB_WKUPINT_M |
|
||||
USB_DISCONNINTMSK_M; // host most only
|
||||
|
||||
dcd_connect(rhport);
|
||||
return true;
|
||||
}
|
||||
|
||||
void dcd_set_address(uint8_t rhport, uint8_t dev_addr)
|
||||
{
|
||||
(void)rhport;
|
||||
ESP_LOGV(TAG, "DCD init - Set address : %u", dev_addr);
|
||||
USB0.dcfg |= ((dev_addr & USB_DEVADDR_V) << USB_DEVADDR_S);
|
||||
// Response with status after changing device address
|
||||
dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0);
|
||||
}
|
||||
|
||||
void dcd_remote_wakeup(uint8_t rhport)
|
||||
{
|
||||
(void)rhport;
|
||||
|
||||
// set remote wakeup
|
||||
USB0.dctl |= USB_RMTWKUPSIG_M;
|
||||
|
||||
// enable SOF to detect bus resume
|
||||
USB0.gintsts = USB_SOF_M;
|
||||
USB0.gintmsk |= USB_SOFMSK_M;
|
||||
|
||||
// Per specs: remote wakeup signal bit must be clear within 1-15ms
|
||||
vTaskDelay(pdMS_TO_TICKS(1));
|
||||
|
||||
USB0.dctl &= ~USB_RMTWKUPSIG_M;
|
||||
}
|
||||
|
||||
// connect by enabling internal pull-up resistor on D+/D-
|
||||
void dcd_connect(uint8_t rhport)
|
||||
{
|
||||
(void) rhport;
|
||||
USB0.dctl &= ~USB_SFTDISCON_M;
|
||||
}
|
||||
|
||||
// disconnect by disabling internal pull-up resistor on D+/D-
|
||||
void dcd_disconnect(uint8_t rhport)
|
||||
{
|
||||
(void) rhport;
|
||||
USB0.dctl |= USB_SFTDISCON_M;
|
||||
}
|
||||
|
||||
void dcd_sof_enable(uint8_t rhport, bool en)
|
||||
{
|
||||
(void) rhport;
|
||||
(void) en;
|
||||
|
||||
// TODO implement later
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------*/
|
||||
/* DCD Endpoint port
|
||||
*------------------------------------------------------------------*/
|
||||
|
||||
bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const *desc_edpt)
|
||||
{
|
||||
ESP_LOGV(TAG, "DCD endpoint opened");
|
||||
(void)rhport;
|
||||
|
||||
usb_out_endpoint_t *out_ep = &(USB0.out_ep_reg[0]);
|
||||
usb_in_endpoint_t *in_ep = &(USB0.in_ep_reg[0]);
|
||||
|
||||
uint8_t const epnum = tu_edpt_number(desc_edpt->bEndpointAddress);
|
||||
uint8_t const dir = tu_edpt_dir(desc_edpt->bEndpointAddress);
|
||||
|
||||
TU_ASSERT(epnum < EP_MAX);
|
||||
|
||||
xfer_ctl_t *xfer = XFER_CTL_BASE(epnum, dir);
|
||||
xfer->max_size = tu_edpt_packet_size(desc_edpt);
|
||||
xfer->interval = desc_edpt->bInterval;
|
||||
|
||||
if (dir == TUSB_DIR_OUT) {
|
||||
out_ep[epnum].doepctl |= USB_USBACTEP1_M |
|
||||
desc_edpt->bmAttributes.xfer << USB_EPTYPE1_S |
|
||||
(desc_edpt->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS ? USB_DO_SETD0PID1_M : 0) |
|
||||
xfer->max_size << USB_MPS1_S;
|
||||
USB0.daintmsk |= (1 << (16 + epnum));
|
||||
} else {
|
||||
// "USB Data FIFOs" section in reference manual
|
||||
// Peripheral FIFO architecture
|
||||
//
|
||||
// --------------- 320 or 1024 ( 1280 or 4096 bytes )
|
||||
// | IN FIFO MAX |
|
||||
// ---------------
|
||||
// | ... |
|
||||
// --------------- y + x + 16 + GRXFSIZ
|
||||
// | IN FIFO 2 |
|
||||
// --------------- x + 16 + GRXFSIZ
|
||||
// | IN FIFO 1 |
|
||||
// --------------- 16 + GRXFSIZ
|
||||
// | IN FIFO 0 |
|
||||
// --------------- GRXFSIZ
|
||||
// | OUT FIFO |
|
||||
// | ( Shared ) |
|
||||
// --------------- 0
|
||||
//
|
||||
// Since OUT FIFO = GRXFSIZ, FIFO 0 = 16, for simplicity, we equally allocated for the rest of endpoints
|
||||
// - Size : (FIFO_SIZE/4 - GRXFSIZ - 16) / (EP_MAX-1)
|
||||
// - Offset: GRXFSIZ + 16 + Size*(epnum-1)
|
||||
// - IN EP 1 gets FIFO 1, IN EP "n" gets FIFO "n".
|
||||
|
||||
uint8_t fifo_num = get_free_fifo();
|
||||
TU_ASSERT(fifo_num != 0);
|
||||
|
||||
in_ep[epnum].diepctl &= ~(USB_D_TXFNUM1_M | USB_D_EPTYPE1_M | USB_DI_SETD0PID1 | USB_D_MPS1_M);
|
||||
in_ep[epnum].diepctl |= USB_D_USBACTEP1_M |
|
||||
fifo_num << USB_D_TXFNUM1_S |
|
||||
desc_edpt->bmAttributes.xfer << USB_D_EPTYPE1_S |
|
||||
(desc_edpt->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS ? (1 << USB_DI_SETD0PID1_S) : 0) |
|
||||
xfer->max_size << 0;
|
||||
|
||||
USB0.daintmsk |= (1 << (0 + epnum));
|
||||
|
||||
// Both TXFD and TXSA are in unit of 32-bit words.
|
||||
// IN FIFO 0 was configured during enumeration, hence the "+ 16".
|
||||
uint16_t const allocated_size = (USB0.grxfsiz & 0x0000ffff) + 16;
|
||||
uint16_t const fifo_size = (EP_FIFO_SIZE/4 - allocated_size) / (EP_FIFO_NUM-1);
|
||||
uint32_t const fifo_offset = allocated_size + fifo_size*(fifo_num-1);
|
||||
|
||||
// DIEPTXF starts at FIFO #1.
|
||||
USB0.dieptxf[epnum - 1] = (fifo_size << USB_NPTXFDEP_S) | fifo_offset;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void dcd_edpt_close_all(uint8_t rhport)
|
||||
{
|
||||
(void) rhport;
|
||||
|
||||
usb_out_endpoint_t *out_ep = &(USB0.out_ep_reg[0]);
|
||||
usb_in_endpoint_t *in_ep = &(USB0.in_ep_reg[0]);
|
||||
|
||||
// Disable non-control interrupt
|
||||
USB0.daintmsk = USB_OUTEPMSK0_M | USB_INEPMSK0_M;
|
||||
|
||||
for(uint8_t n = 1; n < EP_MAX; n++)
|
||||
{
|
||||
// disable OUT endpoint
|
||||
out_ep[n].doepctl = 0;
|
||||
xfer_status[n][TUSB_DIR_OUT].max_size = 0;
|
||||
|
||||
// disable IN endpoint
|
||||
in_ep[n].diepctl = 0;
|
||||
xfer_status[n][TUSB_DIR_IN].max_size = 0;
|
||||
}
|
||||
|
||||
_allocated_fifos = 1;
|
||||
}
|
||||
|
||||
bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes)
|
||||
{
|
||||
(void)rhport;
|
||||
|
||||
uint8_t const epnum = tu_edpt_number(ep_addr);
|
||||
uint8_t const dir = tu_edpt_dir(ep_addr);
|
||||
|
||||
xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, dir);
|
||||
xfer->buffer = buffer;
|
||||
// xfer->ff = NULL; // TODO support dcd_edpt_xfer_fifo API
|
||||
xfer->total_len = total_bytes;
|
||||
xfer->queued_len = 0;
|
||||
xfer->short_packet = false;
|
||||
|
||||
uint16_t num_packets = (total_bytes / xfer->max_size);
|
||||
uint8_t short_packet_size = total_bytes % xfer->max_size;
|
||||
|
||||
// Zero-size packet is special case.
|
||||
if (short_packet_size > 0 || (total_bytes == 0)) {
|
||||
num_packets++;
|
||||
}
|
||||
|
||||
ESP_LOGV(TAG, "Transfer <-> EP%i, %s, pkgs: %i, bytes: %i",
|
||||
epnum, ((dir == TUSB_DIR_IN) ? "USB0.HOST (in)" : "HOST->DEV (out)"),
|
||||
num_packets, total_bytes);
|
||||
|
||||
// IN and OUT endpoint xfers are interrupt-driven, we just schedule them
|
||||
// here.
|
||||
if (dir == TUSB_DIR_IN) {
|
||||
// A full IN transfer (multiple packets, possibly) triggers XFRC.
|
||||
USB0.in_ep_reg[epnum].dieptsiz = (num_packets << USB_D_PKTCNT0_S) | total_bytes;
|
||||
USB0.in_ep_reg[epnum].diepctl |= USB_D_EPENA1_M | USB_D_CNAK1_M; // Enable | CNAK
|
||||
|
||||
// For ISO endpoint with interval=1 set correct DATA0/DATA1 bit for next frame
|
||||
if ((USB0.in_ep_reg[epnum].diepctl & USB_D_EPTYPE0_M) == (1 << USB_D_EPTYPE1_S) && xfer->interval == 1) {
|
||||
// Take odd/even bit from frame counter.
|
||||
uint32_t const odd_frame_now = (USB0.dsts & (1u << USB_SOFFN_S));
|
||||
USB0.in_ep_reg[epnum].diepctl |= (odd_frame_now ? USB_DI_SETD0PID1 : USB_DI_SETD1PID1);
|
||||
}
|
||||
|
||||
// Enable fifo empty interrupt only if there are something to put in the fifo.
|
||||
if(total_bytes != 0) {
|
||||
USB0.dtknqr4_fifoemptymsk |= (1 << epnum);
|
||||
}
|
||||
} else {
|
||||
// Each complete packet for OUT xfers triggers XFRC.
|
||||
USB0.out_ep_reg[epnum].doeptsiz |= USB_PKTCNT0_M | ((xfer->max_size & USB_XFERSIZE0_V) << USB_XFERSIZE0_S);
|
||||
USB0.out_ep_reg[epnum].doepctl |= USB_EPENA0_M | USB_CNAK0_M;
|
||||
|
||||
// For ISO endpoint with interval=1 set correct DATA0/DATA1 bit for next frame
|
||||
if ((USB0.out_ep_reg[epnum].doepctl & USB_D_EPTYPE0_M) == (1 << USB_D_EPTYPE1_S) && xfer->interval == 1) {
|
||||
// Take odd/even bit from frame counter.
|
||||
uint32_t const odd_frame_now = (USB0.dsts & (1u << USB_SOFFN_S));
|
||||
USB0.out_ep_reg[epnum].doepctl |= (odd_frame_now ? USB_DO_SETD0PID1 : USB_DO_SETD1PID1);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#if 0 // TODO support dcd_edpt_xfer_fifo API
|
||||
bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes)
|
||||
{
|
||||
(void)rhport;
|
||||
}
|
||||
#endif
|
||||
|
||||
void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr)
|
||||
{
|
||||
(void)rhport;
|
||||
|
||||
usb_out_endpoint_t *out_ep = &(USB0.out_ep_reg[0]);
|
||||
usb_in_endpoint_t *in_ep = &(USB0.in_ep_reg[0]);
|
||||
|
||||
uint8_t const epnum = tu_edpt_number(ep_addr);
|
||||
uint8_t const dir = tu_edpt_dir(ep_addr);
|
||||
|
||||
if (dir == TUSB_DIR_IN) {
|
||||
// Only disable currently enabled non-control endpoint
|
||||
if ((epnum == 0) || !(in_ep[epnum].diepctl & USB_D_EPENA1_M)) {
|
||||
in_ep[epnum].diepctl |= (USB_DI_SNAK1_M | USB_D_STALL1_M);
|
||||
} else {
|
||||
// Stop transmitting packets and NAK IN xfers.
|
||||
in_ep[epnum].diepctl |= USB_DI_SNAK1_M;
|
||||
while ((in_ep[epnum].diepint & USB_DI_SNAK1_M) == 0) ;
|
||||
|
||||
// Disable the endpoint. Note that both SNAK and STALL are set here.
|
||||
in_ep[epnum].diepctl |= (USB_DI_SNAK1_M | USB_D_STALL1_M | USB_D_EPDIS1_M);
|
||||
while ((in_ep[epnum].diepint & USB_D_EPDISBLD0_M) == 0) ;
|
||||
in_ep[epnum].diepint = USB_D_EPDISBLD0_M;
|
||||
}
|
||||
|
||||
// Flush the FIFO, and wait until we have confirmed it cleared.
|
||||
uint8_t const fifo_num = ((in_ep[epnum].diepctl >> USB_D_TXFNUM1_S) & USB_D_TXFNUM1_V);
|
||||
USB0.grstctl |= (fifo_num << USB_TXFNUM_S);
|
||||
USB0.grstctl |= USB_TXFFLSH_M;
|
||||
while ((USB0.grstctl & USB_TXFFLSH_M) != 0) ;
|
||||
} else {
|
||||
// Only disable currently enabled non-control endpoint
|
||||
if ((epnum == 0) || !(out_ep[epnum].doepctl & USB_EPENA0_M)) {
|
||||
out_ep[epnum].doepctl |= USB_STALL0_M;
|
||||
} else {
|
||||
// Asserting GONAK is required to STALL an OUT endpoint.
|
||||
// Simpler to use polling here, we don't use the "B"OUTNAKEFF interrupt
|
||||
// anyway, and it can't be cleared by user code. If this while loop never
|
||||
// finishes, we have bigger problems than just the stack.
|
||||
USB0.dctl |= USB_SGOUTNAK_M;
|
||||
while ((USB0.gintsts & USB_GOUTNAKEFF_M) == 0) ;
|
||||
|
||||
// Ditto here- disable the endpoint. Note that only STALL and not SNAK
|
||||
// is set here.
|
||||
out_ep[epnum].doepctl |= (USB_STALL0_M | USB_EPDIS0_M);
|
||||
while ((out_ep[epnum].doepint & USB_EPDISBLD0_M) == 0) ;
|
||||
out_ep[epnum].doepint = USB_EPDISBLD0_M;
|
||||
|
||||
// Allow other OUT endpoints to keep receiving.
|
||||
USB0.dctl |= USB_CGOUTNAK_M;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr)
|
||||
{
|
||||
(void)rhport;
|
||||
|
||||
usb_out_endpoint_t *out_ep = &(USB0.out_ep_reg[0]);
|
||||
usb_in_endpoint_t *in_ep = &(USB0.in_ep_reg[0]);
|
||||
|
||||
uint8_t const epnum = tu_edpt_number(ep_addr);
|
||||
uint8_t const dir = tu_edpt_dir(ep_addr);
|
||||
|
||||
if (dir == TUSB_DIR_IN) {
|
||||
in_ep[epnum].diepctl &= ~USB_D_STALL1_M;
|
||||
|
||||
uint8_t eptype = (in_ep[epnum].diepctl & USB_D_EPTYPE1_M) >> USB_D_EPTYPE1_S;
|
||||
// Required by USB spec to reset DATA toggle bit to DATA0 on interrupt
|
||||
// and bulk endpoints.
|
||||
if (eptype == 2 || eptype == 3) {
|
||||
in_ep[epnum].diepctl |= USB_DI_SETD0PID1_M;
|
||||
}
|
||||
} else {
|
||||
out_ep[epnum].doepctl &= ~USB_STALL1_M;
|
||||
|
||||
uint8_t eptype = (out_ep[epnum].doepctl & USB_EPTYPE1_M) >> USB_EPTYPE1_S;
|
||||
// Required by USB spec to reset DATA toggle bit to DATA0 on interrupt
|
||||
// and bulk endpoints.
|
||||
if (eptype == 2 || eptype == 3) {
|
||||
out_ep[epnum].doepctl |= USB_DO_SETD0PID1_M;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------*/
|
||||
|
||||
static void receive_packet(xfer_ctl_t *xfer, /* usb_out_endpoint_t * out_ep, */ uint16_t xfer_size)
|
||||
{
|
||||
ESP_EARLY_LOGV(TAG, "USB - receive_packet");
|
||||
volatile uint32_t *rx_fifo = USB0.fifo[0];
|
||||
|
||||
// See above TODO
|
||||
// uint16_t remaining = (out_ep->DOEPTSIZ & UsbDOEPTSIZ_XFRSIZ_Msk) >> UsbDOEPTSIZ_XFRSIZ_Pos;
|
||||
// xfer->queued_len = xfer->total_len - remaining;
|
||||
|
||||
uint16_t remaining = xfer->total_len - xfer->queued_len;
|
||||
uint16_t to_recv_size;
|
||||
|
||||
if (remaining <= xfer->max_size) {
|
||||
// Avoid buffer overflow.
|
||||
to_recv_size = (xfer_size > remaining) ? remaining : xfer_size;
|
||||
} else {
|
||||
// Room for full packet, choose recv_size based on what the microcontroller
|
||||
// claims.
|
||||
to_recv_size = (xfer_size > xfer->max_size) ? xfer->max_size : xfer_size;
|
||||
}
|
||||
|
||||
// Common buffer read
|
||||
#if 0 // TODO support dcd_edpt_xfer_fifo API
|
||||
if (xfer->ff)
|
||||
{
|
||||
// Ring buffer
|
||||
tu_fifo_write_n_const_addr_full_words(xfer->ff, (const void *) rx_fifo, to_recv_size);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
uint8_t to_recv_rem = to_recv_size % 4;
|
||||
uint16_t to_recv_size_aligned = to_recv_size - to_recv_rem;
|
||||
|
||||
// Do not assume xfer buffer is aligned.
|
||||
uint8_t *base = (xfer->buffer + xfer->queued_len);
|
||||
|
||||
// This for loop always runs at least once- skip if less than 4 bytes
|
||||
// to collect.
|
||||
if (to_recv_size >= 4) {
|
||||
for (uint16_t i = 0; i < to_recv_size_aligned; i += 4) {
|
||||
uint32_t tmp = (*rx_fifo);
|
||||
base[i] = tmp & 0x000000FF;
|
||||
base[i + 1] = (tmp & 0x0000FF00) >> 8;
|
||||
base[i + 2] = (tmp & 0x00FF0000) >> 16;
|
||||
base[i + 3] = (tmp & 0xFF000000) >> 24;
|
||||
}
|
||||
}
|
||||
|
||||
// Do not read invalid bytes from RX FIFO.
|
||||
if (to_recv_rem != 0) {
|
||||
uint32_t tmp = (*rx_fifo);
|
||||
uint8_t *last_32b_bound = base + to_recv_size_aligned;
|
||||
|
||||
last_32b_bound[0] = tmp & 0x000000FF;
|
||||
if (to_recv_rem > 1) {
|
||||
last_32b_bound[1] = (tmp & 0x0000FF00) >> 8;
|
||||
}
|
||||
if (to_recv_rem > 2) {
|
||||
last_32b_bound[2] = (tmp & 0x00FF0000) >> 16;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
xfer->queued_len += xfer_size;
|
||||
|
||||
// Per USB spec, a short OUT packet (including length 0) is always
|
||||
// indicative of the end of a transfer (at least for ctl, bulk, int).
|
||||
xfer->short_packet = (xfer_size < xfer->max_size);
|
||||
}
|
||||
|
||||
static void transmit_packet(xfer_ctl_t *xfer, volatile usb_in_endpoint_t *in_ep, uint8_t fifo_num)
|
||||
{
|
||||
ESP_EARLY_LOGV(TAG, "USB - transmit_packet");
|
||||
volatile uint32_t *tx_fifo = USB0.fifo[fifo_num];
|
||||
|
||||
uint16_t remaining = (in_ep->dieptsiz & 0x7FFFFU) >> USB_D_XFERSIZE0_S;
|
||||
xfer->queued_len = xfer->total_len - remaining;
|
||||
|
||||
uint16_t to_xfer_size = (remaining > xfer->max_size) ? xfer->max_size : remaining;
|
||||
|
||||
#if 0 // TODO support dcd_edpt_xfer_fifo API
|
||||
if (xfer->ff)
|
||||
{
|
||||
tu_fifo_read_n_const_addr_full_words(xfer->ff, (void *) tx_fifo, to_xfer_size);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
uint8_t to_xfer_rem = to_xfer_size % 4;
|
||||
uint16_t to_xfer_size_aligned = to_xfer_size - to_xfer_rem;
|
||||
|
||||
// Buffer might not be aligned to 32b, so we need to force alignment
|
||||
// by copying to a temp var.
|
||||
uint8_t *base = (xfer->buffer + xfer->queued_len);
|
||||
|
||||
// This for loop always runs at least once- skip if less than 4 bytes
|
||||
// to send off.
|
||||
if (to_xfer_size >= 4) {
|
||||
for (uint16_t i = 0; i < to_xfer_size_aligned; i += 4) {
|
||||
uint32_t tmp = base[i] | (base[i + 1] << 8) |
|
||||
(base[i + 2] << 16) | (base[i + 3] << 24);
|
||||
(*tx_fifo) = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
// Do not read beyond end of buffer if not divisible by 4.
|
||||
if (to_xfer_rem != 0) {
|
||||
uint32_t tmp = 0;
|
||||
uint8_t *last_32b_bound = base + to_xfer_size_aligned;
|
||||
|
||||
tmp |= last_32b_bound[0];
|
||||
if (to_xfer_rem > 1) {
|
||||
tmp |= (last_32b_bound[1] << 8);
|
||||
}
|
||||
if (to_xfer_rem > 2) {
|
||||
tmp |= (last_32b_bound[2] << 16);
|
||||
}
|
||||
|
||||
(*tx_fifo) = tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void read_rx_fifo(void)
|
||||
{
|
||||
// Pop control word off FIFO (completed xfers will have 2 control words,
|
||||
// we only pop one ctl word each interrupt).
|
||||
uint32_t const ctl_word = USB0.grxstsp;
|
||||
uint8_t const pktsts = (ctl_word & USB_PKTSTS_M) >> USB_PKTSTS_S;
|
||||
uint8_t const epnum = (ctl_word & USB_CHNUM_M ) >> USB_CHNUM_S;
|
||||
uint16_t const bcnt = (ctl_word & USB_BCNT_M ) >> USB_BCNT_S;
|
||||
|
||||
switch (pktsts) {
|
||||
case 0x01: // Global OUT NAK (Interrupt)
|
||||
ESP_EARLY_LOGV(TAG, "TUSB IRQ - RX type : Global OUT NAK");
|
||||
break;
|
||||
|
||||
case 0x02: { // Out packet recvd
|
||||
ESP_EARLY_LOGV(TAG, "TUSB IRQ - RX type : Out packet");
|
||||
xfer_ctl_t *xfer = XFER_CTL_BASE(epnum, TUSB_DIR_OUT);
|
||||
receive_packet(xfer, bcnt);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x03: // Out packet done (Interrupt)
|
||||
ESP_EARLY_LOGV(TAG, "TUSB IRQ - RX type : Out packet done");
|
||||
break;
|
||||
|
||||
case 0x04: // Step 2: Setup transaction completed (Interrupt)
|
||||
// After this event, OEPINT interrupt will occur with SETUP bit set
|
||||
ESP_EARLY_LOGV(TAG, "TUSB IRQ - RX : Setup packet done");
|
||||
USB0.out_ep_reg[epnum].doeptsiz |= USB_SUPCNT0_M;
|
||||
break;
|
||||
|
||||
case 0x06: { // Step1: Setup data packet received
|
||||
volatile uint32_t *rx_fifo = USB0.fifo[0];
|
||||
|
||||
// We can receive up to three setup packets in succession, but
|
||||
// only the last one is valid. Therefore we just overwrite it
|
||||
_setup_packet[0] = (*rx_fifo);
|
||||
_setup_packet[1] = (*rx_fifo);
|
||||
|
||||
ESP_EARLY_LOGV(TAG, "TUSB IRQ - RX : Setup packet : 0x%08x 0x%08x", _setup_packet[0], _setup_packet[1]);
|
||||
}
|
||||
break;
|
||||
|
||||
default: // Invalid, do something here, like breakpoint?
|
||||
TU_BREAKPOINT();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void handle_epout_ints(void)
|
||||
{
|
||||
// GINTSTS will be cleared with DAINT == 0
|
||||
// DAINT for a given EP clears when DOEPINTx is cleared.
|
||||
// DOEPINT will be cleared when DAINT's out bits are cleared.
|
||||
for (int n = 0; n < USB_OUT_EP_NUM; n++) {
|
||||
xfer_ctl_t *xfer = XFER_CTL_BASE(n, TUSB_DIR_OUT);
|
||||
|
||||
if (USB0.daint & (1 << (16 + n))) {
|
||||
// SETUP packet Setup Phase done.
|
||||
if ((USB0.out_ep_reg[n].doepint & USB_SETUP0_M)) {
|
||||
USB0.out_ep_reg[n].doepint = USB_STUPPKTRCVD0_M | USB_SETUP0_M; // clear
|
||||
dcd_event_setup_received(0, (uint8_t *)&_setup_packet[0], true);
|
||||
}
|
||||
|
||||
// OUT XFER complete (single packet).q
|
||||
if (USB0.out_ep_reg[n].doepint & USB_XFERCOMPL0_M) {
|
||||
|
||||
ESP_EARLY_LOGV(TAG, "TUSB IRQ - EP OUT - XFER complete (single packet)");
|
||||
USB0.out_ep_reg[n].doepint = USB_XFERCOMPL0_M;
|
||||
|
||||
// Transfer complete if short packet or total len is transferred
|
||||
if (xfer->short_packet || (xfer->queued_len == xfer->total_len)) {
|
||||
xfer->short_packet = false;
|
||||
dcd_event_xfer_complete(0, n, xfer->queued_len, XFER_RESULT_SUCCESS, true);
|
||||
} else {
|
||||
// Schedule another packet to be received.
|
||||
USB0.out_ep_reg[n].doeptsiz |= USB_PKTCNT0_M | ((xfer->max_size & USB_XFERSIZE0_V) << USB_XFERSIZE0_S);
|
||||
USB0.out_ep_reg[n].doepctl |= USB_EPENA0_M | USB_CNAK0_M;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void handle_epin_ints(void)
|
||||
{
|
||||
// GINTSTS will be cleared with DAINT == 0
|
||||
// DAINT for a given EP clears when DIEPINTx is cleared.
|
||||
// IEPINT will be cleared when DAINT's out bits are cleared.
|
||||
for (uint32_t n = 0; n < USB_IN_EP_NUM; n++) {
|
||||
xfer_ctl_t *xfer = &xfer_status[n][TUSB_DIR_IN];
|
||||
|
||||
if (USB0.daint & (1 << (0 + n))) {
|
||||
ESP_EARLY_LOGV(TAG, "TUSB IRQ - EP IN %u", n);
|
||||
// IN XFER complete (entire xfer).
|
||||
if (USB0.in_ep_reg[n].diepint & USB_D_XFERCOMPL0_M) {
|
||||
ESP_EARLY_LOGV(TAG, "TUSB IRQ - IN XFER complete!");
|
||||
USB0.in_ep_reg[n].diepint = USB_D_XFERCOMPL0_M;
|
||||
dcd_event_xfer_complete(0, n | TUSB_DIR_IN_MASK, xfer->total_len, XFER_RESULT_SUCCESS, true);
|
||||
}
|
||||
|
||||
// XFER FIFO empty
|
||||
if (USB0.in_ep_reg[n].diepint & USB_D_TXFEMP0_M) {
|
||||
ESP_EARLY_LOGV(TAG, "TUSB IRQ - IN XFER FIFO empty!");
|
||||
USB0.in_ep_reg[n].diepint = USB_D_TXFEMP0_M;
|
||||
transmit_packet(xfer, &USB0.in_ep_reg[n], n);
|
||||
|
||||
// Turn off TXFE if all bytes are written.
|
||||
if (xfer->queued_len == xfer->total_len)
|
||||
{
|
||||
USB0.dtknqr4_fifoemptymsk &= ~(1 << n);
|
||||
}
|
||||
}
|
||||
|
||||
// XFER Timeout
|
||||
if (USB0.in_ep_reg[n].diepint & USB_D_TIMEOUT0_M) {
|
||||
// Clear interrupt or endpoint will hang.
|
||||
USB0.in_ep_reg[n].diepint = USB_D_TIMEOUT0_M;
|
||||
// Maybe retry?
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void _dcd_int_handler(void* arg)
|
||||
{
|
||||
(void) arg;
|
||||
uint8_t const rhport = 0;
|
||||
|
||||
const uint32_t int_msk = USB0.gintmsk;
|
||||
const uint32_t int_status = USB0.gintsts & int_msk;
|
||||
|
||||
if (int_status & USB_USBRST_M) {
|
||||
// start of reset
|
||||
ESP_EARLY_LOGV(TAG, "dcd_int_handler - reset");
|
||||
USB0.gintsts = USB_USBRST_M;
|
||||
// FIFOs will be reassigned when the endpoints are reopen
|
||||
_allocated_fifos = 1;
|
||||
bus_reset();
|
||||
}
|
||||
|
||||
if (int_status & USB_RESETDET_M) {
|
||||
ESP_EARLY_LOGV(TAG, "dcd_int_handler - reset while suspend");
|
||||
USB0.gintsts = USB_RESETDET_M;
|
||||
bus_reset();
|
||||
}
|
||||
|
||||
if (int_status & USB_ENUMDONE_M) {
|
||||
// ENUMDNE detects speed of the link. For full-speed, we
|
||||
// always expect the same value. This interrupt is considered
|
||||
// the end of reset.
|
||||
USB0.gintsts = USB_ENUMDONE_M;
|
||||
enum_done_processing();
|
||||
dcd_event_bus_reset(rhport, TUSB_SPEED_FULL, true);
|
||||
}
|
||||
|
||||
if(int_status & USB_USBSUSP_M)
|
||||
{
|
||||
USB0.gintsts = USB_USBSUSP_M;
|
||||
dcd_event_bus_signal(rhport, DCD_EVENT_SUSPEND, true);
|
||||
}
|
||||
|
||||
if(int_status & USB_WKUPINT_M)
|
||||
{
|
||||
USB0.gintsts = USB_WKUPINT_M;
|
||||
dcd_event_bus_signal(rhport, DCD_EVENT_RESUME, true);
|
||||
}
|
||||
|
||||
if (int_status & USB_OTGINT_M)
|
||||
{
|
||||
// OTG INT bit is read-only
|
||||
ESP_EARLY_LOGV(TAG, "dcd_int_handler - disconnected");
|
||||
|
||||
uint32_t const otg_int = USB0.gotgint;
|
||||
|
||||
if (otg_int & USB_SESENDDET_M)
|
||||
{
|
||||
dcd_event_bus_signal(rhport, DCD_EVENT_UNPLUGGED, true);
|
||||
}
|
||||
|
||||
USB0.gotgint = otg_int;
|
||||
}
|
||||
|
||||
if (int_status & USB_SOF_M) {
|
||||
USB0.gintsts = USB_SOF_M;
|
||||
|
||||
// Disable SOF interrupt since currently only used for remote wakeup detection
|
||||
USB0.gintmsk &= ~USB_SOFMSK_M;
|
||||
|
||||
dcd_event_bus_signal(rhport, DCD_EVENT_SOF, true);
|
||||
}
|
||||
|
||||
|
||||
if (int_status & USB_RXFLVI_M) {
|
||||
// RXFLVL bit is read-only
|
||||
ESP_EARLY_LOGV(TAG, "dcd_int_handler - rx!");
|
||||
|
||||
// Mask out RXFLVL while reading data from FIFO
|
||||
USB0.gintmsk &= ~USB_RXFLVIMSK_M;
|
||||
read_rx_fifo();
|
||||
USB0.gintmsk |= USB_RXFLVIMSK_M;
|
||||
}
|
||||
|
||||
// OUT endpoint interrupt handling.
|
||||
if (int_status & USB_OEPINT_M) {
|
||||
// OEPINT is read-only
|
||||
ESP_EARLY_LOGV(TAG, "dcd_int_handler - OUT endpoint!");
|
||||
handle_epout_ints();
|
||||
}
|
||||
|
||||
// IN endpoint interrupt handling.
|
||||
if (int_status & USB_IEPINT_M) {
|
||||
// IEPINT bit read-only
|
||||
ESP_EARLY_LOGV(TAG, "dcd_int_handler - IN endpoint!");
|
||||
handle_epin_ints();
|
||||
}
|
||||
|
||||
// Without handling
|
||||
USB0.gintsts |= USB_CURMOD_INT_M |
|
||||
USB_MODEMIS_M |
|
||||
USB_OTGINT_M |
|
||||
USB_NPTXFEMP_M |
|
||||
USB_GINNAKEFF_M |
|
||||
USB_GOUTNAKEFF |
|
||||
USB_ERLYSUSP_M |
|
||||
USB_USBSUSP_M |
|
||||
USB_ISOOUTDROP_M |
|
||||
USB_EOPF_M |
|
||||
USB_EPMIS_M |
|
||||
USB_INCOMPISOIN_M |
|
||||
USB_INCOMPIP_M |
|
||||
USB_FETSUSP_M |
|
||||
USB_PTXFEMP_M;
|
||||
}
|
||||
|
||||
void dcd_int_enable (uint8_t rhport)
|
||||
{
|
||||
(void) rhport;
|
||||
esp_intr_alloc(ETS_USB_INTR_SOURCE, ESP_INTR_FLAG_LOWMED, (intr_handler_t) _dcd_int_handler, NULL, &usb_ih);
|
||||
}
|
||||
|
||||
void dcd_int_disable (uint8_t rhport)
|
||||
{
|
||||
(void) rhport;
|
||||
esp_intr_free(usb_ih);
|
||||
}
|
||||
|
||||
#endif // #if OPT_MCU_ESP32S2 || OPT_MCU_ESP32S3
|
||||
@ -31,7 +31,7 @@
|
||||
|
||||
// Version is release as major.minor.revision eg 1.0.0
|
||||
#define TUSB_VERSION_MAJOR 0
|
||||
#define TUSB_VERSION_MINOR 18
|
||||
#define TUSB_VERSION_MINOR 19
|
||||
#define TUSB_VERSION_REVISION 0
|
||||
|
||||
#define TUSB_VERSION_NUMBER (TUSB_VERSION_MAJOR * 10000 + TUSB_VERSION_MINOR * 100 + TUSB_VERSION_REVISION)
|
||||
|
||||
@ -74,7 +74,7 @@ def ListPath(path, blacklist=[]):
|
||||
print('</group>')
|
||||
|
||||
def List():
|
||||
ListPath('src', [ 'template.c', 'dcd_synopsys.c', 'dcd_esp32sx.c' ])
|
||||
ListPath('src', [ 'template.c' ])
|
||||
ListPath('lib/SEGGER_RTT')
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
import re
|
||||
import gen_doc
|
||||
|
||||
version = '0.18.0'
|
||||
version = '0.19.0'
|
||||
|
||||
print('version {}'.format(version))
|
||||
ver_id = version.split('.')
|
||||
|
||||
Reference in New Issue
Block a user