From fccbcfc88977ebdfb1448f6787cb052cfa949788 Mon Sep 17 00:00:00 2001 From: Greg Davill Date: Mon, 21 Mar 2022 10:01:11 +1030 Subject: [PATCH 01/20] Add WCH CH32V307 port Add WCH mcu submodule Add CH32V307V-R1-1v0 bsp --- .gitmodules | 3 + .../ch32v307/boards/CH32V307V-R1-1v0/board.mk | 3 + .../boards/CH32V307V-R1-1v0/debug_uart.c | 110 +++ .../boards/CH32V307V-R1-1v0/debug_uart.h | 31 + hw/bsp/ch32v307/ch32v30x_conf.h | 43 + hw/bsp/ch32v307/ch32v30x_it.c | 49 ++ hw/bsp/ch32v307/ch32v30x_it.h | 18 + hw/bsp/ch32v307/core_riscv.h | 384 +++++++++ hw/bsp/ch32v307/family.c | 160 ++++ hw/bsp/ch32v307/family.mk | 62 ++ hw/bsp/ch32v307/system_ch32v30x.c | 776 ++++++++++++++++++ hw/bsp/ch32v307/system_ch32v30x.h | 30 + hw/mcu/wch/ch32v307 | 1 + src/common/tusb_mcu.h | 4 + .../wch/ch32v307/usb_ch32_usbhs_reg.h | 345 ++++++++ src/portable/wch/ch32v307/usb_dc_usbhs.c | 388 +++++++++ src/tusb_option.h | 3 + 17 files changed, 2410 insertions(+) create mode 100644 hw/bsp/ch32v307/boards/CH32V307V-R1-1v0/board.mk create mode 100644 hw/bsp/ch32v307/boards/CH32V307V-R1-1v0/debug_uart.c create mode 100644 hw/bsp/ch32v307/boards/CH32V307V-R1-1v0/debug_uart.h create mode 100644 hw/bsp/ch32v307/ch32v30x_conf.h create mode 100644 hw/bsp/ch32v307/ch32v30x_it.c create mode 100644 hw/bsp/ch32v307/ch32v30x_it.h create mode 100644 hw/bsp/ch32v307/core_riscv.h create mode 100644 hw/bsp/ch32v307/family.c create mode 100644 hw/bsp/ch32v307/family.mk create mode 100644 hw/bsp/ch32v307/system_ch32v30x.c create mode 100644 hw/bsp/ch32v307/system_ch32v30x.h create mode 160000 hw/mcu/wch/ch32v307 create mode 100644 src/portable/wch/ch32v307/usb_ch32_usbhs_reg.h create mode 100644 src/portable/wch/ch32v307/usb_dc_usbhs.c diff --git a/.gitmodules b/.gitmodules index 21bbf08c0..fd2b75cb8 100644 --- a/.gitmodules +++ b/.gitmodules @@ -146,3 +146,6 @@ [submodule "hw/mcu/allwinner"] path = hw/mcu/allwinner url = https://github.com/hathach/allwinner_driver.git +[submodule "hw/mcu/wch/ch32v307"] + path = hw/mcu/wch/ch32v307 + url = https://github.com/openwch/ch32v307.git diff --git a/hw/bsp/ch32v307/boards/CH32V307V-R1-1v0/board.mk b/hw/bsp/ch32v307/boards/CH32V307V-R1-1v0/board.mk new file mode 100644 index 000000000..f71def2c7 --- /dev/null +++ b/hw/bsp/ch32v307/boards/CH32V307V-R1-1v0/board.mk @@ -0,0 +1,3 @@ +LINKER_SCRIPTS = $(CH32V307_SDK_SRC)/Ld + +LD_FILE = $(LINKER_SCRIPTS)/Link.ld # CH32V307 diff --git a/hw/bsp/ch32v307/boards/CH32V307V-R1-1v0/debug_uart.c b/hw/bsp/ch32v307/boards/CH32V307V-R1-1v0/debug_uart.c new file mode 100644 index 000000000..416782d0e --- /dev/null +++ b/hw/bsp/ch32v307/boards/CH32V307V-R1-1v0/debug_uart.c @@ -0,0 +1,110 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2022 Greg Davill + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +#include "debug_uart.h" +#include + + +#define UART_RINGBUFFER_SIZE_TX 64 +#define UART_RINGBUFFER_MASK_TX (UART_RINGBUFFER_SIZE_TX-1) + +static char tx_buf[UART_RINGBUFFER_SIZE_TX]; +static unsigned int tx_produce; +static volatile unsigned int tx_consume; + +void USART1_IRQHandler(void) __attribute__((naked)); +void USART1_IRQHandler(void) { + __asm volatile ("call USART1_IRQHandler_impl; mret"); +} + +__attribute__((used)) void USART1_IRQHandler_impl(void) +{ + if(USART_GetITStatus(USART1, USART_IT_TC) != RESET) + { + USART_ClearITPendingBit(USART1, USART_IT_TC); + + if(tx_consume != tx_produce) { + USART_SendData(USART1, tx_buf[tx_consume]); + tx_consume = (tx_consume + 1) & UART_RINGBUFFER_MASK_TX; + } + } + +} + +void uart_write(char c) +{ + unsigned int tx_produce_next = (tx_produce + 1) & UART_RINGBUFFER_MASK_TX; + + NVIC_DisableIRQ(USART1_IRQn); + if((tx_consume != tx_produce) || (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET)) { + tx_buf[tx_produce] = c; + tx_produce = tx_produce_next; + } else { + USART_SendData(USART1, c); + } + NVIC_EnableIRQ(USART1_IRQn); +} + + +void uart_sync(void) +{ + while(tx_consume != tx_produce); +} + + +void USART_Printf_Init(uint32_t baudrate) +{ + GPIO_InitTypeDef GPIO_InitStructure; + USART_InitTypeDef USART_InitStructure; + + tx_produce = 0; + tx_consume = 0; + + RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE); + + GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; + GPIO_Init(GPIOA, &GPIO_InitStructure); + + USART_InitStructure.USART_BaudRate = baudrate; + USART_InitStructure.USART_WordLength = USART_WordLength_8b; + USART_InitStructure.USART_StopBits = USART_StopBits_1; + USART_InitStructure.USART_Parity = USART_Parity_No; + USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; + USART_InitStructure.USART_Mode = USART_Mode_Tx; + + USART_Init(USART1, &USART_InitStructure); + USART_ITConfig(USART1, USART_IT_TC, ENABLE); + USART_Cmd(USART1, ENABLE); + + NVIC_InitTypeDef NVIC_InitStructure = {0}; + NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; + NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; + NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; + NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; + NVIC_Init(&NVIC_InitStructure); +} diff --git a/hw/bsp/ch32v307/boards/CH32V307V-R1-1v0/debug_uart.h b/hw/bsp/ch32v307/boards/CH32V307V-R1-1v0/debug_uart.h new file mode 100644 index 000000000..4348438bb --- /dev/null +++ b/hw/bsp/ch32v307/boards/CH32V307V-R1-1v0/debug_uart.h @@ -0,0 +1,31 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2022 Greg Davill + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +#include + +void uart_write(char c); +void uart_sync(void); +void USART_Printf_Init(uint32_t baudrate); diff --git a/hw/bsp/ch32v307/ch32v30x_conf.h b/hw/bsp/ch32v307/ch32v30x_conf.h new file mode 100644 index 000000000..399feaf68 --- /dev/null +++ b/hw/bsp/ch32v307/ch32v30x_conf.h @@ -0,0 +1,43 @@ +/********************************** (C) COPYRIGHT ******************************* +* File Name : ch32v30x_conf.h +* Author : WCH +* Version : V1.0.0 +* Date : 2021/06/06 +* Description : Library configuration file. +* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd. +* SPDX-License-Identifier: Apache-2.0 +*******************************************************************************/ +#ifndef __CH32V30x_CONF_H +#define __CH32V30x_CONF_H + +#include "ch32v30x_adc.h" +#include "ch32v30x_bkp.h" +#include "ch32v30x_can.h" +#include "ch32v30x_crc.h" +#include "ch32v30x_dac.h" +#include "ch32v30x_dbgmcu.h" +#include "ch32v30x_dma.h" +#include "ch32v30x_exti.h" +#include "ch32v30x_flash.h" +#include "ch32v30x_fsmc.h" +#include "ch32v30x_gpio.h" +#include "ch32v30x_i2c.h" +#include "ch32v30x_iwdg.h" +#include "ch32v30x_pwr.h" +#include "ch32v30x_rcc.h" +#include "ch32v30x_rtc.h" +#include "ch32v30x_sdio.h" +#include "ch32v30x_spi.h" +#include "ch32v30x_tim.h" +#include "ch32v30x_usart.h" +#include "ch32v30x_wwdg.h" +#include "ch32v30x_it.h" +#include "ch32v30x_misc.h" + + +#endif /* __CH32V30x_CONF_H */ + + + + + diff --git a/hw/bsp/ch32v307/ch32v30x_it.c b/hw/bsp/ch32v307/ch32v30x_it.c new file mode 100644 index 000000000..d348dd989 --- /dev/null +++ b/hw/bsp/ch32v307/ch32v30x_it.c @@ -0,0 +1,49 @@ +/********************************** (C) COPYRIGHT ******************************* +* File Name : ch32v30x_it.c +* Author : WCH +* Version : V1.0.0 +* Date : 2021/06/06 +* Description : Main Interrupt Service Routines. +* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd. +* SPDX-License-Identifier: Apache-2.0 +*******************************************************************************/ +#include "ch32v30x_it.h" + +void NMI_Handler(void) __attribute__((naked)); +void HardFault_Handler(void) __attribute__((naked)); + +/********************************************************************* + * @fn NMI_Handler + * + * @brief This function handles NMI exception. + * + * @return none + */ +void NMI_Handle(void){ + __asm volatile ("call NMI_Handler_impl; mret"); +} + +__attribute__((used)) void NMI_Handler_impl(void) +{ + +} + +/********************************************************************* + * @fn HardFault_Handler + * + * @brief This function handles Hard Fault exception. + * + * @return none + */ +void HardFault_Handler(void){ + __asm volatile ("call HardFault_Handler_impl; mret"); +} + +__attribute__((used)) void HardFault_Handler_impl(void) +{ + while (1) + { + } +} + + diff --git a/hw/bsp/ch32v307/ch32v30x_it.h b/hw/bsp/ch32v307/ch32v30x_it.h new file mode 100644 index 000000000..6475c5f11 --- /dev/null +++ b/hw/bsp/ch32v307/ch32v30x_it.h @@ -0,0 +1,18 @@ +/********************************** (C) COPYRIGHT ******************************* +* File Name : ch32v30x_it.h +* Author : WCH +* Version : V1.0.0 +* Date : 2021/06/06 +* Description : This file contains the headers of the interrupt handlers. +* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd. +* SPDX-License-Identifier: Apache-2.0 +*******************************************************************************/ +#ifndef __CH32V30x_IT_H +#define __CH32V30x_IT_H + +#include "debug.h" + + +#endif /* __CH32V30x_IT_H */ + + diff --git a/hw/bsp/ch32v307/core_riscv.h b/hw/bsp/ch32v307/core_riscv.h new file mode 100644 index 000000000..2e94ec683 --- /dev/null +++ b/hw/bsp/ch32v307/core_riscv.h @@ -0,0 +1,384 @@ +/********************************** (C) COPYRIGHT ******************************* +* File Name : core_riscv.h +* Author : WCH +* Version : V1.0.0 +* Date : 2021/06/06 +* Description : RISC-V Core Peripheral Access Layer Header File for CH32V30x +* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd. +* SPDX-License-Identifier: Apache-2.0 +*******************************************************************************/ +#ifndef __CORE_RISCV_H__ +#define __CORE_RISCV_H__ + +/* IO definitions */ +#ifdef __cplusplus + #define __I volatile /* defines 'read only' permissions */ +#else + #define __I volatile const /* defines 'read only' permissions */ +#endif +#define __O volatile /* defines 'write only' permissions */ +#define __IO volatile /* defines 'read / write' permissions */ + +/* Standard Peripheral Library old types (maintained for legacy purpose) */ +typedef __I uint64_t vuc64; /* Read Only */ +typedef __I uint32_t vuc32; /* Read Only */ +typedef __I uint16_t vuc16; /* Read Only */ +typedef __I uint8_t vuc8; /* Read Only */ + +typedef const uint64_t uc64; /* Read Only */ +typedef const uint32_t uc32; /* Read Only */ +typedef const uint16_t uc16; /* Read Only */ +typedef const uint8_t uc8; /* Read Only */ + +typedef __I int64_t vsc64; /* Read Only */ +typedef __I int32_t vsc32; /* Read Only */ +typedef __I int16_t vsc16; /* Read Only */ +typedef __I int8_t vsc8; /* Read Only */ + +typedef const int64_t sc64; /* Read Only */ +typedef const int32_t sc32; /* Read Only */ +typedef const int16_t sc16; /* Read Only */ +typedef const int8_t sc8; /* Read Only */ + +typedef __IO uint64_t vu64; +typedef __IO uint32_t vu32; +typedef __IO uint16_t vu16; +typedef __IO uint8_t vu8; + +typedef uint64_t u64; +typedef uint32_t u32; +typedef uint16_t u16; +typedef uint8_t u8; + +typedef __IO int64_t vs64; +typedef __IO int32_t vs32; +typedef __IO int16_t vs16; +typedef __IO int8_t vs8; + +typedef int64_t s64; +typedef int32_t s32; +typedef int16_t s16; +typedef int8_t s8; + +typedef enum {ERROR = 0, SUCCESS = !ERROR} ErrorStatus; + +typedef enum {DISABLE = 0, ENABLE = !DISABLE} FunctionalState; + +typedef enum {RESET = 0, SET = !RESET} FlagStatus, ITStatus; + +#define RV_STATIC_INLINE static inline + +/* memory mapped structure for Program Fast Interrupt Controller (PFIC) */ +typedef struct{ + __I uint32_t ISR[8]; + __I uint32_t IPR[8]; + __IO uint32_t ITHRESDR; + __IO uint32_t RESERVED; + __IO uint32_t CFGR; + __I uint32_t GISR; + uint8_t VTFIDR[4]; + uint8_t RESERVED0[12]; + __IO uint32_t VTFADDR[4]; + uint8_t RESERVED1[0x90]; + __O uint32_t IENR[8]; + uint8_t RESERVED2[0x60]; + __O uint32_t IRER[8]; + uint8_t RESERVED3[0x60]; + __O uint32_t IPSR[8]; + uint8_t RESERVED4[0x60]; + __O uint32_t IPRR[8]; + uint8_t RESERVED5[0x60]; + __IO uint32_t IACTR[8]; + uint8_t RESERVED6[0xE0]; + __IO uint8_t IPRIOR[256]; + uint8_t RESERVED7[0x810]; + __IO uint32_t SCTLR; +}PFIC_Type; + +/* memory mapped structure for SysTick */ +typedef struct +{ + __IO u32 CTLR; + __IO u32 SR; + __IO u64 CNT; + __IO u64 CMP; +}SysTick_Type; + + +#define PFIC ((PFIC_Type *) 0xE000E000 ) +#define NVIC PFIC +#define NVIC_KEY1 ((uint32_t)0xFA050000) +#define NVIC_KEY2 ((uint32_t)0xBCAF0000) +#define NVIC_KEY3 ((uint32_t)0xBEEF0000) + +#define SysTick ((SysTick_Type *) 0xE000F000) + + +/********************************************************************* + * @fn __enable_irq + * + * @brief Enable Global Interrupt + * + * @return none + */ +RV_STATIC_INLINE void __enable_irq(void) +{ + __asm volatile ("csrw 0x800, %0" : : "r" (0x6088) ); +} + +/********************************************************************* + * @fn __disable_irq + * + * @brief Disable Global Interrupt + * + * @return none + */ +RV_STATIC_INLINE void __disable_irq(void) +{ + __asm volatile ("csrw 0x800, %0" : : "r" (0x6000) ); +} + +/********************************************************************* + * @fn __NOP + * + * @brief nop + * + * @return none + */ +RV_STATIC_INLINE void __NOP(void) +{ + __asm volatile ("nop"); +} + +/********************************************************************* + * @fn NVIC_EnableIRQ + * + * @brief Enable Interrupt + * + * @param IRQn: Interrupt Numbers + * + * @return none + */ +RV_STATIC_INLINE void NVIC_EnableIRQ(IRQn_Type IRQn) +{ + NVIC->IENR[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F)); +} + +/********************************************************************* + * @fn NVIC_DisableIRQ + * + * @brief Disable Interrupt + * + * @param IRQn: Interrupt Numbers + * + * @return none + */ +RV_STATIC_INLINE void NVIC_DisableIRQ(IRQn_Type IRQn) +{ + NVIC->IRER[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F)); +} + +/********************************************************************* + * @fn NVIC_GetStatusIRQ + * + * @brief Get Interrupt Enable State + * + * @param IRQn: Interrupt Numbers + * + * @return 1 - Interrupt Enable + * 0 - Interrupt Disable + */ +RV_STATIC_INLINE uint32_t NVIC_GetStatusIRQ(IRQn_Type IRQn) +{ + return((uint32_t) ((NVIC->ISR[(uint32_t)(IRQn) >> 5] & (1 << ((uint32_t)(IRQn) & 0x1F)))?1:0)); +} + +/********************************************************************* + * @fn NVIC_GetPendingIRQ + * + * @brief Get Interrupt Pending State + * + * @param IRQn: Interrupt Numbers + * + * @return 1 - Interrupt Pending Enable + * 0 - Interrupt Pending Disable + */ +RV_STATIC_INLINE uint32_t NVIC_GetPendingIRQ(IRQn_Type IRQn) +{ + return((uint32_t) ((NVIC->IPR[(uint32_t)(IRQn) >> 5] & (1 << ((uint32_t)(IRQn) & 0x1F)))?1:0)); +} + +/********************************************************************* + * @fn NVIC_SetPendingIRQ + * + * @brief Set Interrupt Pending + * + * @param IRQn: Interrupt Numbers + * + * @return None + */ +RV_STATIC_INLINE void NVIC_SetPendingIRQ(IRQn_Type IRQn) +{ + NVIC->IPSR[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F)); +} + +/********************************************************************* + * @fn NVIC_ClearPendingIRQ + * + * @brief Clear Interrupt Pending + * + * @param IRQn: Interrupt Numbers + * + * @return None + */ +RV_STATIC_INLINE void NVIC_ClearPendingIRQ(IRQn_Type IRQn) +{ + NVIC->IPRR[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F)); +} + +/********************************************************************* + * @fn NVIC_GetActive + * + * @brief Get Interrupt Active State + * + * @param IRQn: Interrupt Numbers + * + * @return 1 - Interrupt Active + * 0 - Interrupt No Active + */ +RV_STATIC_INLINE uint32_t NVIC_GetActive(IRQn_Type IRQn) +{ + return((uint32_t)((NVIC->IACTR[(uint32_t)(IRQn) >> 5] & (1 << ((uint32_t)(IRQn) & 0x1F)))?1:0)); +} + +/********************************************************************* + * @fn NVIC_SetPriority + * + * @brief Set Interrupt Priority + * + * @param IRQn - Interrupt Numbers + * priority - + * bit7 - pre-emption priority + * bit6~bit4 - subpriority + * @return None + */ +RV_STATIC_INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint8_t priority) +{ + NVIC->IPRIOR[(uint32_t)(IRQn)] = priority; +} + +/********************************************************************* + * @fn __WFI + * + * @brief Wait for Interrupt + * + * @return None + */ +__attribute__( ( always_inline ) ) RV_STATIC_INLINE void __WFI(void) +{ + NVIC->SCTLR &= ~(1<<3); // wfi + asm volatile ("wfi"); +} + +/********************************************************************* + * @fn __WFE + * + * @brief Wait for Events + * + * @return None + */ +__attribute__( ( always_inline ) ) RV_STATIC_INLINE void __WFE(void) +{ + uint32_t t; + + t = NVIC->SCTLR; + NVIC->SCTLR |= (1<<3)|(1<<5); // (wfi->wfe)+(__sev) + NVIC->SCTLR = (NVIC->SCTLR & ~(1<<5)) | ( t & (1<<5)); + asm volatile ("wfi"); + asm volatile ("wfi"); +} + +/********************************************************************* + * @fn SetVTFIRQ + * + * @brief Set VTF Interrupt + * + * @param add - VTF interrupt service function base address. + * IRQn -Interrupt Numbers + * num - VTF Interrupt Numbers + * NewState - DISABLE or ENABLE + * @return None + */ +RV_STATIC_INLINE void SetVTFIRQ(uint32_t addr, IRQn_Type IRQn, uint8_t num, FunctionalState NewState){ + if(num > 3) return ; + + if (NewState != DISABLE) + { + NVIC->VTFIDR[num] = IRQn; + NVIC->VTFADDR[num] = ((addr&0xFFFFFFFE)|0x1); + } + else{ + NVIC->VTFIDR[num] = IRQn; + NVIC->VTFADDR[num] = ((addr&0xFFFFFFFE)&(~0x1)); + } +} + +/********************************************************************* + * @fn NVIC_SystemReset + * + * @brief Initiate a system reset request + * + * @return None + */ +RV_STATIC_INLINE void NVIC_SystemReset(void) +{ + NVIC->CFGR = NVIC_KEY3|(1<<7); +} + + +/* Core_Exported_Functions */ +extern uint32_t __get_FFLAGS(void); +extern void __set_FFLAGS(uint32_t value); +extern uint32_t __get_FRM(void); +extern void __set_FRM(uint32_t value); +extern uint32_t __get_FCSR(void); +extern void __set_FCSR(uint32_t value); +extern uint32_t __get_MSTATUS(void); +extern void __set_MSTATUS(uint32_t value); +extern uint32_t __get_MISA(void); +extern void __set_MISA(uint32_t value); +extern uint32_t __get_MIE(void); +extern void __set_MIE(uint32_t value); +extern uint32_t __get_MTVEC(void); +extern void __set_MTVEC(uint32_t value); +extern uint32_t __get_MSCRATCH(void); +extern void __set_MSCRATCH(uint32_t value); +extern uint32_t __get_MEPC(void); +extern void __set_MEPC(uint32_t value); +extern uint32_t __get_MCAUSE(void); +extern void __set_MCAUSE(uint32_t value); +extern uint32_t __get_MTVAL(void); +extern void __set_MTVAL(uint32_t value); +extern uint32_t __get_MIP(void); +extern void __set_MIP(uint32_t value); +extern uint32_t __get_MCYCLE(void); +extern void __set_MCYCLE(uint32_t value); +extern uint32_t __get_MCYCLEH(void); +extern void __set_MCYCLEH(uint32_t value); +extern uint32_t __get_MINSTRET(void); +extern void __set_MINSTRET(uint32_t value); +extern uint32_t __get_MINSTRETH(void); +extern void __set_MINSTRETH(uint32_t value); +extern uint32_t __get_MVENDORID(void); +extern uint32_t __get_MARCHID(void); +extern uint32_t __get_MIMPID(void); +extern uint32_t __get_MHARTID(void); +extern uint32_t __get_SP(void); + + +#endif + + + + + diff --git a/hw/bsp/ch32v307/family.c b/hw/bsp/ch32v307/family.c new file mode 100644 index 000000000..ea1c252c4 --- /dev/null +++ b/hw/bsp/ch32v307/family.c @@ -0,0 +1,160 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2022 Greg Davill + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +#include "stdio.h" +#include "debug_uart.h" +#include "ch32v30x.h" + +#include "../board.h" + +//--------------------------------------------------------------------+ +// Forward USB interrupt events to TinyUSB IRQ Handler +//--------------------------------------------------------------------+ + +void USBHS_IRQHandler(void) __attribute__((naked)); +void USBHS_IRQHandler(void) { + __asm volatile ("call USBHS_IRQHandler_impl; mret"); +} + +__attribute__ ((used)) void USBHS_IRQHandler_impl(void) { + tud_int_handler(0); +} + +//--------------------------------------------------------------------+ +// MACRO TYPEDEF CONSTANT ENUM +//--------------------------------------------------------------------+ + +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; +} + +void board_init(void) { + + /* Disable interrupts during init */ + __disable_irq(); + + +#if CFG_TUSB_OS == OPT_OS_NONE + SysTick_Config(SystemCoreClock / 1000); +#endif + + USART_Printf_Init(115200); + + RCC_USBCLK48MConfig(RCC_USBCLK48MCLKSource_USBPHY); + RCC_USBHSPLLCLKConfig(RCC_HSBHSPLLCLKSource_HSE); + RCC_USBHSConfig(RCC_USBPLL_Div2); + RCC_USBHSPLLCKREFCLKConfig(RCC_USBHSPLLCKREFCLK_4M); + RCC_USBHSPHYPLLALIVEcmd(ENABLE); + RCC_AHBPeriphClockCmd(RCC_AHBPeriph_USBHS, ENABLE); + + GPIO_InitTypeDef GPIO_InitStructure = {0}; + + RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE); + GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; + GPIO_Init(GPIOC, &GPIO_InitStructure); + + /* Enable interrupts globaly */ + __enable_irq(); + + board_delay(2); +} + +#if CFG_TUSB_OS == OPT_OS_NONE + +volatile uint32_t system_ticks = 0; + +/* Small workaround to support HW stack save/restore */ +void SysTick_Handler(void) __attribute__((naked)); +void SysTick_Handler(void) { + __asm volatile ("call SysTick_Handler_impl; mret"); +} + +__attribute__((used)) void SysTick_Handler_impl(void) { + SysTick->SR=0; + system_ticks++; +} + +uint32_t board_millis(void) { return system_ticks; } + +#endif + +//--------------------------------------------------------------------+ +// Board porting API +//--------------------------------------------------------------------+ + +void board_led_write(bool state) { + (void) state; + + GPIO_WriteBit(GPIOC, GPIO_Pin_0, state); +} + +uint32_t board_button_read(void) { + return false; +} + +int board_uart_read(uint8_t* buf, int len) { + (void)buf; + (void)len; + return 0; +} + +int board_uart_write(void const* buf, int len) { + int txsize = len; + while (txsize--) { + uart_write(*(uint8_t const*)buf); + buf++; + } + return len; +} + + + +#ifdef USE_FULL_ASSERT +/** + * @brief Reports the name of the source file and the source line number + * where the assert_param error has occurred. + * @param file: pointer to the source file name + * @param line: assert_param error line source number + * @retval None + */ +void assert_failed(char* file, uint32_t line) { + /* USER CODE BEGIN 6 */ + /* User can add his own implementation to report the file name and line + number, + tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) + */ + /* USER CODE END 6 */ +} +#endif /* USE_FULL_ASSERT */ diff --git a/hw/bsp/ch32v307/family.mk b/hw/bsp/ch32v307/family.mk new file mode 100644 index 000000000..dfb4853d9 --- /dev/null +++ b/hw/bsp/ch32v307/family.mk @@ -0,0 +1,62 @@ +# https://www.embecosm.com/resources/tool-chain-downloads/#riscv-stable +#CROSS_COMPILE ?= riscv32-unknown-elf- + +# Toolchain from https://github.com/xpack-dev-tools/riscv-none-embed-gcc-xpack +CROSS_COMPILE ?= riscv-none-embed- + +# Submodules +CH32V307_SDK = hw/mcu/wch/ch32v307 +DEPS_SUBMODULES += $(CH32V307_SDK) + +# WCH-SDK paths +CH32V307_SDK_SRC = $(CH32V307_SDK)/EVT/EXAM/SRC +CH32V307_SDK_SRC_TOP = $(TOP)/$(CH32V307_SDK_SRC) +CH32V307_STARTUP_ASM = $(CH32V307_SDK_SRC)/Startup + +include $(TOP)/$(BOARD_PATH)/board.mk + +SKIP_NANOLIB = 1 + +CFLAGS += \ + -flto \ + -march=rv32imac \ + -mabi=ilp32 \ + -msmall-data-limit=8 \ + -mno-save-restore -Os \ + -fmessage-length=0 \ + -fsigned-char \ + -ffunction-sections \ + -fdata-sections \ + -nostdlib -nostartfiles \ + -DCFG_TUSB_MCU=OPT_MCU_CH32VF307 \ + -Xlinker --gc-sections \ + -DBOARD_DEVICE_RHPORT_SPEED=OPT_MODE_HIGH_SPEED + +LDFLAGS += \ + -Xlinker --gc-sections --specs=nano.specs --specs=nosys.specs + +SRC_C += \ + src/portable/wch/ch32v307/usb_dc_usbhs.c \ + $(CH32V307_SDK_SRC_TOP)/Core/core_riscv.c \ + $(CH32V307_SDK_SRC_TOP)/Peripheral/src/ch32v30x_gpio.c \ + $(CH32V307_SDK_SRC_TOP)/Peripheral/src/ch32v30x_misc.c \ + $(CH32V307_SDK_SRC_TOP)/Peripheral/src/ch32v30x_rcc.c \ + $(CH32V307_SDK_SRC_TOP)/Peripheral/src/ch32v30x_usart.c + +SRC_S += \ + $(CH32V307_STARTUP_ASM)/startup_ch32v30x_D8C.S + +INC += \ + src/portable/wch/ch32v307 \ + $(TOP)/$(BOARD_PATH)/.. \ + $(TOP)/$(BOARD_PATH) \ + $(CH32V307_SDK_SRC_TOP)/Peripheral/inc \ + $(CH32V307_SDK_SRC_TOP)/Debug \ + $(CH32V307_SDK_SRC_TOP) + +# For freeRTOS port source +FREERTOS_PORT = RISC-V + +# flash target ROM bootloader +flash: $(BUILD)/$(PROJECT).elf + openocd -f wch-riscv.cfg -c init -c halt -c "program $< 0x08000000" -c reset -c exit diff --git a/hw/bsp/ch32v307/system_ch32v30x.c b/hw/bsp/ch32v307/system_ch32v30x.c new file mode 100644 index 000000000..12b18d7b8 --- /dev/null +++ b/hw/bsp/ch32v307/system_ch32v30x.c @@ -0,0 +1,776 @@ +/********************************** (C) COPYRIGHT ******************************* +* File Name : system_ch32v30x.c +* Author : WCH +* Version : V1.0.0 +* Date : 2021/06/06 +* Description : CH32V30x Device Peripheral Access Layer System Source File. +* For HSE = 8Mhz +* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd. +* SPDX-License-Identifier: Apache-2.0 +*********************************************************************************/ +#include "ch32v30x.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_24MHz 24000000 */ +//#define SYSCLK_FREQ_48MHz 48000000 +/* #define SYSCLK_FREQ_56MHz 56000000 */ +//#define SYSCLK_FREQ_72MHz 72000000 +//#define SYSCLK_FREQ_96MHz 96000000 +//#define SYSCLK_FREQ_120MHz 120000000 +#define SYSCLK_FREQ_144MHz 144000000 + +/* Clock Definitions */ +#ifdef SYSCLK_FREQ_HSE + uint32_t SystemCoreClock = SYSCLK_FREQ_HSE; /* System Clock Frequency (Core Clock) */ +#elif defined SYSCLK_FREQ_24MHz + uint32_t SystemCoreClock = SYSCLK_FREQ_24MHz; /* System Clock Frequency (Core Clock) */ +#elif defined SYSCLK_FREQ_48MHz + uint32_t SystemCoreClock = SYSCLK_FREQ_48MHz; /* System Clock Frequency (Core Clock) */ +#elif defined SYSCLK_FREQ_56MHz + uint32_t SystemCoreClock = SYSCLK_FREQ_56MHz; /* System Clock Frequency (Core Clock) */ +#elif defined SYSCLK_FREQ_72MHz + uint32_t SystemCoreClock = SYSCLK_FREQ_72MHz; /* System Clock Frequency (Core Clock) */ + +#elif defined SYSCLK_FREQ_96MHz + uint32_t SystemCoreClock = SYSCLK_FREQ_96MHz; /* System Clock Frequency (Core Clock) */ +#elif defined SYSCLK_FREQ_120MHz + uint32_t SystemCoreClock = SYSCLK_FREQ_120MHz; /* System Clock Frequency (Core Clock) */ +#elif defined SYSCLK_FREQ_144MHz + uint32_t SystemCoreClock = SYSCLK_FREQ_144MHz; /* System Clock Frequency (Core Clock) */ + +#else /* HSI Selected as System Clock source */ + 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}; + + +/* system_private_function_proto_types */ +static void SetSysClock(void); + +#ifdef SYSCLK_FREQ_HSE + static void SetSysClockToHSE(void); +#elif defined SYSCLK_FREQ_24MHz + static void SetSysClockTo24(void); +#elif defined SYSCLK_FREQ_48MHz + static void SetSysClockTo48(void); +#elif defined SYSCLK_FREQ_56MHz + static void SetSysClockTo56(void); +#elif defined SYSCLK_FREQ_72MHz + static void SetSysClockTo72(void); + +#elif defined SYSCLK_FREQ_96MHz + static void SetSysClockTo96(void); +#elif defined SYSCLK_FREQ_120MHz + static void SetSysClockTo120(void); +#elif defined SYSCLK_FREQ_144MHz + static void SetSysClockTo144(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; + +#ifdef CH32V30x_D8C + RCC->CFGR0 &= (uint32_t)0xF8FF0000; +#else + RCC->CFGR0 &= (uint32_t)0xF0FF0000; +#endif + + RCC->CTLR &= (uint32_t)0xFEF6FFFF; + RCC->CTLR &= (uint32_t)0xFFFBFFFF; + RCC->CFGR0 &= (uint32_t)0xFF80FFFF; + +#ifdef CH32V30x_D8C + RCC->CTLR &= (uint32_t)0xEBFFFFFF; + RCC->INTR = 0x00FF0000; + RCC->CFGR2 = 0x00000000; +#else + RCC->INTR = 0x009F0000; +#endif + 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, Pll_6_5 = 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; + +#ifdef CH32V30x_D8 + if(pllmull == 17) pllmull = 18; +#else + if(pllmull == 2) pllmull = 18; + if(pllmull == 15){ + pllmull = 13; /* *6.5 */ + Pll_6_5 = 1; + } + if(pllmull == 16) pllmull = 15; + if(pllmull == 17) pllmull = 16; +#endif + + if (pllsource == 0x00) + { + SystemCoreClock = (HSI_VALUE >> 1) * pllmull; + } + else + { + if ((RCC->CFGR0 & RCC_PLLXTPRE) != (uint32_t)RESET) + { + SystemCoreClock = (HSE_VALUE >> 1) * pllmull; + } + else + { + SystemCoreClock = HSE_VALUE * pllmull; + } + } + + if(Pll_6_5 == 1) SystemCoreClock = (SystemCoreClock / 2); + + 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) +{ +#ifdef SYSCLK_FREQ_HSE + SetSysClockToHSE(); +#elif defined SYSCLK_FREQ_24MHz + SetSysClockTo24(); +#elif defined SYSCLK_FREQ_48MHz + SetSysClockTo48(); +#elif defined SYSCLK_FREQ_56MHz + SetSysClockTo56(); +#elif defined SYSCLK_FREQ_72MHz + SetSysClockTo72(); +#elif defined SYSCLK_FREQ_96MHz + SetSysClockTo96(); +#elif defined SYSCLK_FREQ_120MHz + SetSysClockTo120(); +#elif defined SYSCLK_FREQ_144MHz + SetSysClockTo144(); + +#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) + { + /* 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_24MHz + +/********************************************************************* + * @fn SetSysClockTo24 + * + * @brief Sets System clock frequency to 24MHz and configure HCLK, PCLK2 and PCLK1 prescalers. + * + * @return none + */ +static void SetSysClockTo24(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) + { + /* 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; + + RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_PLLSRC | RCC_PLLXTPRE | RCC_PLLMULL)); + +#ifdef CH32V30x_D8 + RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSE | RCC_PLLXTPRE_HSE | RCC_PLLMULL3); +#else + RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSE | RCC_PLLXTPRE_HSE | RCC_PLLMULL3_EXTEN); +#endif + /* 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 + +/********************************************************************* + * @fn SetSysClockTo48 + * + * @brief Sets System clock frequency to 48MHz and configure HCLK, PCLK2 and PCLK1 prescalers. + * + * @return none + */ +static void SetSysClockTo48(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) + { + /* 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)); + +#ifdef CH32V30x_D8 + RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSE | RCC_PLLXTPRE_HSE | RCC_PLLMULL6); +#else + RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSE | RCC_PLLXTPRE_HSE | RCC_PLLMULL6_EXTEN); +#endif + + /* 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 + +/********************************************************************* + * @fn SetSysClockTo56 + * + * @brief Sets System clock frequency to 56MHz and configure HCLK, PCLK2 and PCLK1 prescalers. + * + * @return none + */ +static void SetSysClockTo56(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) + { + /* 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)); + +#ifdef CH32V30x_D8 + RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSE | RCC_PLLXTPRE_HSE | RCC_PLLMULL7); +#else + RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSE | RCC_PLLXTPRE_HSE | RCC_PLLMULL7_EXTEN); +#endif + + /* 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 + +/********************************************************************* + * @fn SetSysClockTo72 + * + * @brief Sets System clock frequency to 72MHz and configure HCLK, PCLK2 and PCLK1 prescalers. + * + * @return none + */ +static void SetSysClockTo72(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) + { + /* 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)); + +#ifdef CH32V30x_D8 + RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSE | RCC_PLLXTPRE_HSE | RCC_PLLMULL9); +#else + RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSE | RCC_PLLXTPRE_HSE | RCC_PLLMULL9_EXTEN); +#endif + + /* 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_96MHz + +/********************************************************************* + * @fn SetSysClockTo96 + * + * @brief Sets System clock frequency to 96MHz and configure HCLK, PCLK2 and PCLK1 prescalers. + * + * @return none + */ +static void SetSysClockTo96(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) + { + /* 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 * 12 = 96 MHz */ + RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_PLLSRC | RCC_PLLXTPRE | + RCC_PLLMULL)); + +#ifdef CH32V30x_D8 + RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSE | RCC_PLLXTPRE_HSE | RCC_PLLMULL12); +#else + RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSE | RCC_PLLXTPRE_HSE | RCC_PLLMULL12_EXTEN); +#endif + + /* 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_120MHz + +/********************************************************************* + * @fn SetSysClockTo120 + * + * @brief Sets System clock frequency to 120MHz and configure HCLK, PCLK2 and PCLK1 prescalers. + * + * @return none + */ +static void SetSysClockTo120(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) + { + /* 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 * 15 = 120 MHz */ + RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_PLLSRC | RCC_PLLXTPRE | + RCC_PLLMULL)); + +#ifdef CH32V30x_D8 + RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSE | RCC_PLLXTPRE_HSE | RCC_PLLMULL15); +#else + RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSE | RCC_PLLXTPRE_HSE | RCC_PLLMULL15_EXTEN); +#endif + + /* 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_144MHz + +/********************************************************************* + * @fn SetSysClockTo144 + * + * @brief Sets System clock frequency to 144MHz and configure HCLK, PCLK2 and PCLK1 prescalers. + * + * @return none + */ +static void SetSysClockTo144(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) + { + /* 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 * 18 = 144 MHz */ + RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_PLLSRC | RCC_PLLXTPRE | + RCC_PLLMULL)); + +#ifdef CH32V30x_D8 + RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSE | RCC_PLLXTPRE_HSE | RCC_PLLMULL18); +#else + RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSE | RCC_PLLXTPRE_HSE | RCC_PLLMULL18_EXTEN); +#endif + + /* 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 + */ + } +} + + +#endif diff --git a/hw/bsp/ch32v307/system_ch32v30x.h b/hw/bsp/ch32v307/system_ch32v30x.h new file mode 100644 index 000000000..0e0ef4e51 --- /dev/null +++ b/hw/bsp/ch32v307/system_ch32v30x.h @@ -0,0 +1,30 @@ +/********************************** (C) COPYRIGHT ******************************* +* File Name : system_ch32v30x.h +* Author : WCH +* Version : V1.0.0 +* Date : 2021/06/06 +* Description : CH32V30x Device Peripheral Access Layer System Header File. +* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd. +* SPDX-License-Identifier: Apache-2.0 +*******************************************************************************/ +#ifndef __SYSTEM_CH32V30x_H +#define __SYSTEM_CH32V30x_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 /*__CH32V30x_SYSTEM_H */ + + + diff --git a/hw/mcu/wch/ch32v307 b/hw/mcu/wch/ch32v307 new file mode 160000 index 000000000..17761f5cf --- /dev/null +++ b/hw/mcu/wch/ch32v307 @@ -0,0 +1 @@ +Subproject commit 17761f5cf9dbbf2dcf665b7c04934188add20082 diff --git a/src/common/tusb_mcu.h b/src/common/tusb_mcu.h index 8eb4ad475..84d629eac 100644 --- a/src/common/tusb_mcu.h +++ b/src/common/tusb_mcu.h @@ -266,6 +266,10 @@ #elif TU_CHECK_MCU(OPT_MCU_F1C100S) #define TUP_DCD_ENDPOINT_MAX 4 +//------------- WCH -------------// +#elif TU_CHECK_MCU(OPT_MCU_CH32VF307) + #define TUP_DCD_ENDPOINT_MAX 8 + #endif //--------------------------------------------------------------------+ diff --git a/src/portable/wch/ch32v307/usb_ch32_usbhs_reg.h b/src/portable/wch/ch32v307/usb_ch32_usbhs_reg.h new file mode 100644 index 000000000..1b7c0e791 --- /dev/null +++ b/src/portable/wch/ch32v307/usb_ch32_usbhs_reg.h @@ -0,0 +1,345 @@ +#ifndef _USB_CH32_USBHS_REG_H +#define _USB_CH32_USBHS_REG_H + +#include + +/******************* GLOBAL ******************/ + +// USB CONTROL +#define USBHS_CONTROL_OFFSET 0x00 +#define USBHS_DMA_EN (1 << 0) +#define USBHS_ALL_CLR (1 << 1) +#define USBHS_FORCE_RST (1 << 2) +#define USBHS_INT_BUSY_EN (1 << 3) +#define USBHS_DEV_PU_EN (1 << 4) +#define USBHS_SPEED_MASK (3 << 5) +#define USBHS_FULL_SPEED (0 << 5) +#define USBHS_HIGH_SPEED (1 << 5) +#define USBHS_LOW_SPEED (2 << 5) +#define USBHS_HOST_MODE (1 << 7) + +// USB_INT_EN +#define USBHS_INT_EN_OFFSET 0x02 +#define USBHS_BUS_RST_EN (1 << 0) +#define USBHS_DETECT_EN (1 << 0) +#define USBHS_TRANSFER_EN (1 << 1) +#define USBHS_SUSPEND_EN (1 << 2) +#define USBHS_SOF_ACT_EN (1 << 3) +#define USBHS_FIFO_OV_EN (1 << 4) +#define USBHS_SETUP_ACT_EN (1 << 5) +#define USBHS_ISO_ACT_EN (1 << 6) +#define USBHS_DEV_NAK_EN (1 << 7) + +// USB DEV AD +#define USBHS_DEV_AD_OFFSET 0x03 +// USB FRAME_NO +#define USBHS_FRAME_NO_OFFSET 0x04 +// USB SUSPEND +#define USBHS_SUSPEND_OFFSET 0x06 +#define USBHS_DEV_REMOTE_WAKEUP (1 << 2) +#define USBHS_LINESTATE_MASK (2 << 4) /* Read Only */ + +// RESERVED0 + +// USB SPEED TYPE +#define USBHS_SPEED_TYPE_OFFSET 0x08 +#define USBSPEED_MASK (0x03) + +// USB_MIS_ST +#define USBHS_MIS_ST_OFFSET 0x09 +#define USBHS_SPLIT_CAN (1 << 0) +#define USBHS_ATTACH (1 << 1) +#define USBHS_SUSPEND (1 << 2) +#define USBHS_BUS_RESET (1 << 3) +#define USBHS_R_FIFO_RDY (1 << 4) +#define USBHS_SIE_FREE (1 << 5) +#define USBHS_SOF_ACT (1 << 6) +#define USBHS_SOF_PRES (1 << 7) + +// INT_FLAG +#define USBHS_INT_FLAG_OFFSET 0x0A +#define USBHS_BUS_RST_FLAG (1 << 0) +#define USBHS_DETECT_FLAG (1 << 0) +#define USBHS_TRANSFER_FLAG (1 << 1) +#define USBHS_SUSPEND_FLAG (1 << 2) +#define USBHS_HST_SOF_FLAG (1 << 3) +#define USBHS_FIFO_OV_FLAG (1 << 4) +#define USBHS_SETUP_FLAG (1 << 5) +#define USBHS_ISO_ACT_FLAG (1 << 6) + +// INT_ST +#define USBHS_INT_ST_OFFSET 0x0B +#define USBHS_DEV_UIS_IS_NAK (1 << 7) +#define USBHS_DEV_UIS_TOG_OK (1 << 6) +#define MASK_UIS_TOKEN (3 << 4) +#define MASK_UIS_ENDP (0x0F) +#define MASK_UIS_H_RES (0x0F) + +#define USBHS_TOGGLE_OK (0x40) +#define USBHS_HOST_RES (0x0f) + +//USB_RX_LEN +#define USBHS_RX_LEN_OFFSET 0x0C +/******************* DEVICE ******************/ + +//UEP_CONFIG +#define USBHS_UEP_CONFIG_OFFSET 0x10 +#define USBHS_EP0_T_EN (1 << 0) +#define USBHS_EP0_R_EN (1 << 16) + +#define USBHS_EP1_T_EN (1 << 1) +#define USBHS_EP1_R_EN (1 << 17) + +#define USBHS_EP2_T_EN (1 << 2) +#define USBHS_EP2_R_EN (1 << 18) + +#define USBHS_EP3_T_EN (1 << 3) +#define USBHS_EP3_R_EN (1 << 19) + +#define USBHS_EP4_T_EN (1 << 4) +#define USBHS_EP4_R_EN (1 << 20) + +#define USBHS_EP5_T_EN (1 << 5) +#define USBHS_EP5_R_EN (1 << 21) + +#define USBHS_EP6_T_EN (1 << 6) +#define USBHS_EP6_R_EN (1 << 22) + +#define USBHS_EP7_T_EN (1 << 7) +#define USBHS_EP7_R_EN (1 << 23) + +#define USBHS_EP8_T_EN (1 << 8) +#define USBHS_EP8_R_EN (1 << 24) + +#define USBHS_EP9_T_EN (1 << 9) +#define USBHS_EP9_R_EN (1 << 25) + +#define USBHS_EP10_T_EN (1 << 10) +#define USBHS_EP10_R_EN (1 << 26) + +#define USBHS_EP11_T_EN (1 << 11) +#define USBHS_EP11_R_EN (1 << 27) + +#define USBHS_EP12_T_EN (1 << 12) +#define USBHS_EP12_R_EN (1 << 28) + +#define USBHS_EP13_T_EN (1 << 13) +#define USBHS_EP13_R_EN (1 << 29) + +#define USBHS_EP14_T_EN (1 << 14) +#define USBHS_EP14_R_EN (1 << 30) + +#define USBHS_EP15_T_EN (1 << 15) +#define USBHS_EP15_R_EN (1 << 31) + +//UEP_TYPE +#define USBHS_UEP_TYPE_OFFSET 0x14 +#define USBHS_EP0_T_TYP (1 << 0) +#define USBHS_EP0_R_TYP (1 << 16) + +#define USBHS_EP1_T_TYP (1 << 1) +#define USBHS_EP1_R_TYP (1 << 17) + +#define USBHS_EP2_T_TYP (1 << 2) +#define USBHS_EP2_R_TYP (1 << 18) + +#define USBHS_EP3_T_TYP (1 << 3) +#define USBHS_EP3_R_TYP (1 << 19) + +#define USBHS_EP4_T_TYP (1 << 4) +#define USBHS_EP4_R_TYP (1 << 20) + +#define USBHS_EP5_T_TYP (1 << 5) +#define USBHS_EP5_R_TYP (1 << 21) + +#define USBHS_EP6_T_TYP (1 << 6) +#define USBHS_EP6_R_TYP (1 << 22) + +#define USBHS_EP7_T_TYP (1 << 7) +#define USBHS_EP7_R_TYP (1 << 23) + +#define USBHS_EP8_T_TYP (1 << 8) +#define USBHS_EP8_R_TYP (1 << 24) + +#define USBHS_EP9_T_TYP (1 << 8) +#define USBHS_EP9_R_TYP (1 << 25) + +#define USBHS_EP10_T_TYP (1 << 10) +#define USBHS_EP10_R_TYP (1 << 26) + +#define USBHS_EP11_T_TYP (1 << 11) +#define USBHS_EP11_R_TYP (1 << 27) + +#define USBHS_EP12_T_TYP (1 << 12) +#define USBHS_EP12_R_TYP (1 << 28) + +#define USBHS_EP13_T_TYP (1 << 13) +#define USBHS_EP13_R_TYP (1 << 29) + +#define USBHS_EP14_T_TYP (1 << 14) +#define USBHS_EP14_R_TYP (1 << 30) + +#define USBHS_EP15_T_TYP (1 << 15) +#define USBHS_EP15_R_TYP (1 << 31) + +/* BUF_MOD UEP1~15 */ +#define USBHS_BUF_MOD_OFFSET 0x18 +#define USBHS_EP0_BUF_MOD (1 << 0) +#define USBHS_EP0_ISO_BUF_MOD (1 << 16) + +#define USBHS_EP1_BUF_MOD (1 << 1) +#define USBHS_EP1_ISO_BUF_MOD (1 << 17) + +#define USBHS_EP2_BUF_MOD (1 << 2) +#define USBHS_EP2_ISO_BUF_MOD (1 << 18) + +#define USBHS_EP3_BUF_MOD (1 << 3) +#define USBHS_EP3_ISO_BUF_MOD (1 << 19) + +#define USBHS_EP4_BUF_MOD (1 << 4) +#define USBHS_EP4_ISO_BUF_MOD (1 << 20) + +#define USBHS_EP5_BUF_MOD (1 << 5) +#define USBHS_EP5_ISO_BUF_MOD (1 << 21) + +#define USBHS_EP6_BUF_MOD (1 << 6) +#define USBHS_EP6_ISO_BUF_MOD (1 << 22) + +#define USBHS_EP7_BUF_MOD (1 << 7) +#define USBHS_EP7_ISO_BUF_MOD (1 << 23) + +#define USBHS_EP8_BUF_MOD (1 << 8) +#define USBHS_EP8_ISO_BUF_MOD (1 << 24) + +#define USBHS_EP9_BUF_MOD (1 << 9) +#define USBHS_EP9_ISO_BUF_MOD (1 << 25) + +#define USBHS_EP10_BUF_MOD (1 << 10) +#define USBHS_EP10_ISO_BUF_MOD (1 << 26) + +#define USBHS_EP11_BUF_MOD (1 << 11) +#define USBHS_EP11_ISO_BUF_MOD (1 << 27) + +#define USBHS_EP12_BUF_MOD (1 << 12) +#define USBHS_EP12_ISO_BUF_MOD (1 << 28) + +#define USBHS_EP13_BUF_MOD (1 << 13) +#define USBHS_EP13_ISO_BUF_MOD (1 << 29) + +#define USBHS_EP14_BUF_MOD (1 << 14) +#define USBHS_EP14_ISO_BUF_MOD (1 << 30) + +#define USBHS_EP15_BUF_MOD (1 << 15) +#define USBHS_EP15_ISO_BUF_MOD (1 << 31) +//USBHS_EPn_T_EN USBHS_EPn_R_EN USBHS_EPn_BUF_MOD 锟斤拷锟斤拷锟斤拷锟斤拷UEPn_DMA为锟斤拷始锟斤拷址锟缴碉拷锟斤拷锟斤拷锟斤拷锟� +// 0 0 x 锟剿点被锟斤拷锟矫o拷未锟矫碉拷UEPn_*_DMA锟斤拷锟斤拷锟斤拷锟斤拷 +// 1 0 0 锟斤拷锟秸o拷OUT锟斤拷锟斤拷锟斤拷锟斤拷锟阶碉拷址为UEPn_RX_DMA +// 1 0 1 bUEPn_RX_TOG[0]=0,使锟矫伙拷锟斤拷锟斤拷UEPn_RX_DMA锟斤拷bUEPn_RX_TOG[0]=1,使锟矫伙拷锟斤拷锟斤拷UEPn_TX_DMA +// 0 1 0 锟斤拷锟斤拷(IN)锟斤拷锟斤拷锟斤拷锟阶碉拷址为UEPn_TX_DMA锟斤拷 +// 0 1 1 bUEPn_TX_TOG[0]=0,使锟矫伙拷锟斤拷锟斤拷UEPn_TX_DMA锟斤拷bUEPn_TX_TOG[0]=1,使锟矫伙拷锟斤拷锟斤拷UEPn_RX_DMA + +/* USB0_DMA */ +#define USBHS_UEP0_DMA_OFFSET(n) (0x1C) // endpoint 0 DMA buffer address + +/* USBX_RX_DMA */ +#define USBHS_UEPx_RX_DMA_OFFSET(n) (0x1C + 4 * (n)) // endpoint x DMA buffer address + +#define USBHS_UEPx_TX_DMA_OFFSET(n) (0x58 + 4 * (n)) // endpoint x DMA buffer address + +#define USBHS_UEPx_MAX_LEN_OFFSET(n) (0x98 + 4 * (n)) // endpoint x DMA buffer address + +#define USBHS_UEPx_T_LEN_OFFSET(n) (0xD8 + 4 * (n)) // endpoint x DMA buffer address +#define USBHS_UEPx_TX_CTRL_OFFSET(n) (0xD8 + 4 * (n) + 2) // endpoint x DMA buffer address +#define USBHS_UEPx_RX_CTRL_OFFSET(n) (0xD8 + 4 * (n) + 3) // endpoint x DMA buffer address + +// UEPn_T_LEN +#define USBHS_EP_T_LEN_MASK (0x7FF) + +//UEPn_TX_CTRL +#define USBHS_EP_T_RES_MASK (3 << 0) +#define USBHS_EP_T_RES_ACK (0 << 0) +#define USBHS_EP_T_RES_NYET (1 << 0) +#define USBHS_EP_T_RES_NAK (2 << 0) +#define USBHS_EP_T_RES_STALL (3 << 0) + +#define USBHS_EP_T_TOG_MASK (3 << 3) +#define USBHS_EP_T_TOG_0 (0 << 3) +#define USBHS_EP_T_TOG_1 (1 << 3) +#define USBHS_EP_T_TOG_2 (2 << 3) +#define USBHS_EP_T_TOG_M (3 << 3) + +#define USBHS_EP_T_AUTOTOG (1 << 5) + +//UEPn_RX_CTRL +#define USBHS_EP_R_RES_MASK (3 << 0) +#define USBHS_EP_R_RES_ACK (0 << 0) +#define USBHS_EP_R_RES_NYET (1 << 0) +#define USBHS_EP_R_RES_NAK (2 << 0) +#define USBHS_EP_R_RES_STALL (3 << 0) + +#define USBHS_EP_R_TOG_MASK (3 << 3) +#define USBHS_EP_R_TOG_0 (0 << 3) +#define USBHS_EP_R_TOG_1 (1 << 3) +#define USBHS_EP_R_TOG_2 (2 << 3) +#define USBHS_EP_R_TOG_M (3 << 3) + +#define USBHS_EP_R_AUTOTOG (1 << 5) + +#define USBHS_TOG_MATCH (1 << 6) + +/******************* HOST ******************/ +// USB HOST_CTRL +#define USBHS_SEND_BUS_RESET (1 << 0) +#define USBHS_SEND_BUS_SUSPEND (1 << 1) +#define USBHS_SEND_BUS_RESUME (1 << 2) +#define USBHS_REMOTE_WAKE (1 << 3) +#define USBHS_PHY_SUSPENDM (1 << 4) +#define USBHS_UH_SOFT_FREE (1 << 6) +#define USBHS_SEND_SOF_EN (1 << 7) + +//UH_CONFIG +#define USBHS_HOST_TX_EN (1 << 3) +#define USBHS_HOST_RX_EN (1 << 18) + +// HOST_EP_TYPE +#define USBHS_ENDP_TX_ISO (1 << 3) +#define USBHS_ENDP_RX_ISO (1 << (16 + 2)) + +// R32_UH_EP_PID +#define USBHS_HOST_MASK_TOKEN (0x0f) +#define USBHS_HOST_MASK_ENDP (0x0f << 4) + +//R8_UH_RX_CTRL +#define USBHS_EP_R_RES_MASK (3 << 0) +#define USBHS_EP_R_RES_ACK (0 << 0) +#define USBHS_EP_R_RES_NYET (1 << 0) +#define USBHS_EP_R_RES_NAK (2 << 0) +#define USBHS_EP_R_RES_STALL (3 << 0) + +#define USBHS_UH_R_RES_NO (1 << 2) +#define USBHS_UH_R_TOG_1 (1 << 3) +#define USBHS_UH_R_TOG_2 (2 << 3) +#define USBHS_UH_R_TOG_3 (3 << 3) +#define USBHS_UH_R_TOG_AUTO (1 << 5) +#define USBHS_UH_R_DATA_NO (1 << 6) +//R8_UH_TX_CTRL +#define USBHS_UH_T_RES_MASK (3 << 0) +#define USBHS_UH_T_RES_ACK (0 << 0) +#define USBHS_UH_T_RES_NYET (1 << 0) +#define USBHS_UH_T_RES_NAK (2 << 0) +#define USBHS_UH_T_RES_STALL (3 << 0) + +#define USBHS_UH_T_RES_NO (1 << 2) +#define USBHS_UH_T_TOG_1 (1 << 3) +#define USBHS_UH_T_TOG_2 (2 << 3) +#define USBHS_UH_T_TOG_3 (3 << 3) +#define USBHS_UH_T_TOG_AUTO (1 << 5) +#define USBHS_UH_T_DATA_NO (1 << 6) + +// 00: OUT, 01:SOF, 10:IN, 11:SETUP +#define PID_OUT 0 +#define PID_SOF 1 +#define PID_IN 2 +#define PID_SETUP 3 + +#endif diff --git a/src/portable/wch/ch32v307/usb_dc_usbhs.c b/src/portable/wch/ch32v307/usb_dc_usbhs.c new file mode 100644 index 000000000..32645dc5f --- /dev/null +++ b/src/portable/wch/ch32v307/usb_dc_usbhs.c @@ -0,0 +1,388 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2022 Greg Davill + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +#include "tusb_option.h" + +#if CFG_TUD_ENABLED && (CFG_TUSB_MCU == OPT_MCU_CH32VF307) +#include "device/dcd.h" + +#include "usb_ch32_usbhs_reg.h" +#include "core_riscv.h" + +// Max number of bi-directional endpoints including EP0 +#define EP_MAX 16 + +typedef struct { + uint8_t *buffer; + // tu_fifo_t * ff; // TODO support dcd_edpt_xfer_fifo API + uint16_t total_len; + uint16_t queued_len; + uint16_t max_size; + bool short_packet; +} xfer_ctl_t; + +#define XFER_CTL_BASE(_ep, _dir) &xfer_status[_ep][_dir] +static xfer_ctl_t xfer_status[EP_MAX][2]; + +#define EP_TX_LEN(ep) *(volatile uint16_t *)((volatile uint16_t *)&(USBHSD->UEP0_TX_LEN) + (ep)*2) +#define EP_TX_CTRL(ep) *(volatile uint8_t *)((volatile uint8_t *)&(USBHSD->UEP0_TX_CTRL) + (ep)*4) +#define EP_RX_CTRL(ep) *(volatile uint8_t *)((volatile uint8_t *)&(USBHSD->UEP0_RX_CTRL) + (ep)*4) +#define EP_RX_MAX_LEN(ep) *(volatile uint16_t *)((volatile uint16_t *)&(USBHSD->UEP0_MAX_LEN) + (ep)*2) + +#define EP_TX_DMA_ADDR(ep) *(volatile uint32_t *)((volatile uint32_t *)&(USBHSD->UEP1_TX_DMA) + (ep - 1)) +#define EP_RX_DMA_ADDR(ep) *(volatile uint32_t *)((volatile uint32_t *)&(USBHSD->UEP1_RX_DMA) + (ep - 1)) + +/* Endpoint Buffer */ +__attribute__((aligned(4))) uint8_t setup[8]; // ep0(64) +__attribute__((aligned(4))) uint8_t EP0_DatabufHD[64]; // ep0(64) + +volatile uint8_t mps_over_flag = 0; +volatile uint8_t USBHS_Dev_Endp0_Tog = 0x01; + +void dcd_init(uint8_t rhport) { + (void)rhport; + + memset(&xfer_status, 0, sizeof(xfer_status)); + + // usb_dc_low_level_init(); + + USBHSD->HOST_CTRL = 0x00; + USBHSD->HOST_CTRL = USBHS_PHY_SUSPENDM; + + USBHSD->CONTROL = 0; +#if 1 + USBHSD->CONTROL = USBHS_DMA_EN | USBHS_INT_BUSY_EN | USBHS_HIGH_SPEED; +#else + USBHSD->CONTROL = USBHS_DMA_EN | USBHS_INT_BUSY_EN | USBHS_FULL_SPEED; +#endif + + USBHSD->INT_EN = 0; + USBHSD->INT_EN = USBHS_SETUP_ACT_EN | USBHS_TRANSFER_EN | USBHS_DETECT_EN | USBHS_SUSPEND_EN; + + /* ALL endpoint enable */ + USBHSD->ENDP_CONFIG = 0xffffffff; + + USBHSD->ENDP_CONFIG = USBHS_EP0_T_EN | USBHS_EP0_R_EN; + USBHSD->ENDP_TYPE = 0x00; + USBHSD->BUF_MODE = 0x00; + + USBHSD->UEP0_MAX_LEN = 64; + + USBHSD->UEP0_DMA = (uint32_t)EP0_DatabufHD; + + USBHSD->UEP0_TX_LEN = 0; + USBHSD->UEP0_TX_CTRL = USBHS_EP_T_RES_NAK; + USBHSD->UEP0_RX_CTRL = USBHS_EP_R_RES_ACK; + + for (int ep = 1; ep < EP_MAX; ep++) { + EP_TX_LEN(ep) = 0; + EP_TX_CTRL(ep) = USBHS_EP_T_AUTOTOG | USBHS_EP_T_RES_NAK; + EP_RX_CTRL(ep) = USBHS_EP_R_AUTOTOG | USBHS_EP_R_RES_NAK; + + EP_RX_MAX_LEN(ep) = 512; + } + + USBHSD->DEV_AD = 0; + USBHSD->CONTROL |= USBHS_DEV_PU_EN; +} + +void dcd_int_enable(uint8_t rhport) { + (void)rhport; + + NVIC_EnableIRQ(USBHS_IRQn); +} + +void dcd_int_disable(uint8_t rhport) { + (void)rhport; + + NVIC_DisableIRQ(USBHS_IRQn); +} + +void dcd_edpt_close_all(uint8_t rhport) { + (void)rhport; +} + +void dcd_set_address(uint8_t rhport, uint8_t dev_addr) { + (void)dev_addr; + + // Response with zlp status + dcd_edpt_xfer(rhport, 0x80, NULL, 0); +} + +void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const *request) { + (void)rhport; + + if (request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_DEVICE && + request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD && + request->bRequest == TUSB_REQ_SET_ADDRESS) { + USBHSD->DEV_AD = (uint8_t)request->wValue; + } + + EP_TX_CTRL(0) = USBHS_EP_T_RES_NAK; + EP_RX_CTRL(0) = USBHS_EP_R_RES_ACK; +} + +bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const *desc_edpt) { + (void)rhport; + + uint8_t const epnum = tu_edpt_number(desc_edpt->bEndpointAddress); + uint8_t const dir = tu_edpt_dir(desc_edpt->bEndpointAddress); + + TU_ASSERT(epnum < EP_MAX); + + xfer_ctl_t *xfer = XFER_CTL_BASE(epnum, dir); + xfer->max_size = tu_edpt_packet_size(desc_edpt); + + if (epnum != 0) { + if (tu_edpt_dir(desc_edpt->bEndpointAddress) == TUSB_DIR_OUT) { + EP_RX_CTRL(epnum) = USBHS_EP_R_AUTOTOG | USBHS_EP_R_RES_ACK; + } else { + EP_TX_LEN(epnum) = 0; + EP_TX_CTRL(epnum) = USBHS_EP_T_AUTOTOG | USBHS_EP_T_RES_NAK | USBHS_EP_T_TOG_0; + } + } + + return true; +} + +int usbd_ep_close(const uint8_t ep) { + (void)ep; + + return 0; +} +void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) { + (void)rhport; + + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + if (epnum == 0) { + if (dir == TUSB_DIR_OUT) { + USBHSD->UEP0_RX_CTRL = USBHS_EP_R_RES_STALL; + } else { + USBHSD->UEP0_TX_LEN = 0; + USBHSD->UEP0_TX_CTRL = USBHS_EP_T_RES_STALL; + } + } else { + if (dir == TUSB_DIR_OUT) { + EP_RX_CTRL(epnum) = (EP_RX_CTRL(epnum) & ~USBHS_EP_R_RES_MASK) | USBHS_EP_R_RES_STALL; + + } else { + EP_TX_CTRL(epnum) = (EP_TX_CTRL(epnum) & ~USBHS_EP_T_RES_MASK) | USBHS_EP_T_RES_STALL; + } + } +} + +void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) { + (void)rhport; + + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + if (epnum == 0) { + if (dir == TUSB_DIR_OUT) { + USBHSD->UEP0_RX_CTRL = USBHS_EP_R_RES_ACK; + } else { + } + } else { + if (dir == TUSB_DIR_OUT) { + EP_RX_CTRL(epnum) = (EP_RX_CTRL(epnum) & ~(USBHS_EP_R_RES_MASK | USBHS_EP_T_TOG_MASK)) | USBHS_EP_T_RES_ACK; + + } else { + EP_TX_CTRL(epnum) = (EP_TX_CTRL(epnum) & ~(USBHS_EP_T_RES_MASK | USBHS_EP_T_TOG_MASK)) | USBHS_EP_T_RES_NAK; + } + } +} + +bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes) { + (void)rhport; + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + xfer_ctl_t *xfer = XFER_CTL_BASE(epnum, dir); + xfer->buffer = buffer; + // xfer->ff = NULL; // TODO support dcd_edpt_xfer_fifo API + xfer->total_len = total_bytes; + xfer->queued_len = 0; + xfer->short_packet = false; + + // uint16_t num_packets = (total_bytes / xfer->max_size); + uint16_t short_packet_size = total_bytes % (xfer->max_size + 1); + + // Zero-size packet is special case. + if (short_packet_size == 0 || (total_bytes == 0)) { + xfer->short_packet = true; + } + + if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN) { + if (!total_bytes) { + xfer->short_packet = true; + if (epnum == 0) { + USBHSD->UEP0_TX_LEN = 0; + USBHSD->UEP0_TX_CTRL = USBHS_EP_T_RES_ACK | (USBHS_Dev_Endp0_Tog ? USBHS_EP_T_TOG_1 : USBHS_EP_T_TOG_0); + USBHS_Dev_Endp0_Tog ^= 1; + } else { + EP_TX_LEN(epnum) = 0; + EP_TX_CTRL(epnum) = (EP_TX_CTRL(epnum) & ~(USBHS_EP_T_RES_MASK)) | USBHS_EP_T_RES_ACK; + } + } else { + if (epnum == 0) { + xfer->queued_len += short_packet_size; + memcpy(&EP0_DatabufHD[0], buffer, short_packet_size); + + USBHSD->UEP0_TX_LEN = short_packet_size; + USBHSD->UEP0_TX_CTRL = USBHS_EP_T_RES_ACK | (USBHS_Dev_Endp0_Tog ? USBHS_EP_T_TOG_1 : USBHS_EP_T_TOG_0); + USBHS_Dev_Endp0_Tog ^= 1; + } else { + xfer->queued_len += short_packet_size; + + EP_TX_DMA_ADDR(epnum) = (uint32_t)buffer; + USBHSD->ENDP_CONFIG |= (USBHS_EP0_T_EN << epnum); + EP_TX_LEN(epnum) = short_packet_size; + EP_TX_CTRL(epnum) = (EP_TX_CTRL(epnum) & ~(USBHS_EP_T_RES_MASK)) | USBHS_EP_T_RES_ACK; + } + } + } else { /* TUSB_DIR_OUT */ + if (epnum == 0) { + uint32_t read_count = USBHSD->RX_LEN; + read_count = TU_MIN(read_count, total_bytes); + + if ((total_bytes == 8)) { + read_count = 8; + memcpy(buffer, &EP0_DatabufHD[0], 8); + } else { + memcpy(buffer, &EP0_DatabufHD[0], read_count); + } + } else { + EP_RX_DMA_ADDR(epnum) = (uint32_t)xfer->buffer; + USBHSD->ENDP_CONFIG |= (USBHS_EP0_R_EN << epnum); + } + + // usbd_ep_read(ep_addr, buffer, total_bytes, &ret_bytes); + } + return true; +} + + +static void receive_packet(xfer_ctl_t *xfer, uint16_t xfer_size) { + // xfer->queued_len = xfer->total_len - remaining; + + uint16_t remaining = xfer->total_len - xfer->queued_len; + uint16_t to_recv_size; + + if (remaining <= xfer->max_size) { + // Avoid buffer overflow. + to_recv_size = (xfer_size > remaining) ? remaining : xfer_size; + } else { + // Room for full packet, choose recv_size based on what the microcontroller + // claims. + to_recv_size = (xfer_size > xfer->max_size) ? xfer->max_size : xfer_size; + } + + if (to_recv_size) { + } + + xfer->queued_len += xfer_size; + + // Per USB spec, a short OUT packet (including length 0) is always + // indicative of the end of a transfer (at least for ctl, bulk, int). + xfer->short_packet = (xfer_size < xfer->max_size); +} + +void dcd_int_handler(uint8_t rhport) { + (void)rhport; + + uint32_t end_num, rx_token; + uint8_t intflag = 0; + + intflag = USBHSD->INT_FG; + + if (intflag & USBHS_TRANSFER_FLAG) { + + end_num = (USBHSD->INT_ST) & MASK_UIS_ENDP; + rx_token = (((USBHSD->INT_ST) & MASK_UIS_TOKEN) >> 4) & 0x03; + + uint8_t endp = end_num | (rx_token == PID_IN ? TUSB_DIR_IN_MASK : 0); + + xfer_ctl_t *xfer = XFER_CTL_BASE(end_num, tu_edpt_dir(endp)); + + if (rx_token == PID_OUT) { + uint16_t rx_len = USBHSD->RX_LEN; + + receive_packet(xfer, rx_len); + + if (xfer->short_packet || (xfer->queued_len == xfer->total_len)) { + xfer->short_packet = false; + + dcd_event_xfer_complete(0, endp, xfer->queued_len, XFER_RESULT_SUCCESS, true); + } + + if (end_num == 0) { + USBHSD->UEP0_RX_CTRL = USBHS_EP_R_RES_ACK | USBHS_EP_R_TOG_0; + } + + } else if (rx_token == PID_IN) { + if (xfer->short_packet || (xfer->queued_len == xfer->total_len)) { + xfer->short_packet = false; + xfer->total_len = 0; + dcd_event_xfer_complete(0, endp, xfer->queued_len, XFER_RESULT_SUCCESS, true); + + EP_TX_CTRL(end_num) = (EP_TX_CTRL(end_num) & ~(USBHS_EP_T_RES_MASK)) | USBHS_EP_T_RES_NAK; + + if (end_num == 0) { + } + } else { + dcd_edpt_xfer(0, endp, xfer->buffer + xfer->queued_len, xfer->total_len - xfer->queued_len); + } + } + + USBHSD->INT_FG = USBHS_TRANSFER_FLAG; /* Clear flag */ + } else if (intflag & USBHS_SETUP_FLAG) { + USBHS_Dev_Endp0_Tog = 1; + dcd_event_setup_received(0, EP0_DatabufHD, true); + + USBHSD->INT_FG = USBHS_SETUP_FLAG; /* Clear flag */ + } else if (intflag & USBHS_DETECT_FLAG) { + USBHS_Dev_Endp0_Tog = 1; + + xfer_status[0][TUSB_DIR_OUT].max_size = 64; + xfer_status[0][TUSB_DIR_IN].max_size = 64; + + dcd_event_bus_reset(0, TUSB_SPEED_HIGH, true); + + USBHSD->DEV_AD = 0; + USBHSD->UEP0_RX_CTRL = USBHS_EP_R_RES_ACK | USBHS_EP_R_TOG_0; + + USBHSD->INT_FG = USBHS_DETECT_FLAG; /* Clear flag */ + } else if (intflag & USBHS_SUSPEND_FLAG) { + dcd_event_t event = { .rhport = rhport, .event_id = DCD_EVENT_SUSPEND }; + dcd_event_handler(&event, true); + + USBHSD->INT_FG = USBHS_SUSPEND_FLAG; /* Clear flag */ + } +} + +#endif \ No newline at end of file diff --git a/src/tusb_option.h b/src/tusb_option.h index bd87a953c..ffeec2241 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -149,6 +149,9 @@ // Allwinner #define OPT_MCU_F1C100S 2100 ///< Allwinner F1C100s family +// WCH +#define OPT_MCU_CH32VF307 2200 ///< WCH CH32V307 config + // Helper to check if configured MCU is one of listed // Apply _TU_CHECK_MCU with || as separator to list of input #define _TU_CHECK_MCU(_m) (CFG_TUSB_MCU == _m) From 1d254be1a48264f906c5bbc50c4eca56eea063df Mon Sep 17 00:00:00 2001 From: Greg Davill Date: Tue, 22 Mar 2022 16:03:53 +1030 Subject: [PATCH 02/20] Increase stack size to 4096 bytes --- hw/bsp/ch32v307/Link.ld | 170 ++++++++++++++++++ .../ch32v307/boards/CH32V307V-R1-1v0/board.mk | 2 +- 2 files changed, 171 insertions(+), 1 deletion(-) create mode 100644 hw/bsp/ch32v307/Link.ld diff --git a/hw/bsp/ch32v307/Link.ld b/hw/bsp/ch32v307/Link.ld new file mode 100644 index 000000000..af7c06615 --- /dev/null +++ b/hw/bsp/ch32v307/Link.ld @@ -0,0 +1,170 @@ +ENTRY( _start ) + +__stack_size = 4096; + +PROVIDE( _stack_size = __stack_size ); + + +MEMORY +{ + FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 288K + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 32K +} + + +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.*) + . = 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 = .); + __freertos_irq_stack_top = .; + } >RAM + +} + + + diff --git a/hw/bsp/ch32v307/boards/CH32V307V-R1-1v0/board.mk b/hw/bsp/ch32v307/boards/CH32V307V-R1-1v0/board.mk index f71def2c7..a7c359588 100644 --- a/hw/bsp/ch32v307/boards/CH32V307V-R1-1v0/board.mk +++ b/hw/bsp/ch32v307/boards/CH32V307V-R1-1v0/board.mk @@ -1,3 +1,3 @@ -LINKER_SCRIPTS = $(CH32V307_SDK_SRC)/Ld +LINKER_SCRIPTS = $(BOARD_PATH)/../.. LD_FILE = $(LINKER_SCRIPTS)/Link.ld # CH32V307 From ac058a4c4553a237b297812be712a9c8dce0069a Mon Sep 17 00:00:00 2001 From: Greg Davill Date: Tue, 22 Mar 2022 22:32:53 +1030 Subject: [PATCH 03/20] Add ch32v307 to build workflow --- .github/workflows/build_riscv.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build_riscv.yml b/.github/workflows/build_riscv.yml index 0c7b2d154..4ac265da3 100644 --- a/.github/workflows/build_riscv.yml +++ b/.github/workflows/build_riscv.yml @@ -15,6 +15,7 @@ jobs: matrix: family: # Alphabetical order + - 'ch32v307' - 'fomu' - 'gd32vf103' steps: From d828d203fcdc9f6839330e1007a331f740224ab8 Mon Sep 17 00:00:00 2001 From: Greg Davill Date: Tue, 22 Mar 2022 23:29:09 +1030 Subject: [PATCH 04/20] Skip freertos for ch32v307 --- examples/device/cdc_msc_freertos/skip.txt | 1 + examples/device/hid_composite_freertos/skip.txt | 1 + 2 files changed, 2 insertions(+) diff --git a/examples/device/cdc_msc_freertos/skip.txt b/examples/device/cdc_msc_freertos/skip.txt index 7137b78af..edb8a34aa 100644 --- a/examples/device/cdc_msc_freertos/skip.txt +++ b/examples/device/cdc_msc_freertos/skip.txt @@ -6,5 +6,6 @@ mcu:MKL25ZXX mcu:RP2040 mcu:SAMX7X mcu:GD32VF103 +mcu:CH32V307 family:broadcom_64bit family:broadcom_32bit \ No newline at end of file diff --git a/examples/device/hid_composite_freertos/skip.txt b/examples/device/hid_composite_freertos/skip.txt index e64187fd4..b12de1a90 100644 --- a/examples/device/hid_composite_freertos/skip.txt +++ b/examples/device/hid_composite_freertos/skip.txt @@ -5,5 +5,6 @@ mcu:VALENTYUSB_EPTRI mcu:RP2040 mcu:SAMX7X mcu:GD32VF103 +mcu:CH32V307 family:broadcom_64bit family:broadcom_32bit \ No newline at end of file From a09c1648f56580bcdb59b08af255442d9240281c Mon Sep 17 00:00:00 2001 From: Greg Davill Date: Tue, 22 Mar 2022 23:31:20 +1030 Subject: [PATCH 05/20] Fix typo --- hw/bsp/ch32v307/family.mk | 2 +- src/common/tusb_mcu.h | 2 +- src/portable/wch/ch32v307/usb_dc_usbhs.c | 2 +- src/tusb_option.h | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/hw/bsp/ch32v307/family.mk b/hw/bsp/ch32v307/family.mk index dfb4853d9..ef2af26e6 100644 --- a/hw/bsp/ch32v307/family.mk +++ b/hw/bsp/ch32v307/family.mk @@ -28,7 +28,7 @@ CFLAGS += \ -ffunction-sections \ -fdata-sections \ -nostdlib -nostartfiles \ - -DCFG_TUSB_MCU=OPT_MCU_CH32VF307 \ + -DCFG_TUSB_MCU=OPT_MCU_CH32V307 \ -Xlinker --gc-sections \ -DBOARD_DEVICE_RHPORT_SPEED=OPT_MODE_HIGH_SPEED diff --git a/src/common/tusb_mcu.h b/src/common/tusb_mcu.h index 84d629eac..9de092e34 100644 --- a/src/common/tusb_mcu.h +++ b/src/common/tusb_mcu.h @@ -267,7 +267,7 @@ #define TUP_DCD_ENDPOINT_MAX 4 //------------- WCH -------------// -#elif TU_CHECK_MCU(OPT_MCU_CH32VF307) +#elif TU_CHECK_MCU(OPT_MCU_CH32V307) #define TUP_DCD_ENDPOINT_MAX 8 #endif diff --git a/src/portable/wch/ch32v307/usb_dc_usbhs.c b/src/portable/wch/ch32v307/usb_dc_usbhs.c index 32645dc5f..3a2c9979e 100644 --- a/src/portable/wch/ch32v307/usb_dc_usbhs.c +++ b/src/portable/wch/ch32v307/usb_dc_usbhs.c @@ -26,7 +26,7 @@ #include "tusb_option.h" -#if CFG_TUD_ENABLED && (CFG_TUSB_MCU == OPT_MCU_CH32VF307) +#if CFG_TUD_ENABLED && (CFG_TUSB_MCU == OPT_MCU_CH32V307) #include "device/dcd.h" #include "usb_ch32_usbhs_reg.h" diff --git a/src/tusb_option.h b/src/tusb_option.h index ffeec2241..28bf8a60d 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -150,7 +150,7 @@ #define OPT_MCU_F1C100S 2100 ///< Allwinner F1C100s family // WCH -#define OPT_MCU_CH32VF307 2200 ///< WCH CH32V307 config +#define OPT_MCU_CH32V307 2200 ///< WCH CH32V307 config // Helper to check if configured MCU is one of listed // Apply _TU_CHECK_MCU with || as separator to list of input From 325923b6c61d0a914a0c6f78e650c6b85fbd13d2 Mon Sep 17 00:00:00 2001 From: Greg Davill Date: Tue, 22 Mar 2022 23:40:54 +1030 Subject: [PATCH 06/20] Update comments about endpoint buffer modes --- src/portable/wch/ch32v307/usb_ch32_usbhs_reg.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/portable/wch/ch32v307/usb_ch32_usbhs_reg.h b/src/portable/wch/ch32v307/usb_ch32_usbhs_reg.h index 1b7c0e791..5a2c1fbc9 100644 --- a/src/portable/wch/ch32v307/usb_ch32_usbhs_reg.h +++ b/src/portable/wch/ch32v307/usb_ch32_usbhs_reg.h @@ -231,12 +231,12 @@ #define USBHS_EP15_BUF_MOD (1 << 15) #define USBHS_EP15_ISO_BUF_MOD (1 << 31) -//USBHS_EPn_T_EN USBHS_EPn_R_EN USBHS_EPn_BUF_MOD 锟斤拷锟斤拷锟斤拷锟斤拷UEPn_DMA为锟斤拷始锟斤拷址锟缴碉拷锟斤拷锟斤拷锟斤拷锟� -// 0 0 x 锟剿点被锟斤拷锟矫o拷未锟矫碉拷UEPn_*_DMA锟斤拷锟斤拷锟斤拷锟斤拷 -// 1 0 0 锟斤拷锟秸o拷OUT锟斤拷锟斤拷锟斤拷锟斤拷锟阶碉拷址为UEPn_RX_DMA -// 1 0 1 bUEPn_RX_TOG[0]=0,使锟矫伙拷锟斤拷锟斤拷UEPn_RX_DMA锟斤拷bUEPn_RX_TOG[0]=1,使锟矫伙拷锟斤拷锟斤拷UEPn_TX_DMA -// 0 1 0 锟斤拷锟斤拷(IN)锟斤拷锟斤拷锟斤拷锟阶碉拷址为UEPn_TX_DMA锟斤拷 -// 0 1 1 bUEPn_TX_TOG[0]=0,使锟矫伙拷锟斤拷锟斤拷UEPn_TX_DMA锟斤拷bUEPn_TX_TOG[0]=1,使锟矫伙拷锟斤拷锟斤拷UEPn_RX_DMA +//USBHS_EPn_T_EN USBHS_EPn_R_EN USBHS_EPn_BUF_MOD Description: Arrange from low to high with UEPn_DMA as the starting address +// 0 0 x The endpoint is disabled and the UEPn_*_DMA buffers are not used. +// 1 0 0 The first address of the receive (OUT) buffer is UEPn_RX_DMA +// 1 0 1 RB_UEPn_RX_TOG[0]=0, use buffer UEPn_RX_DMA RB_UEPn_RX_TOG[0]=1, use buffer UEPn_TX_DMA +// 0 1 0 The first address of the transmit (IN) buffer is UEPn_TX_DMA. +// 0 1 1 RB_UEPn_TX_TOG[0]=0, use buffer UEPn_TX_DMA RB_UEPn_TX_TOG[0]=1, use buffer UEPn_RX_DMA /* USB0_DMA */ #define USBHS_UEP0_DMA_OFFSET(n) (0x1C) // endpoint 0 DMA buffer address From cdb8a1a2a1dd863f35fd91d58c18ec83115f9326 Mon Sep 17 00:00:00 2001 From: Greg Davill Date: Wed, 23 Mar 2022 00:00:06 +1030 Subject: [PATCH 07/20] Clean up driver --- src/common/tusb_mcu.h | 2 +- src/portable/wch/ch32v307/usb_dc_usbhs.c | 10 ++++------ 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/src/common/tusb_mcu.h b/src/common/tusb_mcu.h index 9de092e34..fb0cdd361 100644 --- a/src/common/tusb_mcu.h +++ b/src/common/tusb_mcu.h @@ -268,7 +268,7 @@ //------------- WCH -------------// #elif TU_CHECK_MCU(OPT_MCU_CH32V307) - #define TUP_DCD_ENDPOINT_MAX 8 + #define TUP_DCD_ENDPOINT_MAX 16 #endif diff --git a/src/portable/wch/ch32v307/usb_dc_usbhs.c b/src/portable/wch/ch32v307/usb_dc_usbhs.c index 3a2c9979e..e647389ee 100644 --- a/src/portable/wch/ch32v307/usb_dc_usbhs.c +++ b/src/portable/wch/ch32v307/usb_dc_usbhs.c @@ -56,10 +56,8 @@ static xfer_ctl_t xfer_status[EP_MAX][2]; #define EP_RX_DMA_ADDR(ep) *(volatile uint32_t *)((volatile uint32_t *)&(USBHSD->UEP1_RX_DMA) + (ep - 1)) /* Endpoint Buffer */ -__attribute__((aligned(4))) uint8_t setup[8]; // ep0(64) -__attribute__((aligned(4))) uint8_t EP0_DatabufHD[64]; // ep0(64) +TU_ATTR_ALIGNED(4) uint8_t EP0_DatabufHD[64]; // ep0(64) -volatile uint8_t mps_over_flag = 0; volatile uint8_t USBHS_Dev_Endp0_Tog = 0x01; void dcd_init(uint8_t rhport) { @@ -67,15 +65,15 @@ void dcd_init(uint8_t rhport) { memset(&xfer_status, 0, sizeof(xfer_status)); - // usb_dc_low_level_init(); - USBHSD->HOST_CTRL = 0x00; USBHSD->HOST_CTRL = USBHS_PHY_SUSPENDM; USBHSD->CONTROL = 0; -#if 1 + +#if (BOARD_DEVICE_RHPORT_SPEED == OPT_MODE_HIGH_SPEED) USBHSD->CONTROL = USBHS_DMA_EN | USBHS_INT_BUSY_EN | USBHS_HIGH_SPEED; #else + #error OPT_MODE_FULL_SPEED not currently supported on CH32V307 USBHSD->CONTROL = USBHS_DMA_EN | USBHS_INT_BUSY_EN | USBHS_FULL_SPEED; #endif From 46fb850e02ae5010e0f7209775e1f5392112efa4 Mon Sep 17 00:00:00 2001 From: Greg Davill Date: Wed, 23 Mar 2022 00:06:51 +1030 Subject: [PATCH 08/20] Update support table --- docs/reference/supported.rst | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/docs/reference/supported.rst b/docs/reference/supported.rst index 7ce982713..aebee2c29 100644 --- a/docs/reference/supported.rst +++ b/docs/reference/supported.rst @@ -102,6 +102,8 @@ Supported MCUs +--------------+-----------------------+--------+------+-----------+-------------------+--------------+ | ValentyUSB | eptri | ✔ | ✖ | ✖ | eptri | | +--------------+-----------------------+--------+------+-----------+-------------------+--------------+ +| WCH | CH32V307 | ✔ | ✖ | ✔ | ch32v307 | | ++--------------+-----------------------+--------+------+-----------+-------------------+--------------+ Table Legend @@ -388,3 +390,8 @@ Tomu ---- - `Fomu `__ + +WCH +--- + +- `CH32V307V-R1-1v0 ` From 7d395c674ca083a245df0601c8a6d392c75b34e8 Mon Sep 17 00:00:00 2001 From: Greg Davill Date: Wed, 23 Mar 2022 00:46:44 +1030 Subject: [PATCH 09/20] Update supported table --- docs/reference/supported.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/reference/supported.rst b/docs/reference/supported.rst index aebee2c29..7543e44ab 100644 --- a/docs/reference/supported.rst +++ b/docs/reference/supported.rst @@ -102,7 +102,7 @@ Supported MCUs +--------------+-----------------------+--------+------+-----------+-------------------+--------------+ | ValentyUSB | eptri | ✔ | ✖ | ✖ | eptri | | +--------------+-----------------------+--------+------+-----------+-------------------+--------------+ -| WCH | CH32V307 | ✔ | ✖ | ✔ | ch32v307 | | +| WCH | CH32V307 | ✔ | | ✔ | ch32v307 | | +--------------+-----------------------+--------+------+-----------+-------------------+--------------+ From 817227a850d4942cf48ede675325d635e2e7b3d5 Mon Sep 17 00:00:00 2001 From: Rafael Silva Date: Fri, 1 Apr 2022 10:05:14 +0100 Subject: [PATCH 10/20] Add WCH CH32V307 to readme supported list --- README.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/README.rst b/README.rst index 5b994c357..755bd97e9 100644 --- a/README.rst +++ b/README.rst @@ -54,6 +54,7 @@ The stack supports the following MCUs: - **ST:** STM32 series: F0, F1, F2, F3, F4, F7, H7, G4, L0, L1, L4, L4+ - **TI:** MSP430, MSP432E4, TM4C123 - **ValentyUSB:** eptri +- **WCH:** CH32V307 Here is the list of `Supported Devices`_ that can be used with provided examples. From a7e1de1e837961b33021a8ae4ca63571fbf1f4a2 Mon Sep 17 00:00:00 2001 From: hathach Date: Sun, 8 Jan 2023 00:02:17 +0700 Subject: [PATCH 11/20] temporarily suppress redundant-decls due to USART_Printf_Init() fix codespell --- hw/bsp/ch32v307/family.c | 2 +- hw/bsp/ch32v307/family.mk | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/hw/bsp/ch32v307/family.c b/hw/bsp/ch32v307/family.c index ea1c252c4..428466ad7 100644 --- a/hw/bsp/ch32v307/family.c +++ b/hw/bsp/ch32v307/family.c @@ -85,7 +85,7 @@ void board_init(void) { GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOC, &GPIO_InitStructure); - /* Enable interrupts globaly */ + /* Enable interrupts globally */ __enable_irq(); board_delay(2); diff --git a/hw/bsp/ch32v307/family.mk b/hw/bsp/ch32v307/family.mk index ef2af26e6..12565016d 100644 --- a/hw/bsp/ch32v307/family.mk +++ b/hw/bsp/ch32v307/family.mk @@ -30,7 +30,10 @@ CFLAGS += \ -nostdlib -nostartfiles \ -DCFG_TUSB_MCU=OPT_MCU_CH32V307 \ -Xlinker --gc-sections \ - -DBOARD_DEVICE_RHPORT_SPEED=OPT_MODE_HIGH_SPEED + -DBOARD_DEVICE_RHPORT_SPEED=OPT_MODE_HIGH_SPEED + +# caused by extra void USART_Printf_Init() in debug_uart.h and EVT/EXAME/SRC/DEBUG/debug.h +CFLAGS += -Wno-error=redundant-decls LDFLAGS += \ -Xlinker --gc-sections --specs=nano.specs --specs=nosys.specs From 3cc6cece0783e893d9fadc868f7fb58c81625fe0 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 12 Jan 2023 10:25:48 +0700 Subject: [PATCH 12/20] add note for openocd with wch, also add wch-riscv.cfg --- hw/bsp/ch32v307/family.mk | 18 +++++++++++++++--- hw/bsp/ch32v307/wch-riscv.cfg | 15 +++++++++++++++ src/portable/wch/ch32v307/usb_dc_usbhs.c | 4 ++-- 3 files changed, 32 insertions(+), 5 deletions(-) create mode 100644 hw/bsp/ch32v307/wch-riscv.cfg diff --git a/hw/bsp/ch32v307/family.mk b/hw/bsp/ch32v307/family.mk index 12565016d..58542041f 100644 --- a/hw/bsp/ch32v307/family.mk +++ b/hw/bsp/ch32v307/family.mk @@ -30,7 +30,7 @@ CFLAGS += \ -nostdlib -nostartfiles \ -DCFG_TUSB_MCU=OPT_MCU_CH32V307 \ -Xlinker --gc-sections \ - -DBOARD_DEVICE_RHPORT_SPEED=OPT_MODE_HIGH_SPEED + -DBOARD_TUD_MAX_SPEED=OPT_MODE_HIGH_SPEED # caused by extra void USART_Printf_Init() in debug_uart.h and EVT/EXAME/SRC/DEBUG/debug.h CFLAGS += -Wno-error=redundant-decls @@ -51,7 +51,6 @@ SRC_S += \ INC += \ src/portable/wch/ch32v307 \ - $(TOP)/$(BOARD_PATH)/.. \ $(TOP)/$(BOARD_PATH) \ $(CH32V307_SDK_SRC_TOP)/Peripheral/inc \ $(CH32V307_SDK_SRC_TOP)/Debug \ @@ -60,6 +59,19 @@ INC += \ # For freeRTOS port source FREERTOS_PORT = RISC-V +# wch-link is not supported yet in official openOCD yet. We need to either use +# 1. download openocd as part of mounriver studio http://www.mounriver.com/download or +# 2. compiled from modified source https://github.com/kprasadvnsi/riscv-openocd-wch +# +# Note: For Linux, somehow openocd in mounriver studio does not seem to have wch-link enable, +# therefore we need to compile it from source as follows: +# git clone https://github.com/kprasadvnsi/riscv-openocd-wch +# cd riscv-openocd-wch +# ./bootstrap +# ./configure CFLAGS="-Wno-error" --enable-wlink +# make +# openocd binaries will be generated in riscv-openocd-wch/src + # flash target ROM bootloader flash: $(BUILD)/$(PROJECT).elf - openocd -f wch-riscv.cfg -c init -c halt -c "program $< 0x08000000" -c reset -c exit + openocd -f $(TOP)/$(FAMILY_PATH)/wch-riscv.cfg -c init -c halt -c "program $<" -c reset -c exit diff --git a/hw/bsp/ch32v307/wch-riscv.cfg b/hw/bsp/ch32v307/wch-riscv.cfg new file mode 100644 index 000000000..0d24d16ca --- /dev/null +++ b/hw/bsp/ch32v307/wch-riscv.cfg @@ -0,0 +1,15 @@ +#interface wlink +adapter driver wlink +wlink_set +set _CHIPNAME riscv +jtag newtap $_CHIPNAME cpu -irlen 5 -expected-id 0x00001 + +set _TARGETNAME $_CHIPNAME.cpu + +target create $_TARGETNAME.0 riscv -chain-position $_TARGETNAME +$_TARGETNAME.0 configure -work-area-phys 0x80000000 -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/src/portable/wch/ch32v307/usb_dc_usbhs.c b/src/portable/wch/ch32v307/usb_dc_usbhs.c index e647389ee..39fd41392 100644 --- a/src/portable/wch/ch32v307/usb_dc_usbhs.c +++ b/src/portable/wch/ch32v307/usb_dc_usbhs.c @@ -70,7 +70,7 @@ void dcd_init(uint8_t rhport) { USBHSD->CONTROL = 0; -#if (BOARD_DEVICE_RHPORT_SPEED == OPT_MODE_HIGH_SPEED) +#if TUD_OPT_HIGH_SPEED USBHSD->CONTROL = USBHS_DMA_EN | USBHS_INT_BUSY_EN | USBHS_HIGH_SPEED; #else #error OPT_MODE_FULL_SPEED not currently supported on CH32V307 @@ -383,4 +383,4 @@ void dcd_int_handler(uint8_t rhport) { } } -#endif \ No newline at end of file +#endif From e61d4aefe6b9fbab862e7c440ff9ff25ebb5092c Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 12 Jan 2023 12:08:56 +0700 Subject: [PATCH 13/20] rename driver with dcd_ to be consitent with other ports --- hw/bsp/ch32v307/family.mk | 22 ++++++++----------- ...{usb_ch32_usbhs_reg.h => ch32_usbhs_reg.h} | 0 .../ch32v307/{usb_dc_usbhs.c => dcd_usbhs.c} | 2 +- 3 files changed, 10 insertions(+), 14 deletions(-) rename src/portable/wch/ch32v307/{usb_ch32_usbhs_reg.h => ch32_usbhs_reg.h} (100%) rename src/portable/wch/ch32v307/{usb_dc_usbhs.c => dcd_usbhs.c} (99%) diff --git a/hw/bsp/ch32v307/family.mk b/hw/bsp/ch32v307/family.mk index 58542041f..ffc992f21 100644 --- a/hw/bsp/ch32v307/family.mk +++ b/hw/bsp/ch32v307/family.mk @@ -10,8 +10,6 @@ DEPS_SUBMODULES += $(CH32V307_SDK) # WCH-SDK paths CH32V307_SDK_SRC = $(CH32V307_SDK)/EVT/EXAM/SRC -CH32V307_SDK_SRC_TOP = $(TOP)/$(CH32V307_SDK_SRC) -CH32V307_STARTUP_ASM = $(CH32V307_SDK_SRC)/Startup include $(TOP)/$(BOARD_PATH)/board.mk @@ -39,22 +37,20 @@ LDFLAGS += \ -Xlinker --gc-sections --specs=nano.specs --specs=nosys.specs SRC_C += \ - src/portable/wch/ch32v307/usb_dc_usbhs.c \ - $(CH32V307_SDK_SRC_TOP)/Core/core_riscv.c \ - $(CH32V307_SDK_SRC_TOP)/Peripheral/src/ch32v30x_gpio.c \ - $(CH32V307_SDK_SRC_TOP)/Peripheral/src/ch32v30x_misc.c \ - $(CH32V307_SDK_SRC_TOP)/Peripheral/src/ch32v30x_rcc.c \ - $(CH32V307_SDK_SRC_TOP)/Peripheral/src/ch32v30x_usart.c + src/portable/wch/ch32v307/dcd_usbhs.c \ + $(CH32V307_SDK_SRC)/Core/core_riscv.c \ + $(CH32V307_SDK_SRC)/Peripheral/src/ch32v30x_gpio.c \ + $(CH32V307_SDK_SRC)/Peripheral/src/ch32v30x_misc.c \ + $(CH32V307_SDK_SRC)/Peripheral/src/ch32v30x_rcc.c \ + $(CH32V307_SDK_SRC)/Peripheral/src/ch32v30x_usart.c SRC_S += \ - $(CH32V307_STARTUP_ASM)/startup_ch32v30x_D8C.S + $(CH32V307_SDK_SRC)/Startup/startup_ch32v30x_D8C.S INC += \ - src/portable/wch/ch32v307 \ $(TOP)/$(BOARD_PATH) \ - $(CH32V307_SDK_SRC_TOP)/Peripheral/inc \ - $(CH32V307_SDK_SRC_TOP)/Debug \ - $(CH32V307_SDK_SRC_TOP) + $(TOP)/$(CH32V307_SDK_SRC)/Peripheral/inc \ + $(TOP)/$(CH32V307_SDK_SRC)/Debug # For freeRTOS port source FREERTOS_PORT = RISC-V diff --git a/src/portable/wch/ch32v307/usb_ch32_usbhs_reg.h b/src/portable/wch/ch32v307/ch32_usbhs_reg.h similarity index 100% rename from src/portable/wch/ch32v307/usb_ch32_usbhs_reg.h rename to src/portable/wch/ch32v307/ch32_usbhs_reg.h diff --git a/src/portable/wch/ch32v307/usb_dc_usbhs.c b/src/portable/wch/ch32v307/dcd_usbhs.c similarity index 99% rename from src/portable/wch/ch32v307/usb_dc_usbhs.c rename to src/portable/wch/ch32v307/dcd_usbhs.c index 39fd41392..7a0dcfc23 100644 --- a/src/portable/wch/ch32v307/usb_dc_usbhs.c +++ b/src/portable/wch/ch32v307/dcd_usbhs.c @@ -29,7 +29,7 @@ #if CFG_TUD_ENABLED && (CFG_TUSB_MCU == OPT_MCU_CH32V307) #include "device/dcd.h" -#include "usb_ch32_usbhs_reg.h" +#include "ch32_usbhs_reg.h" #include "core_riscv.h" // Max number of bi-directional endpoints including EP0 From 658897cf4e3058aee66f65c17a152ef65b1671c1 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 12 Jan 2023 12:30:18 +0700 Subject: [PATCH 14/20] fix redundant-decls warnings with USART_Printf_Init() --- hw/bsp/ch32v307/boards/CH32V307V-R1-1v0/debug_uart.c | 2 +- hw/bsp/ch32v307/boards/CH32V307V-R1-1v0/debug_uart.h | 2 +- hw/bsp/ch32v307/ch32v30x_it.h | 2 +- hw/bsp/ch32v307/family.c | 2 +- hw/bsp/ch32v307/family.mk | 6 +----- 5 files changed, 5 insertions(+), 9 deletions(-) diff --git a/hw/bsp/ch32v307/boards/CH32V307V-R1-1v0/debug_uart.c b/hw/bsp/ch32v307/boards/CH32V307V-R1-1v0/debug_uart.c index 416782d0e..ad8b32957 100644 --- a/hw/bsp/ch32v307/boards/CH32V307V-R1-1v0/debug_uart.c +++ b/hw/bsp/ch32v307/boards/CH32V307V-R1-1v0/debug_uart.c @@ -75,7 +75,7 @@ void uart_sync(void) } -void USART_Printf_Init(uint32_t baudrate) +void usart_printf_init(uint32_t baudrate) { GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; diff --git a/hw/bsp/ch32v307/boards/CH32V307V-R1-1v0/debug_uart.h b/hw/bsp/ch32v307/boards/CH32V307V-R1-1v0/debug_uart.h index 4348438bb..a7e070585 100644 --- a/hw/bsp/ch32v307/boards/CH32V307V-R1-1v0/debug_uart.h +++ b/hw/bsp/ch32v307/boards/CH32V307V-R1-1v0/debug_uart.h @@ -28,4 +28,4 @@ void uart_write(char c); void uart_sync(void); -void USART_Printf_Init(uint32_t baudrate); +void usart_printf_init(uint32_t baudrate); diff --git a/hw/bsp/ch32v307/ch32v30x_it.h b/hw/bsp/ch32v307/ch32v30x_it.h index 6475c5f11..42f285edf 100644 --- a/hw/bsp/ch32v307/ch32v30x_it.h +++ b/hw/bsp/ch32v307/ch32v30x_it.h @@ -10,7 +10,7 @@ #ifndef __CH32V30x_IT_H #define __CH32V30x_IT_H -#include "debug.h" +// #include "debug.h" #endif /* __CH32V30x_IT_H */ diff --git a/hw/bsp/ch32v307/family.c b/hw/bsp/ch32v307/family.c index 428466ad7..0260918ab 100644 --- a/hw/bsp/ch32v307/family.c +++ b/hw/bsp/ch32v307/family.c @@ -68,7 +68,7 @@ void board_init(void) { SysTick_Config(SystemCoreClock / 1000); #endif - USART_Printf_Init(115200); + usart_printf_init(115200); RCC_USBCLK48MConfig(RCC_USBCLK48MCLKSource_USBPHY); RCC_USBHSPLLCLKConfig(RCC_HSBHSPLLCLKSource_HSE); diff --git a/hw/bsp/ch32v307/family.mk b/hw/bsp/ch32v307/family.mk index ffc992f21..93370fc57 100644 --- a/hw/bsp/ch32v307/family.mk +++ b/hw/bsp/ch32v307/family.mk @@ -30,9 +30,6 @@ CFLAGS += \ -Xlinker --gc-sections \ -DBOARD_TUD_MAX_SPEED=OPT_MODE_HIGH_SPEED -# caused by extra void USART_Printf_Init() in debug_uart.h and EVT/EXAME/SRC/DEBUG/debug.h -CFLAGS += -Wno-error=redundant-decls - LDFLAGS += \ -Xlinker --gc-sections --specs=nano.specs --specs=nosys.specs @@ -49,8 +46,7 @@ SRC_S += \ INC += \ $(TOP)/$(BOARD_PATH) \ - $(TOP)/$(CH32V307_SDK_SRC)/Peripheral/inc \ - $(TOP)/$(CH32V307_SDK_SRC)/Debug + $(TOP)/$(CH32V307_SDK_SRC)/Peripheral/inc # For freeRTOS port source FREERTOS_PORT = RISC-V From e6a3cfb3506fdd908c47ad0cf63fc67a1ef2455c Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 12 Jan 2023 13:12:37 +0700 Subject: [PATCH 15/20] rename link file --- hw/bsp/ch32v307/boards/CH32V307V-R1-1v0/board.mk | 4 +--- hw/bsp/ch32v307/{Link.ld => ch32v307.ld} | 0 2 files changed, 1 insertion(+), 3 deletions(-) rename hw/bsp/ch32v307/{Link.ld => ch32v307.ld} (100%) diff --git a/hw/bsp/ch32v307/boards/CH32V307V-R1-1v0/board.mk b/hw/bsp/ch32v307/boards/CH32V307V-R1-1v0/board.mk index a7c359588..4e91d8938 100644 --- a/hw/bsp/ch32v307/boards/CH32V307V-R1-1v0/board.mk +++ b/hw/bsp/ch32v307/boards/CH32V307V-R1-1v0/board.mk @@ -1,3 +1 @@ -LINKER_SCRIPTS = $(BOARD_PATH)/../.. - -LD_FILE = $(LINKER_SCRIPTS)/Link.ld # CH32V307 +LD_FILE = $(FAMILY_PATH)/ch32v307.ld diff --git a/hw/bsp/ch32v307/Link.ld b/hw/bsp/ch32v307/ch32v307.ld similarity index 100% rename from hw/bsp/ch32v307/Link.ld rename to hw/bsp/ch32v307/ch32v307.ld From 65f7a8006cdeae74e5258657250ae7568b607cd1 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 12 Jan 2023 13:31:36 +0700 Subject: [PATCH 16/20] rename board to lower case ch32v307v-r1-1v0 --- .../boards/{CH32V307V-R1-1v0 => ch32v307v-r1-1v0}/board.mk | 0 .../boards/{CH32V307V-R1-1v0 => ch32v307v-r1-1v0}/debug_uart.c | 0 .../boards/{CH32V307V-R1-1v0 => ch32v307v-r1-1v0}/debug_uart.h | 0 hw/bsp/ch32v307/family.mk | 2 +- 4 files changed, 1 insertion(+), 1 deletion(-) rename hw/bsp/ch32v307/boards/{CH32V307V-R1-1v0 => ch32v307v-r1-1v0}/board.mk (100%) rename hw/bsp/ch32v307/boards/{CH32V307V-R1-1v0 => ch32v307v-r1-1v0}/debug_uart.c (100%) rename hw/bsp/ch32v307/boards/{CH32V307V-R1-1v0 => ch32v307v-r1-1v0}/debug_uart.h (100%) diff --git a/hw/bsp/ch32v307/boards/CH32V307V-R1-1v0/board.mk b/hw/bsp/ch32v307/boards/ch32v307v-r1-1v0/board.mk similarity index 100% rename from hw/bsp/ch32v307/boards/CH32V307V-R1-1v0/board.mk rename to hw/bsp/ch32v307/boards/ch32v307v-r1-1v0/board.mk diff --git a/hw/bsp/ch32v307/boards/CH32V307V-R1-1v0/debug_uart.c b/hw/bsp/ch32v307/boards/ch32v307v-r1-1v0/debug_uart.c similarity index 100% rename from hw/bsp/ch32v307/boards/CH32V307V-R1-1v0/debug_uart.c rename to hw/bsp/ch32v307/boards/ch32v307v-r1-1v0/debug_uart.c diff --git a/hw/bsp/ch32v307/boards/CH32V307V-R1-1v0/debug_uart.h b/hw/bsp/ch32v307/boards/ch32v307v-r1-1v0/debug_uart.h similarity index 100% rename from hw/bsp/ch32v307/boards/CH32V307V-R1-1v0/debug_uart.h rename to hw/bsp/ch32v307/boards/ch32v307v-r1-1v0/debug_uart.h diff --git a/hw/bsp/ch32v307/family.mk b/hw/bsp/ch32v307/family.mk index 93370fc57..49e496853 100644 --- a/hw/bsp/ch32v307/family.mk +++ b/hw/bsp/ch32v307/family.mk @@ -66,4 +66,4 @@ FREERTOS_PORT = RISC-V # flash target ROM bootloader flash: $(BUILD)/$(PROJECT).elf - openocd -f $(TOP)/$(FAMILY_PATH)/wch-riscv.cfg -c init -c halt -c "program $<" -c reset -c exit + openocd -f $(TOP)/$(FAMILY_PATH)/wch-riscv.cfg -c init -c halt -c "program $<" -c wlink_reset_resume -c exit From f05f81e8b3d7ac6b061eaab20fc456fbed89d690 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 12 Jan 2023 15:19:26 +0700 Subject: [PATCH 17/20] add button support --- .../ch32v307/boards/ch32v307v-r1-1v0/board.h | 50 +++++++++++++ hw/bsp/ch32v307/family.c | 71 +++++++++++-------- 2 files changed, 92 insertions(+), 29 deletions(-) create mode 100644 hw/bsp/ch32v307/boards/ch32v307v-r1-1v0/board.h diff --git a/hw/bsp/ch32v307/boards/ch32v307v-r1-1v0/board.h b/hw/bsp/ch32v307/boards/ch32v307v-r1-1v0/board.h new file mode 100644 index 000000000..0eab34916 --- /dev/null +++ b/hw/bsp/ch32v307/boards/ch32v307v-r1-1v0/board.h @@ -0,0 +1,50 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2023 Ha Thach (tinyusb.org) for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef BOARD_H_ +#define BOARD_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +// LED: need to wire pin LED1 to PC0 in the J3 header +#define LED_PORT GPIOC +#define LED_PIN GPIO_Pin_0 +#define LED_STATE_ON 0 +#define LED_CLOCK_EN() RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE) + +// Button: need to wire pin KEY to PC1 in the J3 header +#define BUTTON_PORT GPIOC +#define BUTTON_PIN GPIO_Pin_1 +#define BUTTON_STATE_ACTIVE 0 +#define BUTTON_CLOCK_EN() do { } while(0) // same as LED clock, no need to do anything + +// TODO UART port + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/hw/bsp/ch32v307/family.c b/hw/bsp/ch32v307/family.c index 0260918ab..65519ce50 100644 --- a/hw/bsp/ch32v307/family.c +++ b/hw/bsp/ch32v307/family.c @@ -28,19 +28,22 @@ #include "debug_uart.h" #include "ch32v30x.h" -#include "../board.h" +#include "bsp/board.h" +#include "board.h" //--------------------------------------------------------------------+ // Forward USB interrupt events to TinyUSB IRQ Handler //--------------------------------------------------------------------+ -void USBHS_IRQHandler(void) __attribute__((naked)); -void USBHS_IRQHandler(void) { - __asm volatile ("call USBHS_IRQHandler_impl; mret"); +void USBHS_IRQHandler (void) __attribute__((naked)); +void USBHS_IRQHandler (void) +{ + __asm volatile ("call USBHS_IRQHandler_impl; mret"); } -__attribute__ ((used)) void USBHS_IRQHandler_impl(void) { - tud_int_handler(0); +__attribute__ ((used)) void USBHS_IRQHandler_impl (void) +{ + tud_int_handler(0); } //--------------------------------------------------------------------+ @@ -49,13 +52,13 @@ __attribute__ ((used)) void USBHS_IRQHandler_impl(void) { 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; } void board_init(void) { @@ -63,7 +66,6 @@ void board_init(void) { /* Disable interrupts during init */ __disable_irq(); - #if CFG_TUSB_OS == OPT_OS_NONE SysTick_Config(SystemCoreClock / 1000); #endif @@ -79,11 +81,19 @@ void board_init(void) { GPIO_InitTypeDef GPIO_InitStructure = {0}; - RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE); - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; + // LED + LED_CLOCK_EN(); + GPIO_InitStructure.GPIO_Pin = LED_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; - GPIO_Init(GPIOC, &GPIO_InitStructure); + GPIO_Init(LED_PORT, &GPIO_InitStructure); + + // Button + BUTTON_CLOCK_EN(); + GPIO_InitStructure.GPIO_Pin = BUTTON_PIN; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; + GPIO_Init(BUTTON_PORT, &GPIO_InitStructure); /* Enable interrupts globally */ __enable_irq(); @@ -114,26 +124,29 @@ uint32_t board_millis(void) { return system_ticks; } // Board porting API //--------------------------------------------------------------------+ -void board_led_write(bool state) { - (void) state; - - GPIO_WriteBit(GPIOC, GPIO_Pin_0, state); +void board_led_write (bool state) +{ + GPIO_WriteBit(LED_PORT, LED_PIN, state); } -uint32_t board_button_read(void) { - return false; +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; +int board_uart_read (uint8_t *buf, int len) +{ + (void) buf; + (void) len; return 0; } -int board_uart_write(void const* buf, int len) { +int board_uart_write (void const *buf, int len) +{ int txsize = len; - while (txsize--) { - uart_write(*(uint8_t const*)buf); + while ( txsize-- ) + { + uart_write(*(uint8_t const*) buf); buf++; } return len; From 3cf21c66b6ef19c6dd648f952e8679a654b15803 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 12 Jan 2023 15:26:48 +0700 Subject: [PATCH 18/20] add dcd_remote_wakeup() stub --- src/portable/wch/ch32v307/dcd_usbhs.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/portable/wch/ch32v307/dcd_usbhs.c b/src/portable/wch/ch32v307/dcd_usbhs.c index 7a0dcfc23..b7a79e166 100644 --- a/src/portable/wch/ch32v307/dcd_usbhs.c +++ b/src/portable/wch/ch32v307/dcd_usbhs.c @@ -130,6 +130,11 @@ void dcd_set_address(uint8_t rhport, uint8_t dev_addr) { dcd_edpt_xfer(rhport, 0x80, NULL, 0); } +void dcd_remote_wakeup(uint8_t rhport) +{ + (void) rhport; +} + void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const *request) { (void)rhport; From 160d64b00a1b4ad46cd61cba3b649a07901d3c65 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 12 Jan 2023 15:34:29 +0700 Subject: [PATCH 19/20] minor clean up. ch32v307 has issue with uart LOG=2 (skipping characters) --- .../boards/ch32v307v-r1-1v0/debug_uart.c | 48 +++++++++---------- hw/bsp/ch32v307/family.c | 17 ++++--- hw/bsp/ch32v307/family.mk | 5 -- 3 files changed, 35 insertions(+), 35 deletions(-) diff --git a/hw/bsp/ch32v307/boards/ch32v307v-r1-1v0/debug_uart.c b/hw/bsp/ch32v307/boards/ch32v307v-r1-1v0/debug_uart.c index ad8b32957..45fc9e3aa 100644 --- a/hw/bsp/ch32v307/boards/ch32v307v-r1-1v0/debug_uart.c +++ b/hw/bsp/ch32v307/boards/ch32v307v-r1-1v0/debug_uart.c @@ -77,34 +77,34 @@ void uart_sync(void) void usart_printf_init(uint32_t baudrate) { - GPIO_InitTypeDef GPIO_InitStructure; - USART_InitTypeDef USART_InitStructure; + GPIO_InitTypeDef GPIO_InitStructure; + USART_InitTypeDef USART_InitStructure; - tx_produce = 0; - tx_consume = 0; + tx_produce = 0; + tx_consume = 0; - RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE); + RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE); - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; - GPIO_Init(GPIOA, &GPIO_InitStructure); + GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; + GPIO_Init(GPIOA, &GPIO_InitStructure); - USART_InitStructure.USART_BaudRate = baudrate; - USART_InitStructure.USART_WordLength = USART_WordLength_8b; - USART_InitStructure.USART_StopBits = USART_StopBits_1; - USART_InitStructure.USART_Parity = USART_Parity_No; - USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; - USART_InitStructure.USART_Mode = USART_Mode_Tx; + USART_InitStructure.USART_BaudRate = baudrate; + USART_InitStructure.USART_WordLength = USART_WordLength_8b; + USART_InitStructure.USART_StopBits = USART_StopBits_1; + USART_InitStructure.USART_Parity = USART_Parity_No; + USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; + USART_InitStructure.USART_Mode = USART_Mode_Tx; - USART_Init(USART1, &USART_InitStructure); - USART_ITConfig(USART1, USART_IT_TC, ENABLE); - USART_Cmd(USART1, ENABLE); + USART_Init(USART1, &USART_InitStructure); + USART_ITConfig(USART1, USART_IT_TC, ENABLE); + USART_Cmd(USART1, ENABLE); - NVIC_InitTypeDef NVIC_InitStructure = {0}; - NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; - NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; - NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; - NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; - NVIC_Init(&NVIC_InitStructure); + NVIC_InitTypeDef NVIC_InitStructure = { 0 }; + NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; + NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; + NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; + NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; + NVIC_Init(&NVIC_InitStructure); } diff --git a/hw/bsp/ch32v307/family.c b/hw/bsp/ch32v307/family.c index 65519ce50..d5602c7b4 100644 --- a/hw/bsp/ch32v307/family.c +++ b/hw/bsp/ch32v307/family.c @@ -106,17 +106,22 @@ void board_init(void) { volatile uint32_t system_ticks = 0; /* Small workaround to support HW stack save/restore */ -void SysTick_Handler(void) __attribute__((naked)); -void SysTick_Handler(void) { - __asm volatile ("call SysTick_Handler_impl; mret"); +void SysTick_Handler (void) __attribute__((naked)); +void SysTick_Handler (void) +{ + __asm volatile ("call SysTick_Handler_impl; mret"); } -__attribute__((used)) void SysTick_Handler_impl(void) { - SysTick->SR=0; +__attribute__((used)) void SysTick_Handler_impl (void) +{ + SysTick->SR = 0; system_ticks++; } -uint32_t board_millis(void) { return system_ticks; } +uint32_t board_millis (void) +{ + return system_ticks; +} #endif diff --git a/hw/bsp/ch32v307/family.mk b/hw/bsp/ch32v307/family.mk index 49e496853..15f6724a8 100644 --- a/hw/bsp/ch32v307/family.mk +++ b/hw/bsp/ch32v307/family.mk @@ -13,8 +13,6 @@ CH32V307_SDK_SRC = $(CH32V307_SDK)/EVT/EXAM/SRC include $(TOP)/$(BOARD_PATH)/board.mk -SKIP_NANOLIB = 1 - CFLAGS += \ -flto \ -march=rv32imac \ @@ -30,9 +28,6 @@ CFLAGS += \ -Xlinker --gc-sections \ -DBOARD_TUD_MAX_SPEED=OPT_MODE_HIGH_SPEED -LDFLAGS += \ - -Xlinker --gc-sections --specs=nano.specs --specs=nosys.specs - SRC_C += \ src/portable/wch/ch32v307/dcd_usbhs.c \ $(CH32V307_SDK_SRC)/Core/core_riscv.c \ From b1021d53f3617491656c50f6a1cb2c21da029f6a Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 12 Jan 2023 15:38:18 +0700 Subject: [PATCH 20/20] add TUP_RHPORT_HIGHSPEED for ch32v307 --- src/common/tusb_mcu.h | 2 +- src/tusb_option.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/common/tusb_mcu.h b/src/common/tusb_mcu.h index b37ce9a34..0b10c5118 100644 --- a/src/common/tusb_mcu.h +++ b/src/common/tusb_mcu.h @@ -278,7 +278,7 @@ //------------- WCH -------------// #elif TU_CHECK_MCU(OPT_MCU_CH32V307) #define TUP_DCD_ENDPOINT_MAX 16 - + #define TUP_RHPORT_HIGHSPEED 1 #endif //--------------------------------------------------------------------+ diff --git a/src/tusb_option.h b/src/tusb_option.h index 92fbbd33f..67377b7ec 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -161,7 +161,7 @@ typedef int make_iso_compilers_happy; #define OPT_MCU_F1C100S 2100 ///< Allwinner F1C100s family // WCH -#define OPT_MCU_CH32V307 2200 ///< WCH CH32V307 config +#define OPT_MCU_CH32V307 2200 ///< WCH CH32V307 // Helper to check if configured MCU is one of listed // Apply _TU_CHECK_MCU with || as separator to list of input