From 42ce7a34683c747a4d99d8d2be92274ca6931063 Mon Sep 17 00:00:00 2001 From: Jie Feng Date: Sun, 14 Jun 2026 19:24:55 +0800 Subject: [PATCH 01/13] CH32X035 port --- README.rst | 2 + docs/reference/boards.rst | 29 +-- docs/reference/dependencies.rst | 1 + .../weact_ch32x035_core_board/board.cmake | 9 + .../boards/weact_ch32x035_core_board/board.h | 23 +++ .../boards/weact_ch32x035_core_board/board.mk | 7 + hw/bsp/ch32x035/ch32x035_conf.h | 23 +++ hw/bsp/ch32x035/ch32x035_it.h | 29 +++ hw/bsp/ch32x035/family.c | 176 ++++++++++++++++++ hw/bsp/ch32x035/family.cmake | 104 +++++++++++ hw/bsp/ch32x035/family.mk | 45 +++++ hw/bsp/ch32x035/linker/ch32x035.ld | 151 +++++++++++++++ hw/bsp/ch32x035/system_ch32x035.c | 76 ++++++++ hw/bsp/ch32x035/system_ch32x035.h | 28 +++ hw/bsp/ch32x035/wch-riscv.cfg | 12 ++ src/common/tusb_mcu.h | 9 + src/portable/wch/ch32_usbfs_reg.h | 7 + src/portable/wch/dcd_ch32_usbfs.c | 26 ++- src/tusb_option.h | 1 + tools/get_deps.py | 3 + 20 files changed, 744 insertions(+), 17 deletions(-) create mode 100644 hw/bsp/ch32x035/boards/weact_ch32x035_core_board/board.cmake create mode 100644 hw/bsp/ch32x035/boards/weact_ch32x035_core_board/board.h create mode 100644 hw/bsp/ch32x035/boards/weact_ch32x035_core_board/board.mk create mode 100644 hw/bsp/ch32x035/ch32x035_conf.h create mode 100644 hw/bsp/ch32x035/ch32x035_it.h create mode 100644 hw/bsp/ch32x035/family.c create mode 100644 hw/bsp/ch32x035/family.cmake create mode 100644 hw/bsp/ch32x035/family.mk create mode 100644 hw/bsp/ch32x035/linker/ch32x035.ld create mode 100644 hw/bsp/ch32x035/system_ch32x035.c create mode 100644 hw/bsp/ch32x035/system_ch32x035.h create mode 100644 hw/bsp/ch32x035/wch-riscv.cfg diff --git a/README.rst b/README.rst index 7fa8d70f10..024c5bec86 100644 --- a/README.rst +++ b/README.rst @@ -314,6 +314,8 @@ Supported CPUs | | CH32V305, CH32V307 | 🟡 | | ✅ | ch32_usbfs/hs | ISO data loss [2]_ | | +-----------------------------+--------+------+-----------+------------------------+--------------------+ | | CH583/2, CH32V103 | 🟡 | | ❌ | ch32_usbfs | ISO data loss [2]_ | +| +-----------------------------+--------+------+-----------+------------------------+--------------------+ +| | CH32X033, CH32X035 | ✅ | | ❌ | ch32_usbfs | EP4 quirk | +--------------+-----------------------------+--------+------+-----------+------------------------+--------------------+ Table Legend diff --git a/docs/reference/boards.rst b/docs/reference/boards.rst index 1334f6e698..4b7e5059c1 100644 --- a/docs/reference/boards.rst +++ b/docs/reference/boards.rst @@ -373,17 +373,18 @@ fomu fomu fomu https://tomu.im/fomu.html WCH --- -================== ============================= ======== ===================================================================== ====== -Board Name Family URL Note -================== ============================= ======== ===================================================================== ====== -ch32f205r-r0 CH32F205r-r0 ch32f20x https://github.com/openwch/ch32f20x -ch32v103c_bluepill CH32V103C8T6-Bluepill ch32v10x https://stm32-base.org/boards/STM32F103C8T6-Blue-Pill -ch32v103r_r1_1v0 CH32V103R-R1-1v1 ch32v10x https://github.com/openwch/ch32v103/tree/main/SCHPCB/CH32V103R-R1-1v1 -ch32v203c_r0_1v0 CH32V203C-R0-1v0 ch32v20x https://github.com/openwch/ch32v20x/tree/main/SCHPCB/CH32V203C-R0 -ch32v203g_r0_1v0 CH32V203G-R0-1v0 ch32v20x https://github.com/openwch/ch32v20x/tree/main/SCHPCB/CH32V203C-R0 -nanoch32v203 nanoCH32V203 ch32v20x https://github.com/wuxx/nanoCH32V203 -ch32v307v_r1_1v0 CH32V307V-R1-1v0 ch32v30x https://github.com/openwch/ch32v307/tree/main/SCHPCB/CH32V307V-R1-1v0 -nanoch32v305 nanoCH32V305 ch32v30x https://github.com/wuxx/nanoCH32V305 -ch582m_evt CH582M-EVT evaluation board ch583 https://www.wch-ic.com/products/CH582.html -yd-ch582m yd-ch582m from vcc-gnd studio ch583 http://vcc-gnd.com/ -================== ============================= ======== ===================================================================== ====== +=========================== ============================= ======== ===================================================================== ====== +Board Name Family URL Note +=========================== ============================= ======== ===================================================================== ====== +ch32f205r-r0 CH32F205r-r0 ch32f20x https://github.com/openwch/ch32f20x +ch32v103c_bluepill CH32V103C8T6-Bluepill ch32v10x https://stm32-base.org/boards/STM32F103C8T6-Blue-Pill +ch32v103r_r1_1v0 CH32V103R-R1-1v1 ch32v10x https://github.com/openwch/ch32v103/tree/main/SCHPCB/CH32V103R-R1-1v1 +ch32v203c_r0_1v0 CH32V203C-R0-1v0 ch32v20x https://github.com/openwch/ch32v20x/tree/main/SCHPCB/CH32V203C-R0 +ch32v203g_r0_1v0 CH32V203G-R0-1v0 ch32v20x https://github.com/openwch/ch32v20x/tree/main/SCHPCB/CH32V203C-R0 +nanoch32v203 nanoCH32V203 ch32v20x https://github.com/wuxx/nanoCH32V203 +ch32v307v_r1_1v0 CH32V307V-R1-1v0 ch32v30x https://github.com/openwch/ch32v307/tree/main/SCHPCB/CH32V307V-R1-1v0 +nanoch32v305 nanoCH32V305 ch32v30x https://github.com/wuxx/nanoCH32V305 +ch582m_evt CH582M-EVT evaluation board ch583 https://www.wch-ic.com/products/CH582.html +yd-ch582m yd-ch582m from vcc-gnd studio ch583 http://vcc-gnd.com/ +weact_ch32x035_core_board WeAct CH32X035 Core Board ch32x035 https://github.com/WeActStudio/WeActStudio.CH32X035CoreBoard +=========================== ============================= ======== ===================================================================== ====== diff --git a/docs/reference/dependencies.rst b/docs/reference/dependencies.rst index b4685f4c08..379d6a1206 100644 --- a/docs/reference/dependencies.rst +++ b/docs/reference/dependencies.rst @@ -94,6 +94,7 @@ hw/mcu/wch/ch32v103 https://github.com/openwch/ch32v103.gi hw/mcu/wch/ch32v20x https://github.com/openwch/ch32v20x.git c4c38f507e258a4e69b059ccc2dc27dde33cea1b ch32v20x hw/mcu/wch/ch32v307 https://github.com/openwch/ch32v307.git 184f21b852cb95eed58e86e901837bc9fff68775 ch32v30x hw/mcu/wch/ch583 https://github.com/openwch/ch583.git bd508ad7ceed48377619837051412a651952857f ch583 +hw/mcu/wch/ch32x035 https://github.com/openwch/ch32x035.git c6253942b29ff2a3f5e2829182a874afffa45881 ch32x035 lib/CMSIS_5 https://github.com/ARM-software/CMSIS_5.git 2b7495b8535bdcb306dac29b9ded4cfb679d7e5c kinetis_k kinetis_kl lpc54 rw61x mm32 msp432e4 nrf samd2x_l2x lpc11 lpc13 lpc15 lpc17 lpc18 lpc40 lpc43 stm32c0 stm32f0 stm32f1 stm32f2 stm32f3 stm32f4 stm32f7 stm32g0 stm32g4 stm32h5 stm32h7 stm32h7rs stm32l0 stm32l1 stm32l4 stm32l5 stm32u0 stm32u5 stm32wb stm32wba sam3x samd11 samd21 samd2x_l2x samd51 samd5x_e5x same5x same7x samg tm4c lib/CMSIS_6 https://github.com/ARM-software/CMSIS_6.git 6f0a58d01aa9bd2feba212097f9afe7acd991d52 imxrt kinetis_k32l ra stm32n6 lpc51 lpc55 mcx stm32c5 lib/FreeRTOS-Kernel https://github.com/FreeRTOS/FreeRTOS-Kernel.git 9b777ae5c5b8e9e456065a00294d1e5f5f9facf5 all diff --git a/hw/bsp/ch32x035/boards/weact_ch32x035_core_board/board.cmake b/hw/bsp/ch32x035/boards/weact_ch32x035_core_board/board.cmake new file mode 100644 index 0000000000..36dd500e3e --- /dev/null +++ b/hw/bsp/ch32x035/boards/weact_ch32x035_core_board/board.cmake @@ -0,0 +1,9 @@ +set(LD_FLASH_SIZE 62K) +set(LD_RAM_SIZE 20K) + +function(update_board TARGET) + target_compile_definitions(${TARGET} PUBLIC + SYSCLK_FREQ_48MHz_HSI=48000000 + CFG_EXAMPLE_MSC_DUAL_READONLY + ) +endfunction() diff --git a/hw/bsp/ch32x035/boards/weact_ch32x035_core_board/board.h b/hw/bsp/ch32x035/boards/weact_ch32x035_core_board/board.h new file mode 100644 index 0000000000..e42970ed70 --- /dev/null +++ b/hw/bsp/ch32x035/boards/weact_ch32x035_core_board/board.h @@ -0,0 +1,23 @@ +/* metadata: + name: WeAct CH32X035 Core Board + url: https://github.com/WeActStudio/WeActStudio.CH32X035CoreBoard +*/ + +#ifndef BOARD_H_ +#define BOARD_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#define LED_PORT GPIOB +#define LED_PIN GPIO_Pin_12 +#define LED_STATE_ON 1 +#define LED_CLOCK_EN() RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE) +#define LED_MODE GPIO_Mode_Out_PP + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/hw/bsp/ch32x035/boards/weact_ch32x035_core_board/board.mk b/hw/bsp/ch32x035/boards/weact_ch32x035_core_board/board.mk new file mode 100644 index 0000000000..bbd8106f39 --- /dev/null +++ b/hw/bsp/ch32x035/boards/weact_ch32x035_core_board/board.mk @@ -0,0 +1,7 @@ +CFLAGS += \ + -DSYSCLK_FREQ_48MHz_HSI=48000000 \ + -DCFG_EXAMPLE_MSC_DUAL_READONLY \ + +LDFLAGS += \ + -Wl,--defsym=__FLASH_SIZE=62K \ + -Wl,--defsym=__RAM_SIZE=20K \ diff --git a/hw/bsp/ch32x035/ch32x035_conf.h b/hw/bsp/ch32x035/ch32x035_conf.h new file mode 100644 index 0000000000..9672f983ff --- /dev/null +++ b/hw/bsp/ch32x035/ch32x035_conf.h @@ -0,0 +1,23 @@ +/********************************** (C) COPYRIGHT ******************************* + * File Name : ch32x035_conf.h + * Author : WCH + * Version : V1.0.0 + * Date : 2023/04/06 + * Description : Library configuration file. + ********************************************************************************* + * Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd. + * Attention: This software (modified or not) and binary are used for + * microcontroller manufactured by Nanjing Qinheng Microelectronics. + *******************************************************************************/ +#ifndef __CH32X035_CONF_H +#define __CH32X035_CONF_H + +#include "ch32x035_dbgmcu.h" +#include "ch32x035_flash.h" +#include "ch32x035_gpio.h" +#include "ch32x035_misc.h" +#include "ch32x035_rcc.h" +#include "ch32x035_usb.h" +#include "ch32x035_usart.h" + +#endif diff --git a/hw/bsp/ch32x035/ch32x035_it.h b/hw/bsp/ch32x035/ch32x035_it.h new file mode 100644 index 0000000000..5d6c5d9b2a --- /dev/null +++ b/hw/bsp/ch32x035/ch32x035_it.h @@ -0,0 +1,29 @@ +/********************************** (C) COPYRIGHT ******************************* + * File Name : ch32x035_it.h + * Author : WCH + * Version : V1.0.0 + * Date : 2023/04/06 + * Description : This file contains the headers of the interrupt handlers. + ********************************************************************************* + * Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd. + * Attention: This software (modified or not) and binary are used for + * microcontroller manufactured by Nanjing Qinheng Microelectronics. + *******************************************************************************/ +#ifndef __CH32X035_IT_H +#define __CH32X035_IT_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "ch32x035.h" + +void USBFS_IRQHandler(void); +void USBFSWakeUp_IRQHandler(void); +void SysTick_Handler(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/hw/bsp/ch32x035/family.c b/hw/bsp/ch32x035/family.c new file mode 100644 index 0000000000..edfaa6fbcf --- /dev/null +++ b/hw/bsp/ch32x035/family.c @@ -0,0 +1,176 @@ +/* metadata: +manufacturer: WCH +*/ + +#include + +// https://github.com/openwch/ch32v307/pull/90 +// https://github.com/openwch/ch32v20x/pull/12 +#ifdef __GNUC__ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wstrict-prototypes" +#endif + +#include "ch32x035.h" +#include "ch32x035_it.h" + +#ifdef __GNUC__ + #pragma GCC diagnostic pop +#endif + +#include "bsp/board_api.h" +#include "board.h" + +__attribute__((interrupt)) __attribute__((used)) void USBFS_IRQHandler(void) { +#if CFG_TUD_ENABLED && CFG_TUD_WCH_USBIP_USBFS + tud_int_handler(0); +#endif +} + +__attribute__((interrupt)) __attribute__((used)) void USBFSWakeUp_IRQHandler(void) { +#if CFG_TUD_ENABLED && CFG_TUD_WCH_USBIP_USBFS + tud_int_handler(0); +#endif +} + +//--------------------------------------------------------------------+ +// Board API +//--------------------------------------------------------------------+ +#if CFG_TUSB_OS == OPT_OS_NONE +volatile uint32_t system_ticks = 0; + +__attribute__((interrupt)) void SysTick_Handler(void) { + SysTick->SR = 0; + system_ticks++; +} + +static uint32_t SysTick_Config(uint32_t ticks) { + NVIC_EnableIRQ(SysTicK_IRQn); + SysTick->CTLR = 0; + SysTick->SR = 0; + SysTick->CNT = 0; + SysTick->CMP = ticks - 1; + SysTick->CTLR = 0xF; + return 0; +} + +uint32_t tusb_time_millis_api(void) { + return system_ticks; +} +#endif + +void board_init(void) { + __disable_irq(); + + SystemCoreClockUpdate(); + +#if CFG_TUSB_OS == OPT_OS_NONE + SysTick_Config(SystemCoreClock / 1000); +#endif + + LED_CLOCK_EN(); + + GPIO_InitTypeDef GPIO_InitStructure = { + .GPIO_Pin = LED_PIN, + .GPIO_Mode = LED_MODE, + .GPIO_Speed = GPIO_Speed_50MHz, + }; + GPIO_Init(LED_PORT, &GPIO_InitStructure); + + RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); + RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE); + RCC_AHBPeriphClockCmd(RCC_AHBPeriph_USBFS, ENABLE); + + GPIO_InitStructure.GPIO_Pin = GPIO_Pin_16; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; + GPIO_Init(GPIOC, &GPIO_InitStructure); + + GPIO_InitStructure.GPIO_Pin = GPIO_Pin_17; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; + GPIO_Init(GPIOC, &GPIO_InitStructure); + + AFIO->CTLR = (AFIO->CTLR & ~(AFIO_CTLR_UDP_PUE | AFIO_CTLR_UDM_PUE)) | AFIO_CTLR_USB_PHY_V33 | AFIO_CTLR_UDP_PUE | + AFIO_CTLR_USB_IOEN; + +#ifdef UART_DEV + UART_CLOCK_EN(); + GPIO_InitTypeDef usart_init = { + .GPIO_Pin = UART_TX_PIN | UART_RX_PIN, + .GPIO_Speed = GPIO_Speed_50MHz, + .GPIO_Mode = GPIO_Mode_AF_PP, + }; + GPIO_Init(GPIOA, &usart_init); + + USART_InitTypeDef usart = { + .USART_BaudRate = 115200, + .USART_WordLength = USART_WordLength_8b, + .USART_StopBits = USART_StopBits_1, + .USART_Parity = USART_Parity_No, + .USART_Mode = USART_Mode_Tx | USART_Mode_Rx, + .USART_HardwareFlowControl = USART_HardwareFlowControl_None, + }; + USART_Init(UART_DEV, &usart); + USART_Cmd(UART_DEV, ENABLE); +#endif + + __enable_irq(); +} + +void board_reset_to_bootloader(void) { +} + +void board_led_write(bool state) { + GPIO_WriteBit(LED_PORT, LED_PIN, state ? LED_STATE_ON : (1 - LED_STATE_ON)); +} + +uint32_t board_button_read(void) { + return false; +} + +size_t board_get_unique_id(uint8_t id[], size_t max_len) { + (void)max_len; + volatile uint32_t *ch32_uuid = ((volatile uint32_t *)0x1FFFF7E8UL); + uint32_t *serial_32 = (uint32_t *)(uintptr_t)id; + serial_32[0] = ch32_uuid[0]; + serial_32[1] = ch32_uuid[1]; + serial_32[2] = ch32_uuid[2]; + + return 12; +} + +int board_uart_read(uint8_t *buf, int len) { +#ifdef UART_DEV + int count; + for (count = 0; count < len; count++) { + if (USART_GetFlagStatus(UART_DEV, USART_FLAG_RXNE) == RESET) { + break; + } + buf[count] = USART_ReceiveData(UART_DEV); + } + return count; +#else + (void)buf; + (void)len; + return 0; +#endif +} + +int board_uart_write(const void *buf, int len) { +#ifdef UART_DEV + const uint8_t *p = (const uint8_t *)buf; + int count = 0; + while (count < len) { + if (USART_GetFlagStatus(UART_DEV, USART_FLAG_TC) != RESET) { + USART_SendData(UART_DEV, p[count]); + count++; + } else { + break; + } + } + return count; +#else + (void)buf; + (void)len; + return 0; +#endif +} diff --git a/hw/bsp/ch32x035/family.cmake b/hw/bsp/ch32x035/family.cmake new file mode 100644 index 0000000000..1ec1bb01b0 --- /dev/null +++ b/hw/bsp/ch32x035/family.cmake @@ -0,0 +1,104 @@ +include_guard() + +set(UF2_FAMILY_ID 0x699b62ec) +set(CH32_FAMILY ch32x035) +set(SDK_DIR ${TOP}/hw/mcu/wch/${CH32_FAMILY}) +set(SDK_SRC_DIR ${SDK_DIR}/EVT/EXAM/SRC) + +# include board specific +include(${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}/board.cmake) + +# toolchain set up +set(CMAKE_SYSTEM_CPU rv32imac-ilp32 CACHE INTERNAL "System Processor") +set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/riscv_${TOOLCHAIN}.cmake) + +set(FAMILY_MCUS CH32X035 CACHE INTERNAL "") +set(OPENOCD_OPTION "-f ${CMAKE_CURRENT_LIST_DIR}/wch-riscv.cfg") + +set(RHPORT_DEVICE 0) + +#------------------------------------ +# Startup & Linker script +#------------------------------------ +if (NOT DEFINED LD_FILE_GNU) + set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/linker/${CH32_FAMILY}.ld) +endif () +set(LD_FILE_Clang ${LD_FILE_GNU}) +if (NOT DEFINED STARTUP_FILE_GNU) + set(STARTUP_FILE_GNU ${SDK_SRC_DIR}/Startup/startup_${CH32_FAMILY}.S) +endif () +set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) + +#------------------------------------ +# Board Target +#------------------------------------ +function(family_add_board BOARD_TARGET) + add_library(${BOARD_TARGET} STATIC + ${SDK_SRC_DIR}/Core/core_riscv.c + ${SDK_SRC_DIR}/Peripheral/src/${CH32_FAMILY}_dbgmcu.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}_rcc.c + ${SDK_SRC_DIR}/Peripheral/src/${CH32_FAMILY}_usart.c + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/system_${CH32_FAMILY}.c + ) + target_include_directories(${BOARD_TARGET} PUBLIC + ${SDK_SRC_DIR}/Core + ${SDK_SRC_DIR}/Peripheral/inc + ${CMAKE_CURRENT_FUNCTION_LIST_DIR} + ) + target_compile_definitions(${BOARD_TARGET} PUBLIC + BOARD_TUD_RHPORT=${RHPORT_DEVICE} + ) + + update_board(${BOARD_TARGET}) + + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") + target_compile_options(${BOARD_TARGET} PUBLIC -mcmodel=medany) + endif() +endfunction() + +#------------------------------------ +# Functions +#------------------------------------ +function(family_configure_example TARGET RTOS) + family_configure_common(${TARGET} ${RTOS}) + family_add_tinyusb(${TARGET} OPT_MCU_CH32X035) + + target_sources(${TARGET} PUBLIC + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c + ${TOP}/src/portable/wch/dcd_ch32_usbfs.c + ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} + ) + target_include_directories(${TARGET} PUBLIC + ${CMAKE_CURRENT_FUNCTION_LIST_DIR} + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../ + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} + ) + + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_link_options(${TARGET} PUBLIC + -nostartfiles + --specs=nosys.specs --specs=nano.specs + -Wl,--defsym=__FLASH_SIZE=${LD_FLASH_SIZE} + -Wl,--defsym=__RAM_SIZE=${LD_RAM_SIZE} + "LINKER:--script=${LD_FILE_GNU}" + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") + message(FATAL_ERROR "Clang is not supported") + elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") + target_link_options(${TARGET} PUBLIC + "LINKER:--config=${LD_FILE_IAR}" + ) + endif () + + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + SKIP_LINTING ON + COMPILE_OPTIONS -w) + + # Flashing + family_add_bin_hex(${TARGET}) + family_flash_openocd_wch(${TARGET}) + family_flash_wlink_rs(${TARGET}) +endfunction() diff --git a/hw/bsp/ch32x035/family.mk b/hw/bsp/ch32x035/family.mk new file mode 100644 index 0000000000..5d2ef64158 --- /dev/null +++ b/hw/bsp/ch32x035/family.mk @@ -0,0 +1,45 @@ +# Toolchain from https://github.com/xpack-dev-tools/riscv-none-elf-gcc-xpack +CROSS_COMPILE ?= riscv-none-elf- + +CH32_FAMILY = ch32x035 +SDK_DIR = hw/mcu/wch/ch32x035 +SDK_SRC_DIR = $(SDK_DIR)/EVT/EXAM/SRC + +include $(TOP)/$(BOARD_PATH)/board.mk +CPU_CORE ?= rv32imac-ilp32 + +CFLAGS += \ + -mcmodel=medany \ + -ffat-lto-objects \ + -flto \ + -DCFG_TUSB_MCU=OPT_MCU_CH32X035 \ + -DCFG_TUD_WCH_USBIP_USBFS=1 \ + +CFLAGS += -Wno-error=strict-prototypes + +LDFLAGS += \ + -nostdlib -nostartfiles \ + --specs=nosys.specs --specs=nano.specs \ + +LD_FILE = $(FAMILY_PATH)/linker/${CH32_FAMILY}.ld + +SRC_C += \ + src/portable/wch/dcd_ch32_usbfs.c \ + $(SDK_SRC_DIR)/Core/core_riscv.c \ + $(SDK_SRC_DIR)/Peripheral/src/${CH32_FAMILY}_dbgmcu.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}_rcc.c \ + $(SDK_SRC_DIR)/Peripheral/src/${CH32_FAMILY}_usart.c \ + +SRC_S += $(SDK_SRC_DIR)/Startup/startup_${CH32_FAMILY}.S + +INC += \ + $(TOP)/$(BOARD_PATH) \ + $(TOP)/$(SDK_SRC_DIR)/Core \ + $(TOP)/$(SDK_SRC_DIR)/Peripheral/inc \ + +FREERTOS_PORTABLE_SRC = $(FREERTOS_PORTABLE_PATH)/RISC-V + +OPENOCD_WCH_OPTION=-f $(TOP)/$(FAMILY_PATH)/wch-riscv.cfg +flash: flash-wlink-rs diff --git a/hw/bsp/ch32x035/linker/ch32x035.ld b/hw/bsp/ch32x035/linker/ch32x035.ld new file mode 100644 index 0000000000..c52b058046 --- /dev/null +++ b/hw/bsp/ch32x035/linker/ch32x035.ld @@ -0,0 +1,151 @@ +/* Define default values if not already defined */ +__flash_size = DEFINED(__FLASH_SIZE) ? __FLASH_SIZE : 62K; +__ram_size = DEFINED(__RAM_SIZE) ? __RAM_SIZE : 20K; +__stack_size = DEFINED(__STACK_SIZE) ? __STACK_SIZE : 2048; + +MEMORY +{ + FLASH (rx) : ORIGIN = 0x00000000, LENGTH = __flash_size + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = __ram_size +} + +ENTRY( _start ) + +PROVIDE( _stack_size = __stack_size ); +_estack = ORIGIN(RAM) + LENGTH(RAM); + +SECTIONS +{ + .init : + { + _sinit = .; + . = ALIGN(4); + KEEP(*(SORT_NONE(.init))) + . = ALIGN(4); + _einit = .; + } >FLASH AT>FLASH + + .vector : + { + *(.vector); + . = ALIGN(64); + } >FLASH AT>FLASH + + .text : + { + . = ALIGN(4); + *(.text) + *(.text.*) + *(.rodata) + *(.rodata*) + *(.gnu.linkonce.t.*) + . = ALIGN(4); + } >FLASH AT>FLASH + + .fini : + { + KEEP(*(SORT_NONE(.fini))) + . = ALIGN(4); + } >FLASH AT>FLASH + + PROVIDE( _etext = . ); + PROVIDE( _eitcm = . ); + + .preinit_array : + { + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + } >FLASH AT>FLASH + + .init_array : + { + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*))) + KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors)) + PROVIDE_HIDDEN (__init_array_end = .); + } >FLASH AT>FLASH + + .fini_array : + { + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*))) + KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors)) + PROVIDE_HIDDEN (__fini_array_end = .); + } >FLASH AT>FLASH + + .ctors : + { + KEEP (*crtbegin.o(.ctors)) + KEEP (*crtbegin?.o(.ctors)) + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + } >FLASH AT>FLASH + + .dtors : + { + KEEP (*crtbegin.o(.dtors)) + KEEP (*crtbegin?.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + } >FLASH AT>FLASH + + .dalign : + { + . = ALIGN(4); + PROVIDE(_data_vma = .); + } >RAM AT>FLASH + + .dlalign : + { + . = ALIGN(4); + PROVIDE(_data_lma = .); + } >FLASH AT>FLASH + + .data : + { + *(.gnu.linkonce.r.*) + *(.data .data.*) + *(.gnu.linkonce.d.*) + . = ALIGN(8); + PROVIDE( __global_pointer$ = . + 0x800 ); + *(.sdata .sdata.*) + *(.sdata2.*) + *(.gnu.linkonce.s.*) + . = ALIGN(8); + *(.srodata.cst16) + *(.srodata.cst8) + *(.srodata.cst4) + *(.srodata.cst2) + *(.srodata .srodata.*) + . = ALIGN(4); + PROVIDE( _edata = .); + } >RAM AT>FLASH + + .bss : + { + . = ALIGN(4); + PROVIDE( _sbss = .); + *(.sbss*) + *(.gnu.linkonce.sb.*) + *(.bss*) + *(.gnu.linkonce.b.*) + *(COMMON*) + . = ALIGN(4); + 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 +} diff --git a/hw/bsp/ch32x035/system_ch32x035.c b/hw/bsp/ch32x035/system_ch32x035.c new file mode 100644 index 0000000000..1a48906042 --- /dev/null +++ b/hw/bsp/ch32x035/system_ch32x035.c @@ -0,0 +1,76 @@ +/********************************** (C) COPYRIGHT ******************************* + * File Name : system_ch32x035.c + * Author : WCH + * Version : V1.0.0 + * Date : 2023/04/06 + * Description : CH32X035 Device Peripheral Access Layer System Source File. + ********************************************************************************* + * Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd. + * Attention: This software (modified or not) and binary are used for + * microcontroller manufactured by Nanjing Qinheng Microelectronics. + *******************************************************************************/ +#include "ch32x035.h" + +#if defined SYSCLK_FREQ_8MHz_HSI +uint32_t SystemCoreClock = SYSCLK_FREQ_8MHz_HSI; +#elif defined SYSCLK_FREQ_12MHz_HSI +uint32_t SystemCoreClock = SYSCLK_FREQ_12MHz_HSI; +#elif defined SYSCLK_FREQ_16MHz_HSI +uint32_t SystemCoreClock = SYSCLK_FREQ_16MHz_HSI; +#elif defined SYSCLK_FREQ_24MHz_HSI +uint32_t SystemCoreClock = SYSCLK_FREQ_24MHz_HSI; +#else +uint32_t SystemCoreClock = HSI_VALUE; +#endif + +__I uint8_t AHBPrescTable[16] = {1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8}; + +static void SetSysClock(void); + +void SystemInit(void) { + RCC->CTLR |= (uint32_t)0x00000001; + RCC->CFGR0 |= (uint32_t)0x00000050; + RCC->CFGR0 &= (uint32_t)0xF8FFFF5F; + SetSysClock(); +} + +void SystemCoreClockUpdate(void) { + uint32_t tmp; + + SystemCoreClock = HSI_VALUE; + tmp = AHBPrescTable[((RCC->CFGR0 & RCC_HPRE) >> 4)]; + + if (((RCC->CFGR0 & RCC_HPRE) >> 4) < 8) { + SystemCoreClock /= tmp; + } else { + SystemCoreClock >>= tmp; + } +} + +static void SetSysClock(void) { + GPIO_IPD_Unused(); + + FLASH->ACTLR &= (uint32_t)((uint32_t)~FLASH_ACTLR_LATENCY); + FLASH->ACTLR |= (uint32_t)FLASH_ACTLR_LATENCY_2; + + RCC->CFGR0 &= (uint32_t)0xFFFFFF0F; + +#if defined SYSCLK_FREQ_8MHz_HSI + RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV6; + FLASH->ACTLR &= (uint32_t)((uint32_t)~FLASH_ACTLR_LATENCY); + FLASH->ACTLR |= (uint32_t)FLASH_ACTLR_LATENCY_0; +#elif defined SYSCLK_FREQ_12MHz_HSI + RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV4; + FLASH->ACTLR &= (uint32_t)((uint32_t)~FLASH_ACTLR_LATENCY); + FLASH->ACTLR |= (uint32_t)FLASH_ACTLR_LATENCY_0; +#elif defined SYSCLK_FREQ_16MHz_HSI + RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV3; + FLASH->ACTLR &= (uint32_t)((uint32_t)~FLASH_ACTLR_LATENCY); + FLASH->ACTLR |= (uint32_t)FLASH_ACTLR_LATENCY_1; +#elif defined SYSCLK_FREQ_24MHz_HSI + RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV2; + FLASH->ACTLR = (uint32_t)FLASH_ACTLR_LATENCY_1; +#else + RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1; +#endif +} diff --git a/hw/bsp/ch32x035/system_ch32x035.h b/hw/bsp/ch32x035/system_ch32x035.h new file mode 100644 index 0000000000..173b16c1b9 --- /dev/null +++ b/hw/bsp/ch32x035/system_ch32x035.h @@ -0,0 +1,28 @@ +/********************************** (C) COPYRIGHT ******************************* + * File Name : system_ch32x035.h + * Author : WCH + * Version : V1.0.0 + * Date : 2023/04/06 + * Description : CH32X035 Device Peripheral Access Layer System Header File. + ********************************************************************************* + * Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd. + * Attention: This software (modified or not) and binary are used for + * microcontroller manufactured by Nanjing Qinheng Microelectronics. + *******************************************************************************/ +#ifndef __SYSTEM_CH32X035_H +#define __SYSTEM_CH32X035_H + +#ifdef __cplusplus +extern "C" { +#endif + +extern uint32_t SystemCoreClock; + +extern void SystemInit(void); +extern void SystemCoreClockUpdate(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/hw/bsp/ch32x035/wch-riscv.cfg b/hw/bsp/ch32x035/wch-riscv.cfg new file mode 100644 index 0000000000..7051c5c941 --- /dev/null +++ b/hw/bsp/ch32x035/wch-riscv.cfg @@ -0,0 +1,12 @@ +adapter driver wlinke +adapter speed 6000 +transport select sdi + +set _CHIPNAME wch_riscv +jtag newtap $_CHIPNAME cpu -irlen 5 -expected-id 0x00001 +set _TARGETNAME $_CHIPNAME.cpu + +target create $_TARGETNAME.0 wch_riscv -chain-position $_TARGETNAME +$_TARGETNAME.0 configure -work-area-phys 0x20000000 -work-area-size 10000 -work-area-backup 1 +set _FLASHNAME $_CHIPNAME.flash +flash bank $_FLASHNAME wch_riscv 0x00000000 0 0 0 $_TARGETNAME.0 diff --git a/src/common/tusb_mcu.h b/src/common/tusb_mcu.h index af43dfb120..9bf52c504a 100644 --- a/src/common/tusb_mcu.h +++ b/src/common/tusb_mcu.h @@ -606,6 +606,15 @@ #define TUP_DCD_ENDPOINT_MAX 8 +#elif TU_CHECK_MCU(OPT_MCU_CH32X035) + #define TUP_USBIP_WCH_USBFS + + #if !defined(CFG_TUD_WCH_USBIP_USBFS) + #define CFG_TUD_WCH_USBIP_USBFS 1 + #endif + + #define TUP_DCD_ENDPOINT_MAX 8 + #elif TU_CHECK_MCU(OPT_MCU_CH32V20X) // v20x support both port0 FSDEV (USBD) and port1 USBFS #define TUP_USBIP_WCH_USBFS diff --git a/src/portable/wch/ch32_usbfs_reg.h b/src/portable/wch/ch32_usbfs_reg.h index 5b037281fc..9d2efa2fb6 100644 --- a/src/portable/wch/ch32_usbfs_reg.h +++ b/src/portable/wch/ch32_usbfs_reg.h @@ -177,6 +177,13 @@ #define NVIC_EnableIRQ(n) PFIC_EnableIRQ(n) #define NVIC_DisableIRQ(n) PFIC_DisableIRQ(n) #endif +#elif CFG_TUSB_MCU == OPT_MCU_CH32X035 + #include + #define USBOTG_FS USBFSD + #define CH32_USBFS_EP_CTRL_COMBINED 1 + #define CH32_USBFS_EP_MANUAL_TOG 1 + #define CH32_USBFS_EP4_SHARES_EP0 1 + #define USBHD_IRQn USBFS_IRQn #endif // CH32V20x/V30x/F20x USBFS gives endpoint 3 a 1023-byte isochronous packet (CH32FV2x_V3xRM ch23: diff --git a/src/portable/wch/dcd_ch32_usbfs.c b/src/portable/wch/dcd_ch32_usbfs.c index ec521224e5..421c1ec69b 100644 --- a/src/portable/wch/dcd_ch32_usbfs.c +++ b/src/portable/wch/dcd_ch32_usbfs.c @@ -41,6 +41,25 @@ #define EP_DMA(ep) (*((ep) <= 3u ? &USBOTG_FS->EP_DMA_0_3[0].DMA + (ep) * 2u \ : (ep) == 4u ? &USBOTG_FS->EP_DMA_0_3[0].DMA \ : &USBOTG_FS->EP_DMA_5_7[0].DMA + ((ep) - 5u) * 2u)) + #elif CFG_TUSB_MCU == OPT_MCU_CH32X035 + static inline volatile uint32_t* ch32_usbfs_ep_dma_reg(uint8_t ep) { + switch (ep) { + case 0: return &USBOTG_FS->UEP0_DMA; + case 1: return &USBOTG_FS->UEP1_DMA; + case 2: return &USBOTG_FS->UEP2_DMA; + case 3: return &USBOTG_FS->UEP3_DMA; + case 4: return &USBOTG_FS->UEP0_DMA; + case 5: return &USBOTG_FS->UEP5_DMA; + case 6: return &USBOTG_FS->UEP6_DMA; + default: return &USBOTG_FS->UEP7_DMA; + } + } + + // There's a gap between EP4 and EP5 registers. + #define EP_DMA(ep) (*ch32_usbfs_ep_dma_reg(ep)) + #define EP_TX_LEN(ep) ((&USBOTG_FS->UEP0_TX_LEN)[2 * (ep) + ((ep) > 4 ? 24 : 0)]) + #define EP_TX_CTRL(ep) ((&USBOTG_FS->UEP0_CTRL_H)[2 * (ep) + ((ep) > 4 ? 24 : 0)]) + #define EP_RX_CTRL(ep) EP_TX_CTRL(ep) #else #define EP_DMA(ep) ((&USBOTG_FS->UEP0_DMA)[ep]) #define EP_TX_LEN(ep) ((&USBOTG_FS->UEP0_TX_LEN)[2 * ep]) @@ -48,9 +67,8 @@ #define EP_RX_CTRL(ep) ((&USBOTG_FS->UEP0_RX_CTRL)[4 * ep]) #endif -// Endpoint control register access. The newer USBFS IP (CH32V20x/V307/X035) has separate -// TX_CTRL and RX_CTRL bytes per endpoint; the older IP (CH32V103) has a single combined -// UEPn_CTRL register. These helpers hide the difference so the rest of the driver is shared. +// Endpoint control register access. Some WCH USBFS IPs have separate TX_CTRL/RX_CTRL bytes per +// endpoint; others have a single combined UEPn_CTRL register. These helpers hide the difference. // Values use the newer-IP encoding (USBFS_EP_T_*/USBFS_EP_R_*); the combined path remaps them. #ifdef CH32_USBFS_EP_CTRL_COMBINED #ifndef EP_CTRL // parts with a custom register map (CH58X) define EP_CTRL directly in reg.h @@ -311,6 +329,8 @@ bool dcd_init(uint8_t rhport, const tusb_rhport_init_t *rh_init) { // CH58X: a single mode register enables EP5/6/7 RX+TX (different bit layout than CH32). USBOTG_FS->UEP567_MOD = RB_UEP5_RX_EN | RB_UEP5_TX_EN | RB_UEP6_RX_EN | RB_UEP6_TX_EN | RB_UEP7_RX_EN | RB_UEP7_TX_EN; +#elif CFG_TUSB_MCU == OPT_MCU_CH32X035 + USBOTG_FS->UEP567_MOD = 0x3F; #else USBOTG_FS->UEP5_6_MOD = 0xCC; USBOTG_FS->UEP7_MOD = 0x0C; diff --git a/src/tusb_option.h b/src/tusb_option.h index 861c5e586b..b02f30b69d 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -178,6 +178,7 @@ #define OPT_MCU_CH32V103 2230 ///< WCH CH32V103 #define OPT_MCU_CH583 2240 ///< WCH CH583 #define OPT_MCU_CH582 OPT_MCU_CH583 ///< WCH CH582 (alias, same USB IP as CH583) +#define OPT_MCU_CH32X035 2250 ///< WCH CH32X035 // NXP LPC MCX #define OPT_MCU_MCXN9 2300 ///< NXP MCX N9 Series diff --git a/tools/get_deps.py b/tools/get_deps.py index 553d206ce5..bfd00e480e 100755 --- a/tools/get_deps.py +++ b/tools/get_deps.py @@ -265,6 +265,9 @@ 'hw/mcu/wch/ch583': ['https://github.com/openwch/ch583.git', 'bd508ad7ceed48377619837051412a651952857f', 'ch583'], + 'hw/mcu/wch/ch32x035': ['https://github.com/openwch/ch32x035.git', + 'c6253942b29ff2a3f5e2829182a874afffa45881', + 'ch32x035'], 'hw/mcu/artery/at32f403a_407': ['https://github.com/ArteryTek/AT32F403A_407_Firmware_Library.git', 'f2cb360c3d28fada76b374308b8c4c61d37a090b', 'at32f403a_407'], From af8a514424f00e0df9439d0e67c837911b09f439 Mon Sep 17 00:00:00 2001 From: Jie Feng Date: Sun, 14 Jun 2026 20:07:09 +0800 Subject: [PATCH 02/13] Examples now pass --- .../device/audio_4_channel_mic_freertos/skip.txt | 1 + examples/device/audio_test_freertos/skip.txt | 1 + examples/device/cdc_msc_freertos/skip.txt | 1 + examples/device/hid_composite_freertos/skip.txt | 1 + examples/device/midi_test_freertos/skip.txt | 1 + examples/device/net_lwip_webserver/skip.txt | 1 + .../boards/weact_ch32x035_core_board/board.cmake | 1 - .../boards/weact_ch32x035_core_board/board.mk | 4 +--- hw/bsp/ch32x035/family.cmake | 2 ++ hw/bsp/ch32x035/family.mk | 2 ++ src/portable/wch/dcd_ch32_usbfs.c | 13 ++----------- 11 files changed, 13 insertions(+), 15 deletions(-) diff --git a/examples/device/audio_4_channel_mic_freertos/skip.txt b/examples/device/audio_4_channel_mic_freertos/skip.txt index d47f1d327c..4b3fefb1fc 100644 --- a/examples/device/audio_4_channel_mic_freertos/skip.txt +++ b/examples/device/audio_4_channel_mic_freertos/skip.txt @@ -3,6 +3,7 @@ mcu:CH32V103 mcu:CH32V20X mcu:CH32V307 mcu:CH583 +mcu:CH32X035 mcu:CXD56 mcu:F1C100S mcu:GD32VF103 diff --git a/examples/device/audio_test_freertos/skip.txt b/examples/device/audio_test_freertos/skip.txt index 70aa232d07..262833b619 100644 --- a/examples/device/audio_test_freertos/skip.txt +++ b/examples/device/audio_test_freertos/skip.txt @@ -3,6 +3,7 @@ mcu:CH32V103 mcu:CH32V20X mcu:CH32V307 mcu:CH583 +mcu:CH32X035 mcu:CXD56 mcu:F1C100S mcu:GD32VF103 diff --git a/examples/device/cdc_msc_freertos/skip.txt b/examples/device/cdc_msc_freertos/skip.txt index 24e6931419..3bc1c4dd2e 100644 --- a/examples/device/cdc_msc_freertos/skip.txt +++ b/examples/device/cdc_msc_freertos/skip.txt @@ -3,6 +3,7 @@ mcu:CH32V103 mcu:CH32V20X mcu:CH32V307 mcu:CH583 +mcu:CH32X035 mcu:CXD56 mcu:F1C100S mcu:GD32VF103 diff --git a/examples/device/hid_composite_freertos/skip.txt b/examples/device/hid_composite_freertos/skip.txt index 049ea996f1..5e10774144 100644 --- a/examples/device/hid_composite_freertos/skip.txt +++ b/examples/device/hid_composite_freertos/skip.txt @@ -3,6 +3,7 @@ mcu:CH32V103 mcu:CH32V20X mcu:CH32V307 mcu:CH583 +mcu:CH32X035 mcu:CXD56 mcu:F1C100S mcu:GD32VF103 diff --git a/examples/device/midi_test_freertos/skip.txt b/examples/device/midi_test_freertos/skip.txt index 049ea996f1..5e10774144 100644 --- a/examples/device/midi_test_freertos/skip.txt +++ b/examples/device/midi_test_freertos/skip.txt @@ -3,6 +3,7 @@ mcu:CH32V103 mcu:CH32V20X mcu:CH32V307 mcu:CH583 +mcu:CH32X035 mcu:CXD56 mcu:F1C100S mcu:GD32VF103 diff --git a/examples/device/net_lwip_webserver/skip.txt b/examples/device/net_lwip_webserver/skip.txt index 53836b581c..71bf26fdbd 100644 --- a/examples/device/net_lwip_webserver/skip.txt +++ b/examples/device/net_lwip_webserver/skip.txt @@ -1,6 +1,7 @@ mcu:APM32F0XX mcu:CH32V103 mcu:CH32V20X +mcu:CH32X035 mcu:LPC11UXX mcu:LPC13XX mcu:LPC15XX diff --git a/hw/bsp/ch32x035/boards/weact_ch32x035_core_board/board.cmake b/hw/bsp/ch32x035/boards/weact_ch32x035_core_board/board.cmake index 36dd500e3e..4687e127fe 100644 --- a/hw/bsp/ch32x035/boards/weact_ch32x035_core_board/board.cmake +++ b/hw/bsp/ch32x035/boards/weact_ch32x035_core_board/board.cmake @@ -4,6 +4,5 @@ set(LD_RAM_SIZE 20K) function(update_board TARGET) target_compile_definitions(${TARGET} PUBLIC SYSCLK_FREQ_48MHz_HSI=48000000 - CFG_EXAMPLE_MSC_DUAL_READONLY ) endfunction() diff --git a/hw/bsp/ch32x035/boards/weact_ch32x035_core_board/board.mk b/hw/bsp/ch32x035/boards/weact_ch32x035_core_board/board.mk index bbd8106f39..b6698c9721 100644 --- a/hw/bsp/ch32x035/boards/weact_ch32x035_core_board/board.mk +++ b/hw/bsp/ch32x035/boards/weact_ch32x035_core_board/board.mk @@ -1,6 +1,4 @@ -CFLAGS += \ - -DSYSCLK_FREQ_48MHz_HSI=48000000 \ - -DCFG_EXAMPLE_MSC_DUAL_READONLY \ +CFLAGS += -DSYSCLK_FREQ_48MHz_HSI=48000000 LDFLAGS += \ -Wl,--defsym=__FLASH_SIZE=62K \ diff --git a/hw/bsp/ch32x035/family.cmake b/hw/bsp/ch32x035/family.cmake index 1ec1bb01b0..2eb9f20e77 100644 --- a/hw/bsp/ch32x035/family.cmake +++ b/hw/bsp/ch32x035/family.cmake @@ -49,6 +49,8 @@ function(family_add_board BOARD_TARGET) ) target_compile_definitions(${BOARD_TARGET} PUBLIC BOARD_TUD_RHPORT=${RHPORT_DEVICE} + CFG_EXAMPLE_MSC_DUAL_READONLY + CFG_EXAMPLE_VIDEO_READONLY ) update_board(${BOARD_TARGET}) diff --git a/hw/bsp/ch32x035/family.mk b/hw/bsp/ch32x035/family.mk index 5d2ef64158..715ef810c1 100644 --- a/hw/bsp/ch32x035/family.mk +++ b/hw/bsp/ch32x035/family.mk @@ -14,6 +14,8 @@ CFLAGS += \ -flto \ -DCFG_TUSB_MCU=OPT_MCU_CH32X035 \ -DCFG_TUD_WCH_USBIP_USBFS=1 \ + -DCFG_EXAMPLE_MSC_DUAL_READONLY=1 \ + -DCFG_EXAMPLE_VIDEO_READONLY=1 CFLAGS += -Wno-error=strict-prototypes diff --git a/src/portable/wch/dcd_ch32_usbfs.c b/src/portable/wch/dcd_ch32_usbfs.c index 421c1ec69b..b527fa8e0e 100644 --- a/src/portable/wch/dcd_ch32_usbfs.c +++ b/src/portable/wch/dcd_ch32_usbfs.c @@ -58,8 +58,7 @@ // There's a gap between EP4 and EP5 registers. #define EP_DMA(ep) (*ch32_usbfs_ep_dma_reg(ep)) #define EP_TX_LEN(ep) ((&USBOTG_FS->UEP0_TX_LEN)[2 * (ep) + ((ep) > 4 ? 24 : 0)]) - #define EP_TX_CTRL(ep) ((&USBOTG_FS->UEP0_CTRL_H)[2 * (ep) + ((ep) > 4 ? 24 : 0)]) - #define EP_RX_CTRL(ep) EP_TX_CTRL(ep) + #define EP_CTRL(ep) ((&USBOTG_FS->UEP0_CTRL_H)[2 * (ep) + ((ep) > 4 ? 24 : 0)]) #else #define EP_DMA(ep) ((&USBOTG_FS->UEP0_DMA)[ep]) #define EP_TX_LEN(ep) ((&USBOTG_FS->UEP0_TX_LEN)[2 * ep]) @@ -71,10 +70,6 @@ // endpoint; others have a single combined UEPn_CTRL register. These helpers hide the difference. // Values use the newer-IP encoding (USBFS_EP_T_*/USBFS_EP_R_*); the combined path remaps them. #ifdef CH32_USBFS_EP_CTRL_COMBINED - #ifndef EP_CTRL // parts with a custom register map (CH58X) define EP_CTRL directly in reg.h - #define EP_CTRL(ep) EP_TX_CTRL(ep) // UEPn_TX_CTRL field aliases the combined UEPn_CTRL register - #endif - static inline uint8_t ep_tx_to_comb(uint8_t v) { uint8_t c = v & USBFS_EP_T_RES_MASK; // IN response: bits [1:0] in both encodings if (v & USBFS_EP_T_TOG) { c |= USBFS_EPC_T_TOG; } @@ -325,11 +320,7 @@ bool dcd_init(uint8_t rhport, const tusb_rhport_init_t *rh_init) { // enable other endpoints but NAK everything USBOTG_FS->UEP4_1_MOD = 0xCC; USBOTG_FS->UEP2_3_MOD = 0xCC; -#if CFG_TUSB_MCU == OPT_MCU_CH583 - // CH58X: a single mode register enables EP5/6/7 RX+TX (different bit layout than CH32). - USBOTG_FS->UEP567_MOD = RB_UEP5_RX_EN | RB_UEP5_TX_EN | RB_UEP6_RX_EN | RB_UEP6_TX_EN | - RB_UEP7_RX_EN | RB_UEP7_TX_EN; -#elif CFG_TUSB_MCU == OPT_MCU_CH32X035 +#if CFG_TUSB_MCU == OPT_MCU_CH583 || CFG_TUSB_MCU == OPT_MCU_CH32X035 USBOTG_FS->UEP567_MOD = 0x3F; #else USBOTG_FS->UEP5_6_MOD = 0xCC; From e19fea6898593e1010219ccec19acf0de3d13072 Mon Sep 17 00:00:00 2001 From: Jie Feng Date: Tue, 23 Jun 2026 12:59:27 +0800 Subject: [PATCH 03/13] EP buffer cleanup and fix UART --- hw/bsp/ch32x035/family.c | 2 +- src/portable/wch/dcd_ch32_usbfs.c | 129 ++++++++++++++++-------------- 2 files changed, 72 insertions(+), 59 deletions(-) diff --git a/hw/bsp/ch32x035/family.c b/hw/bsp/ch32x035/family.c index edfaa6fbcf..1e31add8f0 100644 --- a/hw/bsp/ch32x035/family.c +++ b/hw/bsp/ch32x035/family.c @@ -160,7 +160,7 @@ int board_uart_write(const void *buf, int len) { const uint8_t *p = (const uint8_t *)buf; int count = 0; while (count < len) { - if (USART_GetFlagStatus(UART_DEV, USART_FLAG_TC) != RESET) { + if (USART_GetFlagStatus(UART_DEV, USART_FLAG_TXE) != RESET) { USART_SendData(UART_DEV, p[count]); count++; } else { diff --git a/src/portable/wch/dcd_ch32_usbfs.c b/src/portable/wch/dcd_ch32_usbfs.c index b527fa8e0e..c961b40098 100644 --- a/src/portable/wch/dcd_ch32_usbfs.c +++ b/src/portable/wch/dcd_ch32_usbfs.c @@ -42,6 +42,7 @@ : (ep) == 4u ? &USBOTG_FS->EP_DMA_0_3[0].DMA \ : &USBOTG_FS->EP_DMA_5_7[0].DMA + ((ep) - 5u) * 2u)) #elif CFG_TUSB_MCU == OPT_MCU_CH32X035 + // EP0-4 and EP5-7 are split, and EP4 has no DMA register static inline volatile uint32_t* ch32_usbfs_ep_dma_reg(uint8_t ep) { switch (ep) { case 0: return &USBOTG_FS->UEP0_DMA; @@ -66,10 +67,14 @@ #define EP_RX_CTRL(ep) ((&USBOTG_FS->UEP0_RX_CTRL)[4 * ep]) #endif -// Endpoint control register access. Some WCH USBFS IPs have separate TX_CTRL/RX_CTRL bytes per -// endpoint; others have a single combined UEPn_CTRL register. These helpers hide the difference. -// Values use the newer-IP encoding (USBFS_EP_T_*/USBFS_EP_R_*); the combined path remaps them. +// Map generic TX/RX control values to split or combined endpoint control registers. +// Combined: V103/CH58X/X035 +// Split: V20x/V307 #ifdef CH32_USBFS_EP_CTRL_COMBINED + #ifndef EP_CTRL // parts with a custom register map (CH58X) define EP_CTRL directly in reg.h + #define EP_CTRL(ep) EP_TX_CTRL(ep) // UEPn_TX_CTRL field aliases the combined UEPn_CTRL register + #endif + static inline uint8_t ep_tx_to_comb(uint8_t v) { uint8_t c = v & USBFS_EP_T_RES_MASK; // IN response: bits [1:0] in both encodings if (v & USBFS_EP_T_TOG) { c |= USBFS_EPC_T_TOG; } @@ -134,98 +139,105 @@ static struct { bool isochronous[EP_MAX][2]; // per [ep][dir]: an ep number may be iso in one direction struct usb_xfer xfer[EP_MAX][2]; #ifdef CH32_USBFS_EP4_SHARES_EP0 - // CH58X buffers laid out by hand so EP0/EP4 don't burn two unused buffer[] slots. EP0 and EP4 + // CH58X/X035 buffers laid out by hand so EP0/EP4 don't burn two unused buffer[] slots. EP0 and EP4 // share one contiguous 192-byte DMA region (EP4 has no DMA register of its own): // EP0 [0:63] (half-duplex OUT+IN) + EP4 OUT [64:127] + EP4 IN [128:191]. Every other endpoint - // (incl. EP3, which is bulk-only here — CH58X has no isochronous support) gets a plain 128-byte - // OUT+IN buffer, so no oversized EP3 buffer is needed. - TU_ATTR_ALIGNED(4) uint8_t ep0_ep4_buffer[3 * 64]; - TU_ATTR_ALIGNED(4) uint8_t ep1_buffer[2][64]; - TU_ATTR_ALIGNED(4) uint8_t ep2_buffer[2][64]; - TU_ATTR_ALIGNED(4) uint8_t ep3_buffer[2][64]; - TU_ATTR_ALIGNED(4) uint8_t ep5_buffer[2][64]; - TU_ATTR_ALIGNED(4) uint8_t ep6_buffer[2][64]; - TU_ATTR_ALIGNED(4) uint8_t ep7_buffer[2][64]; + // gets a plain 128-byte OUT+IN buffer. + TU_ATTR_ALIGNED(4) union { + uint8_t ep0_ep4_buffer[3 * 64]; + struct { + uint8_t ep0_buffer[64]; + uint8_t ep4_buffer[2][64]; + }; + }; + TU_ATTR_ALIGNED(4) uint8_t buffer[6][2][64]; #else - // Every endpoint gets a 64-byte OUT + 64-byte IN buffer. - TU_ATTR_ALIGNED(4) uint8_t buffer[EP_MAX][2][64]; #if CFG_TUD_WCH_USBFS_EP3_BUFSIZE > 64 - // ...except EP3, which supports full-speed iso packets up to 1023 B on CH32V20x/V30x/F20x, so its - // IN buffer is enlarged (OUT stays 64 B; an OUT transfer >64 B on EP3 would overwrite queued IN). + // EP3 uses the enlarged buffer below, so omit its regular 128-byte slot. + TU_ATTR_ALIGNED(4) uint8_t buffer[EP_MAX - 1][2][64]; + // EP3 supports full-speed iso packets up to 1023 B on CH32V20x/V30x/F20x. Its IN buffer is + // enlarged; OUT stays 64 B, so an OUT transfer over 64 B would overwrite queued IN data. TU_ATTR_ALIGNED(4) struct { uint8_t out[64]; uint8_t in[CFG_TUD_WCH_USBFS_EP3_BUFSIZE]; uint8_t pad; } ep3_buffer; + #else + TU_ATTR_ALIGNED(4) uint8_t buffer[EP_MAX][2][64]; #endif #endif } data; // DMA / copy buffer pointers per endpoint. The WCH USBFS buffer holds OUT (RX) at offset 0 and -// IN (TX) at +64; EP0 is half-duplex and reuses its OUT chunk for IN. On CH58X, EP0/EP4 share +// IN (TX) at +64; EP0 is half-duplex and reuses its OUT chunk for IN. On CH58X/X035, EP0/EP4 share // ep0_ep4_buffer and the regular endpoints use their own named buffer (see the struct above). #ifdef CH32_USBFS_EP4_SHARES_EP0 -// OUT base of the regular CH58X endpoints (EP1/2/3/5/6/7; EP0/EP4 share ep0_ep4_buffer). -static inline uint8_t* ch58x_ep_buffer(uint8_t ep) { +static inline uint8_t* ep_buffer(uint8_t ep, uint8_t dir) { switch (ep) { - case 1: return data.ep1_buffer[0]; - case 2: return data.ep2_buffer[0]; - case 3: return data.ep3_buffer[0]; - case 5: return data.ep5_buffer[0]; - case 6: return data.ep6_buffer[0]; - default: return data.ep7_buffer[0]; // ep == 7 + case 1: return data.buffer[0][dir]; + case 2: return data.buffer[1][dir]; + case 3: return data.buffer[2][dir]; + case 4: return data.ep4_buffer[dir]; + case 5: return data.buffer[3][dir]; + case 6: return data.buffer[4][dir]; + default: return data.buffer[5][dir]; // ep == 7 } } -#endif static inline uint32_t ep_dma_addr(uint8_t ep) { -#ifdef CH32_USBFS_EP4_SHARES_EP0 - if (ep == 0 || ep == 4) { return (uint32_t) &data.ep0_ep4_buffer[0]; } // EP4 shares EP0's DMA - return (uint32_t) ch58x_ep_buffer(ep); + if (ep == 0 || ep == 4) { return (uint32_t) data.ep0_ep4_buffer; } // EP4 shares EP0's DMA + return (uint32_t) ep_buffer(ep, TUSB_DIR_OUT); +} + +static inline uint8_t* ep_out_buf(uint8_t ep) { + if (ep == 0) { return data.ep0_buffer; } + return ep_buffer(ep, TUSB_DIR_OUT); +} + +static inline uint8_t* ep_in_buf(uint8_t ep) { + if (ep == 0) { return data.ep0_buffer; } // EP0 half-duplex: IN reuses OUT chunk + return ep_buffer(ep, TUSB_DIR_IN); +} + +// EP4 on CH58X/X035 has no DMA register (shares EP0's); skip its EP_DMA() write. +static inline bool ep_shares_ep0_dma(uint8_t ep) { + return ep == 4; +} #else +static inline uint8_t* ep_buffer(uint8_t ep, uint8_t dir) { #if CFG_TUD_WCH_USBFS_EP3_BUFSIZE > 64 - if (ep == 3) { return (uint32_t) &data.ep3_buffer.out[0]; } // EP3 has an enlarged IN buffer + if (ep > 3) { return data.buffer[ep - 1][dir]; } #endif - return (uint32_t) &data.buffer[ep][0]; -#endif + return data.buffer[ep][dir]; +} + +static inline uint32_t ep_dma_addr(uint8_t ep) { + #if CFG_TUD_WCH_USBFS_EP3_BUFSIZE > 64 + if (ep == 3) { return (uint32_t) &data.ep3_buffer.out[0]; } + #endif + return (uint32_t) ep_buffer(ep, TUSB_DIR_OUT); } static inline uint8_t* ep_out_buf(uint8_t ep) { -#ifdef CH32_USBFS_EP4_SHARES_EP0 - if (ep == 0) { return &data.ep0_ep4_buffer[0]; } - if (ep == 4) { return &data.ep0_ep4_buffer[64]; } - return ch58x_ep_buffer(ep); -#else #if CFG_TUD_WCH_USBFS_EP3_BUFSIZE > 64 if (ep == 3) { return data.ep3_buffer.out; } #endif - return data.buffer[ep][TUSB_DIR_OUT]; -#endif + return ep_buffer(ep, TUSB_DIR_OUT); } static inline uint8_t* ep_in_buf(uint8_t ep) { -#ifdef CH32_USBFS_EP4_SHARES_EP0 - if (ep == 0) { return &data.ep0_ep4_buffer[0]; } // EP0 half-duplex: IN reuses OUT chunk - if (ep == 4) { return &data.ep0_ep4_buffer[128]; } - return ch58x_ep_buffer(ep) + 64; // IN at +64 within the endpoint's 128-byte buffer -#else - if (ep == 0) { return data.buffer[0][TUSB_DIR_OUT]; } // EP0 half-duplex: IN reuses OUT chunk + if (ep == 0) { return ep_buffer(0, TUSB_DIR_OUT); } // EP0 half-duplex: IN reuses OUT chunk #if CFG_TUD_WCH_USBFS_EP3_BUFSIZE > 64 - if (ep == 3) { return data.ep3_buffer.in; } // enlarged IN buffer for full-speed iso + if (ep == 3) { return data.ep3_buffer.in; } #endif - return data.buffer[ep][TUSB_DIR_IN]; -#endif + return ep_buffer(ep, TUSB_DIR_IN); } -// EP4 on CH58X has no DMA register (shares EP0's); skip its EP_DMA() write. static inline bool ep_shares_ep0_dma(uint8_t ep) { -#ifdef CH32_USBFS_EP4_SHARES_EP0 - return ep == 4; -#else (void) ep; return false; -#endif } +#endif /* private helpers */ static void update_in(uint8_t rhport, uint8_t ep, bool force) { @@ -233,9 +245,9 @@ static void update_in(uint8_t rhport, uint8_t ep, bool force) { if (xfer->valid) { if (force || xfer->len) { size_t len = TU_MIN(xfer->max_size, xfer->len); -#if CFG_TUSB_MCU == OPT_MCU_CH583 - // Every CH58x endpoint buffer is 64 bytes; cap the copy so an iso mps a class mistakenly set - // larger can't write past the buffer into a neighbouring endpoint's. +#if CFG_TUSB_MCU == OPT_MCU_CH583 || CFG_TUSB_MCU == OPT_MCU_CH32X035 + // Every CH58x/X035 endpoint buffer is 64 bytes; cap the copy so a bad iso mps cannot write + // past the buffer into a neighbouring endpoint's. len = TU_MIN(len, 64u); #endif memcpy(ep_in_buf(ep), xfer->buffer, len); @@ -268,7 +280,7 @@ static void update_out(uint8_t rhport, uint8_t ep, size_t rx_len) { 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 CFG_TUSB_MCU == OPT_MCU_CH583 +#if CFG_TUSB_MCU == OPT_MCU_CH583 || CFG_TUSB_MCU == OPT_MCU_CH32X035 len = TU_MIN(len, 64u); // cap to the 64-byte EP buffer (see update_in) #endif memcpy(xfer->buffer, ep_out_buf(ep), len); @@ -321,6 +333,7 @@ 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; #if CFG_TUSB_MCU == OPT_MCU_CH583 || CFG_TUSB_MCU == OPT_MCU_CH32X035 + // CH58X: a single mode register enables EP5/6/7 RX+TX (different bit layout than CH32). USBOTG_FS->UEP567_MOD = 0x3F; #else USBOTG_FS->UEP5_6_MOD = 0xCC; From 29f2606c9e39a34a1c78bdc5681b2b44c64a4582 Mon Sep 17 00:00:00 2001 From: Jie Feng Date: Sat, 4 Jul 2026 17:29:12 +0800 Subject: [PATCH 04/13] Sync make and cmake --- hw/bsp/ch32x035/family.cmake | 3 --- hw/bsp/ch32x035/family.mk | 1 - 2 files changed, 4 deletions(-) diff --git a/hw/bsp/ch32x035/family.cmake b/hw/bsp/ch32x035/family.cmake index 2eb9f20e77..35d8c04d6f 100644 --- a/hw/bsp/ch32x035/family.cmake +++ b/hw/bsp/ch32x035/family.cmake @@ -15,8 +15,6 @@ set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/riscv_${TO set(FAMILY_MCUS CH32X035 CACHE INTERNAL "") set(OPENOCD_OPTION "-f ${CMAKE_CURRENT_LIST_DIR}/wch-riscv.cfg") -set(RHPORT_DEVICE 0) - #------------------------------------ # Startup & Linker script #------------------------------------ @@ -48,7 +46,6 @@ function(family_add_board BOARD_TARGET) ${CMAKE_CURRENT_FUNCTION_LIST_DIR} ) target_compile_definitions(${BOARD_TARGET} PUBLIC - BOARD_TUD_RHPORT=${RHPORT_DEVICE} CFG_EXAMPLE_MSC_DUAL_READONLY CFG_EXAMPLE_VIDEO_READONLY ) diff --git a/hw/bsp/ch32x035/family.mk b/hw/bsp/ch32x035/family.mk index 715ef810c1..f389bed723 100644 --- a/hw/bsp/ch32x035/family.mk +++ b/hw/bsp/ch32x035/family.mk @@ -13,7 +13,6 @@ CFLAGS += \ -ffat-lto-objects \ -flto \ -DCFG_TUSB_MCU=OPT_MCU_CH32X035 \ - -DCFG_TUD_WCH_USBIP_USBFS=1 \ -DCFG_EXAMPLE_MSC_DUAL_READONLY=1 \ -DCFG_EXAMPLE_VIDEO_READONLY=1 From 9e2dab6f98ba29ccce970641d1d8d863b4920ff3 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Sun, 19 Jul 2026 15:12:37 +0200 Subject: [PATCH 05/13] fix audio debug script PID Signed-off-by: HiFiPhile --- examples/device/uac2_speaker_fb/src/audio_debug.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/device/uac2_speaker_fb/src/audio_debug.py b/examples/device/uac2_speaker_fb/src/audio_debug.py index 1c6035a440..d345c4a116 100755 --- a/examples/device/uac2_speaker_fb/src/audio_debug.py +++ b/examples/device/uac2_speaker_fb/src/audio_debug.py @@ -14,7 +14,7 @@ # Example must be compiled with CFG_AUDIO_DEBUG=1 VID = 0xcafe -PID = 0x4014 +PID = 0x401b CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX = 2 From b7ef2f4d8246964716e0f9b5692138801ffdfa5a Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Sun, 19 Jul 2026 15:21:45 +0200 Subject: [PATCH 06/13] update example skip Signed-off-by: HiFiPhile --- examples/device/audio_4_channel_mic/skip.txt | 1 + examples/device/audio_test/skip.txt | 1 + examples/device/audio_test_multi_rate/skip.txt | 1 + examples/device/uac2_headset/skip.txt | 3 +++ examples/device/uac2_speaker_fb/skip.txt | 3 +++ 5 files changed, 9 insertions(+) diff --git a/examples/device/audio_4_channel_mic/skip.txt b/examples/device/audio_4_channel_mic/skip.txt index e5e74cd60a..53f8f9c5a2 100644 --- a/examples/device/audio_4_channel_mic/skip.txt +++ b/examples/device/audio_4_channel_mic/skip.txt @@ -3,3 +3,4 @@ mcu:SAMG family:broadcom_64bit family:espressif mcu:CH583 +mcu:CH32X035 diff --git a/examples/device/audio_test/skip.txt b/examples/device/audio_test/skip.txt index 862c91c6f3..b48f79a679 100644 --- a/examples/device/audio_test/skip.txt +++ b/examples/device/audio_test/skip.txt @@ -2,3 +2,4 @@ mcu:SAMD11 mcu:SAMG family:espressif mcu:CH583 +mcu:CH32X035 diff --git a/examples/device/audio_test_multi_rate/skip.txt b/examples/device/audio_test_multi_rate/skip.txt index 862c91c6f3..b48f79a679 100644 --- a/examples/device/audio_test_multi_rate/skip.txt +++ b/examples/device/audio_test_multi_rate/skip.txt @@ -2,3 +2,4 @@ mcu:SAMD11 mcu:SAMG family:espressif mcu:CH583 +mcu:CH32X035 diff --git a/examples/device/uac2_headset/skip.txt b/examples/device/uac2_headset/skip.txt index 3159cb1768..d53fb1d843 100644 --- a/examples/device/uac2_headset/skip.txt +++ b/examples/device/uac2_headset/skip.txt @@ -6,3 +6,6 @@ mcu:SAMG board:stm32l052dap52 family:espressif mcu:CH583 +mcu:CH32X035 +mcu:CH32V103 +mcu:CH32V20X diff --git a/examples/device/uac2_speaker_fb/skip.txt b/examples/device/uac2_speaker_fb/skip.txt index 88df3e549b..17f9c6dbe2 100644 --- a/examples/device/uac2_speaker_fb/skip.txt +++ b/examples/device/uac2_speaker_fb/skip.txt @@ -6,3 +6,6 @@ mcu:SAMG board:stm32l052dap52 family:broadcom_64bit mcu:CH583 +mcu:CH32X035 +mcu:CH32V103 +mcu:CH32V20X From 2f3aaca4f714fb56cbdf7973e3e15ec8ec5940cb Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Sun, 19 Jul 2026 15:27:17 +0200 Subject: [PATCH 07/13] update readme Signed-off-by: HiFiPhile --- README.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.rst b/README.rst index 024c5bec86..e1abb7c9ad 100644 --- a/README.rst +++ b/README.rst @@ -315,7 +315,7 @@ Supported CPUs | +-----------------------------+--------+------+-----------+------------------------+--------------------+ | | CH583/2, CH32V103 | 🟡 | | ❌ | ch32_usbfs | ISO data loss [2]_ | | +-----------------------------+--------+------+-----------+------------------------+--------------------+ -| | CH32X033, CH32X035 | ✅ | | ❌ | ch32_usbfs | EP4 quirk | +| | CH32X033, CH32X035 | 🟡 | | ❌ | ch32_usbfs | ISO data loss [2]_ | +--------------+-----------------------------+--------+------+-----------+------------------------+--------------------+ Table Legend From 333aa946c9a0c4c175a59f0b14a01c75c307a9af Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Sun, 19 Jul 2026 18:12:19 +0200 Subject: [PATCH 08/13] fix ep0 out toggle check Signed-off-by: HiFiPhile --- src/portable/wch/dcd_ch32_usbfs.c | 43 ++++++++++++++++++------------- 1 file changed, 25 insertions(+), 18 deletions(-) diff --git a/src/portable/wch/dcd_ch32_usbfs.c b/src/portable/wch/dcd_ch32_usbfs.c index c961b40098..ce14211210 100644 --- a/src/portable/wch/dcd_ch32_usbfs.c +++ b/src/portable/wch/dcd_ch32_usbfs.c @@ -101,7 +101,6 @@ static inline void ep_rx_set_response(uint8_t ep, uint8_t res) { EP_CTRL(ep) = (uint8_t) ((EP_CTRL(ep) & ~USBFS_EPC_R_RES_MASK) | ((res & USBFS_EP_R_RES_MASK) << USBFS_EPC_R_RES_SHIFT)); } - #define EP0_SETUP_RX_TOG USBFS_EP_R_TOG // combined IP: data/status stage after SETUP is DATA1 #else static inline void ep_tx_ctrl_set(uint8_t ep, uint8_t v) { EP_TX_CTRL(ep) = v; } static inline void ep_rx_ctrl_set(uint8_t ep, uint8_t v) { EP_RX_CTRL(ep) = v; } @@ -111,7 +110,6 @@ static inline void ep_rx_set_response(uint8_t ep, uint8_t res) { EP_RX_CTRL(ep) = (uint8_t) ((EP_RX_CTRL(ep) & ~USBFS_EP_R_RES_MASK) | res); } - #define EP0_SETUP_RX_TOG 0 #endif // Hardware auto data-toggle flag. Parts whose AUTO_TOG is reliable OR it into the EP setup so the @@ -136,6 +134,7 @@ struct usb_xfer { static struct { bool ep0_tog; + uint8_t ep0_status_dir; bool isochronous[EP_MAX][2]; // per [ep][dir]: an ep number may be iso in one direction struct usb_xfer xfer[EP_MAX][2]; #ifdef CH32_USBFS_EP4_SHARES_EP0 @@ -258,7 +257,6 @@ static void update_in(uint8_t rhport, uint8_t ep, bool force) { EP_TX_LEN(ep) = len; if (ep == 0) { ep_tx_ctrl_set(0, USBFS_EP_T_RES_ACK | (data.ep0_tog ? USBFS_EP_T_TOG : 0)); - data.ep0_tog = !data.ep0_tog; } else if (data.isochronous[ep][TUSB_DIR_IN]) { ep_tx_set_response(ep, USBFS_EP_T_RES_NYET); } else { @@ -294,7 +292,7 @@ static void update_out(uint8_t rhport, uint8_t ep, size_t rx_len) { } if (ep == 0) { - ep_rx_set_response(0, USBFS_EP_R_RES_NAK); + ep_rx_ctrl_set(0, USBFS_EP_R_RES_NAK | (data.ep0_tog ? USBFS_EP_R_TOG : 0)); } else { uint8_t rx_res = data.isochronous[ep][TUSB_DIR_OUT] ? USBFS_EP_R_RES_NYET : (xfer->valid ? USBFS_EP_R_RES_ACK : USBFS_EP_R_RES_NAK); @@ -358,23 +356,22 @@ void dcd_int_handler(uint8_t rhport) { switch (token) { case PID_OUT: { - // Drop an OUT packet whose data toggle doesn't match what we expect -- a host retransmit - // after a lost ACK, or a host that doesn't alternate DATA0/DATA1. The hardware auto-toggle - // does not reject these on its own, so the check is needed on every variant. EP0 keeps its - // own toggle via the SETUP/status flow and is exempt; isochronous is DATA0-only (no toggle), - // so its packets must not be toggle-checked. - if (ep != 0 && !data.isochronous[ep][TUSB_DIR_OUT] && !(int_st & USBFS_INT_ST_TOG_OK)) { break; } + // A lost ACK makes the host retry the previous DATA PID. Drop the duplicate before it + // reaches the transfer state and before advancing the expected toggle. EP0 owns its + // toggle in ep0_tog on every variant; isochronous endpoints are DATA0-only (no toggle). + if (!data.isochronous[ep][TUSB_DIR_OUT] && !(int_st & USBFS_INT_ST_TOG_OK)) { break; } + if (ep == 0) { data.ep0_tog = !data.ep0_tog; } #ifdef CH32_USBFS_EP_MANUAL_TOG - // CH58x has no hardware auto-toggle: advance the expected RX toggle after each accepted packet - // (EP0 included -- it also has no auto-toggle and a control-OUT data stage can span packets). - // Iso endpoints are DATA0-only, so leave them alone (matches the PID_IN path). - if (!data.isochronous[ep][TUSB_DIR_OUT]) { EP_CTRL(ep) ^= USBFS_EPC_R_TOG; } + // Advance the expected RX toggle after each accepted packet. Iso endpoints are DATA0-only, + // and EP0 is handled explicitly from ep0_tog, so leave both alone. + if (ep != 0 && !data.isochronous[ep][TUSB_DIR_OUT]) { EP_CTRL(ep) ^= USBFS_EPC_R_TOG; } #endif update_out(rhport, ep, rx_len); break; } case PID_IN: + if (ep == 0) { data.ep0_tog = !data.ep0_tog; } #ifdef CH32_USBFS_EP_MANUAL_TOG // Manual toggle: flip the TX toggle after each ACK'd IN packet (EP0 manages its own). // Isochronous transfers are DATA0-only (no toggle), so leave iso endpoints alone. @@ -385,8 +382,8 @@ void dcd_int_handler(uint8_t rhport) { case PID_SETUP: // setup clears stall - ep_tx_ctrl_set(0, USBFS_EP_T_RES_NAK); data.ep0_tog = true; + ep_tx_ctrl_set(0, USBFS_EP_T_RES_NAK | USBFS_EP_T_TOG); // A new SETUP supersedes any control transfer still in flight; drop its stale EP0 state so a // spurious EP0 IN/OUT can't run update_in()/update_out() against the previous request. data.xfer[0][TUSB_DIR_OUT].valid = false; @@ -394,8 +391,10 @@ void dcd_int_handler(uint8_t rhport) { uint8_t *ep0_out = ep_out_buf(0); const tusb_control_request_t *setup = (const tusb_control_request_t *)ep0_out; - // EP0_SETUP_RX_TOG arms the data/status stage at DATA1 on the combined-control IP - ep_rx_ctrl_set(0, ((setup->wLength == 0) ? USBFS_EP_R_RES_ACK : USBFS_EP_R_RES_NAK) | EP0_SETUP_RX_TOG); + data.ep0_status_dir = (setup->wLength && setup->bmRequestType_bit.direction == TUSB_DIR_IN) ? TUSB_DIR_OUT + : TUSB_DIR_IN; + // The first transaction of either the data or status stage always uses DATA1. + ep_rx_ctrl_set(0, ((setup->wLength == 0) ? USBFS_EP_R_RES_ACK : USBFS_EP_R_RES_NAK) | USBFS_EP_R_TOG); dcd_event_setup_received(rhport, ep0_out, true); break; @@ -555,6 +554,10 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t to // read-modify-write of the (combined) EP control register, which the ISR also RMWs to flip the // manual data toggle; re-enabling before they run lets a transfer IRQ clobber that toggle. dcd_int_disable(rhport); + // The status stage is opposite the data direction (or IN when there is no data) and always + // uses DATA1. A zero-length data packet remains in the data direction and keeps its sequence. + if (ep == 0 && total_bytes == 0 && dir == data.ep0_status_dir) { data.ep0_tog = true; } + xfer->valid = true; xfer->buffer = buffer; xfer->len = total_bytes; @@ -564,7 +567,11 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t to update_in(rhport, ep, true); } else { uint8_t rx_res = data.isochronous[ep][TUSB_DIR_OUT] ? USBFS_EP_R_RES_NYET : USBFS_EP_R_RES_ACK; - ep_rx_set_response(ep, rx_res); + if (ep == 0) { + ep_rx_ctrl_set(0, rx_res | (data.ep0_tog ? USBFS_EP_R_TOG : 0)); + } else { + ep_rx_set_response(ep, rx_res); + } } dcd_int_enable(rhport); return true; From 193360136c780cdac1e58cdf3f9da66dfbe5ccf7 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Sun, 19 Jul 2026 18:35:27 +0200 Subject: [PATCH 09/13] fix ep3 buffer addr Signed-off-by: HiFiPhile --- src/portable/wch/dcd_ch32_usbfs.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/src/portable/wch/dcd_ch32_usbfs.c b/src/portable/wch/dcd_ch32_usbfs.c index ce14211210..2f7fa55e91 100644 --- a/src/portable/wch/dcd_ch32_usbfs.c +++ b/src/portable/wch/dcd_ch32_usbfs.c @@ -205,30 +205,22 @@ static inline bool ep_shares_ep0_dma(uint8_t ep) { #else static inline uint8_t* ep_buffer(uint8_t ep, uint8_t dir) { #if CFG_TUD_WCH_USBFS_EP3_BUFSIZE > 64 + if (ep == 3) { return dir == TUSB_DIR_IN ? data.ep3_buffer.in : data.ep3_buffer.out; } if (ep > 3) { return data.buffer[ep - 1][dir]; } #endif return data.buffer[ep][dir]; } static inline uint32_t ep_dma_addr(uint8_t ep) { - #if CFG_TUD_WCH_USBFS_EP3_BUFSIZE > 64 - if (ep == 3) { return (uint32_t) &data.ep3_buffer.out[0]; } - #endif return (uint32_t) ep_buffer(ep, TUSB_DIR_OUT); } static inline uint8_t* ep_out_buf(uint8_t ep) { - #if CFG_TUD_WCH_USBFS_EP3_BUFSIZE > 64 - if (ep == 3) { return data.ep3_buffer.out; } - #endif return ep_buffer(ep, TUSB_DIR_OUT); } static inline uint8_t* ep_in_buf(uint8_t ep) { if (ep == 0) { return ep_buffer(0, TUSB_DIR_OUT); } // EP0 half-duplex: IN reuses OUT chunk - #if CFG_TUD_WCH_USBFS_EP3_BUFSIZE > 64 - if (ep == 3) { return data.ep3_buffer.in; } - #endif return ep_buffer(ep, TUSB_DIR_IN); } From 3f25e38c19e957ff72683a0e0b8c9b58c87c96a6 Mon Sep 17 00:00:00 2001 From: Jie Feng Date: Mon, 20 Jul 2026 01:13:03 +0800 Subject: [PATCH 10/13] Restrict MANUAL_TOG to EP4 --- src/portable/wch/ch32_usbfs_reg.h | 4 ++-- src/portable/wch/dcd_ch32_usbfs.c | 30 +++++++++++++++--------------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/portable/wch/ch32_usbfs_reg.h b/src/portable/wch/ch32_usbfs_reg.h index 9d2efa2fb6..e73a8b3ae2 100644 --- a/src/portable/wch/ch32_usbfs_reg.h +++ b/src/portable/wch/ch32_usbfs_reg.h @@ -168,7 +168,7 @@ // CH58x's hardware AUTO_TOG does not stay in sync (notably across clear-stall and multi-packet // bulk transfers), causing data-toggle mismatch and bus resets. Drive the toggle manually in // the ISR instead. CH32V103/V20x/V307 keep AUTO_TOG (this macro is undefined for them). - #define CH32_USBFS_EP_MANUAL_TOG 1 + #define CH32_USBFS_EP4_MANUAL_TOG 1 // CH58x EP4 has no DMA register of its own: it overlays EP0's DMA region as // EP0[0:63] + EP4_OUT[64:127] + EP4_IN[128:191], so EP0 needs a 192-byte buffer. #define CH32_USBFS_EP4_SHARES_EP0 1 @@ -181,7 +181,7 @@ #include #define USBOTG_FS USBFSD #define CH32_USBFS_EP_CTRL_COMBINED 1 - #define CH32_USBFS_EP_MANUAL_TOG 1 + #define CH32_USBFS_EP4_MANUAL_TOG 1 #define CH32_USBFS_EP4_SHARES_EP0 1 #define USBHD_IRQn USBFS_IRQn #endif diff --git a/src/portable/wch/dcd_ch32_usbfs.c b/src/portable/wch/dcd_ch32_usbfs.c index 2f7fa55e91..25c9bfd168 100644 --- a/src/portable/wch/dcd_ch32_usbfs.c +++ b/src/portable/wch/dcd_ch32_usbfs.c @@ -113,15 +113,10 @@ #endif // Hardware auto data-toggle flag. Parts whose AUTO_TOG is reliable OR it into the EP setup so the -// controller flips DATA0/DATA1 itself; CH58x (CH32_USBFS_EP_MANUAL_TOG) leaves it clear and the +// controller flips DATA0/DATA1 itself; CH58x (CH32_USBFS_EP4_MANUAL_TOG) leaves it clear and the // ISR flips the toggle bit after each packet instead. -#ifdef CH32_USBFS_EP_MANUAL_TOG - #define EP_T_AUTO_TOG 0 - #define EP_R_AUTO_TOG 0 -#else - #define EP_T_AUTO_TOG USBFS_EP_T_AUTO_TOG - #define EP_R_AUTO_TOG USBFS_EP_R_AUTO_TOG -#endif +#define EP_T_AUTO_TOG USBFS_EP_T_AUTO_TOG +#define EP_R_AUTO_TOG USBFS_EP_R_AUTO_TOG /* private data */ struct usb_xfer { @@ -353,10 +348,9 @@ void dcd_int_handler(uint8_t rhport) { // toggle in ep0_tog on every variant; isochronous endpoints are DATA0-only (no toggle). if (!data.isochronous[ep][TUSB_DIR_OUT] && !(int_st & USBFS_INT_ST_TOG_OK)) { break; } if (ep == 0) { data.ep0_tog = !data.ep0_tog; } -#ifdef CH32_USBFS_EP_MANUAL_TOG - // Advance the expected RX toggle after each accepted packet. Iso endpoints are DATA0-only, - // and EP0 is handled explicitly from ep0_tog, so leave both alone. - if (ep != 0 && !data.isochronous[ep][TUSB_DIR_OUT]) { EP_CTRL(ep) ^= USBFS_EPC_R_TOG; } +#ifdef CH32_USBFS_EP4_MANUAL_TOG + // Advance the expected EP4 RX toggle after each accepted packet. Iso endpoints are DATA0-only, + if (ep == 4 && !data.isochronous[ep][TUSB_DIR_OUT]) { EP_CTRL(ep) ^= USBFS_EPC_R_TOG; } #endif update_out(rhport, ep, rx_len); break; @@ -364,10 +358,10 @@ void dcd_int_handler(uint8_t rhport) { case PID_IN: if (ep == 0) { data.ep0_tog = !data.ep0_tog; } -#ifdef CH32_USBFS_EP_MANUAL_TOG - // Manual toggle: flip the TX toggle after each ACK'd IN packet (EP0 manages its own). +#ifdef CH32_USBFS_EP4_MANUAL_TOG + // Manual toggle: flip the TX toggle after each ACK'd IN packet for EP4. // Isochronous transfers are DATA0-only (no toggle), so leave iso endpoints alone. - if (ep != 0 && !data.isochronous[ep][TUSB_DIR_IN]) { EP_CTRL(ep) ^= USBFS_EPC_T_TOG; } + if (ep == 4 && !data.isochronous[ep][TUSB_DIR_IN]) { EP_CTRL(ep) ^= USBFS_EPC_T_TOG; } #endif update_in(rhport, ep, false); break; @@ -603,11 +597,17 @@ void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) { // submitted and won't re-arm), fall back to ACK, not NAK, or the endpoint NAKs forever and the // host times out (usbtest toggle test 29 clears the halt between bulk writes on an armed EP). if (dir == TUSB_DIR_OUT) { +#ifdef CH32_USBFS_EP4_MANUAL_TOG + ep_rx_ctrl_set(ep, USBFS_EP_R_RES_NAK); +#endif uint8_t res = data.xfer[ep][TUSB_DIR_OUT].valid ? (data.isochronous[ep][TUSB_DIR_OUT] ? USBFS_EP_R_RES_NYET : USBFS_EP_R_RES_ACK) : USBFS_EP_R_RES_NAK; ep_rx_ctrl_set(ep, EP_R_AUTO_TOG | res); } else { +#ifdef CH32_USBFS_EP4_MANUAL_TOG + ep_tx_ctrl_set(ep, USBFS_EP_T_RES_NAK); +#endif ep_tx_ctrl_set(ep, EP_T_AUTO_TOG | USBFS_EP_T_RES_NAK); } } From 39b33861f67bace4a03c28797ad16838e008c414 Mon Sep 17 00:00:00 2001 From: rhgndf <16336768+rhgndf@users.noreply.github.com> Date: Mon, 20 Jul 2026 10:30:29 +0800 Subject: [PATCH 11/13] Fix clear_stall for EP4 manual toggling Modified endpoint response handling for USBFS to ensure proper ACK/NAK behavior based on transfer validity. --- src/portable/wch/dcd_ch32_usbfs.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/portable/wch/dcd_ch32_usbfs.c b/src/portable/wch/dcd_ch32_usbfs.c index 25c9bfd168..4762e682df 100644 --- a/src/portable/wch/dcd_ch32_usbfs.c +++ b/src/portable/wch/dcd_ch32_usbfs.c @@ -597,12 +597,12 @@ void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) { // submitted and won't re-arm), fall back to ACK, not NAK, or the endpoint NAKs forever and the // host times out (usbtest toggle test 29 clears the halt between bulk writes on an armed EP). if (dir == TUSB_DIR_OUT) { -#ifdef CH32_USBFS_EP4_MANUAL_TOG - ep_rx_ctrl_set(ep, USBFS_EP_R_RES_NAK); -#endif uint8_t res = data.xfer[ep][TUSB_DIR_OUT].valid ? (data.isochronous[ep][TUSB_DIR_OUT] ? USBFS_EP_R_RES_NYET : USBFS_EP_R_RES_ACK) : USBFS_EP_R_RES_NAK; +#ifdef CH32_USBFS_EP4_MANUAL_TOG + ep_rx_ctrl_set(ep, res); +#endif ep_rx_ctrl_set(ep, EP_R_AUTO_TOG | res); } else { #ifdef CH32_USBFS_EP4_MANUAL_TOG From b71a9c9490fe72e377ebd9c727b5ac2700719b8e Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Sun, 27 Sep 2026 13:09:13 +0200 Subject: [PATCH 12/13] fix(ch32x035): respect unique ID buffer capacity Signed-off-by: HiFiPhile --- hw/bsp/ch32x035/family.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/hw/bsp/ch32x035/family.c b/hw/bsp/ch32x035/family.c index 1e31add8f0..4c84b3c1eb 100644 --- a/hw/bsp/ch32x035/family.c +++ b/hw/bsp/ch32x035/family.c @@ -3,6 +3,7 @@ manufacturer: WCH */ #include +#include // https://github.com/openwch/ch32v307/pull/90 // https://github.com/openwch/ch32v20x/pull/12 @@ -128,14 +129,12 @@ uint32_t board_button_read(void) { } size_t board_get_unique_id(uint8_t id[], size_t max_len) { - (void)max_len; volatile uint32_t *ch32_uuid = ((volatile uint32_t *)0x1FFFF7E8UL); - uint32_t *serial_32 = (uint32_t *)(uintptr_t)id; - serial_32[0] = ch32_uuid[0]; - serial_32[1] = ch32_uuid[1]; - serial_32[2] = ch32_uuid[2]; + uint32_t uid[3] = {ch32_uuid[0], ch32_uuid[1], ch32_uuid[2]}; + size_t len = TU_MIN(max_len, sizeof(uid)); + memcpy(id, uid, len); - return 12; + return len; } int board_uart_read(uint8_t *buf, int len) { From 093092040bb6b5cf88b19e987338a70a9f45646e Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Sun, 27 Sep 2026 13:32:50 +0200 Subject: [PATCH 13/13] fix(ch32x035): integrate board with CI and shared flash helpers Signed-off-by: HiFiPhile --- .github/scripts/ci_set_matrix.py | 1 + docs/reference/boards.rst | 30 +++++++++++++++--------------- docs/reference/dependencies.rst | 2 +- hw/bsp/ch32x035/family.cmake | 2 +- hw/bsp/family.json | 18 ++++++++++++++++++ 5 files changed, 36 insertions(+), 17 deletions(-) diff --git a/.github/scripts/ci_set_matrix.py b/.github/scripts/ci_set_matrix.py index 6b7866a745..4a50185d69 100755 --- a/.github/scripts/ci_set_matrix.py +++ b/.github/scripts/ci_set_matrix.py @@ -37,6 +37,7 @@ "ch32v10x": ["riscv-gcc"], "ch32v20x": ["riscv-gcc"], "ch32v30x": ["riscv-gcc"], + "ch32x035": ["riscv-gcc"], "ch583": ["riscv-gcc"], "da1469x": ["arm-gcc"], "f1c100s": ["arm-gcc"], diff --git a/docs/reference/boards.rst b/docs/reference/boards.rst index 4b7e5059c1..a1d1d6d67a 100644 --- a/docs/reference/boards.rst +++ b/docs/reference/boards.rst @@ -373,18 +373,18 @@ fomu fomu fomu https://tomu.im/fomu.html WCH --- -=========================== ============================= ======== ===================================================================== ====== -Board Name Family URL Note -=========================== ============================= ======== ===================================================================== ====== -ch32f205r-r0 CH32F205r-r0 ch32f20x https://github.com/openwch/ch32f20x -ch32v103c_bluepill CH32V103C8T6-Bluepill ch32v10x https://stm32-base.org/boards/STM32F103C8T6-Blue-Pill -ch32v103r_r1_1v0 CH32V103R-R1-1v1 ch32v10x https://github.com/openwch/ch32v103/tree/main/SCHPCB/CH32V103R-R1-1v1 -ch32v203c_r0_1v0 CH32V203C-R0-1v0 ch32v20x https://github.com/openwch/ch32v20x/tree/main/SCHPCB/CH32V203C-R0 -ch32v203g_r0_1v0 CH32V203G-R0-1v0 ch32v20x https://github.com/openwch/ch32v20x/tree/main/SCHPCB/CH32V203C-R0 -nanoch32v203 nanoCH32V203 ch32v20x https://github.com/wuxx/nanoCH32V203 -ch32v307v_r1_1v0 CH32V307V-R1-1v0 ch32v30x https://github.com/openwch/ch32v307/tree/main/SCHPCB/CH32V307V-R1-1v0 -nanoch32v305 nanoCH32V305 ch32v30x https://github.com/wuxx/nanoCH32V305 -ch582m_evt CH582M-EVT evaluation board ch583 https://www.wch-ic.com/products/CH582.html -yd-ch582m yd-ch582m from vcc-gnd studio ch583 http://vcc-gnd.com/ -weact_ch32x035_core_board WeAct CH32X035 Core Board ch32x035 https://github.com/WeActStudio/WeActStudio.CH32X035CoreBoard -=========================== ============================= ======== ===================================================================== ====== +========================= ============================= ======== ===================================================================== ====== +Board Name Family URL Note +========================= ============================= ======== ===================================================================== ====== +ch32f205r-r0 CH32F205r-r0 ch32f20x https://github.com/openwch/ch32f20x +ch32v103c_bluepill CH32V103C8T6-Bluepill ch32v10x https://stm32-base.org/boards/STM32F103C8T6-Blue-Pill +ch32v103r_r1_1v0 CH32V103R-R1-1v1 ch32v10x https://github.com/openwch/ch32v103/tree/main/SCHPCB/CH32V103R-R1-1v1 +ch32v203c_r0_1v0 CH32V203C-R0-1v0 ch32v20x https://github.com/openwch/ch32v20x/tree/main/SCHPCB/CH32V203C-R0 +ch32v203g_r0_1v0 CH32V203G-R0-1v0 ch32v20x https://github.com/openwch/ch32v20x/tree/main/SCHPCB/CH32V203C-R0 +nanoch32v203 nanoCH32V203 ch32v20x https://github.com/wuxx/nanoCH32V203 +ch32v307v_r1_1v0 CH32V307V-R1-1v0 ch32v30x https://github.com/openwch/ch32v307/tree/main/SCHPCB/CH32V307V-R1-1v0 +nanoch32v305 nanoCH32V305 ch32v30x https://github.com/wuxx/nanoCH32V305 +weact_ch32x035_core_board WeAct CH32X035 Core Board ch32x035 https://github.com/WeActStudio/WeActStudio.CH32X035CoreBoard +ch582m_evt CH582M-EVT evaluation board ch583 https://www.wch-ic.com/products/CH582.html +yd-ch582m yd-ch582m from vcc-gnd studio ch583 http://vcc-gnd.com/ +========================= ============================= ======== ===================================================================== ====== diff --git a/docs/reference/dependencies.rst b/docs/reference/dependencies.rst index 379d6a1206..204b067dba 100644 --- a/docs/reference/dependencies.rst +++ b/docs/reference/dependencies.rst @@ -93,8 +93,8 @@ hw/mcu/wch/ch32f20x https://github.com/openwch/ch32f20x.gi hw/mcu/wch/ch32v103 https://github.com/openwch/ch32v103.git 7578cae0b21f86dd053a1f781b2fc6ab99d0ec17 ch32v10x hw/mcu/wch/ch32v20x https://github.com/openwch/ch32v20x.git c4c38f507e258a4e69b059ccc2dc27dde33cea1b ch32v20x hw/mcu/wch/ch32v307 https://github.com/openwch/ch32v307.git 184f21b852cb95eed58e86e901837bc9fff68775 ch32v30x -hw/mcu/wch/ch583 https://github.com/openwch/ch583.git bd508ad7ceed48377619837051412a651952857f ch583 hw/mcu/wch/ch32x035 https://github.com/openwch/ch32x035.git c6253942b29ff2a3f5e2829182a874afffa45881 ch32x035 +hw/mcu/wch/ch583 https://github.com/openwch/ch583.git bd508ad7ceed48377619837051412a651952857f ch583 lib/CMSIS_5 https://github.com/ARM-software/CMSIS_5.git 2b7495b8535bdcb306dac29b9ded4cfb679d7e5c kinetis_k kinetis_kl lpc54 rw61x mm32 msp432e4 nrf samd2x_l2x lpc11 lpc13 lpc15 lpc17 lpc18 lpc40 lpc43 stm32c0 stm32f0 stm32f1 stm32f2 stm32f3 stm32f4 stm32f7 stm32g0 stm32g4 stm32h5 stm32h7 stm32h7rs stm32l0 stm32l1 stm32l4 stm32l5 stm32u0 stm32u5 stm32wb stm32wba sam3x samd11 samd21 samd2x_l2x samd51 samd5x_e5x same5x same7x samg tm4c lib/CMSIS_6 https://github.com/ARM-software/CMSIS_6.git 6f0a58d01aa9bd2feba212097f9afe7acd991d52 imxrt kinetis_k32l ra stm32n6 lpc51 lpc55 mcx stm32c5 lib/FreeRTOS-Kernel https://github.com/FreeRTOS/FreeRTOS-Kernel.git 9b777ae5c5b8e9e456065a00294d1e5f5f9facf5 all diff --git a/hw/bsp/ch32x035/family.cmake b/hw/bsp/ch32x035/family.cmake index 35d8c04d6f..6ccf9022e4 100644 --- a/hw/bsp/ch32x035/family.cmake +++ b/hw/bsp/ch32x035/family.cmake @@ -98,6 +98,6 @@ function(family_configure_example TARGET RTOS) # Flashing family_add_bin_hex(${TARGET}) - family_flash_openocd_wch(${TARGET}) + family_flash_openocd(${TARGET}) family_flash_wlink_rs(${TARGET}) endfunction() diff --git a/hw/bsp/family.json b/hw/bsp/family.json index e2ce8eb413..8805b90aa4 100644 --- a/hw/bsp/family.json +++ b/hw/bsp/family.json @@ -517,6 +517,24 @@ } } }, + "ch32x035": { + "weact_ch32x035_core_board": { + "cmake": { + "defines": {}, + "family_mcus": [ + "CH32X035" + ], + "mcu": "OPT_MCU_CH32X035", + "options": {}, + "portable": [ + "wch/dcd_ch32_usbfs.c" + ], + "roles": [ + "device" + ] + } + } + }, "ch583": { "ch582m_evt": { "cmake": {