summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZixun LI <[email protected]>2026-05-23 21:12:30 +0200
committerGitHub <[email protected]>2026-05-23 21:12:30 +0200
commit65fb8dfbadbb0b5970a1e984c290b5d6a5bcb315 (patch)
tree070990b12b8bf13b27873dad44515a04653aae70
parent4c87db341e4af7d53ce9cbbdf693593a520dc538 (diff)
parent311fb46eb2f963254af6ab206b74828a0ba0273c (diff)
Merge pull request #3622 from mickabrig7/master
fix(dcd_ch32_usbfs): fix dropped bulk OUT packets by properly re-arming EP_RX_CTRL state
-rwxr-xr-xexamples/device/audio_4_channel_mic/src/plot_audio_samples.py49
-rw-r--r--examples/device/audio_4_channel_mic/src/usb_descriptors.c4
-rwxr-xr-xexamples/device/audio_4_channel_mic_freertos/src/plot_audio_samples.py50
-rwxr-xr-xexamples/device/audio_test/src/plot_audio_samples.py50
-rw-r--r--examples/device/audio_test/src/usb_descriptors.c4
-rwxr-xr-xexamples/device/audio_test_freertos/src/plot_audio_samples.py50
-rwxr-xr-xexamples/device/audio_test_multi_rate/src/plot_audio_samples.py50
-rw-r--r--examples/device/audio_test_multi_rate/src/usb_descriptors.c4
-rw-r--r--examples/device/cdc_msc_throughput/CMakePresets.json6
-rw-r--r--examples/device/net_lwip_webserver/src/tusb_config.h2
-rw-r--r--hw/bsp/ch32v10x/linker/ch32v10x.ld23
-rw-r--r--hw/bsp/ch32v20x/family.cmake3
-rw-r--r--hw/bsp/ch32v20x/linker/ch32v20x.ld23
-rw-r--r--hw/bsp/ch32v30x/linker/ch32v30x.ld24
-rw-r--r--src/common/tusb_mcu.h10
-rw-r--r--src/portable/wch/dcd_ch32_usbfs.c199
-rw-r--r--src/portable/wch/dcd_ch32_usbhs.c434
17 files changed, 644 insertions, 341 deletions
diff --git a/examples/device/audio_4_channel_mic/src/plot_audio_samples.py b/examples/device/audio_4_channel_mic/src/plot_audio_samples.py
index 4d61e7f5e..618745934 100755
--- a/examples/device/audio_4_channel_mic/src/plot_audio_samples.py
+++ b/examples/device/audio_4_channel_mic/src/plot_audio_samples.py
@@ -4,6 +4,51 @@ import matplotlib.pyplot as plt
import numpy as np
import platform
+
+def find_windows_input_device(name_hint, channels, preferred_apis=None):
+ """Pick a Windows input device index from query_devices() output."""
+ preferred_apis = preferred_apis or []
+ name_hint = name_hint.lower()
+ candidates = []
+
+ for index in range(len(sd.query_devices())):
+ device_info = sd.query_devices(index)
+ max_input_channels = int(device_info.get('max_input_channels', 0))
+
+ if max_input_channels < channels:
+ continue
+
+ device_name = str(device_info.get('name', '')).lower()
+ if name_hint not in device_name:
+ continue
+
+ score = 0
+
+ # Prefer exact channel matches to avoid selecting a different stream layout.
+ if max_input_channels == channels:
+ score += 100
+ else:
+ score += 10
+
+ hostapi_index = int(device_info.get('hostapi', -1))
+ api_name = ''
+ if hostapi_index >= 0:
+ api_name = str(sd.query_hostapis(hostapi_index)).lower()
+
+ for priority, api_hint in enumerate(preferred_apis):
+ if api_hint in api_name:
+ score += 50 - priority
+ break
+
+ candidates.append((score, index))
+
+ if not candidates:
+ raise ValueError(
+ 'No input device matching hint="{}" with at least {} channels'.format(name_hint, channels)
+ )
+
+ return max(candidates, key=lambda item: item[0])[1]
+
if __name__ == '__main__':
# If you got "ValueError: No input device matching", that is because your PC name example device
@@ -14,8 +59,8 @@ if __name__ == '__main__':
duration = 1 # Duration of recording
if platform.system() == 'Windows':
- # WDM-KS is needed since there are more than one MicNode device APIs (at least in Windows)
- device = 'Microphone (MicNode_4_Ch), Windows WASAPI'
+ # Match by substring to support names like "Microphone (2- MicNode_4_Ch)".
+ device = find_windows_input_device('micnode_4_ch', channels=4, preferred_apis=['wasapi', 'wdm-ks', 'mme'])
elif platform.system() == 'Darwin':
device = 'MicNode_4_Ch'
else:
diff --git a/examples/device/audio_4_channel_mic/src/usb_descriptors.c b/examples/device/audio_4_channel_mic/src/usb_descriptors.c
index 2380ea0ae..6b9a9bbae 100644
--- a/examples/device/audio_4_channel_mic/src/usb_descriptors.c
+++ b/examples/device/audio_4_channel_mic/src/usb_descriptors.c
@@ -95,6 +95,10 @@ enum
// Put audio iso on EP>=8 so the 2048/4096-byte FIFOs can back double packet buffering
#define EPNUM_AUDIO 0x0A
+#elif TU_CHECK_MCU(OPT_MCU_CH32V20X, OPT_MCU_CH32V307)
+ // Only EP3 is available for ISO
+ #define EPNUM_AUDIO 0x03
+
#else
#define EPNUM_AUDIO 0x01
#endif
diff --git a/examples/device/audio_4_channel_mic_freertos/src/plot_audio_samples.py b/examples/device/audio_4_channel_mic_freertos/src/plot_audio_samples.py
index 4d5ca28d6..3b3cd0d83 100755
--- a/examples/device/audio_4_channel_mic_freertos/src/plot_audio_samples.py
+++ b/examples/device/audio_4_channel_mic_freertos/src/plot_audio_samples.py
@@ -4,6 +4,52 @@ import matplotlib.pyplot as plt
import numpy as np
import platform
+
+def find_windows_input_device(name_hint, channels, preferred_apis=None):
+ """Pick a Windows input device index from query_devices() output."""
+ preferred_apis = preferred_apis or []
+ name_hint = name_hint.lower()
+ candidates = []
+
+ for index in range(len(sd.query_devices())):
+ device_info = sd.query_devices(index)
+ max_input_channels = int(device_info.get('max_input_channels', 0))
+
+ if max_input_channels < channels:
+ continue
+
+ device_name = str(device_info.get('name', '')).lower()
+ if name_hint not in device_name:
+ continue
+
+ score = 0
+
+ # Prefer exact channel matches to avoid selecting a different stream layout.
+ if max_input_channels == channels:
+ score += 100
+ else:
+ score += 10
+
+ hostapi_index = int(device_info.get('hostapi', -1))
+ api_name = ''
+ if hostapi_index >= 0:
+ hostapi_info = sd.query_hostapis(hostapi_index)
+ api_name = str(hostapi_info.get('name', '')).lower()
+
+ for priority, api_hint in enumerate(preferred_apis):
+ if api_hint in api_name:
+ score += 50 - priority
+ break
+
+ candidates.append((score, index))
+
+ if not candidates:
+ raise ValueError(
+ 'No input device matching hint="{}" with at least {} channels'.format(name_hint, channels)
+ )
+
+ return max(candidates, key=lambda item: item[0])[1]
+
if __name__ == '__main__':
# If you got "ValueError: No input device matching", that is because your PC name example device
@@ -14,8 +60,8 @@ if __name__ == '__main__':
duration = 100e-3 # Duration of recording
if platform.system() == 'Windows':
- # WDM-KS is needed since there are more than one MicNode device APIs (at least in Windows)
- device = 'Microphone (MicNode_4_Ch), Windows WDM-KS'
+ # Match by substring to support names like "Microphone (2- MicNode_4_Ch)".
+ device = find_windows_input_device('micnode_4_ch', channels=4, preferred_apis=['wdm-ks', 'wasapi', 'mme'])
elif platform.system() == 'Darwin':
device = 'MicNode_4_Ch'
else:
diff --git a/examples/device/audio_test/src/plot_audio_samples.py b/examples/device/audio_test/src/plot_audio_samples.py
index 2be8948ea..af01b7b3e 100755
--- a/examples/device/audio_test/src/plot_audio_samples.py
+++ b/examples/device/audio_test/src/plot_audio_samples.py
@@ -5,6 +5,52 @@ import numpy as np
import platform
import csv
+
+def find_windows_input_device(name_hint, channels, preferred_apis=None):
+ """Pick a Windows input device index from query_devices() output."""
+ preferred_apis = preferred_apis or []
+ name_hint = name_hint.lower()
+ candidates = []
+
+ for index in range(len(sd.query_devices())):
+ device_info = sd.query_devices(index)
+ max_input_channels = int(device_info.get('max_input_channels', 0))
+
+ if max_input_channels < channels:
+ continue
+
+ device_name = str(device_info.get('name', '')).lower()
+ if name_hint not in device_name:
+ continue
+
+ score = 0
+
+ # Prefer exact channel matches (for example 1ch source over a 4ch source).
+ if max_input_channels == channels:
+ score += 100
+ else:
+ score += 10
+
+ hostapi_index = int(device_info.get('hostapi', -1))
+ api_name = ''
+ if hostapi_index >= 0:
+ hostapi_info = sd.query_hostapis(hostapi_index)
+ api_name = str(hostapi_info.get('name', '')).lower()
+
+ for priority, api_hint in enumerate(preferred_apis):
+ if api_hint in api_name:
+ score += 50 - priority
+ break
+
+ candidates.append((score, index))
+
+ if not candidates:
+ raise ValueError(
+ 'No input device matching hint="{}" with at least {} channels'.format(name_hint, channels)
+ )
+
+ return max(candidates, key=lambda item: item[0])[1]
+
if __name__ == '__main__':
# If you got "ValueError: No input device matching", that is because your PC name example device
@@ -15,8 +61,8 @@ if __name__ == '__main__':
duration = 3 # Duration of recording
if platform.system() == 'Windows':
- # MME is needed since there are more than one MicNode device APIs (at least in Windows)
- device = 'Microphone (MicNode), Windows WASAPI'
+ # Match by substring to support names like "Microphone (2- MicNode)".
+ device = find_windows_input_device('micnode', channels=1, preferred_apis=['wasapi', 'mme', 'wdm-ks'])
elif platform.system() == 'Darwin':
device = 'MicNode'
else:
diff --git a/examples/device/audio_test/src/usb_descriptors.c b/examples/device/audio_test/src/usb_descriptors.c
index 37ebf84d3..cea4eb8d1 100644
--- a/examples/device/audio_test/src/usb_descriptors.c
+++ b/examples/device/audio_test/src/usb_descriptors.c
@@ -95,6 +95,10 @@ enum
// Put audio iso on EP>=8 so the 2048/4096-byte FIFOs can back double packet buffering
#define EPNUM_AUDIO 0x0A
+#elif TU_CHECK_MCU(OPT_MCU_CH32V20X, OPT_MCU_CH32V307)
+ // Only EP3 is available for ISO
+ #define EPNUM_AUDIO 0x03
+
#else
#define EPNUM_AUDIO 0x01
#endif
diff --git a/examples/device/audio_test_freertos/src/plot_audio_samples.py b/examples/device/audio_test_freertos/src/plot_audio_samples.py
index b6d8e824b..b6a916be4 100755
--- a/examples/device/audio_test_freertos/src/plot_audio_samples.py
+++ b/examples/device/audio_test_freertos/src/plot_audio_samples.py
@@ -4,6 +4,52 @@ import matplotlib.pyplot as plt
import numpy as np
import platform
+
+def find_windows_input_device(name_hint, channels, preferred_apis=None):
+ """Pick a Windows input device index from query_devices() output."""
+ preferred_apis = preferred_apis or []
+ name_hint = name_hint.lower()
+ candidates = []
+
+ for index in range(len(sd.query_devices())):
+ device_info = sd.query_devices(index)
+ max_input_channels = int(device_info.get('max_input_channels', 0))
+
+ if max_input_channels < channels:
+ continue
+
+ device_name = str(device_info.get('name', '')).lower()
+ if name_hint not in device_name:
+ continue
+
+ score = 0
+
+ # Prefer exact channel matches (for example 1ch source over a 4ch source).
+ if max_input_channels == channels:
+ score += 100
+ else:
+ score += 10
+
+ hostapi_index = int(device_info.get('hostapi', -1))
+ api_name = ''
+ if hostapi_index >= 0:
+ hostapi_info = sd.query_hostapis(hostapi_index)
+ api_name = str(hostapi_info.get('name', '')).lower()
+
+ for priority, api_hint in enumerate(preferred_apis):
+ if api_hint in api_name:
+ score += 50 - priority
+ break
+
+ candidates.append((score, index))
+
+ if not candidates:
+ raise ValueError(
+ 'No input device matching hint="{}" with at least {} channels'.format(name_hint, channels)
+ )
+
+ return max(candidates, key=lambda item: item[0])[1]
+
if __name__ == '__main__':
# If you got "ValueError: No input device matching", that is because your PC name example device
@@ -14,8 +60,8 @@ if __name__ == '__main__':
duration = 3 # Duration of recording
if platform.system() == 'Windows':
- # MME is needed since there are more than one MicNode device APIs (at least in Windows)
- device = 'Microphone (MicNode), Windows WASAPI'
+ # Match by substring to support names like "Microphone (2- MicNode)".
+ device = find_windows_input_device('micnode', channels=1, preferred_apis=['wasapi', 'mme', 'wdm-ks'])
elif platform.system() == 'Darwin':
device = 'MicNode'
else:
diff --git a/examples/device/audio_test_multi_rate/src/plot_audio_samples.py b/examples/device/audio_test_multi_rate/src/plot_audio_samples.py
index 1f33a003e..f35cfa311 100755
--- a/examples/device/audio_test_multi_rate/src/plot_audio_samples.py
+++ b/examples/device/audio_test_multi_rate/src/plot_audio_samples.py
@@ -5,6 +5,52 @@ import numpy as np
import platform
import csv
+
+def find_windows_input_device(name_hint, channels, preferred_apis=None):
+ """Pick a Windows input device index from query_devices() output."""
+ preferred_apis = preferred_apis or []
+ name_hint = name_hint.lower()
+ candidates = []
+
+ for index in range(len(sd.query_devices())):
+ device_info = sd.query_devices(index)
+ max_input_channels = int(device_info.get('max_input_channels', 0))
+
+ if max_input_channels < channels:
+ continue
+
+ device_name = str(device_info.get('name', '')).lower()
+ if name_hint not in device_name:
+ continue
+
+ score = 0
+
+ # Prefer exact channel matches (for example 1ch source over a 4ch source).
+ if max_input_channels == channels:
+ score += 100
+ else:
+ score += 10
+
+ hostapi_index = int(device_info.get('hostapi', -1))
+ api_name = ''
+ if hostapi_index >= 0:
+ hostapi_info = sd.query_hostapis(hostapi_index)
+ api_name = str(hostapi_info.get('name', '')).lower()
+
+ for priority, api_hint in enumerate(preferred_apis):
+ if api_hint in api_name:
+ score += 50 - priority
+ break
+
+ candidates.append((score, index))
+
+ if not candidates:
+ raise ValueError(
+ 'No input device matching hint="{}" with at least {} channels'.format(name_hint, channels)
+ )
+
+ return max(candidates, key=lambda item: item[0])[1]
+
if __name__ == '__main__':
# If you got "ValueError: No input device matching", that is because your PC name example device
@@ -15,8 +61,8 @@ if __name__ == '__main__':
duration = 100e-3 # Duration of recording
if platform.system() == 'Windows':
- # MME is needed since there are more than one MicNode device APIs (at least in Windows)
- device = 'Microphone (MicNode) MME'
+ # Match by substring to support names like "Microphone (2- MicNode)".
+ device = find_windows_input_device('micnode', channels=1, preferred_apis=['mme', 'wasapi', 'wdm-ks'])
elif platform.system() == 'Darwin':
device = 'MicNode'
else:
diff --git a/examples/device/audio_test_multi_rate/src/usb_descriptors.c b/examples/device/audio_test_multi_rate/src/usb_descriptors.c
index 31333dcd3..b1f60dd10 100644
--- a/examples/device/audio_test_multi_rate/src/usb_descriptors.c
+++ b/examples/device/audio_test_multi_rate/src/usb_descriptors.c
@@ -92,6 +92,10 @@ enum {
// Put audio iso on EP>=8 so the 2048/4096-byte FIFOs can back double packet buffering
#define EPNUM_AUDIO 0x0A
+#elif TU_CHECK_MCU(OPT_MCU_CH32V20X, OPT_MCU_CH32V307)
+ // Only EP3 is available for ISO
+ #define EPNUM_AUDIO 0x03
+
#else
#define EPNUM_AUDIO 0x01
#endif
diff --git a/examples/device/cdc_msc_throughput/CMakePresets.json b/examples/device/cdc_msc_throughput/CMakePresets.json
new file mode 100644
index 000000000..5cd8971e9
--- /dev/null
+++ b/examples/device/cdc_msc_throughput/CMakePresets.json
@@ -0,0 +1,6 @@
+{
+ "version": 6,
+ "include": [
+ "../../../hw/bsp/BoardPresets.json"
+ ]
+}
diff --git a/examples/device/net_lwip_webserver/src/tusb_config.h b/examples/device/net_lwip_webserver/src/tusb_config.h
index aff75866d..c594d1ebd 100644
--- a/examples/device/net_lwip_webserver/src/tusb_config.h
+++ b/examples/device/net_lwip_webserver/src/tusb_config.h
@@ -103,7 +103,7 @@ extern "C" {
TU_CHECK_MCU(OPT_MCU_STM32F2, OPT_MCU_STM32F4, OPT_MCU_STM32F7) || \
TU_CHECK_MCU(OPT_MCU_STM32H5, OPT_MCU_STM32H7, OPT_MCU_STM32H7RS) || \
TU_CHECK_MCU(OPT_MCU_STM32U5, OPT_MCU_STM32N6) || \
- TU_CHECK_MCU(OPT_MCU_RP2040) || \
+ TU_CHECK_MCU(OPT_MCU_RP2040, OPT_MCU_CH32V307) || \
TU_CHECK_MCU(OPT_MCU_MIMXRT1XXX) || \
TU_CHECK_MCU(OPT_MCU_NRF5X)
#define LWIP_HIGH_THROUGHPUT 1
diff --git a/hw/bsp/ch32v10x/linker/ch32v10x.ld b/hw/bsp/ch32v10x/linker/ch32v10x.ld
index cd5c8dc17..a2de3c25f 100644
--- a/hw/bsp/ch32v10x/linker/ch32v10x.ld
+++ b/hw/bsp/ch32v10x/linker/ch32v10x.ld
@@ -13,6 +13,7 @@ ENTRY( _start )
__stack_size = 2048;
PROVIDE( _stack_size = __stack_size );
+_estack = ORIGIN(RAM) + LENGTH(RAM);
SECTIONS
{
@@ -150,16 +151,16 @@ SECTIONS
PROVIDE( _ebss = .);
} >RAM AT>FLASH
- PROVIDE( _end = _ebss);
- PROVIDE( end = . );
-
- .stack ORIGIN(RAM) + LENGTH(RAM) - __stack_size :
- {
- PROVIDE( _heap_end = . );
- . = ALIGN(4);
- PROVIDE(_susrstack = . );
- . = . + __stack_size;
- PROVIDE( _eusrstack = .);
- } >RAM
+ ._user_heap_stack :
+ {
+ . = ALIGN(8);
+ PROVIDE( end = . );
+ PROVIDE( _end = . );
+ . = . + __stack_size;
+ . = ALIGN(8);
+ } >RAM
+ PROVIDE( _heap_end = ORIGIN(RAM) + LENGTH(RAM) - __stack_size );
+ PROVIDE( _susrstack = _heap_end );
+ PROVIDE( _eusrstack = ORIGIN(RAM) + LENGTH(RAM) );
}
diff --git a/hw/bsp/ch32v20x/family.cmake b/hw/bsp/ch32v20x/family.cmake
index 59a96f70d..785f5ee35 100644
--- a/hw/bsp/ch32v20x/family.cmake
+++ b/hw/bsp/ch32v20x/family.cmake
@@ -61,8 +61,9 @@ function(family_add_board BOARD_TARGET)
if (RHPORT_DEVICE EQUAL 0)
target_compile_definitions(${BOARD_TARGET} PUBLIC CFG_TUD_WCH_USBIP_FSDEV=1)
+ target_compile_definitions(${BOARD_TARGET} PUBLIC CFG_TUH_WCH_USBIP_FSDEV=1)
elseif (RHPORT_DEVICE EQUAL 1)
- target_compile_definitions(${BOARD_TARGET} PUBLIC CFG_TUH_WCH_USBIP_USBFS=1)
+ target_compile_definitions(${BOARD_TARGET} PUBLIC CFG_TUD_WCH_USBIP_USBFS=1)
else()
message(FATAL_ERROR "Invalid RHPORT_DEVICE ${RHPORT_DEVICE}")
endif()
diff --git a/hw/bsp/ch32v20x/linker/ch32v20x.ld b/hw/bsp/ch32v20x/linker/ch32v20x.ld
index f84808b0d..bfa9a8436 100644
--- a/hw/bsp/ch32v20x/linker/ch32v20x.ld
+++ b/hw/bsp/ch32v20x/linker/ch32v20x.ld
@@ -12,6 +12,7 @@ MEMORY
ENTRY( _start )
PROVIDE( _stack_size = __stack_size );
+_estack = ORIGIN(RAM) + LENGTH(RAM);
SECTIONS
{
@@ -149,16 +150,16 @@ SECTIONS
PROVIDE( _ebss = .);
} >RAM AT>FLASH
- PROVIDE( _end = _ebss);
- PROVIDE( end = . );
-
- .stack ORIGIN(RAM) + LENGTH(RAM) - __stack_size :
- {
- PROVIDE( _heap_end = . );
- . = ALIGN(4);
- PROVIDE(_susrstack = . );
- . = . + __stack_size;
- PROVIDE( _eusrstack = .);
- } >RAM
+ ._user_heap_stack :
+ {
+ . = ALIGN(8);
+ PROVIDE( end = . );
+ PROVIDE( _end = . );
+ . = . + __stack_size;
+ . = ALIGN(8);
+ } >RAM
+ PROVIDE( _heap_end = ORIGIN(RAM) + LENGTH(RAM) - __stack_size );
+ PROVIDE( _susrstack = _heap_end );
+ PROVIDE( _eusrstack = ORIGIN(RAM) + LENGTH(RAM) );
}
diff --git a/hw/bsp/ch32v30x/linker/ch32v30x.ld b/hw/bsp/ch32v30x/linker/ch32v30x.ld
index 6dd5d344a..2941c41a0 100644
--- a/hw/bsp/ch32v30x/linker/ch32v30x.ld
+++ b/hw/bsp/ch32v30x/linker/ch32v30x.ld
@@ -12,6 +12,7 @@ MEMORY
ENTRY( _start )
PROVIDE( _stack_size = __stack_size );
+_estack = ORIGIN(RAM) + LENGTH(RAM);
SECTIONS
{
@@ -151,17 +152,16 @@ SECTIONS
PROVIDE( _ebss = .);
} >RAM AT>FLASH
- PROVIDE( _end = _ebss);
- PROVIDE( end = . );
-
- .stack ORIGIN(RAM) + LENGTH(RAM) - __stack_size :
- {
- PROVIDE( _heap_end = . );
- . = ALIGN(4);
- PROVIDE(_susrstack = . );
- . = . + __stack_size;
- PROVIDE( _eusrstack = .);
- __freertos_irq_stack_top = .;
- } >RAM
+ ._user_heap_stack :
+ {
+ . = ALIGN(8);
+ PROVIDE( end = . );
+ PROVIDE( _end = . );
+ . = . + __stack_size;
+ . = ALIGN(8);
+ } >RAM
+ PROVIDE( _heap_end = ORIGIN(RAM) + LENGTH(RAM) - __stack_size );
+ PROVIDE( _susrstack = _heap_end );
+ PROVIDE( _eusrstack = ORIGIN(RAM) + LENGTH(RAM) );
}
diff --git a/src/common/tusb_mcu.h b/src/common/tusb_mcu.h
index c85ade4d0..413ac4850 100644
--- a/src/common/tusb_mcu.h
+++ b/src/common/tusb_mcu.h
@@ -616,10 +616,6 @@
#define CFG_TUH_WCH_USBIP_USBFS 1
#endif
- #define TUP_USBIP_FSDEV
- #define TUP_USBIP_FSDEV_CH32
- #define CFG_TUSB_FSDEV_PMA_SIZE 512u
-
// default to FSDEV for device
#if !defined(CFG_TUD_WCH_USBIP_USBFS)
#define CFG_TUD_WCH_USBIP_USBFS 0
@@ -629,6 +625,12 @@
#define CFG_TUD_WCH_USBIP_FSDEV (CFG_TUD_WCH_USBIP_USBFS ? 0 : 1)
#endif
+ #if CFG_TUD_WCH_USBIP_FSDEV
+ #define TUP_USBIP_FSDEV
+ #define TUP_USBIP_FSDEV_CH32
+ #define CFG_TUSB_FSDEV_PMA_SIZE 512u
+ #endif
+
#define TUP_DCD_ENDPOINT_MAX 8
#elif TU_CHECK_MCU(OPT_MCU_CH32V307)
diff --git a/src/portable/wch/dcd_ch32_usbfs.c b/src/portable/wch/dcd_ch32_usbfs.c
index 5cd25e33e..af0f17785 100644
--- a/src/portable/wch/dcd_ch32_usbfs.c
+++ b/src/portable/wch/dcd_ch32_usbfs.c
@@ -29,29 +29,29 @@
#if CFG_TUD_ENABLED && defined(TUP_USBIP_WCH_USBFS) && CFG_TUD_WCH_USBIP_USBFS
-#include "device/dcd.h"
-#include "ch32_usbfs_reg.h"
+ #include "device/dcd.h"
+ #include "ch32_usbfs_reg.h"
-/* private defines */
-#define EP_MAX (8)
+ /* private defines */
+ #define EP_MAX (8)
-#define EP_DMA(ep) ((&USBOTG_FS->UEP0_DMA)[ep])
-#define EP_TX_LEN(ep) ((&USBOTG_FS->UEP0_TX_LEN)[2 * ep])
-#define EP_TX_CTRL(ep) ((&USBOTG_FS->UEP0_TX_CTRL)[4 * ep])
-#define EP_RX_CTRL(ep) ((&USBOTG_FS->UEP0_RX_CTRL)[4 * ep])
+ #define EP_DMA(ep) ((&USBOTG_FS->UEP0_DMA)[ep])
+ #define EP_TX_LEN(ep) ((&USBOTG_FS->UEP0_TX_LEN)[2 * ep])
+ #define EP_TX_CTRL(ep) ((&USBOTG_FS->UEP0_TX_CTRL)[4 * ep])
+ #define EP_RX_CTRL(ep) ((&USBOTG_FS->UEP0_RX_CTRL)[4 * ep])
/* private data */
struct usb_xfer {
- bool valid;
- uint8_t* buffer;
- size_t len;
- size_t processed_len;
- size_t max_size;
+ bool valid;
+ uint8_t *buffer;
+ size_t len;
+ size_t processed_len;
+ size_t max_size;
};
static struct {
- bool ep0_tog;
- bool isochronous[EP_MAX];
+ bool ep0_tog;
+ bool isochronous[EP_MAX];
struct usb_xfer xfer[EP_MAX][2];
TU_ATTR_ALIGNED(4) uint8_t buffer[EP_MAX][2][64];
TU_ATTR_ALIGNED(4) struct {
@@ -64,7 +64,7 @@ static struct {
/* private helpers */
static void update_in(uint8_t rhport, uint8_t ep, bool force) {
- struct usb_xfer* xfer = &data.xfer[ep][TUSB_DIR_IN];
+ struct usb_xfer *xfer = &data.xfer[ep][TUSB_DIR_IN];
if (xfer->valid) {
if (force || xfer->len) {
size_t len = TU_MIN(xfer->max_size, xfer->len);
@@ -82,7 +82,7 @@ static void update_in(uint8_t rhport, uint8_t ep, bool force) {
EP_TX_LEN(ep) = len;
if (ep == 0) {
EP_TX_CTRL(0) = USBFS_EP_T_RES_ACK | (data.ep0_tog ? USBFS_EP_T_TOG : 0);
- data.ep0_tog = !data.ep0_tog;
+ data.ep0_tog = !data.ep0_tog;
} else if (data.isochronous[ep]) {
EP_TX_CTRL(ep) = (EP_TX_CTRL(ep) & ~(USBFS_EP_T_RES_MASK)) | USBFS_EP_T_RES_NYET;
} else {
@@ -90,16 +90,18 @@ static void update_in(uint8_t rhport, uint8_t ep, bool force) {
}
} else {
xfer->valid = false;
- EP_TX_CTRL(ep) = (EP_TX_CTRL(ep) & ~(USBFS_EP_T_RES_MASK)) | USBFS_EP_T_RES_NAK;
- dcd_event_xfer_complete(
- rhport, ep | TUSB_DIR_IN_MASK, xfer->processed_len,
- XFER_RESULT_SUCCESS, true);
+ if (ep == 0) {
+ EP_TX_CTRL(0) = USBFS_EP_T_RES_NAK | (data.ep0_tog ? USBFS_EP_T_TOG : 0);
+ } else if (!data.isochronous[ep]) {
+ EP_TX_CTRL(ep) = (EP_TX_CTRL(ep) & ~(USBFS_EP_T_RES_MASK)) | USBFS_EP_T_RES_NAK;
+ }
+ dcd_event_xfer_complete(rhport, ep | TUSB_DIR_IN_MASK, xfer->processed_len, XFER_RESULT_SUCCESS, true);
}
}
}
static void update_out(uint8_t rhport, uint8_t ep, size_t rx_len) {
- struct usb_xfer* xfer = &data.xfer[ep][TUSB_DIR_OUT];
+ struct usb_xfer *xfer = &data.xfer[ep][TUSB_DIR_OUT];
if (xfer->valid) {
size_t len = TU_MIN(xfer->max_size, TU_MIN(xfer->len, rx_len));
if (ep == 3) {
@@ -117,25 +119,39 @@ static void update_out(uint8_t rhport, uint8_t ep, size_t rx_len) {
}
if (ep == 0) {
- EP_RX_CTRL(0) = USBFS_EP_R_RES_ACK;
+ EP_RX_CTRL(0) = USBFS_EP_R_RES_NAK;
+ } else {
+ uint8_t rx_res =
+ data.isochronous[ep] ? USBFS_EP_R_RES_NYET : (xfer->valid ? USBFS_EP_R_RES_ACK : USBFS_EP_R_RES_NAK);
+ EP_RX_CTRL(ep) = (EP_RX_CTRL(ep) & ~USBFS_EP_R_RES_MASK) | rx_res;
}
}
}
+static void reset_ep_ctrls(void) {
+ for (uint8_t ep = 1; ep < EP_MAX; ep++) {
+ EP_DMA(ep) = (uint32_t)&data.buffer[ep][0];
+ EP_TX_LEN(ep) = 0;
+ EP_TX_CTRL(ep) = USBFS_EP_T_AUTO_TOG | USBFS_EP_T_RES_NYET;
+ EP_RX_CTRL(ep) = USBFS_EP_R_AUTO_TOG | USBFS_EP_R_RES_NYET;
+ }
+ EP_DMA(3) = (uint32_t)&data.ep3_buffer.out[0];
+}
+
/* public functions */
-bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) {
- (void) rh_init;
+bool dcd_init(uint8_t rhport, const tusb_rhport_init_t *rh_init) {
+ (void)rh_init;
// init registers
USBOTG_FS->BASE_CTRL = USBFS_CTRL_SYS_CTRL | USBFS_CTRL_INT_BUSY | USBFS_CTRL_DMA_EN;
USBOTG_FS->UDEV_CTRL = USBFS_UDEV_CTRL_PD_DIS | USBFS_UDEV_CTRL_PORT_EN;
- USBOTG_FS->DEV_ADDR = 0x00;
+ USBOTG_FS->DEV_ADDR = 0x00;
USBOTG_FS->INT_FG = 0xFF;
USBOTG_FS->INT_EN = USBFS_INT_EN_BUS_RST | USBFS_INT_EN_TRANSFER | USBFS_INT_EN_SUSPEND;
// setup endpoint 0
- EP_DMA(0) = (uint32_t) &data.buffer[0][0];
- EP_TX_LEN(0) = 0;
+ EP_DMA(0) = (uint32_t)&data.buffer[0][0];
+ EP_TX_LEN(0) = 0;
EP_TX_CTRL(0) = USBFS_EP_T_RES_NAK;
EP_RX_CTRL(0) = USBFS_EP_R_RES_ACK;
@@ -143,15 +159,9 @@ bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) {
USBOTG_FS->UEP4_1_MOD = 0xCC;
USBOTG_FS->UEP2_3_MOD = 0xCC;
USBOTG_FS->UEP5_6_MOD = 0xCC;
- USBOTG_FS->UEP7_MOD = 0x0C;
+ USBOTG_FS->UEP7_MOD = 0x0C;
- for (uint8_t ep = 1; ep < EP_MAX; ep++) {
- EP_DMA(ep) = (uint32_t) &data.buffer[ep][0];
- EP_TX_LEN(ep) = 0;
- EP_TX_CTRL(ep) = USBFS_EP_T_AUTO_TOG | USBFS_EP_T_RES_NAK;
- EP_RX_CTRL(ep) = USBFS_EP_R_AUTO_TOG | USBFS_EP_R_RES_NAK;
- }
- EP_DMA(3) = (uint32_t) &data.ep3_buffer.out[0];
+ reset_ep_ctrls();
dcd_connect(rhport);
@@ -159,15 +169,15 @@ bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) {
}
void dcd_int_handler(uint8_t rhport) {
- (void) rhport;
+ (void)rhport;
uint8_t status = USBOTG_FS->INT_FG;
if (status & USBFS_INT_FG_TRANSFER) {
- uint8_t ep = USBFS_INT_ST_MASK_UIS_ENDP(USBOTG_FS->INT_ST);
- uint8_t token = USBFS_INT_ST_MASK_UIS_TOKEN(USBOTG_FS->INT_ST);
+ uint8_t ep = USBFS_INT_ST_MASK_UIS_ENDP(USBOTG_FS->INT_ST);
+ uint8_t token = USBFS_INT_ST_MASK_UIS_TOKEN(USBOTG_FS->INT_ST);
+ uint16_t rx_len = USBOTG_FS->RX_LEN;
switch (token) {
case PID_OUT: {
- uint16_t rx_len = USBOTG_FS->RX_LEN;
update_out(rhport, ep, rx_len);
break;
}
@@ -179,24 +189,30 @@ void dcd_int_handler(uint8_t rhport) {
case PID_SETUP:
// setup clears stall
EP_TX_CTRL(0) = USBFS_EP_T_RES_NAK;
- EP_RX_CTRL(0) = USBFS_EP_R_RES_ACK;
+ data.ep0_tog = true;
+
+ const tusb_control_request_t *setup = (const tusb_control_request_t *)&data.buffer[0][TUSB_DIR_OUT][0];
+ EP_RX_CTRL(0) = (setup->wLength == 0) ? USBFS_EP_R_RES_ACK : USBFS_EP_R_RES_NAK;
- data.ep0_tog = true;
dcd_event_setup_received(rhport, &data.buffer[0][TUSB_DIR_OUT][0], true);
break;
}
USBOTG_FS->INT_FG = USBFS_INT_FG_TRANSFER;
} else if (status & USBFS_INT_FG_BUS_RST) {
- data.ep0_tog = true;
+ data.ep0_tog = true;
data.xfer[0][TUSB_DIR_OUT].max_size = 64;
- data.xfer[0][TUSB_DIR_IN].max_size = 64;
+ data.xfer[0][TUSB_DIR_IN].max_size = 64;
- //dcd_event_bus_reset(rhport, (USBOTG_FS->BASE_CTRL & USBFS_CTRL_LOW_SPEED) ? TUSB_SPEED_LOW : TUSB_SPEED_FULL, true);
- dcd_event_bus_reset(rhport, (USBOTG_FS->UDEV_CTRL & USBFS_UDEV_CTRL_LOW_SPEED) ? TUSB_SPEED_LOW : TUSB_SPEED_FULL, true);
+ // dcd_event_bus_reset(rhport, (USBOTG_FS->BASE_CTRL & USBFS_CTRL_LOW_SPEED) ? TUSB_SPEED_LOW : TUSB_SPEED_FULL,
+ // true);
+ dcd_event_bus_reset(rhport, (USBOTG_FS->UDEV_CTRL & USBFS_UDEV_CTRL_LOW_SPEED) ? TUSB_SPEED_LOW : TUSB_SPEED_FULL,
+ true);
USBOTG_FS->DEV_ADDR = 0x00;
- EP_RX_CTRL(0) = USBFS_EP_R_RES_ACK;
+ EP_RX_CTRL(0) = USBFS_EP_R_RES_ACK;
+
+ reset_ep_ctrls();
USBOTG_FS->INT_FG = USBFS_INT_FG_BUS_RST;
} else if (status & USBFS_INT_FG_SUSPEND) {
@@ -207,71 +223,62 @@ void dcd_int_handler(uint8_t rhport) {
}
void dcd_int_enable(uint8_t rhport) {
- (void) rhport;
+ (void)rhport;
NVIC_EnableIRQ(USBHD_IRQn);
}
void dcd_int_disable(uint8_t rhport) {
- (void) rhport;
+ (void)rhport;
NVIC_DisableIRQ(USBHD_IRQn);
}
void dcd_set_address(uint8_t rhport, uint8_t dev_addr) {
- (void) dev_addr;
+ (void)dev_addr;
dcd_edpt_xfer(rhport, 0x80, NULL, 0, false); // zlp status response
}
void dcd_remote_wakeup(uint8_t rhport) {
- (void) rhport;
+ (void)rhport;
// TODO optional
}
void dcd_connect(uint8_t rhport) {
- (void) rhport;
+ (void)rhport;
USBOTG_FS->BASE_CTRL |= USBFS_CTRL_DEV_PUEN;
}
void dcd_disconnect(uint8_t rhport) {
- (void) rhport;
+ (void)rhport;
USBOTG_FS->BASE_CTRL &= ~USBFS_CTRL_DEV_PUEN;
}
void dcd_sof_enable(uint8_t rhport, bool en) {
- (void) rhport;
- (void) en;
+ (void)rhport;
+ (void)en;
// TODO implement later
}
-void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const* request) {
- (void) rhport;
+void dcd_edpt0_status_complete(uint8_t rhport, const tusb_control_request_t *request) {
+ (void)rhport;
if (request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_DEVICE &&
- request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD &&
- request->bRequest == TUSB_REQ_SET_ADDRESS) {
- USBOTG_FS->DEV_ADDR = (uint8_t) request->wValue;
+ request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD && request->bRequest == TUSB_REQ_SET_ADDRESS) {
+ USBOTG_FS->DEV_ADDR = (uint8_t)request->wValue;
}
- EP_TX_CTRL(0) = USBFS_EP_T_RES_NAK;
- EP_RX_CTRL(0) = USBFS_EP_R_RES_ACK;
}
-bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const* desc_ep) {
- (void) rhport;
- uint8_t ep = tu_edpt_number(desc_ep->bEndpointAddress);
+bool dcd_edpt_open(uint8_t rhport, const tusb_desc_endpoint_t *desc_ep) {
+ (void)rhport;
+ uint8_t ep = tu_edpt_number(desc_ep->bEndpointAddress);
uint8_t dir = tu_edpt_dir(desc_ep->bEndpointAddress);
TU_ASSERT(ep < EP_MAX);
- data.isochronous[ep] = desc_ep->bmAttributes.xfer == TUSB_XFER_ISOCHRONOUS;
data.xfer[ep][dir].max_size = tu_edpt_packet_size(desc_ep);
if (ep != 0) {
if (dir == TUSB_DIR_OUT) {
- if (data.isochronous[ep]) {
- EP_RX_CTRL(ep) = USBFS_EP_R_AUTO_TOG | USBFS_EP_R_RES_NYET;
- } else {
- EP_RX_CTRL(ep) = USBFS_EP_R_AUTO_TOG | USBFS_EP_R_RES_ACK;
- }
+ EP_RX_CTRL(ep) = USBFS_EP_R_AUTO_TOG | USBFS_EP_T_RES_NAK;
} else {
- EP_TX_LEN(ep) = 0;
EP_TX_CTRL(ep) = USBFS_EP_T_AUTO_TOG | USBFS_EP_T_RES_NAK;
}
}
@@ -279,52 +286,60 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const* desc_ep) {
}
void dcd_edpt_close_all(uint8_t rhport) {
- (void) rhport;
+ (void)rhport;
// TODO optional
}
bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size) {
- (void) rhport;
- (void) ep_addr;
+ (void)rhport;
+ (void)ep_addr;
(void)largest_packet_size;
- return false;
+ uint8_t ep = tu_edpt_number(ep_addr);
+ uint8_t dir = tu_edpt_dir(ep_addr);
+
+ data.isochronous[ep] = true;
+ data.xfer[ep][dir].max_size = largest_packet_size;
+ return true;
}
bool dcd_edpt_iso_activate(uint8_t rhport, const tusb_desc_endpoint_t *desc_ep) {
(void)rhport;
(void)desc_ep;
- return false;
+ return true;
}
-bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes, bool is_isr) {
- (void) is_isr;
- (void) rhport;
- uint8_t ep = tu_edpt_number(ep_addr);
+bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes, bool is_isr) {
+ (void)is_isr;
+ (void)rhport;
+ uint8_t ep = tu_edpt_number(ep_addr);
uint8_t dir = tu_edpt_dir(ep_addr);
- struct usb_xfer* xfer = &data.xfer[ep][dir];
+ struct usb_xfer *xfer = &data.xfer[ep][dir];
dcd_int_disable(rhport);
- xfer->valid = true;
- xfer->buffer = buffer;
- xfer->len = total_bytes;
+ xfer->valid = true;
+ xfer->buffer = buffer;
+ xfer->len = total_bytes;
xfer->processed_len = 0;
dcd_int_enable(rhport);
if (dir == TUSB_DIR_IN) {
update_in(rhport, ep, true);
+ } else {
+ uint8_t rx_res = data.isochronous[ep] ? USBFS_EP_R_RES_NYET : USBFS_EP_R_RES_ACK;
+ EP_RX_CTRL(ep) = (EP_RX_CTRL(ep) & ~USBFS_EP_R_RES_MASK) | rx_res;
}
return true;
}
void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) {
- (void) rhport;
- uint8_t ep = tu_edpt_number(ep_addr);
+ (void)rhport;
+ uint8_t ep = tu_edpt_number(ep_addr);
uint8_t dir = tu_edpt_dir(ep_addr);
if (ep == 0) {
if (dir == TUSB_DIR_OUT) {
EP_RX_CTRL(0) = USBFS_EP_R_RES_STALL;
} else {
- EP_TX_LEN(0) = 0;
+ EP_TX_LEN(0) = 0;
EP_TX_CTRL(0) = USBFS_EP_T_RES_STALL;
}
} else {
@@ -337,8 +352,8 @@ void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) {
}
void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) {
- (void) rhport;
- uint8_t ep = tu_edpt_number(ep_addr);
+ (void)rhport;
+ uint8_t ep = tu_edpt_number(ep_addr);
uint8_t dir = tu_edpt_dir(ep_addr);
if (ep == 0) {
if (dir == TUSB_DIR_OUT) {
@@ -346,9 +361,9 @@ void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) {
}
} else {
if (dir == TUSB_DIR_OUT) {
- EP_RX_CTRL(ep) = (EP_RX_CTRL(ep) & ~(USBFS_EP_R_RES_MASK | USBFS_EP_R_TOG)) | USBFS_EP_R_RES_ACK;
+ EP_RX_CTRL(ep) = USBFS_EP_R_AUTO_TOG | USBFS_EP_R_RES_NAK;
} else {
- EP_TX_CTRL(ep) = (EP_TX_CTRL(ep) & ~(USBFS_EP_T_RES_MASK | USBFS_EP_T_TOG)) | USBFS_EP_T_RES_NAK;
+ EP_TX_CTRL(ep) = USBFS_EP_T_AUTO_TOG | USBFS_EP_T_RES_NAK;
}
}
}
diff --git a/src/portable/wch/dcd_ch32_usbhs.c b/src/portable/wch/dcd_ch32_usbhs.c
index 11734de37..a6dd5bb79 100644
--- a/src/portable/wch/dcd_ch32_usbhs.c
+++ b/src/portable/wch/dcd_ch32_usbhs.c
@@ -24,7 +24,6 @@
*
* This file is part of the TinyUSB stack.
*/
-
#include "tusb_option.h"
#if CFG_TUD_ENABLED && defined(TUP_USBIP_WCH_USBHS) && defined(CFG_TUD_WCH_USBIP_USBHS) && \
@@ -37,138 +36,182 @@
#define EP_MAX 16
typedef struct {
- uint8_t* buffer;
+ uint8_t *buffer;
uint16_t total_len;
uint16_t queued_len;
uint16_t max_size;
- bool is_last_packet;
- bool is_iso;
+ bool is_iso;
+ bool valid;
} xfer_ctl_t;
-typedef enum {
- EP_RESPONSE_ACK,
- EP_RESPONSE_NAK,
-} ep_response_list_t;
-
-#define XFER_CTL_BASE(_ep, _dir) &xfer_status[_ep][_dir]
+ #define XFER_CTL_BASE(_ep, _dir) &xfer_status[_ep][_dir]
static xfer_ctl_t xfer_status[EP_MAX][2];
-#define EP_TX_LEN(ep) *(volatile uint16_t *)((volatile uint16_t *)&(USBHSD->UEP0_TX_LEN) + (ep) * 2)
-#define EP_TX_CTRL(ep) *(volatile uint8_t *)((volatile uint8_t *)&(USBHSD->UEP0_TX_CTRL) + (ep) * 4)
-#define EP_RX_CTRL(ep) *(volatile uint8_t *)((volatile uint8_t *)&(USBHSD->UEP0_RX_CTRL) + (ep) * 4)
-#define EP_RX_MAX_LEN(ep) *(volatile uint16_t *)((volatile uint16_t *)&(USBHSD->UEP0_MAX_LEN) + (ep) * 2)
+ #define EP_TX_LEN(ep) *(volatile uint16_t *)((volatile uint16_t *)&(USBHSD->UEP0_TX_LEN) + (ep) * 2)
+ #define EP_TX_CTRL(ep) *(volatile uint8_t *)((volatile uint8_t *)&(USBHSD->UEP0_TX_CTRL) + (ep) * 4)
+ #define EP_RX_CTRL(ep) *(volatile uint8_t *)((volatile uint8_t *)&(USBHSD->UEP0_RX_CTRL) + (ep) * 4)
+ #define EP_RX_MAX_LEN(ep) *(volatile uint16_t *)((volatile uint16_t *)&(USBHSD->UEP0_MAX_LEN) + (ep) * 2)
-#define EP_TX_DMA_ADDR(ep) *(volatile uint32_t *)((volatile uint32_t *)&(USBHSD->UEP1_TX_DMA) + (ep - 1))
-#define EP_RX_DMA_ADDR(ep) *(volatile uint32_t *)((volatile uint32_t *)&(USBHSD->UEP1_RX_DMA) + (ep - 1))
+ #define EP_TX_DMA_ADDR(ep) *(volatile uint32_t *)((volatile uint32_t *)&(USBHSD->UEP1_TX_DMA) + (ep - 1))
+ #define EP_RX_DMA_ADDR(ep) *(volatile uint32_t *)((volatile uint32_t *)&(USBHSD->UEP1_RX_DMA) + (ep - 1))
/* Endpoint Buffer */
TU_ATTR_ALIGNED(4) static uint8_t ep0_buffer[CFG_TUD_ENDPOINT0_SIZE];
+static bool ep0_tog;
+static bool ep_data_tog[EP_MAX][2];
-static void ep_set_response_and_toggle(uint8_t ep_num, tusb_dir_t ep_dir, ep_response_list_t response_type) {
+static void set_ep_toggle(uint8_t ep_num, tusb_dir_t ep_dir, bool data1) {
if (ep_dir == TUSB_DIR_IN) {
- uint8_t response = (response_type == EP_RESPONSE_ACK) ? USBHS_EP_T_RES_ACK : USBHS_EP_T_RES_NAK;
- if (ep_num == 0) {
- if (response_type == EP_RESPONSE_ACK) {
- if (EP_TX_LEN(ep_num) == 0) {
- EP_TX_CTRL(ep_num) |= USBHS_EP_T_TOG_1;
- } else {
- EP_TX_CTRL(ep_num) ^= USBHS_EP_T_TOG_1;
- }
- }
- }
- if (xfer_status[ep_num][TUSB_DIR_IN].is_iso == true) {
- EP_TX_CTRL(ep_num) = USBHS_EP_T_AUTOTOG;
- } else {
- EP_TX_CTRL(ep_num) = (EP_TX_CTRL(ep_num) & ~(USBHS_EP_T_RES_MASK)) | response;
- }
+ EP_TX_CTRL(ep_num) = (EP_TX_CTRL(ep_num) & ~(USBHS_EP_T_TOG_MASK)) |
+ (data1 ? USBHS_EP_T_TOG_1 : USBHS_EP_T_TOG_0);
} else {
- uint8_t response = (response_type == EP_RESPONSE_ACK) ? USBHS_EP_R_RES_ACK : USBHS_EP_R_RES_NAK;
- if (ep_num == 0) {
- if (response_type == EP_RESPONSE_ACK) {
- if (xfer_status[ep_num][TUSB_DIR_OUT].queued_len == 0) {
- EP_RX_CTRL(ep_num) |= USBHS_EP_R_TOG_1;
- }
- } else {
- EP_RX_CTRL(ep_num) ^= USBHS_EP_R_TOG_1;
- }
- }
- EP_RX_CTRL(ep_num) = (EP_RX_CTRL(ep_num) & ~(USBHS_EP_R_RES_MASK)) | response;
+ EP_RX_CTRL(ep_num) = (EP_RX_CTRL(ep_num) & ~(USBHS_EP_R_TOG_MASK)) |
+ (data1 ? USBHS_EP_R_TOG_1 : USBHS_EP_R_TOG_0);
}
}
-static void xfer_data_packet(uint8_t ep_num, tusb_dir_t ep_dir, xfer_ctl_t* xfer) {
- if (ep_dir == TUSB_DIR_IN) {
- uint16_t remaining = xfer->total_len - xfer->queued_len;
- uint16_t next_tx_size = TU_MIN(remaining, xfer->max_size);
+static void queue_in_packet(uint8_t ep_num, xfer_ctl_t* xfer) {
+ uint16_t remaining = xfer->total_len - xfer->queued_len;
+ uint16_t tx_len = TU_MIN(remaining, xfer->max_size);
+
+ if (ep_num == 0) {
+ memcpy(ep0_buffer, &xfer->buffer[xfer->queued_len], tx_len);
+ } else {
+ EP_TX_DMA_ADDR(ep_num) = (uint32_t) &xfer->buffer[xfer->queued_len];
+ }
+
+ EP_TX_LEN(ep_num) = tx_len;
+ xfer->queued_len += tx_len;
+
+ if (ep_num == 0) {
+ EP_TX_CTRL(0) = USBHS_EP_T_RES_ACK | (ep0_tog ? USBHS_EP_T_TOG_1 : USBHS_EP_T_TOG_0);
+ ep0_tog = !ep0_tog;
+ } else if (xfer->is_iso) {
+ EP_TX_CTRL(ep_num) = (EP_TX_CTRL(ep_num) & ~(USBHS_EP_T_RES_MASK)) | USBHS_EP_T_RES_NYET;
+ } else {
+ set_ep_toggle(ep_num, TUSB_DIR_IN, ep_data_tog[ep_num][TUSB_DIR_IN]);
+ EP_TX_CTRL(ep_num) = (EP_TX_CTRL(ep_num) & ~(USBHS_EP_T_RES_MASK)) | USBHS_EP_T_RES_ACK;
+ }
+}
+
+static void queue_out_packet(uint8_t ep_num, xfer_ctl_t* xfer) {
+ uint16_t remaining = xfer->total_len - xfer->queued_len;
+ uint16_t rx_len = TU_MIN(remaining, xfer->max_size);
+ if (ep_num > 0) {
+ EP_RX_DMA_ADDR(ep_num) = (uint32_t) &xfer->buffer[xfer->queued_len];
+ EP_RX_MAX_LEN(ep_num) = rx_len;
+ }
+
+ if (ep_num == 0) {
+ EP_RX_CTRL(0) = (EP_RX_CTRL(0) & ~(USBHS_EP_R_RES_MASK)) | USBHS_EP_R_RES_ACK;
+ } else if (xfer->is_iso) {
+ EP_RX_CTRL(ep_num) = (EP_RX_CTRL(ep_num) & ~(USBHS_EP_R_RES_MASK)) | USBHS_EP_R_RES_NYET;
+ } else {
+ set_ep_toggle(ep_num, TUSB_DIR_OUT, ep_data_tog[ep_num][TUSB_DIR_OUT]);
+ EP_RX_CTRL(ep_num) = (EP_RX_CTRL(ep_num) & ~(USBHS_EP_R_RES_MASK)) | USBHS_EP_R_RES_ACK;
+ }
+}
+
+static void update_in(uint8_t rhport, uint8_t ep_num, bool force) {
+ xfer_ctl_t* xfer = XFER_CTL_BASE(ep_num, TUSB_DIR_IN);
+ if (!xfer->valid) {
+ return;
+ }
+
+ if (!force && ep_num != 0 && !xfer->is_iso) {
+ ep_data_tog[ep_num][TUSB_DIR_IN] = !ep_data_tog[ep_num][TUSB_DIR_IN];
+ }
+
+ if (force || (xfer->total_len > xfer->queued_len)) {
+ queue_in_packet(ep_num, xfer);
+ } else {
+ xfer->valid = false;
if (ep_num == 0) {
- memcpy(ep0_buffer, &xfer->buffer[xfer->queued_len], next_tx_size);
+ EP_TX_CTRL(0) = USBHS_EP_T_RES_NAK | (ep0_tog ? USBHS_EP_T_TOG_1 : USBHS_EP_T_TOG_0);
} else {
- EP_TX_DMA_ADDR(ep_num) = (uint32_t) &xfer->buffer[xfer->queued_len];
+ EP_TX_CTRL(ep_num) = (EP_TX_CTRL(ep_num) & ~(USBHS_EP_T_RES_MASK)) | USBHS_EP_T_RES_NAK;
}
+ dcd_event_xfer_complete(rhport, ep_num | TUSB_DIR_IN_MASK, xfer->queued_len, XFER_RESULT_SUCCESS, true);
+ }
+}
- EP_TX_LEN(ep_num) = next_tx_size;
- xfer->queued_len += next_tx_size;
- if (xfer->queued_len == xfer->total_len) {
- xfer->is_last_packet = true;
- }
- if (xfer->is_iso == true) {
- /* Enable EP to generate ISA_ACT interrupt */
- USBHSD->ENDP_CONFIG |= (USBHS_EP0_T_EN << ep_num);
- }
- } else { /* TUSB_DIR_OUT */
- uint16_t left_to_receive = xfer->total_len - xfer->queued_len;
- uint16_t max_possible_rx_size = TU_MIN(xfer->max_size, left_to_receive);
+static void update_out(uint8_t rhport, uint8_t ep_num, uint16_t rx_len) {
+ xfer_ctl_t* xfer = XFER_CTL_BASE(ep_num, TUSB_DIR_OUT);
+ if (!xfer->valid) {
+ return;
+ }
+
+ uint16_t remaining = xfer->total_len - xfer->queued_len;
+ uint16_t len = TU_MIN(rx_len, TU_MIN(remaining, xfer->max_size));
+
+ if (ep_num == 0) {
+ memcpy(&xfer->buffer[xfer->queued_len], ep0_buffer, len);
+ }
+
+ xfer->queued_len += len;
+
+ if (ep_num != 0 && !xfer->is_iso) {
+ ep_data_tog[ep_num][TUSB_DIR_OUT] = !ep_data_tog[ep_num][TUSB_DIR_OUT];
+ }
- if (max_possible_rx_size == left_to_receive) {
- xfer->is_last_packet = true;
+ if ((xfer->queued_len == xfer->total_len) || (len < xfer->max_size)) {
+ xfer->valid = false;
+ if (ep_num == 0) {
+ EP_RX_CTRL(0) = (EP_RX_CTRL(0) & ~(USBHS_EP_R_RES_MASK)) | USBHS_EP_R_RES_NAK;
}
+ dcd_event_xfer_complete(rhport, ep_num, xfer->queued_len, XFER_RESULT_SUCCESS, true);
+ }
- if (ep_num > 0) {
- EP_RX_DMA_ADDR(ep_num) = (uint32_t) &xfer->buffer[xfer->queued_len];
- EP_RX_MAX_LEN(ep_num) = max_possible_rx_size;
+ if (ep_num != 0) {
+ if (xfer->valid) {
+ queue_out_packet(ep_num, xfer);
+ } else {
+ uint8_t rx_res = xfer->is_iso ? USBHS_EP_R_RES_NYET : USBHS_EP_R_RES_NAK;
+ EP_RX_CTRL(ep_num) = (EP_RX_CTRL(ep_num) & ~(USBHS_EP_R_RES_MASK)) | rx_res;
}
}
- ep_set_response_and_toggle(ep_num, ep_dir, USBHS_EP_R_RES_ACK);
}
-bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) {
- (void) rhport;
- (void) rh_init;
+bool dcd_init(uint8_t rhport, const tusb_rhport_init_t *rh_init) {
+ (void)rhport;
+ (void)rh_init;
memset(&xfer_status, 0, sizeof(xfer_status));
+ memset(ep_data_tog, 0, sizeof(ep_data_tog));
+ ep0_tog = true;
USBHSD->HOST_CTRL = 0x00;
USBHSD->HOST_CTRL = USBHS_PHY_SUSPENDM;
USBHSD->CONTROL = 0;
-#if TUD_OPT_HIGH_SPEED
+ #if TUD_OPT_HIGH_SPEED
USBHSD->CONTROL = USBHS_DMA_EN | USBHS_INT_BUSY_EN | USBHS_HIGH_SPEED;
-#else
- #error OPT_MODE_FULL_SPEED not currently supported on CH32
+ #else
+ #error OPT_MODE_FULL_SPEED not currently supported on CH32
USBHSD->CONTROL = USBHS_DMA_EN | USBHS_INT_BUSY_EN | USBHS_FULL_SPEED;
-#endif
+ #endif
USBHSD->INT_EN = 0;
- USBHSD->INT_EN = USBHS_SETUP_ACT_EN | USBHS_TRANSFER_EN | USBHS_BUS_RST_EN | USBHS_SUSPEND_EN | USBHS_ISO_ACT_EN;
+ USBHSD->INT_EN = USBHS_SETUP_ACT_EN | USBHS_TRANSFER_EN | USBHS_BUS_RST_EN | USBHS_SUSPEND_EN;
USBHSD->ENDP_CONFIG = USBHS_EP0_T_EN | USBHS_EP0_R_EN;
- USBHSD->ENDP_TYPE = 0x00;
- USBHSD->BUF_MODE = 0x00;
+ USBHSD->ENDP_TYPE = 0x00;
+ USBHSD->BUF_MODE = 0x00;
for (int ep = 0; ep < EP_MAX; ep++) {
- EP_TX_LEN(ep) = 0;
- EP_TX_CTRL(ep) = USBHS_EP_T_AUTOTOG | USBHS_EP_T_RES_NAK;
- EP_RX_CTRL(ep) = USBHS_EP_R_AUTOTOG | USBHS_EP_R_RES_NAK;
+ EP_TX_LEN(ep) = 0;
+ EP_TX_CTRL(ep) = USBHS_EP_T_RES_NAK | USBHS_EP_T_TOG_0;
+ EP_RX_CTRL(ep) = USBHS_EP_R_RES_NAK | USBHS_EP_R_TOG_0;
EP_RX_MAX_LEN(ep) = 0;
}
- USBHSD->UEP0_DMA = (uint32_t) ep0_buffer;
- USBHSD->UEP0_MAX_LEN = CFG_TUD_ENDPOINT0_SIZE;
+ USBHSD->UEP0_DMA = (uint32_t)ep0_buffer;
+ USBHSD->UEP0_MAX_LEN = CFG_TUD_ENDPOINT0_SIZE;
xfer_status[0][TUSB_DIR_OUT].max_size = CFG_TUD_ENDPOINT0_SIZE;
- xfer_status[0][TUSB_DIR_IN].max_size = CFG_TUD_ENDPOINT0_SIZE;
+ xfer_status[0][TUSB_DIR_IN].max_size = CFG_TUD_ENDPOINT0_SIZE;
USBHSD->DEV_AD = 0;
USBHSD->CONTROL |= USBHS_DEV_PU_EN;
@@ -177,22 +220,24 @@ bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) {
}
void dcd_int_enable(uint8_t rhport) {
- (void) rhport;
+ (void)rhport;
NVIC_EnableIRQ(USBHS_IRQn);
}
void dcd_int_disable(uint8_t rhport) {
- (void) rhport;
+ (void)rhport;
NVIC_DisableIRQ(USBHS_IRQn);
}
void dcd_edpt_close_all(uint8_t rhport) {
- (void) rhport;
+ (void)rhport;
+
+ memset(ep_data_tog, 0, sizeof(ep_data_tog));
for (size_t ep = 1; ep < EP_MAX; ep++) {
- EP_TX_LEN(ep) = 0;
- EP_TX_CTRL(ep) = USBHS_EP_T_AUTOTOG | USBHS_EP_T_RES_NAK;
- EP_RX_CTRL(ep) = USBHS_EP_R_AUTOTOG | USBHS_EP_R_RES_NAK;
+ EP_TX_LEN(ep) = 0;
+ EP_TX_CTRL(ep) = USBHS_EP_T_RES_NAK | USBHS_EP_T_TOG_0;
+ EP_RX_CTRL(ep) = USBHS_EP_R_RES_NAK | USBHS_EP_R_TOG_0;
EP_RX_MAX_LEN(ep) = 0;
}
@@ -201,18 +246,18 @@ void dcd_edpt_close_all(uint8_t rhport) {
}
void dcd_set_address(uint8_t rhport, uint8_t dev_addr) {
- (void) dev_addr;
+ (void)dev_addr;
// Response with zlp status
dcd_edpt_xfer(rhport, 0x80, NULL, 0, false);
}
void dcd_remote_wakeup(uint8_t rhport) {
- (void) rhport;
+ (void)rhport;
}
void dcd_sof_enable(uint8_t rhport, bool en) {
- (void) rhport;
+ (void)rhport;
if (en) {
USBHSD->INT_EN |= USBHS_SOF_ACT_EN;
} else {
@@ -220,24 +265,19 @@ void dcd_sof_enable(uint8_t rhport, bool en) {
}
}
-void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const* request) {
- (void) rhport;
-
+void dcd_edpt0_status_complete(uint8_t rhport, const tusb_control_request_t *request) {
+ (void)rhport;
if (request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_DEVICE &&
- request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD &&
- request->bRequest == TUSB_REQ_SET_ADDRESS) {
- USBHSD->DEV_AD = (uint8_t) request->wValue;
+ request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD && request->bRequest == TUSB_REQ_SET_ADDRESS) {
+ USBHSD->DEV_AD = (uint8_t)request->wValue;
}
-
- EP_TX_CTRL(0) = USBHS_EP_T_RES_NAK | USBHS_EP_T_TOG_0;
- EP_RX_CTRL(0) = USBHS_EP_R_RES_NAK | USBHS_EP_R_TOG_0;
}
-bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const* desc_edpt) {
- (void) rhport;
+bool dcd_edpt_open(uint8_t rhport, const tusb_desc_endpoint_t *desc_edpt) {
+ (void)rhport;
- uint8_t const ep_num = tu_edpt_number(desc_edpt->bEndpointAddress);
- tusb_dir_t const dir = tu_edpt_dir(desc_edpt->bEndpointAddress);
+ const uint8_t ep_num = tu_edpt_number(desc_edpt->bEndpointAddress);
+ const tusb_dir_t dir = tu_edpt_dir(desc_edpt->bEndpointAddress);
TU_ASSERT(ep_num < EP_MAX);
@@ -245,13 +285,14 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const* desc_edpt) {
return true;
}
- xfer_ctl_t* xfer = XFER_CTL_BASE(ep_num, dir);
- xfer->max_size = tu_edpt_packet_size(desc_edpt);
+ xfer_ctl_t *xfer = XFER_CTL_BASE(ep_num, dir);
+ xfer->max_size = tu_edpt_packet_size(desc_edpt);
+ ep_data_tog[ep_num][dir] = false;
xfer->is_iso = (desc_edpt->bmAttributes.xfer == TUSB_XFER_ISOCHRONOUS);
if (dir == TUSB_DIR_OUT) {
USBHSD->ENDP_CONFIG |= (USBHS_EP0_R_EN << ep_num);
- EP_RX_CTRL(ep_num) = USBHS_EP_R_AUTOTOG | USBHS_EP_R_RES_NAK;
+ EP_RX_CTRL(ep_num) = USBHS_EP_R_RES_NAK | USBHS_EP_R_TOG_0;
if (xfer->is_iso == true) {
USBHSD->ENDP_TYPE |= (USBHS_EP0_R_TYP << ep_num);
}
@@ -259,31 +300,31 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const* desc_edpt) {
} else {
if (xfer->is_iso == true) {
USBHSD->ENDP_TYPE |= (USBHS_EP0_T_TYP << ep_num);
- } else {
- /* Enable all types except Isochronous to avoid ISO_ACT interrupt generation */
- USBHSD->ENDP_CONFIG |= (USBHS_EP0_T_EN << ep_num);
}
- EP_TX_LEN(ep_num) = 0;
- EP_TX_CTRL(ep_num) = USBHS_EP_T_AUTOTOG | USBHS_EP_T_RES_NAK | USBHS_EP_T_TOG_0;
+ USBHSD->ENDP_CONFIG |= (USBHS_EP0_T_EN << ep_num);
+ EP_TX_LEN(ep_num) = 0;
+ EP_TX_CTRL(ep_num) = USBHS_EP_T_RES_NAK | USBHS_EP_T_TOG_0;
}
return true;
}
void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) {
- (void) rhport;
+ (void)rhport;
- uint8_t const ep_num = tu_edpt_number(ep_addr);
- tusb_dir_t const dir = tu_edpt_dir(ep_addr);
+ const uint8_t ep_num = tu_edpt_number(ep_addr);
+ const tusb_dir_t dir = tu_edpt_dir(ep_addr);
if (dir == TUSB_DIR_OUT) {
- EP_RX_CTRL(ep_num) = USBHS_EP_R_AUTOTOG | USBHS_EP_R_RES_NAK;
+ EP_RX_CTRL(ep_num) = USBHS_EP_R_RES_NAK | USBHS_EP_R_TOG_0;
EP_RX_MAX_LEN(ep_num) = 0;
+ ep_data_tog[ep_num][TUSB_DIR_OUT] = false;
USBHSD->ENDP_TYPE &= ~(USBHS_EP0_R_TYP << ep_num);
USBHSD->ENDP_CONFIG &= ~(USBHS_EP0_R_EN << ep_num);
- } else { // TUSB_DIR_IN
- EP_TX_CTRL(ep_num) = USBHS_EP_T_AUTOTOG | USBHS_EP_T_RES_NAK | USBHS_EP_T_TOG_0;
- EP_TX_LEN(ep_num) = 0;
+ } else { // TUSB_DIR_IN
+ EP_TX_CTRL(ep_num) = USBHS_EP_T_RES_NAK | USBHS_EP_T_TOG_0;
+ EP_TX_LEN(ep_num) = 0;
+ ep_data_tog[ep_num][TUSB_DIR_IN] = false;
USBHSD->ENDP_TYPE &= ~(USBHS_EP0_T_TYP << ep_num);
USBHSD->ENDP_CONFIG &= ~(USBHS_EP0_T_EN << ep_num);
}
@@ -305,128 +346,120 @@ bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const * desc_ep)
#endif
void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) {
- (void) rhport;
+ (void)rhport;
- uint8_t const ep_num = tu_edpt_number(ep_addr);
- tusb_dir_t const dir = tu_edpt_dir(ep_addr);
+ const uint8_t ep_num = tu_edpt_number(ep_addr);
+ const tusb_dir_t dir = tu_edpt_dir(ep_addr);
if (dir == TUSB_DIR_OUT) {
EP_RX_CTRL(ep_num) = USBHS_EP_R_RES_STALL;
} else {
- EP_TX_LEN(0) = 0;
+ EP_TX_LEN(0) = 0;
EP_TX_CTRL(ep_num) = USBHS_EP_T_RES_STALL;
}
}
void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) {
- (void) rhport;
+ (void)rhport;
- uint8_t const ep_num = tu_edpt_number(ep_addr);
- tusb_dir_t const dir = tu_edpt_dir(ep_addr);
+ const uint8_t ep_num = tu_edpt_number(ep_addr);
+ const tusb_dir_t dir = tu_edpt_dir(ep_addr);
if (dir == TUSB_DIR_OUT) {
- EP_RX_CTRL(ep_num) = USBHS_EP_R_AUTOTOG | USBHS_EP_R_RES_NAK;
+ EP_RX_CTRL(ep_num) = USBHS_EP_R_RES_NAK | USBHS_EP_R_TOG_0;
+ ep_data_tog[ep_num][TUSB_DIR_OUT] = false;
} else {
- EP_TX_CTRL(ep_num) = USBHS_EP_T_AUTOTOG | USBHS_EP_R_RES_NAK;
+ EP_TX_CTRL(ep_num) = USBHS_EP_T_RES_NAK | USBHS_EP_T_TOG_0;
+ ep_data_tog[ep_num][TUSB_DIR_IN] = false;
}
}
-bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes, bool is_isr) {
- (void) is_isr;
- (void) rhport;
- uint8_t const ep_num = tu_edpt_number(ep_addr);
- tusb_dir_t const dir = tu_edpt_dir(ep_addr);
+bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes, bool is_isr) {
+ (void)is_isr;
+ (void)rhport;
+ const uint8_t ep_num = tu_edpt_number(ep_addr);
+ const tusb_dir_t dir = tu_edpt_dir(ep_addr);
+
+ xfer_ctl_t *xfer = XFER_CTL_BASE(ep_num, dir);
+ xfer->buffer = buffer;
+ xfer->total_len = total_bytes;
+ xfer->queued_len = 0;
+ xfer->valid = true;
- xfer_ctl_t* xfer = XFER_CTL_BASE(ep_num, dir);
- xfer->buffer = buffer;
- xfer->total_len = total_bytes;
- xfer->queued_len = 0;
- xfer->is_last_packet = false;
+ if (ep_num == 0 && dir == TUSB_DIR_OUT) {
+ if (total_bytes == 0) {
+ EP_RX_CTRL(0) = (EP_RX_CTRL(0) & ~(USBHS_EP_R_TOG_MASK)) | USBHS_EP_R_TOG_1;
+ } else {
+ EP_RX_CTRL(0) ^= USBHS_EP_R_TOG_1;
+ }
+ }
- xfer_data_packet(ep_num, dir, xfer);
+ if (dir == TUSB_DIR_IN) {
+ update_in(rhport, ep_num, true);
+ } else {
+ queue_out_packet(ep_num, xfer);
+ }
return true;
}
void dcd_int_handler(uint8_t rhport) {
- (void) rhport;
+ (void)rhport;
- uint8_t int_flag = USBHSD->INT_FG;
+ uint8_t int_flag = USBHSD->INT_FG;
uint8_t int_status = USBHSD->INT_ST;
- if (int_flag & (USBHS_ISO_ACT_FLAG | USBHS_TRANSFER_FLAG)) {
- uint8_t const token = int_status & MASK_UIS_TOKEN;
+ if (int_flag & USBHS_TRANSFER_FLAG) {
+ const uint8_t token = int_status & MASK_UIS_TOKEN;
+ const uint8_t ep_num = int_status & MASK_UIS_ENDP;
+ const uint16_t len = USBHSD->RX_LEN;
if (token == USBHS_TOKEN_PID_SOF) {
uint32_t frame_count = USBHSD->FRAME_NO & USBHS_FRAME_NO_NUM_MASK;
dcd_event_sof(rhport, frame_count, true);
- }else {
- uint8_t const ep_num = int_status & MASK_UIS_ENDP;
- tusb_dir_t const ep_dir = (token == USBHS_TOKEN_PID_IN) ? TUSB_DIR_IN : TUSB_DIR_OUT;
- uint8_t const ep_addr = tu_edpt_addr(ep_num, ep_dir);
- xfer_ctl_t* xfer = XFER_CTL_BASE(ep_num, ep_dir);
-
- if (token == USBHS_TOKEN_PID_OUT) {
- uint16_t rx_len = USBHSD->RX_LEN;
-
- if (ep_num == 0) {
- memcpy(&xfer->buffer[xfer->queued_len], ep0_buffer, rx_len);
- }
-
- xfer->queued_len += rx_len;
- if (rx_len < xfer->max_size) {
- xfer->is_last_packet = true;
- }
- } else if (token == USBHS_TOKEN_PID_IN) {
- if (xfer->is_iso && xfer->is_last_packet) {
- /* Disable EP to avoid ISO_ACT interrupt generation */
- USBHSD->ENDP_CONFIG &= ~(USBHS_EP0_T_EN << ep_num);
- } else {
- // Do nothing, no need to update xfer->is_last_packet, it is already updated in xfer_data_packet
- }
- }
-
- if (xfer->is_last_packet == true) {
- ep_set_response_and_toggle(ep_num, ep_dir, EP_RESPONSE_NAK);
- dcd_event_xfer_complete(0, ep_addr, xfer->queued_len, XFER_RESULT_SUCCESS, true);
- } else {
- /* prepare next part of packet to xref */
- xfer_data_packet(ep_num, ep_dir, xfer);
- }
+ } else if (token == USBHS_TOKEN_PID_OUT) {
+ update_out(rhport, ep_num, len);
+ } else if (token == USBHS_TOKEN_PID_IN) {
+ update_in(rhport, ep_num, false);
}
-
- USBHSD->INT_FG = (int_flag & (USBHS_ISO_ACT_FLAG | USBHS_TRANSFER_FLAG)); /* Clear flag */
+ USBHSD->INT_FG = (int_flag & USBHS_TRANSFER_FLAG); /* Clear flag */
} else if (int_flag & USBHS_SETUP_FLAG) {
- ep_set_response_and_toggle(0, TUSB_DIR_IN, EP_RESPONSE_NAK);
- ep_set_response_and_toggle(0, TUSB_DIR_OUT, EP_RESPONSE_NAK);
+ tusb_control_request_t const* setup =
+ (tusb_control_request_t const*) ep0_buffer;
+ ep0_tog = true;
+ EP_RX_CTRL(0) = (setup->wLength == 0) ? USBHS_EP_R_RES_ACK : USBHS_EP_R_RES_NAK;
+ EP_TX_CTRL(0) = USBHS_EP_T_RES_NAK;
+
dcd_event_setup_received(0, ep0_buffer, true);
USBHSD->INT_FG = USBHS_SETUP_FLAG; /* Clear flag */
} else if (int_flag & USBHS_BUS_RST_FLAG) {
// TODO CH32 does not detect actual speed at this time (should be known at end of reset)
// This interrupt probably triggered at start of bus reset
-// tusb_speed_t actual_speed;
-// switch(USBHSD->SPEED_TYPE & USBHS_SPEED_TYPE_MASK){
-// case USBHS_SPEED_TYPE_HIGH:
-// actual_speed = TUSB_SPEED_HIGH;
-// break;
-// case USBHS_SPEED_TYPE_FULL:
-// actual_speed = TUSB_SPEED_FULL;
-// break;
-// case USBHS_SPEED_TYPE_LOW:
-// actual_speed = TUSB_SPEED_LOW;
-// break;
-// default:
-// TU_ASSERT(0,);
-// break;
-// }
-// dcd_event_bus_reset(0, actual_speed, true);
+ // tusb_speed_t actual_speed;
+ // switch(USBHSD->SPEED_TYPE & USBHS_SPEED_TYPE_MASK){
+ // case USBHS_SPEED_TYPE_HIGH:
+ // actual_speed = TUSB_SPEED_HIGH;
+ // break;
+ // case USBHS_SPEED_TYPE_FULL:
+ // actual_speed = TUSB_SPEED_FULL;
+ // break;
+ // case USBHS_SPEED_TYPE_LOW:
+ // actual_speed = TUSB_SPEED_LOW;
+ // break;
+ // default:
+ // TU_ASSERT(0,);
+ // break;
+ // }
+ // dcd_event_bus_reset(0, actual_speed, true);
dcd_event_bus_reset(0, TUSB_SPEED_HIGH, true);
USBHSD->DEV_AD = 0;
- EP_RX_CTRL(0) = USBHS_EP_R_RES_ACK | USBHS_EP_R_TOG_0;
- EP_TX_CTRL(0) = USBHS_EP_T_RES_NAK | USBHS_EP_T_TOG_0;
+ memset(ep_data_tog, 0, sizeof(ep_data_tog));
+ ep0_tog = true;
+ EP_RX_CTRL(0) = USBHS_EP_R_RES_ACK | USBHS_EP_R_TOG_0;
+ EP_TX_CTRL(0) = USBHS_EP_T_RES_NAK | USBHS_EP_T_TOG_0;
USBHSD->INT_FG = USBHS_BUS_RST_FLAG; /* Clear flag */
} else if (int_flag & USBHS_SUSPEND_FLAG) {
@@ -434,6 +467,9 @@ void dcd_int_handler(uint8_t rhport) {
dcd_event_handler(&event, true);
USBHSD->INT_FG = USBHS_SUSPEND_FLAG; /* Clear flag */
+ } else {
+ // Unhandled interrupt
+ USBHSD->INT_FG = int_flag; /* Clear all flags */
}
}
#endif