fsdev: reorganize functions

Signed-off-by: HiFiPhile <admin@hifiphile.com>
This commit is contained in:
HiFiPhile
2025-11-24 21:03:04 +01:00
parent fb631c9a40
commit 03bd8c26d6
42 changed files with 548 additions and 484 deletions

View File

@ -13,6 +13,7 @@ mcu:MSP432E4
mcu:RX65X mcu:RX65X
mcu:RAXXX mcu:RAXXX
mcu:MAX3421 mcu:MAX3421
mcu:STM32C0
mcu:STM32F4 mcu:STM32F4
mcu:STM32F7 mcu:STM32F7
mcu:STM32H7 mcu:STM32H7

View File

@ -13,6 +13,7 @@ mcu:MSP432E4
mcu:RX65X mcu:RX65X
mcu:RAXXX mcu:RAXXX
mcu:MAX3421 mcu:MAX3421
mcu:STM32C0
mcu:STM32F4 mcu:STM32F4
mcu:STM32F7 mcu:STM32F7
mcu:STM32H7 mcu:STM32H7

View File

@ -9,6 +9,7 @@ mcu:MIMXRT11XX
mcu:MSP432E4 mcu:MSP432E4
mcu:RX65X mcu:RX65X
mcu:MAX3421 mcu:MAX3421
mcu:STM32C0
mcu:STM32F4 mcu:STM32F4
mcu:STM32F7 mcu:STM32F7
mcu:STM32H7 mcu:STM32H7

View File

