summaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
authorhathach <[email protected]>2024-05-24 13:58:44 +0700
committerhathach <[email protected]>2024-05-24 13:58:44 +0700
commit4ce439a75a6f7aa995c74e7ac32e70ab8216c771 (patch)
treea1bed9351159f79f09de0c9a906c0dfb915686c5 /hw
parent927015baae9b2d265d1daaa0fc2ffca1aa4f9e91 (diff)
add ch32 support for fsdev driver. v20x can select fsdev or usbfs with make/cmake PORT=0/1. default to fsdev
Diffstat (limited to 'hw')
-rw-r--r--hw/bsp/ch32v20x/boards/ch32v203_r0_1v0/board.h1
-rw-r--r--hw/bsp/ch32v20x/family.c147
-rw-r--r--hw/bsp/ch32v20x/family.cmake20
-rw-r--r--hw/bsp/ch32v20x/family.mk15
-rw-r--r--hw/bsp/ch32v20x/linker/ch32v20x.ld166
5 files changed, 306 insertions, 43 deletions
diff --git a/hw/bsp/ch32v20x/boards/ch32v203_r0_1v0/board.h b/hw/bsp/ch32v20x/boards/ch32v203_r0_1v0/board.h
index c8d28d90f..3ed2aef04 100644
--- a/hw/bsp/ch32v20x/boards/ch32v203_r0_1v0/board.h
+++ b/hw/bsp/ch32v20x/boards/ch32v203_r0_1v0/board.h
@@ -8,7 +8,6 @@ extern "C" {
#define LED_PORT GPIOA
#define LED_PIN GPIO_Pin_15
#define LED_STATE_ON 0
-#define LED_CLOCK_EN() RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE)
#ifdef __cplusplus
}
diff --git a/hw/bsp/ch32v20x/family.c b/hw/bsp/ch32v20x/family.c
index 247dacde6..a0a8c3f50 100644
--- a/hw/bsp/ch32v20x/family.c
+++ b/hw/bsp/ch32v20x/family.c
@@ -1,82 +1,153 @@
#include <stdio.h>
#include "ch32v20x.h"
+
#include "bsp/board_api.h"
#include "board.h"
-__attribute__((interrupt))
+/* CH32v203 depending on variants can support 2 USB IPs: FSDEV and USBFS.
+ * By default, we use FSDEV, but you can explicitly select by define:
+ * - CFG_TUD_WCH_USBIP_FSDEV
+ * - CFG_TUD_WCH_USBIP_USBFS
+ */
+
+// USBFS
+__attribute__((interrupt)) __attribute__((used))
void USBHD_IRQHandler(void) {
- tud_int_handler(0);
+ #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
+}
+
+// USBD (fsdev)
+__attribute__((interrupt)) __attribute__((used))
+void USB_LP_CAN1_RX0_IRQHandler(void) {
+ #if CFG_TUD_WCH_USBIP_FSDEV
+ tud_int_handler(0);
+ #endif
+}
+
+__attribute__((interrupt)) __attribute__((used))
+void USB_HP_CAN1_TX_IRQHandler(void) {
+ #if CFG_TUD_WCH_USBIP_FSDEV
+ tud_int_handler(0);
+ #endif
+
+}
+
+__attribute__((interrupt)) __attribute__((used))
+void USBWakeUp_IRQHandler(void) {
+ #if CFG_TUD_WCH_USBIP_FSDEV
+ tud_int_handler(0);
+ #endif
}
+
#if CFG_TUSB_OS == OPT_OS_NONE
volatile uint32_t system_ticks = 0;
__attribute__((interrupt))
void SysTick_Handler(void) {
- SysTick->SR = 0;
- system_ticks++;
+ SysTick->SR = 0;
+ system_ticks++;
}
uint32_t SysTick_Config(uint32_t ticks) {
- NVIC_EnableIRQ(SysTicK_IRQn);
- SysTick->CTLR = 0;
- SysTick->SR = 0;
- SysTick->CNT = 0;
- SysTick->CMP = ticks-1;
- SysTick->CTLR = 0xF;
- return 0;
+ NVIC_EnableIRQ(SysTicK_IRQn);
+ SysTick->CTLR = 0;
+ SysTick->SR = 0;
+ SysTick->CNT = 0;
+ SysTick->CMP = ticks - 1;
+ SysTick->CTLR = 0xF;
+ return 0;
}
uint32_t board_millis(void) {
- return system_ticks;
+ return system_ticks;
}
#endif
void board_init(void) {
- __disable_irq();
+ __disable_irq();
#if CFG_TUSB_OS == OPT_OS_NONE
- SysTick_Config(SystemCoreClock / 1000);
+ SysTick_Config(SystemCoreClock / 1000);
#endif
- switch (SystemCoreClock) {
- case 48000000: RCC_USBCLKConfig(RCC_USBCLKSource_PLLCLK_Div1); break;
- case 96000000: RCC_USBCLKConfig(RCC_USBCLKSource_PLLCLK_Div2); break;
- case 144000000: RCC_USBCLKConfig(RCC_USBCLKSource_PLLCLK_Div3); break;
- default: TU_ASSERT(0,); break;
- }
- RCC_AHBPeriphClockCmd(RCC_AHBPeriph_OTG_FS, ENABLE);
+ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
+
+ uint8_t usb_div;
+ switch (SystemCoreClock) {
+ case 48000000: usb_div = RCC_USBCLKSource_PLLCLK_Div1; break;
+ case 96000000: usb_div = RCC_USBCLKSource_PLLCLK_Div2; break;
+ case 144000000: usb_div = RCC_USBCLKSource_PLLCLK_Div3; break;
+ default: TU_ASSERT(0,); break;
+ }
+ RCC_USBCLKConfig(usb_div);
+ RCC_APB1PeriphClockCmd(RCC_APB1Periph_USB, ENABLE); // FSDEV
+ RCC_AHBPeriphClockCmd(RCC_AHBPeriph_OTG_FS, ENABLE); // USB FS
- LED_CLOCK_EN();
- GPIO_InitTypeDef GPIO_InitStructure = {
- .GPIO_Pin = LED_PIN,
- .GPIO_Mode = GPIO_Mode_Out_OD,
- .GPIO_Speed = GPIO_Speed_50MHz,
- };
- GPIO_Init(LED_PORT, &GPIO_InitStructure);
+ GPIO_InitTypeDef GPIO_InitStructure = {
+ .GPIO_Pin = LED_PIN,
+ .GPIO_Mode = GPIO_Mode_Out_OD,
+ .GPIO_Speed = GPIO_Speed_50MHz,
+ };
+ GPIO_Init(LED_PORT, &GPIO_InitStructure);
- __enable_irq();
- board_delay(2);
+ // 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_delay(2);
+
+ printf("SystemCoreClock = %ld\r\n", SystemCoreClock);
}
void board_led_write(bool state) {
- GPIO_WriteBit(LED_PORT, LED_PIN, state);
+ GPIO_WriteBit(LED_PORT, LED_PIN, state);
}
uint32_t board_button_read(void) {
- return false;
+ return false;
}
int board_uart_read(uint8_t *buf, int len) {
- (void) buf;
- (void) len;
- return 0;
+ (void) buf;
+ (void) len;
+ return 0;
}
int board_uart_write(void const *buf, int len) {
- (void) buf;
- (void) len;
- return 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/ch32v20x/family.cmake b/hw/bsp/ch32v20x/family.cmake
index 80b035fc0..3fb1c0e79 100644
--- a/hw/bsp/ch32v20x/family.cmake
+++ b/hw/bsp/ch32v20x/family.cmake
@@ -14,6 +14,11 @@ set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/riscv_${TO
set(FAMILY_MCUS CH32V20X CACHE INTERNAL "")
set(OPENOCD_OPTION "-f ${CMAKE_CURRENT_LIST_DIR}/wch-riscv.cfg")
+# Port0 use FSDev, Port1 use USBFS
+if (NOT DEFINED PORT)
+ set(PORT 0)
+endif()
+
#------------------------------------
# BOARD_TARGET
#------------------------------------
@@ -48,9 +53,20 @@ function(add_board_target BOARD_TARGET)
)
target_compile_definitions(${BOARD_TARGET} PUBLIC
CH32V20x_${MCU_VARIANT}
- BOARD_TUD_MAX_SPEED=OPT_MODE_FULL_SPEED
)
+ if (PORT EQUAL 0)
+ target_compile_definitions(${BOARD_TARGET} PUBLIC
+ CFG_TUD_WCH_USBIP_FSDEV=1
+ )
+ elseif (PORT EQUAL 1)
+ target_compile_definitions(${BOARD_TARGET} PUBLIC
+ CFG_TUD_WCH_USBIP_USBFS=1
+ )
+ else()
+ message(FATAL_ERROR "Invalid PORT ${PORT}")
+ endif()
+
update_board(${BOARD_TARGET})
if (CMAKE_C_COMPILER_ID STREQUAL "GNU")
@@ -99,8 +115,10 @@ function(family_configure_example TARGET RTOS)
# Add TinyUSB target and port source
family_add_tinyusb(${TARGET} OPT_MCU_CH32V20X ${RTOS})
+
target_sources(${TARGET}-tinyusb PUBLIC
${TOP}/src/portable/wch/dcd_ch32_usbfs.c
+ ${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c
)
target_link_libraries(${TARGET}-tinyusb PUBLIC board_${BOARD})
diff --git a/hw/bsp/ch32v20x/family.mk b/hw/bsp/ch32v20x/family.mk
index 5c8b31a1c..49d4d2feb 100644
--- a/hw/bsp/ch32v20x/family.mk
+++ b/hw/bsp/ch32v20x/family.mk
@@ -14,13 +14,23 @@ 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 \
-DCH32V20x_${MCU_VARIANT} \
- -DCFG_TUSB_MCU=OPT_MCU_CH32V20X \
- -DBOARD_TUD_MAX_SPEED=OPT_MODE_FULL_SPEED \
+ -DCFG_TUSB_MCU=OPT_MCU_CH32V20X
+
+ifeq ($(PORT),0)
+ $(info "Using FSDEV driver")
+ CFLAGS += -DCFG_TUD_WCH_USBIP_FSDEV=1
+else
+ $(info "Using USBFS driver")
+ CFLAGS += -DCFG_TUD_WCH_USBIP_USBFS=1
+endif
LDFLAGS_GCC += \
-nostdlib -nostartfiles \
@@ -30,6 +40,7 @@ LD_FILE = $(FAMILY_PATH)/linker/${CH32_FAMILY}.ld
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 \
diff --git a/hw/bsp/ch32v20x/linker/ch32v20x.ld b/hw/bsp/ch32v20x/linker/ch32v20x.ld
index 6ee2fa1c7..cd5c8dc17 100644
--- a/hw/bsp/ch32v20x/linker/ch32v20x.ld
+++ b/hw/bsp/ch32v20x/linker/ch32v20x.ld
@@ -1 +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 }
+/* 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
+
+}