mirror of
https://github.com/hathach/tinyusb.git
synced 2025-03-22 10:20:55 +00:00
Merge pull request #1405 from gregdavill/ch32v307
Add WCH CH32V307 port
This commit is contained in:
commit
fa9d19027b
1
.github/workflows/build_riscv.yml
vendored
1
.github/workflows/build_riscv.yml
vendored
@ -27,6 +27,7 @@ jobs:
|
||||
matrix:
|
||||
family:
|
||||
# Alphabetical order
|
||||
- 'ch32v307'
|
||||
- 'fomu'
|
||||
- 'gd32vf103'
|
||||
steps:
|
||||
|
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -146,6 +146,9 @@
|
||||
[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
|
||||
[submodule "hw/mcu/raspberry_pi/Pico-PIO-USB"]
|
||||
path = hw/mcu/raspberry_pi/Pico-PIO-USB
|
||||
url = https://github.com/sekigon-gonnoc/Pico-PIO-USB.git
|
||||
|
@ -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+, WB
|
||||
- **TI:** MSP430, MSP432E4, TM4C123
|
||||
- **ValentyUSB:** eptri
|
||||
- **WCH:** CH32V307
|
||||
|
||||
Here is the list of `Supported Devices`_ that can be used with provided examples.
|
||||
|
||||
|
@ -106,6 +106,8 @@ Supported MCUs
|
||||
+--------------+-----------------------+--------+------+-----------+-------------------+--------------+
|
||||
| ValentyUSB | eptri | ✔ | ✖ | ✖ | eptri | |
|
||||
+--------------+-----------------------+--------+------+-----------+-------------------+--------------+
|
||||
| WCH | CH32V307 | ✔ | | ✔ | ch32v307 | |
|
||||
+--------------+-----------------------+--------+------+-----------+-------------------+--------------+
|
||||
|
||||
|
||||
Table Legend
|
||||
@ -397,3 +399,8 @@ Tomu
|
||||
----
|
||||
|
||||
- `Fomu <https://www.crowdsupply.com/sutajio-kosagi/fomu>`__
|
||||
|
||||
WCH
|
||||
---
|
||||
|
||||
- `CH32V307V-R1-1v0 <https://lcsc.com/product-detail/Development-Boards-Kits_WCH-Jiangsu-Qin-Heng-CH32V307V-EVT-R1_C2943980.html>`
|
||||
|
@ -1,3 +1,4 @@
|
||||
mcu:CH32V307
|
||||
mcu:CXD56
|
||||
mcu:F1C100S
|
||||
mcu:GD32VF103
|
||||
@ -8,4 +9,4 @@ mcu:SAMD11
|
||||
mcu:SAMX7X
|
||||
mcu:VALENTYUSB_EPTRI
|
||||
family:broadcom_32bit
|
||||
family:broadcom_64bit
|
||||
family:broadcom_64bit
|
||||
|
@ -1,3 +1,4 @@
|
||||
mcu:CH32V307
|
||||
mcu:CXD56
|
||||
mcu:F1C100S
|
||||
mcu:GD32VF103
|
||||
@ -8,4 +9,4 @@ mcu:SAMD11
|
||||
mcu:SAMX7X
|
||||
mcu:VALENTYUSB_EPTRI
|
||||
family:broadcom_32bit
|
||||
family:broadcom_64bit
|
||||
family:broadcom_64bit
|
||||
|
50
hw/bsp/ch32v307/boards/ch32v307v-r1-1v0/board.h
Normal file
50
hw/bsp/ch32v307/boards/ch32v307v-r1-1v0/board.h
Normal file
@ -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
|
1
hw/bsp/ch32v307/boards/ch32v307v-r1-1v0/board.mk
Normal file
1
hw/bsp/ch32v307/boards/ch32v307v-r1-1v0/board.mk
Normal file
@ -0,0 +1 @@
|
||||
LD_FILE = $(FAMILY_PATH)/ch32v307.ld
|
110
hw/bsp/ch32v307/boards/ch32v307v-r1-1v0/debug_uart.c
Normal file
110
hw/bsp/ch32v307/boards/ch32v307v-r1-1v0/debug_uart.c
Normal file
@ -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 <ch32v30x.h>
|
||||
|
||||
|
||||
#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);
|
||||
}
|
31
hw/bsp/ch32v307/boards/ch32v307v-r1-1v0/debug_uart.h
Normal file
31
hw/bsp/ch32v307/boards/ch32v307v-r1-1v0/debug_uart.h
Normal file
@ -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 <stdint.h>
|
||||
|
||||
void uart_write(char c);
|
||||
void uart_sync(void);
|
||||
void usart_printf_init(uint32_t baudrate);
|
170
hw/bsp/ch32v307/ch32v307.ld
Normal file
170
hw/bsp/ch32v307/ch32v307.ld
Normal file
@ -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
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
43
hw/bsp/ch32v307/ch32v30x_conf.h
Normal file
43
hw/bsp/ch32v307/ch32v30x_conf.h
Normal file
@ -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 */
|
||||
|
||||
|
||||
|
||||
|
||||
|
49
hw/bsp/ch32v307/ch32v30x_it.c
Normal file
49
hw/bsp/ch32v307/ch32v30x_it.c
Normal file
@ -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)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
|
18
hw/bsp/ch32v307/ch32v30x_it.h
Normal file
18
hw/bsp/ch32v307/ch32v30x_it.h
Normal file
@ -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 */
|
||||
|
||||
|
384
hw/bsp/ch32v307/core_riscv.h
Normal file
384
hw/bsp/ch32v307/core_riscv.h
Normal file
@ -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
|
||||
|
||||
|
||||
|
||||
|
||||
|
178
hw/bsp/ch32v307/family.c
Normal file
178
hw/bsp/ch32v307/family.c
Normal file
@ -0,0 +1,178 @@
|
||||
/*
|
||||
* 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 "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");
|
||||
}
|
||||
|
||||
__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};
|
||||
|
||||
// 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(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();
|
||||
|
||||
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)
|
||||
{
|
||||
GPIO_WriteBit(LED_PORT, LED_PIN, state);
|
||||
}
|
||||
|
||||
uint32_t board_button_read (void)
|
||||
{
|
||||
return BUTTON_STATE_ACTIVE == GPIO_ReadInputDataBit(BUTTON_PORT, BUTTON_PIN);
|
||||
}
|
||||
|
||||
int board_uart_read (uint8_t *buf, int len)
|
||||
{
|
||||
(void) buf;
|
||||
(void) len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int board_uart_write (void const *buf, int len)
|
||||
{
|
||||
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 */
|
64
hw/bsp/ch32v307/family.mk
Normal file
64
hw/bsp/ch32v307/family.mk
Normal file
@ -0,0 +1,64 @@
|
||||
# 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
|
||||
|
||||
include $(TOP)/$(BOARD_PATH)/board.mk
|
||||
|
||||
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_CH32V307 \
|
||||
-Xlinker --gc-sections \
|
||||
-DBOARD_TUD_MAX_SPEED=OPT_MODE_HIGH_SPEED
|
||||
|
||||
SRC_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_SDK_SRC)/Startup/startup_ch32v30x_D8C.S
|
||||
|
||||
INC += \
|
||||
$(TOP)/$(BOARD_PATH) \
|
||||
$(TOP)/$(CH32V307_SDK_SRC)/Peripheral/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 $(TOP)/$(FAMILY_PATH)/wch-riscv.cfg -c init -c halt -c "program $<" -c wlink_reset_resume -c exit
|
776
hw/bsp/ch32v307/system_ch32v30x.c
Normal file
776
hw/bsp/ch32v307/system_ch32v30x.c
Normal file
@ -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
|
30
hw/bsp/ch32v307/system_ch32v30x.h
Normal file
30
hw/bsp/ch32v307/system_ch32v30x.h
Normal file
@ -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 */
|
||||
|
||||
|
||||
|
15
hw/bsp/ch32v307/wch-riscv.cfg
Normal file
15
hw/bsp/ch32v307/wch-riscv.cfg
Normal file
@ -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"
|
1
hw/mcu/wch/ch32v307
Submodule
1
hw/mcu/wch/ch32v307
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 17761f5cf9dbbf2dcf665b7c04934188add20082
|
@ -275,6 +275,10 @@
|
||||
#elif TU_CHECK_MCU(OPT_MCU_F1C100S)
|
||||
#define TUP_DCD_ENDPOINT_MAX 4
|
||||
|
||||
//------------- WCH -------------//
|
||||
#elif TU_CHECK_MCU(OPT_MCU_CH32V307)
|
||||
#define TUP_DCD_ENDPOINT_MAX 16
|
||||
#define TUP_RHPORT_HIGHSPEED 1
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
|
345
src/portable/wch/ch32v307/ch32_usbhs_reg.h
Normal file
345
src/portable/wch/ch32v307/ch32_usbhs_reg.h
Normal file
@ -0,0 +1,345 @@
|
||||
#ifndef _USB_CH32_USBHS_REG_H
|
||||
#define _USB_CH32_USBHS_REG_H
|
||||
|
||||
#include <ch32v30x.h>
|
||||
|
||||
/******************* 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 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
|
||||
|
||||
/* 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
|
391
src/portable/wch/ch32v307/dcd_usbhs.c
Normal file
391
src/portable/wch/ch32v307/dcd_usbhs.c
Normal file
@ -0,0 +1,391 @@
|
||||
/*
|
||||
* 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_CH32V307)
|
||||
#include "device/dcd.h"
|
||||
|
||||
#include "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 */
|
||||
TU_ATTR_ALIGNED(4) uint8_t EP0_DatabufHD[64]; // ep0(64)
|
||||
|
||||
volatile uint8_t USBHS_Dev_Endp0_Tog = 0x01;
|
||||
|
||||
void dcd_init(uint8_t rhport) {
|
||||
(void)rhport;
|
||||
|
||||
memset(&xfer_status, 0, sizeof(xfer_status));
|
||||
|
||||
USBHSD->HOST_CTRL = 0x00;
|
||||
USBHSD->HOST_CTRL = USBHS_PHY_SUSPENDM;
|
||||
|
||||
USBHSD->CONTROL = 0;
|
||||
|
||||
#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
|
||||
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_remote_wakeup(uint8_t rhport)
|
||||
{
|
||||
(void) rhport;
|
||||
}
|
||||
|
||||
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
|
@ -160,6 +160,9 @@ typedef int make_iso_compilers_happy;
|
||||
// Allwinner
|
||||
#define OPT_MCU_F1C100S 2100 ///< Allwinner F1C100s family
|
||||
|
||||
// WCH
|
||||
#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
|
||||
#define _TU_CHECK_MCU(_m) (CFG_TUSB_MCU == _m)
|
||||
|
Loading…
x
Reference in New Issue
Block a user