summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorhathach <[email protected]>2024-06-14 16:06:37 +0700
committerhathach <[email protected]>2024-06-14 16:06:37 +0700
commit33f5547ed435f33259afc2a8e906eb7a258fbdd6 (patch)
treeb99975931d78579a58c7bc8e7a28ddd9b8a20d92
parent969b06d77c8a37510c9bed8dde377ff7bf462a30 (diff)
add ch32v103 bsp support, compile but does not run, probably due to compile/linker issue
-rw-r--r--hw/bsp/ch32v10x/boards/ch32v103r_r1_1v0/board.cmake8
-rw-r--r--hw/bsp/ch32v10x/boards/ch32v103r_r1_1v0/board.h20
-rw-r--r--hw/bsp/ch32v10x/boards/ch32v103r_r1_1v0/board.mk7
-rw-r--r--hw/bsp/ch32v10x/ch32v10x_conf.h37
-rw-r--r--hw/bsp/ch32v10x/ch32v10x_it.h15
-rw-r--r--hw/bsp/ch32v10x/family.c147
-rw-r--r--hw/bsp/ch32v10x/family.cmake117
-rw-r--r--hw/bsp/ch32v10x/family.mk53
-rw-r--r--hw/bsp/ch32v10x/linker/ch32v10x.ld165
-rw-r--r--hw/bsp/ch32v10x/system_ch32v10x.c600
-rw-r--r--hw/bsp/ch32v10x/system_ch32v10x.h29
-rw-r--r--hw/bsp/ch32v10x/wch-riscv.cfg17
-rw-r--r--hw/bsp/ch32v20x/family.mk10
-rw-r--r--hw/bsp/family_support.cmake2
-rw-r--r--src/common/tusb_mcu.h9
-rw-r--r--src/portable/wch/ch32_usbfs_reg.h65
-rw-r--r--src/tusb_option.h6
-rw-r--r--tools/get_deps.py3
18 files changed, 1295 insertions, 15 deletions
diff --git a/hw/bsp/ch32v10x/boards/ch32v103r_r1_1v0/board.cmake b/hw/bsp/ch32v10x/boards/ch32v103r_r1_1v0/board.cmake
new file mode 100644
index 000000000..f6e47ba30
--- /dev/null
+++ b/hw/bsp/ch32v10x/boards/ch32v103r_r1_1v0/board.cmake
@@ -0,0 +1,8 @@
+set(LD_FLASH_SIZE 64K)
+set(LD_RAM_SIZE 20K)
+
+function(update_board TARGET)
+ target_compile_definitions(${TARGET} PUBLIC
+ CFG_EXAMPLE_MSC_DUAL_READONLY
+ )
+endfunction()
diff --git a/hw/bsp/ch32v10x/boards/ch32v103r_r1_1v0/board.h b/hw/bsp/ch32v10x/boards/ch32v103r_r1_1v0/board.h
new file mode 100644
index 000000000..3b1187c3a
--- /dev/null
+++ b/hw/bsp/ch32v10x/boards/ch32v103r_r1_1v0/board.h
@@ -0,0 +1,20 @@
+#ifndef BOARD_H_
+#define BOARD_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define LED_PORT GPIOA
+#define LED_PIN GPIO_Pin_10
+#define LED_STATE_ON 0
+
+#define BUTTON_PORT GPIOA
+#define BUTTON_PIN GPIO_Pin_1
+#define BUTTON_STATE_ACTIVE 0
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/hw/bsp/ch32v10x/boards/ch32v103r_r1_1v0/board.mk b/hw/bsp/ch32v10x/boards/ch32v103r_r1_1v0/board.mk
new file mode 100644
index 000000000..7d7462312
--- /dev/null
+++ b/hw/bsp/ch32v10x/boards/ch32v103r_r1_1v0/board.mk
@@ -0,0 +1,7 @@
+MCU_VARIANT = D6
+
+CFLAGS += -DCFG_EXAMPLE_MSC_DUAL_READONLY
+
+LDFLAGS += \
+ -Wl,--defsym=__flash_size=64K \
+ -Wl,--defsym=__ram_size=20K \
diff --git a/hw/bsp/ch32v10x/ch32v10x_conf.h b/hw/bsp/ch32v10x/ch32v10x_conf.h
new file mode 100644
index 000000000..939c0fbde
--- /dev/null
+++ b/hw/bsp/ch32v10x/ch32v10x_conf.h
@@ -0,0 +1,37 @@
+/********************************** (C) COPYRIGHT *******************************
+ * File Name : ch32v10x_conf.h
+ * Author : WCH
+ * Version : V1.0.0
+ * Date : 2020/04/30
+ * Description : Library configuration file.
+*********************************************************************************
+* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
+* Attention: This software (modified or not) and binary are used for
+* microcontroller manufactured by Nanjing Qinheng Microelectronics.
+*******************************************************************************/
+#ifndef __CH32V10x_CONF_H
+#define __CH32V10x_CONF_H
+
+#include "ch32v10x_adc.h"
+#include "ch32v10x_bkp.h"
+#include "ch32v10x_crc.h"
+#include "ch32v10x_dbgmcu.h"
+#include "ch32v10x_dma.h"
+#include "ch32v10x_exti.h"
+#include "ch32v10x_flash.h"
+#include "ch32v10x_gpio.h"
+#include "ch32v10x_i2c.h"
+#include "ch32v10x_iwdg.h"
+#include "ch32v10x_pwr.h"
+#include "ch32v10x_rcc.h"
+#include "ch32v10x_rtc.h"
+#include "ch32v10x_spi.h"
+#include "ch32v10x_tim.h"
+#include "ch32v10x_usart.h"
+#include "ch32v10x_wwdg.h"
+#include "ch32v10x_usb.h"
+#include "ch32v10x_usb_host.h"
+#include "ch32v10x_it.h"
+#include "ch32v10x_misc.h"
+
+#endif /* __CH32V10x_CONF_H */
diff --git a/hw/bsp/ch32v10x/ch32v10x_it.h b/hw/bsp/ch32v10x/ch32v10x_it.h
new file mode 100644
index 000000000..13afc2412
--- /dev/null
+++ b/hw/bsp/ch32v10x/ch32v10x_it.h
@@ -0,0 +1,15 @@
+/********************************** (C) COPYRIGHT *******************************
+ * File Name : ch32v10x_it.h
+ * Author : WCH
+ * Version : V1.0.0
+ * Date : 2022/08/20
+ * Description : This file contains the headers of the interrupt handlers.
+*********************************************************************************
+* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
+* Attention: This software (modified or not) and binary are used for
+* microcontroller manufactured by Nanjing Qinheng Microelectronics.
+*******************************************************************************/
+#ifndef __CH32V10x_IT_H
+#define __CH32V10x_IT_H
+
+#endif /* __CH32V10x_IT_H */
diff --git a/hw/bsp/ch32v10x/family.c b/hw/bsp/ch32v10x/family.c
new file mode 100644
index 000000000..6de17521e
--- /dev/null
+++ b/hw/bsp/ch32v10x/family.c
@@ -0,0 +1,147 @@
+#include <stdio.h>
+
+// https://github.com/openwch/ch32v307/pull/90
+// https://github.com/openwch/ch32v20x/pull/12
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wstrict-prototypes"
+#endif
+
+#include "ch32v10x.h"
+
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
+
+#include "bsp/board_api.h"
+#include "board.h"
+
+__attribute__((interrupt)) __attribute__((used))
+void USBHD_IRQHandler(void) {
+ #if CFG_TUD_WCH_USBIP_USBFS
+ tud_int_handler(0);
+ #endif
+}
+
+__attribute__((interrupt)) __attribute__((used))
+void USBHDWakeUp_IRQHandler(void) {
+ #if CFG_TUD_WCH_USBIP_USBFS
+ tud_int_handler(0);
+ #endif
+}
+
+#if CFG_TUSB_OS == OPT_OS_NONE
+volatile uint32_t system_ticks = 0;
+
+__attribute__((interrupt)) __attribute__((used))
+void SysTick_Handler(void) {
+ SysTick->CNTL0 = SysTick->CNTL1 = SysTick->CNTL2 = SysTick->CNTL3 = 0;
+ SysTick->CNTH0 = SysTick->CNTH1 = SysTick->CNTH2 = SysTick->CNTH3 = 0;
+ system_ticks++;
+}
+
+uint32_t SysTick_Config(uint32_t ticks) {
+ NVIC_EnableIRQ(SysTicK_IRQn);
+ SysTick->CTLR = 0;
+ SysTick->CNTL0 = SysTick->CNTL1 = SysTick->CNTL2 = SysTick->CNTL3 = 0;
+ SysTick->CNTH0 = SysTick->CNTH1 = SysTick->CNTH2 = SysTick->CNTH3 = 0;
+
+ SysTick->CMPLR0 = (u8)(ticks & 0xFF);
+ SysTick->CMPLR1 = (u8)(ticks >> 8);
+ SysTick->CMPLR2 = (u8)(ticks >> 16);
+ SysTick->CMPLR3 = (u8)(ticks >> 24);
+
+ SysTick->CMPHR0 = SysTick->CMPHR1 = SysTick->CMPHR2 = SysTick->CMPHR3 = 0;
+ SysTick->CTLR = 1;
+ return 0;
+}
+
+uint32_t board_millis(void) {
+ return system_ticks;
+}
+#endif
+
+void board_init(void) {
+ __disable_irq();
+
+#if CFG_TUSB_OS == OPT_OS_NONE
+ SysTick_Config(SystemCoreClock / 1000);
+#endif
+
+ uint8_t usb_div;
+ switch (SystemCoreClock) {
+ case 48000000: usb_div = RCC_USBCLKSource_PLLCLK_Div1; break;
+ case 72000000: usb_div = RCC_USBCLKSource_PLLCLK_1Div5; break;
+ default: TU_ASSERT(0,); break;
+ }
+ RCC_USBCLKConfig(usb_div);
+ RCC_APB1PeriphClockCmd(RCC_APB1Periph_USB, ENABLE);
+
+ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
+
+ #ifdef LED_PIN
+ GPIO_InitTypeDef led_init = {
+ .GPIO_Pin = LED_PIN,
+ .GPIO_Mode = GPIO_Mode_Out_OD,
+ .GPIO_Speed = GPIO_Speed_50MHz,
+ };
+ GPIO_Init(LED_PORT, &led_init);
+ #endif
+
+ #ifdef BUTTON_PIN
+ GPIO_InitTypeDef button_init = {
+ .GPIO_Pin = BUTTON_PIN,
+ .GPIO_Mode = GPIO_Mode_IPU,
+ .GPIO_Speed = GPIO_Speed_50MHz,
+ };
+ GPIO_Init(BUTTON_PORT, &button_init);
+ #endif
+
+ // UART TX is PA9
+ RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
+ GPIO_InitTypeDef usart_init = {
+ .GPIO_Pin = GPIO_Pin_9,
+ .GPIO_Speed = GPIO_Speed_50MHz,
+ .GPIO_Mode = GPIO_Mode_AF_PP,
+ };
+ GPIO_Init(GPIOA, &usart_init);
+
+ USART_InitTypeDef usart = {
+ .USART_BaudRate = 115200,
+ .USART_WordLength = USART_WordLength_8b,
+ .USART_StopBits = USART_StopBits_1,
+ .USART_Parity = USART_Parity_No,
+ .USART_Mode = USART_Mode_Tx,
+ .USART_HardwareFlowControl = USART_HardwareFlowControl_None,
+ };
+ USART_Init(USART1, &usart);
+ USART_Cmd(USART1, ENABLE);
+
+ __enable_irq();
+
+ board_led_write(true);
+}
+
+void board_led_write(bool state) {
+ GPIO_WriteBit(LED_PORT, LED_PIN, state ? LED_STATE_ON : (1-LED_STATE_ON));
+}
+
+uint32_t board_button_read(void) {
+ return BUTTON_STATE_ACTIVE == GPIO_ReadInputDataBit(BUTTON_PORT, BUTTON_PIN);
+}
+
+int board_uart_read(uint8_t *buf, int len) {
+ (void) buf;
+ (void) len;
+ return 0;
+}
+
+int board_uart_write(void const *buf, int len) {
+ const char *bufc = (const char *) buf;
+ for (int i = 0; i < len; i++) {
+ while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
+ USART_SendData(USART1, *bufc++);
+ }
+
+ return len;
+}
diff --git a/hw/bsp/ch32v10x/family.cmake b/hw/bsp/ch32v10x/family.cmake
new file mode 100644
index 000000000..b0d8241d3
--- /dev/null
+++ b/hw/bsp/ch32v10x/family.cmake
@@ -0,0 +1,117 @@
+include_guard()
+
+#set(UF2_FAMILY_ID 0x699b62ec)
+set(CH32_FAMILY ch32v10x)
+set(SDK_DIR ${TOP}/hw/mcu/wch/ch32v103)
+set(SDK_SRC_DIR ${SDK_DIR}/EVT/EXAM/SRC)
+
+# include board specific
+include(${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}/board.cmake)
+
+# toolchain set up
+set(CMAKE_SYSTEM_PROCESSOR rv32imac-ilp32 CACHE INTERNAL "System Processor")
+set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/riscv_${TOOLCHAIN}.cmake)
+
+set(FAMILY_MCUS CH32V103 CACHE INTERNAL "")
+set(OPENOCD_OPTION "-f ${CMAKE_CURRENT_LIST_DIR}/wch-riscv.cfg")
+
+#------------------------------------
+# BOARD_TARGET
+#------------------------------------
+# only need to be built ONCE for all examples
+function(add_board_target BOARD_TARGET)
+ if (TARGET ${BOARD_TARGET})
+ return()
+ endif()
+
+ if (NOT DEFINED LD_FILE_GNU)
+ set(LD_FILE_GNU ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/linker/${CH32_FAMILY}.ld)
+ endif ()
+ set(LD_FILE_Clang ${LD_FILE_GNU})
+
+ if (NOT DEFINED STARTUP_FILE_GNU)
+ set(STARTUP_FILE_GNU ${SDK_SRC_DIR}/Startup/startup_${CH32_FAMILY}.S)
+ endif ()
+ set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU})
+
+ add_library(${BOARD_TARGET} STATIC
+ ${SDK_SRC_DIR}/Core/core_riscv.c
+ ${SDK_SRC_DIR}/Peripheral/src/${CH32_FAMILY}_gpio.c
+ ${SDK_SRC_DIR}/Peripheral/src/${CH32_FAMILY}_misc.c
+ ${SDK_SRC_DIR}/Peripheral/src/${CH32_FAMILY}_rcc.c
+ ${SDK_SRC_DIR}/Peripheral/src/${CH32_FAMILY}_usart.c
+ ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/system_${CH32_FAMILY}.c
+ ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}}
+ )
+ target_include_directories(${BOARD_TARGET} PUBLIC
+ ${SDK_SRC_DIR}/Core
+ ${SDK_SRC_DIR}/Peripheral/inc
+ ${CMAKE_CURRENT_FUNCTION_LIST_DIR}
+ )
+ target_compile_definitions(${BOARD_TARGET} PUBLIC
+ )
+
+ update_board(${BOARD_TARGET})
+
+ if (CMAKE_C_COMPILER_ID STREQUAL "GNU")
+ target_compile_options(${BOARD_TARGET} PUBLIC
+ -mcmodel=medany
+ )
+ target_link_options(${BOARD_TARGET} PUBLIC
+ "LINKER:--script=${LD_FILE_GNU}"
+ -Wl,--defsym=__flash_size=${LD_FLASH_SIZE}
+ -Wl,--defsym=__ram_size=${LD_RAM_SIZE}
+ -nostartfiles
+ --specs=nosys.specs --specs=nano.specs
+ )
+ elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang")
+ message(FATAL_ERROR "Clang is not supported for MSP432E4")
+ elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR")
+ target_link_options(${BOARD_TARGET} PUBLIC
+ "LINKER:--config=${LD_FILE_IAR}"
+ )
+ endif ()
+endfunction()
+
+
+#------------------------------------
+# Functions
+#------------------------------------
+function(family_configure_example TARGET RTOS)
+ family_configure_common(${TARGET} ${RTOS})
+
+ # Board target
+ add_board_target(board_${BOARD})
+
+ #---------- Port Specific ----------
+ # These files are built for each example since it depends on example's tusb_config.h
+ target_sources(${TARGET} PUBLIC
+ # BSP
+ ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c
+ ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c
+ )
+ target_include_directories(${TARGET} PUBLIC
+ # family, hw, board
+ ${CMAKE_CURRENT_FUNCTION_LIST_DIR}
+ ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../
+ ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD}
+ )
+
+ # Add TinyUSB target and port source
+ family_add_tinyusb(${TARGET} OPT_MCU_CH32V103 ${RTOS})
+
+ target_sources(${TARGET}-tinyusb PUBLIC
+ ${TOP}/src/portable/wch/dcd_ch32_usbfs.c
+ )
+ target_link_libraries(${TARGET}-tinyusb PUBLIC board_${BOARD})
+
+ # Link dependencies
+ target_link_libraries(${TARGET} PUBLIC board_${BOARD} ${TARGET}-tinyusb)
+
+ # Flashing
+ family_add_bin_hex(${TARGET})
+ family_flash_openocd_wch(${TARGET})
+
+ #family_add_uf2(${TARGET} ${UF2_FAMILY_ID})
+ #family_flash_uf2(${TARGET} ${UF2_FAMILY_ID})
+endfunction()
diff --git a/hw/bsp/ch32v10x/family.mk b/hw/bsp/ch32v10x/family.mk
new file mode 100644
index 000000000..d96d5012e
--- /dev/null
+++ b/hw/bsp/ch32v10x/family.mk
@@ -0,0 +1,53 @@
+# https://www.embecosm.com/resources/tool-chain-downloads/#riscv-stable
+#CROSS_COMPILE ?= riscv32-unknown-elf-
+
+# Toolchain from https://nucleisys.com/download.php
+#CROSS_COMPILE ?= riscv-nuclei-elf-
+
+# Toolchain from https://github.com/xpack-dev-tools/riscv-none-elf-gcc-xpack
+CROSS_COMPILE ?= riscv-none-elf-
+
+CH32_FAMILY = ch32v10x
+SDK_DIR = hw/mcu/wch/ch32v103
+SDK_SRC_DIR = $(SDK_DIR)/EVT/EXAM/SRC
+
+include $(TOP)/$(BOARD_PATH)/board.mk
+CPU_CORE ?= rv32imac-ilp32
+
+# Port0 use FSDev, Port1 use USBFS
+PORT ?= 0
+
+CFLAGS += \
+ -mcmodel=medany \
+ -ffat-lto-objects \
+ -flto \
+ -DCFG_TUSB_MCU=OPT_MCU_CH32V103
+
+# https://github.com/openwch/ch32v20x/pull/12
+CFLAGS += -Wno-error=strict-prototypes
+
+LDFLAGS_GCC += \
+ -nostdlib -nostartfiles \
+ --specs=nosys.specs --specs=nano.specs \
+
+LD_FILE = $(FAMILY_PATH)/linker/${CH32_FAMILY}.ld
+
+SRC_C += \
+ src/portable/wch/dcd_ch32_usbfs.c \
+ $(SDK_SRC_DIR)/Core/core_riscv.c \
+ $(SDK_SRC_DIR)/Peripheral/src/${CH32_FAMILY}_gpio.c \
+ $(SDK_SRC_DIR)/Peripheral/src/${CH32_FAMILY}_misc.c \
+ $(SDK_SRC_DIR)/Peripheral/src/${CH32_FAMILY}_rcc.c \
+ $(SDK_SRC_DIR)/Peripheral/src/${CH32_FAMILY}_usart.c \
+
+SRC_S += $(SDK_SRC_DIR)/Startup/startup_${CH32_FAMILY}.S
+
+INC += \
+ $(TOP)/$(BOARD_PATH) \
+ $(TOP)/$(SDK_SRC_DIR)/Core \
+ $(TOP)/$(SDK_SRC_DIR)/Peripheral/inc \
+
+FREERTOS_PORTABLE_SRC = $(FREERTOS_PORTABLE_PATH)/RISC-V
+
+OPENOCD_WCH_OPTION=-f $(TOP)/$(FAMILY_PATH)/wch-riscv.cfg
+flash: flash-openocd-wch
diff --git a/hw/bsp/ch32v10x/linker/ch32v10x.ld b/hw/bsp/ch32v10x/linker/ch32v10x.ld
new file mode 100644
index 000000000..cd5c8dc17
--- /dev/null
+++ b/hw/bsp/ch32v10x/linker/ch32v10x.ld
@@ -0,0 +1,165 @@
+/* Define default values if not already defined */
+__FLASH_SIZE = DEFINED(__flash_size) ? __flash_size : 64K;
+__RAM_SIZE = DEFINED(__ram_size) ? __ram_size : 20K;
+
+MEMORY
+{
+ FLASH (rx) : ORIGIN = 0x00000000, LENGTH = __FLASH_SIZE
+ RAM (xrw) : ORIGIN = 0x20000000, LENGTH = __RAM_SIZE
+}
+
+ENTRY( _start )
+
+__stack_size = 2048;
+
+PROVIDE( _stack_size = __stack_size );
+
+SECTIONS
+{
+ .init :
+ {
+ _sinit = .;
+ . = ALIGN(4);
+ KEEP(*(SORT_NONE(.init)))
+ . = ALIGN(4);
+ _einit = .;
+ } >FLASH AT>FLASH
+
+ .vector :
+ {
+ *(.vector);
+ . = ALIGN(64);
+ } >FLASH AT>FLASH
+
+ .text :
+ {
+ . = ALIGN(4);
+ *(.text)
+ *(.text.*)
+ *(.rodata)
+ *(.rodata*)
+ *(.gnu.linkonce.t.*)
+ . = ALIGN(4);
+ } >FLASH AT>FLASH
+
+ .fini :
+ {
+ KEEP(*(SORT_NONE(.fini)))
+ . = ALIGN(4);
+ } >FLASH AT>FLASH
+
+ PROVIDE( _etext = . );
+ PROVIDE( _eitcm = . );
+
+ .preinit_array :
+ {
+ PROVIDE_HIDDEN (__preinit_array_start = .);
+ KEEP (*(.preinit_array))
+ PROVIDE_HIDDEN (__preinit_array_end = .);
+ } >FLASH AT>FLASH
+
+ .init_array :
+ {
+ PROVIDE_HIDDEN (__init_array_start = .);
+ KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
+ KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))
+ PROVIDE_HIDDEN (__init_array_end = .);
+ } >FLASH AT>FLASH
+
+ .fini_array :
+ {
+ PROVIDE_HIDDEN (__fini_array_start = .);
+ KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))
+ KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors))
+ PROVIDE_HIDDEN (__fini_array_end = .);
+ } >FLASH AT>FLASH
+
+ .ctors :
+ {
+ /* 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 = .);
+ } >RAM
+
+}
diff --git a/hw/bsp/ch32v10x/system_ch32v10x.c b/hw/bsp/ch32v10x/system_ch32v10x.c
new file mode 100644
index 000000000..b083b83b4
--- /dev/null
+++ b/hw/bsp/ch32v10x/system_ch32v10x.c
@@ -0,0 +1,600 @@
+/********************************** (C) COPYRIGHT *******************************
+ * File Name : system_ch32v10x.c
+ * Author : WCH
+ * Version : V1.0.0
+ * Date : 2020/04/30
+ * Description : CH32V10x Device Peripheral Access Layer System Source File.
+*********************************************************************************
+* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
+* Attention: This software (modified or not) and binary are used for
+* microcontroller manufactured by Nanjing Qinheng Microelectronics.
+*******************************************************************************/
+#include "ch32v10x.h"
+
+/*
+ * Uncomment the line corresponding to the desired System clock (SYSCLK) frequency (after
+ * reset the HSI is used as SYSCLK source).
+ * If none of the define below is enabled, the HSI is used as System clock source.
+ */
+//#define SYSCLK_FREQ_HSE HSE_VALUE
+//#define SYSCLK_FREQ_48MHz_HSE 48000000
+//#define SYSCLK_FREQ_56MHz_HSE 56000000
+#define SYSCLK_FREQ_72MHz_HSE 72000000
+//#define SYSCLK_FREQ_HSI HSI_VALUE
+//#define SYSCLK_FREQ_48MHz_HSI 48000000
+//#define SYSCLK_FREQ_56MHz_HSI 56000000
+//#define SYSCLK_FREQ_72MHz_HSI 72000000
+
+/* Clock Definitions */
+#ifdef SYSCLK_FREQ_HSE
+uint32_t SystemCoreClock = SYSCLK_FREQ_HSE; /* System Clock Frequency (Core Clock) */
+#elif defined SYSCLK_FREQ_48MHz_HSE
+uint32_t SystemCoreClock = SYSCLK_FREQ_48MHz_HSE; /* System Clock Frequency (Core Clock) */
+#elif defined SYSCLK_FREQ_56MHz_HSE
+uint32_t SystemCoreClock = SYSCLK_FREQ_56MHz_HSE; /* System Clock Frequency (Core Clock) */
+#elif defined SYSCLK_FREQ_72MHz_HSE
+uint32_t SystemCoreClock = SYSCLK_FREQ_72MHz_HSE; /* System Clock Frequency (Core Clock) */
+#elif defined SYSCLK_FREQ_48MHz_HSI
+uint32_t SystemCoreClock = SYSCLK_FREQ_48MHz_HSI; /* System Clock Frequency (Core Clock) */
+#elif defined SYSCLK_FREQ_56MHz_HSI
+uint32_t SystemCoreClock = SYSCLK_FREQ_56MHz_HSI; /* System Clock Frequency (Core Clock) */
+#elif defined SYSCLK_FREQ_72MHz_HSI
+uint32_t SystemCoreClock = SYSCLK_FREQ_72MHz_HSI; /* System Clock Frequency (Core Clock) */
+#else
+uint32_t SystemCoreClock = HSI_VALUE; /* System Clock Frequency (Core Clock) */
+
+#endif
+
+__I uint8_t AHBPrescTable[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9};
+
+/* ch32v10x_system_private_function_proto_types */
+static void SetSysClock(void);
+
+#ifdef SYSCLK_FREQ_HSE
+static void SetSysClockToHSE( void );
+#elif defined SYSCLK_FREQ_48MHz_HSE
+static void SetSysClockTo48_HSE( void );
+#elif defined SYSCLK_FREQ_56MHz_HSE
+static void SetSysClockTo56_HSE( void );
+#elif defined SYSCLK_FREQ_72MHz_HSE
+static void SetSysClockTo72_HSE( void );
+#elif defined SYSCLK_FREQ_48MHz_HSI
+static void SetSysClockTo48_HSI( void );
+#elif defined SYSCLK_FREQ_56MHz_HSI
+static void SetSysClockTo56_HSI( void );
+#elif defined SYSCLK_FREQ_72MHz_HSI
+static void SetSysClockTo72_HSI( void );
+
+#endif
+
+/*********************************************************************
+ * @fn SystemInit
+ *
+ * @brief Setup the microcontroller system Initialize the Embedded Flash Interface,
+ * the PLL and update the SystemCoreClock variable.
+ *
+ * @return none
+ */
+void SystemInit(void)
+{
+ RCC->CTLR |= (uint32_t)0x00000001;
+ RCC->CFGR0 &= (uint32_t)0xF8FF0000;
+ RCC->CTLR &= (uint32_t)0xFEF6FFFF;
+ RCC->CTLR &= (uint32_t)0xFFFBFFFF;
+ RCC->CFGR0 &= (uint32_t)0xFF80FFFF;
+ RCC->INTR = 0x009F0000;
+ SetSysClock();
+}
+
+/*********************************************************************
+ * @fn SystemCoreClockUpdate
+ *
+ * @brief Update SystemCoreClock variable according to Clock Register Values.
+ *
+ * @return none
+ */
+void SystemCoreClockUpdate(void)
+{
+ uint32_t tmp = 0, pllmull = 0, pllsource = 0;
+
+ tmp = RCC->CFGR0 & RCC_SWS;
+
+ switch(tmp)
+ {
+ case 0x00:
+ SystemCoreClock = HSI_VALUE;
+ break;
+ case 0x04:
+ SystemCoreClock = HSE_VALUE;
+ break;
+ case 0x08:
+ pllmull = RCC->CFGR0 & RCC_PLLMULL;
+ pllsource = RCC->CFGR0 & RCC_PLLSRC;
+ pllmull = (pllmull >> 18) + 2;
+ if(pllsource == 0x00)
+ {
+ if( EXTEN->EXTEN_CTR & EXTEN_PLL_HSI_PRE )
+ {
+ SystemCoreClock = ( HSI_VALUE ) * pllmull;
+ }
+ else
+ {
+ SystemCoreClock = ( HSI_VALUE >> 1 ) * pllmull;
+ }
+ }
+ else
+ {
+ if((RCC->CFGR0 & RCC_PLLXTPRE) != (uint32_t)RESET)
+ {
+ SystemCoreClock = (HSE_VALUE >> 1) * pllmull;
+ }
+ else
+ {
+ SystemCoreClock = HSE_VALUE * pllmull;
+ }
+ }
+ break;
+ default:
+ SystemCoreClock = HSI_VALUE;
+ break;
+ }
+
+ tmp = AHBPrescTable[((RCC->CFGR0 & RCC_HPRE) >> 4)];
+ SystemCoreClock >>= tmp;
+}
+
+/*********************************************************************
+ * @fn SetSysClock
+ *
+ * @brief Configures the System clock frequency, HCLK, PCLK2 and PCLK1 prescalers.
+ *
+ * @return none
+ */
+static void SetSysClock(void)
+{
+ //GPIO_IPD_Unused();
+#ifdef SYSCLK_FREQ_HSE
+ SetSysClockToHSE();
+#elif defined SYSCLK_FREQ_48MHz_HSE
+ SetSysClockTo48_HSE();
+#elif defined SYSCLK_FREQ_56MHz_HSE
+ SetSysClockTo56_HSE();
+#elif defined SYSCLK_FREQ_72MHz_HSE
+ SetSysClockTo72_HSE();
+#elif defined SYSCLK_FREQ_48MHz_HSI
+ SetSysClockTo48_HSI();
+#elif defined SYSCLK_FREQ_56MHz_HSI
+ SetSysClockTo56_HSI();
+#elif defined SYSCLK_FREQ_72MHz_HSI
+ SetSysClockTo72_HSI();
+
+#endif
+
+ /* If none of the define above is enabled, the HSI is used as System clock
+ * source (default after reset)
+ */
+}
+
+#ifdef SYSCLK_FREQ_HSE
+
+/*********************************************************************
+ * @fn SetSysClockToHSE
+ *
+ * @brief Sets HSE as System clock source and configure HCLK, PCLK2 and PCLK1 prescalers.
+ *
+ * @return none
+ */
+static void SetSysClockToHSE(void)
+{
+ __IO uint32_t StartUpCounter = 0, HSEStatus = 0;
+
+ RCC->CTLR |= ((uint32_t)RCC_HSEON);
+
+ /* Wait till HSE is ready and if Time out is reached exit */
+ do
+ {
+ HSEStatus = RCC->CTLR & RCC_HSERDY;
+ StartUpCounter++;
+ } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
+
+ if((RCC->CTLR & RCC_HSERDY) != RESET)
+ {
+ HSEStatus = (uint32_t)0x01;
+ }
+ else
+ {
+ HSEStatus = (uint32_t)0x00;
+ }
+
+ if(HSEStatus == (uint32_t)0x01)
+ {
+ FLASH->ACTLR |= FLASH_ACTLR_PRFTBE;
+ /* Flash 0 wait state */
+ FLASH->ACTLR &= (uint32_t)((uint32_t)~FLASH_ACTLR_LATENCY);
+ FLASH->ACTLR |= (uint32_t)FLASH_ACTLR_LATENCY_0;
+
+ /* HCLK = SYSCLK */
+ RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1;
+ /* PCLK2 = HCLK */
+ RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1;
+ /* PCLK1 = HCLK */
+ RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV1;
+
+ /* Select HSE as system clock source */
+ RCC->CFGR0 &= (uint32_t)((uint32_t) ~(RCC_SW));
+ RCC->CFGR0 |= (uint32_t)RCC_SW_HSE;
+
+ /* Wait till HSE is used as system clock source */
+ while((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x04)
+ {
+ }
+ }
+ else
+ {
+ /* If HSE fails to start-up, the application will have wrong clock
+ * configuration. User can add here some code to deal with this error
+ */
+ }
+}
+
+
+#elif defined SYSCLK_FREQ_48MHz_HSE
+
+/*********************************************************************
+ * @fn SetSysClockTo48_HSE
+ *
+ * @brief Sets System clock frequency to 48MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
+ *
+ * @return none
+ */
+static void SetSysClockTo48_HSE(void)
+{
+ __IO uint32_t StartUpCounter = 0, HSEStatus = 0;
+
+ RCC->CTLR |= ((uint32_t)RCC_HSEON);
+ /* Wait till HSE is ready and if Time out is reached exit */
+ do
+ {
+ HSEStatus = RCC->CTLR & RCC_HSERDY;
+ StartUpCounter++;
+ } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
+
+ if((RCC->CTLR & RCC_HSERDY) != RESET)
+ {
+ HSEStatus = (uint32_t)0x01;
+ }
+ else
+ {
+ HSEStatus = (uint32_t)0x00;
+ }
+
+ if(HSEStatus == (uint32_t)0x01)
+ {
+ /* Enable Prefetch Buffer */
+ FLASH->ACTLR |= FLASH_ACTLR_PRFTBE;
+
+ /* Flash 1 wait state */
+ FLASH->ACTLR &= (uint32_t)((uint32_t)~FLASH_ACTLR_LATENCY);
+ FLASH->ACTLR |= (uint32_t)FLASH_ACTLR_LATENCY_1;
+
+ /* HCLK = SYSCLK */
+ RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1;
+ /* PCLK2 = HCLK */
+ RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1;
+ /* PCLK1 = HCLK */
+ RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV2;
+
+ /* PLL configuration: PLLCLK = HSE * 6 = 48 MHz */
+ RCC->CFGR0 &= (uint32_t)((uint32_t) ~(RCC_PLLSRC | RCC_PLLXTPRE | RCC_PLLMULL));
+ RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSE | RCC_PLLMULL6);
+
+ /* Enable PLL */
+ RCC->CTLR |= RCC_PLLON;
+ /* Wait till PLL is ready */
+ while((RCC->CTLR & RCC_PLLRDY) == 0)
+ {
+ }
+ /* Select PLL as system clock source */
+ RCC->CFGR0 &= (uint32_t)((uint32_t) ~(RCC_SW));
+ RCC->CFGR0 |= (uint32_t)RCC_SW_PLL;
+ /* Wait till PLL is used as system clock source */
+ while((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08)
+ {
+ }
+ }
+ else
+ {
+ /*
+ * If HSE fails to start-up, the application will have wrong clock
+ * configuration. User can add here some code to deal with this error
+ */
+ }
+}
+
+#elif defined SYSCLK_FREQ_56MHz_HSE
+
+/*********************************************************************
+ * @fn SetSysClockTo56_HSE
+ *
+ * @brief Sets System clock frequency to 56MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
+ *
+ * @return none
+ */
+static void SetSysClockTo56_HSE(void)
+{
+ __IO uint32_t StartUpCounter = 0, HSEStatus = 0;
+
+ RCC->CTLR |= ((uint32_t)RCC_HSEON);
+
+ /* Wait till HSE is ready and if Time out is reached exit */
+ do
+ {
+ HSEStatus = RCC->CTLR & RCC_HSERDY;
+ StartUpCounter++;
+ } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
+
+ if((RCC->CTLR & RCC_HSERDY) != RESET)
+ {
+ HSEStatus = (uint32_t)0x01;
+ }
+ else
+ {
+ HSEStatus = (uint32_t)0x00;
+ }
+
+ if(HSEStatus == (uint32_t)0x01)
+ {
+ /* Enable Prefetch Buffer */
+ FLASH->ACTLR |= FLASH_ACTLR_PRFTBE;
+
+ /* Flash 2 wait state */
+ FLASH->ACTLR &= (uint32_t)((uint32_t)~FLASH_ACTLR_LATENCY);
+ FLASH->ACTLR |= (uint32_t)FLASH_ACTLR_LATENCY_2;
+
+ /* HCLK = SYSCLK */
+ RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1;
+ /* PCLK2 = HCLK */
+ RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1;
+ /* PCLK1 = HCLK */
+ RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV2;
+
+ /* PLL configuration: PLLCLK = HSE * 7 = 56 MHz */
+ RCC->CFGR0 &= (uint32_t)((uint32_t) ~(RCC_PLLSRC | RCC_PLLXTPRE | RCC_PLLMULL));
+ RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSE | RCC_PLLMULL7);
+ /* Enable PLL */
+ RCC->CTLR |= RCC_PLLON;
+ /* Wait till PLL is ready */
+ while((RCC->CTLR & RCC_PLLRDY) == 0)
+ {
+ }
+
+ /* Select PLL as system clock source */
+ RCC->CFGR0 &= (uint32_t)((uint32_t) ~(RCC_SW));
+ RCC->CFGR0 |= (uint32_t)RCC_SW_PLL;
+ /* Wait till PLL is used as system clock source */
+ while((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08)
+ {
+ }
+ }
+ else
+ {
+ /*
+ * If HSE fails to start-up, the application will have wrong clock
+ * configuration. User can add here some code to deal with this error
+ */
+ }
+}
+
+#elif defined SYSCLK_FREQ_72MHz_HSE
+
+/*********************************************************************
+ * @fn SetSysClockTo72_HSE
+ *
+ * @brief Sets System clock frequency to 72MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
+ *
+ * @return none
+ */
+static void SetSysClockTo72_HSE(void)
+{
+ __IO uint32_t StartUpCounter = 0, HSEStatus = 0;
+
+ RCC->CTLR |= ((uint32_t)RCC_HSEON);
+
+ /* Wait till HSE is ready and if Time out is reached exit */
+ do
+ {
+ HSEStatus = RCC->CTLR & RCC_HSERDY;
+ StartUpCounter++;
+ } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
+
+ if((RCC->CTLR & RCC_HSERDY) != RESET)
+ {
+ HSEStatus = (uint32_t)0x01;
+ }
+ else
+ {
+ HSEStatus = (uint32_t)0x00;
+ }
+
+ if(HSEStatus == (uint32_t)0x01)
+ {
+ /* Enable Prefetch Buffer */
+ FLASH->ACTLR |= FLASH_ACTLR_PRFTBE;
+
+ /* Flash 2 wait state */
+ FLASH->ACTLR &= (uint32_t)((uint32_t)~FLASH_ACTLR_LATENCY);
+ FLASH->ACTLR |= (uint32_t)FLASH_ACTLR_LATENCY_2;
+
+ /* HCLK = SYSCLK */
+ RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1;
+ /* PCLK2 = HCLK */
+ RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1;
+ /* PCLK1 = HCLK */
+ RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV2;
+
+ /* PLL configuration: PLLCLK = HSE * 9 = 72 MHz */
+ RCC->CFGR0 &= (uint32_t)((uint32_t) ~(RCC_PLLSRC | RCC_PLLXTPRE |
+ RCC_PLLMULL));
+ RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSE | RCC_PLLMULL9);
+ /* Enable PLL */
+ RCC->CTLR |= RCC_PLLON;
+ /* Wait till PLL is ready */
+ while((RCC->CTLR & RCC_PLLRDY) == 0)
+ {
+ }
+ /* Select PLL as system clock source */
+ RCC->CFGR0 &= (uint32_t)((uint32_t) ~(RCC_SW));
+ RCC->CFGR0 |= (uint32_t)RCC_SW_PLL;
+ /* Wait till PLL is used as system clock source */
+ while((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08)
+ {
+ }
+ }
+ else
+ {
+ /*
+ * If HSE fails to start-up, the application will have wrong clock
+ * configuration. User can add here some code to deal with this error
+ */
+ }
+}
+
+#elif defined SYSCLK_FREQ_48MHz_HSI
+
+/*********************************************************************
+ * @fn SetSysClockTo48_HSI
+ *
+ * @brief Sets System clock frequency to 48MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
+ *
+ * @return none
+ */
+static void SetSysClockTo48_HSI(void)
+{
+ EXTEN->EXTEN_CTR |= EXTEN_PLL_HSI_PRE;
+
+ /* Enable Prefetch Buffer */
+ FLASH->ACTLR |= FLASH_ACTLR_PRFTBE;
+
+ /* Flash 1 wait state */
+ FLASH->ACTLR &= (uint32_t)((uint32_t)~FLASH_ACTLR_LATENCY);
+ FLASH->ACTLR |= (uint32_t)FLASH_ACTLR_LATENCY_1;
+
+ /* HCLK = SYSCLK */
+ RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1;
+ /* PCLK2 = HCLK */
+ RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1;
+ /* PCLK1 = HCLK */
+ RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV2;
+
+ /* PLL configuration: PLLCLK = HSI * 6 = 48 MHz */
+ RCC->CFGR0 &= (uint32_t)((uint32_t) ~(RCC_PLLSRC | RCC_PLLXTPRE | RCC_PLLMULL));
+ RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSI_Div2 | RCC_PLLMULL6);
+
+ /* Enable PLL */
+ RCC->CTLR |= RCC_PLLON;
+ /* Wait till PLL is ready */
+ while((RCC->CTLR & RCC_PLLRDY) == 0)
+ {
+ }
+ /* Select PLL as system clock source */
+ RCC->CFGR0 &= (uint32_t)((uint32_t) ~(RCC_SW));
+ RCC->CFGR0 |= (uint32_t)RCC_SW_PLL;
+ /* Wait till PLL is used as system clock source */
+ while((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08)
+ {
+ }
+}
+
+#elif defined SYSCLK_FREQ_56MHz_HSI
+
+/*********************************************************************
+ * @fn SetSysClockTo56_HSI
+ *
+ * @brief Sets System clock frequency to 56MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
+ *
+ * @return none
+ */
+static void SetSysClockTo56_HSI(void)
+{
+ EXTEN->EXTEN_CTR |= EXTEN_PLL_HSI_PRE;
+
+ /* Enable Prefetch Buffer */
+ FLASH->ACTLR |= FLASH_ACTLR_PRFTBE;
+
+ /* Flash 1 wait state */
+ FLASH->ACTLR &= (uint32_t)((uint32_t)~FLASH_ACTLR_LATENCY);
+ FLASH->ACTLR |= (uint32_t)FLASH_ACTLR_LATENCY_1;
+
+ /* HCLK = SYSCLK */
+ RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1;
+ /* PCLK2 = HCLK */
+ RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1;
+ /* PCLK1 = HCLK */
+ RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV2;
+
+ /* PLL configuration: PLLCLK = HSI * 7 = 56 MHz */
+ RCC->CFGR0 &= (uint32_t)((uint32_t) ~(RCC_PLLSRC | RCC_PLLXTPRE | RCC_PLLMULL));
+ RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSI_Div2 | RCC_PLLMULL7);
+
+ /* Enable PLL */
+ RCC->CTLR |= RCC_PLLON;
+ /* Wait till PLL is ready */
+ while((RCC->CTLR & RCC_PLLRDY) == 0)
+ {
+ }
+ /* Select PLL as system clock source */
+ RCC->CFGR0 &= (uint32_t)((uint32_t) ~(RCC_SW));
+ RCC->CFGR0 |= (uint32_t)RCC_SW_PLL;
+ /* Wait till PLL is used as system clock source */
+ while((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08)
+ {
+ }
+}
+
+#elif defined SYSCLK_FREQ_72MHz_HSI
+
+/*********************************************************************
+ * @fn SetSysClockTo72_HSI
+ *
+ * @brief Sets System clock frequency to 72MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
+ *
+ * @return none
+ */
+static void SetSysClockTo72_HSI(void)
+{
+ EXTEN->EXTEN_CTR |= EXTEN_PLL_HSI_PRE;
+
+ /* Enable Prefetch Buffer */
+ FLASH->ACTLR |= FLASH_ACTLR_PRFTBE;
+
+ /* Flash 1 wait state */
+ FLASH->ACTLR &= (uint32_t)((uint32_t)~FLASH_ACTLR_LATENCY);
+ FLASH->ACTLR |= (uint32_t)FLASH_ACTLR_LATENCY_1;
+
+ /* HCLK = SYSCLK */
+ RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1;
+ /* PCLK2 = HCLK */
+ RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1;
+ /* PCLK1 = HCLK */
+ RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV2;
+
+ /* PLL configuration: PLLCLK = HSI * 9 = 72 MHz */
+ RCC->CFGR0 &= (uint32_t)((uint32_t) ~(RCC_PLLSRC | RCC_PLLXTPRE | RCC_PLLMULL));
+ RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSI_Div2 | RCC_PLLMULL9);
+
+ /* Enable PLL */
+ RCC->CTLR |= RCC_PLLON;
+ /* Wait till PLL is ready */
+ while((RCC->CTLR & RCC_PLLRDY) == 0)
+ {
+ }
+ /* Select PLL as system clock source */
+ RCC->CFGR0 &= (uint32_t)((uint32_t) ~(RCC_SW));
+ RCC->CFGR0 |= (uint32_t)RCC_SW_PLL;
+ /* Wait till PLL is used as system clock source */
+ while((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08)
+ {
+ }
+}
+
+#endif
diff --git a/hw/bsp/ch32v10x/system_ch32v10x.h b/hw/bsp/ch32v10x/system_ch32v10x.h
new file mode 100644
index 000000000..d15624520
--- /dev/null
+++ b/hw/bsp/ch32v10x/system_ch32v10x.h
@@ -0,0 +1,29 @@
+/********************************** (C) COPYRIGHT *******************************
+ * File Name : system_ch32v10x.h
+ * Author : WCH
+ * Version : V1.0.0
+ * Date : 2020/04/30
+ * Description : CH32V10x Device Peripheral Access Layer System Header File.
+*********************************************************************************
+* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
+* Attention: This software (modified or not) and binary are used for
+* microcontroller manufactured by Nanjing Qinheng Microelectronics.
+*******************************************************************************/
+#ifndef __SYSTEM_CH32V10x_H
+#define __SYSTEM_CH32V10x_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern uint32_t SystemCoreClock; /* System Clock Frequency (Core Clock) */
+
+/* System_Exported_Functions */
+extern void SystemInit(void);
+extern void SystemCoreClockUpdate(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*__CH32V10x_SYSTEM_H */
diff --git a/hw/bsp/ch32v10x/wch-riscv.cfg b/hw/bsp/ch32v10x/wch-riscv.cfg
new file mode 100644
index 000000000..aa35aa9c5
--- /dev/null
+++ b/hw/bsp/ch32v10x/wch-riscv.cfg
@@ -0,0 +1,17 @@
+adapter driver wlinke
+adapter speed 6000
+transport select sdi
+
+wlink_set_address 0x00000000
+set _CHIPNAME wch_riscv
+sdi newtap $_CHIPNAME cpu -irlen 5 -expected-id 0x00001
+
+set _TARGETNAME $_CHIPNAME.cpu
+
+target create $_TARGETNAME.0 wch_riscv -chain-position $_TARGETNAME
+$_TARGETNAME.0 configure -work-area-phys 0x20000000 -work-area-size 10000 -work-area-backup 1
+set _FLASHNAME $_CHIPNAME.flash
+
+flash bank $_FLASHNAME wch_riscv 0x00000000 0 0 0 $_TARGETNAME.0
+
+echo "Ready for Remote Connections"
diff --git a/hw/bsp/ch32v20x/family.mk b/hw/bsp/ch32v20x/family.mk
index daf3148f8..4485091dc 100644
--- a/hw/bsp/ch32v20x/family.mk
+++ b/hw/bsp/ch32v20x/family.mk
@@ -45,12 +45,12 @@ SRC_C += \
src/portable/wch/dcd_ch32_usbfs.c \
src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c \
$(SDK_SRC_DIR)/Core/core_riscv.c \
- $(SDK_SRC_DIR)/Peripheral/src/ch32v20x_gpio.c \
- $(SDK_SRC_DIR)/Peripheral/src/ch32v20x_misc.c \
- $(SDK_SRC_DIR)/Peripheral/src/ch32v20x_rcc.c \
- $(SDK_SRC_DIR)/Peripheral/src/ch32v20x_usart.c \
+ $(SDK_SRC_DIR)/Peripheral/src/${CH32_FAMILY}_gpio.c \
+ $(SDK_SRC_DIR)/Peripheral/src/${CH32_FAMILY}_misc.c \
+ $(SDK_SRC_DIR)/Peripheral/src/${CH32_FAMILY}_rcc.c \
+ $(SDK_SRC_DIR)/Peripheral/src/${CH32_FAMILY}_usart.c \
-SRC_S += $(SDK_SRC_DIR)/Startup/startup_ch32v20x_${MCU_VARIANT}.S
+SRC_S += $(SDK_SRC_DIR)/Startup/startup_${CH32_FAMILY}_${MCU_VARIANT}.S
INC += \
$(TOP)/$(BOARD_PATH) \
diff --git a/hw/bsp/family_support.cmake b/hw/bsp/family_support.cmake
index d9443f811..94d55f04a 100644
--- a/hw/bsp/family_support.cmake
+++ b/hw/bsp/family_support.cmake
@@ -443,7 +443,7 @@ function(family_flash_openocd TARGET)
# note skip verify since it has issue with rp2040
add_custom_target(${TARGET}-openocd
DEPENDS ${TARGET}
- COMMAND ${OPENOCD} ${OPTION_LIST} -c "program $<TARGET_FILE:${TARGET}> reset" ${OPTION_LIST2} -c exit
+ COMMAND ${OPENOCD} ${OPTION_LIST} -c init -c halt -c "program $<TARGET_FILE:${TARGET}> reset" ${OPTION_LIST2} -c exit
VERBATIM
)
endfunction()
diff --git a/src/common/tusb_mcu.h b/src/common/tusb_mcu.h
index c66996c4f..d9d11e96d 100644
--- a/src/common/tusb_mcu.h
+++ b/src/common/tusb_mcu.h
@@ -420,6 +420,15 @@
#define TUP_RHPORT_HIGHSPEED CFG_TUD_WCH_USBIP_USBHS
#define TUP_DCD_ENDPOINT_MAX (CFG_TUD_WCH_USBIP_USBHS ? 16 : 8)
+#elif TU_CHECK_MCU(OPT_MCU_CH32V103)
+ #define TUP_USBIP_WCH_USBFS
+
+ #if !defined(CFG_TUD_WCH_USBIP_USBFS)
+ #define CFG_TUD_WCH_USBIP_USBFS 1
+ #endif
+
+ #define TUP_DCD_ENDPOINT_MAX 8
+
#elif TU_CHECK_MCU(OPT_MCU_CH32V20X)
// v20x support both FSDEV (USBD) and USBFS, default to FSDEV
#define TUP_USBIP_WCH_USBFS
diff --git a/src/portable/wch/ch32_usbfs_reg.h b/src/portable/wch/ch32_usbfs_reg.h
index ef6ebf2dc..68be64f5e 100644
--- a/src/portable/wch/ch32_usbfs_reg.h
+++ b/src/portable/wch/ch32_usbfs_reg.h
@@ -35,15 +35,68 @@
#pragma GCC diagnostic ignored "-Wstrict-prototypes"
#endif
-#if CFG_TUSB_MCU == OPT_MCU_CH32V307
- #include <ch32v30x.h>
- #define USBHD_IRQn OTG_FS_IRQn
+#if CFG_TUSB_MCU == OPT_MCU_CH32F20X
+ #include <ch32f20x.h>
+#elif CFG_TUSB_MCU == OPT_MCU_CH32V103
+ #include <ch32v10x.h>
+ typedef struct
+ {
+ __IO uint8_t BASE_CTRL;
+ __IO uint8_t UDEV_CTRL;
+ __IO uint8_t INT_EN;
+ __IO uint8_t DEV_ADDR;
+ __IO uint8_t Reserve0;
+ __IO uint8_t MIS_ST;
+ __IO uint8_t INT_FG;
+ __IO uint8_t INT_ST;
+ __IO uint32_t RX_LEN;
+ __IO uint8_t UEP4_1_MOD;
+ __IO uint8_t UEP2_3_MOD;
+ __IO uint8_t UEP5_6_MOD;
+ __IO uint8_t UEP7_MOD;
+ __IO uint32_t UEP0_DMA;
+ __IO uint32_t UEP1_DMA;
+ __IO uint32_t UEP2_DMA;
+ __IO uint32_t UEP3_DMA;
+ __IO uint32_t UEP4_DMA;
+ __IO uint32_t UEP5_DMA;
+ __IO uint32_t UEP6_DMA;
+ __IO uint32_t UEP7_DMA;
+ __IO uint16_t UEP0_TX_LEN;
+ __IO uint8_t UEP0_TX_CTRL;
+ __IO uint8_t UEP0_RX_CTRL;
+ __IO uint16_t UEP1_TX_LEN;
+ __IO uint8_t UEP1_TX_CTRL;
+ __IO uint8_t UEP1_RX_CTRL;
+ __IO uint16_t UEP2_TX_LEN;
+ __IO uint8_t UEP2_TX_CTRL;
+ __IO uint8_t UEP2_RX_CTRL;
+ __IO uint16_t UEP3_TX_LEN;
+ __IO uint8_t UEP3_TX_CTRL;
+ __IO uint8_t UEP3_RX_CTRL;
+ __IO uint16_t UEP4_TX_LEN;
+ __IO uint8_t UEP4_TX_CTRL;
+ __IO uint8_t UEP4_RX_CTRL;
+ __IO uint16_t UEP5_TX_LEN;
+ __IO uint8_t UEP5_TX_CTRL;
+ __IO uint8_t UEP5_RX_CTRL;
+ __IO uint16_t UEP6_TX_LEN;
+ __IO uint8_t UEP6_TX_CTRL;
+ __IO uint8_t UEP6_RX_CTRL;
+ __IO uint16_t UEP7_TX_LEN;
+ __IO uint8_t UEP7_TX_CTRL;
+ __IO uint8_t UEP7_RX_CTRL;
+ __IO uint32_t Reserve1;
+ __IO uint32_t OTG_CR;
+ __IO uint32_t OTG_SR;
+ } USBOTG_FS_TypeDef;
+ #define USBOTG_FS ((USBOTG_FS_TypeDef *) 0x40023400)
#elif CFG_TUSB_MCU == OPT_MCU_CH32V20X
#include <ch32v20x.h>
-
-#elif CFG_TUSB_MCU == OPT_MCU_CH32F20X
- #include <ch32f20x.h>
+#elif CFG_TUSB_MCU == OPT_MCU_CH32V307
+ #include <ch32v30x.h>
+ #define USBHD_IRQn OTG_FS_IRQn
#endif
#ifdef __GNUC__
diff --git a/src/tusb_option.h b/src/tusb_option.h
index db8b94580..1ca09e902 100644
--- a/src/tusb_option.h
+++ b/src/tusb_option.h
@@ -24,8 +24,8 @@
* This file is part of the TinyUSB stack.
*/
-#ifndef _TUSB_OPTION_H_
-#define _TUSB_OPTION_H_
+#ifndef TUSB_OPTION_H_
+#define TUSB_OPTION_H_
#include "common/tusb_compiler.h"
@@ -182,7 +182,7 @@
#define OPT_MCU_CH32V307 2200 ///< WCH CH32V307
#define OPT_MCU_CH32F20X 2210 ///< WCH CH32F20x
#define OPT_MCU_CH32V20X 2220 ///< WCH CH32V20X
-
+#define OPT_MCU_CH32V103 2230 ///< WCH CH32V103
// NXP LPC MCX
#define OPT_MCU_MCXN9 2300 ///< NXP MCX N9 Series
diff --git a/tools/get_deps.py b/tools/get_deps.py
index 50cc5c893..92bfb86a2 100644
--- a/tools/get_deps.py
+++ b/tools/get_deps.py
@@ -168,6 +168,9 @@ deps_optional = {
'hw/mcu/ti': ['https://github.com/hathach/ti_driver.git',
'143ed6cc20a7615d042b03b21e070197d473e6e5',
'msp430 msp432e4 tm4c'],
+ 'hw/mcu/wch/ch32v103': ['https://github.com/openwch/ch32v103.git',
+ '7578cae0b21f86dd053a1f781b2fc6ab99d0ec17',
+ 'ch32v10x'],
'hw/mcu/wch/ch32v20x': ['https://github.com/openwch/ch32v20x.git',
'de6d68c654340d7f27b00cebbfc9aa2740a1abc2',
'ch32v20x'],