From 2df5bef9816a9f368df839be4ebc1f4797812271 Mon Sep 17 00:00:00 2001 From: seteiro <276597748+cms19859230182-lang@users.noreply.github.com> Date: Tue, 22 Sep 2026 18:27:46 +0800 Subject: [PATCH 1/4] [bsp][ch32v203] add CH32V203C8T6-EVT-R0 support The EVT-R0 board is a QingKe V4B D6 part: 64KB zero-wait Flash and 20KB SRAM. The CH32V20x SDK package ships D8W startup and exits on D6, so this BSP adds a D6 vector table and keeps that package building. Default config enables GPIO and UART1 so the image fits with room to spare. PWM, ADC, RTC, the independent watchdog, and USB device were checked on the board as separate menuconfig sets. USB CDC on the Type-C port answered help and version. The shared USBFS device driver keeps endpoint buffers in SRAM and writes the device address after the status IN. CH32V2 watchdog code includes the V2 header. --- .github/ALL_BSP_COMPILE.json | 1 + .../manual_trigger_scons_except_STM32_all.yml | 1 + bsp/README.md | 1 + .../.ci/attachconfig/ci.attachconfig.yml | 7 + bsp/wch/risc-v/ch32v203c-evt-r0/.config | 412 ++++++++++++ bsp/wch/risc-v/ch32v203c-evt-r0/Kconfig | 12 + bsp/wch/risc-v/ch32v203c-evt-r0/README.md | 114 ++++ bsp/wch/risc-v/ch32v203c-evt-r0/SConscript | 15 + bsp/wch/risc-v/ch32v203c-evt-r0/SConstruct | 92 +++ .../ch32v203c-evt-r0/applications/SConscript | 18 + .../ch32v203c-evt-r0/applications/main.c | 21 + .../ch32v203c-evt-r0/applications/wdt_msh.c | 71 ++ bsp/wch/risc-v/ch32v203c-evt-r0/board/Kconfig | 631 ++++++++++++++++++ .../risc-v/ch32v203c-evt-r0/board/SConscript | 19 + bsp/wch/risc-v/ch32v203c-evt-r0/board/board.c | 103 +++ bsp/wch/risc-v/ch32v203c-evt-r0/board/board.h | 43 ++ .../board/linker_scripts/link.lds | 212 ++++++ .../ch32v203c-evt-r0/board/software_irq.c | 41 ++ .../board/startup_ch32v20x_D6.S | 258 +++++++ bsp/wch/risc-v/ch32v203c-evt-r0/rtconfig.h | 220 ++++++ bsp/wch/risc-v/ch32v203c-evt-r0/rtconfig.py | 72 ++ .../risc-v/libraries/ch32_drivers/drv_iwdt.c | 6 + .../risc-v/libraries/ch32_drivers/drv_usbd.c | 159 +++-- tools/ci/bsp_detail.yml | 6 + tools/ci/toolchain_bsp.yml | 3 +- 25 files changed, 2481 insertions(+), 57 deletions(-) create mode 100644 bsp/wch/risc-v/ch32v203c-evt-r0/.ci/attachconfig/ci.attachconfig.yml create mode 100644 bsp/wch/risc-v/ch32v203c-evt-r0/.config create mode 100644 bsp/wch/risc-v/ch32v203c-evt-r0/Kconfig create mode 100644 bsp/wch/risc-v/ch32v203c-evt-r0/README.md create mode 100644 bsp/wch/risc-v/ch32v203c-evt-r0/SConscript create mode 100644 bsp/wch/risc-v/ch32v203c-evt-r0/SConstruct create mode 100644 bsp/wch/risc-v/ch32v203c-evt-r0/applications/SConscript create mode 100644 bsp/wch/risc-v/ch32v203c-evt-r0/applications/main.c create mode 100644 bsp/wch/risc-v/ch32v203c-evt-r0/applications/wdt_msh.c create mode 100644 bsp/wch/risc-v/ch32v203c-evt-r0/board/Kconfig create mode 100644 bsp/wch/risc-v/ch32v203c-evt-r0/board/SConscript create mode 100644 bsp/wch/risc-v/ch32v203c-evt-r0/board/board.c create mode 100644 bsp/wch/risc-v/ch32v203c-evt-r0/board/board.h create mode 100644 bsp/wch/risc-v/ch32v203c-evt-r0/board/linker_scripts/link.lds create mode 100644 bsp/wch/risc-v/ch32v203c-evt-r0/board/software_irq.c create mode 100644 bsp/wch/risc-v/ch32v203c-evt-r0/board/startup_ch32v20x_D6.S create mode 100644 bsp/wch/risc-v/ch32v203c-evt-r0/rtconfig.h create mode 100644 bsp/wch/risc-v/ch32v203c-evt-r0/rtconfig.py diff --git a/.github/ALL_BSP_COMPILE.json b/.github/ALL_BSP_COMPILE.json index fc3600e713a9..1eaa4c704b0d 100644 --- a/.github/ALL_BSP_COMPILE.json +++ b/.github/ALL_BSP_COMPILE.json @@ -427,6 +427,7 @@ "RTT_TOOL_CHAIN": "sourcery-riscv-none-embed", "SUB_RTT_BSP": [ "k210", + "wch/risc-v/ch32v203c-evt-r0", "wch/risc-v/ch32v208w-r0", "wch/risc-v/ch32v307v-r1", "wch/risc-v/yd-ch32v307vct6", diff --git a/.github/workflows/manual_trigger_scons_except_STM32_all.yml b/.github/workflows/manual_trigger_scons_except_STM32_all.yml index 6b1debcda324..cdbe789dff04 100644 --- a/.github/workflows/manual_trigger_scons_except_STM32_all.yml +++ b/.github/workflows/manual_trigger_scons_except_STM32_all.yml @@ -266,6 +266,7 @@ jobs: - {RTT_BSP_NAME: "wch_arm_ch32f203r-evt", RTT_TOOL_CHAIN: "sourcery-arm", RTT_BSP: "wch/arm/ch32f203r-evt"} #- {RTT_BSP_NAME: "wch_arm_ch579m", RTT_TOOL_CHAIN: "sourcery-arm", RTT_BSP: "wch/arm/ch579m"} #编译错误 #- {RTT_BSP_NAME: "wch_risc-v_ch32v103r-evt", RTT_TOOL_CHAIN: "sourcery-riscv-none-embed", RTT_BSP: "wch/risc-v/ch32v103r-evt"} #编译出错 + - {RTT_BSP_NAME: "wch_risc-v_ch32v203c-evt-r0", RTT_TOOL_CHAIN: "sourcery-riscv-none-embed", RTT_BSP: "wch/risc-v/ch32v203c-evt-r0"} - {RTT_BSP_NAME: "wch_risc-v_ch32v208w-r0", RTT_TOOL_CHAIN: "sourcery-riscv-none-embed", RTT_BSP: "wch/risc-v/ch32v208w-r0"} - {RTT_BSP_NAME: "wch_risc-v_ch32v307v-r1", RTT_TOOL_CHAIN: "sourcery-riscv-none-embed", RTT_BSP: "wch/risc-v/ch32v307v-r1"} #- {RTT_BSP_NAME: "wch_risc-v_ch569w-evt", RTT_TOOL_CHAIN: "sourcery-riscv-none-embed", RTT_BSP: "wch/risc-v/ch569w-evt"} #编译出错 diff --git a/bsp/README.md b/bsp/README.md index e4fed6f96afb..62f798fcd701 100644 --- a/bsp/README.md +++ b/bsp/README.md @@ -802,6 +802,7 @@ This document is based on the RT-Thread mainline repository and categorizes the | [ch32f203r-evt](wch/arm/ch32f203r-evt) | ✅ | ✅ | - | - | - | - | ✅ | ✅ | ✅ | ✅ | ✅ | - | ✅ | - | - | | [ch579m](wch/arm/ch579m) | ✅ | ✅ | - | - | - | ✅ | - | - | - | - | - | - | - | - | ✅ | | [ch32v103r-evt](wch/risc-v/ch32v103r-evt) | ✅ | ✅ | - | - | - | - | - | - | - | - | - | - | - | - | - | +| [ch32v203c-evt-r0](wch/risc-v/ch32v203c-evt-r0) | ✅ | ✅ | ✅ | - | - | - | - | - | - | - | ✅ | ✅ | ✅ | ✅ | - | | [ch32v208w-r0](wch/risc-v/ch32v208w-r0) | ✅ | ✅ | ✅ | ✅ | ✅ | - | - | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | - | - | | [ch32v307v-r1](wch/risc-v/ch32v307v-r1) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | | [ch569w-evt](wch/risc-v/ch569w-evt) | ✅ | ✅ | - | - | - | - | - | ✅ | - | ✅ | - | - | - | - | - | diff --git a/bsp/wch/risc-v/ch32v203c-evt-r0/.ci/attachconfig/ci.attachconfig.yml b/bsp/wch/risc-v/ch32v203c-evt-r0/.ci/attachconfig/ci.attachconfig.yml new file mode 100644 index 000000000000..a6bd78a0aa62 --- /dev/null +++ b/bsp/wch/risc-v/ch32v203c-evt-r0/.ci/attachconfig/ci.attachconfig.yml @@ -0,0 +1,7 @@ +devices.gpio: + kconfig: + - CONFIG_BSP_USING_GPIO=y +devices.uart: + kconfig: + - CONFIG_BSP_USING_UART=y + - CONFIG_BSP_USING_UART1=y diff --git a/bsp/wch/risc-v/ch32v203c-evt-r0/.config b/bsp/wch/risc-v/ch32v203c-evt-r0/.config new file mode 100644 index 000000000000..dc0ba7def6d3 --- /dev/null +++ b/bsp/wch/risc-v/ch32v203c-evt-r0/.config @@ -0,0 +1,412 @@ + +# +# RT-Thread Kernel +# + +# +# klibc options +# + +# +# rt_vsnprintf options +# +# CONFIG_RT_KLIBC_USING_LIBC_VSNPRINTF is not set +# CONFIG_RT_KLIBC_USING_VSNPRINTF_LONGLONG is not set +# CONFIG_RT_KLIBC_USING_VSNPRINTF_STANDARD is not set +# end of rt_vsnprintf options + +# +# rt_vsscanf options +# +# CONFIG_RT_KLIBC_USING_LIBC_VSSCANF is not set +# end of rt_vsscanf options + +# +# rt_memset options +# +# CONFIG_RT_KLIBC_USING_USER_MEMSET is not set +# CONFIG_RT_KLIBC_USING_LIBC_MEMSET is not set +# CONFIG_RT_KLIBC_USING_TINY_MEMSET is not set +# end of rt_memset options + +# +# rt_memcpy options +# +# CONFIG_RT_KLIBC_USING_USER_MEMCPY is not set +# CONFIG_RT_KLIBC_USING_LIBC_MEMCPY is not set +# CONFIG_RT_KLIBC_USING_TINY_MEMCPY is not set +# end of rt_memcpy options + +# +# rt_memmove options +# +# CONFIG_RT_KLIBC_USING_USER_MEMMOVE is not set +# CONFIG_RT_KLIBC_USING_LIBC_MEMMOVE is not set +# end of rt_memmove options + +# +# rt_memcmp options +# +# CONFIG_RT_KLIBC_USING_USER_MEMCMP is not set +# CONFIG_RT_KLIBC_USING_LIBC_MEMCMP is not set +# end of rt_memcmp options + +# +# rt_strstr options +# +# CONFIG_RT_KLIBC_USING_USER_STRSTR is not set +# CONFIG_RT_KLIBC_USING_LIBC_STRSTR is not set +# end of rt_strstr options + +# +# rt_strcasecmp options +# +# CONFIG_RT_KLIBC_USING_USER_STRCASECMP is not set +# end of rt_strcasecmp options + +# +# rt_strncpy options +# +# CONFIG_RT_KLIBC_USING_USER_STRNCPY is not set +# CONFIG_RT_KLIBC_USING_LIBC_STRNCPY is not set +# end of rt_strncpy options + +# +# rt_strcpy options +# +# CONFIG_RT_KLIBC_USING_USER_STRCPY is not set +# CONFIG_RT_KLIBC_USING_LIBC_STRCPY is not set +# end of rt_strcpy options + +# +# rt_strncmp options +# +# CONFIG_RT_KLIBC_USING_USER_STRNCMP is not set +# CONFIG_RT_KLIBC_USING_LIBC_STRNCMP is not set +# end of rt_strncmp options + +# +# rt_strcmp options +# +# CONFIG_RT_KLIBC_USING_USER_STRCMP is not set +# CONFIG_RT_KLIBC_USING_LIBC_STRCMP is not set +# end of rt_strcmp options + +# +# rt_strlen options +# +# CONFIG_RT_KLIBC_USING_USER_STRLEN is not set +# CONFIG_RT_KLIBC_USING_LIBC_STRLEN is not set +# end of rt_strlen options + +# +# rt_strnlen options +# +# CONFIG_RT_KLIBC_USING_USER_STRNLEN is not set +# end of rt_strnlen options +# end of klibc options + +CONFIG_RT_NAME_MAX=12 +# CONFIG_RT_USING_ARCH_DATA_TYPE is not set +# CONFIG_RT_USING_NANO is not set +# CONFIG_RT_USING_AMP is not set +# CONFIG_RT_USING_SMP is not set +CONFIG_RT_CPUS_NR=1 +CONFIG_RT_ALIGN_SIZE=8 +# CONFIG_RT_THREAD_PRIORITY_8 is not set +CONFIG_RT_THREAD_PRIORITY_32=y +# CONFIG_RT_THREAD_PRIORITY_256 is not set +CONFIG_RT_THREAD_PRIORITY_MAX=32 +CONFIG_RT_TICK_PER_SECOND=1000 +# CONFIG_RT_USING_OVERFLOW_CHECK is not set +CONFIG_RT_USING_HOOK=y +CONFIG_RT_HOOK_USING_FUNC_PTR=y +# CONFIG_RT_USING_HOOKLIST is not set +CONFIG_RT_USING_IDLE_HOOK=y +CONFIG_RT_IDLE_HOOK_LIST_SIZE=4 +CONFIG_IDLE_THREAD_STACK_SIZE=512 +CONFIG_RT_USING_TIMER_SOFT=y +CONFIG_RT_TIMER_THREAD_PRIO=4 +CONFIG_RT_TIMER_THREAD_STACK_SIZE=512 +# CONFIG_RT_USING_TIMER_ALL_SOFT is not set +# CONFIG_RT_USING_CPU_USAGE_TRACER is not set + +# +# kservice options +# +# CONFIG_RT_USING_TINY_FFS is not set +# end of kservice options + +CONFIG_RT_USING_DEBUG=y +CONFIG_RT_DEBUGING_ASSERT=y +CONFIG_RT_DEBUGING_COLOR=y +CONFIG_RT_DEBUGING_CONTEXT=y +# CONFIG_RT_DEBUGING_AUTO_INIT is not set +# CONFIG_RT_USING_CI_ACTION is not set + +# +# Inter-Thread communication +# +CONFIG_RT_USING_SEMAPHORE=y +CONFIG_RT_USING_MUTEX=y +CONFIG_RT_USING_EVENT=y +CONFIG_RT_USING_MAILBOX=y +CONFIG_RT_USING_MESSAGEQUEUE=y +# CONFIG_RT_USING_MESSAGEQUEUE_PRIORITY is not set +# CONFIG_RT_USING_SIGNALS is not set +# end of Inter-Thread communication + +# +# Memory Management +# +# CONFIG_RT_USING_MEMPOOL is not set +CONFIG_RT_USING_SMALL_MEM=y +# CONFIG_RT_USING_SLAB is not set +# CONFIG_RT_USING_MEMHEAP is not set +CONFIG_RT_USING_SMALL_MEM_AS_HEAP=y +# CONFIG_RT_USING_MEMHEAP_AS_HEAP is not set +# CONFIG_RT_USING_SLAB_AS_HEAP is not set +# CONFIG_RT_USING_USERHEAP is not set +# CONFIG_RT_USING_NOHEAP is not set +# CONFIG_RT_USING_MEMTRACE is not set +# CONFIG_RT_USING_HEAP_ISR is not set +CONFIG_RT_USING_HEAP=y +# end of Memory Management + +CONFIG_RT_USING_DEVICE=y +# CONFIG_RT_USING_DEVICE_OPS is not set +# CONFIG_RT_USING_INTERRUPT_INFO is not set +# CONFIG_RT_USING_THREADSAFE_PRINTF is not set +CONFIG_RT_USING_CONSOLE=y +CONFIG_RT_CONSOLEBUF_SIZE=128 +CONFIG_RT_CONSOLE_DEVICE_NAME="uart1" +CONFIG_RT_USING_CONSOLE_OUTPUT_CTL=y +CONFIG_RT_VER_NUM=0x50301 +# CONFIG_RT_USING_STDC_ATOMIC is not set +CONFIG_RT_BACKTRACE_LEVEL_MAX_NR=32 +# end of RT-Thread Kernel + +CONFIG_RT_USING_HW_ATOMIC=y +CONFIG_ARCH_RISCV=y + +# +# RT-Thread Components +# +CONFIG_RT_USING_COMPONENTS_INIT=y +CONFIG_RT_USING_USER_MAIN=y +CONFIG_RT_MAIN_THREAD_STACK_SIZE=2048 +CONFIG_RT_MAIN_THREAD_PRIORITY=10 +# CONFIG_RT_USING_LEGACY is not set +CONFIG_RT_USING_MSH=y +CONFIG_RT_USING_FINSH=y +CONFIG_FINSH_USING_MSH=y +CONFIG_FINSH_THREAD_NAME="tshell" +CONFIG_FINSH_THREAD_PRIORITY=20 +CONFIG_FINSH_THREAD_STACK_SIZE=1024 +CONFIG_FINSH_USING_HISTORY=y +CONFIG_FINSH_HISTORY_LINES=5 +# CONFIG_FINSH_USING_WORD_OPERATION is not set +# CONFIG_FINSH_USING_FUNC_EXT is not set +CONFIG_FINSH_USING_SYMTAB=y +CONFIG_FINSH_CMD_SIZE=80 +CONFIG_MSH_USING_BUILT_IN_COMMANDS=y +# CONFIG_FINSH_USING_DESCRIPTION is not set +# CONFIG_FINSH_ECHO_DISABLE_DEFAULT is not set +# CONFIG_FINSH_USING_AUTH is not set +CONFIG_FINSH_ARG_MAX=10 +CONFIG_FINSH_USING_OPTION_COMPLETION=y + +# +# DFS: device virtual file system +# +# CONFIG_RT_USING_DFS is not set +# end of DFS: device virtual file system + +# CONFIG_RT_USING_FAL is not set + +# +# Device Drivers +# +# CONFIG_RT_USING_DM is not set +# CONFIG_RT_USING_DEV_BUS is not set +CONFIG_RT_USING_DEVICE_IPC=y +CONFIG_RT_UNAMED_PIPE_NUMBER=64 +# CONFIG_RT_USING_SYSTEM_WORKQUEUE is not set +CONFIG_RT_USING_SERIAL=y +CONFIG_RT_USING_SERIAL_V1=y +# CONFIG_RT_USING_SERIAL_V2 is not set +# CONFIG_RT_SERIAL_USING_DMA is not set +CONFIG_RT_SERIAL_RB_BUFSZ=64 +# CONFIG_RT_USING_SERIAL_BYPASS is not set +# CONFIG_RT_USING_CAN is not set +# CONFIG_RT_USING_ADC is not set +# CONFIG_RT_USING_CLOCK_TIME is not set +# CONFIG_RT_USING_I2C is not set +# CONFIG_RT_USING_PHY is not set +# CONFIG_RT_USING_PHY_V2 is not set +# CONFIG_RT_USING_DAC is not set +# CONFIG_RT_USING_NULL is not set +# CONFIG_RT_USING_ZERO is not set +# CONFIG_RT_USING_RANDOM is not set +# CONFIG_RT_USING_PWM is not set +# CONFIG_RT_USING_PULSE_ENCODER is not set +# CONFIG_RT_USING_INPUT_CAPTURE is not set +# CONFIG_RT_USING_MTD_NOR is not set +# CONFIG_RT_USING_MTD_NAND is not set +# CONFIG_RT_USING_PM is not set +# CONFIG_RT_USING_RTC is not set +# CONFIG_RT_USING_SDIO is not set +# CONFIG_RT_USING_SPI is not set +# CONFIG_RT_USING_WDT is not set +# CONFIG_RT_USING_AUDIO is not set +# CONFIG_RT_USING_SENSOR is not set +# CONFIG_RT_USING_TOUCH is not set +# CONFIG_RT_USING_LCD is not set +# CONFIG_RT_USING_HWCRYPTO is not set +# CONFIG_RT_USING_WIFI is not set +# CONFIG_RT_USING_RPMSG is not set +# CONFIG_RT_USING_BLK is not set +# CONFIG_RT_USING_REGULATOR is not set +# CONFIG_RT_USING_POWER_SUPPLY is not set +CONFIG_RT_USING_PIN=y +# CONFIG_RT_USING_CHERRYUSB is not set +# end of Device Drivers + +# +# C/C++ and POSIX layer +# + +# +# ISO-ANSI C layer +# + +# +# Timezone and Daylight Saving Time +# +# CONFIG_RT_LIBC_USING_FULL_TZ_DST is not set +CONFIG_RT_LIBC_USING_LIGHT_TZ_DST=y +CONFIG_RT_LIBC_TZ_DEFAULT_HOUR=8 +CONFIG_RT_LIBC_TZ_DEFAULT_MIN=0 +CONFIG_RT_LIBC_TZ_DEFAULT_SEC=0 +# end of Timezone and Daylight Saving Time +# end of ISO-ANSI C layer + +# +# POSIX (Portable Operating System Interface) layer +# +# CONFIG_RT_USING_POSIX_FS is not set +# CONFIG_RT_USING_POSIX_DELAY is not set +# CONFIG_RT_USING_POSIX_CLOCK is not set +# CONFIG_RT_USING_POSIX_TIMER is not set +# CONFIG_RT_USING_PTHREADS is not set +# CONFIG_RT_USING_MODULE is not set + +# +# Interprocess Communication (IPC) +# +# CONFIG_RT_USING_POSIX_PIPE is not set +# CONFIG_RT_USING_POSIX_MESSAGE_QUEUE is not set +# CONFIG_RT_USING_POSIX_MESSAGE_SEMAPHORE is not set + +# +# Socket is in the 'Network' category +# +# end of Interprocess Communication (IPC) +# end of POSIX (Portable Operating System Interface) layer + +# CONFIG_RT_USING_CPLUSPLUS is not set +# end of C/C++ and POSIX layer + +# +# Network +# +# CONFIG_RT_USING_SAL is not set +# CONFIG_RT_USING_NETDEV is not set +# CONFIG_RT_USING_LWIP is not set +# CONFIG_RT_USING_AT is not set +# end of Network + +# +# Memory protection +# +# CONFIG_RT_USING_MEM_PROTECTION is not set +# CONFIG_RT_USING_HW_STACK_GUARD is not set +# end of Memory protection + +# +# Utilities +# +# CONFIG_RT_USING_RYM is not set +# CONFIG_RT_USING_ULOG is not set +# CONFIG_RT_USING_UTEST is not set +# CONFIG_RT_USING_VAR_EXPORT is not set +# CONFIG_RT_USING_RESOURCE_ID is not set +# CONFIG_RT_USING_ADT is not set +# CONFIG_RT_USING_RT_LINK is not set +# end of Utilities + +# +# Using USB legacy version +# +# CONFIG_RT_USING_USB_HOST is not set +# CONFIG_RT_USING_USB_DEVICE is not set +# end of Using USB legacy version + +# CONFIG_RT_USING_FDT is not set +# CONFIG_RT_USING_RUST is not set +# end of RT-Thread Components + +# +# RT-Thread Utestcases +# +# CONFIG_RT_USING_UTESTCASES is not set +# end of RT-Thread Utestcases + +# +# WCH HAL & SDK Drivers +# +CONFIG_PKG_USING_CH32V20x_SDK=y +CONFIG_PKG_CH32V20x_SDK_PATH="/packages/peripherals/hal-sdk/wch/ch32v20x_sdk" +# CONFIG_PKG_USING_CH32V20x_SDK_V202 is not set +CONFIG_PKG_USING_CH32V20x_SDK_LATEST_VERSION=y +CONFIG_PKG_CH32V20x_SDK_VER="latest" +# end of WCH HAL & SDK Drivers + +CONFIG_SOC_RISCV_FAMILY_CH32=y +CONFIG_SOC_RISCV_SERIES_CH32V2=y +CONFIG_SOC_RISCV_SERIES_CH32V20x_D6=y + +# +# Hardware Drivers Config +# +CONFIG_SOC_CH32V203C8=y + +# +# Onboard Peripheral Drivers +# + +# +# On-chip Peripheral Drivers +# +CONFIG_BSP_USING_GPIO=y +CONFIG_BSP_USING_UART=y +CONFIG_BSP_USING_UART1=y +# CONFIG_BSP_USING_UART2 is not set +# CONFIG_BSP_USING_UART3 is not set +# CONFIG_BSP_USING_UART4 is not set +# CONFIG_BSP_USING_ADC is not set +# CONFIG_BSP_USING_DAC is not set +# CONFIG_BSP_USING_SOFT_I2C is not set +# CONFIG_BSP_USING_SPI is not set +# CONFIG_BSP_USING_RTC is not set +CONFIG_LSI_VALUE=40000 +# CONFIG_BSP_USING_IWDT is not set +# CONFIG_BSP_USING_USBD is not set +# CONFIG_BSP_USING_CAN is not set +# CONFIG_BSP_USING_TIM is not set +# end of On-chip Peripheral Drivers + +# +# Board extended module Drivers +# +# end of Hardware Drivers Config diff --git a/bsp/wch/risc-v/ch32v203c-evt-r0/Kconfig b/bsp/wch/risc-v/ch32v203c-evt-r0/Kconfig new file mode 100644 index 000000000000..07edfefc341e --- /dev/null +++ b/bsp/wch/risc-v/ch32v203c-evt-r0/Kconfig @@ -0,0 +1,12 @@ +mainmenu "RT-Thread Configuration" + +BSP_DIR := . + +RTT_DIR := ../../../.. + +PKGS_DIR := packages + +source "$(RTT_DIR)/Kconfig" +osource "$PKGS_DIR/Kconfig" +rsource "../libraries/Kconfig" +rsource "board/Kconfig" diff --git a/bsp/wch/risc-v/ch32v203c-evt-r0/README.md b/bsp/wch/risc-v/ch32v203c-evt-r0/README.md new file mode 100644 index 000000000000..0c0ef910c014 --- /dev/null +++ b/bsp/wch/risc-v/ch32v203c-evt-r0/README.md @@ -0,0 +1,114 @@ +# ch32v203c-evt-r0 BSP 说明 + +**中文** + +## 1 开发板简介 + +CH32V203C8T6-EVT-R0 是 WCH 沁恒的 RISC-V 评估板。芯片是 QingKe **V4B(CH32V20x_D6)**,手册零等待 Flash **64KB**、SRAM **20KB**。LinkUtility 读到的 224KB 是 V203 系列总 CodeFlash,**不要**写进链接脚本。 + +**基本特性:** + +- MCU:CH32V203C8T6,最高 144MHz +- 封装:LQFP48 +- 板载用户灯默认**没接到 GPIO**,要杜邦线才闪 +- **无板载 WCH-Link**,需外接 WCH-LinkE + +资料:[CH32V203](https://www.wch.cn/products/CH32V203.html)、[openwch/ch32v20x](https://github.com/openwch/ch32v20x) + +本 BSP 骨架对齐主仓 `ch32v208w-r0`(同一套 `CH32V20x` SDK、仓内 `ch32_drivers`),堆和 64K/20K 按手册与 `ch32v307v-r1` 的 `HEAP_BEGIN`/`HEAP_END`。USART1 默认 **PA9 TX / PA10 RX**。 + +官方软件包 `CH32V20x-SDK-for-RTT` 只带 D8W 启动文件,D6 会 `Exit()`。本 BSP 在 `board/startup_ch32v20x_D6.S` 使用沁恒 EVT 的 D6 向量表,复位后跳到 RT-Thread `entry`(与该包 D8W 的 rtt-patch 相同)。`SConstruct` 会去掉包里对 D6 的 `Exit()`。 + +## 2 编译说明 + +| IDE/编译器 | 已测试版本 | +| ---------- | -------------------- | +| GCC | WCH RISC-V GCC 8.2.0 | + +默认配置只打开 GPIO 和 UART1,给 64KB 留余量。PWM、ADC、RTC、看门狗、USB 都在 menuconfig 里,默认关着。64KB 放不下 USB 和 PWM、ADC、RTC、看门狗同时打开。 + +已在这块板上分开测过: + +- 打开 TIM1 通道 1(PA8)、ADC1、RTC(LSE)和独立看门狗,并关掉命令帮助文字。本机那次 Flash **64892** 字节,**99.02%**。 +- 只开 USB CDC,关掉上面四项。USB 线程栈用 **1024**(菜单默认 4096,20KB SRAM 不合适)。扁口插电脑、Type-C 插板子 P7 后,电脑串口是 COM12,`help` 和 `version` 有回应。 + +`pwm` 命令依赖 Finsh 的选项补全。 + +### 2.1 使用 Env 编译 + +1. 安装 [WCH RISC-V GCC](https://github.com/NanjingQinheng/sdk-toolchain-RISC-V-GCC-WCH) 与 [Env](https://github.com/RT-Thread/env-windows/releases) +2. 进入本目录,设置 `RTT_EXEC_PATH` 为工具链 `bin` +3. `pkgs --update` 拉取 `CH32V20x_SDK`(或按 `package.json` clone `kaidegit/CH32V20x-SDK-for-RTT` 到 `packages/`) +4. `scons -j4`,生成 **rtthread.bin** + +## 3 硬件连接与下载 + +### 3.1 SWD(已用于认出芯片) + +独立 WCH-LinkE: + +- 3V3 — 3V3 +- GND — GND +- SWDIO — PA13 +- SWCLK — PA14 + +不要把 LinkE 的 5V USB 和板子供电叠在一起。 + +### 3.2 USART1(msh) + +SWD 那四根(3V3 / GND / PA13 / PA14)不够出串口。LinkE 排针上另外有丝印 **TX** / **RX**(WCH-Link 手册图一),接到板上 **P1** 排针的 PA9 / PA10(沁恒 EVT 原理图 `CH32V203C8T6-R0`)。交叉: + +- LinkE **TX** → 板 **PA10**(USART1_RX) +- LinkE **RX** → 板 **PA9**(USART1_TX) +- GND 已共地就不用再加 + +本机 LinkE 虚拟串口是 **COM11**,115200-8-1-N。 + +### 3.3 下载 + +WCH-LinkUtility:Series **CH32V20X**。固件按手册 **64K Flash + 20K SRAM** 链接。默认镜像只含 GPIO 和 UART1,本机 `scons` 为 Flash **44480** 字节,**67.87%**。 + +V20X 的 Chip Mem 下拉没有 64K+20K(常见是 128K+64K 等),**不要点 Set** 改 option bytes。不要用 307 的 224K+96K。Target → Program(F10),不要勾 Erase All。界面读到 Flash Size 224KB 是系列总 CodeFlash,不是这份 bin 的大小。 + +复位后 COM11 应出现 RT-Thread / `msh >`。`help`、`ps`、`free` 有输出即启动成功。 + +### 3.4 已核对的外设 + +TIM1 通道 1 在 **PA8**,不占用 USART1 和 SWD: + +``` +pwm probe pwm1 +pwm set 1 1000000 500000 +pwm enable 1 +pwm get 1 +``` + +读回 period `1000000` ns、pulse `500000` ns,即 1 kHz、50%。 + +ADC1 内部通道要在本板 `board.c` 里打开 `ADC_TempSensorVrefintCmd`。通道 17(Vref)连续读到 `0x5C9`、`0x5C9`、`0x5CA`、`0x5C9`。通道 16(温度)换通道后的第一次会带上一路的值,随后三次都是 `0x6C4`。 + +``` +adc probe adc1 +adc enable 17 +adc read 17 +adc enable 16 +adc read 16 +``` + +RTC 用 LSE,不要选 LSI。默认镜像没开 RTC,要在 menuconfig 里打开。设置后几秒再读,时间应往前走: + +``` +date +date 2026 9 22 12 40 0 +date +``` + +设置后约 5 秒再读,时间从 `12:40:00` 走到 `12:40:05`。 + +独立看门狗设备名是 `wdt`。`wdt start 5` 之后 `wdt feed`,`msh` 还在;停止喂狗后约 5 秒串口重新打出 RT-Thread 横幅。看门狗一旦启动,复位后如果没有再喂,会按同一超时再次复位。要停掉就重新下载这份默认镜像。V2 的 `drv_iwdt.c` 必须包含 `ch32v20x_iwdg.h`,不能用 V3 的头文件。 + +## 4 外设表 + +`bsp/README.md` 里本板勾了 GPIO、UART、ADC、RTC、PWM、WDT、USBD。这些勾选表示驱动在、而且板上见过结果,不是默认镜像全开。SPI、I2C、CAN、DAC、USBH 仍不勾。外部 ADC 通道 0 是 PA0。接到板子自己的 3V3,连续四次都是 `0xFFF`。改接到 GND,四次是 `0x4`、`0x4`、`0x5`、`0x5`。 + +USB 设备走板子下边的 Type-C(丝印 P7,PA11/PA12)。扁口插电脑,Type-C 插这块板。打开 USB、关掉 PWM、ADC、RTC 和看门狗之后,电脑多出一个串口,这边是 COM12,厂商号 `0FFE`,产品号 `0001`。把控制台切到 `vcom` 之后,在 COM12 上敲 `help` 能收回命令列表,`version` 打出 RT-Thread 5.3.1。PA8 的 PWM 只核对了寄存器读回,没有示波器波形。 diff --git a/bsp/wch/risc-v/ch32v203c-evt-r0/SConscript b/bsp/wch/risc-v/ch32v203c-evt-r0/SConscript new file mode 100644 index 000000000000..20f7689c53ca --- /dev/null +++ b/bsp/wch/risc-v/ch32v203c-evt-r0/SConscript @@ -0,0 +1,15 @@ +# for module compiling +import os +Import('RTT_ROOT') +from building import * + +cwd = GetCurrentDir() +objs = [] +list = os.listdir(cwd) + +for d in list: + path = os.path.join(cwd, d) + if os.path.isfile(os.path.join(path, 'SConscript')): + objs = objs + SConscript(os.path.join(d, 'SConscript')) + +Return('objs') diff --git a/bsp/wch/risc-v/ch32v203c-evt-r0/SConstruct b/bsp/wch/risc-v/ch32v203c-evt-r0/SConstruct new file mode 100644 index 000000000000..b17bcc0d5af7 --- /dev/null +++ b/bsp/wch/risc-v/ch32v203c-evt-r0/SConstruct @@ -0,0 +1,92 @@ +import os +import sys +import rtconfig +from SCons.Script import * + +if os.getenv('RTT_ROOT'): + RTT_ROOT = os.getenv('RTT_ROOT') +else: + RTT_ROOT = os.path.normpath(os.getcwd() + '/../../../..') + +sys.path = sys.path + [os.path.join(RTT_ROOT, 'tools')] +try: + from building import * +except: + print('Cannot found RT-Thread root directory, please check RTT_ROOT') + print(RTT_ROOT) + exit(-1) + + +TARGET = 'rtthread.' + rtconfig.TARGET_EXT + +DefaultEnvironment(tools=[]) +env = Environment(tools = ['mingw'], + AS = rtconfig.AS, ASFLAGS = rtconfig.AFLAGS, + CC = rtconfig.CC, CFLAGS = rtconfig.CFLAGS, + AR = rtconfig.AR, ARFLAGS = '-rc', + CXX = rtconfig.CXX, CXXFLAGS = rtconfig.CXXFLAGS, + LINK = rtconfig.LINK, LINKFLAGS = rtconfig.LFLAGS) +env.PrependENVPath('PATH', rtconfig.EXEC_PATH) + +if rtconfig.PLATFORM in ['iccarm']: + env.Replace(CCCOM = ['$CC $CFLAGS $CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS -o $TARGET $SOURCES']) + env.Replace(ARFLAGS = ['']) + env.Replace(LINKCOM = env["LINKCOM"] + ' --map project.map') + +Export('RTT_ROOT') +Export('rtconfig') + +SDK_ROOT = os.path.abspath('./') + +if os.path.exists(SDK_ROOT + '/libraries'): + libraries_path_prefix = SDK_ROOT + '/libraries' +else: + libraries_path_prefix = os.path.dirname(SDK_ROOT) + '/libraries' + +SDK_LIB = libraries_path_prefix +Export('SDK_LIB') + +def _allow_ch32v20x_d6_in_sdk_package(): + """Official CH32V20x-SDK-for-RTT ships a D8W startup file and Exit()s on D6. + CH32V203C8T6 is D6. Keep the SDK peripherals and use board/startup_ch32v20x_D6.S. + Only that package is edited, and only while Exit() is still present, so a + D8W tree or an already patched file is left untouched. + """ + import re + sc = os.path.join(SDK_ROOT, 'packages', 'CH32V20x-SDK-for-RTT', 'SConscript') + if not os.path.isfile(sc): + return + with open(sc, 'r', encoding='utf-8') as f: + text = f.read() + if 'Exit()' not in text or 'SOC_RISCV_SERIES_CH32V20x_D6' not in text: + return + if not re.search(r'^import os\b', text, re.M): + text = 'import os\n' + text + patched, n = re.subn( + r"if GetDepend\(\['SOC_RISCV_SERIES_CH32V20x_D6'\]\):.*?\n Exit\(\)\n", + "if GetDepend(['SOC_RISCV_SERIES_CH32V20x_D6']):\n" + " CPPDEFINES.append(\"CH32V20x_D6\")\n", + text, + count=1, + flags=re.S, + ) + if n == 0 or patched == text: + return + with open(sc, 'w', encoding='utf-8', newline='\n') as f: + f.write(patched) + +_allow_ch32v20x_d6_in_sdk_package() + +# prepare building environment +objs = PrepareBuilding(env, RTT_ROOT, has_libcpu=False) + +ch32_library = 'ch32v20x_libraries' +rtconfig.BSP_LIBRARY_TYPE = ch32_library + +bsp_vdir = 'build' + +# common include drivers +objs.extend(SConscript(os.path.join(libraries_path_prefix, 'ch32_drivers','SConscript'), variant_dir='build/libraries/ch32_drivers', duplicate=0)) + +# make a building +DoBuilding(TARGET, objs) diff --git a/bsp/wch/risc-v/ch32v203c-evt-r0/applications/SConscript b/bsp/wch/risc-v/ch32v203c-evt-r0/applications/SConscript new file mode 100644 index 000000000000..e1c7fa599623 --- /dev/null +++ b/bsp/wch/risc-v/ch32v203c-evt-r0/applications/SConscript @@ -0,0 +1,18 @@ +from building import * +import os + +cwd = GetCurrentDir() +CPPPATH = [cwd] +src = Glob('*.c') + +if GetDepend(['PKG_USING_RTDUINO']) and not GetDepend(['RTDUINO_NO_SETUP_LOOP']): + src += ['arduino_main.cpp'] + +group = DefineGroup('Applications', src, depend = [''], CPPPATH = CPPPATH) + +list = os.listdir(cwd) +for item in list: + if os.path.isfile(os.path.join(cwd, item, 'SConscript')): + group = group + SConscript(os.path.join(item, 'SConscript')) + +Return('group') diff --git a/bsp/wch/risc-v/ch32v203c-evt-r0/applications/main.c b/bsp/wch/risc-v/ch32v203c-evt-r0/applications/main.c new file mode 100644 index 000000000000..6f91c9a1fab9 --- /dev/null +++ b/bsp/wch/risc-v/ch32v203c-evt-r0/applications/main.c @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2006-2026, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2026-09-21 seteiro CH32V203C8T6-EVT-R0: print chip id, no LED default + */ + +#include + +int main(void) +{ + rt_kprintf("MCU: CH32V203C8T6\n"); + + while (1) + { + rt_thread_mdelay(1000); + } +} diff --git a/bsp/wch/risc-v/ch32v203c-evt-r0/applications/wdt_msh.c b/bsp/wch/risc-v/ch32v203c-evt-r0/applications/wdt_msh.c new file mode 100644 index 000000000000..f11556f86ef7 --- /dev/null +++ b/bsp/wch/risc-v/ch32v203c-evt-r0/applications/wdt_msh.c @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2006-2026, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2026-09-22 seteiro CH32V203: start or feed the independent watchdog + */ + +#include +#include +#include + +#ifdef BSP_USING_IWDT + +static int wdt(int argc, char **argv) +{ + rt_device_t dev; + rt_uint32_t timeout; + rt_err_t err; + + if (argc < 2) + { + rt_kprintf("wdt start | wdt feed\n"); + return -RT_ERROR; + } + + dev = rt_device_find("wdt"); + if (dev == RT_NULL) + { + rt_kprintf("wdt device not found\n"); + return -RT_ERROR; + } + + if (!rt_strcmp(argv[1], "start")) + { + if (argc < 3) + { + rt_kprintf("wdt start \n"); + return -RT_ERROR; + } + timeout = atoi(argv[2]); + err = rt_device_init(dev); + if (err != RT_EOK) + { + return err; + } + err = rt_device_control(dev, RT_DEVICE_CTRL_WDT_SET_TIMEOUT, &timeout); + if (err != RT_EOK) + { + return err; + } + err = rt_device_control(dev, RT_DEVICE_CTRL_WDT_START, RT_NULL); + rt_kprintf("wdt start %u %s\n", timeout, err == RT_EOK ? "ok" : "fail"); + return err; + } + + if (!rt_strcmp(argv[1], "feed")) + { + err = rt_device_control(dev, RT_DEVICE_CTRL_WDT_KEEPALIVE, RT_NULL); + rt_kprintf("wdt feed %s\n", err == RT_EOK ? "ok" : "fail"); + return err; + } + + rt_kprintf("wdt start | wdt feed\n"); + return -RT_ERROR; +} +MSH_CMD_EXPORT(wdt, start or feed independent watchdog); + +#endif diff --git a/bsp/wch/risc-v/ch32v203c-evt-r0/board/Kconfig b/bsp/wch/risc-v/ch32v203c-evt-r0/board/Kconfig new file mode 100644 index 000000000000..e50efed34f0d --- /dev/null +++ b/bsp/wch/risc-v/ch32v203c-evt-r0/board/Kconfig @@ -0,0 +1,631 @@ +menu "Hardware Drivers Config" + +config SOC_CH32V203C8 + bool + select SOC_RISCV_SERIES_CH32V2 + select SOC_RISCV_SERIES_CH32V20x_D6 + select RT_USING_COMPONENTS_INIT + select RT_USING_USER_MAIN + default y + +menu "Onboard Peripheral Drivers" + +endmenu + +menu "On-chip Peripheral Drivers" + config BSP_USING_GPIO + bool "Enable GPIO" + select RT_USING_PIN + default y + + menuconfig BSP_USING_UART + bool "Enable UART" + select RT_USING_SERIAL + default y + + if BSP_USING_UART + config BSP_USING_UART1 + bool "Enable UART1" + default y + + config BSP_USING_UART2 + bool "Enable UART2" + default n + + config BSP_USING_UART3 + bool "Enable UART3" + default n + + config BSP_USING_UART4 + bool "Enable UART4" + default n + endif + + menuconfig BSP_USING_ADC + bool "Enable ADC" + select RT_USING_ADC + default n + + if BSP_USING_ADC + config BSP_USING_ADC1 + bool "Enable ADC1" + default n + + config BSP_USING_ADC2 + bool "Enable ADC2" + default n + + config ADC_CHANNEL_16 + bool "Enable ADC CHANNEL 16 (inside temperature)" + default n + + config ADC_CHANNEL_17 + bool "Enable ADC CHANNEL 17 (inside Verf)" + default n + endif + + menuconfig BSP_USING_DAC + bool "Enable DAC" + select RT_USING_DAC + default n + + if BSP_USING_DAC + config BSP_USING_DAC_CHANNEL1 + bool "Enable DAC CHANNEL1" + default n + config BSP_USING_DAC_CHANNEL2 + bool "Enable DAC CHANNEL2" + default n + endif + + menuconfig BSP_USING_SOFT_I2C + bool "Enable software I2C (swi2c)" + default n + select RT_USING_I2C + select RT_USING_SOFT_I2C + if BSP_USING_SOFT_I2C + menuconfig BSP_USING_SOFT_I2C1 + bool "Enable software I2C1 Bus (swi2c1)" + default n + select RT_USING_SOFT_I2C1 + if BSP_USING_SOFT_I2C1 + config RT_SOFT_I2C1_SCL_PIN + int "swi2c1 SCL pin number" + default 26 + config RT_SOFT_I2C1_SDA_PIN + int "swi2c1 SDA pin number" + default 27 + endif + + menuconfig BSP_USING_SOFT_I2C2 + bool "Enable software I2C2 Bus (swi2c2)" + default n + select RT_USING_SOFT_I2C2 + if BSP_USING_SOFT_I2C2 + config RT_SOFT_I2C2_SCL_PIN + int "swi2c2 SCL pin number" + default 16 + config RT_SOFT_I2C2_SDA_PIN + int "swi2c2 SDA pin number" + default 17 + endif + endif + menuconfig BSP_USING_SPI + bool "Enable SPI" + select RT_USING_SPI + + if BSP_USING_SPI + config BSP_USING_SPI1 + bool "Enable SPI1" + default n + + config BSP_USING_SPI2 + bool "Enable SPI2" + default n + + config BSP_USING_SPI3 + bool "Enable SPI3" + default n + + if BSP_USING_SPI3 + config BSP_USING_SPI_FLASH + bool "Enable SPI Flash" + default n + endif + + menuconfig BSP_USING_SOFT_SPI1 + bool "Enable software SPI1 Bus (swspi1)" + default n + select RT_USING_SOFT_SPI + select RT_USING_SOFT_SPI1 + if BSP_USING_SOFT_SPI1 + config RT_SOFT_SPI1_SCK_PIN + int "swspi1 SCK pin number" + default 25 + config RT_SOFT_SPI1_MISO_PIN + int "swspi1 MISO pin number" + default 23 + config RT_SOFT_SPI1_MOSI_PIN + int "swspi1 MOSI pin number" + default 24 + endif + + menuconfig BSP_USING_SOFT_SPI2 + bool "Enable software SPI2 Bus (swspi2)" + default n + select RT_USING_SOFT_SPI + select RT_USING_SOFT_SPI2 + if BSP_USING_SOFT_SPI2 + config RT_SOFT_SPI2_SCK_PIN + int "swspi2 SCK pin number" + default 64 + config RT_SOFT_SPI2_MISO_PIN + int "swspi2 MISO pin number" + default 66 + config RT_SOFT_SPI2_MOSI_PIN + int "swspi2 MOSI pin number" + default 65 + endif + + endif + + config RT_SOFT_SPI1_HAS_PIN_DEFAULT + bool + default y if RT_USING_SOFT_SPI1 + + config RT_SOFT_SPI1_SCK_PIN_DEFAULT + int + default 25 if RT_USING_SOFT_SPI1 + + config RT_SOFT_SPI1_MISO_PIN_DEFAULT + int + default 23 if RT_USING_SOFT_SPI1 + + config RT_SOFT_SPI1_MOSI_PIN_DEFAULT + int + default 24 if RT_USING_SOFT_SPI1 + + config RT_SOFT_SPI1_HAS_BUS_NAME_DEFAULT + bool + default y if RT_USING_SOFT_SPI1 + + config RT_SOFT_SPI1_BUS_NAME_DEFAULT + string + default "swspi1" if RT_USING_SOFT_SPI1 + + config RT_SOFT_SPI2_HAS_PIN_DEFAULT + bool + default y if RT_USING_SOFT_SPI2 + + config RT_SOFT_SPI2_SCK_PIN_DEFAULT + int + default 64 if RT_USING_SOFT_SPI2 + + config RT_SOFT_SPI2_MISO_PIN_DEFAULT + int + default 66 if RT_USING_SOFT_SPI2 + + config RT_SOFT_SPI2_MOSI_PIN_DEFAULT + int + default 65 if RT_USING_SOFT_SPI2 + + config RT_SOFT_SPI2_HAS_BUS_NAME_DEFAULT + bool + default y if RT_USING_SOFT_SPI2 + + config RT_SOFT_SPI2_BUS_NAME_DEFAULT + string + default "swspi2" if RT_USING_SOFT_SPI2 + + config BSP_USING_RTC + bool "Enable RTC" + select RT_USING_RTC + default n + + if BSP_USING_RTC + config BSP_USING_RTC_LSI + bool "Using LSI clock for rtc, if not, LSE default" + select LSI_VALUE + default n + endif + + config LSI_VALUE + int + default 40000 + + config BSP_USING_IWDT + bool "Enable IWDT" + select RT_USING_WDT + select LSI_VALUE + default n + + config BSP_USING_USBD + bool "Enable USB Device" + select RT_USING_USB_DEVICE + default n + help + Type-C connector P7, PA11/PA12. + 64KB Flash cannot hold USB together with PWM, ADC, RTC and IWDT. + Set the USB thread stack to 1024. The menu default 4096 is large for 20KB SRAM. + + menuconfig BSP_USING_CAN + bool "Enable CAN" + default n + select RT_USING_CAN + if BSP_USING_CAN + config BSP_USING_CAN1 + bool "Using CAN1" + default n + config BSP_USING_CAN2 + bool "Using CAN2" + default n + endif + + config BSP_USING_TIM + bool "Using TIMx" + default n + + if BSP_USING_TIM + config BSP_USING_CLOCK_TIMER + bool + select RT_USING_CLOCK_TIME + default n + + config BSP_USING_PWM + bool + select RT_USING_PWM + default n + + config BSP_USING_TIM1 + bool "using TIM1" + default n + + if BSP_USING_TIM1 + choice BSP_TIM1_SEL + prompt "Using TIM1 as clock_timer or PWM mode" + default BSP_USING_TIM1_CLOCK_TIMER + + config BSP_USING_TIM1_CLOCK_TIMER + bool "Using TIM1 as clock_timer mode" + select BSP_USING_CLOCK_TIMER + + config BSP_USING_TIM1_PWM + bool "Using TIM1 as PWM mode" + select BSP_USING_PWM + endchoice + + if BSP_USING_TIM1_PWM + config BSP_USING_TIM1_PWM_CH1 + bool "Using TIM1 channel 1" + default n + + config BSP_USING_TIM1_PWM_CH2 + bool "Using TIM1 channel 2" + default n + + config BSP_USING_TIM1_PWM_CH3 + bool "Using TIM1 channel 3" + + config BSP_USING_TIM1_PWM_CH4 + bool "Using TIM1 channel 4" + endif + + endif + + config BSP_USING_TIM2 + bool "Using TIM2" + default n + + if BSP_USING_TIM2 + choice BSP_TIM2_SEL + prompt "Using TIM2 as clock_timer or PWM mode" + default BSP_USING_TIM2_CLOCK_TIMER + + config BSP_USING_TIM2_CLOCK_TIMER + bool "Using TIM2 as clock_timer mode" + select BSP_USING_CLOCK_TIMER + + config BSP_USING_TIM2_PWM + bool "Using TIM2 as PWM mode" + select BSP_USING_PWM + endchoice + + if BSP_USING_TIM2_PWM + config BSP_USING_TIM2_PWM_CH1 + bool "Using TIM2 channel 1" + default n + + config BSP_USING_TIM2_PWM_CH2 + bool "Using TIM2 channel 2" + default n + + config BSP_USING_TIM2_PWM_CH3 + bool "Using TIM2 channel 3" + + config BSP_USING_TIM2_PWM_CH4 + bool "Using TIM2 channel 4" + endif + + endif + + config BSP_USING_TIM3 + bool "Using TIM3" + default n + + if BSP_USING_TIM3 + choice BSP_TIM3_SEL + prompt "Using TIM3 as clock_timer or PWM mode" + default BSP_USING_TIM3_CLOCK_TIMER + + config BSP_USING_TIM3_CLOCK_TIMER + bool "Using TIM3 as clock_timer mode" + select BSP_USING_CLOCK_TIMER + + config BSP_USING_TIM3_PWM + bool "Using TIM3 as PWM mode" + select BSP_USING_PWM + endchoice + + if BSP_USING_TIM3_PWM + config BSP_USING_TIM3_PWM_CH1 + bool "Using TIM3 channel 1" + default n + + config BSP_USING_TIM3_PWM_CH2 + bool "Using TIM3 channel 2" + default n + + config BSP_USING_TIM3_PWM_CH3 + bool "Using TIM3 channel 3" + + config BSP_USING_TIM3_PWM_CH4 + bool "Using TIM3 channel 4" + endif + + endif + + config BSP_USING_TIM4 + bool "Using TIM4" + default n + + if BSP_USING_TIM4 + choice BSP_TIM4_SEL + prompt "Using TIM4 as clock_timer or PWM mode" + default BSP_USING_TIM4_CLOCK_TIMER + + config BSP_USING_TIM4_CLOCK_TIMER + bool "Using TIM4 as clock_timer mode" + select BSP_USING_CLOCK_TIMER + + config BSP_USING_TIM4_PWM + bool "Using TIM4 as PWM mode" + select BSP_USING_PWM + endchoice + + if BSP_USING_TIM4_PWM + config BSP_USING_TIM4_PWM_CH1 + bool "Using TIM4 channel 1" + default n + + config BSP_USING_TIM4_PWM_CH2 + bool "Using TIM4 channel 2" + default n + + config BSP_USING_TIM4_PWM_CH3 + bool "Using TIM4 channel 3" + + config BSP_USING_TIM4_PWM_CH4 + bool "Using TIM4 channel 4" + endif + + endif + + config BSP_USING_TIM5 + bool "Using TIM5" + default n + + if BSP_USING_TIM5 + choice BSP_TIM5_SEL + prompt "Using TIM5 as clock_timer or PWM mode" + default BSP_USING_TIM5_CLOCK_TIMER + + config BSP_USING_TIM5_CLOCK_TIMER + bool "Using TIM5 as clock_timer mode" + select BSP_USING_CLOCK_TIMER + + config BSP_USING_TIM5_PWM + bool "Using TIM5 as PWM mode" + select BSP_USING_PWM + endchoice + + if BSP_USING_TIM5_PWM + config BSP_USING_TIM5_PWM_CH1 + bool "Using TIM5 channel 1" + default n + + config BSP_USING_TIM5_PWM_CH2 + bool "Using TIM5 channel 2" + default n + + config BSP_USING_TIM5_PWM_CH3 + bool "Using TIM5 channel 3" + + config BSP_USING_TIM5_PWM_CH4 + bool "Using TIM5 channel 4" + endif + + endif + + config BSP_USING_TIM6 + bool "Using TIM6" + default n + + if BSP_USING_TIM6 + choice TIM5_CLK_TMR_PWM_MO_SEL + prompt "Using TIM6 as clock_timer (PWM mode not supported)" + default BSP_USING_TIM6_CLOCK_TIMER + + config BSP_USING_TIM6_CLOCK_TIMER + bool "Using TIM6 as clock_timer mode" + select BSP_USING_CLOCK_TIMER + endchoice + + endif + + config BSP_USING_TIM7 + bool "Using TIM7" + default n + + if BSP_USING_TIM7 + choice TIM7_CLK_TMR_PWM_MO_SEL + prompt "Using TIM7 as clock_timer (PWM mode not supported)" + default BSP_USING_TIM7_CLOCK_TIMER + + config BSP_USING_TIM7_CLOCK_TIMER + bool "Using TIM7 as clock_timer mode" + select BSP_USING_CLOCK_TIMER + endchoice + + endif + + config BSP_USING_TIM8 + bool "Using TIM8" + default n + + if BSP_USING_TIM8 + choice BSP_TIM8_SEL + prompt "Using TIM8 as clock_timer or PWM mode" + default BSP_USING_TIM8_CLOCK_TIMER + + config BSP_USING_TIM8_CLOCK_TIMER + bool "Using TIM8 as clock_timer mode" + select BSP_USING_CLOCK_TIMER + + config BSP_USING_TIM8_PWM + bool "Using TIM8 as PWM mode" + select BSP_USING_PWM + endchoice + + if BSP_USING_TIM8_PWM + config BSP_USING_TIM8_PWM_CH1 + bool "Using TIM8 channel 1" + default n + + config BSP_USING_TIM8_PWM_CH2 + bool "Using TIM8 channel 2" + default n + + config BSP_USING_TIM8_PWM_CH3 + bool "Using TIM8 channel 3" + + config BSP_USING_TIM8_PWM_CH4 + bool "Using TIM8 channel 4" + endif + + endif + + config BSP_USING_TIM9 + bool "Using TIM9" + default n + + if BSP_USING_TIM9 + choice BSP_TIM9_SEL + prompt "Using TIM9 as clock_timer or PWM mode" + default BSP_USING_TIM9_CLOCK_TIMER + + config BSP_USING_TIM9_CLOCK_TIMER + bool "Using TIM9 as clock_timer mode" + select BSP_USING_CLOCK_TIMER + + config BSP_USING_TIM9_PWM + bool "Using TIM9 as PWM mode" + select BSP_USING_PWM + endchoice + + if BSP_USING_TIM9_PWM + config BSP_USING_TIM9_PWM_CH1 + bool "Using TIM9 channel 1" + default n + + config BSP_USING_TIM9_PWM_CH2 + bool "Using TIM9 channel 2" + default n + + config BSP_USING_TIM9_PWM_CH3 + bool "Using TIM9 channel 3" + + config BSP_USING_TIM9_PWM_CH4 + bool "Using TIM9 channel 4" + endif + + endif + + config BSP_USING_TIM10 + bool "Using TIM10" + default n + + if BSP_USING_TIM10 + choice BSP_TIM10_SEL + prompt "Using TIM10 as clock_timer or PWM mode" + default BSP_USING_TIM10_CLOCK_TIMER + + config BSP_USING_TIM10_CLOCK_TIMER + bool "Using TIM10 as clock_timer mode" + select BSP_USING_CLOCK_TIMER + + config BSP_USING_TIM10_PWM + bool "Using TIM10 as PWM mode" + select BSP_USING_PWM + endchoice + + if BSP_USING_TIM10_PWM + config BSP_USING_TIM10_PWM_CH1 + bool "Using TIM10 channel 1" + default n + + config BSP_USING_TIM10_PWM_CH2 + bool "Using TIM10 channel 2" + default n + + config BSP_USING_TIM10_PWM_CH3 + bool "Using TIM10 channel 3" + + config BSP_USING_TIM10_PWM_CH4 + bool "Using TIM10 channel 4" + endif + + endif + + endif + +endmenu + +menu "Board extended module Drivers" + +endmenu + + config RT_SOFT_I2C1_HAS_PIN_DEFAULT + bool + default y if RT_USING_SOFT_I2C1 + + config RT_SOFT_I2C1_SCL_PIN_DEFAULT + int + default 26 if RT_USING_SOFT_I2C1 + + config RT_SOFT_I2C1_SDA_PIN_DEFAULT + int + default 27 if RT_USING_SOFT_I2C1 + + config RT_SOFT_I2C2_HAS_PIN_DEFAULT + bool + default y if RT_USING_SOFT_I2C2 + + config RT_SOFT_I2C2_SCL_PIN_DEFAULT + int + default 16 if RT_USING_SOFT_I2C2 + + config RT_SOFT_I2C2_SDA_PIN_DEFAULT + int + default 17 if RT_USING_SOFT_I2C2 + +endmenu diff --git a/bsp/wch/risc-v/ch32v203c-evt-r0/board/SConscript b/bsp/wch/risc-v/ch32v203c-evt-r0/board/SConscript new file mode 100644 index 000000000000..aa6c728dd3cf --- /dev/null +++ b/bsp/wch/risc-v/ch32v203c-evt-r0/board/SConscript @@ -0,0 +1,19 @@ +import os +import rtconfig +from building import * + +Import('SDK_LIB') + +cwd = GetCurrentDir() + +# add general drivers +src = Split(''' +board.c +software_irq.c +startup_ch32v20x_D6.S +''') + +path = [cwd] + +group = DefineGroup('Drivers', src, depend = [''], CPPPATH = path) +Return('group') diff --git a/bsp/wch/risc-v/ch32v203c-evt-r0/board/board.c b/bsp/wch/risc-v/ch32v203c-evt-r0/board/board.c new file mode 100644 index 000000000000..6461eb7a2a1a --- /dev/null +++ b/bsp/wch/risc-v/ch32v203c-evt-r0/board/board.c @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2006-2026, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2026-09-21 seteiro CH32V203C8T6-EVT-R0: linker heap like ch32v307v-r1 + */ + +#include "board.h" +#include +#include "drv_usart.h" +#include "drv_gpio.h" +#include +#include + +extern uint32_t SystemCoreClock; + +static uint32_t _SysTick_Config(rt_uint32_t ticks) +{ + NVIC_SetPriority(SysTicK_IRQn, 0xf0); + NVIC_SetPriority(Software_IRQn, 0xf0); + NVIC_EnableIRQ(SysTicK_IRQn); + NVIC_EnableIRQ(Software_IRQn); + SysTick->CTLR = 0; + SysTick->SR = 0; + SysTick->CNT = 0; + SysTick->CMP = ticks - 1; + SysTick->CTLR = 0xF; + return 0; +} + +void rt_hw_board_init() +{ + _SysTick_Config(SystemCoreClock / RT_TICK_PER_SECOND); + +#if defined(RT_USING_USER_MAIN) && defined(RT_USING_HEAP) + rt_system_heap_init((void *) HEAP_BEGIN, (void *) HEAP_END); +#endif +#ifdef RT_USING_SERIAL + rt_hw_usart_init(); +#endif +#ifdef RT_USING_CONSOLE + rt_console_set_device(RT_CONSOLE_DEVICE_NAME); +#endif +#ifdef RT_USING_PIN + rt_hw_pin_init(); +#endif +#ifdef RT_USING_COMPONENTS_INIT + rt_components_board_init(); +#endif +} + +#ifdef BSP_USING_USBD +#include "ch32v20x_usb.h" +extern int rt_hw_usbd_init(void); + +static int board_usbd_init(void) +{ + RCC_ClocksTypeDef clocks; + volatile int wait; + + RCC_GetClocksFreq(&clocks); + if (clocks.SYSCLK_Frequency == 144000000) + RCC_USBCLKConfig(RCC_USBCLKSource_PLLCLK_Div3); + else if (clocks.SYSCLK_Frequency == 96000000) + RCC_USBCLKConfig(RCC_USBCLKSource_PLLCLK_Div2); + else if (clocks.SYSCLK_Frequency == 48000000) + RCC_USBCLKConfig(RCC_USBCLKSource_PLLCLK_Div1); + RCC_AHBPeriphClockCmd(RCC_AHBPeriph_USBFS, ENABLE); + + /* Same SIE reset the WCH USBFS device example does before enabling. */ + USBFSH->BASE_CTRL = USBFS_UC_RESET_SIE | USBFS_UC_CLR_ALL; + for (wait = 0; wait < 200; wait++) + ; + USBFSH->BASE_CTRL = 0x00; + + return rt_hw_usbd_init(); +} +INIT_DEVICE_EXPORT(board_usbd_init); +#endif + +#if defined(BSP_USING_ADC1) && (defined(ADC_CHANNEL_16) || defined(ADC_CHANNEL_17)) +static int board_adc_internal_on(void) +{ + /* Channels 16 and 17 stay near zero until this switch is on. */ + ADC_TempSensorVrefintCmd(ENABLE); + return 0; +} +INIT_APP_EXPORT(board_adc_internal_on); +#endif + +void SysTick_Handler(void) __attribute__((interrupt())); +void SysTick_Handler(void) +{ + GET_INT_SP(); + rt_interrupt_enter(); + SysTick->SR = 0; + rt_tick_increase(); + rt_interrupt_leave(); + FREE_INT_SP(); +} diff --git a/bsp/wch/risc-v/ch32v203c-evt-r0/board/board.h b/bsp/wch/risc-v/ch32v203c-evt-r0/board/board.h new file mode 100644 index 000000000000..57bd059cedf6 --- /dev/null +++ b/bsp/wch/risc-v/ch32v203c-evt-r0/board/board.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2006-2026, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2026-09-21 seteiro CH32V203C8T6-EVT-R0: D6, 20K SRAM, heap from linker + */ + +#ifndef __BOARD_H__ +#define __BOARD_H__ + +#include +#include "ch32v20x.h" +#include "drv_gpio.h" +#include "drv_pwm.h" + +/* LQFP48 encoding uses port*16+pin; 64 covers GPIOA-D on this part. */ +#define ch32v20x_PIN_NUMBERS 64 + +/* CH32V203C8T6: 20KB SRAM, 64KB zero-wait Flash (datasheet C8 row). */ +#define SRAM_SIZE 20 +#define SRAM_END (0x20000000 + SRAM_SIZE * 1024) + +extern int _ebss, _susrstack; +#define HEAP_BEGIN ((void *)&_ebss) +#define HEAP_END ((void *)&_susrstack) + +void rt_hw_board_init(void); + +#ifdef BSP_USING_USBD +#include "ch32v20x_usb.h" +/* Chip headers define these as macros. drv_usbd.c wants a pointer variable. */ +#undef USBOTG_FS +#undef USBFSD +typedef USBFSD_TypeDef USBOTG_FS_TypeDef; +#define USBOTG_FS ((USBOTG_FS_TypeDef *)USBFS_BASE) +#define OTG_FS_IRQn USBFS_IRQn +#define USBD_IRQHandler USBFS_IRQHandler +#endif + +#endif /* __BOARD_H__ */ diff --git a/bsp/wch/risc-v/ch32v203c-evt-r0/board/linker_scripts/link.lds b/bsp/wch/risc-v/ch32v203c-evt-r0/board/linker_scripts/link.lds new file mode 100644 index 000000000000..815d0b33d263 --- /dev/null +++ b/bsp/wch/risc-v/ch32v203c-evt-r0/board/linker_scripts/link.lds @@ -0,0 +1,212 @@ +ENTRY( _start ) + +__stack_size = 2048; + +PROVIDE( _stack_size = __stack_size ); + + +MEMORY +{ + FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 64K + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 20K +} + + +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*) + *(.glue_7) + *(.glue_7t) + *(.gnu.linkonce.t.*) + + /* section information for finsh shell */ + . = ALIGN(4); + __fsymtab_start = .; + KEEP(*(FSymTab)) + __fsymtab_end = .; + . = ALIGN(4); + __vsymtab_start = .; + KEEP(*(VSymTab)) + __vsymtab_end = .; + . = ALIGN(4); + + /* section information for initial. */ + . = ALIGN(4); + __rt_init_start = .; + KEEP(*(SORT(.rti_fn*))) + __rt_init_end = .; + . = ALIGN(4); + + /* section information for modules */ + . = ALIGN(4); + __rtmsymtab_start = .; + KEEP(*(RTMSymTab)) + __rtmsymtab_end = .; + . = ALIGN(4); + + /* section information for initial. */ + . = ALIGN(4); + __rt_init_start = .; + KEEP(*(SORT(.rti_fn*))) + __rt_init_end = .; + + . = ALIGN(4); + + PROVIDE(__ctors_start__ = .); + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array)) + PROVIDE(__ctors_end__ = .); + + . = ALIGN(4); + + _etext = .; + + } >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 : + { + /* gcc uses crtbegin.o to find the start of + the constructors, so we make sure it is + first. Because this is a wildcard, it + doesn't matter if the user does not + actually link against crtbegin.o; the + linker won't look for a file to match a + wildcard. The wildcard also means that it + doesn't matter which directory crtbegin.o + is in. */ + KEEP (*crtbegin.o(.ctors)) + KEEP (*crtbegin?.o(.ctors)) + /* We don't want to include the .ctor section from + the crtend.o file until after the sorted ctors. + The .ctor section from the crtend file contains the + end of ctors marker and it must be last */ + 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 = .); + PROVIDE( __rt_rvstack = . ); + } >RAM + +} + + + diff --git a/bsp/wch/risc-v/ch32v203c-evt-r0/board/software_irq.c b/bsp/wch/risc-v/ch32v203c-evt-r0/board/software_irq.c new file mode 100644 index 000000000000..e91a5883125e --- /dev/null +++ b/bsp/wch/risc-v/ch32v203c-evt-r0/board/software_irq.c @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-09-09 WCH the first version + * 2023-01-04 WangShun Remove redundant files + */ +#include "rtconfig.h" +#if defined (SOC_RISCV_SERIES_CH32V1) +#include "ch32v10x.h" +#elif defined (SOC_RISCV_SERIES_CH32V2) +#include "ch32v20x.h" +#elif defined (SOC_RISCV_SERIES_CH32V3) +#include "ch32v30x.h" +#else +#error "CH32 architecture doesn't support!" +#endif +void rt_trigger_software_interrupt(void) +{ + /*CH32V103 does not support systick software interrupt*/ +#if defined(SOC_RISCV_SERIES_CH32V1) + NVIC_SetPendingIRQ(Software_IRQn); +#else + SysTick->CTLR |= (1 << 31); +#endif +} + +void rt_hw_do_after_save_above(void) +{ + __asm volatile ("li t0,0x20" ); + __asm volatile ("csrs 0x804, t0"); + /*CH32V103 does not support systick software interrupt*/ +#if defined(SOC_RISCV_SERIES_CH32V1) + NVIC_ClearPendingIRQ(Software_IRQn); +#else + SysTick->CTLR &= ~(1 << 31); +#endif +} \ No newline at end of file diff --git a/bsp/wch/risc-v/ch32v203c-evt-r0/board/startup_ch32v20x_D6.S b/bsp/wch/risc-v/ch32v203c-evt-r0/board/startup_ch32v20x_D6.S new file mode 100644 index 000000000000..f7dc334da65c --- /dev/null +++ b/bsp/wch/risc-v/ch32v203c-evt-r0/board/startup_ch32v20x_D6.S @@ -0,0 +1,258 @@ +/********************************** (C) COPYRIGHT ******************************* +* File Name : startup_ch32v20x_D6.S +* Author : WCH +* Version : V1.0.2 +* Date : 2025/10/21 +* Description : CH32V203C8T6 (D6) vector table from WCH EVT. +* handle_reset jumps to RT-Thread entry, same as +* CH32V20x-SDK-for-RTT D8W rtt-patch (not bare-metal main). +* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd. +* SPDX-License-Identifier: Apache-2.0 +*******************************************************************************/ + + .section .init,"ax",@progbits + .global _start + .align 1 +_start: + j handle_reset + .word 0x00000013 + .word 0x00000013 + .word 0x00000013 + .word 0x00000013 + .word 0x00000013 + .word 0x00000013 + .word 0x00000013 + .word 0x00000013 + .word 0x00000013 + .word 0x00000013 + .word 0x00000013 + .word 0x00100073 + + .section .vector,"ax",@progbits + .align 1 +_vector_base: + .option norvc; + .word _start + .word 0 + .word NMI_Handler + .word HardFault_Handler + .word 0 + .word Ecall_M_Mode_Handler + .word 0 + .word 0 + .word Ecall_U_Mode_Handler + .word Break_Point_Handler + .word 0 + .word 0 + .word SysTick_Handler + .word 0 + .word SW_handler /* libcpu symbol; SW_Handler would be a different infinite loop */ + .word 0 + .word WWDG_IRQHandler + .word PVD_IRQHandler + .word TAMPER_IRQHandler + .word RTC_IRQHandler + .word FLASH_IRQHandler + .word RCC_IRQHandler + .word EXTI0_IRQHandler + .word EXTI1_IRQHandler + .word EXTI2_IRQHandler + .word EXTI3_IRQHandler + .word EXTI4_IRQHandler + .word DMA1_Channel1_IRQHandler + .word DMA1_Channel2_IRQHandler + .word DMA1_Channel3_IRQHandler + .word DMA1_Channel4_IRQHandler + .word DMA1_Channel5_IRQHandler + .word DMA1_Channel6_IRQHandler + .word DMA1_Channel7_IRQHandler + .word ADC1_2_IRQHandler + .word USB_HP_CAN1_TX_IRQHandler + .word USB_LP_CAN1_RX0_IRQHandler + .word CAN1_RX1_IRQHandler + .word CAN1_SCE_IRQHandler + .word EXTI9_5_IRQHandler + .word TIM1_BRK_IRQHandler + .word TIM1_UP_IRQHandler + .word TIM1_TRG_COM_IRQHandler + .word TIM1_CC_IRQHandler + .word TIM2_IRQHandler + .word TIM3_IRQHandler + .word TIM4_IRQHandler + .word I2C1_EV_IRQHandler + .word I2C1_ER_IRQHandler + .word I2C2_EV_IRQHandler + .word I2C2_ER_IRQHandler + .word SPI1_IRQHandler + .word SPI2_IRQHandler + .word USART1_IRQHandler + .word USART2_IRQHandler + .word USART3_IRQHandler + .word EXTI15_10_IRQHandler + .word RTCAlarm_IRQHandler + .word USBWakeUp_IRQHandler + .word USBFS_IRQHandler + .word USBFSWakeUp_IRQHandler + .word UART4_IRQHandler + .word DMA1_Channel8_IRQHandler + + .option rvc; + .section .text.vector_handler, "ax", @progbits + .weak NMI_Handler + .weak HardFault_Handler + .weak Ecall_M_Mode_Handler + .weak Ecall_U_Mode_Handler + .weak Break_Point_Handler + .weak SysTick_Handler + .weak SW_handler + .weak WWDG_IRQHandler + .weak PVD_IRQHandler + .weak TAMPER_IRQHandler + .weak RTC_IRQHandler + .weak FLASH_IRQHandler + .weak RCC_IRQHandler + .weak EXTI0_IRQHandler + .weak EXTI1_IRQHandler + .weak EXTI2_IRQHandler + .weak EXTI3_IRQHandler + .weak EXTI4_IRQHandler + .weak DMA1_Channel1_IRQHandler + .weak DMA1_Channel2_IRQHandler + .weak DMA1_Channel3_IRQHandler + .weak DMA1_Channel4_IRQHandler + .weak DMA1_Channel5_IRQHandler + .weak DMA1_Channel6_IRQHandler + .weak DMA1_Channel7_IRQHandler + .weak ADC1_2_IRQHandler + .weak USB_HP_CAN1_TX_IRQHandler + .weak USB_LP_CAN1_RX0_IRQHandler + .weak CAN1_RX1_IRQHandler + .weak CAN1_SCE_IRQHandler + .weak EXTI9_5_IRQHandler + .weak TIM1_BRK_IRQHandler + .weak TIM1_UP_IRQHandler + .weak TIM1_TRG_COM_IRQHandler + .weak TIM1_CC_IRQHandler + .weak TIM2_IRQHandler + .weak TIM3_IRQHandler + .weak TIM4_IRQHandler + .weak I2C1_EV_IRQHandler + .weak I2C1_ER_IRQHandler + .weak I2C2_EV_IRQHandler + .weak I2C2_ER_IRQHandler + .weak SPI1_IRQHandler + .weak SPI2_IRQHandler + .weak USART1_IRQHandler + .weak USART2_IRQHandler + .weak USART3_IRQHandler + .weak EXTI15_10_IRQHandler + .weak RTCAlarm_IRQHandler + .weak USBWakeUp_IRQHandler + .weak USBFS_IRQHandler + .weak USBFSWakeUp_IRQHandler + .weak UART4_IRQHandler + .weak DMA1_Channel8_IRQHandler + +NMI_Handler: +HardFault_Handler: +Ecall_M_Mode_Handler: +Ecall_U_Mode_Handler: +Break_Point_Handler: +SysTick_Handler: +SW_handler: +WWDG_IRQHandler: +PVD_IRQHandler: +TAMPER_IRQHandler: +RTC_IRQHandler: +FLASH_IRQHandler: +RCC_IRQHandler: +EXTI0_IRQHandler: +EXTI1_IRQHandler: +EXTI2_IRQHandler: +EXTI3_IRQHandler: +EXTI4_IRQHandler: +DMA1_Channel1_IRQHandler: +DMA1_Channel2_IRQHandler: +DMA1_Channel3_IRQHandler: +DMA1_Channel4_IRQHandler: +DMA1_Channel5_IRQHandler: +DMA1_Channel6_IRQHandler: +DMA1_Channel7_IRQHandler: +ADC1_2_IRQHandler: +USB_HP_CAN1_TX_IRQHandler: +USB_LP_CAN1_RX0_IRQHandler: +CAN1_RX1_IRQHandler: +CAN1_SCE_IRQHandler: +EXTI9_5_IRQHandler: +TIM1_BRK_IRQHandler: +TIM1_UP_IRQHandler: +TIM1_TRG_COM_IRQHandler: +TIM1_CC_IRQHandler: +TIM2_IRQHandler: +TIM3_IRQHandler: +TIM4_IRQHandler: +I2C1_EV_IRQHandler: +I2C1_ER_IRQHandler: +I2C2_EV_IRQHandler: +I2C2_ER_IRQHandler: +SPI1_IRQHandler: +SPI2_IRQHandler: +USART1_IRQHandler: +USART2_IRQHandler: +USART3_IRQHandler: +EXTI15_10_IRQHandler: +RTCAlarm_IRQHandler: +USBWakeUp_IRQHandler: +USBFS_IRQHandler: +USBFSWakeUp_IRQHandler: +UART4_IRQHandler: +DMA1_Channel8_IRQHandler: +1: + j 1b + + .section .text.handle_reset,"ax",@progbits + .weak handle_reset + .align 1 +handle_reset: +.option push +.option norelax + la gp, __global_pointer$ +.option pop + la sp, _eusrstack + + la a0, _data_lma + la a1, _data_vma + la a2, _edata + bgeu a1, a2, 2f +1: + lw t0, (a0) + sw t0, (a1) + addi a0, a0, 4 + addi a1, a1, 4 + bltu a1, a2, 1b +2: + la a0, _sbss + la a1, _ebss + bgeu a0, a1, 2f +1: + sw zero, (a0) + addi a0, a0, 4 + bltu a0, a1, 1b +2: + li t0, 0x1f + csrw 0xbc0, t0 + + li t0, 0x2 + csrw 0x804, t0 + + li t0, 0x1800 + csrw mstatus, t0 + + la t0, _vector_base + ori t0, t0, 3 + csrw mtvec, t0 + + jal SystemInit + la t0, entry + csrw mepc, t0 + mret diff --git a/bsp/wch/risc-v/ch32v203c-evt-r0/rtconfig.h b/bsp/wch/risc-v/ch32v203c-evt-r0/rtconfig.h new file mode 100644 index 000000000000..39dcf31162f7 --- /dev/null +++ b/bsp/wch/risc-v/ch32v203c-evt-r0/rtconfig.h @@ -0,0 +1,220 @@ +#ifndef RT_CONFIG_H__ +#define RT_CONFIG_H__ + +/* RT-Thread Kernel */ + +/* klibc options */ + +/* rt_vsnprintf options */ + +/* end of rt_vsnprintf options */ + +/* rt_vsscanf options */ + +/* end of rt_vsscanf options */ + +/* rt_memset options */ + +/* end of rt_memset options */ + +/* rt_memcpy options */ + +/* end of rt_memcpy options */ + +/* rt_memmove options */ + +/* end of rt_memmove options */ + +/* rt_memcmp options */ + +/* end of rt_memcmp options */ + +/* rt_strstr options */ + +/* end of rt_strstr options */ + +/* rt_strcasecmp options */ + +/* end of rt_strcasecmp options */ + +/* rt_strncpy options */ + +/* end of rt_strncpy options */ + +/* rt_strcpy options */ + +/* end of rt_strcpy options */ + +/* rt_strncmp options */ + +/* end of rt_strncmp options */ + +/* rt_strcmp options */ + +/* end of rt_strcmp options */ + +/* rt_strlen options */ + +/* end of rt_strlen options */ + +/* rt_strnlen options */ + +/* end of rt_strnlen options */ +/* end of klibc options */ +#define RT_NAME_MAX 12 +#define RT_CPUS_NR 1 +#define RT_ALIGN_SIZE 8 +#define RT_THREAD_PRIORITY_32 +#define RT_THREAD_PRIORITY_MAX 32 +#define RT_TICK_PER_SECOND 1000 +#define RT_USING_HOOK +#define RT_HOOK_USING_FUNC_PTR +#define RT_USING_IDLE_HOOK +#define RT_IDLE_HOOK_LIST_SIZE 4 +#define IDLE_THREAD_STACK_SIZE 512 +#define RT_USING_TIMER_SOFT +#define RT_TIMER_THREAD_PRIO 4 +#define RT_TIMER_THREAD_STACK_SIZE 512 + +/* kservice options */ + +/* end of kservice options */ +#define RT_USING_DEBUG +#define RT_DEBUGING_ASSERT +#define RT_DEBUGING_COLOR +#define RT_DEBUGING_CONTEXT + +/* Inter-Thread communication */ + +#define RT_USING_SEMAPHORE +#define RT_USING_MUTEX +#define RT_USING_EVENT +#define RT_USING_MAILBOX +#define RT_USING_MESSAGEQUEUE +/* end of Inter-Thread communication */ + +/* Memory Management */ + +#define RT_USING_SMALL_MEM +#define RT_USING_SMALL_MEM_AS_HEAP +#define RT_USING_HEAP +/* end of Memory Management */ +#define RT_USING_DEVICE +#define RT_USING_CONSOLE +#define RT_CONSOLEBUF_SIZE 128 +#define RT_CONSOLE_DEVICE_NAME "uart1" +#define RT_USING_CONSOLE_OUTPUT_CTL +#define RT_VER_NUM 0x50301 +#define RT_BACKTRACE_LEVEL_MAX_NR 32 +/* end of RT-Thread Kernel */ +#define RT_USING_HW_ATOMIC +#define ARCH_RISCV + +/* RT-Thread Components */ + +#define RT_USING_COMPONENTS_INIT +#define RT_USING_USER_MAIN +#define RT_MAIN_THREAD_STACK_SIZE 2048 +#define RT_MAIN_THREAD_PRIORITY 10 +#define RT_USING_MSH +#define RT_USING_FINSH +#define FINSH_USING_MSH +#define FINSH_THREAD_NAME "tshell" +#define FINSH_THREAD_PRIORITY 20 +#define FINSH_THREAD_STACK_SIZE 1024 +#define FINSH_USING_HISTORY +#define FINSH_HISTORY_LINES 5 +#define FINSH_USING_SYMTAB +#define FINSH_CMD_SIZE 80 +#define MSH_USING_BUILT_IN_COMMANDS +#define FINSH_ARG_MAX 10 +#define FINSH_USING_OPTION_COMPLETION + +/* DFS: device virtual file system */ + +/* end of DFS: device virtual file system */ + +/* Device Drivers */ + +#define RT_USING_DEVICE_IPC +#define RT_UNAMED_PIPE_NUMBER 64 +#define RT_USING_SERIAL +#define RT_USING_SERIAL_V1 +#define RT_SERIAL_RB_BUFSZ 64 +#define RT_USING_PIN +/* end of Device Drivers */ + +/* C/C++ and POSIX layer */ + +/* ISO-ANSI C layer */ + +/* Timezone and Daylight Saving Time */ + +#define RT_LIBC_USING_LIGHT_TZ_DST +#define RT_LIBC_TZ_DEFAULT_HOUR 8 +#define RT_LIBC_TZ_DEFAULT_MIN 0 +#define RT_LIBC_TZ_DEFAULT_SEC 0 +/* end of Timezone and Daylight Saving Time */ +/* end of ISO-ANSI C layer */ + +/* POSIX (Portable Operating System Interface) layer */ + + +/* Interprocess Communication (IPC) */ + + +/* Socket is in the 'Network' category */ + +/* end of Interprocess Communication (IPC) */ +/* end of POSIX (Portable Operating System Interface) layer */ +/* end of C/C++ and POSIX layer */ + +/* Network */ + +/* end of Network */ + +/* Memory protection */ + +/* end of Memory protection */ + +/* Utilities */ + +/* end of Utilities */ + +/* Using USB legacy version */ + +/* end of Using USB legacy version */ +/* end of RT-Thread Components */ + +/* RT-Thread Utestcases */ + +/* end of RT-Thread Utestcases */ + +/* WCH HAL & SDK Drivers */ + +#define PKG_USING_CH32V20x_SDK +#define PKG_USING_CH32V20x_SDK_LATEST_VERSION +/* end of WCH HAL & SDK Drivers */ +#define SOC_RISCV_FAMILY_CH32 +#define SOC_RISCV_SERIES_CH32V2 +#define SOC_RISCV_SERIES_CH32V20x_D6 + +/* Hardware Drivers Config */ + +#define SOC_CH32V203C8 + +/* Onboard Peripheral Drivers */ + +/* On-chip Peripheral Drivers */ + +#define BSP_USING_GPIO +#define BSP_USING_UART +#define BSP_USING_UART1 +#define LSI_VALUE 40000 +/* end of On-chip Peripheral Drivers */ + +/* Board extended module Drivers */ + +/* end of Hardware Drivers Config */ + +#endif diff --git a/bsp/wch/risc-v/ch32v203c-evt-r0/rtconfig.py b/bsp/wch/risc-v/ch32v203c-evt-r0/rtconfig.py new file mode 100644 index 000000000000..729497796215 --- /dev/null +++ b/bsp/wch/risc-v/ch32v203c-evt-r0/rtconfig.py @@ -0,0 +1,72 @@ +import os +ARCH = 'risc-v' +CPU = 'ch32' +# toolchains options +CROSS_TOOL = 'gcc' + +#------- toolchains path ------------------------------------------------------- +if os.getenv('RTT_CC'): + CROSS_TOOL = os.getenv('RTT_CC') + +if CROSS_TOOL == 'gcc': + PLATFORM = 'gcc' + EXEC_PATH = r'D:\RT-ThreadStudio\repo\Extract\ToolChain_Support_Packages\WCH\RISC-V-GCC-WCH\8.2.0\bin' +else: + print('Please make sure your toolchains is GNU GCC!') + exit(0) + +if os.getenv('RTT_EXEC_PATH'): + EXEC_PATH = os.getenv('RTT_EXEC_PATH') + +BUILD = 'debug' +#BUILD = 'release' + +CORE = 'risc-v' +MAP_FILE = 'rtthread.map' +LINK_FILE = './board/linker_scripts/link.lds' +TARGET_NAME = 'rtthread.bin' + +#------- GCC settings ---------------------------------------------------------- +if PLATFORM == 'gcc': + # toolchains + PREFIX = 'riscv-none-embed-' + CC = PREFIX + 'gcc' + CXX= PREFIX + 'g++' + AS = PREFIX + 'gcc' + AR = PREFIX + 'ar' + LINK = PREFIX + 'gcc' + TARGET_EXT = 'elf' + SIZE = PREFIX + 'size' + OBJDUMP = PREFIX + 'objdump' + OBJCPY = PREFIX + 'objcopy' + + DEVICE = ' -march=rv32imac -mabi=ilp32 -DUSE_PLIC -DUSE_M_TIME -DNO_INIT -mcmodel=medany -msmall-data-limit=8 -L. -nostartfiles -lc ' + CFLAGS = DEVICE + CFLAGS += ' -ffunction-sections -fdata-sections' + CFLAGS += ' -save-temps=obj' + AFLAGS = '-c'+ DEVICE + ' -x assembler-with-cpp' + LFLAGS = DEVICE + LFLAGS += ' -ffunction-sections -fdata-sections --specs=nano.specs' + LFLAGS += ' -Wl,--gc-sections,-cref,-Map=' + MAP_FILE + LFLAGS += ' -T ' + LINK_FILE + AFLAGS += ' -I.' + CPATH = '' + LPATH = '' + + if BUILD == 'debug': + CFLAGS += ' -Os -g3' + AFLAGS += ' -g3' + else: + CFLAGS += ' -O2' + + CXXFLAGS = CFLAGS + + POST_ACTION = OBJCPY + ' -O binary $TARGET ' + TARGET_NAME + '\n' + POST_ACTION += SIZE + ' $TARGET\n' + +def dist_handle(BSP_ROOT, dist_dir): + import sys + cwd_path = os.getcwd() + sys.path.append(os.path.join(os.path.dirname(BSP_ROOT), 'tools')) + from sdk_dist import dist_do_building + dist_do_building(BSP_ROOT, dist_dir) \ No newline at end of file diff --git a/bsp/wch/risc-v/libraries/ch32_drivers/drv_iwdt.c b/bsp/wch/risc-v/libraries/ch32_drivers/drv_iwdt.c index 1497632cdaaa..694a0d05e4c3 100644 --- a/bsp/wch/risc-v/libraries/ch32_drivers/drv_iwdt.c +++ b/bsp/wch/risc-v/libraries/ch32_drivers/drv_iwdt.c @@ -12,7 +12,13 @@ #include #include #include +#if defined(SOC_RISCV_SERIES_CH32V2) +#include "ch32v20x_iwdg.h" +#elif defined(SOC_RISCV_SERIES_CH32V1) +#include "ch32v10x_iwdg.h" +#else #include "ch32v30x_iwdg.h" +#endif #ifdef BSP_USING_IWDT diff --git a/bsp/wch/risc-v/libraries/ch32_drivers/drv_usbd.c b/bsp/wch/risc-v/libraries/ch32_drivers/drv_usbd.c index b549855adcb9..5b39b12e84a8 100644 --- a/bsp/wch/risc-v/libraries/ch32_drivers/drv_usbd.c +++ b/bsp/wch/risc-v/libraries/ch32_drivers/drv_usbd.c @@ -17,35 +17,51 @@ #include "drv_log.h" #define UEP_MPS_64 64 -#define UEP_MPS_512 512 #define _get_ep_idx(address) ((address) & USB_EPNO_MASK) #define _get_ep_dir(address) ((address) & USB_DIR_MASK) #define _is_dir_in(address) (_get_ep_dir(address) == USB_DIR_IN) #define _is_dir_out(address) (_get_ep_dir(address) == USB_DIR_OUT) -#define _get_dma(ep_idx) (*(volatile uint32_t *)((uint32_t)(USBFSD->UEP0_DMA) + 4 * ep_idx)) -#define _set_dma(ep_idx, addr) (*(volatile uint32_t *)((uint32_t)(USBFSD->UEP0_DMA) + 4 * ep_idx) = addr) -#define _set_tx_len(ep_idx, len) (*(volatile uint16_t *)((uint32_t)(USBFSD->UEP0_TX_LEN) + 4 * ep_idx) = len) -#define _get_tx_len(ep_idx) (*(volatile uint16_t *)((uint32_t)(USBFSD->UEP0_TX_LEN) + 4 * ep_idx)) -#define _set_tx_ctrl(ep_idx, val) (*(volatile uint8_t *)((uint32_t)(USBFSD->UEP0_TX_CTRL) + 4 * ep_idx) = val) -#define _get_tx_ctrl(ep_idx) (*(volatile uint8_t *)((uint32_t)(USBFSD->UEP0_TX_CTRL) + 4 * ep_idx)) -#define _set_rx_ctrl(ep_idx, val) (*(volatile uint8_t *)((uint32_t)(USBFSD->UEP0_RX_CTRL) + 4 * ep_idx) = val) -#define _get_rx_ctrl(ep_idx) (*(volatile uint8_t *)((uint32_t)(USBFSD->UEP0_RX_CTRL) + 4 * ep_idx)) +#define _get_dma(ep_idx) (*(volatile uint32_t *)((uint32_t)&USBFSD->UEP0_DMA + 4 * (ep_idx))) +#define _set_dma(ep_idx, addr) (*(volatile uint32_t *)((uint32_t)&USBFSD->UEP0_DMA + 4 * (ep_idx)) = (addr)) +#define _set_tx_len(ep_idx, len) (*(volatile uint16_t *)((uint32_t)&USBFSD->UEP0_TX_LEN + 4 * (ep_idx)) = (len)) +#define _get_tx_len(ep_idx) (*(volatile uint16_t *)((uint32_t)&USBFSD->UEP0_TX_LEN + 4 * (ep_idx))) +#define _set_tx_ctrl(ep_idx, val) (*(volatile uint8_t *)((uint32_t)&USBFSD->UEP0_TX_CTRL + 4 * (ep_idx)) = (val)) +#define _get_tx_ctrl(ep_idx) (*(volatile uint8_t *)((uint32_t)&USBFSD->UEP0_TX_CTRL + 4 * (ep_idx))) +#define _set_rx_ctrl(ep_idx, val) (*(volatile uint8_t *)((uint32_t)&USBFSD->UEP0_RX_CTRL + 4 * (ep_idx)) = (val)) +#define _get_rx_ctrl(ep_idx) (*(volatile uint8_t *)((uint32_t)&USBFSD->UEP0_RX_CTRL + 4 * (ep_idx))) + +/* The DMA register keeps the low 16 bits. SRAM for that offset starts at 0x20000000. */ +static uint8_t *usb_dma_ram(uint32_t dma) +{ + if (dma < 0x20000000) + dma += 0x20000000; + return (uint8_t *)dma; +} static struct udcd udcd; +/* SETUP and EP0 IN must sit in SRAM. USB DMA cannot read Flash. */ +static rt_uint8_t ep0_buf[64] __attribute__((aligned(4))); +static rt_uint8_t epn_buf[8][64] __attribute__((aligned(4))); +static rt_uint8_t usb_addr_pending; +static rt_uint8_t usb_addr_next; + +#ifndef GET_INT_SP +#define GET_INT_SP() asm volatile("csrrw sp,mscratch,sp") +#define FREE_INT_SP() asm volatile("csrrw sp,mscratch,sp") +#endif + USBOTG_FS_TypeDef *USBFSD = USBOTG_FS; static struct ep_id endpoint_pool[] = { {0x0, USB_EP_ATTR_CONTROL, USB_DIR_INOUT, 64, ID_ASSIGNED }, - {0x1, USB_EP_ATTR_BULK, USB_DIR_IN, 512, ID_UNASSIGNED}, - {0x1, USB_EP_ATTR_BULK, USB_DIR_OUT, 512, ID_UNASSIGNED}, - {0x2, USB_EP_ATTR_INT, USB_DIR_IN, 512, ID_UNASSIGNED}, - {0x2, USB_EP_ATTR_INT, USB_DIR_OUT, 512, ID_UNASSIGNED}, - {0x3, USB_EP_ATTR_ISOC, USB_DIR_IN, 512, ID_UNASSIGNED}, - {0x3, USB_EP_ATTR_ISOC, USB_DIR_OUT, 512, ID_UNASSIGNED}, + /* IN and OUT of the same index share one DMA address, so they use different endpoints. */ + {0x1, USB_EP_ATTR_BULK, USB_DIR_IN, 64, ID_UNASSIGNED}, + {0x3, USB_EP_ATTR_BULK, USB_DIR_OUT, 64, ID_UNASSIGNED}, + {0x2, USB_EP_ATTR_INT, USB_DIR_IN, 64, ID_UNASSIGNED}, {0xFF, USB_EP_ATTR_TYPE_MASK, USB_DIR_MASK, 0, ID_ASSIGNED }, }; @@ -99,13 +115,13 @@ uint8_t _uep_rx_en(uint8_t ep_idx) { switch(ep_idx) { - case 1: return USBFS_UEP1_TX_EN; - case 4: return USBFS_UEP4_TX_EN; - case 2: return USBFS_UEP2_TX_EN; - case 3: return USBFS_UEP3_TX_EN; - case 5: return USBFS_UEP5_TX_EN; - case 6: return USBFS_UEP6_TX_EN; - case 7: return USBFS_UEP7_TX_EN; + case 1: return USBFS_UEP1_RX_EN; + case 4: return USBFS_UEP4_RX_EN; + case 2: return USBFS_UEP2_RX_EN; + case 3: return USBFS_UEP3_RX_EN; + case 5: return USBFS_UEP5_RX_EN; + case 6: return USBFS_UEP6_RX_EN; + case 7: return USBFS_UEP7_RX_EN; default: return 0; } } @@ -114,7 +130,9 @@ rt_err_t usbd_set_address(rt_uint8_t address) { if(address > 0x7f) return -RT_ERROR; - USBFSD->DEV_ADDR = (USBFSD->DEV_ADDR & USBFS_UDA_GP_BIT) | address; + /* Status IN is still at address 0. Apply the new address after that IN. */ + usb_addr_next = address; + usb_addr_pending = 1; return RT_EOK; } @@ -196,15 +214,23 @@ rt_size_t usbd_ep_read_prepare(rt_uint8_t address, void *buffer, rt_size_t size) if (_is_dir_in(address)) return 0; - if (size > (ep_idx ? UEP_MPS_512 : UEP_MPS_64)) - size = (ep_idx ? UEP_MPS_512 : UEP_MPS_64); + /* SRAM buffers and the FS packet size are both 64 bytes. */ + if (size > UEP_MPS_64) + size = UEP_MPS_64; + if (ep_idx == 0 && buffer == RT_NULL) + buffer = ep0_buf; _set_dma(ep_idx, (uint32_t)buffer); if (ep_idx == 0) - if(size == 0) _set_rx_ctrl(0, USBFS_UEP_R_RES_ACK | USBFS_UEP_R_TOG); - else _set_rx_ctrl(ep_idx, USBFS_UEP_R_RES_ACK); - else _set_rx_ctrl(0, (_get_rx_ctrl(ep_idx) & ~USBFS_UEP_R_RES_MASK) | USBFS_UEP_R_RES_ACK | USBFS_UEP_R_TOG); + { + if (size == 0) + _set_rx_ctrl(0, USBFS_UEP_R_RES_ACK | USBFS_UEP_R_TOG); + else + _set_rx_ctrl(0, (_get_rx_ctrl(0) & ~USBFS_UEP_R_RES_MASK) | USBFS_UEP_R_RES_ACK); + } + else + _set_rx_ctrl(ep_idx, (_get_rx_ctrl(ep_idx) & ~USBFS_UEP_R_RES_MASK) | USBFS_UEP_R_RES_ACK); return size; } @@ -213,16 +239,16 @@ rt_size_t usbd_ep_read(rt_uint8_t address, void *buffer) { uint8_t ep_idx = _get_ep_idx(address); - if (_is_dir_out(address)) - return -2; - if ((uint32_t)buffer & 0x03) - return -3; + if (_is_dir_in(address)) + return 0; - uint32_t dmabuf = _get_dma(ep_idx); - rt_size_t size = USBFSD->RX_LEN; + uint8_t *src = usb_dma_ram(_get_dma(ep_idx)); + rt_size_t size = USBFSD->RX_LEN & 0xFF; - if (size > 0 && (uint32_t)buffer != dmabuf) - rt_memcpy(buffer, (void *)dmabuf, size); + if (size > 64) + size = 64; + if (size > 0 && buffer != RT_NULL && (uint8_t *)buffer != src) + rt_memcpy(buffer, src, size); return size; } @@ -231,27 +257,28 @@ rt_size_t usbd_ep_write(rt_uint8_t address, void *buffer, rt_size_t size) { uint8_t ep_idx = _get_ep_idx(address); - if (_is_dir_in(address)) - return -2; - if ((uint32_t)buffer & 0x03) - return -3; - - uint32_t dmabuf = _get_dma(ep_idx); + if (_is_dir_out(address)) + return 0; - if (size > (ep_idx ? UEP_MPS_512 : UEP_MPS_64)) - size = (ep_idx ? UEP_MPS_512 : UEP_MPS_64); + if (size > UEP_MPS_64) + size = UEP_MPS_64; _set_tx_len(ep_idx, size); if(ep_idx == 0) { - if(size != 0) - _set_dma(0, (uint32_t)buffer); - _set_tx_ctrl(0, USBFS_UEP_T_TOG | USBFS_UEP_T_RES_ACK); + if(size != 0 && buffer != RT_NULL && buffer != ep0_buf) + rt_memcpy(ep0_buf, buffer, size); + _set_dma(0, (uint32_t)ep0_buf); + _set_tx_ctrl(0, (_get_tx_ctrl(0) & ~USBFS_UEP_T_RES_MASK) | USBFS_UEP_T_RES_ACK); } else { - if(size != 0) - rt_memcpy((void *)dmabuf, buffer, size); + if (size > 64) + size = 64; + if (size != 0 && buffer != RT_NULL) + rt_memcpy(epn_buf[ep_idx], buffer, size); + _set_dma(ep_idx, (uint32_t)epn_buf[ep_idx]); + _set_tx_len(ep_idx, size); _set_tx_ctrl(ep_idx, (_get_tx_ctrl(ep_idx) & ~USBFS_UEP_T_RES_MASK) | USBFS_UEP_T_RES_ACK); } @@ -262,7 +289,7 @@ rt_err_t usbd_ep0_send_status(void) { _set_tx_len(0, 0); _set_tx_ctrl(0, USBFS_UEP_T_RES_ACK | USBFS_UEP_T_TOG); - _set_dma(0, 0); + _set_dma(0, (uint32_t)ep0_buf); return RT_EOK; } @@ -296,15 +323,18 @@ rt_err_t dcd_init(rt_device_t dev) { USBFSD->BASE_CTRL = 0x00; - USBFSD->UEP4_1_MOD = USBFS_UEP4_RX_EN | USBFS_UEP4_TX_EN | USBFS_UEP1_RX_EN | USBFS_UEP1_TX_EN; - USBFSD->UEP2_3_MOD = USBFS_UEP2_RX_EN | USBFS_UEP2_TX_EN | USBFS_UEP3_RX_EN | USBFS_UEP3_TX_EN; - USBFSD->UEP5_6_MOD = USBFS_UEP5_RX_EN | USBFS_UEP5_TX_EN | USBFS_UEP6_RX_EN | USBFS_UEP6_TX_EN; - USBFSD->UEP7_MOD = USBFS_UEP7_RX_EN | USBFS_UEP7_TX_EN; + /* If both TX and RX are enabled, this chip sends IN data from buffer+64. */ + USBFSD->UEP4_1_MOD = 0; + USBFSD->UEP2_3_MOD = 0; + USBFSD->UEP5_6_MOD = 0; + USBFSD->UEP7_MOD = 0; USBFSD->INT_FG = 0xFF; USBFSD->INT_EN = USBFS_UIE_SUSPEND | USBFS_UIE_BUS_RST | USBFS_UIE_TRANSFER; USBFSD->DEV_ADDR = 0x00; + _set_dma(0, (uint32_t)ep0_buf); + USBFSD->UEP0_RX_CTRL = USBFS_UEP_R_RES_ACK; USBFSD->BASE_CTRL = USBFS_UC_DEV_PU_EN | USBFS_UC_INT_BUSY | USBFS_UC_DMA_EN; USBFSD->UDEV_CTRL = USBFS_UD_PD_DIS | USBFS_UD_PORT_EN; @@ -316,6 +346,7 @@ rt_err_t dcd_init(rt_device_t dev) void USBD_IRQHandler(void) __attribute__((interrupt())); void USBD_IRQHandler() { + GET_INT_SP(); rt_interrupt_enter(); uint8_t int_fg = USBFSD->INT_FG; @@ -324,14 +355,25 @@ void USBD_IRQHandler() uint8_t tog; switch (USBFSD->INT_ST & USBFS_UIS_TOKEN_MASK) { case USBFS_UIS_TOKEN_SETUP: - _set_rx_ctrl(ep_idx, USBFS_UEP_R_RES_NAK); + { + struct urequest setup; + rt_memcpy(&setup, ep0_buf, sizeof(setup)); + USBFSD->UEP0_TX_CTRL = USBFS_UEP_T_TOG | USBFS_UEP_T_RES_NAK; + USBFSD->UEP0_RX_CTRL = USBFS_UEP_R_TOG | USBFS_UEP_R_RES_NAK; + rt_usbd_ep0_setup_handler(&udcd, &setup); break; + } case USBFS_UIS_TOKEN_IN: if (ep_idx == 0x00) { tog = _get_tx_ctrl(ep_idx) & USBFS_UEP_T_TOG; _set_tx_ctrl(ep_idx, (_get_tx_ctrl(ep_idx) & 0b11111000) | ~tog | USBFS_UEP_T_RES_NAK); + if (usb_addr_pending) + { + USBFSD->DEV_ADDR = (USBFSD->DEV_ADDR & USBFS_UDA_GP_BIT) | usb_addr_next; + usb_addr_pending = 0; + } if (_get_dma(ep_idx) != 0) { rt_usbd_ep0_in_handler(&udcd); @@ -355,6 +397,7 @@ void USBD_IRQHandler() { _set_rx_ctrl(ep_idx, (_get_rx_ctrl(ep_idx) & ~USBFS_UEP_R_RES_MASK) | USBFS_UEP_R_RES_NAK); } + rt_usbd_ep0_out_handler(&udcd, USBFSD->RX_LEN & 0xFF); } else { @@ -371,6 +414,8 @@ void USBD_IRQHandler() USBFSD->INT_FG = USBFS_UIF_TRANSFER; } else if (int_fg & USBFS_UIF_BUS_RST) { + usb_addr_pending = 0; + USBFSD->DEV_ADDR = 0; USBFSD->UEP0_TX_LEN = 0; USBFSD->UEP0_TX_CTRL = USBFS_UEP_T_RES_NAK; USBFSD->UEP0_RX_CTRL = USBFS_UEP_R_RES_NAK; @@ -381,6 +426,7 @@ void USBD_IRQHandler() _set_rx_ctrl(i, USBFS_UEP_R_RES_NAK | USBFS_UEP_R_AUTO_TOG); } + _set_dma(0, (uint32_t)ep0_buf); _set_rx_ctrl(0, USBFS_UEP_R_RES_ACK); rt_usbd_reset_handler(&udcd); @@ -392,13 +438,14 @@ void USBD_IRQHandler() } rt_interrupt_leave(); + FREE_INT_SP(); } int rt_hw_usbd_init() { rt_err_t res = -RT_ERROR; - rt_memset((void *)&udcd, 0, sizeof(struct uhcd)); + rt_memset((void *)&udcd, 0, sizeof(udcd)); udcd.parent.type = RT_Device_Class_USBDevice; udcd.parent.user_data = (void *)USBFS_BASE; udcd.parent.init = dcd_init; diff --git a/tools/ci/bsp_detail.yml b/tools/ci/bsp_detail.yml index 815f47d87b57..ddda1b5b4e51 100644 --- a/tools/ci/bsp_detail.yml +++ b/tools/ci/bsp_detail.yml @@ -2568,6 +2568,12 @@ wch/risc-v/ch32v103r-evt: gcc: riscv-none-embed-gcc menuconfig: true rtconfig.h: true +wch/risc-v/ch32v203c-evt-r0: + .config: true + README.md: true + gcc: riscv-none-embed-gcc + menuconfig: true + rtconfig.h: true wch/risc-v/ch32v208w-r0: .config: true gcc: riscv-none-embed-gcc diff --git a/tools/ci/toolchain_bsp.yml b/tools/ci/toolchain_bsp.yml index 4b2e1e69beea..4fe4ac12aac7 100644 --- a/tools/ci/toolchain_bsp.yml +++ b/tools/ci/toolchain_bsp.yml @@ -372,11 +372,12 @@ riscv-none-embed-gcc: - k210 - rv32m1_vega/ri5cy - wch/risc-v/ch32v103r-evt + - wch/risc-v/ch32v203c-evt-r0 - wch/risc-v/ch32v208w-r0 - wch/risc-v/ch32v307v-r1 - wch/risc-v/ch569w-evt - wch/risc-v/yd-ch32v307vct6 - count: 11 + count: 12 download_url: https://github.com/RT-Thread/toolchains-ci/releases/download/v1.5/xpack-riscv-none-embed-gcc-8.3.0-2.3-linux-x64.tar.gz riscv-nuclei-elf-gcc: bsp: From 91f7276889c13bacf803c2cd2b759e18b82d9fd7 Mon Sep 17 00:00:00 2001 From: seteiro <276597748+cms19859230182-lang@users.noreply.github.com> Date: Wed, 23 Sep 2026 09:36:52 +0800 Subject: [PATCH 2/4] [bsp][ch32v203] drop peripherals this C8 part does not have CH32V203C8 is D6, so the menu no longer offers DAC, SPI3, CAN2, or TIM5-TIM10. Software SPI2 was pointing at GPIOE pins this package does not have. The watchdog command now rejects a timeout that is not a whole number of seconds inside the counter range. --- bsp/wch/risc-v/ch32v203c-evt-r0/.config | 1 - bsp/wch/risc-v/ch32v203c-evt-r0/README.md | 2 +- bsp/wch/risc-v/ch32v203c-evt-r0/SConstruct | 2 +- .../ch32v203c-evt-r0/applications/wdt_msh.c | 40 ++- bsp/wch/risc-v/ch32v203c-evt-r0/board/Kconfig | 246 +----------------- 5 files changed, 41 insertions(+), 250 deletions(-) diff --git a/bsp/wch/risc-v/ch32v203c-evt-r0/.config b/bsp/wch/risc-v/ch32v203c-evt-r0/.config index dc0ba7def6d3..70fc11940081 100644 --- a/bsp/wch/risc-v/ch32v203c-evt-r0/.config +++ b/bsp/wch/risc-v/ch32v203c-evt-r0/.config @@ -395,7 +395,6 @@ CONFIG_BSP_USING_UART1=y # CONFIG_BSP_USING_UART3 is not set # CONFIG_BSP_USING_UART4 is not set # CONFIG_BSP_USING_ADC is not set -# CONFIG_BSP_USING_DAC is not set # CONFIG_BSP_USING_SOFT_I2C is not set # CONFIG_BSP_USING_SPI is not set # CONFIG_BSP_USING_RTC is not set diff --git a/bsp/wch/risc-v/ch32v203c-evt-r0/README.md b/bsp/wch/risc-v/ch32v203c-evt-r0/README.md index 0c0ef910c014..33f24c7ceb50 100644 --- a/bsp/wch/risc-v/ch32v203c-evt-r0/README.md +++ b/bsp/wch/risc-v/ch32v203c-evt-r0/README.md @@ -38,7 +38,7 @@ CH32V203C8T6-EVT-R0 是 WCH 沁恒的 RISC-V 评估板。芯片是 QingKe **V4B 1. 安装 [WCH RISC-V GCC](https://github.com/NanjingQinheng/sdk-toolchain-RISC-V-GCC-WCH) 与 [Env](https://github.com/RT-Thread/env-windows/releases) 2. 进入本目录,设置 `RTT_EXEC_PATH` 为工具链 `bin` -3. `pkgs --update` 拉取 `CH32V20x_SDK`(或按 `package.json` clone `kaidegit/CH32V20x-SDK-for-RTT` 到 `packages/`) +3. clone [CH32V20x-SDK-for-RTT](https://github.com/kaidegit/CH32V20x-SDK-for-RTT) 到 `packages/CH32V20x-SDK-for-RTT` 4. `scons -j4`,生成 **rtthread.bin** ## 3 硬件连接与下载 diff --git a/bsp/wch/risc-v/ch32v203c-evt-r0/SConstruct b/bsp/wch/risc-v/ch32v203c-evt-r0/SConstruct index b17bcc0d5af7..43f400b9bf56 100644 --- a/bsp/wch/risc-v/ch32v203c-evt-r0/SConstruct +++ b/bsp/wch/risc-v/ch32v203c-evt-r0/SConstruct @@ -12,7 +12,7 @@ sys.path = sys.path + [os.path.join(RTT_ROOT, 'tools')] try: from building import * except: - print('Cannot found RT-Thread root directory, please check RTT_ROOT') + print('Cannot find RT-Thread root directory, please check RTT_ROOT') print(RTT_ROOT) exit(-1) diff --git a/bsp/wch/risc-v/ch32v203c-evt-r0/applications/wdt_msh.c b/bsp/wch/risc-v/ch32v203c-evt-r0/applications/wdt_msh.c index f11556f86ef7..875a0d0a7bf2 100644 --- a/bsp/wch/risc-v/ch32v203c-evt-r0/applications/wdt_msh.c +++ b/bsp/wch/risc-v/ch32v203c-evt-r0/applications/wdt_msh.c @@ -14,6 +14,38 @@ #ifdef BSP_USING_IWDT +static int wdt_seconds(const char *text, rt_uint32_t *seconds) +{ + const char *p; + char *end; + unsigned long value; + unsigned long max_seconds; + + if (text == RT_NULL || text[0] == '\0') + { + return -RT_ERROR; + } + for (p = text; *p != '\0'; p++) + { + if (*p < '0' || *p > '9') + { + return -RT_ERROR; + } + } + value = strtoul(text, &end, 10); + if (end == text || *end != '\0') + { + return -RT_ERROR; + } + max_seconds = (0xFFFUL * 256UL) / LSI_VALUE; + if (value == 0 || value > max_seconds) + { + return -RT_ERROR; + } + *seconds = (rt_uint32_t)value; + return RT_EOK; +} + static int wdt(int argc, char **argv) { rt_device_t dev; @@ -37,10 +69,14 @@ static int wdt(int argc, char **argv) { if (argc < 3) { - rt_kprintf("wdt start \n"); + rt_kprintf("wdt start <1-%lu seconds>\n", (0xFFFUL * 256UL) / LSI_VALUE); + return -RT_ERROR; + } + if (wdt_seconds(argv[2], &timeout) != RT_EOK) + { + rt_kprintf("wdt start <1-%lu seconds>\n", (0xFFFUL * 256UL) / LSI_VALUE); return -RT_ERROR; } - timeout = atoi(argv[2]); err = rt_device_init(dev); if (err != RT_EOK) { diff --git a/bsp/wch/risc-v/ch32v203c-evt-r0/board/Kconfig b/bsp/wch/risc-v/ch32v203c-evt-r0/board/Kconfig index e50efed34f0d..90323e6b9983 100644 --- a/bsp/wch/risc-v/ch32v203c-evt-r0/board/Kconfig +++ b/bsp/wch/risc-v/ch32v203c-evt-r0/board/Kconfig @@ -60,24 +60,10 @@ menu "On-chip Peripheral Drivers" default n config ADC_CHANNEL_17 - bool "Enable ADC CHANNEL 17 (inside Verf)" + bool "Enable ADC CHANNEL 17 (inside Vref)" default n endif - menuconfig BSP_USING_DAC - bool "Enable DAC" - select RT_USING_DAC - default n - - if BSP_USING_DAC - config BSP_USING_DAC_CHANNEL1 - bool "Enable DAC CHANNEL1" - default n - config BSP_USING_DAC_CHANNEL2 - bool "Enable DAC CHANNEL2" - default n - endif - menuconfig BSP_USING_SOFT_I2C bool "Enable software I2C (swi2c)" default n @@ -123,16 +109,6 @@ menu "On-chip Peripheral Drivers" bool "Enable SPI2" default n - config BSP_USING_SPI3 - bool "Enable SPI3" - default n - - if BSP_USING_SPI3 - config BSP_USING_SPI_FLASH - bool "Enable SPI Flash" - default n - endif - menuconfig BSP_USING_SOFT_SPI1 bool "Enable software SPI1 Bus (swspi1)" default n @@ -150,23 +126,6 @@ menu "On-chip Peripheral Drivers" default 24 endif - menuconfig BSP_USING_SOFT_SPI2 - bool "Enable software SPI2 Bus (swspi2)" - default n - select RT_USING_SOFT_SPI - select RT_USING_SOFT_SPI2 - if BSP_USING_SOFT_SPI2 - config RT_SOFT_SPI2_SCK_PIN - int "swspi2 SCK pin number" - default 64 - config RT_SOFT_SPI2_MISO_PIN - int "swspi2 MISO pin number" - default 66 - config RT_SOFT_SPI2_MOSI_PIN - int "swspi2 MOSI pin number" - default 65 - endif - endif config RT_SOFT_SPI1_HAS_PIN_DEFAULT @@ -193,30 +152,6 @@ menu "On-chip Peripheral Drivers" string default "swspi1" if RT_USING_SOFT_SPI1 - config RT_SOFT_SPI2_HAS_PIN_DEFAULT - bool - default y if RT_USING_SOFT_SPI2 - - config RT_SOFT_SPI2_SCK_PIN_DEFAULT - int - default 64 if RT_USING_SOFT_SPI2 - - config RT_SOFT_SPI2_MISO_PIN_DEFAULT - int - default 66 if RT_USING_SOFT_SPI2 - - config RT_SOFT_SPI2_MOSI_PIN_DEFAULT - int - default 65 if RT_USING_SOFT_SPI2 - - config RT_SOFT_SPI2_HAS_BUS_NAME_DEFAULT - bool - default y if RT_USING_SOFT_SPI2 - - config RT_SOFT_SPI2_BUS_NAME_DEFAULT - string - default "swspi2" if RT_USING_SOFT_SPI2 - config BSP_USING_RTC bool "Enable RTC" select RT_USING_RTC @@ -256,9 +191,6 @@ menu "On-chip Peripheral Drivers" config BSP_USING_CAN1 bool "Using CAN1" default n - config BSP_USING_CAN2 - bool "Using CAN2" - default n endif config BSP_USING_TIM @@ -420,182 +352,6 @@ menu "On-chip Peripheral Drivers" endif - config BSP_USING_TIM5 - bool "Using TIM5" - default n - - if BSP_USING_TIM5 - choice BSP_TIM5_SEL - prompt "Using TIM5 as clock_timer or PWM mode" - default BSP_USING_TIM5_CLOCK_TIMER - - config BSP_USING_TIM5_CLOCK_TIMER - bool "Using TIM5 as clock_timer mode" - select BSP_USING_CLOCK_TIMER - - config BSP_USING_TIM5_PWM - bool "Using TIM5 as PWM mode" - select BSP_USING_PWM - endchoice - - if BSP_USING_TIM5_PWM - config BSP_USING_TIM5_PWM_CH1 - bool "Using TIM5 channel 1" - default n - - config BSP_USING_TIM5_PWM_CH2 - bool "Using TIM5 channel 2" - default n - - config BSP_USING_TIM5_PWM_CH3 - bool "Using TIM5 channel 3" - - config BSP_USING_TIM5_PWM_CH4 - bool "Using TIM5 channel 4" - endif - - endif - - config BSP_USING_TIM6 - bool "Using TIM6" - default n - - if BSP_USING_TIM6 - choice TIM5_CLK_TMR_PWM_MO_SEL - prompt "Using TIM6 as clock_timer (PWM mode not supported)" - default BSP_USING_TIM6_CLOCK_TIMER - - config BSP_USING_TIM6_CLOCK_TIMER - bool "Using TIM6 as clock_timer mode" - select BSP_USING_CLOCK_TIMER - endchoice - - endif - - config BSP_USING_TIM7 - bool "Using TIM7" - default n - - if BSP_USING_TIM7 - choice TIM7_CLK_TMR_PWM_MO_SEL - prompt "Using TIM7 as clock_timer (PWM mode not supported)" - default BSP_USING_TIM7_CLOCK_TIMER - - config BSP_USING_TIM7_CLOCK_TIMER - bool "Using TIM7 as clock_timer mode" - select BSP_USING_CLOCK_TIMER - endchoice - - endif - - config BSP_USING_TIM8 - bool "Using TIM8" - default n - - if BSP_USING_TIM8 - choice BSP_TIM8_SEL - prompt "Using TIM8 as clock_timer or PWM mode" - default BSP_USING_TIM8_CLOCK_TIMER - - config BSP_USING_TIM8_CLOCK_TIMER - bool "Using TIM8 as clock_timer mode" - select BSP_USING_CLOCK_TIMER - - config BSP_USING_TIM8_PWM - bool "Using TIM8 as PWM mode" - select BSP_USING_PWM - endchoice - - if BSP_USING_TIM8_PWM - config BSP_USING_TIM8_PWM_CH1 - bool "Using TIM8 channel 1" - default n - - config BSP_USING_TIM8_PWM_CH2 - bool "Using TIM8 channel 2" - default n - - config BSP_USING_TIM8_PWM_CH3 - bool "Using TIM8 channel 3" - - config BSP_USING_TIM8_PWM_CH4 - bool "Using TIM8 channel 4" - endif - - endif - - config BSP_USING_TIM9 - bool "Using TIM9" - default n - - if BSP_USING_TIM9 - choice BSP_TIM9_SEL - prompt "Using TIM9 as clock_timer or PWM mode" - default BSP_USING_TIM9_CLOCK_TIMER - - config BSP_USING_TIM9_CLOCK_TIMER - bool "Using TIM9 as clock_timer mode" - select BSP_USING_CLOCK_TIMER - - config BSP_USING_TIM9_PWM - bool "Using TIM9 as PWM mode" - select BSP_USING_PWM - endchoice - - if BSP_USING_TIM9_PWM - config BSP_USING_TIM9_PWM_CH1 - bool "Using TIM9 channel 1" - default n - - config BSP_USING_TIM9_PWM_CH2 - bool "Using TIM9 channel 2" - default n - - config BSP_USING_TIM9_PWM_CH3 - bool "Using TIM9 channel 3" - - config BSP_USING_TIM9_PWM_CH4 - bool "Using TIM9 channel 4" - endif - - endif - - config BSP_USING_TIM10 - bool "Using TIM10" - default n - - if BSP_USING_TIM10 - choice BSP_TIM10_SEL - prompt "Using TIM10 as clock_timer or PWM mode" - default BSP_USING_TIM10_CLOCK_TIMER - - config BSP_USING_TIM10_CLOCK_TIMER - bool "Using TIM10 as clock_timer mode" - select BSP_USING_CLOCK_TIMER - - config BSP_USING_TIM10_PWM - bool "Using TIM10 as PWM mode" - select BSP_USING_PWM - endchoice - - if BSP_USING_TIM10_PWM - config BSP_USING_TIM10_PWM_CH1 - bool "Using TIM10 channel 1" - default n - - config BSP_USING_TIM10_PWM_CH2 - bool "Using TIM10 channel 2" - default n - - config BSP_USING_TIM10_PWM_CH3 - bool "Using TIM10 channel 3" - - config BSP_USING_TIM10_PWM_CH4 - bool "Using TIM10 channel 4" - endif - - endif - endif endmenu From 36acaa7b1a9bf5195d33f5158cd1a9b9f070f4c4 Mon Sep 17 00:00:00 2001 From: seteiro <276597748+cms19859230182-lang@users.noreply.github.com> Date: Wed, 23 Sep 2026 13:43:43 +0800 Subject: [PATCH 3/4] [bsp][ch32v203] shorten the board readme Match the CH32V307 Chinese readme outline and drop the measured peripheral logs. --- bsp/wch/risc-v/ch32v203c-evt-r0/README.md | 109 +++++----------------- 1 file changed, 23 insertions(+), 86 deletions(-) diff --git a/bsp/wch/risc-v/ch32v203c-evt-r0/README.md b/bsp/wch/risc-v/ch32v203c-evt-r0/README.md index 33f24c7ceb50..b10e55d567be 100644 --- a/bsp/wch/risc-v/ch32v203c-evt-r0/README.md +++ b/bsp/wch/risc-v/ch32v203c-evt-r0/README.md @@ -1,114 +1,51 @@ # ch32v203c-evt-r0 BSP 说明 -**中文** - ## 1 开发板简介 -CH32V203C8T6-EVT-R0 是 WCH 沁恒的 RISC-V 评估板。芯片是 QingKe **V4B(CH32V20x_D6)**,手册零等待 Flash **64KB**、SRAM **20KB**。LinkUtility 读到的 224KB 是 V203 系列总 CodeFlash,**不要**写进链接脚本。 +CH32V203C8T6-EVT-R0 是 WCH 推出的一款基于 RISC-V 内核的开发板,最高主频为 144MHz。 **基本特性:** -- MCU:CH32V203C8T6,最高 144MHz +- MCU:CH32V203C8T6,主频 144MHz,Flash 64KB,SRAM 20KB - 封装:LQFP48 -- 板载用户灯默认**没接到 GPIO**,要杜邦线才闪 -- **无板载 WCH-Link**,需外接 WCH-LinkE - -资料:[CH32V203](https://www.wch.cn/products/CH32V203.html)、[openwch/ch32v20x](https://github.com/openwch/ch32v20x) - -本 BSP 骨架对齐主仓 `ch32v208w-r0`(同一套 `CH32V20x` SDK、仓内 `ch32_drivers`),堆和 64K/20K 按手册与 `ch32v307v-r1` 的 `HEAP_BEGIN`/`HEAP_END`。USART1 默认 **PA9 TX / PA10 RX**。 +- LED:板载灯默认没有接到引脚,使用时要自己接杜邦线 +- USB:1 个 Type-C +- 板上无 WCH-Link,需外接 -官方软件包 `CH32V20x-SDK-for-RTT` 只带 D8W 启动文件,D6 会 `Exit()`。本 BSP 在 `board/startup_ch32v20x_D6.S` 使用沁恒 EVT 的 D6 向量表,复位后跳到 RT-Thread `entry`(与该包 D8W 的 rtt-patch 相同)。`SConstruct` 会去掉包里对 D6 的 `Exit()`。 +更多信息请访问 [CH32V203](https://www.wch.cn/products/CH32V203.html) 以及 [openwch/ch32v20x](https://github.com/openwch/ch32v20x) ## 2 编译说明 +板级包支持 RISC-V GCC 开发环境,以下是具体版本信息: + | IDE/编译器 | 已测试版本 | | ---------- | -------------------- | | GCC | WCH RISC-V GCC 8.2.0 | -默认配置只打开 GPIO 和 UART1,给 64KB 留余量。PWM、ADC、RTC、看门狗、USB 都在 menuconfig 里,默认关着。64KB 放不下 USB 和 PWM、ADC、RTC、看门狗同时打开。 - -已在这块板上分开测过: - -- 打开 TIM1 通道 1(PA8)、ADC1、RTC(LSE)和独立看门狗,并关掉命令帮助文字。本机那次 Flash **64892** 字节,**99.02%**。 -- 只开 USB CDC,关掉上面四项。USB 线程栈用 **1024**(菜单默认 4096,20KB SRAM 不合适)。扁口插电脑、Type-C 插板子 P7 后,电脑串口是 COM12,`help` 和 `version` 有回应。 - -`pwm` 命令依赖 Finsh 的选项补全。 - -### 2.1 使用 Env 编译 - -1. 安装 [WCH RISC-V GCC](https://github.com/NanjingQinheng/sdk-toolchain-RISC-V-GCC-WCH) 与 [Env](https://github.com/RT-Thread/env-windows/releases) -2. 进入本目录,设置 `RTT_EXEC_PATH` 为工具链 `bin` -3. clone [CH32V20x-SDK-for-RTT](https://github.com/kaidegit/CH32V20x-SDK-for-RTT) 到 `packages/CH32V20x-SDK-for-RTT` -4. `scons -j4`,生成 **rtthread.bin** - -## 3 硬件连接与下载 - -### 3.1 SWD(已用于认出芯片) - -独立 WCH-LinkE: +## 3 使用说明 -- 3V3 — 3V3 -- GND — GND -- SWDIO — PA13 -- SWCLK — PA14 +> 本章节是为刚接触 RT-Thread 的新手准备的使用说明,遵循简单的步骤即可将 RT-Thread 操作系统运行在该开发板上,看到实验效果。 -不要把 LinkE 的 5V USB 和板子供电叠在一起。 +### 3.1 使用 Env 编译 BSP -### 3.2 USART1(msh) +1. [下载 WCH 编译工具链](https://github.com/NanjingQinheng/sdk-toolchain-RISC-V-GCC-WCH) +2. 下载 Env 工具 [最新版本](https://github.com/RT-Thread/env-windows/releases) +3. 将 [CH32V20x-SDK-for-RTT](https://github.com/kaidegit/CH32V20x-SDK-for-RTT) clone 到 `packages/CH32V20x-SDK-for-RTT` +4. 在当前 BSP 目录下执行 `scons --exec-path=工具链的bin目录` +5. 编译完成之后会生成 **rtthread.bin** 文件。默认只打开 GPIO 和 UART1。 -SWD 那四根(3V3 / GND / PA13 / PA14)不够出串口。LinkE 排针上另外有丝印 **TX** / **RX**(WCH-Link 手册图一),接到板上 **P1** 排针的 PA9 / PA10(沁恒 EVT 原理图 `CH32V203C8T6-R0`)。交叉: +### 3.2 硬件连接 -- LinkE **TX** → 板 **PA10**(USART1_RX) -- LinkE **RX** → 板 **PA9**(USART1_TX) -- GND 已共地就不用再加 +使用杜邦线连接 WCH-LinkE:3V3–3V3,GND–GND,SWDIO–PA13,SWCLK–PA14。不要用 LinkE 的 5V 给板子供电。 -本机 LinkE 虚拟串口是 **COM11**,115200-8-1-N。 +串口另外交叉连接:LinkE 的 TX 接板子 PA10,RX 接板子 PA9。 ### 3.3 下载 -WCH-LinkUtility:Series **CH32V20X**。固件按手册 **64K Flash + 20K SRAM** 链接。默认镜像只含 GPIO 和 UART1,本机 `scons` 为 Flash **44480** 字节,**67.87%**。 - -V20X 的 Chip Mem 下拉没有 64K+20K(常见是 128K+64K 等),**不要点 Set** 改 option bytes。不要用 307 的 224K+96K。Target → Program(F10),不要勾 Erase All。界面读到 Flash Size 224KB 是系列总 CodeFlash,不是这份 bin 的大小。 - -复位后 COM11 应出现 RT-Thread / `msh >`。`help`、`ps`、`free` 有输出即启动成功。 - -### 3.4 已核对的外设 - -TIM1 通道 1 在 **PA8**,不占用 USART1 和 SWD: - -``` -pwm probe pwm1 -pwm set 1 1000000 500000 -pwm enable 1 -pwm get 1 -``` - -读回 period `1000000` ns、pulse `500000` ns,即 1 kHz、50%。 - -ADC1 内部通道要在本板 `board.c` 里打开 `ADC_TempSensorVrefintCmd`。通道 17(Vref)连续读到 `0x5C9`、`0x5C9`、`0x5CA`、`0x5C9`。通道 16(温度)换通道后的第一次会带上一路的值,随后三次都是 `0x6C4`。 - -``` -adc probe adc1 -adc enable 17 -adc read 17 -adc enable 16 -adc read 16 -``` - -RTC 用 LSE,不要选 LSI。默认镜像没开 RTC,要在 menuconfig 里打开。设置后几秒再读,时间应往前走: - -``` -date -date 2026 9 22 12 40 0 -date -``` - -设置后约 5 秒再读,时间从 `12:40:00` 走到 `12:40:05`。 - -独立看门狗设备名是 `wdt`。`wdt start 5` 之后 `wdt feed`,`msh` 还在;停止喂狗后约 5 秒串口重新打出 RT-Thread 横幅。看门狗一旦启动,复位后如果没有再喂,会按同一超时再次复位。要停掉就重新下载这份默认镜像。V2 的 `drv_iwdt.c` 必须包含 `ch32v20x_iwdg.h`,不能用 V3 的头文件。 +打开 WCH-LinkUtility,Series 选择 CH32V20X,选择刚刚生成的 **rtthread.bin** 进行下载。不要勾选 Erase All。 -## 4 外设表 +> 注意:Chip Mem 不要点 Set。本板按手册是 64K Flash + 20K SRAM,不要设成 224K ROM + 96K RAM。界面上的 Flash Size 224KB 是 V203 系列的总容量。 -`bsp/README.md` 里本板勾了 GPIO、UART、ADC、RTC、PWM、WDT、USBD。这些勾选表示驱动在、而且板上见过结果,不是默认镜像全开。SPI、I2C、CAN、DAC、USBH 仍不勾。外部 ADC 通道 0 是 PA0。接到板子自己的 3V3,连续四次都是 `0xFFF`。改接到 GND,四次是 `0x4`、`0x4`、`0x5`、`0x5`。 +### 3.4 运行结果 -USB 设备走板子下边的 Type-C(丝印 P7,PA11/PA12)。扁口插电脑,Type-C 插这块板。打开 USB、关掉 PWM、ADC、RTC 和看门狗之后,电脑多出一个串口,这边是 COM12,厂商号 `0FFE`,产品号 `0001`。把控制台切到 `vcom` 之后,在 COM12 上敲 `help` 能收回命令列表,`version` 打出 RT-Thread 5.3.1。PA8 的 PWM 只核对了寄存器读回,没有示波器波形。 +在终端工具里打开 WCH-Link 的串口(115200-8-1-N),复位设备后,可以看到 RT-Thread 的输出信息和 `msh >`。 From 0a3c6cb0a5f52de3ef24f96496df0baaa0e56a18 Mon Sep 17 00:00:00 2001 From: seteiro <276597748+cms19859230182-lang@users.noreply.github.com> Date: Wed, 23 Sep 2026 21:56:01 +0800 Subject: [PATCH 4/4] [bsp][ch32v203] test the watchdog with utest Replace the msh start/feed command with a utest case. The case stays out of the default image unless IWDT and the test switch are both on. This independent watchdog cannot be stopped after start, so the no-feed half is expected to reset. The link script keeps the utest case table. Signed-off-by: seteiro <276597748+cms19859230182-lang@users.noreply.github.com> --- .../applications/utest/SConscript | 10 ++ .../applications/utest/test_wdt.c | 89 +++++++++++++++ .../ch32v203c-evt-r0/applications/wdt_msh.c | 107 ------------------ bsp/wch/risc-v/ch32v203c-evt-r0/board/Kconfig | 8 ++ .../board/linker_scripts/link.lds | 7 ++ 5 files changed, 114 insertions(+), 107 deletions(-) create mode 100644 bsp/wch/risc-v/ch32v203c-evt-r0/applications/utest/SConscript create mode 100644 bsp/wch/risc-v/ch32v203c-evt-r0/applications/utest/test_wdt.c delete mode 100644 bsp/wch/risc-v/ch32v203c-evt-r0/applications/wdt_msh.c diff --git a/bsp/wch/risc-v/ch32v203c-evt-r0/applications/utest/SConscript b/bsp/wch/risc-v/ch32v203c-evt-r0/applications/utest/SConscript new file mode 100644 index 000000000000..c73574cc167c --- /dev/null +++ b/bsp/wch/risc-v/ch32v203c-evt-r0/applications/utest/SConscript @@ -0,0 +1,10 @@ +from building import * + +src = [] + +if GetDepend('BSP_USING_IWDT') and GetDepend('BSP_UTEST_IWDT'): + src += ['test_wdt.c'] + +group = DefineGroup('utestcases', src, depend = ['']) + +Return('group') diff --git a/bsp/wch/risc-v/ch32v203c-evt-r0/applications/utest/test_wdt.c b/bsp/wch/risc-v/ch32v203c-evt-r0/applications/utest/test_wdt.c new file mode 100644 index 000000000000..d5b70854e6cd --- /dev/null +++ b/bsp/wch/risc-v/ch32v203c-evt-r0/applications/utest/test_wdt.c @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2006-2026, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2026-09-23 seteiro CH32V203: independent watchdog utest + */ + +#include +#include +#include + +#define WDT_TIMEOUT_SECONDS 5 +#define WDT_FEED_WAIT_MS 8000 +#define WDT_NOFEED_WAIT_MS 8000 + +static rt_device_t wdg_dev; +static int feed; + +static void idle_hook(void) +{ + if (feed && wdg_dev != RT_NULL) + { + rt_device_control(wdg_dev, RT_DEVICE_CTRL_WDT_KEEPALIVE, RT_NULL); + } +} + +static void test_wdt(void) +{ + rt_uint32_t timeout = WDT_TIMEOUT_SECONDS; + rt_err_t err; + + wdg_dev = rt_device_find("wdt"); + uassert_not_null(wdg_dev); + if (wdg_dev == RT_NULL) + { + return; + } + + err = rt_device_init(wdg_dev); + uassert_int_equal(err, RT_EOK); + if (err != RT_EOK) + { + return; + } + + err = rt_device_control(wdg_dev, RT_DEVICE_CTRL_WDT_SET_TIMEOUT, &timeout); + uassert_int_equal(err, RT_EOK); + if (err != RT_EOK) + { + return; + } + + feed = 1; + err = rt_device_control(wdg_dev, RT_DEVICE_CTRL_WDT_START, RT_NULL); + uassert_int_equal(err, RT_EOK); + if (err != RT_EOK) + { + feed = 0; + return; + } + + /* Keep feeding longer than the timeout. The shell is still up if this returns. */ + rt_thread_mdelay(WDT_FEED_WAIT_MS); + + /* This IWDG cannot be stopped. Clearing the hook should reset the board. */ + feed = 0; + rt_thread_mdelay(WDT_NOFEED_WAIT_MS); + uassert_true(0); +} + +static rt_err_t utest_tc_init(void) +{ + feed = 0; + wdg_dev = RT_NULL; + rt_thread_idle_sethook(idle_hook); + return RT_EOK; +} + +static rt_err_t utest_tc_cleanup(void) +{ + feed = 0; + rt_thread_idle_delhook(idle_hook); + return RT_EOK; +} + +UTEST_TC_EXPORT(test_wdt, "bsp.ch32v203.drivers.wdt", utest_tc_init, utest_tc_cleanup, 20); diff --git a/bsp/wch/risc-v/ch32v203c-evt-r0/applications/wdt_msh.c b/bsp/wch/risc-v/ch32v203c-evt-r0/applications/wdt_msh.c deleted file mode 100644 index 875a0d0a7bf2..000000000000 --- a/bsp/wch/risc-v/ch32v203c-evt-r0/applications/wdt_msh.c +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright (c) 2006-2026, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2026-09-22 seteiro CH32V203: start or feed the independent watchdog - */ - -#include -#include -#include - -#ifdef BSP_USING_IWDT - -static int wdt_seconds(const char *text, rt_uint32_t *seconds) -{ - const char *p; - char *end; - unsigned long value; - unsigned long max_seconds; - - if (text == RT_NULL || text[0] == '\0') - { - return -RT_ERROR; - } - for (p = text; *p != '\0'; p++) - { - if (*p < '0' || *p > '9') - { - return -RT_ERROR; - } - } - value = strtoul(text, &end, 10); - if (end == text || *end != '\0') - { - return -RT_ERROR; - } - max_seconds = (0xFFFUL * 256UL) / LSI_VALUE; - if (value == 0 || value > max_seconds) - { - return -RT_ERROR; - } - *seconds = (rt_uint32_t)value; - return RT_EOK; -} - -static int wdt(int argc, char **argv) -{ - rt_device_t dev; - rt_uint32_t timeout; - rt_err_t err; - - if (argc < 2) - { - rt_kprintf("wdt start | wdt feed\n"); - return -RT_ERROR; - } - - dev = rt_device_find("wdt"); - if (dev == RT_NULL) - { - rt_kprintf("wdt device not found\n"); - return -RT_ERROR; - } - - if (!rt_strcmp(argv[1], "start")) - { - if (argc < 3) - { - rt_kprintf("wdt start <1-%lu seconds>\n", (0xFFFUL * 256UL) / LSI_VALUE); - return -RT_ERROR; - } - if (wdt_seconds(argv[2], &timeout) != RT_EOK) - { - rt_kprintf("wdt start <1-%lu seconds>\n", (0xFFFUL * 256UL) / LSI_VALUE); - return -RT_ERROR; - } - err = rt_device_init(dev); - if (err != RT_EOK) - { - return err; - } - err = rt_device_control(dev, RT_DEVICE_CTRL_WDT_SET_TIMEOUT, &timeout); - if (err != RT_EOK) - { - return err; - } - err = rt_device_control(dev, RT_DEVICE_CTRL_WDT_START, RT_NULL); - rt_kprintf("wdt start %u %s\n", timeout, err == RT_EOK ? "ok" : "fail"); - return err; - } - - if (!rt_strcmp(argv[1], "feed")) - { - err = rt_device_control(dev, RT_DEVICE_CTRL_WDT_KEEPALIVE, RT_NULL); - rt_kprintf("wdt feed %s\n", err == RT_EOK ? "ok" : "fail"); - return err; - } - - rt_kprintf("wdt start | wdt feed\n"); - return -RT_ERROR; -} -MSH_CMD_EXPORT(wdt, start or feed independent watchdog); - -#endif diff --git a/bsp/wch/risc-v/ch32v203c-evt-r0/board/Kconfig b/bsp/wch/risc-v/ch32v203c-evt-r0/board/Kconfig index 90323e6b9983..900bf044d065 100644 --- a/bsp/wch/risc-v/ch32v203c-evt-r0/board/Kconfig +++ b/bsp/wch/risc-v/ch32v203c-evt-r0/board/Kconfig @@ -174,6 +174,14 @@ menu "On-chip Peripheral Drivers" select LSI_VALUE default n + config BSP_UTEST_IWDT + bool "Enable IWDT utest" + depends on BSP_USING_IWDT + select RT_USING_UTEST + default n + help + The utest framework requires a console buffer of at least 256 bytes. + config BSP_USING_USBD bool "Enable USB Device" select RT_USING_USB_DEVICE diff --git a/bsp/wch/risc-v/ch32v203c-evt-r0/board/linker_scripts/link.lds b/bsp/wch/risc-v/ch32v203c-evt-r0/board/linker_scripts/link.lds index 815d0b33d263..9792708cc10f 100644 --- a/bsp/wch/risc-v/ch32v203c-evt-r0/board/linker_scripts/link.lds +++ b/bsp/wch/risc-v/ch32v203c-evt-r0/board/linker_scripts/link.lds @@ -52,6 +52,13 @@ SECTIONS __vsymtab_end = .; . = ALIGN(4); + /* section information for utest */ + . = ALIGN(4); + __rt_utest_tc_tab_start = .; + KEEP(*(UtestTcTab)) + __rt_utest_tc_tab_end = .; + . = ALIGN(4); + /* section information for initial. */ . = ALIGN(4); __rt_init_start = .;