add ch32 support for fsdev driver. v20x can select fsdev or usbfs with make/cmake PORT=0/1. default to fsdev

This commit is contained in:
hathach
2024-05-24 13:58:44 +07:00
parent 927015baae
commit 4ce439a75a
14 changed files with 932 additions and 448 deletions

View File

@@ -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
}

View File

@@ -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);
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);
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
__enable_irq();
board_delay(2);
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);
// 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;
}

View File

@@ -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})

View File

@@ -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 \

View File

@@ -1 +1,165 @@
/* Define default values if not already defined */
/* 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
}