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:
@@ -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
|
||||
}
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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})
|
||||
|
||||
|
@@ -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 \
|
||||
|
@@ -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
|
||||
|
||||
}
|
||||
|
Reference in New Issue
Block a user