@ -61,6 +61,7 @@ function(family_configure_example TARGET RTOS)
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/${AT32_FAMILY}_clock.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/${AT32_FAMILY}_clock.c
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/${AT32_FAMILY}_int.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/${AT32_FAMILY}_int.c
${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c ${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c
${TOP}/src/portable/st/stm32_fsdev/fsdev_common.c
${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}}
) )
target_include_directories(${TARGET} PUBLIC target_include_directories(${TARGET} PUBLIC

View File

@ -16,6 +16,7 @@ LDFLAGS_GCC += \
SRC_C += \ SRC_C += \
src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c \ src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c \
src/portable/st/stm32_fsdev/fsdev_common.c \
$(AT32_SDK_LIB)/drivers/src/${AT32_FAMILY}_gpio.c \ $(AT32_SDK_LIB)/drivers/src/${AT32_FAMILY}_gpio.c \
$(AT32_SDK_LIB)/drivers/src/${AT32_FAMILY}_misc.c \ $(AT32_SDK_LIB)/drivers/src/${AT32_FAMILY}_misc.c \
$(AT32_SDK_LIB)/drivers/src/${AT32_FAMILY}_usart.c \ $(AT32_SDK_LIB)/drivers/src/${AT32_FAMILY}_usart.c \

View File

@ -61,6 +61,7 @@ function(family_configure_example TARGET RTOS)
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/${AT32_FAMILY}_clock.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/${AT32_FAMILY}_clock.c
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/${AT32_FAMILY}_int.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/${AT32_FAMILY}_int.c
${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c ${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c
${TOP}/src/portable/st/stm32_fsdev/fsdev_common.c
${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}}
) )
target_include_directories(${TARGET} PUBLIC target_include_directories(${TARGET} PUBLIC

View File

@ -16,6 +16,7 @@ LDFLAGS_GCC += \
SRC_C += \ SRC_C += \
src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c \ src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c \
src/portable/st/stm32_fsdev/fsdev_common.c \
$(AT32_SDK_LIB)/drivers/src/${AT32_FAMILY}_gpio.c \ $(AT32_SDK_LIB)/drivers/src/${AT32_FAMILY}_gpio.c \
$(AT32_SDK_LIB)/drivers/src/${AT32_FAMILY}_misc.c \ $(AT32_SDK_LIB)/drivers/src/${AT32_FAMILY}_misc.c \
$(AT32_SDK_LIB)/drivers/src/${AT32_FAMILY}_usart.c \ $(AT32_SDK_LIB)/drivers/src/${AT32_FAMILY}_usart.c \

View File

@ -93,6 +93,7 @@ function(family_configure_example TARGET RTOS)
${TOP}/src/portable/wch/dcd_ch32_usbfs.c ${TOP}/src/portable/wch/dcd_ch32_usbfs.c
${TOP}/src/portable/wch/hcd_ch32_usbfs.c ${TOP}/src/portable/wch/hcd_ch32_usbfs.c
${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c ${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c
${TOP}/src/portable/st/stm32_fsdev/fsdev_common.c
${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}}
) )
target_include_directories(${TARGET} PUBLIC target_include_directories(${TARGET} PUBLIC

View File

@ -47,6 +47,7 @@ SRC_C += \
src/portable/wch/dcd_ch32_usbfs.c \ src/portable/wch/dcd_ch32_usbfs.c \
src/portable/wch/hcd_ch32_usbfs.c \ src/portable/wch/hcd_ch32_usbfs.c \
src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c \ src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c \
src/portable/st/stm32_fsdev/fsdev_common.c \
$(SDK_SRC_DIR)/Core/core_riscv.c \ $(SDK_SRC_DIR)/Core/core_riscv.c \
$(SDK_SRC_DIR)/Peripheral/src/${CH32_FAMILY}_gpio.c \ $(SDK_SRC_DIR)/Peripheral/src/${CH32_FAMILY}_gpio.c \
$(SDK_SRC_DIR)/Peripheral/src/${CH32_FAMILY}_misc.c \ $(SDK_SRC_DIR)/Peripheral/src/${CH32_FAMILY}_misc.c \

View File

@ -67,6 +67,7 @@ function(family_configure_example TARGET RTOS)
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c
${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c ${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c
${TOP}/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c ${TOP}/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c
${TOP}/src/portable/st/stm32_fsdev/fsdev_common.c
${TOP}/src/portable/st/typec/typec_stm32.c ${TOP}/src/portable/st/typec/typec_stm32.c
${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}}
) )

View File

@ -30,6 +30,7 @@ LDFLAGS_GCC += \
SRC_C += \ SRC_C += \
src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c \ src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c \
src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c \ src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c \
src/portable/st/stm32_fsdev/fsdev_common.c \
$(ST_CMSIS)/Source/Templates/system_stm32$(ST_FAMILY)xx.c \ $(ST_CMSIS)/Source/Templates/system_stm32$(ST_FAMILY)xx.c \
$(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal.c \ $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal.c \
$(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_cortex.c \ $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_cortex.c \

View File

@ -65,6 +65,7 @@ function(family_configure_example TARGET RTOS)
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c
${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c ${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c
${TOP}/src/portable/st/stm32_fsdev/fsdev_common.c
${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}}
) )
target_include_directories(${TARGET} PUBLIC target_include_directories(${TARGET} PUBLIC

View File

@ -30,6 +30,7 @@ LDFLAGS_GCC += \
SRC_C += \ SRC_C += \
src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c \ src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c \
src/portable/st/stm32_fsdev/fsdev_common.c \
$(ST_CMSIS)/Source/Templates/system_stm32$(ST_FAMILY)xx.c \ $(ST_CMSIS)/Source/Templates/system_stm32$(ST_FAMILY)xx.c \
$(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal.c \ $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal.c \
$(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_cortex.c \ $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_cortex.c \

View File

@ -62,6 +62,7 @@ function(family_configure_example TARGET RTOS)
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c
${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c ${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c
${TOP}/src/portable/st/stm32_fsdev/fsdev_common.c
${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}}
) )
target_include_directories(${TARGET} PUBLIC target_include_directories(${TARGET} PUBLIC

View File

@ -27,6 +27,7 @@ LDFLAGS_GCC += \
# ------------------------ # ------------------------
SRC_C += \ SRC_C += \
src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c \ src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c \
src/portable/st/stm32_fsdev/fsdev_common.c \
${ST_CMSIS}/Source/Templates/system_stm32${ST_FAMILY}xx.c \ ${ST_CMSIS}/Source/Templates/system_stm32${ST_FAMILY}xx.c \
${ST_HAL_DRIVER}/Src/stm32${ST_FAMILY}xx_hal.c \ ${ST_HAL_DRIVER}/Src/stm32${ST_FAMILY}xx_hal.c \
${ST_HAL_DRIVER}/Src/stm32${ST_FAMILY}xx_hal_cortex.c \ ${ST_HAL_DRIVER}/Src/stm32${ST_FAMILY}xx_hal_cortex.c \

View File

@ -62,6 +62,7 @@ function(family_configure_example TARGET RTOS)
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c
${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c ${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c
${TOP}/src/portable/st/stm32_fsdev/fsdev_common.c
${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}}
) )
target_include_directories(${TARGET} PUBLIC target_include_directories(${TARGET} PUBLIC

View File

@ -19,6 +19,7 @@ LDFLAGS_GCC += \
SRC_C += \ SRC_C += \
src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c \ src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c \
src/portable/st/stm32_fsdev/fsdev_common.c \
$(ST_CMSIS)/Source/Templates/system_stm32$(ST_FAMILY)xx.c \ $(ST_CMSIS)/Source/Templates/system_stm32$(ST_FAMILY)xx.c \
$(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal.c \ $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal.c \
$(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_cortex.c \ $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_cortex.c \

View File

@ -64,6 +64,7 @@ function(family_configure_example TARGET RTOS)
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c
${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c ${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c
${TOP}/src/portable/st/stm32_fsdev/fsdev_common.c
${TOP}/src/portable/st/typec/typec_stm32.c ${TOP}/src/portable/st/typec/typec_stm32.c
${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}}
) )

View File

@ -29,6 +29,8 @@ LDFLAGS_GCC += \
SRC_C += \ SRC_C += \
src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c \ src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c \
src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c \
src/portable/st/stm32_fsdev/fsdev_common.c \
$(ST_CMSIS)/Source/Templates/system_stm32$(ST_FAMILY)xx.c \ $(ST_CMSIS)/Source/Templates/system_stm32$(ST_FAMILY)xx.c \
$(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal.c \ $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal.c \
$(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_cortex.c \ $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_cortex.c \

View File

@ -62,6 +62,7 @@ function(family_configure_example TARGET RTOS)
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c
${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c ${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c
${TOP}/src/portable/st/stm32_fsdev/fsdev_common.c
${TOP}/src/portable/st/typec/typec_stm32.c ${TOP}/src/portable/st/typec/typec_stm32.c
${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}}
) )

View File

@ -29,6 +29,7 @@ LDFLAGS_GCC += \
SRC_C += \ SRC_C += \
src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c \ src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c \
src/portable/st/stm32_fsdev/fsdev_common.c \
src/portable/st/typec/typec_stm32.c \ src/portable/st/typec/typec_stm32.c \
$(ST_CMSIS)/Source/Templates/system_stm32$(ST_FAMILY)xx.c \ $(ST_CMSIS)/Source/Templates/system_stm32$(ST_FAMILY)xx.c \
$(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal.c \ $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal.c \

View File

@ -66,6 +66,7 @@ function(family_configure_example TARGET RTOS)
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c
${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c ${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c
${TOP}/src/portable/st/stm32_fsdev/fsdev_common.c
${TOP}/src/portable/st/typec/typec_stm32.c ${TOP}/src/portable/st/typec/typec_stm32.c
${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}}
) )

View File

@ -36,6 +36,8 @@ LDFLAGS_GCC += \
SRC_C += \ SRC_C += \
src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c \ src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c \
src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c \
src/portable/st/stm32_fsdev/fsdev_common.c \
$(ST_CMSIS)/Source/Templates/system_stm32$(ST_FAMILY)xx.c \ $(ST_CMSIS)/Source/Templates/system_stm32$(ST_FAMILY)xx.c \
$(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal.c \ $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal.c \
$(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_cortex.c \ $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_cortex.c \

View File

@ -66,6 +66,7 @@ function(family_configure_example TARGET RTOS)
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c
${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c ${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c
${TOP}/src/portable/st/stm32_fsdev/fsdev_common.c
${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}}
) )
target_include_directories(${TARGET} PUBLIC target_include_directories(${TARGET} PUBLIC

View File

@ -27,6 +27,7 @@ LDFLAGS_GCC += \
SRC_C += \ SRC_C += \
src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c \ src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c \
src/portable/st/stm32_fsdev/fsdev_common.c \
$(ST_CMSIS)/Source/Templates/system_stm32$(ST_FAMILY)xx.c \ $(ST_CMSIS)/Source/Templates/system_stm32$(ST_FAMILY)xx.c \
$(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal.c \ $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal.c \
$(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_cortex.c \ $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_cortex.c \

View File

@ -67,6 +67,7 @@ function(family_configure_example TARGET RTOS)
${TOP}/src/portable/synopsys/dwc2/hcd_dwc2.c ${TOP}/src/portable/synopsys/dwc2/hcd_dwc2.c
${TOP}/src/portable/synopsys/dwc2/dwc2_common.c ${TOP}/src/portable/synopsys/dwc2/dwc2_common.c
${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c ${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c
${TOP}/src/portable/st/stm32_fsdev/fsdev_common.c
${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}}
) )
target_include_directories(${TARGET} PUBLIC target_include_directories(${TARGET} PUBLIC

View File

@ -34,6 +34,7 @@ SRC_C += \
src/portable/synopsys/dwc2/hcd_dwc2.c \ src/portable/synopsys/dwc2/hcd_dwc2.c \
src/portable/synopsys/dwc2/dwc2_common.c \ src/portable/synopsys/dwc2/dwc2_common.c \
src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c \ src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c \
src/portable/st/stm32_fsdev/fsdev_common.c \
$(ST_CMSIS)/Source/Templates/system_stm32$(ST_FAMILY)xx.c \ $(ST_CMSIS)/Source/Templates/system_stm32$(ST_FAMILY)xx.c \
$(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal.c \ $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal.c \
$(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_cortex.c \ $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_cortex.c \

View File

@ -67,6 +67,7 @@ function(family_configure_example TARGET RTOS)
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c
${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c ${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c
${TOP}/src/portable/st/stm32_fsdev/fsdev_common.c
${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}}
) )
target_include_directories(${TARGET} PUBLIC target_include_directories(${TARGET} PUBLIC

View File

@ -27,6 +27,7 @@ LDFLAGS_GCC += \
SRC_C += \ SRC_C += \
src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c \ src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c \
src/portable/st/stm32_fsdev/fsdev_common.c \
$(ST_CMSIS)/Source/Templates/system_stm32$(ST_FAMILY)xx.c \ $(ST_CMSIS)/Source/Templates/system_stm32$(ST_FAMILY)xx.c \
$(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal.c \ $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal.c \
$(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_cortex.c \ $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_cortex.c \

View File

@ -66,6 +66,8 @@ function(family_configure_example TARGET RTOS)
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c
${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c ${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c
${TOP}/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c
${TOP}/src/portable/st/stm32_fsdev/fsdev_common.c
${TOP}/src/portable/synopsys/dwc2/dcd_dwc2.c ${TOP}/src/portable/synopsys/dwc2/dcd_dwc2.c
${TOP}/src/portable/synopsys/dwc2/hcd_dwc2.c ${TOP}/src/portable/synopsys/dwc2/hcd_dwc2.c
${TOP}/src/portable/synopsys/dwc2/dwc2_common.c ${TOP}/src/portable/synopsys/dwc2/dwc2_common.c

View File

@ -39,10 +39,12 @@ SRC_C += \
ifeq ($(MCU_VARIANT),stm32u545xx) ifeq ($(MCU_VARIANT),stm32u545xx)
SRC_C += \ SRC_C += \
src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c \
src/portable/st/stm32_fsdev/fsdev_common.c
else ifeq ($(MCU_VARIANT),stm32u535xx) else ifeq ($(MCU_VARIANT),stm32u535xx)
SRC_C += \ SRC_C += \
src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c \
src/portable/st/stm32_fsdev/fsdev_common.c
else else
SRC_C += \ SRC_C += \
src/portable/synopsys/dwc2/dcd_dwc2.c \ src/portable/synopsys/dwc2/dcd_dwc2.c \

View File

@ -67,6 +67,7 @@ function(family_configure_example TARGET RTOS)
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c
${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c ${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c
${TOP}/src/portable/st/stm32_fsdev/fsdev_common.c
${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}}
) )
target_include_directories(${TARGET} PUBLIC target_include_directories(${TARGET} PUBLIC

View File

@ -20,6 +20,7 @@ LDFLAGS_GCC += -specs=nosys.specs -specs=nano.specs
SRC_C += \ SRC_C += \
src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c \ src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c \
src/portable/st/stm32_fsdev/fsdev_common.c \
$(ST_CMSIS)/Source/Templates/system_${ST_PREFIX}.c \ $(ST_CMSIS)/Source/Templates/system_${ST_PREFIX}.c \
$(ST_HAL_DRIVER)/Src/${ST_PREFIX}_hal.c \ $(ST_HAL_DRIVER)/Src/${ST_PREFIX}_hal.c \
$(ST_HAL_DRIVER)/Src/${ST_PREFIX}_hal_cortex.c \ $(ST_HAL_DRIVER)/Src/${ST_PREFIX}_hal_cortex.c \

View File

@ -18,7 +18,8 @@ if GetDepend(["PKG_TINYUSB_DEVICE_ENABLE"]):
# BSP # BSP
if GetDepend(["SOC_FAMILY_STM32"]): if GetDepend(["SOC_FAMILY_STM32"]):
src += ["../../src/portable/synopsys/dwc2/dcd_dwc2.c", src += ["../../src/portable/synopsys/dwc2/dcd_dwc2.c",
"../../src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c"] "../../src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c",
"../../src/portable/st/stm32_fsdev/fsdev_common.c"]
if GetDepend(["SOC_NRF52840"]): if GetDepend(["SOC_NRF52840"]):
src += ["../../src/portable/nordic/nrf5x/dcd_nrf5x.c"] src += ["../../src/portable/nordic/nrf5x/dcd_nrf5x.c"]

View File

@ -112,16 +112,7 @@
!(defined(TUP_USBIP_FSDEV_CH32) && CFG_TUD_WCH_USBIP_FSDEV == 0) !(defined(TUP_USBIP_FSDEV_CH32) && CFG_TUD_WCH_USBIP_FSDEV == 0)
#include "device/dcd.h" #include "device/dcd.h"
#include "fsdev_common.h"
#if defined(TUP_USBIP_FSDEV_STM32)
#include "fsdev_stm32.h"
#elif defined(TUP_USBIP_FSDEV_CH32)
#include "fsdev_ch32.h"
#elif defined(TUP_USBIP_FSDEV_AT32)
#include "fsdev_at32.h"
#else
#error "Unknown USB IP"
#endif
//--------------------------------------------------------------------+ //--------------------------------------------------------------------+
// MACRO CONSTANT TYPEDEF // MACRO CONSTANT TYPEDEF
@ -162,11 +153,6 @@ static bool edpt_xfer(uint8_t rhport, uint8_t ep_num, tusb_dir_t dir);
static uint16_t ep_buf_ptr; ///< Points to first free memory location static uint16_t ep_buf_ptr; ///< Points to first free memory location
static uint32_t dcd_pma_alloc(uint16_t len, bool dbuf); static uint32_t dcd_pma_alloc(uint16_t len, bool dbuf);
static uint8_t dcd_ep_alloc(uint8_t ep_addr, uint8_t ep_type); static uint8_t dcd_ep_alloc(uint8_t ep_addr, uint8_t ep_type);
static bool dcd_write_packet_memory(uint16_t dst, const void *__restrict src, uint16_t nbytes);
static bool dcd_read_packet_memory(void *__restrict dst, uint16_t src, uint16_t nbytes);
static bool dcd_write_packet_memory_ff(tu_fifo_t *ff, uint16_t dst, uint16_t wNBytes);
static bool dcd_read_packet_memory_ff(tu_fifo_t *ff, uint16_t src, uint16_t wNBytes);
static void edpt0_open(uint8_t rhport); static void edpt0_open(uint8_t rhport);
@ -307,7 +293,7 @@ static void handle_ctr_setup(uint32_t ep_id) {
uint16_t rx_addr = btable_get_addr(ep_id, BTABLE_BUF_RX); uint16_t rx_addr = btable_get_addr(ep_id, BTABLE_BUF_RX);
uint8_t setup_packet[8] TU_ATTR_ALIGNED(4); uint8_t setup_packet[8] TU_ATTR_ALIGNED(4);
dcd_read_packet_memory(setup_packet, rx_addr, rx_count); fsdev_read_packet_memory(setup_packet, rx_addr, rx_count);
// Clear CTR RX if another setup packet arrived before this, it will be discarded // Clear CTR RX if another setup packet arrived before this, it will be discarded
ep_write_clear_ctr(ep_id, TUSB_DIR_OUT); ep_write_clear_ctr(ep_id, TUSB_DIR_OUT);
@ -345,9 +331,9 @@ static void handle_ctr_rx(uint32_t ep_id) {
uint16_t pma_addr = (uint16_t) btable_get_addr(ep_id, buf_id); uint16_t pma_addr = (uint16_t) btable_get_addr(ep_id, buf_id);
if (xfer->ff) { if (xfer->ff) {
dcd_read_packet_memory_ff(xfer->ff, pma_addr, rx_count); fsdev_read_packet_memory_ff(xfer->ff, pma_addr, rx_count);
} else { } else {
dcd_read_packet_memory(xfer->buffer + xfer->queued_len, pma_addr, rx_count); fsdev_read_packet_memory(xfer->buffer + xfer->queued_len, pma_addr, rx_count);
} }
xfer->queued_len += rx_count; xfer->queued_len += rx_count;
@ -742,9 +728,9 @@ static void dcd_transmit_packet(xfer_ctl_t *xfer, uint16_t ep_ix) {
uint16_t addr_ptr = (uint16_t) btable_get_addr(ep_ix, buf_id); uint16_t addr_ptr = (uint16_t) btable_get_addr(ep_ix, buf_id);
if (xfer->ff) { if (xfer->ff) {
dcd_write_packet_memory_ff(xfer->ff, addr_ptr, len); fsdev_write_packet_memory_ff(xfer->ff, addr_ptr, len);
} else { } else {
dcd_write_packet_memory(addr_ptr, &(xfer->buffer[xfer->queued_len]), len); fsdev_write_packet_memory(addr_ptr, &(xfer->buffer[xfer->queued_len]), len);
} }
xfer->queued_len += len; xfer->queued_len += len;
@ -864,168 +850,4 @@ void dcd_disconnect(uint8_t rhport) {
} }
#endif #endif
//--------------------------------------------------------------------+
// PMA read/write
//--------------------------------------------------------------------+
// Write to packet memory area (PMA) from user memory
// - Packet memory must be either strictly 16-bit or 32-bit depending on FSDEV_BUS_32BIT
// - Uses unaligned for RAM (since M0 cannot access unaligned address)
static bool dcd_write_packet_memory(uint16_t dst, const void *__restrict src, uint16_t nbytes) {
if (nbytes == 0) return true;
uint32_t n_write = nbytes / FSDEV_BUS_SIZE;
fsdev_pma_buf_t* pma_buf = PMA_BUF_AT(dst);
const uint8_t *src8 = src;
while (n_write--) {
pma_buf->value = fsdevbus_unaligned_read(src8);
src8 += FSDEV_BUS_SIZE;
pma_buf++;
}
// odd bytes e.g 1 for 16-bit or 1-3 for 32-bit
uint16_t odd = nbytes & (FSDEV_BUS_SIZE - 1);
if (odd) {
fsdev_bus_t temp = 0;
for(uint16_t i = 0; i < odd; i++) {
temp |= *src8++ << (i * 8);
}
pma_buf->value = temp;
}
return true;
}
// Read from packet memory area (PMA) to user memory.
// - Packet memory must be either strictly 16-bit or 32-bit depending on FSDEV_BUS_32BIT
// - Uses unaligned for RAM (since M0 cannot access unaligned address)
static bool dcd_read_packet_memory(void *__restrict dst, uint16_t src, uint16_t nbytes) {
if (nbytes == 0) return true;
uint32_t n_read = nbytes / FSDEV_BUS_SIZE;
fsdev_pma_buf_t* pma_buf = PMA_BUF_AT(src);
uint8_t *dst8 = (uint8_t *)dst;
while (n_read--) {
fsdevbus_unaligned_write(dst8, (fsdev_bus_t ) pma_buf->value);
dst8 += FSDEV_BUS_SIZE;
pma_buf++;
}
// odd bytes e.g 1 for 16-bit or 1-3 for 32-bit
uint16_t odd = nbytes & (FSDEV_BUS_SIZE - 1);
if (odd) {
fsdev_bus_t temp = pma_buf->value;
while (odd--) {
*dst8++ = (uint8_t) (temp & 0xfful);
temp >>= 8;
}
}
return true;
}
// Write to PMA from FIFO
static bool dcd_write_packet_memory_ff(tu_fifo_t *ff, uint16_t dst, uint16_t wNBytes) {
if (wNBytes == 0) return true;
// Since we copy from a ring buffer FIFO, a wrap might occur making it necessary to conduct two copies
tu_fifo_buffer_info_t info;
tu_fifo_get_read_info(ff, &info);
uint16_t cnt_lin = tu_min16(wNBytes, info.len_lin);
uint16_t cnt_wrap = tu_min16(wNBytes - cnt_lin, info.len_wrap);
uint16_t const cnt_total = cnt_lin + cnt_wrap;
// We want to read from the FIFO and write it into the PMA, if LIN part is ODD and has WRAPPED part,
// last lin byte will be combined with wrapped part To ensure PMA is always access aligned
uint16_t lin_even = cnt_lin & ~(FSDEV_BUS_SIZE - 1);
uint16_t lin_odd = cnt_lin & (FSDEV_BUS_SIZE - 1);
uint8_t const *src8 = (uint8_t const*) info.ptr_lin;
// write even linear part
dcd_write_packet_memory(dst, src8, lin_even);
dst += lin_even;
src8 += lin_even;
if (lin_odd == 0) {
src8 = (uint8_t const*) info.ptr_wrap;
} else {
// Combine last linear bytes + first wrapped bytes to form fsdev bus width data
fsdev_bus_t temp = 0;
uint16_t i;
for(i = 0; i < lin_odd; i++) {
temp |= *src8++ << (i * 8);
}
src8 = (uint8_t const*) info.ptr_wrap;
for(; i < FSDEV_BUS_SIZE && cnt_wrap > 0; i++, cnt_wrap--) {
temp |= *src8++ << (i * 8);
}
dcd_write_packet_memory(dst, &temp, FSDEV_BUS_SIZE);
dst += FSDEV_BUS_SIZE;
}
// write the rest of the wrapped part
dcd_write_packet_memory(dst, src8, cnt_wrap);
tu_fifo_advance_read_pointer(ff, cnt_total);
return true;
}
// Read from PMA to FIFO
static bool dcd_read_packet_memory_ff(tu_fifo_t *ff, uint16_t src, uint16_t wNBytes) {
if (wNBytes == 0) return true;
// Since we copy into a ring buffer FIFO, a wrap might occur making it necessary to conduct two copies
// Check for first linear part
tu_fifo_buffer_info_t info;
tu_fifo_get_write_info(ff, &info); // We want to read from the FIFO
uint16_t cnt_lin = tu_min16(wNBytes, info.len_lin);
uint16_t cnt_wrap = tu_min16(wNBytes - cnt_lin, info.len_wrap);
uint16_t cnt_total = cnt_lin + cnt_wrap;
// We want to read from the FIFO and write it into the PMA, if LIN part is ODD and has WRAPPED part,
// last lin byte will be combined with wrapped part To ensure PMA is always access aligned
uint16_t lin_even = cnt_lin & ~(FSDEV_BUS_SIZE - 1);
uint16_t lin_odd = cnt_lin & (FSDEV_BUS_SIZE - 1);
uint8_t *dst8 = (uint8_t *) info.ptr_lin;
// read even linear part
dcd_read_packet_memory(dst8, src, lin_even);
dst8 += lin_even;
src += lin_even;
if (lin_odd == 0) {
dst8 = (uint8_t *) info.ptr_wrap;
} else {
// Combine last linear bytes + first wrapped bytes to form fsdev bus width data
fsdev_bus_t temp;
dcd_read_packet_memory(&temp, src, FSDEV_BUS_SIZE);
src += FSDEV_BUS_SIZE;
uint16_t i;
for (i = 0; i < lin_odd; i++) {
*dst8++ = (uint8_t) (temp & 0xfful);
temp >>= 8;
}
dst8 = (uint8_t *) info.ptr_wrap;
for (; i < FSDEV_BUS_SIZE && cnt_wrap > 0; i++, cnt_wrap--) {
*dst8++ = (uint8_t) (temp & 0xfful);
temp >>= 8;
}
}
// read the rest of the wrapped part
dcd_read_packet_memory(dst8, src, cnt_wrap);
tu_fifo_advance_write_pointer(ff, cnt_total);
return true;
}
#endif #endif

View File

@ -150,8 +150,6 @@
#define USB_EPRX_DTOG2 ((uint16_t)0x2000U) /*!< EndPoint RX Data TOGgle bit1 */ #define USB_EPRX_DTOG2 ((uint16_t)0x2000U) /*!< EndPoint RX Data TOGgle bit1 */
#define USB_EPRX_DTOGMASK (USB_EPRX_STAT|USB_EPREG_MASK) #define USB_EPRX_DTOGMASK (USB_EPRX_STAT|USB_EPREG_MASK)
#include "fsdev_type.h"
//--------------------------------------------------------------------+ //--------------------------------------------------------------------+
// //
//--------------------------------------------------------------------+ //--------------------------------------------------------------------+
@ -168,7 +166,7 @@ enum { FSDEV_IRQ_NUM = TU_ARRAY_SIZE(fsdev_irq) };
#error "Unsupported MCU" #error "Unsupported MCU"
#endif #endif
void fsdev_int_enable(uint8_t rhport) { TU_ATTR_ALWAYS_INLINE static inline void fsdev_int_enable(uint8_t rhport) {
(void)rhport; (void)rhport;
#if (CFG_TUSB_MCU == OPT_MCU_AT32F403A_407) || (CFG_TUSB_MCU == OPT_MCU_AT32F413) #if (CFG_TUSB_MCU == OPT_MCU_AT32F403A_407) || (CFG_TUSB_MCU == OPT_MCU_AT32F413)
// AT32F403A/407 devices allow to remap the USB interrupt vectors from // AT32F403A/407 devices allow to remap the USB interrupt vectors from
@ -187,7 +185,7 @@ void fsdev_int_enable(uint8_t rhport) {
} }
} }
void fsdev_int_disable(uint8_t rhport) { TU_ATTR_ALWAYS_INLINE static inline void fsdev_int_disable(uint8_t rhport) {
(void)rhport; (void)rhport;
#if (CFG_TUSB_MCU == OPT_MCU_AT32F403A_407) || (CFG_TUSB_MCU == OPT_MCU_AT32F413) #if (CFG_TUSB_MCU == OPT_MCU_AT32F403A_407) || (CFG_TUSB_MCU == OPT_MCU_AT32F413)
// AT32F403A/407 devices allow to remap the USB interrupt vectors from // AT32F403A/407 devices allow to remap the USB interrupt vectors from
@ -206,7 +204,7 @@ void fsdev_int_disable(uint8_t rhport) {
} }
} }
void fsdev_disconnect(uint8_t rhport) { TU_ATTR_ALWAYS_INLINE static inline void fsdev_disconnect(uint8_t rhport) {
(void) rhport; (void) rhport;
/* disable usb phy */ /* disable usb phy */
*(volatile uint32_t*)(FSDEV_REG_BASE + 0x40) |= USB_CNTR_PDWN; *(volatile uint32_t*)(FSDEV_REG_BASE + 0x40) |= USB_CNTR_PDWN;
@ -214,7 +212,7 @@ void fsdev_disconnect(uint8_t rhport) {
*(volatile uint32_t *)(FSDEV_REG_BASE+0x60) |= (1u<<1); *(volatile uint32_t *)(FSDEV_REG_BASE+0x60) |= (1u<<1);
} }
void fsdev_connect(uint8_t rhport) { TU_ATTR_ALWAYS_INLINE static inline void fsdev_connect(uint8_t rhport) {
(void) rhport; (void) rhport;
/* enable usb phy */ /* enable usb phy */
*(volatile uint32_t*)(FSDEV_REG_BASE + 0x40) &= ~USB_CNTR_PDWN; *(volatile uint32_t*)(FSDEV_REG_BASE + 0x40) &= ~USB_CNTR_PDWN;

View File

@ -168,8 +168,6 @@
#define USB_EPRX_DTOG2 ((uint16_t)0x2000U) /*!< EndPoint RX Data TOGgle bit1 */ #define USB_EPRX_DTOG2 ((uint16_t)0x2000U) /*!< EndPoint RX Data TOGgle bit1 */
#define USB_EPRX_DTOGMASK (USB_EPRX_STAT|USB_EPREG_MASK) #define USB_EPRX_DTOGMASK (USB_EPRX_STAT|USB_EPREG_MASK)
#include "fsdev_type.h"
//--------------------------------------------------------------------+ //--------------------------------------------------------------------+
// //
//--------------------------------------------------------------------+ //--------------------------------------------------------------------+
@ -185,26 +183,26 @@ enum { FSDEV_IRQ_NUM = TU_ARRAY_SIZE(fsdev_irq) };
#error "Unsupported MCU" #error "Unsupported MCU"
#endif #endif
void fsdev_int_enable(uint8_t rhport) { TU_ATTR_ALWAYS_INLINE static inline void fsdev_int_enable(uint8_t rhport) {
(void)rhport; (void)rhport;
for(uint8_t i=0; i < FSDEV_IRQ_NUM; i++) { for(uint8_t i=0; i < FSDEV_IRQ_NUM; i++) {
NVIC_EnableIRQ(fsdev_irq[i]); NVIC_EnableIRQ(fsdev_irq[i]);
} }
} }
void fsdev_int_disable(uint8_t rhport) { TU_ATTR_ALWAYS_INLINE static inline void fsdev_int_disable(uint8_t rhport) {
(void)rhport; (void)rhport;
for(uint8_t i=0; i < FSDEV_IRQ_NUM; i++) { for(uint8_t i=0; i < FSDEV_IRQ_NUM; i++) {
NVIC_DisableIRQ(fsdev_irq[i]); NVIC_DisableIRQ(fsdev_irq[i]);
} }
} }
void fsdev_disconnect(uint8_t rhport) { TU_ATTR_ALWAYS_INLINE static inline void fsdev_disconnect(uint8_t rhport) {
(void) rhport; (void) rhport;
EXTEN->EXTEN_CTR &= ~EXTEN_USBD_PU_EN; EXTEN->EXTEN_CTR &= ~EXTEN_USBD_PU_EN;
} }
void fsdev_connect(uint8_t rhport) { TU_ATTR_ALWAYS_INLINE static inline void fsdev_connect(uint8_t rhport) {
(void) rhport; (void) rhport;
EXTEN->EXTEN_CTR |= EXTEN_USBD_PU_EN; EXTEN->EXTEN_CTR |= EXTEN_USBD_PU_EN;
} }

View File

@ -0,0 +1,241 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2024 Ha Thach (tinyusb.org)
* Copyright (c) 2025, HiFiPhile (Zixun LI)
*
* 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 defined(TUP_USBIP_FSDEV) && (CFG_TUH_ENABLED || CFG_TUD_ENABLED)
#include "fsdev_common.h"
//--------------------------------------------------------------------+
// PMA read/write
//--------------------------------------------------------------------+
// Write to packet memory area (PMA) from user memory
// - Packet memory must be either strictly 16-bit or 32-bit depending on FSDEV_BUS_32BIT
// - Uses unaligned for RAM (since M0 cannot access unaligned address)
bool fsdev_write_packet_memory(uint16_t dst, const void *__restrict src, uint16_t nbytes) {
if (nbytes == 0) return true;
uint32_t n_write = nbytes / FSDEV_BUS_SIZE;
fsdev_pma_buf_t* pma_buf = PMA_BUF_AT(dst);
const uint8_t *src8 = src;
while (n_write--) {
pma_buf->value = fsdevbus_unaligned_read(src8);
src8 += FSDEV_BUS_SIZE;
pma_buf++;
}
// odd bytes e.g 1 for 16-bit or 1-3 for 32-bit
uint16_t odd = nbytes & (FSDEV_BUS_SIZE - 1);
if (odd) {
fsdev_bus_t temp = 0;
for(uint16_t i = 0; i < odd; i++) {
temp |= *src8++ << (i * 8);
}
pma_buf->value = temp;
}
return true;
}
// Read from packet memory area (PMA) to user memory.
// - Packet memory must be either strictly 16-bit or 32-bit depending on FSDEV_BUS_32BIT
// - Uses unaligned for RAM (since M0 cannot access unaligned address)
bool fsdev_read_packet_memory(void *__restrict dst, uint16_t src, uint16_t nbytes) {
if (nbytes == 0) return true;
uint32_t n_read = nbytes / FSDEV_BUS_SIZE;
fsdev_pma_buf_t* pma_buf = PMA_BUF_AT(src);
uint8_t *dst8 = (uint8_t *)dst;
while (n_read--) {
fsdevbus_unaligned_write(dst8, (fsdev_bus_t ) pma_buf->value);
dst8 += FSDEV_BUS_SIZE;
pma_buf++;
}
// odd bytes e.g 1 for 16-bit or 1-3 for 32-bit
uint16_t odd = nbytes & (FSDEV_BUS_SIZE - 1);
if (odd) {
fsdev_bus_t temp = pma_buf->value;
while (odd--) {
*dst8++ = (uint8_t) (temp & 0xfful);
temp >>= 8;
}
}
return true;
}
// Write to PMA from FIFO
bool fsdev_write_packet_memory_ff(tu_fifo_t *ff, uint16_t dst, uint16_t wNBytes) {
if (wNBytes == 0) return true;
// Since we copy from a ring buffer FIFO, a wrap might occur making it necessary to conduct two copies
tu_fifo_buffer_info_t info;
tu_fifo_get_read_info(ff, &info);
uint16_t cnt_lin = tu_min16(wNBytes, info.len_lin);
uint16_t cnt_wrap = tu_min16(wNBytes - cnt_lin, info.len_wrap);
uint16_t const cnt_total = cnt_lin + cnt_wrap;
// We want to read from the FIFO and write it into the PMA, if LIN part is ODD and has WRAPPED part,
// last lin byte will be combined with wrapped part To ensure PMA is always access aligned
uint16_t lin_even = cnt_lin & ~(FSDEV_BUS_SIZE - 1);
uint16_t lin_odd = cnt_lin & (FSDEV_BUS_SIZE - 1);
uint8_t const *src8 = (uint8_t const*) info.ptr_lin;
// write even linear part
fsdev_write_packet_memory(dst, src8, lin_even);
dst += lin_even;
src8 += lin_even;
if (lin_odd == 0) {
src8 = (uint8_t const*) info.ptr_wrap;
} else {
// Combine last linear bytes + first wrapped bytes to form fsdev bus width data
fsdev_bus_t temp = 0;
uint16_t i;
for(i = 0; i < lin_odd; i++) {
temp |= *src8++ << (i * 8);
}
src8 = (uint8_t const*) info.ptr_wrap;
for(; i < FSDEV_BUS_SIZE && cnt_wrap > 0; i++, cnt_wrap--) {
temp |= *src8++ << (i * 8);
}
fsdev_write_packet_memory(dst, &temp, FSDEV_BUS_SIZE);
dst += FSDEV_BUS_SIZE;
}
// write the rest of the wrapped part
fsdev_write_packet_memory(dst, src8, cnt_wrap);
tu_fifo_advance_read_pointer(ff, cnt_total);
return true;
}
// Read from PMA to FIFO
bool fsdev_read_packet_memory_ff(tu_fifo_t *ff, uint16_t src, uint16_t wNBytes) {
if (wNBytes == 0) return true;
// Since we copy into a ring buffer FIFO, a wrap might occur making it necessary to conduct two copies
// Check for first linear part
tu_fifo_buffer_info_t info;
tu_fifo_get_write_info(ff, &info); // We want to read from the FIFO
uint16_t cnt_lin = tu_min16(wNBytes, info.len_lin);
uint16_t cnt_wrap = tu_min16(wNBytes - cnt_lin, info.len_wrap);
uint16_t cnt_total = cnt_lin + cnt_wrap;
// We want to read from the FIFO and write it into the PMA, if LIN part is ODD and has WRAPPED part,
// last lin byte will be combined with wrapped part To ensure PMA is always access aligned
uint16_t lin_even = cnt_lin & ~(FSDEV_BUS_SIZE - 1);
uint16_t lin_odd = cnt_lin & (FSDEV_BUS_SIZE - 1);
uint8_t *dst8 = (uint8_t *) info.ptr_lin;
// read even linear part
fsdev_read_packet_memory(dst8, src, lin_even);
dst8 += lin_even;
src += lin_even;
if (lin_odd == 0) {
dst8 = (uint8_t *) info.ptr_wrap;
} else {
// Combine last linear bytes + first wrapped bytes to form fsdev bus width data
fsdev_bus_t temp;
fsdev_read_packet_memory(&temp, src, FSDEV_BUS_SIZE);
src += FSDEV_BUS_SIZE;
uint16_t i;
for (i = 0; i < lin_odd; i++) {
*dst8++ = (uint8_t) (temp & 0xfful);
temp >>= 8;
}
dst8 = (uint8_t *) info.ptr_wrap;
for (; i < FSDEV_BUS_SIZE && cnt_wrap > 0; i++, cnt_wrap--) {
*dst8++ = (uint8_t) (temp & 0xfful);
temp >>= 8;
}
}
// read the rest of the wrapped part
fsdev_read_packet_memory(dst8, src, cnt_wrap);
tu_fifo_advance_write_pointer(ff, cnt_total);
return true;
}
//--------------------------------------------------------------------+
// BTable Helper
//--------------------------------------------------------------------+
/* Aligned buffer size according to hardware */
uint16_t pma_align_buffer_size(uint16_t size, uint8_t* blsize, uint8_t* num_block) {
/* The STM32 full speed USB peripheral supports only a limited set of
* buffer sizes given by the RX buffer entry format in the USB_BTABLE. */
uint16_t block_in_bytes;
if (size > 62) {
block_in_bytes = 32;
*blsize = 1;
*num_block = tu_div_ceil(size, 32);
} else {
block_in_bytes = 2;
*blsize = 0;
*num_block = tu_div_ceil(size, 2);
}
return (*num_block) * block_in_bytes;
}
void btable_set_rx_bufsize(uint32_t ep_id, uint8_t buf_id, uint16_t wCount) {
uint8_t blsize, num_block;
(void) pma_align_buffer_size(wCount, &blsize, &num_block);
/* Encode into register. When BLSIZE==1, we need to subtract 1 block count */
uint16_t bl_nb = (blsize << 15) | ((num_block - blsize) << 10);
if (bl_nb == 0) {
// zlp but 0 is invalid value, set blsize to 1 (32 bytes)
// Note: lower value can cause PMAOVR on setup with ch32v203
bl_nb = 1 << 15;
}
#ifdef FSDEV_BUS_32BIT
uint32_t count_addr = FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr;
count_addr = (bl_nb << 16) | (count_addr & 0x0000FFFFu);
FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr = count_addr;
#else
FSDEV_BTABLE->ep16[ep_id][buf_id].count = bl_nb;
#endif
}
#endif

View File

@ -1,8 +1,9 @@
/* /*
* The MIT License (MIT) * The MIT License (MIT)
* *
* Copyright(c) N Conrad * Copyright (c) N Conrad
* Copyright(c) 2024, hathach (tinyusb.org) * Copyright (c) 2024, hathach (tinyusb.org)
* Copyright (c) 2025, HiFiPhile (Zixun LI)
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal
@ -25,14 +26,32 @@
* This file is part of the TinyUSB stack. * This file is part of the TinyUSB stack.
*/ */
#ifndef TUSB_FSDEV_TYPE_H #ifndef TUSB_FSDEV_COMMON_H
#define TUSB_FSDEV_TYPE_H #define TUSB_FSDEV_COMMON_H
#ifdef __cplusplus #include "common/tusb_common.h"
extern "C" {
#if CFG_TUD_ENABLED
#include "device/dcd.h"
#endif #endif
#include "stdint.h" #if CFG_TUH_ENABLED
#include "host/hcd.h"
#endif
#if defined(TUP_USBIP_FSDEV_STM32)
#include "fsdev_stm32.h"
#elif defined(TUP_USBIP_FSDEV_CH32)
#include "fsdev_ch32.h"
#elif defined(TUP_USBIP_FSDEV_AT32)
#include "fsdev_at32.h"
#else
#error "Unknown USB IP"
#endif
#ifdef __cplusplus
extern "C" {
#endif
// If sharing with CAN, one can set this to be non-zero to give CAN space where it wants it // If sharing with CAN, one can set this to be non-zero to give CAN space where it wants it
// Both of these MUST be a multiple of 2, and are in byte units. // Both of these MUST be a multiple of 2, and are in byte units.
@ -177,11 +196,6 @@ typedef enum {
#define CH_STAT_MASK(_dir) (3u << (USB_EPTX_STAT_Pos + ((_dir) == TUSB_DIR_IN ? 8 : 0))) #define CH_STAT_MASK(_dir) (3u << (USB_EPTX_STAT_Pos + ((_dir) == TUSB_DIR_IN ? 8 : 0)))
#define CH_DTOG_MASK(_dir) (1u << (USB_EP_DTOG_TX_Pos + ((_dir) == TUSB_DIR_IN ? 8 : 0))) #define CH_DTOG_MASK(_dir) (1u << (USB_EP_DTOG_TX_Pos + ((_dir) == TUSB_DIR_IN ? 8 : 0)))
void fsdev_int_enable(uint8_t rhport);
void fsdev_int_disable(uint8_t rhport);
void fsdev_connect(uint8_t rhport);
void fsdev_disconnect(uint8_t rhport);
//--------------------------------------------------------------------+ //--------------------------------------------------------------------+
// Endpoint Helper // Endpoint Helper
// - CTR is write 0 to clear // - CTR is write 0 to clear
@ -298,47 +312,32 @@ TU_ATTR_ALWAYS_INLINE static inline void btable_set_count(uint32_t ep_id, uint8_
} }
/* Aligned buffer size according to hardware */ /* Aligned buffer size according to hardware */
TU_ATTR_ALWAYS_INLINE static inline uint16_t pma_align_buffer_size(uint16_t size, uint8_t* blsize, uint8_t* num_block) { uint16_t pma_align_buffer_size(uint16_t size, uint8_t* blsize, uint8_t* num_block);
/* The STM32 full speed USB peripheral supports only a limited set of
* buffer sizes given by the RX buffer entry format in the USB_BTABLE. */
uint16_t block_in_bytes;
if (size > 62) {
block_in_bytes = 32;
*blsize = 1;
*num_block = tu_div_ceil(size, 32);
} else {
block_in_bytes = 2;
*blsize = 0;
*num_block = tu_div_ceil(size, 2);
}
return (*num_block) * block_in_bytes; void btable_set_rx_bufsize(uint32_t ep_id, uint8_t buf_id, uint16_t wCount);
}
TU_ATTR_ALWAYS_INLINE static inline void btable_set_rx_bufsize(uint32_t ep_id, uint8_t buf_id, uint16_t wCount) { //--------------------------------------------------------------------+
uint8_t blsize, num_block; // PMA (Packet Memory Area) Access
(void) pma_align_buffer_size(wCount, &blsize, &num_block); //--------------------------------------------------------------------+
/* Encode into register. When BLSIZE==1, we need to subtract 1 block count */ // Write to packet memory area (PMA) from user memory
uint16_t bl_nb = (blsize << 15) | ((num_block - blsize) << 10); // - Packet memory must be either strictly 16-bit or 32-bit depending on FSDEV_BUS_32BIT
if (bl_nb == 0) { // - Uses unaligned for RAM (since M0 cannot access unaligned address)
// zlp but 0 is invalid value, set blsize to 1 (32 bytes) bool fsdev_write_packet_memory(uint16_t dst, const void *__restrict src, uint16_t nbytes);
// Note: lower value can cause PMAOVR on setup with ch32v203
bl_nb = 1 << 15;
}
#ifdef FSDEV_BUS_32BIT // Read from packet memory area (PMA) to user memory.
uint32_t count_addr = FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr; // - Packet memory must be either strictly 16-bit or 32-bit depending on FSDEV_BUS_32BIT
count_addr = (bl_nb << 16) | (count_addr & 0x0000FFFFu); // - Uses unaligned for RAM (since M0 cannot access unaligned address)
FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr = count_addr; bool fsdev_read_packet_memory(void *__restrict dst, uint16_t src, uint16_t nbytes);
#else
FSDEV_BTABLE->ep16[ep_id][buf_id].count = bl_nb;
#endif
} // Write to PMA from FIFO
bool fsdev_write_packet_memory_ff(tu_fifo_t *ff, uint16_t dst, uint16_t wNBytes);
// Read from PMA to FIFO
bool fsdev_read_packet_memory_ff(tu_fifo_t *ff, uint16_t src, uint16_t wNBytes);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif #endif /* TUSB_FSDEV_COMMON_H */

View File

@ -321,8 +321,6 @@
#define FSDEV_USE_SBUF_ISO 0 #define FSDEV_USE_SBUF_ISO 0
#endif #endif
#include "fsdev_type.h"
//--------------------------------------------------------------------+ //--------------------------------------------------------------------+
// //
//--------------------------------------------------------------------+ //--------------------------------------------------------------------+
@ -374,7 +372,7 @@ static const IRQn_Type fsdev_irq[] = {
}; };
enum { FSDEV_IRQ_NUM = TU_ARRAY_SIZE(fsdev_irq) }; enum { FSDEV_IRQ_NUM = TU_ARRAY_SIZE(fsdev_irq) };
void fsdev_int_enable(uint8_t rhport) { TU_ATTR_ALWAYS_INLINE static inline void fsdev_int_enable(uint8_t rhport) {
(void)rhport; (void)rhport;
// forces write to RAM before allowing ISR to execute // forces write to RAM before allowing ISR to execute
@ -397,7 +395,7 @@ void fsdev_int_enable(uint8_t rhport) {
} }
} }
void fsdev_int_disable(uint8_t rhport) { TU_ATTR_ALWAYS_INLINE static inline void fsdev_int_disable(uint8_t rhport) {
(void)rhport; (void)rhport;
#if CFG_TUSB_MCU == OPT_MCU_STM32F3 && defined(SYSCFG_CFGR1_USB_IT_RMP) #if CFG_TUSB_MCU == OPT_MCU_STM32F3 && defined(SYSCFG_CFGR1_USB_IT_RMP)
@ -422,24 +420,24 @@ void fsdev_int_disable(uint8_t rhport) {
// Define only on MCU with internal pull-up. BSP can define on MCU without internal PU. // Define only on MCU with internal pull-up. BSP can define on MCU without internal PU.
#if defined(USB_BCDR_DPPU) #if defined(USB_BCDR_DPPU)
void fsdev_disconnect(uint8_t rhport) { TU_ATTR_ALWAYS_INLINE static inline void fsdev_disconnect(uint8_t rhport) {
(void)rhport; (void)rhport;
USB->BCDR &= ~(USB_BCDR_DPPU); USB->BCDR &= ~(USB_BCDR_DPPU);
} }
void fsdev_connect(uint8_t rhport) { TU_ATTR_ALWAYS_INLINE static inline void fsdev_connect(uint8_t rhport) {
(void)rhport; (void)rhport;
USB->BCDR |= USB_BCDR_DPPU; USB->BCDR |= USB_BCDR_DPPU;
} }
#elif defined(SYSCFG_PMC_USB_PU) // works e.g. on STM32L151 #elif defined(SYSCFG_PMC_USB_PU) // works e.g. on STM32L151
void fsdev_disconnect(uint8_t rhport) { TU_ATTR_ALWAYS_INLINE static inline void fsdev_disconnect(uint8_t rhport) {
(void)rhport; (void)rhport;
SYSCFG->PMC &= ~(SYSCFG_PMC_USB_PU); SYSCFG->PMC &= ~(SYSCFG_PMC_USB_PU);
} }
void fsdev_connect(uint8_t rhport) { TU_ATTR_ALWAYS_INLINE static inline void fsdev_connect(uint8_t rhport) {
(void)rhport; (void)rhport;
SYSCFG->PMC |= SYSCFG_PMC_USB_PU; SYSCFG->PMC |= SYSCFG_PMC_USB_PU;
} }

View File

@ -30,6 +30,7 @@
* *
* C0 2048 byte buffer; 32-bit bus; host mode * C0 2048 byte buffer; 32-bit bus; host mode
* G0 2048 byte buffer; 32-bit bus; host mode * G0 2048 byte buffer; 32-bit bus; host mode
* U3 2048 byte buffer; 32-bit bus; host mode
* H5 2048 byte buffer; 32-bit bus; host mode * H5 2048 byte buffer; 32-bit bus; host mode
* U535, U545 2048 byte buffer; 32-bit bus; host mode * U535, U545 2048 byte buffer; 32-bit bus; host mode
* *
@ -42,19 +43,14 @@
#include "host/hcd.h" #include "host/hcd.h"
#include "host/usbh.h" #include "host/usbh.h"
#include "fsdev_common.h"
#if defined(TUP_USBIP_FSDEV_STM32)
#include "fsdev_stm32.h"
#else
#error "Unknown USB IP"
#endif
//--------------------------------------------------------------------+ //--------------------------------------------------------------------+
// MACRO CONSTANT TYPEDEF // MACRO CONSTANT TYPEDEF
//--------------------------------------------------------------------+ //--------------------------------------------------------------------+
// Debug level for FSDEV // Debug level for FSDEV
#define FSDEV_DEBUG 1 #define FSDEV_DEBUG 3
// Max number of endpoints application can open, can be larger than FSDEV_EP_COUNT // Max number of endpoints application can open, can be larger than FSDEV_EP_COUNT
#ifndef CFG_TUH_FSDEV_ENDPOINT_MAX #ifndef CFG_TUH_FSDEV_ENDPOINT_MAX
@ -76,9 +72,12 @@ typedef struct {
uint8_t ep_addr; uint8_t ep_addr;
uint8_t ep_type; uint8_t ep_type;
uint8_t interval; uint8_t interval;
bool low_speed; struct TU_ATTR_PACKED {
bool allocated; uint8_t low_speed : 1;
bool next_setup; uint8_t allocated : 1;
uint8_t next_setup : 1;
uint8_t pid : 1;
};
} hcd_endpoint_t; } hcd_endpoint_t;
// Additional info for each channel when it is active // Additional info for each channel when it is active
@ -88,7 +87,7 @@ typedef struct {
uint8_t dev_addr; uint8_t dev_addr;
uint8_t ep_num; uint8_t ep_num;
uint8_t ep_type; uint8_t ep_type;
bool allocated[2]; uint8_t allocated[2];
uint8_t retry[2]; uint8_t retry[2];
uint8_t result; uint8_t result;
} hcd_xfer_t; } hcd_xfer_t;
@ -113,24 +112,35 @@ static uint8_t endpoint_alloc(void);
static uint8_t endpoint_find(uint8_t dev_addr, uint8_t ep_addr); static uint8_t endpoint_find(uint8_t dev_addr, uint8_t ep_addr);
static uint32_t hcd_pma_alloc(uint8_t channel, tusb_dir_t dir, uint16_t len); static uint32_t hcd_pma_alloc(uint8_t channel, tusb_dir_t dir, uint16_t len);
static uint8_t channel_alloc(uint8_t dev_addr, uint8_t ep_addr, uint8_t ep_type); static uint8_t channel_alloc(uint8_t dev_addr, uint8_t ep_addr, uint8_t ep_type);
static bool hcd_write_packet_memory(uint16_t dst, const void *__restrict src, uint16_t nbytes);
static bool hcd_read_packet_memory(void *__restrict dst, uint16_t src, uint16_t nbytes);
static bool edpt_xfer_kickoff(uint8_t ep_id); static bool edpt_xfer_kickoff(uint8_t ep_id);
static bool channel_xfer_start(uint8_t ch_id, tusb_dir_t dir); static bool channel_xfer_start(uint8_t ch_id, tusb_dir_t dir);
static void edpoint_close(uint8_t ep_id); static void edpoint_close(uint8_t ep_id);
static void port_status_handler(uint8_t rhport, bool in_isr); static void port_status_handler(uint8_t rhport, bool in_isr);
static void ch_handle_ack(uint8_t ch_id, uint32_t ch_reg, tusb_dir_t dir);
static void ch_handle_nak(uint8_t ch_id, uint32_t ch_reg, tusb_dir_t dir);
static void ch_handle_stall(uint8_t ch_id, uint32_t ch_reg, tusb_dir_t dir);
static void ch_handle_error(uint8_t ch_id, uint32_t ch_reg, tusb_dir_t dir);
//--------------------------------------------------------------------+ //--------------------------------------------------------------------+
// Inline Functions // Inline Functions
//--------------------------------------------------------------------+ //--------------------------------------------------------------------+
static inline void endpoint_dealloc(hcd_endpoint_t* edpt) { static inline void endpoint_dealloc(hcd_endpoint_t* edpt) {
edpt->allocated = false; edpt->allocated = 0;
} }
static inline void channel_dealloc(hcd_xfer_t* xfer, tusb_dir_t dir) { static inline void channel_dealloc(hcd_xfer_t* xfer, tusb_dir_t dir) {
xfer->allocated[dir] = false; xfer->allocated[dir] = 0;
} }
// Write channel state in specified direction
static inline void channel_write_status(uint8_t ch_id, uint32_t ch_reg, tusb_dir_t dir, ep_stat_t state, bool need_exclusive) {
ch_reg &= USB_EPREG_MASK | CH_STAT_MASK(dir);
ch_change_status(&ch_reg, dir, state);
ch_write(ch_id, ch_reg, need_exclusive);
}
//--------------------------------------------------------------------+ //--------------------------------------------------------------------+
// Controller API // Controller API
//--------------------------------------------------------------------+ //--------------------------------------------------------------------+
@ -218,139 +228,153 @@ static void port_status_handler(uint8_t rhport, bool in_isr) {
} }
} }
// Handle CTR interrupt for the TX/OUT direction //--------------------------------------------------------------------+
static void handle_ctr_tx(uint32_t ch_id) { // Interrupt Helper Functions
uint32_t ch_reg = ch_read(ch_id) | USB_EP_CTR_TX | USB_EP_CTR_RX; //--------------------------------------------------------------------+
// Handle ACK response
static void ch_handle_ack(uint8_t ch_id, uint32_t ch_reg, tusb_dir_t dir) {
uint8_t const ep_num = ch_reg & USB_EPADDR_FIELD; uint8_t const ep_num = ch_reg & USB_EPADDR_FIELD;
uint8_t const daddr = (ch_reg & USB_CHEP_DEVADDR_Msk) >> USB_CHEP_DEVADDR_Pos; uint8_t const daddr = (ch_reg & USB_CHEP_DEVADDR_Msk) >> USB_CHEP_DEVADDR_Pos;
uint8_t ep_id = endpoint_find(daddr, ep_num); uint8_t ep_id = endpoint_find(daddr, ep_num | (dir == TUSB_DIR_IN ? TUSB_DIR_IN_MASK : 0));
TU_VERIFY(ep_id != TUSB_INDEX_INVALID_8, ); if (ep_id == TUSB_INDEX_INVALID_8) return;
hcd_endpoint_t* edpt = &_hcd_data.edpt[ep_id]; hcd_endpoint_t* edpt = &_hcd_data.edpt[ep_id];
hcd_xfer_t* xfer = &_hcd_data.xfer[ch_id]; hcd_xfer_t* xfer = &_hcd_data.xfer[ch_id];
TU_VERIFY(xfer->allocated[TUSB_DIR_OUT],);
// Manage Correct Transaction if (dir == TUSB_DIR_OUT) {
if ((ch_reg & USB_CH_ERRTX) == 0U) { // OUT/TX direction
// Acked if (edpt->buflen != xfer->queued_len[TUSB_DIR_OUT]) {
if ((ch_reg & USB_CH_TX_STTX) == USB_CH_TX_ACK_SBUF) { // More data to send
if (edpt->buflen != xfer->queued_len[TUSB_DIR_OUT]) { uint16_t const len = tu_min16(edpt->buflen - xfer->queued_len[TUSB_DIR_OUT], edpt->max_packet_size);
uint16_t const len = tu_min16(edpt->buflen - xfer->queued_len[TUSB_DIR_OUT], edpt->max_packet_size); uint16_t pma_addr = (uint16_t) btable_get_addr(ch_id, BTABLE_BUF_TX);
uint16_t pma_addr = (uint16_t) btable_get_addr(ch_id, BTABLE_BUF_TX); fsdev_write_packet_memory(pma_addr, &(edpt->buffer[xfer->queued_len[TUSB_DIR_OUT]]), len);
hcd_write_packet_memory(pma_addr, &(edpt->buffer[xfer->queued_len[TUSB_DIR_OUT]]), len); btable_set_count(ch_id, BTABLE_BUF_TX, len);
btable_set_count(ch_id, BTABLE_BUF_TX, len); xfer->queued_len[TUSB_DIR_OUT] += len;
xfer->queued_len[TUSB_DIR_OUT] += len; channel_write_status(ch_id, ch_reg, TUSB_DIR_OUT, EP_STAT_VALID, false);
} else {
ch_change_status(&ch_reg, TUSB_DIR_OUT, EP_STAT_VALID); // Transfer complete
ch_reg &= USB_EPREG_MASK | CH_STAT_MASK(TUSB_DIR_OUT); // only change TX Status, reserve other toggle bits
ch_write(ch_id, ch_reg, false);
} else {
channel_dealloc(xfer, TUSB_DIR_OUT);
hcd_event_xfer_complete(daddr, ep_num, xfer->queued_len[TUSB_DIR_OUT], XFER_RESULT_SUCCESS, true);
}
} else if ((ch_reg & USB_CH_TX_STTX) == USB_CH_TX_NAK) {
// NAKed
if (edpt->ep_type != TUSB_XFER_INTERRUPT) {
ch_reg &= USB_EPREG_MASK | CH_STAT_MASK(TUSB_DIR_OUT); // will change TX Status, reserved other toggle bits
ch_change_status(&ch_reg, TUSB_DIR_OUT, EP_STAT_VALID);
ch_write(ch_id, ch_reg, false);
}
} else if ((ch_reg & USB_CH_TX_STTX) == USB_CH_TX_STALL) {
// STALLed
channel_dealloc(xfer, TUSB_DIR_OUT); channel_dealloc(xfer, TUSB_DIR_OUT);
ch_reg &= USB_EPREG_MASK | CH_STAT_MASK(TUSB_DIR_OUT); // will change TX Status, reserved other toggle bits edpt->pid = (ch_reg & USB_CHEP_DTOG_TX) ? 1 : 0;
ch_change_status(&ch_reg, TUSB_DIR_OUT, EP_STAT_DISABLED); hcd_event_xfer_complete(daddr, ep_num, xfer->queued_len[TUSB_DIR_OUT], XFER_RESULT_SUCCESS, true);
ch_write(ch_id, ch_reg, false);
hcd_event_xfer_complete(daddr, ep_num, xfer->queued_len[TUSB_DIR_OUT], XFER_RESULT_STALLED, true);
} }
} else { } else {
// Error // IN/RX direction
TU_LOG(FSDEV_DEBUG, "handle_ctr_tx error epreg=0x%08X ch=%u ep=0x%02X daddr=%u queued=%u/%u\r\n", uint16_t const rx_count = btable_get_count(ch_id, BTABLE_BUF_RX);
ch_reg, ch_id, ep_num, daddr, xfer->queued_len[TUSB_DIR_OUT], edpt->buflen); uint16_t pma_addr = (uint16_t) btable_get_addr(ch_id, BTABLE_BUF_RX);
ch_reg &= USB_EPREG_MASK | CH_STAT_MASK(TUSB_DIR_OUT); // will change TX Status, reserved other toggle bits
ch_reg &=~USB_CH_ERRTX; fsdev_read_packet_memory(edpt->buffer + xfer->queued_len[TUSB_DIR_IN], pma_addr, rx_count);
if (xfer->retry[TUSB_DIR_OUT] < HCD_XFER_ERROR_MAX) { xfer->queued_len[TUSB_DIR_IN] += rx_count;
// Retry
xfer->retry[TUSB_DIR_OUT]++; if ((rx_count < edpt->max_packet_size) || (xfer->queued_len[TUSB_DIR_IN] >= edpt->buflen)) {
// Transfer complete (short packet or all bytes received)
channel_dealloc(xfer, TUSB_DIR_IN);
edpt->pid = (ch_reg & USB_CHEP_DTOG_RX) ? 1 : 0;
hcd_event_xfer_complete(daddr, ep_num | TUSB_DIR_IN_MASK, xfer->queued_len[TUSB_DIR_IN], XFER_RESULT_SUCCESS, true);
} else { } else {
// Failed after retries // More data expected
channel_dealloc(xfer, TUSB_DIR_OUT); uint16_t const cnt = tu_min16(edpt->buflen - xfer->queued_len[TUSB_DIR_IN], edpt->max_packet_size);
ch_change_status(&ch_reg, TUSB_DIR_OUT, EP_STAT_DISABLED); btable_set_rx_bufsize(ch_id, BTABLE_BUF_RX, cnt);
hcd_event_xfer_complete(daddr, ep_num, xfer->queued_len[TUSB_DIR_OUT], XFER_RESULT_FAILED, true); channel_write_status(ch_id, ch_reg, TUSB_DIR_IN, EP_STAT_VALID, false);
} }
ch_write(ch_id, ch_reg, false); }
}
// Handle NAK response
static void ch_handle_nak(uint8_t ch_id, uint32_t ch_reg, tusb_dir_t dir) {
uint8_t const ep_num = ch_reg & USB_EPADDR_FIELD;
uint8_t const daddr = (ch_reg & USB_CHEP_DEVADDR_Msk) >> USB_CHEP_DEVADDR_Pos;
uint8_t ep_id = endpoint_find(daddr, ep_num | (dir == TUSB_DIR_IN ? TUSB_DIR_IN_MASK : 0));
if (ep_id == TUSB_INDEX_INVALID_8) return;
hcd_endpoint_t* edpt = &_hcd_data.edpt[ep_id];
// Retry non-periodic transfer immediately,
// Periodic transfer will be retried by next frame automatically
if (edpt->ep_type == TUSB_XFER_CONTROL || edpt->ep_type == TUSB_XFER_BULK) {
channel_write_status(ch_id, ch_reg, dir, EP_STAT_VALID, false);
}
}
// Handle STALL response
static void ch_handle_stall(uint8_t ch_id, uint32_t ch_reg, tusb_dir_t dir) {
uint8_t const ep_num = ch_reg & USB_EPADDR_FIELD;
uint8_t const daddr = (ch_reg & USB_CHEP_DEVADDR_Msk) >> USB_CHEP_DEVADDR_Pos;
hcd_xfer_t* xfer = &_hcd_data.xfer[ch_id];
channel_dealloc(xfer, dir);
channel_write_status(ch_id, ch_reg, dir, EP_STAT_DISABLED, false);
hcd_event_xfer_complete(daddr, ep_num | (dir == TUSB_DIR_IN ? TUSB_DIR_IN_MASK : 0),
xfer->queued_len[dir], XFER_RESULT_STALLED, true);
}
// Handle error response
static void ch_handle_error(uint8_t ch_id, uint32_t ch_reg, tusb_dir_t dir) {
uint8_t const ep_num = ch_reg & USB_EPADDR_FIELD;
uint8_t const daddr = (ch_reg & USB_CHEP_DEVADDR_Msk) >> USB_CHEP_DEVADDR_Pos;
uint8_t ep_id = endpoint_find(daddr, ep_num | (dir == TUSB_DIR_IN ? TUSB_DIR_IN_MASK : 0));
if (ep_id == TUSB_INDEX_INVALID_8) return;
hcd_xfer_t* xfer = &_hcd_data.xfer[ch_id];
ch_reg &= USB_EPREG_MASK | CH_STAT_MASK(dir);
ch_reg &= ~(dir == TUSB_DIR_OUT ? USB_CH_ERRTX : USB_CH_ERRRX);
if (xfer->retry[dir] < HCD_XFER_ERROR_MAX) {
// Retry
xfer->retry[dir]++;
ch_change_status(&ch_reg, dir, EP_STAT_VALID);
} else {
// Failed after retries
channel_dealloc(xfer, dir);
ch_change_status(&ch_reg, dir, EP_STAT_DISABLED);
hcd_event_xfer_complete(daddr, ep_num | (dir == TUSB_DIR_IN ? TUSB_DIR_IN_MASK : 0),
xfer->queued_len[dir], XFER_RESULT_FAILED, true);
}
ch_write(ch_id, ch_reg, false);
}
// Handle CTR interrupt for the TX/OUT direction
static void handle_ctr_tx(uint32_t ch_id) {
uint32_t ch_reg = ch_read(ch_id) | USB_EP_CTR_TX | USB_EP_CTR_RX;
hcd_xfer_t* xfer = &_hcd_data.xfer[ch_id];
TU_VERIFY(xfer->allocated[TUSB_DIR_OUT] == 1,);
if ((ch_reg & USB_CH_ERRTX) == 0U) {
// No error
if ((ch_reg & USB_CH_TX_STTX) == USB_CH_TX_ACK_SBUF) {
ch_handle_ack(ch_id, ch_reg, TUSB_DIR_OUT);
} else if ((ch_reg & USB_CH_TX_STTX) == USB_CH_TX_NAK) {
ch_handle_nak(ch_id, ch_reg, TUSB_DIR_OUT);
} else if ((ch_reg & USB_CH_TX_STTX) == USB_CH_TX_STALL) {
ch_handle_stall(ch_id, ch_reg, TUSB_DIR_OUT);
}
} else {
ch_handle_error(ch_id, ch_reg, TUSB_DIR_OUT);
} }
} }
// Handle CTR interrupt for the RX/IN direction // Handle CTR interrupt for the RX/IN direction
static void handle_ctr_rx(uint32_t ch_id) { static void handle_ctr_rx(uint32_t ch_id) {
uint32_t ch_reg = ch_read(ch_id) | USB_EP_CTR_TX | USB_EP_CTR_RX; uint32_t ch_reg = ch_read(ch_id) | USB_EP_CTR_TX | USB_EP_CTR_RX;
uint8_t const ep_num = ch_reg & USB_EPADDR_FIELD; hcd_xfer_t* xfer = &_hcd_data.xfer[ch_id];
TU_VERIFY(xfer->allocated[TUSB_DIR_IN] == 1,);
uint8_t const daddr = (ch_reg & USB_CHEP_DEVADDR_Msk) >> USB_CHEP_DEVADDR_Pos;
uint8_t ep_id = endpoint_find(daddr, ep_num | TUSB_DIR_IN_MASK);
TU_VERIFY(ep_id != TUSB_INDEX_INVALID_8, );
hcd_endpoint_t* edpt = &_hcd_data.edpt[ep_id];
hcd_xfer_t* xfer = &_hcd_data.xfer[ch_id];
TU_VERIFY(xfer->allocated[TUSB_DIR_IN],);
// Manage Correct Transaction
if ((ch_reg & USB_CH_ERRRX) == 0U) { if ((ch_reg & USB_CH_ERRRX) == 0U) {
// Acked // No error
if ((ch_reg & USB_CH_RX_STRX) == USB_CH_RX_ACK_SBUF) { if ((ch_reg & USB_CH_RX_STRX) == USB_CH_RX_ACK_SBUF) {
uint16_t const rx_count = btable_get_count(ch_id, BTABLE_BUF_RX); ch_handle_ack(ch_id, ch_reg, TUSB_DIR_IN);
uint16_t pma_addr = (uint16_t) btable_get_addr(ch_id, BTABLE_BUF_RX);
hcd_read_packet_memory(edpt->buffer + xfer->queued_len[TUSB_DIR_IN], pma_addr, rx_count);
xfer->queued_len[TUSB_DIR_IN] += rx_count;
if ((rx_count < edpt->max_packet_size) || (xfer->queued_len[TUSB_DIR_IN] >= edpt->buflen)) {
// all bytes received or short packet
channel_dealloc(xfer, TUSB_DIR_IN);
hcd_event_xfer_complete(daddr, ep_num | TUSB_DIR_IN_MASK, xfer->queued_len[TUSB_DIR_IN], XFER_RESULT_SUCCESS, true);
} else {
// Set endpoint active again for receiving more data. Note that isochronous endpoints stay active always
uint16_t const cnt = tu_min16(edpt->buflen - xfer->queued_len[TUSB_DIR_IN], edpt->max_packet_size);
btable_set_rx_bufsize(ch_id, BTABLE_BUF_RX, cnt);
ch_reg &= USB_EPREG_MASK | CH_STAT_MASK(TUSB_DIR_IN); // will change RX Status, reserved other toggle bits
ch_change_status(&ch_reg, TUSB_DIR_IN, EP_STAT_VALID);
ch_write(ch_id, ch_reg, false);
}
} else if ((ch_reg & USB_CH_RX_STRX) == USB_CH_RX_NAK) { } else if ((ch_reg & USB_CH_RX_STRX) == USB_CH_RX_NAK) {
// NAKed ch_handle_nak(ch_id, ch_reg, TUSB_DIR_IN);
if (edpt->ep_type != TUSB_XFER_INTERRUPT) { } else if ((ch_reg & USB_CH_RX_STRX) == USB_CH_RX_STALL){
ch_reg &= USB_EPREG_MASK | CH_STAT_MASK(TUSB_DIR_IN); // will change TX Status, reserved other toggle bits ch_handle_stall(ch_id, ch_reg, TUSB_DIR_IN);
ch_change_status(&ch_reg, TUSB_DIR_IN, EP_STAT_VALID);
ch_write(ch_id, ch_reg, false);
}
} else {
// STALLed
channel_dealloc(xfer, TUSB_DIR_IN);
ch_reg &= USB_EPREG_MASK | CH_STAT_MASK(TUSB_DIR_IN); // will change TX Status, reserved other toggle bits
ch_change_status(&ch_reg, TUSB_DIR_IN, EP_STAT_DISABLED);
ch_write(ch_id, ch_reg, false);
hcd_event_xfer_complete(daddr, ep_num | TUSB_DIR_IN_MASK, xfer->queued_len[TUSB_DIR_IN], XFER_RESULT_STALLED, true);
} }
} else { } else {
// Error ch_handle_error(ch_id, ch_reg, TUSB_DIR_IN);
TU_LOG(FSDEV_DEBUG, "handle_ctr_tx error epreg=0x%08X ch=%u ep=0x%02X daddr=%u queued=%u/%u\r\n",
ch_reg, ch_id, ep_num, daddr, xfer->queued_len[TUSB_DIR_IN], edpt->buflen);
ch_reg &= USB_EPREG_MASK | CH_STAT_MASK(TUSB_DIR_IN); // will change RX Status, reserved other toggle bits
ch_reg &=~USB_CH_ERRRX;
if (xfer->retry[TUSB_DIR_IN] < HCD_XFER_ERROR_MAX) {
// Retry
xfer->retry[TUSB_DIR_IN]++;
} else {
// Failed after retries
channel_dealloc(xfer, TUSB_DIR_IN);
ch_change_status(&ch_reg, TUSB_DIR_IN, EP_STAT_DISABLED);
hcd_event_xfer_complete(daddr, ep_num | TUSB_DIR_IN_MASK, xfer->queued_len[TUSB_DIR_IN], XFER_RESULT_FAILED, true);
}
ch_write(ch_id, ch_reg, false);
} }
} }
@ -468,7 +492,7 @@ void hcd_device_close(uint8_t rhport, uint8_t dev_addr) {
// Close all endpoints for this device // Close all endpoints for this device
for(uint32_t i = 0; i < CFG_TUH_FSDEV_ENDPOINT_MAX; i++) { for(uint32_t i = 0; i < CFG_TUH_FSDEV_ENDPOINT_MAX; i++) {
hcd_endpoint_t* edpt = &_hcd_data.edpt[i]; hcd_endpoint_t* edpt = &_hcd_data.edpt[i];
if (edpt->allocated && edpt->dev_addr == dev_addr) { if (edpt->allocated == 1 && edpt->dev_addr == dev_addr) {
edpoint_close(i); edpoint_close(i);
} }
} }
@ -496,7 +520,8 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const
edpt->ep_type = ep_type; edpt->ep_type = ep_type;
edpt->max_packet_size = packet_size; edpt->max_packet_size = packet_size;
edpt->interval = ep_desc->bInterval; edpt->interval = ep_desc->bInterval;
edpt->low_speed = (hcd_port_speed_get(rhport) == TUSB_SPEED_FULL && tuh_speed_get(dev_addr) == TUSB_SPEED_LOW); edpt->pid = 0;
edpt->low_speed = (hcd_port_speed_get(rhport) == TUSB_SPEED_FULL && tuh_speed_get(dev_addr) == TUSB_SPEED_LOW) ? 1 : 0;
// EP0 is bi-directional, so we need to open both OUT and IN channels // EP0 is bi-directional, so we need to open both OUT and IN channels
if (ep_addr == 0) { if (ep_addr == 0) {
@ -525,7 +550,7 @@ bool hcd_edpt_close(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) {
edpoint_close(ep_id_in); edpoint_close(ep_id_in);
} }
return false; return true;
} }
// Submit a transfer // Submit a transfer
@ -556,17 +581,12 @@ bool hcd_edpt_abort_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) {
for (uint8_t i = 0; i < FSDEV_EP_COUNT; i++) { for (uint8_t i = 0; i < FSDEV_EP_COUNT; i++) {
hcd_xfer_t* xfer = &_hcd_data.xfer[i]; hcd_xfer_t* xfer = &_hcd_data.xfer[i];
if (xfer->allocated[dir] && if (xfer->allocated[dir] == 1 &&
xfer->dev_addr == dev_addr && xfer->dev_addr == dev_addr &&
xfer->ep_num == tu_edpt_number(ep_addr)) { xfer->ep_num == tu_edpt_number(ep_addr)) {
channel_dealloc(xfer, dir); channel_dealloc(xfer, dir);
uint32_t ch_reg = ch_read(i) | USB_EP_CTR_TX | USB_EP_CTR_RX;
uint32_t ch_reg = ch_read(i) | USB_EP_CTR_TX | USB_EP_CTR_RX; // reserve CTR bits channel_write_status(i, ch_reg, dir, EP_STAT_DISABLED, true);
ch_reg &= USB_EPREG_MASK | CH_STAT_MASK(dir); // will change Status, reserved other toggle bits
ch_change_status(&ch_reg, dir, EP_STAT_DISABLED);
ch_write(i, ch_reg, true);
} }
} }
@ -582,6 +602,7 @@ bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet
hcd_endpoint_t *edpt = &_hcd_data.edpt[ep_id]; hcd_endpoint_t *edpt = &_hcd_data.edpt[ep_id];
edpt->next_setup = true; edpt->next_setup = true;
edpt->pid = 0;
return hcd_edpt_xfer(rhport, dev_addr, 0, (uint8_t*)(uintptr_t) setup_packet, 8); return hcd_edpt_xfer(rhport, dev_addr, 0, (uint8_t*)(uintptr_t) setup_packet, 8);
} }
@ -592,6 +613,12 @@ bool hcd_edpt_clear_stall(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) {
(void) dev_addr; (void) dev_addr;
(void) ep_addr; (void) ep_addr;
uint8_t const ep_id = endpoint_find(dev_addr, 0);
TU_ASSERT(ep_id < CFG_TUH_FSDEV_ENDPOINT_MAX);
hcd_endpoint_t *edpt = &_hcd_data.edpt[ep_id];
edpt->pid = 0;
return true; return true;
} }
@ -602,8 +629,8 @@ bool hcd_edpt_clear_stall(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) {
static uint8_t endpoint_alloc(void) { static uint8_t endpoint_alloc(void) {
for (uint32_t i = 0; i < CFG_TUH_FSDEV_ENDPOINT_MAX; i++) { for (uint32_t i = 0; i < CFG_TUH_FSDEV_ENDPOINT_MAX; i++) {
hcd_endpoint_t* edpt = &_hcd_data.edpt[i]; hcd_endpoint_t* edpt = &_hcd_data.edpt[i];
if (!edpt->allocated) { if (edpt->allocated == 0) {
edpt->allocated = true; edpt->allocated = 1;
return i; return i;
} }
} }
@ -613,7 +640,7 @@ static uint8_t endpoint_alloc(void) {
static uint8_t endpoint_find(uint8_t dev_addr, uint8_t ep_addr) { static uint8_t endpoint_find(uint8_t dev_addr, uint8_t ep_addr) {
for (uint32_t i = 0; i < (uint32_t)CFG_TUH_FSDEV_ENDPOINT_MAX; i++) { for (uint32_t i = 0; i < (uint32_t)CFG_TUH_FSDEV_ENDPOINT_MAX; i++) {
hcd_endpoint_t* edpt = &_hcd_data.edpt[i]; hcd_endpoint_t* edpt = &_hcd_data.edpt[i];
if (edpt->allocated && edpt->dev_addr == dev_addr && edpt->ep_addr == ep_addr) { if (edpt->allocated == 1 && edpt->dev_addr == dev_addr && edpt->ep_addr == ep_addr) {
return i; return i;
} }
} }
@ -628,24 +655,14 @@ static void edpoint_close(uint8_t ep_id) {
// disable active channel belong to this endpoint // disable active channel belong to this endpoint
for (uint8_t i = 0; i < FSDEV_EP_COUNT; i++) { for (uint8_t i = 0; i < FSDEV_EP_COUNT; i++) {
hcd_xfer_t* xfer = &_hcd_data.xfer[i]; hcd_xfer_t* xfer = &_hcd_data.xfer[i];
uint32_t ch_reg = ch_read(i) | USB_EP_CTR_TX | USB_EP_CTR_RX;
if (xfer->allocated[TUSB_DIR_OUT] && xfer->edpt[TUSB_DIR_OUT] == edpt) { if (xfer->allocated[TUSB_DIR_OUT] == 1 && xfer->edpt[TUSB_DIR_OUT] == edpt) {
channel_dealloc(xfer, TUSB_DIR_OUT); channel_dealloc(xfer, TUSB_DIR_OUT);
channel_write_status(i, ch_reg, TUSB_DIR_OUT, EP_STAT_DISABLED, true);
uint32_t ch_reg = ch_read(i) | USB_EP_CTR_TX | USB_EP_CTR_RX; // reserve CTR bits
ch_reg &= USB_EPREG_MASK | CH_STAT_MASK(TUSB_DIR_OUT); // will change RX Status, reserved other toggle bits
ch_change_status(&ch_reg, TUSB_DIR_OUT, EP_STAT_DISABLED);
ch_write(i, ch_reg, true);
} }
if (xfer->allocated[TUSB_DIR_IN] && xfer->edpt[TUSB_DIR_IN] == edpt) { if (xfer->allocated[TUSB_DIR_IN] == 1 && xfer->edpt[TUSB_DIR_IN] == edpt) {
channel_dealloc(xfer, TUSB_DIR_IN); channel_dealloc(xfer, TUSB_DIR_IN);
channel_write_status(i, ch_reg, TUSB_DIR_IN, EP_STAT_DISABLED, true);
uint32_t ch_reg = ch_read(i) | USB_EP_CTR_TX | USB_EP_CTR_RX; // reserve CTR bits
ch_reg &= USB_EPREG_MASK | CH_STAT_MASK(TUSB_DIR_IN); // will change TX Status, reserved other toggle bits
ch_change_status(&ch_reg, TUSB_DIR_IN, EP_STAT_DISABLED);
ch_write(i, ch_reg, true);
} }
} }
} }
@ -654,10 +671,10 @@ static void edpoint_close(uint8_t ep_id) {
static uint32_t hcd_pma_alloc(uint8_t channel, tusb_dir_t dir, uint16_t len) { static uint32_t hcd_pma_alloc(uint8_t channel, tusb_dir_t dir, uint16_t len) {
(void) len; (void) len;
// Simple static allocation as we are unlikely to handle ISO endpoints in host mode // Simple static allocation as we are unlikely to handle ISO endpoints in host mode
// We just give each channel a buffer of max packet size (64 bytes) // We just give each channel two buffers of max packet size (64 bytes) for IN and OUT
uint16_t addr = FSDEV_BTABLE_BASE + 8 * FSDEV_EP_COUNT; uint16_t addr = FSDEV_BTABLE_BASE + 8 * FSDEV_EP_COUNT;
addr += channel * 64 * 2 + (dir == TUSB_DIR_IN ? 64 : 0); addr += channel * TUSB_EPSIZE_BULK_FS * 2 + (dir == TUSB_DIR_IN ? TUSB_EPSIZE_BULK_FS : 0);
TU_ASSERT(addr <= FSDEV_PMA_SIZE, 0xFFFF); TU_ASSERT(addr <= FSDEV_PMA_SIZE, 0xFFFF);
@ -672,12 +689,12 @@ static uint8_t channel_alloc(uint8_t dev_addr, uint8_t ep_addr, uint8_t ep_type)
// Find channel allocate for same ep_num but other direction // Find channel allocate for same ep_num but other direction
tusb_dir_t const other_dir = (dir == TUSB_DIR_IN) ? TUSB_DIR_OUT : TUSB_DIR_IN; tusb_dir_t const other_dir = (dir == TUSB_DIR_IN) ? TUSB_DIR_OUT : TUSB_DIR_IN;
for (uint8_t i = 0; i < FSDEV_EP_COUNT; i++) { for (uint8_t i = 0; i < FSDEV_EP_COUNT; i++) {
if (!_hcd_data.xfer[i].allocated[dir] && if (_hcd_data.xfer[i].allocated[dir] == 0 &&
_hcd_data.xfer[i].allocated[other_dir] && _hcd_data.xfer[i].allocated[other_dir] == 1 &&
_hcd_data.xfer[i].dev_addr == dev_addr && _hcd_data.xfer[i].dev_addr == dev_addr &&
_hcd_data.xfer[i].ep_num == ep_num && _hcd_data.xfer[i].ep_num == ep_num &&
_hcd_data.xfer[i].ep_type == ep_type) { _hcd_data.xfer[i].ep_type == ep_type) {
_hcd_data.xfer[i].allocated[dir] = true; _hcd_data.xfer[i].allocated[dir] = 1;
_hcd_data.xfer[i].queued_len[dir] = 0; _hcd_data.xfer[i].queued_len[dir] = 0;
_hcd_data.xfer[i].retry[dir] = 0; _hcd_data.xfer[i].retry[dir] = 0;
return i; return i;
@ -686,11 +703,11 @@ static uint8_t channel_alloc(uint8_t dev_addr, uint8_t ep_addr, uint8_t ep_type)
// Find free channel // Find free channel
for (uint8_t i = 0; i < FSDEV_EP_COUNT; i++) { for (uint8_t i = 0; i < FSDEV_EP_COUNT; i++) {
if (!_hcd_data.xfer[i].allocated[0] && !_hcd_data.xfer[i].allocated[1]) { if (_hcd_data.xfer[i].allocated[0] == 0 && _hcd_data.xfer[i].allocated[1] == 0) {
_hcd_data.xfer[i].dev_addr = dev_addr; _hcd_data.xfer[i].dev_addr = dev_addr;
_hcd_data.xfer[i].ep_num = ep_num; _hcd_data.xfer[i].ep_num = ep_num;
_hcd_data.xfer[i].ep_type = ep_type; _hcd_data.xfer[i].ep_type = ep_type;
_hcd_data.xfer[i].allocated[dir] = true; _hcd_data.xfer[i].allocated[dir] = 1;
_hcd_data.xfer[i].queued_len[dir] = 0; _hcd_data.xfer[i].queued_len[dir] = 0;
_hcd_data.xfer[i].retry[dir] = 0; _hcd_data.xfer[i].retry[dir] = 0;
return i; return i;
@ -748,86 +765,37 @@ static bool channel_xfer_start(uint8_t ch_id, tusb_dir_t dir) {
if (dir == TUSB_DIR_OUT) { if (dir == TUSB_DIR_OUT) {
uint16_t const len = tu_min16(edpt->buflen - xfer->queued_len[TUSB_DIR_OUT], edpt->max_packet_size); uint16_t const len = tu_min16(edpt->buflen - xfer->queued_len[TUSB_DIR_OUT], edpt->max_packet_size);
hcd_write_packet_memory(pma_addr, &(edpt->buffer[xfer->queued_len[TUSB_DIR_OUT]]), len); fsdev_write_packet_memory(pma_addr, &(edpt->buffer[xfer->queued_len[TUSB_DIR_OUT]]), len);
btable_set_count(ch_id, BTABLE_BUF_TX, len); btable_set_count(ch_id, BTABLE_BUF_TX, len);
xfer->queued_len[TUSB_DIR_OUT] += len; xfer->queued_len[TUSB_DIR_OUT] += len;
if (edpt->next_setup) {
// Setup packet uses IN token
edpt->next_setup = false;
ch_reg |= USB_EP_SETUP;
}
ch_change_status(&ch_reg, TUSB_DIR_OUT, EP_STAT_VALID);
ch_reg &= USB_EPREG_MASK | CH_STAT_MASK(TUSB_DIR_OUT); // only change TX Status, reserve other toggle bits
} else { } else {
btable_set_rx_bufsize(ch_id, BTABLE_BUF_RX, edpt->max_packet_size); btable_set_rx_bufsize(ch_id, BTABLE_BUF_RX, edpt->max_packet_size);
ch_change_status(&ch_reg, TUSB_DIR_IN, EP_STAT_VALID);
ch_reg &= USB_EPREG_MASK | CH_STAT_MASK(TUSB_DIR_IN); // will change RX Status, reserved other toggle bits
} }
if (edpt->low_speed == 1) {
ch_reg |= USB_CHEP_LSEP;
} else {
ch_reg &= ~USB_CHEP_LSEP;
}
if (tu_edpt_number(edpt->ep_addr) == 0) {
edpt->pid = 1;
}
if (edpt->next_setup) {
// Setup packet uses IN token
edpt->next_setup = false;
ch_reg |= USB_EP_SETUP;
edpt->pid = 0;
}
ch_change_status(&ch_reg, dir, EP_STAT_VALID);
ch_change_dtog(&ch_reg, dir, edpt->pid);
ch_reg &= USB_EPREG_MASK | CH_STAT_MASK(dir) | CH_DTOG_MASK(dir);
ch_write(ch_id, ch_reg, true); ch_write(ch_id, ch_reg, true);
return true; return true;
} }
//--------------------------------------------------------------------+
// PMA read/write
//--------------------------------------------------------------------+
// Write to packet memory area (PMA) from user memory
static bool hcd_write_packet_memory(uint16_t dst, const void *__restrict src, uint16_t nbytes) {
if (nbytes == 0) return true;
uint32_t n_write = nbytes / FSDEV_BUS_SIZE;
fsdev_pma_buf_t *pma_buf = PMA_BUF_AT(dst);
const uint8_t *src8 = src;
while (n_write--) {
pma_buf->value = fsdevbus_unaligned_read(src8);
src8 += FSDEV_BUS_SIZE;
pma_buf++;
}
// Handle odd bytes
uint16_t odd = nbytes & (FSDEV_BUS_SIZE - 1);
if (odd) {
fsdev_bus_t temp = 0;
for (uint16_t i = 0; i < odd; i++) {
temp |= *src8++ << (i * 8);
}
pma_buf->value = temp;
}
return true;
}
// Read from packet memory area (PMA) to user memory
static bool hcd_read_packet_memory(void *__restrict dst, uint16_t src, uint16_t nbytes) {
if (nbytes == 0) return true;
uint32_t n_read = nbytes / FSDEV_BUS_SIZE;
fsdev_pma_buf_t *pma_buf = PMA_BUF_AT(src);
uint8_t *dst8 = (uint8_t *)dst;
while (n_read--) {
fsdevbus_unaligned_write(dst8, (fsdev_bus_t) pma_buf->value);
dst8 += FSDEV_BUS_SIZE;
pma_buf++;
}
// Handle odd bytes
uint16_t odd = nbytes & (FSDEV_BUS_SIZE - 1);
if (odd) {
fsdev_bus_t temp = pma_buf->value;
while (odd--) {
*dst8++ = (uint8_t)(temp & 0xfful);
temp >>= 8;
}
}
return true;
}
#endif #endif

View File

@ -217,7 +217,9 @@
</group> </group>
<group name="src/portable/st/stm32_fsdev"> <group name="src/portable/st/stm32_fsdev">
<path>$TUSB_DIR$/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c</path> <path>$TUSB_DIR$/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c</path>
<path>$TUSB_DIR$/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.h</path> <path>$TUSB_DIR$/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c</path>
<path>$TUSB_DIR$/src/portable/st/stm32_fsdev/fsdev_common.c</path>
<path>$TUSB_DIR$/src/portable/st/stm32_fsdev/fsdev_common.h</path>
</group> </group>
<group name="src/portable/st/typec"> <group name="src/portable/st/typec">
<path>$TUSB_DIR$/src/portable/st/typec/typec_stm32.c</path> <path>$TUSB_DIR$/src/portable/st/typec/typec_stm32.c</path>