[ch569w]ch569w support for uart spi serdes usb and watchdog from Song_yanguang

it is OK
This commit is contained in:
xuedongliang 2025-08-22 15:46:26 +08:00
commit e67eca9a8b
46 changed files with 4836 additions and 81 deletions

View File

@ -0,0 +1,293 @@
#
# Automatically generated file; DO NOT EDIT.
# XiZi_IIoT Project Configuration
#
CONFIG_BOARD_CH569W=y
CONFIG_ARCH_RISCV=y
#
# ch569w feature
#
CONFIG_BSP_USING_UART=y
CONFIG_BSP_USING_UART1=y
CONFIG_SERIAL_BUS_NAME_1="uart1"
CONFIG_SERIAL_DRV_NAME_1="uart1_drv"
CONFIG_SERIAL_1_DEVICE_NAME_0="uart1_dev1"
#
# Hardware feature
#
CONFIG_RESOURCES_SERIAL=y
CONFIG_SERIAL_USING_DMA=y
CONFIG_SERIAL_RB_BUFSZ=128
#
# Kernel feature
#
#
# separate compile(choose none for compile once)
#
# CONFIG_SEPARATE_COMPILE is not set
# CONFIG_COMPILER_APP is not set
# CONFIG_APP_STARTUP_FROM_SDCARD is not set
CONFIG_APP_STARTUP_FROM_FLASH=y
# CONFIG_COMPILER_KERNEL is not set
#
# Memory Management
#
# CONFIG_KERNEL_MEMBLOCK is not set
CONFIG_MEM_ALIGN_SIZE=8
# CONFIG_MEM_EXTERN_SRAM is not set
CONFIG_MM_PAGE_SIZE=4096
#
# Using small memory allocator
#
CONFIG_KERNEL_SMALL_MEM_ALLOC=y
CONFIG_SMALL_NUMBER_32B=64
CONFIG_SMALL_NUMBER_64B=32
#
# Task feature
#
CONFIG_USER_APPLICATION=y
# CONFIG_TASK_ISOLATION is not set
# CONFIG_KERNEL_CAPABILITY is not set
#
# Inter-Task communication
#
CONFIG_KERNEL_SEMAPHORE=y
CONFIG_KERNEL_MUTEX=y
CONFIG_KERNEL_EVENT=y
CONFIG_KERNEL_MESSAGEQUEUE=y
CONFIG_KERNEL_SOFTTIMER=y
CONFIG_SCHED_POLICY_RR_REMAINSLICE=y
# CONFIG_SCHED_POLICY_RR is not set
# CONFIG_SCHED_POLICY_FIFO is not set
# CONFIG_KTASK_PRIORITY_8 is not set
CONFIG_KTASK_PRIORITY_32=y
# CONFIG_KTASK_PRIORITY_256 is not set
CONFIG_KTASK_PRIORITY_MAX=32
CONFIG_TICK_PER_SECOND=1000
CONFIG_KERNEL_STACK_OVERFLOW_CHECK=y
CONFIG_IDLE_KTASK_STACKSIZE=1024
CONFIG_ZOMBIE_KTASK_STACKSIZE=2048
#
# Kernel Console
#
CONFIG_KERNEL_CONSOLE=y
CONFIG_KERNEL_BANNER=y
CONFIG_KERNEL_CONSOLEBUF_SIZE=128
#
# Kernel Hook
#
# CONFIG_KERNEL_HOOK is not set
#
# Command shell
#
CONFIG_TOOL_SHELL=y
CONFIG_SHELL_ENTER_CR=y
CONFIG_SHELL_ENTER_LF=y
CONFIG_SHELL_ENTER_CR_AND_LF=y
# CONFIG_SHELL_ENTER_CRLF is not set
#
# Set shell user control
#
CONFIG_SHELL_DEFAULT_USER="letter"
CONFIG_SHELL_DEFAULT_USER_PASSWORD=""
CONFIG_SHELL_LOCK_TIMEOUT=10000
#
# Set shell config param
#
CONFIG_SHELL_TASK_STACK_SIZE=4096
CONFIG_SHELL_TASK_PRIORITY=20
CONFIG_SHELL_MAX_NUMBER=5
CONFIG_SHELL_PARAMETER_MAX_NUMBER=8
CONFIG_SHELL_HISTORY_MAX_NUMBER=5
CONFIG_SHELL_PRINT_BUFFER=128
CONFIG_SHELL_HELP_SHOW_PERMISSION=y
# CONFIG_SHELL_HELP_LIST_USER is not set
CONFIG_SHELL_HELP_LIST_VAR=y
# CONFIG_SHELL_HELP_LIST_KEY is not set
#
# Kernel data structure Manage
#
CONFIG_KERNEL_QUEUEMANAGE=y
CONFIG_KERNEL_WORKQUEUE=y
CONFIG_WORKQUEUE_KTASK_STACKSIZE=2048
CONFIG_WORKQUEUE_KTASK_PRIORITY=23
CONFIG_QUEUE_MAX=16
CONFIG_KERNEL_WAITQUEUE=y
CONFIG_KERNEL_DATAQUEUE=y
# CONFIG_KERNEL_CIRCULAR_AREA is not set
# CONFIG_KERNEL_AVL_TREE is not set
#
# Kernel components init
#
CONFIG_KERNEL_COMPONENTS_INIT=y
CONFIG_ENV_INIT_KTASK_STACK_SIZE=8192
CONFIG_KERNEL_USER_MAIN=y
CONFIG_NAME_NUM_MAX=32
# CONFIG_KERNEL_DEBUG is not set
# CONFIG_ARCH_SMP is not set
#
# hash table config
#
CONFIG_ID_HTABLE_SIZE=16
CONFIG_ID_NUM_MAX=128
# CONFIG_KERNEL_TEST is not set
#
# Kernel Lib
#
CONFIG_LIB=y
CONFIG_LIB_POSIX=y
CONFIG_LIB_NEWLIB=y
# CONFIG_LIB_MUSLLIB is not set
# CONFIG_LIB_OTHER is not set
#
# C++ features
#
# CONFIG_LIB_CPLUSPLUS is not set
#
# File system
#
CONFIG_FS_VFS=y
CONFIG_VFS_USING_WORKDIR=y
CONFIG_FS_VFS_DEVFS=y
CONFIG_FS_VFS_FATFS=y
# CONFIG_FS_CH376 is not set
# CONFIG_FS_LWEXT4 is not set
#
# Tool feature
#
#
# OTA function
#
# CONFIG_TOOL_USING_OTA is not set
#
# APP_Framework
#
#
# Framework
#
CONFIG_TRANSFORM_LAYER_ATTRIUBUTE=y
CONFIG_ADD_XIZI_FEATURES=y
# CONFIG_ADD_NUTTX_FEATURES is not set
# CONFIG_ADD_RTTHREAD_FEATURES is not set
# CONFIG_SUPPORT_SENSOR_FRAMEWORK is not set
# CONFIG_SUPPORT_CONNECTION_FRAMEWORK is not set
# CONFIG_SUPPORT_KNOWING_FRAMEWORK is not set
# CONFIG_SUPPORT_CONTROL_FRAMEWORK is not set
#
# Security
#
# CONFIG_CRYPTO is not set
# CONFIG_MBEDTLS is not set
#
# Applications
#
#
# config stack size and priority of main task
#
CONFIG_MAIN_KTASK_STACK_SIZE=1024
CONFIG_MAIN_KTASK_PRIORITY=16
#
# test app
#
# CONFIG_USER_TEST is not set
#
# connection app
#
# CONFIG_APPLICATION_CONNECTION is not set
#
# control app
#
#
# knowing app
#
# CONFIG_APPLICATION_KNOWING is not set
#
# sensor app
#
# CONFIG_APPLICATION_SENSOR is not set
# CONFIG_USING_EMBEDDED_DATABASE_APP is not set
# CONFIG_APP_USING_WEBNET is not set
# CONFIG_APPLICATION_WEBSERVER is not set
#
# app lib
#
CONFIG_APP_SELECT_NEWLIB=y
# CONFIG_APP_SELECT_OTHER_LIB is not set
#
# lib using cJSON
#
# CONFIG_LIB_USING_CJSON is not set
#
# lib using queue
#
# CONFIG_LIB_USING_QUEUE is not set
#
# lib using LVGL
#
# CONFIG_LIB_LV is not set
#
# lvgl image display parameter settings
#
CONFIG_LVGL_WIDTH=320
CONFIG_LVGL_HEIGHT=320
#
# lib using embedded_database
#
# CONFIG_USING_EMBEDDED_DATABASE is not set
#
# lib using LoRaWan
#
# CONFIG_LIB_USING_LORAWAN is not set
#
# lib using MQTT
#
# CONFIG_LIB_USING_MQTT is not set
#
# lib using JerryScript
#
# CONFIG_LIB_USING_JERRYSCRIPT is not set
#
# lib using SQLite
#
# CONFIG_LIB_USING_SQLITE is not set

View File

@ -1,78 +1,75 @@
# 1. 简介
| 硬件 | 描述 |
| --------- | ----------------------------------------- |
| 芯片型号 | CH569W |
| CPU | 单核RISC-V3A |
| 主频 | 120MHz |
| 片内SRAM | 32/64/96KB 可配置的 128 位宽 SRAMRAMX |
| 片内FLASH | 448KB 用户应用程序存储区 CodeFlash |
| 外设 | UART等 |
# 2. 克隆代码
将XiUOS的源代码克隆下来
```bash
git clone https://gitlink.org.cn/xuos/xiuos.git
```
# 3. 下载编译工具链
编译环境Ubuntu 20.04.6 LTS
编译工具链riscv-none-embed-gccxpack-riscv-none-embed-gcc-8.2.0-3.1
编译工具链可到Github进行下载https://github.com/xpack-dev-tools/riscv-none-embed-gcc-xpack/releases/download/v8.2.0-3.1/xpack-riscv-none-embed-gcc-8.2.0-3.1-linux-x64.tgz
下载完成后将其移动到`/opt`目录下,并进行解压:
```bash
sudo tar -xvzf xpack-riscv-none-embed-gcc-8.2.0-3.1-linux-x64.tgz
```
# 4. 编译
## 方式1推荐
可以在`Ubiquitous/XiZi_IIoT`目录下创建文件`script.sh`,内容如下:
```sh
#! /bin/env sh
export CROSS_COMPILE=/opt/xPacks/riscv-none-embed-gcc/8.2.0-3.1/bin/riscv-none-embed-
make BOARD=ch569w distclean # 将之前的编译生成文件清空
make BOARD=ch569w menuconfig
make BOARD=ch569w
```
创建之后,在命令行移动到`XiZi-IIOT`目录下,键入`./script`运行该脚本。
经过Kconfig配置、编译后即可在`Ubiquitous/XiZi_IIoT/build`目录中生成`XiZi-ch569w.bin`文件将该文件拷贝至Windows侧待下一步进行烧录。
> [!CAUTION]
>
> 如果`make BOARD=ch569w menuconfig`显示【无法找到`kconfig-mconf`】,需要先安装`ncurses-devel`和`kconfig-mconf`,如下:
>
> ```bash
> sudo apt install libncurses5-dev kconfig-frontends
# 5. 烧录
1. 沁恒微电子官网下载 WCHISPTool.exe 工具进行 bin 文件下载到芯片 flash 的操作。CH569W 芯片需要进入下载模式才能使用 ISP 工具下载代码,一般使用 USB 方式下载代码最为方便。
2. 将 CH569W 评估板使用 USB 插头对插头线和计算机连接起来。如图,打开 ISP 下载工具,芯片信号选择 CH569下载方式选择 USB将 CH569W 评估板断电,然后将下载配置脚(出厂默认为 PA5原理图上的HD0接地后对评估板上电此时 ISP 工具的 USB 设备列表中将显示新连上来的 CH569W 芯片。最后点击“下载”,即可使程序下载到评估版上的主芯片。
<img src="imgs/image_shaolukaifabanpaizhao.jpg" alt="image_shaolukaifabanpaizhao" style="zoom:30%;" />
<img src="imgs/image_shaoluruanjianjietu.png" alt="image_shaoluruanjianjietu" style="zoom:50%;" />
# 6. 启动
烧录完成后,并且将串口连接至电脑。
将评估板上电重新,即可看到操作系统启动的信息,如下:
# 1. 简介
| 硬件 | 描述 |
| --------- | ------------------------------------------------- |
| 芯片型号 | CH569W |
| CPU | 单核RISC-V3A |
| 主频 | 120MHz |
| 片内SRAM | 32/64/96KB 可配置的 128 位宽 SRAMRAMX |
| 片内FLASH | 448KB 用户应用程序存储区 CodeFlash |
| 外设 | 串口、SPI FLASH、SerDes网络、USBD CDC、Watchdog等 |
# 2. 克隆代码
将XiUOS的源代码克隆下来
```bash
git clone https://gitlink.org.cn/xuos/xiuos.git
```
# 3. 下载编译工具链
编译环境Ubuntu 20.04.6 LTS
编译工具链riscv-none-embed-gccxpack-riscv-none-embed-gcc-8.2.0-3.1
编译工具链可到Github进行下载https://github.com/xpack-dev-tools/riscv-none-embed-gcc-xpack/releases/download/v8.2.0-3.1/xpack-riscv-none-embed-gcc-8.2.0-3.1-linux-x64.tgz
下载完成后将其移动到`/opt`目录下,并进行解压:
```bash
sudo tar -xvzf xpack-riscv-none-embed-gcc-8.2.0-3.1-linux-x64.tgz
```
# 4. 编译
## 方式1推荐
可以在`Ubiquitous/XiZi_IIoT`目录下创建文件`script.sh`,内容如下:
```sh
#! /bin/env sh
export CROSS_COMPILE=/opt/xPacks/riscv-none-embed-gcc/8.2.0-3.1/bin/riscv-none-embed-
make BOARD=ch569w distclean # 将之前的编译生成文件清空
make BOARD=ch569w menuconfig
make BOARD=ch569w
```
创建之后,在命令行移动到`XiZi-IIOT`目录下,键入`./script.sh`运行该脚本。
经过Kconfig配置、编译后即可在`Ubiquitous/XiZi_IIoT/build`目录中生成`XiZi-ch569w.bin`文件将该文件拷贝至Windows本地电脑用于下一步烧录。
如果`make BOARD=ch569w menuconfig`显示【无法找到`kconfig-mconf`】,需要先安装`ncurses-devel`和`kconfig-mconf`,如下:
```bash
sudo apt install libncurses5-dev kconfig-frontends
```
# 5. 烧录
1. 沁恒微电子官网下载 WCHISPTool.exe 工具进行 bin 文件下载到芯片 flash 的操作。CH569W 芯片需要进入下载模式才能使用 ISP 工具下载代码,一般使用 USB 方式下载代码最为方便。
2. 将 CH569W 评估板使用 USB 插头对插头线和计算机连接起来。如图,打开 ISP 下载工具,芯片信号选择 CH569下载方式选择 USB将 CH569W 评估板断电,然后将下载配置脚(出厂默认为 PA5原理图上的HD0接地后对评估板上电此时 ISP 工具的 USB 设备列表中将显示新连上来的 CH569W 芯片。最后点击“下载”,即可使程序下载到评估版上的主芯片。
<img src="imgs/image_shaolukaifabanpaizhao.jpg" alt="image_shaolukaifabanpaizhao" style="zoom:30%;" />
<img src="imgs/image_shaoluruanjianjietu.png" alt="image_shaoluruanjianjietu" style="zoom:50%;" />
# 6. 启动
烧录完成后,并且将串口连接至电脑。
将评估板上电重新,即可看到操作系统启动的信息,如下:
![image_xitongqidongrizhi](imgs/image_xitongqidongrizhi.png)

View File

@ -29,11 +29,10 @@
void InitBoardHardware()
{
SystemInit(FREQ_SYS);
Delay_Init(FREQ_SYS);
SysTick_Config(FREQ_SYS / TICK_PER_SECOND);
SysTick_Config(FREQ_SYS / 8 / TICK_PER_SECOND);
PFIC_EnableIRQ(SWI_IRQn);
/* initialize memory system */
@ -45,6 +44,11 @@ void InitBoardHardware()
KPrintf("\nconsole init completed.\n");
#endif
#ifdef BSP_USING_SPI
int InitHwSpi(void);
InitHwSpi();
#endif
KPrintf("memory address range: [0x%08x - 0x%08x] ssize: %x\n", (x_ubase)MEMORY_START_ADDRESS,
(x_ubase)MEMORY_END_ADDRESS, MEMORY_STACK_SIZE);

View File

@ -14,5 +14,10 @@ export DEFINES := -DDEBUG=1
export ARCH = risc-v
export MCU = CH569W
ifeq ($(CONFIG_BSP_USING_SERDES), y)
export LINK_BOARD += $(KERNEL_ROOT)/board/ch569w/third_party_driver/serdes/libSERDES.a
endif
ifeq ($(CONFIG_BSP_USING_USBD), y)
export LINK_BOARD += $(KERNEL_ROOT)/board/ch569w/third_party_driver/usb/usbd/simulate_cdc/USB30/libCH56x_USB30_device_lib.a
endif

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 21 KiB

View File

@ -5,3 +5,28 @@ menuconfig BSP_USING_UART
if BSP_USING_UART
source "$BSP_DIR/third_party_driver/uart/Kconfig"
endif
menuconfig BSP_USING_SPI
bool "Using SPI device"
default y
if BSP_USING_SPI
source "$BSP_DIR/third_party_driver/spi/Kconfig"
endif
menuconfig BSP_USING_SERDES
bool "Using serdes device"
default y
if BSP_USING_SERDES
source "$BSP_DIR/third_party_driver/serdes/Kconfig"
endif
menuconfig BSP_USING_USB
bool "Using usb device"
default y
if BSP_USING_USB
source "$BSP_DIR/third_party_driver/usb/Kconfig"
endif
menuconfig BSP_USING_WDT
bool "Using watchdog timer device"
default n

View File

@ -1,7 +1,25 @@
SRC_DIR := Peripheral
SRC_DIR += sys
ifeq ($(CONFIG_BSP_USING_UART),y)
SRC_DIR += uart
endif
ifeq ($(CONFIG_BSP_USING_SPI),y)
SRC_DIR += spi
endif
ifeq ($(CONFIG_BSP_USING_SERDES),y)
SRC_DIR += serdes
endif
ifeq ($(CONFIG_BSP_USING_USB),y)
SRC_DIR += usb
endif
ifeq ($(CONFIG_BSP_USING_WDT),y)
SRC_DIR += wdt
endif
include $(KERNEL_ROOT)/compiler.mk

View File

@ -1341,6 +1341,7 @@ extern "C" {
#ifndef TABLE_IRQN
typedef enum IRQn
{
PWMX_OFFn = 0,
Reset_IRQn = 1,
NMI_IRQn = 2, /*!< Non Maskable Interrupt */
EXC_IRQn = 3, /*!< Exceptions Interrupt */
@ -1367,6 +1368,7 @@ typedef enum IRQn
ETH_IRQn = 34,
PMT_IRQn = 35,
ECDC_IRQn = 36,
END_OF_IRQn
} IRQn_Type;
#endif

View File

@ -0,0 +1,61 @@
# 1. 模块编译配置
开发板支持外设驱动UART、SPI FLASH、SerDes网络、USBD CDC、Watchdog。
默认配置文件路径:`xiuos/Ubiquitous/XiZi_IIoT$ ll board/ch569w/.defconfig`
可以通过命令`make BOARD=ch569w menuconfig` ,查看`ch569w feature`的默认配置。
![make-menuconfig.png](imgs/make-menuconfig.png)
# 2. 模块测试用例
下面介绍各模块的测试方法。
## 2.1 UART
UART用于串口打印和shell命令输入。
测试方法,查看设备启动日志,以及输入命令。
## 2.2 SPI FLASH
开发板的spi没有外部接口是连接的flash芯片。测试通过spi对flash的读写。
串口执行:`SpiFlashTest`
![SpiFlashTest.png](imgs/SpiFlashTest.png)
## 2.3 SerDes
串并互转控制器及收发器SerDes。系统内置了支持信号隔离和远距离传输的 SerDes 模块,支持 1.2Gbps 高速差分信号GXM/GXP
引脚),可以通过光纤模块或网线中的一个差分对等传输媒体,进行远距离数据传输。
开发板上SERDES为半双工接口仅单向传输使用。需要两个CH569设备通过SerDes进行通信。
SerDes测试需要先执行`SerdesRxTest`等到SerdesRx打印初始化成功后在另有一个设备上执行`SerdesTxTest`。
![SerdesTestRx.png](imgs/SerdesTestRx.png)
![SerdesTxTest.png](imgs/SerdesTxTest.png)
## 2.4 USBD CDC
USBD CDCUSB Device Communication Device Class是一种将 USB 设备模拟为串口(虚拟串口)的功能实现,允许设备通过 USB 与主机进行串行数据通信。
串口输入命令:`UsbdCdcTest`在电脑的设备管理器查看出现新增COM口。
![UsbdCdcTestCmd.png](imgs/UsbdCdcTestCmd.png)
![UsbdCdcTestUSB20.png](imgs/UsbdCdcTestUSB20.png)
## 2.5 Watchdog
看门狗测试需要编译时选择打开watchdog功能。
系统在后台运行wdt通过命令`WdtTest`,停止喂狗,触发系统重启。
![WdtTest.png](imgs/WdtTest.png)

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

View File

@ -0,0 +1,56 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : CH56x_usb20.h
* Author : WCH
* Version : V1.2
* Date : 2024/07/10
* Description :
*********************************************************************************
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
* Attention: This software (modified or not) and binary are used for
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
*******************************************************************************/
#ifndef USB20_CH56X_USB20_H_
#define USB20_CH56X_USB20_H_
#include "CH56x_common.h"
#ifdef __cplusplus
extern "C" {
#endif
/* Global define */
#define U20_MAXPACKET_LEN 512
#define U20_UEP0_MAXSIZE 64
#define PID_OUT 0
#define PID_SOF 1
#define PID_IN 2
/* Global Variable */
typedef struct __attribute__((packed))
{
UINT8 dev_speed;
UINT8 dev_addr;
UINT8 dev_config_value;
UINT8 dev_sleep_status;
UINT8 dev_enum_status;
}DevInfo_Typedef;
extern const UINT8 hs_device_descriptor[];
extern const UINT8 hs_config_descriptor[];
extern const UINT8 hs_string_descriptor0[];
extern const UINT8 hs_string_descriptor1[];
extern const UINT8 hs_string_descriptor2[];
extern const UINT8 hs_bos_descriptor[];
/* Function declaration */
void USB20_Device_Init ( FunctionalState sta );
UINT16 U20_NonStandard_Request_Deal();
UINT16 U20_Standard_Request_Deal();
UINT16 U20_Endp0_IN_Callback(void);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,61 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : CH56x_usb30.h
* Author : WCH
* Version : V1.2
* Date : 2024/07/10
* Description :
*********************************************************************************
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
* Attention: This software (modified or not) and binary are used for
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
*******************************************************************************/
#ifndef USB30_CH56X_USB30_H_
#define USB30_CH56X_USB30_H_
#ifdef __cplusplus
extern "C" {
#endif
#include "CH56x_common.h"
/* Global define */
#define endpoint_1_OUT_burst_level 1
#define endpoint_1_IN_burst_level 1
#define endpoint_2_OUT_burst_level 1
#define endpoint_2_IN_burst_level 1
#define SIZE_DEVICE_DESC 18
#define SIZE_CONFIG_DESC 85
#define SIZE_STRING_LANGID 4
#define SIZE_STRING_VENDOR 8
#define SIZE_STRING_PRODUCT 38
#define SIZE_STRING_SERIAL 22
#define SIZE_BOS_DESC 22
#define SIZE_STRING_OS 18
#define LINK_STA_1 (1<<0)
#define LINK_STA_3 (1<<2)
/* Global Variable */
extern __attribute__ ((aligned(16))) UINT8 endp0RTbuff[512] __attribute__((section(".DMADATA")));
extern __attribute__ ((aligned(16))) UINT8 endp1RTbuff[4096] __attribute__((section(".DMADATA")));
extern __attribute__ ((aligned(16))) UINT8 endp2Rxbuff[4096] __attribute__((section(".DMADATA")));
extern __attribute__ ((aligned(16))) UINT8 endp2Txbuff[4096] __attribute__((section(".DMADATA")));
extern UINT8V Link_Sta;
/* Function declaration */
void USB30D_init(FunctionalState sta);
void TMR0_IRQHandler() __attribute__((interrupt()));
void LINK_IRQHandler() __attribute__((interrupt()));
void USBSS_IRQHandler(void) __attribute__((interrupt())); //USB3.0 interrupt service
#ifdef __cplusplus
}
#endif
#endif /* USER_USB30_DESC_H_ */

View File

@ -0,0 +1,482 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : CH56x_usb30_lib.h
* Author : WCH
* Version : V1.2
* Date : 2024/07/10
* Description :
*********************************************************************************
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
* Attention: This software (modified or not) and binary are used for
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
*******************************************************************************/
#ifndef USB30_CH56X_USB30_LIB_H_
#define USB30_CH56X_USB30_LIB_H_
#ifdef __cplusplus
extern "C" {
#endif
#include "CH56x_common.h"
// link CFG
#define TERM_EN (1<<1)
#define PIPE_RESET (1<<3)
#define LFPS_RX_PD (1<<5)
#define CFG_EQ_EN (1<<6)
#define TX_SWING (1<<7)
#define DEEMPH_CFG (1<<8)
#define POWER_MODE_0 ((UINT32)0x00000000)
#define POWER_MODE_1 ((UINT32)0x00000001)
#define POWER_MODE_2 ((UINT32)0x00000002)
#define POWER_MODE_3 ((UINT32)0x00000003)
#define LINK_PRESENT (1<<0)
#define RX_WARM_RESET ((UINT32)1<<1)
#define LINK_TXEQ (1<<6)
#define GO_DISABLED (1<<4)
#define POLLING_EN (1<<12)
#define TX_HOT_RESET ((UINT32)1<<16)
#define RX_HOT_RESET ((UINT32)1<<24)
#define TX_WARM_RESET ((UINT32)1<<8)
#define TX_Ux_EXIT ((UINT32)1<<9)
// link int flag
#define LINK_RDY_FLAG (1<<0)
#define LINK_RECOV_FLAG (1<<1)
#define LINK_INACT_FLAG (1<<2)
#define LINK_DISABLE_FLAG (1<<3)
#define LINK_GO_U3_FLAG (1<<4)
#define LINK_GO_U2_FLAG (1<<5)
#define LINK_GO_U1_FLAG (1<<6)
#define LINK_GO_U0_FLAG (1<<7)
#define LINK_U3_WAKE_FLAG (1<<8)
#define LINK_Ux_REJECT_FLAG (1<<9)
#define TERM_PRESENT_FLAG (1<<10)
#define LINK_TXEQ_FLAG (1<<11)
#define LINK_Ux_EXIT_FLAG (1<<12)
#define WARM_RESET_FLAG (1<<13)
#define U3_WAKEUP_FLAG (1<<14)
#define HOT_RESET_FLAG (1<<15)
#define LINK_RX_DET_FLAG (1<<20)
#define EP0_R_EN (1<<0)
#define EP1_R_EN (1<<1)
#define EP2_R_EN (1<<2)
#define EP3_R_EN (1<<3)
#define EP4_R_EN (1<<4)
#define EP5_R_EN (1<<5)
#define EP6_R_EN (1<<6)
#define EP7_R_EN (1<<7)
#define EP0_T_EN (1<<8)
#define EP1_T_EN (1<<9)
#define EP2_T_EN (1<<10)
#define EP3_T_EN (1<<11)
#define EP4_T_EN (1<<12)
#define EP5_T_EN (1<<13)
#define EP6_T_EN (1<<14)
#define EP7_T_EN (1<<15)
#define USB_FORCE_RST (1<<2)
#define USB_ALL_CLR (1<<1)
// LMP
#define LMP_HP (0)
#define LMP_SUBTYPE_MASK (0xf<<5)
#define SET_LINK_FUNC (0x1<<5)
#define U2_INACT_TOUT (0x2<<5)
#define VENDOR_TEST (0x3<<5)
#define PORT_CAP (0x4<<5)
#define PORT_CFG (0x5<<5)
#define PORT_CFG_RES (0x6<<5)
#define LINK_SPEED (1<<9)
#define NUM_HP_BUF (4<<0)
#define DOWN_STREAM (1<<16)
#define UP_STREAM (2<<16)
#define TIE_BRK (1<<20)
/**********device status***********/
typedef enum _DEVICE_STATE
{
UNCONNECTED,
ATTACHED,
POWERED,
SUSPENDED,
ADDRESSED,
CONFIGURED
} DEVICE_STATE;
/**********standard request command***********/
typedef struct __PACKED
{
UINT8 bRequestType;
UINT8 bRequest;
UINT8 wValueL;
UINT8 wValueH;
UINT8 wIndexL;
UINT8 wIndexH;
UINT16 wLength;
} *PUSB_SETUP;
#define UsbSetupBuf ((PUSB_SETUP)endp0RTbuff)//endpoint 0
#define ENDP0_MAXPACK 512
// status response
#define NRDY 0
#define ACK 0x01
#define STALL 0x02
#define INVALID 0x03
// number of NUMP
#define NUMP_0 0x00
#define NUMP_1 0x01
#define NUMP_2 0x02
#define NUMP_3 0x03
#define NUMP_4 0x04
#define NUMP_5 0x05
#define NUMP_6 0x06
/* USB endpoint direction */
#define OUT 0x00
#define IN 0x80
/* USB endpoint serial number */
#define ENDP_0 0x00
#define ENDP_1 0x01
#define ENDP_2 0x02
#define ENDP_3 0x03
#define ENDP_4 0x04
#define ENDP_5 0x05
#define ENDP_6 0x06
#define ENDP_7 0x07
#define USB_DESCR_TYP_BOS 0x0f
#define USB_DESCR_UNSUPPORTED 0xffff
#define INVALID_REQ_CODE 0xFF
/* string descriptor type */
#ifndef USB_DESCR_STRING
#define USB_DESCR_LANGID_STRING 0x00
#define USB_DESCR_VENDOR_STRING 0x01
#define USB_DESCR_PRODUCT_STRING 0x02
#define USB_DESCR_SERIAL_STRING 0x03
#define USB_DESCR_OS_STRING 0xee
#endif
extern void USB30_Device_forceclr();
/*******************************************************************************
* @fn USB30_Device_Init
*
* @brief USB3.0 Device initialization
*
* @return None
*/
extern UINT8 USB30_Device_Init(void);
/*******************************************************************************
* @fn USB30_Lib_Getversion
*
* @brief USB3.0 Device Lib initialization
*
* @return None
*/
extern UINT8 USB30_Lib_Getversion(void);
/*******************************************************************************
* @fn USB30_ISO_Setendp
*
* @brief Configure synchronization endpoint
*
* @return None
*/
extern void USB30_ISO_Setendp(UINT8 num,FunctionalState Status );
/*******************************************************************************
* @fn USB30_ISO_Setdelay( UINT32 dly )
*
* @brief Set synchronization delay time
*
* @param dly - delay time
*
* @return None
*/
extern void USB30_ISO_Setdelay( UINT32 dly );
/*******************************************************************************
* @fn USB30_ITP_Enable
*
* @brief USB ITP enable
*
* @param Status - enable/disable
*
* @return None
*/
extern void USB30_ITP_Enable(FunctionalState Status);
/*******************************************************************************
* @fn USB30_OUT_Status
*
* @brief Get the length of endpoint received data
*
* @param endp - Endpoint number
* nump - The remaining number of packets that can be received by the endpoint
* len - The length of data received by the endpoint. For burst transmission,
* it indicates the length of the last packet received by the endpoint.
* status - Indicates whether the host still has data packets to be distributed,
* 1 - the end of the burst received non-full packets,
* 0 - the host still has data packets to be distributed.
*
* @return None
*/
extern void USB30_OUT_Status(UINT8 endp,UINT8 *nump,UINT16 *len,UINT8 *status);
/*******************************************************************************
* @fn USB30_OUT_Set
*
* @brief Endpoint receive settings
*
* @param endp - Set endpoint number
* nump - The remaining number of packets that can be received by the endpoint
* status - Endpoint Status :0-NRDY,1-ACK,2-STALL
*
* @return None
*/
extern void USB30_OUT_Set(UINT8 endp,UINT8 status,UINT8 nump);
/*******************************************************************************
* @fn USB30_OUT_ClearIT
*
* @brief Clear the OUT transaction completion interrupt, and only keep the package serial number
*
* @param endp - Set endpoint number
*
* @return None
*/
extern void USB30_OUT_ClearIT(UINT8 endp);
/*******************************************************************************
* @fn USB30_OUT_ClearPendingIT
*
* @brief Clear the OUT transaction completion interrupt, and keep other endpoint configurations
*
* @param endp - Set endpoint number
*
* @return None
*/
extern void USB30_OUT_ClearPendingIT(UINT8 endp);
/*******************************************************************************
* @fn USB30_OUT_ITflag
*
* @brief Get the OUT transaction completion interrupt flag
*
* @param endp - Set endpoint number
*
* @return 1 - interrupt 0 - non-interrupt
*/
extern UINT8 USB30_OUT_ITflag(UINT8 endp);
/*******************************************************************************
* @fn USB30_IN_Set
*
* @brief Endpoint sending settings
*
* @param endp - endpoint number
* lpf - end of burst: 1-enable 0-disable
* nump - The number of packets that the endpoint can send
* status - endpoint status: 0-NRDY,1-ACK,2-STALL
* TxLen - The data length of the last packet sent by the endpoint
*
* @return None
*/
extern void USB30_IN_Set(UINT8 endp,FunctionalState lpf,UINT8 status,UINT8 nump,UINT16 TxLen);
/*******************************************************************************
* @fn USB30_IN_ClearPendingIT
*
* @brief Clear the IN transaction completion interrupt and keep the other configurations of the endpoint
*
* @param endp - endpoint number
*
* @return None
*/
extern void USB30_IN_ClearPendingIT(UINT8 endp);
/*******************************************************************************
* @fn USB30_IN_ClearIT
*
* @brief Clear the IN transaction interrupt and the remaining status of the endpoint,
* and only retain the packet serial number.
*
* @param endp - endpoint number
*
* @return None
*/
extern void USB30_IN_ClearIT(UINT8 endp);
/*******************************************************************************
* @fn USB30_IN_ITflagT
*
* @brief Get IN transaction completion interrupt flag
*
* @param endp - Set endpoint number
*
* @return None
*/
extern UINT8 USB30_IN_ITflag(UINT8 endp);
/*******************************************************************************
* @fn USB30_IN_Nump
*
* @brief Get the remaining number of packets to be sent by the endpoint
*
* @param endp - endpoint number
*
* @return Remaining number of packets to be sent
*/
extern UINT8 USB30_IN_Nump(UINT8 endp);
/*******************************************************************************
* @fn USB30_Send_ERDY
*
* @brief send ERDY packet
*
* @param endp - endpoint number
* nump - Number of packets received or sent by the endpoint
*
* @return None
*/
extern void USB30_Send_ERDY(UINT8 endp,UINT8 nump);
/*******************************************************************************
* @fn USB30_Device_Setaddress
*
* @brief Set device address
*
* @param address - device address
*
* @return None
*/
extern void USB30_Device_Setaddress( UINT32 address );
/*******************************************************************************
* @fn USB30_IN_Nump
*
* @brief Get the remaining number of packets to be sent by the endpoint
*
* @return Control the length of data sent by the host when the transmission data stage is OUT
*/
extern UINT16 USB30_Setup_OutData(void);
/*******************************************************************************
* @fn USB30_IRQHandler
*
* @brief USB30_IRQHandler
*
* @return None
*/
extern void USB30_IRQHandler();
/*******************************************************************************
* @fn USB30_StandardReq
*
* @brief USB device mode standard request command processing
*
* @return The length of data sent by the host request device
*/
extern UINT16 USB30_StandardReq();
/*******************************************************************************
* @fn USB30_NonStandardReq
*
* @brief USB device mode non-standard request command processing
*
* @return The length of data sent by the host request device
*/
extern UINT16 USB30_NonStandardReq();
/*******************************************************************************
* @fn EP0_IN_Callback
*
* @brief endpoint 0 IN Transfer completion callback function
*
* @return Data length
*/
extern UINT16 EP0_IN_Callback();
/*******************************************************************************
* @fn EP0_OUT_Callback
*
* @brief endpoint 0 OUT Transfer completion callback function
*
* @return None
*/
extern UINT16 EP0_OUT_Callback();
/*******************************************************************************
* @fn USB30_Setup_Status
*
* @brief Control transmission status stage
*
* @return None
*/
extern void USB30_Setup_Status();
/*******************************************************************************
* @fn USB30_ITP_Callback
*
* @brief ITP Callback function
*
* @return None
*/
extern void USB30_ITP_Callback(UINT32 ITPCounter);
/*******************************************************************************
* @fn USB30_switch_pwr_mode
*
* @brief switch USB3.0 Power mode
*
* @return None
*/
extern void USB30_Switch_Powermode( UINT8 pwr_mode );
/*******************************************************************************
* @fn EPn_IN_Callback()
*
* @brief endpointN IN transaction callback function
*
* @return None
*/
extern void EP1_IN_Callback(void);
extern void EP2_IN_Callback(void);
extern void EP3_IN_Callback(void);
extern void EP4_IN_Callback(void);
extern void EP5_IN_Callback(void);
extern void EP6_IN_Callback(void);
extern void EP7_IN_Callback(void);
/*******************************************************************************
* @fn EPn_IN_Callback()
*
* @brief endpointN OUT transaction callback function
*
* @return None
*/
extern void EP1_OUT_Callback(void);
extern void EP2_OUT_Callback(void);
extern void EP3_OUT_Callback(void);
extern void EP4_OUT_Callback(void);
extern void EP5_OUT_Callback(void);
extern void EP6_OUT_Callback(void);
extern void EP7_OUT_Callback(void);
#ifdef __cplusplus
}
#endif
#endif /* USB30_CH56X_USB30_LIB_H_ */

View File

@ -0,0 +1,27 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : cdc.h
* Author : WCH
* Version : V1.2
* Date : 2024/07/10
* Description :
*********************************************************************************
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
* Attention: This software (modified or not) and binary are used for
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
*******************************************************************************/
#ifndef CDC_CDC_H_
#define CDC_CDC_H_
extern volatile UINT16 USBByteCount;
extern volatile UINT16 USBBufOutPoint;
extern volatile UINT8 UploadPoint2_Busy;
extern volatile UINT8 DownloadPoint2_Busy;
extern volatile UINT16 Uart_Sendlenth;
void CDC_Uart_Init( UINT32 baudrate );
void TMR2_TimerInit1( void );
void CDC_Uart_Deal( void );
void CDC_Variable_Clear(void);
#endif /* CDC_CDC_H_ */

View File

@ -0,0 +1,196 @@
#ifndef __CONNECT_SERDES_H__
#define __CONNECT_SERDES_H__
#ifdef __cplusplus
extern "C" {
#endif
#include "CH56xSFR.h"
#include "core_riscv.h"
#
#define SDS_ALIGN_EN (1<<18)
#define SDS_CONT_EN (1<<17)
#define SDS_POWR_UP (1<<16)
#define SDS_TX_PU (1<<15)
#define SDS_RX_PU (1<<14)
#define SDS_PLL_PU (1<<13)
#define SDS_PLL_DIV (18<<8) // 60*(DIV+2)MHz
#define SDS_PLL_1_2G (18<<8) // 60*(18+2)MHz
#define SDS_PLL_900M (13<<8) // 60*(13+2)MHz
#define SDS_PLL_600M ( 8<<8) // 60*(8+2)MHz
#define SDS_DMA_EN 1<<7
#define SDS_TX_EN 1<<6
#define SDS_RX_EN 1<<5
#define SDS_RX_POLAR 1<<4
#define SDS_INT_BUSY_EN 1<<3
#define PHY_RESET 1<<2
#define LINK_RESET 1<<1
#define SDS_ALL_CLR 1<<0
#define SDS_LINK_INIT 1<<16
#define SDS_TX_START ((uint32_t)1<<17)
#define SDS_BUF_MODE 1<<18
#define SDS_PHY_RDY_EN 1<<0
#define SDS_TX_INT_EN 1<<1
#define SDS_RX_ERR_EN 1<<1
#define SDS_RX_INT_EN 1<<2
#define SDS_FIFO_OV_EN 1<<3
#define SDS_COMMA_INT_EN 1<<5
#define ALL_INT_TYPE 47
#define SDS_PHY_RDY_FLG 1<<0
#define SDS_TX_INT_FLG 1<<1
#define SDS_RX_INT_FLG 1<<2
#define SDS_FIFO_OV_FLG 1<<3
#define SDS_COMMA_INT_FLG 1<<5
#define ALL_INT_FLG 47
#define SDS_SEQ_MATCH 1<<17
#define SDS_RX_CRC_OK 1<<18
#define SDS_PLL_READY 1<<19
#define SDS_TX_READY 1<<20
#define SDS_RX_BUF 1<<24
#define SDS_TX_BUF 1<<28
#define SDS_TX_NUMP_1 1<<20
#define SDS_TX_NUMP_2 2<<20
#define SDS_TX_NUMP_3 3<<20
#define SDS_TX_NUMP_4 4<<20
/*******************************************************************************
* Function Name : Serdes_Tx_Init
* Description : Serdes configuration of hardware in Tx mode
* Input : None
* Return : None
*******************************************************************************/
extern void Serdes_Tx_Init(void);
/*******************************************************************************
* Function Name : Serdes_Rx_init
* Description : Serdes configuration of hardware in Rx mode
* Input : None
* Return : None
*******************************************************************************/
extern UINT8 Serdes_Rx_Init(UINT32 cnt);
/*******************************************************************************
* Function Name : DMA_Tx_CFG
* Description : Configure DMA transmitting mode
* Input : DMAaddr: DMA starting address
* Tx_len : length of transmitting data once
* custom_number: customized data using for data checking
* Return : None
*******************************************************************************/
extern void DMA_Tx_CFG( UINT32 DMAaddr, UINT32 Tx_len, UINT32 custom_number);
/*******************************************************************************
* Function Name : DoubleDMA_Rx_CFG
* Description : Configure double DMA receiving mode
* Input : DMA0_addr: DMA0 starting address
DMA1_addr: DMA1 starting address
* Return : None
*******************************************************************************/
extern void DoubleDMA_Rx_CFG( UINT32 DMA0_addr , UINT32 DMA1_addr );
/*******************************************************************************
* Function Name : DMA_Tx
* Description : DMA start sending data
* Input : None
* Return : None
*******************************************************************************/
extern void DMA_Tx(void);
/*******************************************************************************
* Function Name : DMA_Rx_check
* Description : double DMA receiving data
* Input : DMA0_addr--DMA0 address
DMA1_addr--DMA1 address
custom_number: customized data using for data checking,
consistent with the transmitting one
* Return : None
*******************************************************************************/
extern void DMA_Rx_check( UINT32 DMA0_addr, UINT32 DMA1_addr, UINT32 custom_number);
/*******************************************************************************
* Function Name : ClearITFlag
* Description : Clear interruption flag
* Input : ITFlag:
1.SDS_PHY_RDY_FLG
2.SDS_TX_INT_FLG
3.SDS_RX_INT_FLG
4.SDS_FIFO_OV_FLG
5.SDS_COMMA_INT_FLG
6.ALL_INT_FLG
* Return : None
*******************************************************************************/
extern void ClearITFlag( UINT16 ITFlag);
/*******************************************************************************
* Function Name : EnableIT
* Description : Enable Interrupt
* Input : ITType:
1.SDS_PHY_RDY_EN
2(1).SDS_TX_INT_EN (Tx mode)
2(2).SDS_RX_ERR_EN (Rx mode)
3.SDS_RX_INT_EN
4.SDS_FIFO_OV_EN
5.SDS_COMMA_INT_EN
6.ALL_INT_TYPE
* Return : None
*******************************************************************************/
extern void EnableIT( UINT16 ITType);
/*******************************************************************************
* Function Name : Wait_Txdone
* Description : waiting for Tx done
* Input : None
* Return : None
*******************************************************************************/
extern void Wait_Txdone(void);
/*******************************************************************************
* Function Name : Wait_commadone
* Description : waiting for Rx COMMA done
* Input : None
* Return : None
*******************************************************************************/
extern UINT8 Wait_commadone(UINT32 cnt);
/*******************************************************************************
* Function Name : ReadRxFlagBit
* Description : read Rx IT status
* Input : None
* Return : None
*******************************************************************************/
extern UINT32 ReadITFlagBit(UINT16 ITFlag);
/*******************************************************************************
* Function Name : ReadCOMMAFlagBit
* Description : read COMMA IT status
* Input : None
* Return : None
*******************************************************************************/
extern UINT32 ReadCOMMAFlagBit(void);
/*******************************************************************************
* Function Name : serdes_Rx_init
* Description : receiver module initialization
* Input : None
* Return : None
*******************************************************************************/
extern void serdes_Rx_init(void);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,98 @@
/*
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2022-07-15 Emuzit first version
*/
#ifndef __CONNECT_SOC_H__
#define __CONNECT_SOC_H__
#include <stdint.h>
#include <stddef.h>
#include <assert.h>
#if !defined(SOC_CH567) && \
!defined(SOC_CH568) && \
!defined(SOC_SERIES_CH569)
#define SOC_SERIES_CH569
#endif
#ifndef __packed
#define __packed __attribute__((packed))
#endif
//#define CHECK_STRUCT_SIZE(s, size) \
// static_assert(sizeof(s) == size, #s " has wrong size")
#define BITS_SET(x, bits) do x |= bits; while(0)
#define BITS_CLR(x, bits) do x &= ~bits; while(0)
#define FLASH_BASE_ADDRESS 0x00000000
#define RAMS_BASE_ADDRESS 0x20000000
#define BUS8_BASE_ADDRESS 0x80000000
#ifdef SOC_SERIES_CH569
#define RAMX_BASE_ADDRESS 0x20020000
#define RAMS_SIZE 16
#else
#define RAMS_SIZE 32
#endif
#define RAMS_END (RAMS_BASE_ADDRESS + RAMS_SIZE * 1024)
#define SYS_REG_BASE 0x40001000
#define GPIO_REG_BASE 0x40001000
#define GPIO_REG_BASE_PA 0x40001040
#define GPIO_REG_BASE_PB 0x40001060
#define GPIO_PORTS 2 // 2 ports : PA & PB
#define GPIO_PA_PIN_START 0 // PA : pin number 0~31
#define GPIO_PB_PIN_START 32 // PB : pin number 32~63
#ifdef SOC_SERIES_CH569
#define GPIO_PA_PIN_MARK 0x00ffffff // PA : bits 0~23
#define GPIO_PB_PIN_MARK 0x01ffffff // PB : bits 0~24
#else
#define GPIO_PA_PIN_MARK 0x0000ffff // PA : bits 0~15
#define GPIO_PB_PIN_MARK 0x00003fff // PB : bits 0~13
#endif
#define TMR0_REG_BASE 0x40002000
#define TMR1_REG_BASE 0x40002400
#define TMR2_REG_BASE 0x40002800
#define UART0_REG_BASE 0x40003000
#define UART1_REG_BASE 0x40003400
#define UART2_REG_BASE 0x40003800
#define UART3_REG_BASE 0x40003c00
#define SPI0_REG_BASE 0x40004000
#define SPI1_REG_BASE 0x40004400
#define PWMX_REG_BASE 0x40005000
#define PFIC_REG_BASE 0xe000e000
#define SysTick_REG_BASE 0xe000f000
#ifdef SOC_SERIES_CH569
#define HSPI_REG_BASE 0x40006000 // CH569W
#define ECDC_REG_BASE 0x40007000
#define USBSS_REG_BASE 0x40008000
#define USBHS_REG_BASE 0x40009000
#define EMMC_REG_BASE 0x4000a000
#define SERDES_REG_BASE 0x4000b000
#define ETH_REG_BASE 0x4000c000 // CH565W/CH569W
#define DVP_REG_BASE 0x4000e000 // CH565W/CH565M
#else
#define LED_REG_BASE 0x40006000
#define USB0_REG_BASE 0x40008000 // CH567
#define USB1_REG_BASE 0x40009000 // CH567
#define USB_REG_BASE 0x40009000 // CH568
#define SDC_REG_BASE 0x4000a000
#define SATA_REG_BASE 0x4000b000 // CH568
#define ECDC_REG_BASE 0x4000c400
#endif
#endif

View File

@ -0,0 +1,396 @@
/*
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2022-07-15 Emuzit first version
*/
#ifndef __CONNECT_SYS_H__
#define __CONNECT_SYS_H__
#include "connect_soc.h"
#ifdef __cplusplus
extern "C" {
#endif
#define sys_safe_access_enter(sys) \
do { \
sys->SAFE_ACCESS_SIG.reg = SAFE_ACCESS_SIG_1; \
sys->SAFE_ACCESS_SIG.reg = SAFE_ACCESS_SIG_2; \
} while(0)
#define sys_safe_access_leave(sys) \
do sys->SAFE_ACCESS_SIG.reg = 0; while(0)
union _sys_safe_access_sig
{
uint8_t reg;
struct
{
uint8_t safe_acc_mode : 2; // RO, current safe access, 11b => RWA ok
uint8_t resv_2 : 2;
uint8_t safe_acc_timer : 3; // RO, current safe access time count
uint8_t resv_7 : 1;
};
};
#define RB_SAFE_ACC_MODE 0x03
#define RB_SAFE_ACC_TIMER 0x70
#define SAFE_ACCESS_SIG_1 0x57
#define SAFE_ACCESS_SIG_2 0xa8
union _sys_glob_rom_cfg
{
uint8_t reg;
struct
{
uint8_t rom_ext_re : 1; // RO, allow programmer to read FlashROM
uint8_t code_ram_we : 1; // RWA, code SRAM writaboe
uint8_t rom_data_we : 1; // RWA, FlashROM data erasable/writable
uint8_t rom_code_we : 1; // RWA, FlashROM code erasable/writable
uint8_t rom_code_ofs : 1; // RWA, FlashROM offset for user code
uint8_t resv_5 : 3;
};
};
#define RB_ROM_EXT_RE 0x01
#define RB_CODE_RAM_WE 0x02
#define RB_ROM_DATA_WE 0x04
#define RB_ROM_CODE_WE 0x08
#define RB_ROM_CODE_OFS 0x10
#define ROM_CODE_OFS_0x00000 0
#define ROM_CODE_OFS_0x04000 1
union _sys_rst_boot_stat
{
uint8_t reg;
struct
{
uint8_t reset_flag : 2; // RO, last reset cause
uint8_t cfg_reset_en : 1; // RO, external reset pin (#RST) status
uint8_t cfg_boot_en : 1; // RO, reset as 1
uint8_t cfg_debug_en : 1; // RO
uint8_t boot_loader : 1; // RO
uint8_t resv_6 : 2;
};
};
#define RB_RESET_FLAG 0x03
#define RB_CFG_RESET_EN 0x04
#define RB_CFG_BOOT_EN 0x08
#define RB_CFG_DEBUG_EN 0x10
#define RB_BOOT_LOADER 0x20
#define RESET_FLAG_IS_SOFT 0
#define RESET_FLAG_IS_POR 1
#define RESET_FLAG_IS_WDOG 2
#define RESET_FLAG_IS_RSTPIN 3
union _sys_rst_wdog_ctrl
{
uint8_t reg;
struct
{
uint8_t software_reset : 1; // WA/WZ, system software reset, auto clear
#if defined(SOC_SERIES_CH569)
uint8_t wdog_rst_en : 1; // RWA, enable watchdog overflow to reset
uint8_t wdog_int_en : 1; // RWA, enable watchdog overflow interrupt
uint8_t wdog_int_flag : 1; // RW1, watchdog counter overflow
#else
uint8_t resv_2 : 3;
#endif
uint8_t resv_4 : 4; // RO, B.7-6 must write 01b
};
};
#define RB_SOFTWARE_RESET 0x01
#ifdef SOC_SERIES_CH569
#define RB_WDOG_RST_EN 0x02
#define RB_WDOG_INT_EN 0x04
#define RB_WDOG_INT_FLAG 0x08
#endif
#define wdog_ctrl_wdat(v) (0x40 | (v))
union _sys_clk_pll_div
{
uint8_t reg;
struct
{
uint8_t pll_div : 4; // RWA, min 2
uint8_t resv_4 : 4; // RWA, B.7-6 must write 01b
};
};
#define clk_pll_div_wdat(div) (0x40 | (div))
union _sys_clk_cfg_ctrl
{
uint8_t reg;
struct
{
uint8_t pll_sleep : 1; // RWA, PLL sleep control
uint8_t sel_pll : 1; // RWA, clock source select
uint8_t resv_6 : 6; // RWA, must write 10b
};
};
#define RB_CLK_PLL_SLEEP 0x01
#define RB_CLK_SEL_PLL 0x02
#define CLK_PLL_SLEEP_DISABLE 0
#define CLK_PLL_SLEEP_ENABLE 1
#define CLK_SEL_PLL_HSE_30M 0
#define CLK_SEL_PLL_USB_480M 1
#define clk_cfg_ctrl_wdat(v) (0x80 | (v))
union _sys_clk_mod_aux
{
uint8_t reg;
struct
{
uint8_t int_125m_en : 1; // RWA, USB PHY 125MHz to ETH
uint8_t ext_125m_en : 1; // RWA, external 125MHz to ETH
uint8_t mco_sel_msk : 2; // RWA, MCO output select
uint8_t mco_en : 1; // RWA, MCO output enable
uint8_t resv_5 : 3;
};
};
#define RB_INT_125M_EN 0x01
#define RB_EXT_125M_EN 0x02
#define RB_MCO_SEL_MSK 0x0C
#define RB_MCO_EN 0x10
#define MCO_SEL_MSK_125M 0
#define MCO_SEL_MSK_25M 1
#define MCO_SEL_MSK_2_5M 2
/* All bits are RWA (need safe_access_sig), 0/1 : clock on/off
*/
union _sys_slp_clk_off0
{
uint8_t reg;
struct
{
uint8_t tmr0 : 1;
uint8_t tmr1 : 1;
uint8_t tmr2 : 1;
uint8_t pwmx : 1;
uint8_t uart0 : 1;
uint8_t uart1 : 1;
uint8_t uart2 : 1;
uint8_t uart3 : 1;
};
};
#define RB_SLP_CLK_TMR0 0x01
#define RB_SLP_CLK_TMR1 0x02
#define RB_SLP_CLK_TMR2 0x04
#define RB_SLP_CLK_PWMX 0x08
#define RB_SLP_CLK_UART0 0x10
#define RB_SLP_CLK_UART1 0x20
#define RB_SLP_CLK_UART2 0x40
#define RB_SLP_CLK_UART3 0x80
#define SYS_SLP_CLK_ON 0
#define SYS_SLP_CLK_OFF 1
/* All writable bits are RWA (need safe_access_sig), 0/1 : clock on/off
*/
union _sys_slp_clk_off1
{
uint8_t reg;
struct
{
uint8_t spi0 : 1;
uint8_t spi1 : 1;
#if defined(SOC_CH567)
uint8_t sdc : 1;
uint8_t led : 1;
uint8_t usb0 : 1;
uint8_t usb1 : 1;
uint8_t resv_6 : 1;
#elif defined(SOC_CH568)
uint8_t sdc : 1;
uint8_t led : 1;
uint8_t resv_4 : 1;
uint8_t usb1 : 1;
uint8_t sata : 1;
uint8_t ecdc : 1;
#else
uint8_t emmc : 1;
uint8_t hspi : 1;
uint8_t usbhs : 1;
uint8_t usbss : 1;
uint8_t serd : 1;
uint8_t dvp : 1;
#endif
};
};
#define RB_SLP_CLK_SPI0 0x01
#define RB_SLP_CLK_SPI1 0x02
#if defined(SOC_WCH_CH567)
#define RB_SLP_CLK_SDC 0x04
#define RB_SLP_CLK_LED 0x08
#define RB_SLP_CLK_USB0 0x10
#define RB_SLP_CLK_USB1 0x20
#define RB_SLP_CLK_ECDC 0x80
#elif defined(SOC_WCH_CH568)
#define RB_SLP_CLK_SDC 0x04
#define RB_SLP_CLK_LED 0x08
#define RB_SLP_CLK_USB1 0x20
#define RB_SLP_CLK_SATA 0x40
#define RB_SLP_CLK_ECDC 0x80
#else
#define RB_SLP_CLK_EMMC 0x04
#define RB_SLP_CLK_HSPI 0x08
#define RB_SLP_CLK_USBHS 0x10
#define RB_SLP_CLK_USBSS 0x20
#define RB_SLP_CLK_SERD 0x40
#define RB_SLP_CLK_DVP 0x80
#endif
/* All writable bits are RWA (need safe_access_sig)
*/
union _sys_slp_wake_ctrl
{
uint8_t reg;
struct
{
#if defined(SOC_WCH_CH567)
uint8_t usb0_wake : 1;
uint8_t usb1_wake : 1;
uint8_t resv_2 : 2;
uint8_t gpio_wake : 1;
uint8_t resv_5 : 3;
#elif defined(SOC_WCH_CH568)
uint8_t resv_0 : 1;
uint8_t usb1_wake : 1;
uint8_t sata_wake : 1;
uint8_t resv_3 : 1;
uint8_t gpio_wake : 1;
uint8_t resv_5 : 3;
#else
uint8_t usbhs_wake : 1;
uint8_t usbss_wake : 1;
uint8_t clk_eth : 1;
uint8_t clk_ecdc : 1;
uint8_t gpio_wake : 1;
uint8_t eth_wake : 1;
uint8_t resv_6 : 2;
#endif
};
};
#if defined(SOC_WCH_CH567)
#define RB_SLP_USB0_WAKE 0x01
#define RB_SLP_USB1_WAKE 0x02
#define RB_SLP_GPIO_WAKE 0x10
#elif defined(SOC_WCH_CH568)
#define RB_SLP_USB1_WAKE 0x02
#define RB_SLP_SATA_WAKE 0x04
#define RB_SLP_GPIO_WAKE 0x10
#else
#define RB_SLP_USBHS_WAKE 0x01
#define RB_SLP_USBSS_WAKE 0x02
#define RB_SLP_CLK_ETH 0x04
#define RB_SLP_CLK_ECDC 0x08
#define RB_SLP_GPIO_WAKE 0x10
#define RB_SLP_ETH_WAKE 0x20
#endif
union _sys_slp_power_ctrl
{
uint8_t reg;
struct
{
uint8_t usbhs_pwrdn : 1; // RWA, USBHS power down (0:PWRUP)
uint8_t resv_2 : 7;
};
};
#define RB_SLP_USBHS_PWRDN 0x01
union _sys_serd_ana_cfg1
{
uint16_t reg;
struct
{
uint8_t serd_pll_cfg; // RWA, reset as 0x5a
uint8_t serd_30m_sel : 1; // RWA
uint8_t serd_dn_tst : 1; // RWA
uint8_t resv_10 : 6;
};
};
#define RB_SERD_PLL_CFG 0x0ff
#define RB_SERD_30M_SEL 0x100
#define RB_SERD_DN_TST 0x200
union _sys_serd_ana_cfg2
{
uint32_t reg;
struct
{
uint32_t serd_trx_cfg : 25; // RWA, reset as 423015h
uint32_t resv_25 : 7;
};
};
#define RB_SERD_TRX_CFG 0x1000000
/*
* 0x00 R8_SAFE_ACCESS_SIG: safe access signature register
* 0x01 R8_CHIP_ID: RF, chip ID register
* 0x02 R8_SAFE_ACCESS_ID: RF, read as 02h
* 0x03 R8_WDOG_COUNT RW, watchdog counter
* 0x04 R8_GLOB_ROM_CFG: ROM config register
* 0x05 R8_RST_BOOT_STAT: RO, boot state register
* 0x06 R8_RST_WDOG_CTRL: software reset & watchdog control register
* 0x07 R8_GLOB_RESET_KEEP: RW, only power-on-reset can clear this register
* 0x08 R8_CLK_PLL_DIV: RWA, PLL output divisor register
* 0x0a R8_CLK_CFG_CTRL: RWA, clock config register
* 0x0b R8_CLK_MOD_AUX: RWA, clock auxiliary register
* 0x0c R8_SLP_CLK_OFF0: RWA, sleep control register 0
* 0x0d R8_SLP_CLK_OFF1: RWA, sleep control register 1
* 0x0e R8_SLP_WAKE_CTRL: RWA, wakeup control register
* 0x0f R8_SLP_POWER_CTRL: RWA, low power management register
* 0x20 R16_SERD_ANA_CFG1: RWA, SerDes PHY analog param config register 1
* 0x24 R32_SERD_ANA_CFG2: RWA, SerDes PHY analog param config register 2
*
* CAVEAT: gcc (as of 8.2.0) tends to read 32-bit word for bit field test.
* Be careful for those with side effect for read.
*/
struct sys_registers
{
union _sys_safe_access_sig SAFE_ACCESS_SIG;
uint8_t CHIP_ID;
uint8_t SAFE_ACCESS_ID;
uint8_t WDOG_COUNT;
union _sys_glob_rom_cfg GLOB_ROM_CFG;
union _sys_rst_boot_stat RST_BOOT_STAT;
union _sys_rst_wdog_ctrl RST_WDOG_CTRL;
uint8_t GLOB_RESET_KEEP;
union _sys_clk_pll_div CLK_PLL_DIV;
uint8_t resv_9;
union _sys_clk_cfg_ctrl CLK_CFG_CTRL;
union _sys_clk_mod_aux CLK_MOD_AUX;
union _sys_slp_clk_off0 SLP_CLK_OFF0;
union _sys_slp_clk_off1 SLP_CLK_OFF1;
union _sys_slp_wake_ctrl SLP_WAKE_CTRL;
union _sys_slp_power_ctrl SLP_POWER_CTRL;
#if defined(SOC_SERIES_CH569)
uint32_t resv_10[4];
union _sys_serd_ana_cfg1 SERD_ANA_CFG1;
uint16_t resv_22;
union _sys_serd_ana_cfg2 SERD_ANA_CFG2;
#endif
} __packed;
//CHECK_STRUCT_SIZE(struct sys_registers, 0x28);
uint32_t sys_hclk_calc(void);
uint32_t sys_hclk_get(void);
int sys_hclk_set(uint32_t freq);
int sys_clk_off_by_irqn(uint8_t irqn, int off);
void sys_slp_clk_off0(uint8_t bits, int off);
void sys_slp_clk_off1(uint8_t bits, int off);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,37 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file connect_usb.h
* @brief define aiit-arm32-board usb function and struct
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-04-25
*/
#ifndef CONNECT_USB_H
#define CONNECT_USB_H
#ifdef __cplusplus
extern "C" {
#endif
#ifdef BSP_USING_USBD_CDC
// TODO
#endif
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,7 @@
config SERDES_TRANS
bool "Config serdes transmit mode."
default y
config SERIAL_RECEI
bool "Config serdes receive mode."
default y

View File

@ -0,0 +1,3 @@
SRC_FILES := connect_serdes.c
include $(KERNEL_ROOT)/compiler.mk

View File

@ -0,0 +1,154 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan
* PSL v2. You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY
* KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
* NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. See the
* Mulan PSL v2 for more details.
*/
/**
* @file connect_usart.c
* @brief support ch569 uart function and register to bus framework
* @version 1.0
* @author AIIT XUOS Lab
* @date 2025-04-07
*/
#include "CH56x_common.h"
#include "xizi.h"
#include "board.h"
#include "shell.h"
#include "connect_serdes.h"
//#define Trans 1
//#define Recei 1
//UINT32 Tx_DMAaddr = 0x20020000;
//UINT32 RX_DMA0_addr = 0x20033330;
//UINT32 RX_DMA1_addr = 0x20034330;
UINT32 Tx_DMAaddr[512] __attribute__((aligned(16))) = {0};
UINT32 RX_DMA0_addr[512] __attribute__((aligned(16))) = {0};
UINT32 RX_DMA1_addr[512] __attribute__((aligned(16))) = {0};
volatile UINT32 i=0;
volatile UINT32 k=0;
/*******************************************************************************
* Function Name : __attribute__((interrupt()))
* Description : SERDES_IRQHandler hard push
* Input : baudrate: UART1 communication baud rate.
* Return : None
*******************************************************************************/
void SERDES_IRQHandler (void) __attribute__((interrupt()));
/*******************************************************************************
* Function Name : SerdesTxTest
* Description : SerdesTxTest program.
* Input : None
* Return : None
*******************************************************************************/
int SerdesTxTest(void)
{
UINT32 *p32_txdma = (UINT32 *)Tx_DMAaddr;
UINT32 n=0;
UINT32 data=0;
KPrintf("SerdesTxTest start\r\n");
KPrintf("SerdesTxTest Tx_DMAaddr=0x%08x\r\n", (UINT32)Tx_DMAaddr);
#ifdef SERDES_TRANS //Serdes query sent.
Serdes_Tx_Init();
do
{
*p32_txdma++ = data;
data += 0x01010101;
n++;
}while(n!=512);
mDelaymS(500);
DMA_Tx_CFG( (UINT32)Tx_DMAaddr,2048,0x555555); //512 address spaces 2048 bytes
while(1)
{
KPrintf("SerdesTxTest DMA_Tx\r\n");
DMA_Tx();
Wait_Txdone();
ClearITFlag(SDS_TX_INT_FLG);
mDelaymS(5000);
}
#endif
}
/*******************************************************************************
* Function Name : SerdesRxTest
* Description : SerdesRxTest program.
* Input : None
* Return : None
*******************************************************************************/
int SerdesRxTest(void)
{
KPrintf("SerdesRxTest start\r\n");
KPrintf("SerdesRxTest RX_DMA0_addr=0x%08x RX_DMA1_addr=0x%08x\r\n", (UINT32)RX_DMA0_addr, (UINT32)RX_DMA1_addr);
#ifdef SERIAL_RECEI // Serdes interrupt reception.
PFIC_EnableIRQ(INT_ID_SERDES);
DoubleDMA_Rx_CFG((UINT32)RX_DMA0_addr , (UINT32)RX_DMA1_addr );
Serdes_Rx_Init(10*1000*1000);
Wait_commadone(10*1000*1000);
Serdes_Rx_Init(10*1000*1000);
EnableIT(SDS_RX_INT_EN|SDS_COMMA_INT_EN);
KPrintf("SerdesRxTest init OK\r\n");
while(1)
{
if(k==2) // After each completion of the double-buffered reception, print the received data.
{
for(i=0;i<512;i++)
{
KPrintf("%x\r\n",*(UINT32 *)(0x20033330+4*i));
KPrintf("%x\r\n",*(UINT32 *)(0x20034330+4*i));
}
k=0;
}
}
#endif
}
/*******************************************************************************
* Function Name : SERDES_IRQHandler
* Description : Interruption function
* Input : None
* Return : None
*******************************************************************************/
void SERDES_IRQHandler (void)
{
if(ReadITFlagBit(SDS_RX_INT_FLG))
{
ClearITFlag(SDS_RX_INT_FLG);
k++;
DMA_Rx_check((UINT32)RX_DMA0_addr, (UINT32)RX_DMA1_addr, 0x555555);
KPrintf("\nbuffer received ....... !\n");
}
if(ReadITFlagBit(SDS_COMMA_INT_FLG))
{
KPrintf("\nreceive COMMA, init....... !\n");
Serdes_Rx_Init( 1000*30 );
i = 0;
mDelaymS(50);
ClearITFlag(SDS_COMMA_INT_FLG);
}
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN),
SerdesTxTest, SerdesTxTest, test serdes tx);
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN),
SerdesRxTest, SerdesRxTest, test serdes rx);

View File

@ -0,0 +1,3 @@
menuconfig BSP_USING_SPI0_FLASH
bool "Enable SPI0 FLASH"
default y

View File

@ -0,0 +1,5 @@
ifeq ($(CONFIG_BSP_USING_SPI0_FLASH),y)
SRC_FILES += connect_spi_flash.c
endif
include $(KERNEL_ROOT)/compiler.mk

View File

@ -0,0 +1,463 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan
* PSL v2. You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY
* KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
* NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. See the
* Mulan PSL v2 for more details.
*/
/**
* @file connect_spi.c
* @brief support ch569 spi function and register to bus framework
* @version 1.0
* @author AIIT XUOS Lab
* @date 2025-04-07
*/
/*
*@Note
*SPI0_FLASH routine
* SPI0 operation external FLASH
*/
#include <xizi.h>
#include "xsconfig.h"
#include "CH56x_common.h"
#include "board.h"
#include "shell.h"
#define CMD_STATUS1 0x05
#define CMD_WR_ENABLE 0x06
#define CMD_ERASE_4KBYTE 0x20
#define CMD_ERASE_32KBYTE 0x52
#define CMD_READ_DATA 0x03
#define CMD_PAGE_PROG 0x02
#define CMD_FAST_READ 0x0B
#define CMD_DEVICE_ID 0x90
/********************************* Pin Definitions ************************************
* PA12 <===========> SCS0
* PA13 <===========> SCK0
* PA14 <===========> MOSI0
* PA15 <===========> MISO0
*******************************************************************************/
#define SPI0_CS_LOW() R32_PA_CLR |= 1<<12
#define SPI0_CS_HIGH() R32_PA_OUT |= 1<<12
/*******************************************************************************
* @fn DebugInit
*
* @brief Initializes the UART1 peripheral.
*
* @param baudrate - UART1 communication baud rate.
*
* @return None
*/
void DebugInit(UINT32 baudrate)
{
UINT32 x;
UINT32 t = FREQ_SYS;
x = 10 * t * 2 / 16 / baudrate;
x = ( x + 5 ) / 10;
R8_UART1_DIV = 1;
R16_UART1_DL = x;
R8_UART1_FCR = RB_FCR_FIFO_TRIG | RB_FCR_TX_FIFO_CLR | RB_FCR_RX_FIFO_CLR | RB_FCR_FIFO_EN;
R8_UART1_LCR = RB_LCR_WORD_SZ;
R8_UART1_IER = RB_IER_TXD_EN;
R32_PA_SMT |= (1<<8) |(1<<7);
R32_PA_DIR |= (1<<8);
}
/*******************************************************************************
* @fn SPI_MASTER_INIT
*
* @brief SPI0 master mode initialization
*
* @return None
*/
void SPI_MASTER_INIT(void)
{
R8_SPI0_CTRL_MOD = RB_SPI_MOSI_OE|RB_SPI_SCK_OE; /* MOSI, SCK output enable, host mode, mode 0 */
R8_SPI0_CLOCK_DIV = 0x0a; /* 10 frequency division, 100/10=10M */
R32_PA_DIR |= (1<<14 | 1<<13 | 1<<12); /* MOSI(PA14), SCK0(PA13), SCS(PA12) are the output*/
R32_PA_PU |= 1<<12 ;
R8_SPI0_CTRL_CFG &= ~RB_SPI_DMA_ENABLE;
}
/*******************************************************************************
* @fn SPI0_Trans
*
* @brief send a byte of data
*
* @param data - data to send
*
* @return None
*/
void SPI0_Trans(UINT8 data)
{
// R8_SPI0_CTRL_MOD &= ~RB_SPI_FIFO_DIR;
// R8_SPI0_BUFFER = data;
// while( !(R8_SPI0_INT_FLAG & RB_SPI_FREE) );
R32_SPI0_FIFO = data;
R16_SPI0_TOTAL_CNT = 0x01;
while( R8_SPI0_FIFO_COUNT != 0 ); /* Wait for the data to be sent */
}
/*******************************************************************************
* @fn SPI0_Recv
*
* @brief Receive a byte of data
*
* @return None
*/
UINT8 SPI0_Recv(void)
{
// R8_SPI0_CTRL_MOD &= ~RB_SPI_FIFO_DIR;
// R8_SPI0_BUFFER = 0xFF; //start transfer
// while( !(R8_SPI0_INT_FLAG & RB_SPI_FREE) );
// return ( R8_SPI0_BUFFER );
UINT8 data;
R32_SPI0_FIFO = 0xff;
R16_SPI0_TOTAL_CNT = 0x01;
while( R8_SPI0_FIFO_COUNT != 0 ); /* wait for data to come back */
data = R8_SPI0_BUFFER;
return data;
}
/*******************************************************************************
* @fn SPI0_RecvS
*
* @brief Receive multiple bytes continuously using FIFO
*
* @param pbuf - The first address of the data content to be sent
len - The length of the data sent by the request, the maximum is 4095
* @return None
*/
void SPI0_RecvS(UINT8 *pbuf, UINT16 len)
{
UINT16 readlen;
readlen = len;
R8_SPI0_CTRL_MOD |= RB_SPI_FIFO_DIR; //Set data direction to input
R16_SPI0_TOTAL_CNT = len; //Set the length of the data to be received, the FIFO direction will start the transmission if the input length is not 0
R8_SPI0_INT_FLAG = RB_SPI_IF_CNT_END;
while( readlen )
{
if( R8_SPI0_FIFO_COUNT )
{
*pbuf = R8_SPI0_FIFO;
pbuf++;
readlen--;
}
}
}
/*******************************************************************************
* @fn ReadExternalFlashStatusReg_SPI
*
* @brief Used to read the status register and return the value of the status register
*
* @return ExFlashRegStatus
*/
UINT8 ReadExternalFlashStatusReg_SPI(void)
{
UINT8 ExFlashRegStatus;
SPI0_CS_LOW();
SPI0_Trans( CMD_STATUS1 ); //Send a command to read the status register
ExFlashRegStatus = SPI0_Recv(); //read status register
SPI0_CS_HIGH();
return ExFlashRegStatus;
}
/*******************************************************************************
* @fn WaitExternalFlashIfBusy
*
* @brief Wait for the chip to be free (after performing Byte-Program, Sector-Erase, Block-Erase, Chip-Erase operations)
*
* @return None
*/
void WaitExternalFlashIfBusy(void)
{
while ((ReadExternalFlashStatusReg_SPI())&0x01 == 0x01 )
{
; //Waiting for Flash to be idle
}
}
/*******************************************************************************
* @fn WriteExternalFlashEnable_SPI
*
* @brief Write enable, also can be used to enable write status register
*
* @return None
*/
void WriteExternalFlashEnable_SPI(void)
{
SPI0_CS_LOW();
SPI0_Trans( CMD_WR_ENABLE ); //Send write enable command
SPI0_CS_HIGH();
}
/*******************************************************************************
* @fn EraseExternal4KFlash_SPI
*
* @brief Erase 4K Flash Erase a sector
*
* @param Dst_Addr 0-1 ffff ffff, Clear the sector where any address is located
*
* @return None
*/
void EraseExternal4KFlash_SPI(UINT32 Dst_Addr)
{
WriteExternalFlashEnable_SPI();
WaitExternalFlashIfBusy();
SPI0_CS_LOW();
SPI0_Trans(CMD_ERASE_4KBYTE); //sector erase command
SPI0_Trans(((Dst_Addr & 0xFFFFFF) >> 16)); //Send 3 byte address
SPI0_Trans(((Dst_Addr & 0xFFFF) >> 8));
SPI0_Trans(Dst_Addr & 0xFF);
SPI0_CS_HIGH();
WaitExternalFlashIfBusy();
}
/*******************************************************************************
* @fn EraseExternalFlash_SPI
*
* @brief Erase 32K Flash Erase a sector
*
* @param Dst_Addr 0-1 ffff ffff, Clear the sector where any address is located
*
* @return None
*/
void EraseExternal32KFlash_SPI(UINT32 Dst_Addr)
{
WriteExternalFlashEnable_SPI();
WaitExternalFlashIfBusy();
SPI0_CS_LOW();
SPI0_Trans(CMD_ERASE_32KBYTE); //32K erase command
SPI0_Trans(((Dst_Addr & 0xFFFFFF) >> 16)); //Send 3 byte address
SPI0_Trans(((Dst_Addr & 0xFFFF) >> 8));
SPI0_Trans(Dst_Addr & 0xFF);
SPI0_CS_HIGH();
WaitExternalFlashIfBusy();
}
/*******************************************************************************
* @fn PageWriteExternalFlash_SPI
*
* @brief Page write, SPI writes less than 256 bytes of data in one page
*
* @param RcvBuffer - data storage area
* StarAddr - address to start writing
* Len - The number of bytes to write (up to 256), which should not exceed the number of bytes remaining on the page
*
* @returnNone
*/
void PageWriteExternalFlash_SPI(UINT32 StarAddr, UINT16 Len, PUINT8 RcvBuffer)
{
UINT16 i;
WriteExternalFlashEnable_SPI(); //SET WEL
SPI0_CS_LOW();
SPI0_Trans(CMD_PAGE_PROG); //send write page command
SPI0_Trans(((StarAddr & 0xFFFFFF) >> 16)); //Send 24bit address
SPI0_Trans(((StarAddr & 0xFFFF) >> 8));
SPI0_Trans(StarAddr & 0xFF);
for(i=0; i!=Len; i++){
SPI0_Trans(RcvBuffer[i]); //cycle write
}
SPI0_CS_HIGH();
WaitExternalFlashIfBusy(); //Wait for write to end
}
/*******************************************************************************
* @fn BlukWriteExternalFlash_SPI
*
* @brief Write SPI FLASH without verification
* It must be ensured that the data in the address range to be written is all 0XFF, otherwise the data written at non-0XFF will fail
*
* @param SendBuffer - data storage area
* StarAddr - address to start writing
* Len - The number of bytes to write (max 65535)
*
* @return None
*/
void BlukWriteExternalFlash_SPI(UINT32 StarAddr, UINT16 Len, PUINT8 SendBuffer)
{
UINT16 pageremain;
pageremain = 256-StarAddr%256; //The remaining bytes of a single page
if(Len<=pageremain)
{
pageremain=Len; //No more than 256 bytes
}
while(1)
{
PageWriteExternalFlash_SPI(StarAddr,pageremain,SendBuffer);
if(Len==pageremain)
{
break; //end of writing
}
else
{
SendBuffer+=pageremain;
StarAddr+=pageremain;
Len-=pageremain; //Subtract the number of bytes already written
if(Len>256)
{
pageremain=256; //256 bytes can be written at a time
}
else
{
pageremain=Len; //Not enough 256 bytes
}
}
}
}
/*******************************************************************************
* @fn ReadExternalFlash_SPI
*
* @brief read data from address
*
* @param StarAddr
* Len read data length
* RcvBuffer Receive buffer start address
*
* @return None
*/
void ReadExternalFlash_SPI(UINT32 StarAddr, UINT16 Len, PUINT8 RcvBuffer)
{
SPI0_CS_LOW();
SPI0_Trans(CMD_READ_DATA); //read command
SPI0_Trans(((StarAddr & 0xFFFFFF) >> 16)); //Send 3 byte address
SPI0_Trans(((StarAddr & 0xFFFF) >> 8));
SPI0_Trans(StarAddr & 0xFF);
SPI0_RecvS( RcvBuffer, Len );
SPI0_CS_HIGH();
}
/*******************************************************************************
* @fn BlukReadExternalFlash_SPI
*
* @brief Read the data of multiple bytes in the starting address and store it in the buffer
*
* @param StarAddr -Destination Address 000000H - 1FFFFFH
Len - read data length
RcvBuffer - Receive buffer start address
* @return None
*/
void BlukReadExternalFlash_SPI(UINT32 StarAddr, UINT16 Len, PUINT8 RcvBuffer)
{
SPI0_CS_LOW();
SPI0_Trans(CMD_FAST_READ); //high speed
SPI0_Trans(((StarAddr & 0xFFFFFF) >> 16)); //Send 3 byte address
SPI0_Trans(((StarAddr & 0xFFFF) >> 8));
SPI0_Trans(StarAddr & 0xFF);
SPI0_Trans(0x00);
SPI0_RecvS( RcvBuffer, Len );
SPI0_CS_HIGH();
}
/*******************************************************************************
* @fn SPIFlash_ReadID
*
* @brief SPI Flash read chip ID
*
* @return 0XEF13 - Indicates that the chip model is W25Q80
* 0XEF14 - Indicates that the chip model is W25Q16
* 0XEF15 - Indicates that the chip model is W25Q32
* 0XEF16 - Indicates that the chip model is W25Q64
* 0XEF17 - Indicates that the chip model is W25Q128
*/
UINT16 SPIFlash_ReadID(void)
{
UINT16 temp = 0;
R32_PA_CLR |= 1<<12 ;
SPI0_Trans(0x90); //read ID command
SPI0_Trans(0x00);
SPI0_Trans(0x00);
SPI0_Trans(0x00);
temp = SPI0_Recv();
temp = temp<<8;
temp |= SPI0_Recv();
R32_PA_OUT |= 1<<12 ;
return temp;
}
/*********************************************************************
* @fn InitHwSpi
*
* @brief InitHwSpi program.
*
* @return none
*/
int InitHwSpi(void) {
SPI_MASTER_INIT ( ); /* SPI0 master mode initialization */
return 0;
}
int SpiFlashTest(int argc, char *argv[])
{
UINT8 buf[1024];
UINT8 i;
int read_only = 0;
KPrintf("SpiFlashTest Start\n");
KPrintf("spi flash id:0x%04x\n", SPIFlash_ReadID() ); /*Read chip ID */
for(i=0; i!=255; i++){
buf[i] = i;
}
if (argc == 3) {
KPrintf("SpiFlashTest argv[2]=%s\n", argv[2]);
if (argv[2][0] == 'r') {
read_only = 1;
}
else {
buf[0] = argv[2][0] - '0';
}
}
if (read_only == 0) {
EraseExternal4KFlash_SPI(0);
BlukWriteExternalFlash_SPI(0,255,buf);
}
BlukReadExternalFlash_SPI( 0,255,buf );
for(i=0; i!=255; i++){
KPrintf("%d ",(UINT16)buf[i]);
}
KPrintf("done\n");
return 0;
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN),
SpiFlashTest, SpiFlashTest, test spi);

View File

@ -0,0 +1,3 @@
SRC_FILES := connect_sys.c
include $(KERNEL_ROOT)/compiler.mk

View File

@ -0,0 +1,280 @@
/*
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2022-07-15 Emuzit first version
*/
#include <xizi.h>
#include "xsconfig.h"
#include "board.h"
#include "xs_isr.h"
#include "CH56xSFR.h"
#include "connect_sys.h"
static uint32_t hclk_freq;
uint8_t _slp_clk_off0_irqn_bit(uint8_t irqn)
{
uint8_t bitpos;
switch (irqn)
{
case TMR0_IRQn: bitpos = RB_SLP_CLK_TMR0; break;
case TMR1_IRQn: bitpos = RB_SLP_CLK_TMR1; break;
case TMR2_IRQn: bitpos = RB_SLP_CLK_TMR2; break;
/* special case to control PWMX clock in irqn way */
case PWMX_OFFn: bitpos = RB_SLP_CLK_PWMX; break;
case UART0_IRQn: bitpos = RB_SLP_CLK_UART0; break;
case UART1_IRQn: bitpos = RB_SLP_CLK_UART1; break;
case UART2_IRQn: bitpos = RB_SLP_CLK_UART2; break;
case UART3_IRQn: bitpos = RB_SLP_CLK_UART3; break;
default:
bitpos = 0;
}
return bitpos;
}
uint8_t _slp_clk_off1_irqn_bit(uint8_t irqn)
{
uint8_t bitpos;
switch (irqn)
{
case SPI0_IRQn: bitpos = RB_SLP_CLK_SPI0; break;
case SPI1_IRQn: bitpos = RB_SLP_CLK_SPI1; break;
#if defined(SOC_CH567)
case SDC_IRQn: bitpos = RB_SLP_CLK_SDC; break;
case LED_IRQn: bitpos = RB_SLP_CLK_LED; break;
case USB0_IRQn: bitpos = RB_SLP_CLK_USB0; break;
case USB1_IRQn: bitpos = RB_SLP_CLK_USB1; break;
case ECDC_IRQn: bitpos = RB_SLP_CLK_ECDC; break;
#elif defined(SOC_CH568)
case SDC_IRQn: bitpos = RB_SLP_CLK_SDC; break;
case LED_IRQn: bitpos = RB_SLP_CLK_LED; break;
case USB1_IRQn: bitpos = RB_SLP_CLK_USB1; break;
case USB0_IRQn: bitpos = RB_SLP_CLK_SATA; break;
case ECDC_IRQn: bitpos = RB_SLP_CLK_ECDC; break;
#else
case EMMC_IRQn: bitpos = RB_SLP_CLK_EMMC; break;
case HSPI_IRQn: bitpos = RB_SLP_CLK_HSPI; break;
case USBHS_IRQn: bitpos = RB_SLP_CLK_USBHS; break;
case USBSS_IRQn: bitpos = RB_SLP_CLK_USBSS; break;
case SERDES_IRQn: bitpos = RB_SLP_CLK_SERD; break;
case DVP_IRQn: bitpos = RB_SLP_CLK_DVP; break;
#endif
default:
bitpos = 0;
}
return bitpos;
}
#if defined(SOC_SERIES_CH569)
uint8_t _wake_clk_off_irqn_bit(uint8_t irqn)
{
uint8_t bitpos;
switch (irqn)
{
case ETH_IRQn: bitpos = RB_SLP_CLK_ETH; break;
case ECDC_IRQn: bitpos = RB_SLP_CLK_ECDC; break;
default:
bitpos = 0;
}
return bitpos;
}
#endif
/**
* @brief Turn on/off device clock for group clk_off0.
*
* @param bits is a bit mask to select corresponding devices.
*
* @param off is to turn off the clock (1) or trun on (0).
*/
void sys_slp_clk_off0(uint8_t bits, int off)
{
volatile struct sys_registers *sys = (void *)SYS_REG_BASE;
x_base level;
uint8_t u8v;
u8v = sys->SLP_CLK_OFF0.reg;
if ((u8v & bits) != (off ? bits : 0))
{
u8v = off ? (u8v | bits) : (u8v & ~bits);
level = DisableLocalInterrupt();
sys_safe_access_enter(sys);
sys->SLP_CLK_OFF0.reg = u8v;
sys_safe_access_leave(sys);
EnableLocalInterrupt(level);
}
}
/**
* @brief Turn on/off device clock for group clk_off1.
*
* @param bits is a bit mask to select corresponding devices.
*
* @param off is to turn off the clock (1) or trun on (0).
*/
void sys_slp_clk_off1(uint8_t bits, int off)
{
volatile struct sys_registers *sys = (void *)SYS_REG_BASE;
x_base level;
uint8_t u8v;
u8v = sys->SLP_CLK_OFF1.reg;
if ((u8v & bits) != (off ? bits : 0))
{
u8v = off ? (u8v | bits) : (u8v & ~bits);
level = DisableLocalInterrupt();
sys_safe_access_enter(sys);
sys->SLP_CLK_OFF1.reg = u8v;
sys_safe_access_leave(sys);
EnableLocalInterrupt(level);
}
}
/**
* @brief Turn on/off device clock, specified by its irq number.
*
* @param irqn is the irq number of the target device.
* PWMX does not have irqn, use special PWMX_OFFn number.
*
* @param off is to turn off the clock (1) or trun on (0).
*
* @return Returns if irqn-device has corresponding clk off bit :
* 0 if device not found; otherwise bit position of off0/off1.
*/
int sys_clk_off_by_irqn(uint8_t irqn, int off)
{
volatile struct sys_registers *sys = (void *)SYS_REG_BASE;
uint8_t u8v;
size_t offset;
uint8_t bitpos = 0;
if (irqn < END_OF_IRQn)
{
if ((bitpos = _slp_clk_off0_irqn_bit(irqn)) != 0)
{
offset = offsetof(struct sys_registers, SLP_CLK_OFF0);
}
else if ((bitpos = _slp_clk_off1_irqn_bit(irqn)) != 0)
{
offset = offsetof(struct sys_registers, SLP_CLK_OFF1);
}
#if defined(SOC_SERIES_CH569)
else if ((bitpos = _wake_clk_off_irqn_bit(irqn)) != 0)
{
offset = offsetof(struct sys_registers, SLP_WAKE_CTRL);
}
#endif
if (bitpos)
{
volatile uint8_t *cxreg = (void *)sys;
x_base level;
u8v = cxreg[offset];
if ((u8v & bitpos) != (off ? bitpos : 0))
{
u8v = off ? (u8v | bitpos) : (u8v & ~bitpos);
level = DisableLocalInterrupt();
sys_safe_access_enter(sys);
cxreg[offset] = u8v;
sys_safe_access_leave(sys);
EnableLocalInterrupt(level);
}
}
}
return bitpos;
}
/**
* @brief Setup HCLK frequency.
*
* @param freq is the desired hclk frequency.
* supported : 120/96/80/60/48/40/32/30/15/10/6/3/2 MHz
*
* @return Returns 0 if hclk is successfully set.
*/
int sys_hclk_set(uint32_t freq)
{
volatile struct sys_registers *sys = (void *)SYS_REG_BASE;
uint8_t plldiv;
int clksel = -1;
if (freq >= 30000000)
{
if (freq <= 120000000)
{
/* supported : 120/96/80/60/48/40/32/30 MHz */
plldiv = 480000000 / freq; // 30M => 16 & 0xf => 0
clksel = RB_CLK_SEL_PLL;
}
}
else if (freq >= 2000000)
{
/* supported : 15/10/6/3/2 MHz */
plldiv = 30000000 / freq;
clksel = 0;
}
if (clksel >= 0)
{
x_base level = DisableLocalInterrupt();
sys_safe_access_enter(sys);
sys->CLK_PLL_DIV.reg = clk_pll_div_wdat(plldiv);
sys->CLK_CFG_CTRL.reg = clk_cfg_ctrl_wdat(clksel);
sys_safe_access_leave(sys);
EnableLocalInterrupt(level);
/* save to hclk_freq for quick report */
sys_hclk_calc();
clksel = 0;
}
return clksel;
}
/**
* @brief Get saved HCLK frequency.
*
* Valid only if HCLK is set strickly with sys_hclk_set().
* Use sys_hclk_calc() otherwise.
*
* @return Returns saved HCLK frequency (Hz, 0 if not set yet).
*/
uint32_t sys_hclk_get(void)
{
return hclk_freq;
}
/**
* @brief Get current HCLK frequency, calculated from hw setting.
*
* @return Returns current HCLK frequency (Hz).
*/
uint32_t sys_hclk_calc(void)
{
volatile struct sys_registers *sys = (void *)SYS_REG_BASE;
uint8_t plldiv = sys->CLK_PLL_DIV.pll_div;
if (sys->CLK_CFG_CTRL.sel_pll == CLK_SEL_PLL_USB_480M)
{
hclk_freq = plldiv ? 480000000 / plldiv : 30000000;
}
else
{
hclk_freq = plldiv ? 30000000 / plldiv : 2000000;
}
return hclk_freq;
}

View File

@ -0,0 +1,6 @@
menuconfig BSP_USING_USBD
bool "Using usbd device"
default y
if BSP_USING_USBD
source "$BSP_DIR/third_party_driver/usb/usbd/Kconfig"
endif

View File

@ -0,0 +1,5 @@
ifeq ($(CONFIG_BSP_USING_USBD),y)
SRC_DIR += usbd
endif
include $(KERNEL_ROOT)/compiler.mk

View File

@ -0,0 +1,3 @@
menuconfig BSP_USING_USBD_CDC
bool "Using usbd cdc device"
default y

View File

@ -0,0 +1,5 @@
ifeq ($(CONFIG_BSP_USING_USBD_CDC),y)
SRC_DIR += simulate_cdc
endif
include $(KERNEL_ROOT)/compiler.mk

View File

@ -0,0 +1,337 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : cdc.c
* Author : WCH
* Version : V1.2
* Date : 2024/07/10
* Description :
*********************************************************************************
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
* Attention: This software (modified or not) and binary are used for
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
*******************************************************************************/
#include "CH56x_common.h"
#include "CH56x_usb30_LIB.h"
#include "CH56x_usb30.h"
#include "CH56x_usb20.h"
#include "cdc.h"
/* Global define */
#define UART_REV_LEN 1024 //uart receive buffer size
#define UART_TIMEOUT 1000
/* Global Variable */
__attribute__ ((aligned(16))) UINT8 Receive_Uart_Buf[UART_REV_LEN] __attribute__((section(".DMADATA")));//uart receive buffer
volatile UINT16 Uart_Input_Point = 0; //Circular buffer write pointer
volatile UINT16 Uart_Output_Point = 0; //Loop buffer fetch pointer
volatile UINT16 UartByteCount = 0; //The number of bytes remaining to be fetched in the current buffer
volatile UINT16 USBByteCount = 0; //Data received by USB endpoint
volatile UINT16 USBBufOutPoint = 0; //Get data pointer
volatile UINT8 UploadPoint2_Busy = 0; //Upload whether the endpoint is busy
volatile UINT8 DownloadPoint2_Busy = 0; //Download whether the endpoint is busy
volatile UINT16 Uart_Timecount = 0; //Timeout processing calculation time
volatile UINT16 Uart_Sendlenth = 0; //USB upload data length
/* Function declaration */
void TMR2_IRQHandler (void) __attribute__((interrupt()));
void UART2_IRQHandler (void) __attribute__((interrupt()));
/*******************************************************************************
* @fn CDC_Uart_Init
*
* @brief CDC UART initialization
*
* @param baudrate: UART2 communication baud rate.
*
* @return None
*/
void CDC_Uart_Init( UINT32 baudrate )
{
UINT32 x;
UINT32 t = FREQ_SYS;
x = 10 * t * 2 / 16 / baudrate;
x = ( x + 5 ) / 10;
R8_UART2_DIV = 1;
R16_UART2_DL = x;
R8_UART2_FCR = RB_FCR_FIFO_TRIG | RB_FCR_TX_FIFO_CLR | RB_FCR_RX_FIFO_CLR | RB_FCR_FIFO_EN;
R8_UART2_LCR = RB_LCR_WORD_SZ;
R8_UART2_IER = RB_IER_TXD_EN;
GPIOA_SetBits(GPIO_Pin_3);
GPIOA_ModeCfg(GPIO_Pin_2, GPIO_ModeIN_PU_NSMT);
GPIOA_ModeCfg(GPIO_Pin_3, GPIO_Slowascent_PP_8mA);
UART2_ByteTrigCfg( UART_7BYTE_TRIG );
UART2_INTCfg( ENABLE, RB_IER_RECV_RDY|RB_IER_LINE_STAT );
PFIC_EnableIRQ( UART2_IRQn );
}
/*******************************************************************************
* @fn TMR2_TimerInit1
*
* @brief CDC timeout timer initialization
*
* @return None
*/
void TMR2_TimerInit1( void )
{
R32_TMR2_CNT_END = FREQ_SYS/100000; //10us
R8_TMR2_CTRL_MOD = RB_TMR_ALL_CLEAR;
R8_TMR2_CTRL_MOD = RB_TMR_COUNT_EN;
R8_TMR2_INTER_EN |= 0x01;
PFIC_EnableIRQ( TMR2_IRQn );
}
/*******************************************************************************
* @fn TMR2_IRQHandler
*
* @brief CDC timer interrupt function
*
* @return None
*/
void TMR2_IRQHandler( void )
{
if( R8_TMR2_INT_FLAG &0x01 )
{
R8_TMR2_INT_FLAG = 0x01;
Uart_Timecount++;
}
}
/*******************************************************************************
* @fn U30_CDC_UartRx_Deal
*
* @brief usb3.0 CDC serial port receiving data processing
*
* @return None
*/
void U30_CDC_UartRx_Deal( void )
{
if(!UploadPoint2_Busy)
{
Uart_Sendlenth = UartByteCount;
if(Uart_Sendlenth > 0)
{
if( (Uart_Sendlenth >= (UART_REV_LEN/2) && DownloadPoint2_Busy == 0 ) || Uart_Timecount > UART_TIMEOUT )//If the sent data overflows or times out, upload the data
{
if(Uart_Output_Point+Uart_Sendlenth>UART_REV_LEN)//Determine if the pointer to the stored data array is out of bounds
{
Uart_Sendlenth = UART_REV_LEN-Uart_Output_Point;
}
if(Uart_Sendlenth > (UART_REV_LEN/2))//Limit sending length
{
Uart_Sendlenth = (UART_REV_LEN/2);
}
UartByteCount -= Uart_Sendlenth;//Reduce the length of data to be sent
memcpy(endp2Txbuff,&Receive_Uart_Buf[Uart_Output_Point],Uart_Sendlenth);//Copy the data to be sent to the USB buffer
Uart_Output_Point+=Uart_Sendlenth;//Move buffer pointer
if(Uart_Output_Point>=UART_REV_LEN)
{
Uart_Output_Point = 0;
}
UploadPoint2_Busy = 1;
/* Start USB sending */
USB30_IN_ClearIT( ENDP_2 );
USB30_IN_Set( ENDP_2 , ENABLE , ACK , 1, Uart_Sendlenth);
USB30_Send_ERDY( ENDP_2 | IN , 1 );
Uart_Timecount = 0;
}
}
}
}
/*******************************************************************************
* @fn U20_CDC_UartRx_Deal
*
* @brief usb2.0 CDC serial port receiving data processing
*
* @return None
*/
void U20_CDC_UartRx_Deal( void )
{
UINT16 i= 0;
if(!UploadPoint2_Busy)
{
Uart_Sendlenth = UartByteCount;
if(Uart_Sendlenth>0)
{
if( (Uart_Sendlenth >= (UART_REV_LEN/4)) || Uart_Timecount > UART_TIMEOUT )
{
if(Uart_Output_Point+Uart_Sendlenth>UART_REV_LEN)
{
Uart_Sendlenth = UART_REV_LEN - Uart_Output_Point;
}
if(Uart_Sendlenth > (UART_REV_LEN/4))
{
Uart_Sendlenth = (UART_REV_LEN/4);
}
UartByteCount -= Uart_Sendlenth;
memcpy(endp2Txbuff,&Receive_Uart_Buf[Uart_Output_Point],Uart_Sendlenth);
Uart_Output_Point+=Uart_Sendlenth;
if(Uart_Output_Point>=UART_REV_LEN)
{
Uart_Output_Point = 0;
}
UploadPoint2_Busy = 1;
R16_UEP2_T_LEN = Uart_Sendlenth;
R8_UEP2_TX_CTRL = (R8_UEP2_TX_CTRL & ~RB_UEP_TRES_MASK) | UEP_T_RES_ACK;
Uart_Timecount = 0;
}
}
}
}
/*******************************************************************************
* @fn U30_CDC_UartTx_Deal
*
* @brief usb3.0 CDC serial port sending data processing
*
* @return None
*/
void U30_CDC_UartTx_Deal( void )
{
static UINT16 i = 0;
if(USBByteCount)//If there is any remaining data to be downloaded, it will be sent through the uart
{
UART2_SendString(&endp2Rxbuff[USBBufOutPoint++],1);
USBByteCount --;
}
if( DownloadPoint2_Busy == 0 )
{
if(USBByteCount == 0 && UploadPoint2_Busy == 0)//Allow Next Send
{
USBBufOutPoint = 0;
DownloadPoint2_Busy = 1;
USBSS->UEP2_RX_DMA = (UINT32)(UINT8 *)endp2Rxbuff;
USB30_OUT_ClearIT(ENDP_2);
USB30_OUT_Set( ENDP_2 , ACK , 1 );
USB30_Send_ERDY( ENDP_2 | OUT , 1 );
}
}
}
/*******************************************************************************
* @fn U20_CDC_UartTx_Deal
*
* @brief usb2.0 CDC serial port sending data processing
*
* @return None
*/
void U20_CDC_UartTx_Deal( void )
{
static UINT16 i = 0;
if(USBByteCount)
{
UART2_SendString(&endp2Rxbuff[USBBufOutPoint++],1);
USBByteCount--;
if(USBByteCount==0){
USBBufOutPoint = 0;
R32_UEP2_RX_DMA = (UINT32)(UINT8 *)endp2Rxbuff;
R8_UEP2_RX_CTRL = (R8_UEP2_RX_CTRL &~RB_UEP_RRES_MASK)|UEP_R_RES_ACK;
}
}
}
/*******************************************************************************
* @fn CDC_Uart_Deal
*
* @brief CDC processing function
*
* @return None
*/
void CDC_Uart_Deal( void )
{
if( Link_Sta == LINK_STA_1)//2.0
{
U20_CDC_UartTx_Deal();
U20_CDC_UartRx_Deal();
}
else
{
U30_CDC_UartTx_Deal();
U30_CDC_UartRx_Deal();
}
}
/*******************************************************************************
* @fn CDC_Variable_Clear
*
* @brief CDC variable initialization
*
* @return None
*/
void CDC_Variable_Clear(void){
Uart_Input_Point = 0;
Uart_Output_Point = 0;
UartByteCount = 0;
USBByteCount = 0;
USBBufOutPoint = 0;
UploadPoint2_Busy = 0;
Uart_Timecount = 0;
Uart_Sendlenth = 0;
}
/*******************************************************************************
* @fn UART2_IRQHandler
*
* @brief CDC serial port interrupt function
*
* @return None
*/
void UART2_IRQHandler(void)
{
UINT8 i,rec_length;
UINT8 rec[7] = {0};
switch( UART2_GetITFlag() )
{
case UART_II_LINE_STAT: //Line status error
printf("error:%x\n",R8_UART2_LSR);
break;
case UART_II_RECV_RDY: //Data reaches the trigger point
for(rec_length = 0; rec_length < 7; rec_length++)
{
Receive_Uart_Buf[Uart_Input_Point++] = UART2_RecvByte();
if(Uart_Input_Point>=UART_REV_LEN )
{
Uart_Input_Point = 0;
}
}
UartByteCount += rec_length;
Uart_Timecount = 0;
break;
case UART_II_RECV_TOUT: //Receive timeout
rec_length = UART2_RecvString(rec);
for(i = 0; i < rec_length ; i++)
{
Receive_Uart_Buf[Uart_Input_Point++] = rec[i];
if(Uart_Input_Point>=UART_REV_LEN )
{
Uart_Input_Point = 0;
}
}
UartByteCount += i;
Uart_Timecount = 0;
break;
case UART_II_THR_EMPTY: //Send buffer empty
break;
default:
break;
}
}

View File

@ -0,0 +1,3 @@
SRC_FILES := connect_cdc.c USB20/CH56x_usb20.c USB30/CH56x_usb30.c CDC/cdc.c
include $(KERNEL_ROOT)/compiler.mk

View File

@ -0,0 +1,756 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : CH56x_usb20.c
* Author : WCH
* Version : V1.2
* Date : 2024/07/10
* Description :
*********************************************************************************
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
* Attention: This software (modified or not) and binary are used for
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
*******************************************************************************/
#include "CH56x_common.h"
#include "CH56x_usb20.h"
#include "CH56x_usb30.h"
#include "CH56x_usb30_LIB.h"
#include "cdc.h"
/* Global Variable */
UINT32V U20_vitrul_buad = 115200;
UINT16V U20_EndpnMaxSize = 512;
UINT16V SetupReqLen=0; //Host request data length
UINT16V SetupLen = 0; //Data length actually sent or received in data phase
UINT32V seq_num = 0;
DevInfo_Typedef g_devInfo;
static UINT8V SetupReqType = 0; //Host request descriptor type
static UINT8V SetupReq = 0; //Host request descriptor type
static PUINT8 pDescr;
extern UINT8V Link_Sta;
__attribute__ ((aligned(16))) UINT8 vendor_buff[16] __attribute__((section(".DMADATA")));
/* Function declaration */
void USBHS_IRQHandler(void) __attribute__((interrupt()));
const UINT8 hs_device_descriptor[] =
{
0x12, // bLength
0x01, // DEVICE descriptor type
0x00, // 2.00
0x02,
0x02, // device class
0x00, // device sub-class
0x00, // vendor specific protocol
0x40, // max packet size 64B
0x86, // vendor id-0x1A86(qinheng)
0x1A,
0x0c, // product id 0xfe0c
0xfe,
0x01, //bcdDevice 0x01
0x00,
0x01, // manufacturer index string
0x02, // product index string
0x03, // serial number index string
0x01 // number of configurations
};
const UINT8 hs_config_descriptor[] =
{
0x09, // length of this descriptor
0x02, // CONFIGURATION (2)
0x43, // total length includes endpoint descriptors (should be 1 more than last address)
0x00, // total length high byte
0x02, // number of interfaces
0x01, // configuration value for this one
0x00, // configuration - string is here, 0 means no string
0x80, // attributes - bus powered, no wakeup
0x32, // max power - 800 ma is 100 (64 hex)
/*control interface*/
0x09, // length of the interface descriptor
0x04, // INTERFACE (4)
0x00, // Zero based index 0f this interface
0x00, // Alternate setting value (?)
0x01, // Number of endpoints (not counting 0)
0x02, // Interface class, ff is vendor specific
0x02, // Interface sub-class
0x01, // Interface protocol
0x00, // Index to string descriptor for this interface
/*Header Functional Descriptor*/
0x05, /* bLength: Endpoint Descriptor size */
0x24, /* bDescriptorType: CS_INTERFACE */
0x00, /* bDescriptorSubtype: Header Func Desc */
0x10, /* bcdCDC: spec release number */
0x01,
/*Call Management Functional Descriptor*/
0x05, /* bFunctionLength */
0x24, /* bDescriptorType: CS_INTERFACE */
0x01, /* bDescriptorSubtype: Call Management Func Desc */
0x00,
0x01,
0x04,
0x24,
0x02,
0x02,
0x05,
0x24,
0x06,
0x00,
0x01,
0x07, // length of this endpoint descriptor
0x05, // ENDPOINT (5)
0x81, // endpoint direction (80 is in) and address
0x03, // transfer type - 00 = control, 01 = iso, 10 = bulk, 11 = int
0x40, // max packet size - 1024 bytes
0x00, // max packet size - high
0x01, // polling interval in milliseconds (1 for iso)
/*data interface*/
0x09, // length of the interface descriptor
0x04, // INTERFACE (4)
0x01, // Zero based index 0f this interface
0x00, // Alternate setting value (?)
0x02, // Number of endpoints (not counting 0)
0x0a, // Interface class, ff is vendor specific
0x00, // Interface sub-class
0x00, // Interface protocol
0x00, // Index to string descriptor for this interface
//Endpoint 2 Descriptor
0x07, // length of this endpoint descriptor
0x05, // ENDPOINT (5)
0x82, // endpoint direction (80 is in) and address
0x02, // transfer type - 00 = control, 01 = iso, 10 = bulk, 11 = int
0x00, // max packet size - 1024 bytes
0x02, // max packet size - high
0x00, // polling interval in milliseconds (1 for iso)
//endp2_descriptor
0x07, // length of this endpoint descriptor
0x05, // ENDPOINT (5)
0x02, // endpoint direction (00 is out) and address
0x02, // transfer type - 00 = control, 01 = iso, 10 = bulk, 11 = int
0x00, // max packet size - 1024 bytes
0x02, // max packet size - high
0x00, // polling interval in milliseconds (1 for iso)
};
/* Language Descriptor */
const UINT8 hs_string_descriptor0[] =
{
0x04, // this descriptor length
0x03, // descriptor type
0x09, // Language ID 0 low byte
0x04 // Language ID 0 high byte
};
/* Manufacturer Descriptor */
const UINT8 hs_string_descriptor1[] =
{
0x08, // length of this descriptor
0x03,
'W',
0x00,
'C',
0x00,
'H',
0x00
};
/* Product Descriptor */
const UINT8 hs_string_descriptor2[]=
{
38, //38 bytes
0x03, //0x03
0x57, 0x00, //W
0x43, 0x00, //C
0x48, 0x00, //H
0x20, 0x00, //
0x55, 0x00, //U
0x53, 0x00, //S
0x42, 0x00, //B
0x32, 0x00, //2
0x2e, 0x00, //.
0x30, 0x00, //0
0x20, 0x00, //
0x44, 0x00, //D
0x45, 0x00, //E
0x56, 0x00, //V
0x49, 0x00, //I
0x43, 0x00, //C
0x45, 0x00, //E
0x20, 0x00 //
};
const UINT8 hs_bos_descriptor[] =
{
0x05, // length of this descriptor
0x0f, // CONFIGURATION (2)
0x16, // total length includes endpoint descriptors (should be 1 more than last address)
0x00, // total length high byte
0x02, // number of device cap
0x07,
0x10, // DEVICE CAPABILITY type
0x02, // USB2.0 EXTENSION
0x02,
0x00,
0x00,
0x00,
0x0a, // length of this descriptor
0x10, // DEVICE CAPABILITY type
0x03, // superspeed usb device capability
0x00, //
0x0e, // ss/hs/fs
0x00,
0x01, // the lowest speed is full speed
0x0a, // u1 exit latency is 10us
0xff, // u1 exit latency is 8us
0x07
};
/*******************************************************************************
* @fn USB20_Endp_Init
*
* @brief USB2.0 Endpoint initialization
*
* @return None
*/
void USB20_Endp_Init () // USBHS device endpoint initial
{
R8_UEP4_1_MOD = RB_UEP1_TX_EN;
R8_UEP2_3_MOD = RB_UEP2_RX_EN | RB_UEP2_TX_EN ;
R16_UEP0_MAX_LEN = 64;
R16_UEP1_MAX_LEN = 512;
R16_UEP2_MAX_LEN = 512;
R32_UEP0_RT_DMA = (UINT32)(UINT8 *)endp0RTbuff;
R32_UEP1_TX_DMA = (UINT32)(UINT8 *)endp1RTbuff;
R32_UEP2_TX_DMA = (UINT32)(UINT8 *)endp2Txbuff;
R32_UEP2_RX_DMA = (UINT32)(UINT8 *)endp2Rxbuff;
R16_UEP0_T_LEN = 0;
R8_UEP0_TX_CTRL = UEP_T_RES_NAK;
R8_UEP0_RX_CTRL = 0;
R16_UEP1_T_LEN = 0;
R8_UEP1_TX_CTRL = UEP_T_RES_NAK ;
R16_UEP2_T_LEN = U20_MAXPACKET_LEN;
R8_UEP2_TX_CTRL = UEP_T_RES_NAK | RB_UEP_T_TOG_0;
R8_UEP2_RX_CTRL = UEP_R_RES_ACK | RB_UEP_R_TOG_0;
}
/*******************************************************************************
* @fn USB20_Device_Init
*
* @brief USB2.0 Device initialization
*
* @param sta - ENABLE / DISABLE
*
* @return None
*/
void USB20_Device_Init ( FunctionalState sta ) // USBHS device initial
{
UINT16 i;
UINT32 *p;
if(sta)
{
R8_USB_CTRL = 0;
R8_USB_CTRL = UCST_HS | RB_DEV_PU_EN | RB_USB_INT_BUSY |RB_USB_DMA_EN;
R8_USB_INT_EN = RB_USB_IE_SETUPACT | RB_USB_IE_TRANS | RB_USB_IE_SUSPEND |RB_USB_IE_BUSRST ;
USB20_Endp_Init();
}
else
{
R8_USB_CTRL = RB_USB_CLR_ALL | RB_USB_RESET_SIE;
}
}
/*******************************************************************************
* @fn USB20_Device_setaddress
*
* @brief USB2.0 Set device address
*
* @param address
*
* @return None
**/
void USB20_Device_Setaddress( UINT32 address )
{
R8_USB_DEV_AD = address; // SET ADDRESS
}
/*******************************************************************************
* @fn U20_NonStandard_Request_Deal
*
* @brief Non-standard request processing
*
* @return None
*/
UINT16 U20_NonStandard_Request_Deal()
{
UINT16 len = 0;
switch( UsbSetupBuf->bRequest )
{
/* Open the serial port and send the baud rate */
case 0x20:
R8_UEP0_RX_CTRL = UEP_R_RES_ACK | RB_UEP_R_TOG_1;
break;
/* Read the current serial port configuration */
case 0x21:
*(UINT32 *)&endp0RTbuff[0] = U20_vitrul_buad;
endp0RTbuff[4]=0x00;endp0RTbuff[5]=0x00;endp0RTbuff[6]=0x08;
len = 7;
break;
/* Close uart */
case 0x22:
CDC_Variable_Clear();
break;
case 0x02:
break;
default:
return USB_DESCR_UNSUPPORTED;
break;
}
return len;
}
/*******************************************************************************
* @fn U20_Standard_Request_Deal
*
* @brief USB2.0 standard request deal
*
* @return None
*/
UINT16 U20_Standard_Request_Deal()
{
UINT16 len = 0;
UINT8 endp_dir;
SetupLen = 0;
endp_dir = UsbSetupBuf->bRequestType & 0x80;
switch( SetupReq )
{
case USB_GET_DESCRIPTOR:
{
switch( UsbSetupBuf->wValueH )
{
case USB_DESCR_TYP_DEVICE:
pDescr = (UINT8 *)hs_device_descriptor;
SetupLen = ( SetupReqLen > sizeof(hs_device_descriptor) )? sizeof(hs_device_descriptor):SetupReqLen;
break;
case USB_DESCR_TYP_CONFIG:
pDescr = (UINT8 *)hs_config_descriptor;
SetupLen = ( SetupReqLen > sizeof(hs_config_descriptor) )? sizeof(hs_config_descriptor):SetupReqLen;
break;
case USB_DESCR_TYP_STRING:
switch( UsbSetupBuf->wValueL )
{
case USB_DESCR_LANGID_STRING:
pDescr = (UINT8 *)hs_string_descriptor0;
SetupLen = ( SetupReqLen > sizeof(hs_string_descriptor0) )? sizeof(hs_string_descriptor0):SetupReqLen;
break;
case USB_DESCR_VENDOR_STRING:
pDescr = (UINT8 *)hs_string_descriptor1;
SetupLen = ( SetupReqLen > sizeof(hs_string_descriptor1) )? sizeof(hs_string_descriptor1):SetupReqLen;
break;
case USB_DESCR_PRODUCT_STRING:
pDescr =(UINT8 *) hs_string_descriptor2;
SetupLen = ( SetupReqLen > sizeof(hs_string_descriptor2) )? sizeof(hs_string_descriptor2):SetupReqLen;
break;
case USB_DESCR_SERIAL_STRING:
break;
default:
SetupLen = USB_DESCR_UNSUPPORTED;
break;
}
break;
case USB_DESCR_TYP_BOS:
pDescr =(UINT8 *) hs_bos_descriptor;
SetupLen = ( SetupReqLen > sizeof(hs_bos_descriptor) )? sizeof(hs_bos_descriptor):SetupReqLen;
break;
default :
SetupLen = USB_DESCR_UNSUPPORTED;
break;
}
}
break;
case USB_SET_ADDRESS:
g_devInfo.dev_addr = UsbSetupBuf->wValueL;
break;
case USB_GET_CONFIGURATION:
endp0RTbuff[ 0 ] = g_devInfo.dev_config_value;
SetupLen = 1;
break;
case USB_SET_CONFIGURATION:
if( (R8_USB_SPD_TYPE & RB_USBSPEED_MASK) == UST_FS )
{
U20_EndpnMaxSize = 64;
}
else if( (R8_USB_SPD_TYPE & RB_USBSPEED_MASK) == UST_LS )
{
U20_EndpnMaxSize = 8;
}
g_devInfo.dev_config_value = UsbSetupBuf->wValueL;
g_devInfo.dev_enum_status = 0x01;
break;
case USB_CLEAR_FEATURE:
if( ( UsbSetupBuf->bRequestType & USB_REQ_RECIP_MASK ) == USB_REQ_RECIP_ENDP )
{
switch( UsbSetupBuf->wIndexL )
{
case 0x82:
R16_UEP2_T_LEN= 0;
R8_UEP2_TX_CTRL = UEP_T_RES_NAK | RB_UEP_T_TOG_0;
break;
case 0x02:
R8_UEP2_TX_CTRL = UEP_R_RES_ACK | RB_UEP_R_TOG_0;
break;
case 0x81:
R16_UEP1_T_LEN = 0;
R8_UEP1_TX_CTRL = UEP_T_RES_NAK | RB_UEP_T_TOG_0;
break;
case 0x01:
R8_UEP1_RX_CTRL = UEP_T_RES_ACK | RB_UEP_R_TOG_0;
break;
default:
SetupLen = USB_DESCR_UNSUPPORTED;
break;
}
}
else if( ( UsbSetupBuf->bRequestType & USB_REQ_RECIP_MASK ) == USB_REQ_RECIP_DEVICE )
{
if( ( UsbSetupBuf->wValueL ) == 1 )
{
g_devInfo.dev_sleep_status &= ~0x01;
}
}
else
{
SetupLen = USB_DESCR_UNSUPPORTED;
}
break;
case USB_SET_FEATURE:
if( ( UsbSetupBuf->bRequestType & 0x1F ) == 0x00 )
{
if( UsbSetupBuf->wValueL == 0x01 )
{
if( hs_config_descriptor[ 7 ] & 0x20 )
{
g_devInfo.dev_sleep_status = 0x01;
}
else
{
SetupLen = USB_DESCR_UNSUPPORTED;
}
}
else
{
SetupLen = USB_DESCR_UNSUPPORTED;
}
}
else if( ( UsbSetupBuf->bRequestType & 0x1F ) == 0x02 )
{
if( UsbSetupBuf->wValueL == 0x00 )
{
switch( UsbSetupBuf->wIndexL )
{
case 0x82:
R8_UEP2_TX_CTRL = ( R8_UEP2_TX_CTRL & ~RB_UEP_TRES_MASK ) | UEP_T_RES_STALL;
break;
case 0x02:
R8_UEP2_RX_CTRL = ( R8_UEP2_RX_CTRL & ~RB_UEP_RRES_MASK ) | UEP_R_RES_STALL;
break;
case 0x81:
R8_UEP1_TX_CTRL = ( R8_UEP1_TX_CTRL & ~RB_UEP_TRES_MASK ) | UEP_T_RES_STALL;
break;
case 0x01:
R8_UEP1_RX_CTRL = ( R8_UEP1_RX_CTRL & ~RB_UEP_RRES_MASK ) | UEP_R_RES_STALL;
break;
default:
SetupLen = USB_DESCR_UNSUPPORTED;
break;
}
}
else
{
SetupLen = USB_DESCR_UNSUPPORTED;
}
}
else
{
SetupLen = USB_DESCR_UNSUPPORTED;
}
break;
case USB_GET_INTERFACE:
break;
case USB_SET_INTERFACE:
break;
case USB_GET_STATUS:
endp0RTbuff[ 0 ] = 0x00;
endp0RTbuff[ 1 ] = 0x00;
SetupLen = 2;
if( UsbSetupBuf->wIndexL == 0x81 )
{
if( ( R8_UEP1_TX_CTRL & RB_UEP_TRES_MASK ) == UEP_T_RES_STALL )
{
endp0RTbuff[ 0 ] = 0x01;
SetupLen = 1;
}
}
else if( UsbSetupBuf->wIndexL == 0x01 )
{
if( ( R8_UEP1_RX_CTRL & RB_UEP_RRES_MASK ) == UEP_R_RES_STALL )
{
endp0RTbuff[ 0 ] = 0x01;
SetupLen = 1;
}
}
else if( UsbSetupBuf->wIndexL == 0x82 )
{
if( ( R8_UEP2_TX_CTRL & RB_UEP_TRES_MASK ) == UEP_T_RES_STALL )
{
endp0RTbuff[ 0 ] = 0x01;
SetupLen = 1;
}
}
else if( UsbSetupBuf->wIndexL == 0x02 )
{
if( ( R8_UEP2_RX_CTRL & RB_UEP_RRES_MASK ) == UEP_R_RES_STALL )
{
endp0RTbuff[ 0 ] = 0x01;
SetupLen = 1;
}
}
break;
default:
SetupLen = USB_DESCR_UNSUPPORTED;
break;
}
if( (SetupLen != USB_DESCR_UNSUPPORTED) && (SetupLen != 0))
{
len = ( SetupLen >= U20_UEP0_MAXSIZE ) ? U20_UEP0_MAXSIZE : SetupLen;
if(endp_dir)
{
memcpy( endp0RTbuff, pDescr, len );
pDescr += len;
}
SetupLen -= len;
}
return len;
}
/*******************************************************************************
* @fn USBHSD_IRQHandler
*
* @brief USB2.0 Interrupt Handler.
*
* @return None
*/
void USBHS_IRQHandler(void) //USBHS interrupt service
{
UINT32 end_num;
UINT32 rx_token;
UINT16 ret_len,i;
UINT16 rxlen;
UINT8 *p8;
UINT8 int_flg;
UINT32 baudrate;
int_flg = R8_USB_INT_FG;
if( int_flg & RB_USB_IF_SETUOACT ) //SETUP interrupt
{
#if 0
printf("SETUP :");
p8 = (UINT8 *)endp0RTbuff;
for(i=0; i<8; i++) { printf("%02x ", *p8++); }
printf("\n");
#endif
SetupReqType = UsbSetupBuf->bRequestType;
SetupReq = UsbSetupBuf->bRequest;
SetupReqLen = UsbSetupBuf->wLength; //Data length
/*Analyze host requests*/
if((UsbSetupBuf->bRequestType & USB_REQ_TYP_MASK) != USB_REQ_TYP_STANDARD)
{
ret_len = U20_NonStandard_Request_Deal();
}
else
{
ret_len = U20_Standard_Request_Deal();
}
if(ret_len == 0xFFFF)
{
R16_UEP0_T_LEN = 0;
R8_UEP0_TX_CTRL = UEP_T_RES_STALL ;
R8_UEP0_RX_CTRL = UEP_R_RES_STALL ;
}
else
{
R16_UEP0_T_LEN = ret_len;
R8_UEP0_TX_CTRL = UEP_T_RES_ACK | RB_UEP_T_TOG_1;
R8_UEP0_RX_CTRL = UEP_R_RES_ACK | RB_UEP_R_TOG_1;
}
R8_USB_INT_FG = RB_USB_IF_SETUOACT; // clear int flag
}
/*Transaction transfer complete interrupt*/
else if( int_flg & RB_USB_IF_TRANSFER )
{
end_num = R8_USB_INT_ST & 0xf;
rx_token = ( (R8_USB_INT_ST )>>4) & 0x3;
#if 0
if( !(R8_USB_INT_ST & RB_USB_ST_TOGOK) )
{
printf(" TOG MATCH FAIL : ENDP %x token %x \n", end_num, rx_token);
}
#endif
switch( end_num )
{
case 0:
if( rx_token == PID_IN )
{
ret_len = U20_Endp0_IN_Callback();
if(ret_len == 0)
{
R8_UEP0_RX_CTRL = UEP_R_RES_ACK | RB_UEP_R_TOG_1;
R16_UEP0_T_LEN = 0;
R8_UEP0_TX_CTRL = 0;
}
else
{
R16_UEP0_T_LEN = ret_len;
R8_UEP0_TX_CTRL ^= RB_UEP_T_TOG_1;
R8_UEP0_TX_CTRL = ( R8_UEP0_TX_CTRL &~RB_UEP_TRES_MASK )| UEP_T_RES_ACK ;
}
}
else if( rx_token == PID_OUT )
{
SetupLen -= SetupLen > R16_USB_RX_LEN ? R16_USB_RX_LEN :SetupLen;
if( SetupLen > 0 )
{
R8_UEP0_RX_CTRL ^=RB_UEP_R_TOG_1;
R8_UEP0_RX_CTRL = ( R8_UEP0_RX_CTRL &~RB_UEP_RRES_MASK) | UEP_R_RES_ACK;
}
else
{
R16_UEP0_T_LEN = 0;
R8_UEP0_TX_CTRL = UEP_T_RES_ACK | RB_UEP_T_TOG_1;
R8_UEP0_RX_CTRL = 0 ;
}
/* save bauds */
baudrate = endp0RTbuff[ 0 ];
baudrate += ((UINT32)endp0RTbuff[ 1 ] << 8 );
baudrate += ((UINT32)endp0RTbuff[ 2 ] << 16 );
baudrate += ((UINT32)endp0RTbuff[ 3 ] << 24 );
U20_vitrul_buad = baudrate;
CDC_Uart_Init(baudrate);
}
break;
case 1:
break;
case 2:
if(rx_token == PID_IN)
{
R16_UEP2_T_LEN = 0;
R8_UEP2_TX_CTRL ^= RB_UEP_T_TOG_1;
R8_UEP2_TX_CTRL = (R8_UEP2_TX_CTRL & ~RB_UEP_TRES_MASK) | UEP_T_RES_NAK;
UploadPoint2_Busy = 0;
}
else if(rx_token == PID_OUT)
{
USBByteCount = R16_USB_RX_LEN;
R8_UEP2_RX_CTRL ^= RB_UEP_R_TOG_1;
R8_UEP2_RX_CTRL = (R8_UEP2_RX_CTRL &~RB_UEP_RRES_MASK) | UEP_R_RES_NAK;
}
break;
case 3:
break;
case 4:
break;
case 5:
break;
case 6:
break;
case 7:
break;
default:
break;
}
R8_USB_INT_FG = RB_USB_IF_TRANSFER;
}
else if( int_flg & RB_USB_IF_BUSRST )
{
USB20_Endp_Init();
USB20_Device_Setaddress( 0 );
R8_USB_INT_FG = RB_USB_IF_BUSRST;
if( Link_Sta == LINK_STA_1 )
{
PFIC_EnableIRQ(USBSS_IRQn);
PFIC_EnableIRQ(LINK_IRQn);
PFIC_EnableIRQ(TMR0_IRQn);
R8_TMR0_INTER_EN = 1;
TMR0_TimerInit( 67000000 );
USB30D_init(ENABLE);
}
}
else if( int_flg & RB_USB_IF_SUSPEND )
{
R8_USB_INT_FG = RB_USB_IF_SUSPEND;
}
}
/*******************************************************************************
* @fn U20_Endp0_IN_Callback
*
* @brief U20_Endp0_IN_Callback Handler.
*
* @return None
*/
UINT16 U20_Endp0_IN_Callback(void)
{
UINT16 len = 0;
switch(SetupReq)
{
case USB_GET_DESCRIPTOR:
len = SetupLen >= U20_UEP0_MAXSIZE ? U20_UEP0_MAXSIZE : SetupLen;
memcpy(endp0RTbuff, pDescr, len);
SetupLen -= len;
pDescr += len;
break;
case USB_SET_ADDRESS:
USB20_Device_Setaddress(g_devInfo.dev_addr);
break;
default:
break;
}
return len;
}

View File

@ -0,0 +1,832 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : CH56x_usb30.c
* Author : WCH
* Version : V1.2
* Date : 2024/07/10
* Description :
*********************************************************************************
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
* Attention: This software (modified or not) and binary are used for
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
*******************************************************************************/
#include "CH56x_common.h"
#include "CH56x_usb30_LIB.h"
#include "CH56x_usb20.h"
#include "CH56x_usb30.h"
#include "cdc.h"
/* Global Variable */
UINT8V Tx_Lmp_Port = 0;
UINT8V Link_Sta = 0;
UINT32V vitrul_buad = 115200;
static UINT32 SetupLen = 0;
static UINT8 SetupReqCode = 0;
static PUINT8 pDescr;
__attribute__ ((aligned(16))) UINT8 endp0RTbuff[512] __attribute__((section(".DMADATA"))); //Endpoint 0 data receiving and sending buffer
__attribute__ ((aligned(16))) UINT8 endp1RTbuff[4096] __attribute__((section(".DMADATA"))); //Endpoint 1 data receiving and sending buffer
__attribute__ ((aligned(16))) UINT8 endp2Rxbuff[4096] __attribute__((section(".DMADATA"))); //Endpoint 2 data receiving and sending buffer
__attribute__ ((aligned(16))) UINT8 endp2Txbuff[4096] __attribute__((section(".DMADATA"))); //Endpoint 2 data receiving and sending buffer
/*Superspeed device descriptor*/
const UINT8 SS_DeviceDescriptor[] =
{
0x12, // bLength
0x01, // DEVICE descriptor type
0x00, // 3.00
0x03,
0x02, // device class
0x00, // device sub-class
0x00, // vendor specific protocol
0x09, // max packet size 512B
0x86, // vendor id 0x1a86
0x1a,
0x0c, // product id 0xfe0c
0xfe,
0x01, // bcdDevice
0x00,
0x01, // manufacturer index string
0x02, // product index string
0x03, // serial number index string
0x01 // number of configurations
};
/*Superspeed Configuration Descriptor*/
const UINT8 SS_ConfigDescriptor[] =
{
0x09, // length of this descriptor
0x02, // CONFIGURATION (2)
85, // total length includes endpoint descriptors (should be 1 more than last address)
0x00, // total length high byte
0x02, // number of interfaces
0x01, // configuration value for this one
0x00, // configuration - string is here, 0 means no string
0x80, // attributes - bus powered, no wakeup
0x64, // max power - 800 ma is 100 (64 hex)
0x09, // length of the interface descriptor
0x04, // INTERFACE (4)
0x00, // Zero based index 0f this interface
0x00, // Alternate setting value (?)
0x01, // Number of endpoints (not counting 0)
0x02, // Interface class, ff is vendor specific
0x02, // Interface sub-class
0x01, // Interface protocol
0x00, // Index to string descriptor for this interface
0x05, /* bLength: Endpoint Descriptor size */
0x24, /* bDescriptorType: CS_INTERFACE */
0x00, /* bDescriptorSubtype: Header Func Desc */
0x10, /* bcdCDC: spec release number */
0x01,
0x05, /* bFunctionLength */
0x24, /* bDescriptorType: CS_INTERFACE */
0x01, /* bDescriptorSubtype: Call Management Func Desc */
0x00,
0x01,
0x04,
0x24,
0x02,
0x02,
0x05,
0x24,
0x06,
0x00,
0x01,
0x07, // length of this endpoint descriptor
0x05, // ENDPOINT (5)
0x81, // endpoint direction (80 is in) and address
0x03, // transfer type - 00 = control, 01 = iso, 10 = bulk, 11 = int
0x00, // max packet size - 1024 bytes
0x04, // max packet size - high
0x08, // polling interval in milliseconds (1 for iso)
0x06, // length of this endpoint compansion descriptor
0x30,
0x00, // max burst size
0x00, // no stream
0x00,
0x00,
0x09, // length of the interface descriptor
0x04, // INTERFACE (4)
0x01, // Zero based index 0f this interface
0x00, // Alternate setting value (?)
0x02, // Number of endpoints (not counting 0)
0x0a, // Interface class, ff is vendor specific
0x00, // Interface sub-class
0x00, // Interface protocol
0x00, // Index to string descriptor for this interface
//Endpoint 2 Descriptor
0x07, // length of this endpoint descriptor
0x05, // ENDPOINT (5)
0x82, // endpoint direction (80 is in) and address
0x02, // transfer type - 00 = control, 01 = iso, 10 = bulk, 11 = int
0x00, // max packet size - 1024 bytes
0x04, // max packet size - high
0x00, // polling interval in milliseconds (1 for iso)
0x06, // length of this endpoint compansion descriptor
0x30,
0x00, // max burst size
0x00, // no stream
0x00,
0x00,
//endp2_descriptor
0x07, // length of this endpoint descriptor
0x05, // ENDPOINT (5)
0x02, // endpoint direction (00 is out) and address
0x02, // transfer type - 00 = control, 01 = iso, 10 = bulk, 11 = int
0x00, // max packet size - 1024 bytes
0x04, // max packet size - high
0x00, // polling interval in milliseconds (1 for iso)
0x06, // length of this endpoint compansion descriptor
0x30,
0x00, // max burst size
0x00, // no stream
0x00,
0x00
};
/*String Descriptor Lang ID*/
const UINT8 StringLangID[] =
{
0x04, // this descriptor length
0x03, // descriptor type
0x09, // Language ID 0 low byte
0x04 // Language ID 0 high byte
};
/*String Descriptor Vendor*/
const UINT8 StringVendor[] =
{
0x08, // length of this descriptor
0x03,
'W',
0x00,
'C',
0x00,
'H',
0x00
};
/*String Descriptor Product*/
const UINT8 StringProduct[]=
{
38, //38 bytes in length
0x03, //Type code
0x57, 0x00, //W
0x43, 0x00, //C
0x48, 0x00, //H
0x20, 0x00, //
0x55, 0x00, //U
0x53, 0x00, //S
0x42, 0x00, //B
0x33, 0x00, //3
0x2e, 0x00, //.
0x30, 0x00, //0
0x20, 0x00, //
0x44, 0x00, //D
0x45, 0x00, //E
0x56, 0x00, //V
0x49, 0x00, //I
0x43, 0x00, //C
0x45, 0x00, //E
0x20, 0x00
};
/*String Descriptor Serial*/
UINT8 StringSerial[] =
{
0x16, // length of this descriptor
0x03,
'0',
0x00,
'1',
0x00,
'2',
0x00,
'3',
0x00,
'4',
0x00,
'5',
0x00,
'6',
0x00,
'7',
0x00,
'8',
0x00,
'9',
0x00,
};
const UINT8 OSStringDescriptor[] =
{
0x12, // length of this descriptor
0x03,
'M',
0x00,
'S',
0x00,
'F',
0x00,
'T',
0x00,
'1',
0x00,
'0',
0x00,
'0',
0x00,
0x01,
0x00
};
const UINT8 BOSDescriptor[] =
{
0x05, // length of this descriptor
0x0f, // CONFIGURATION (2)
0x16, // total length includes endpoint descriptors (should be 1 more than last address)
0x00, // total length high byte
0x02, // number of device cap
//dev_cap_descriptor1
0x07,
0x10, // DEVICE CAPABILITY type
0x02, // USB2.0 EXTENSION
0x06,
0x00,
0x00,
0x00,
//dev_cap_descriptor2
0x0a, // length of this descriptor
0x10, // DEVICE CAPABILITY type
0x03, // superspeed usb device capability
0x00, //
0x0e, // ss/hs/fs
0x00,
0x01, // the lowest speed is full speed
0x0a, // u1 exit latency is 10us
0xff, // u1 exit latency is 8us
0x07
};
/*******************************************************************************
* @fn USB30D_init
*
* @brief USB3.0 initialization
*
* @return None
*/
void USB30D_init(FunctionalState sta) {
UINT16 i,s;
if (sta) {
USB30_Device_Init();
USBSS->UEP0_DMA = (UINT32)(UINT8 *)endp0RTbuff;
USBSS->UEP1_TX_DMA = (UINT32)(UINT8 *)endp1RTbuff;
USBSS->UEP2_TX_DMA = (UINT32)(UINT8 *)endp2Txbuff;
USBSS->UEP2_RX_DMA = (UINT32)(UINT8 *)endp2Rxbuff;
USBSS->UEP_CFG = EP0_R_EN | EP0_T_EN | EP1_T_EN | EP2_R_EN | EP2_T_EN;// set end point rx/tx enable
USB30_OUT_Set(ENDP_2, ACK, 1);
}
else {
USB30_Switch_Powermode(POWER_MODE_2);
USBSS->LINK_CFG = PIPE_RESET | LFPS_RX_PD;
USBSS->LINK_CTRL = GO_DISABLED | POWER_MODE_3;
USBSS->LINK_INT_CTRL = 0;
USB30_Device_forceclr();
}
}
/*******************************************************************************
* @fn USB30_NonStandardReq
*
* @brief USB3.0 Nonstandard request processing function
*
* @return Length
*/
UINT16 USB30_NonStandardReq() {
UINT16 len = 0;
SetupReqCode = UsbSetupBuf->bRequest;
SetupLen = UsbSetupBuf->wLength;
switch (SetupReqCode) {
/* Open the serial port and send the baud rate */
case 0x20:
USB30_OUT_Set(ENDP_0, ACK, 1 );
break;
/* Read the current serial port configuration */
case 0x21:
*(UINT32 *)&endp0RTbuff[50] = vitrul_buad;
endp0RTbuff[54]=0x00;endp0RTbuff[55]=0x00;endp0RTbuff[56]=0x08;
SetupLen = 7;
break;
/* Close uart */
case 0x22:
CDC_Variable_Clear();
break;
default:
printf("stall\n");
SetupReqCode = INVALID_REQ_CODE;
return USB_DESCR_UNSUPPORTED;
break;
}
len = SetupLen >= ENDP0_MAXPACK ? ENDP0_MAXPACK : SetupLen;
memcpy(endp0RTbuff, &endp0RTbuff[50], len);
SetupLen -= len;
pDescr += len;
return len;
}
/*******************************************************************************
* @fn USB30_StandardReq
*
* @brief USB3.0 Standard request
*
* @return Length
*/
UINT16 USB30_StandardReq() {
UINT16 len = 0;
SetupReqCode = UsbSetupBuf->bRequest;
SetupLen = UsbSetupBuf->wLength;
if (( UsbSetupBuf->bRequestType & USB_REQ_TYP_MASK) != USB_REQ_TYP_STANDARD)
{
len= USB30_NonStandardReq();
}
else
{
switch (SetupReqCode) {
case USB_GET_DESCRIPTOR:
switch (UsbSetupBuf->wValueH) {
case USB_DESCR_TYP_DEVICE:
if (SetupLen > SIZE_DEVICE_DESC)
SetupLen = SIZE_DEVICE_DESC;
pDescr = (PUINT8) SS_DeviceDescriptor;
break;
case USB_DESCR_TYP_CONFIG:
if (SetupLen > SIZE_CONFIG_DESC)
SetupLen = SIZE_CONFIG_DESC;
pDescr = (PUINT8) SS_ConfigDescriptor;
break;
case USB_DESCR_TYP_BOS:
if (SetupLen > SIZE_BOS_DESC)
SetupLen = SIZE_BOS_DESC;
pDescr = (PUINT8) BOSDescriptor;
break;
case USB_DESCR_TYP_STRING:
switch (UsbSetupBuf->wValueL) {
case USB_DESCR_LANGID_STRING:
if (SetupLen > SIZE_STRING_LANGID)
SetupLen = SIZE_STRING_LANGID;
pDescr = (PUINT8) StringLangID;
break;
case USB_DESCR_VENDOR_STRING:
if (SetupLen > SIZE_STRING_VENDOR)
SetupLen = SIZE_STRING_VENDOR;
pDescr = (PUINT8) StringVendor;
break;
case USB_DESCR_PRODUCT_STRING:
if (SetupLen > SIZE_STRING_PRODUCT)
SetupLen = SIZE_STRING_PRODUCT;
pDescr = (PUINT8) StringProduct;
break;
case USB_DESCR_SERIAL_STRING:
if (SetupLen > SIZE_STRING_SERIAL)
SetupLen = SIZE_STRING_SERIAL;
pDescr = (PUINT8) StringSerial;
break;
case USB_DESCR_OS_STRING:
if (SetupLen > SIZE_STRING_OS)
SetupLen = SIZE_STRING_OS;
pDescr = (PUINT8) OSStringDescriptor;
break;
default:
len = USB_DESCR_UNSUPPORTED;
SetupReqCode = INVALID_REQ_CODE;
break;
}
break;
default:
len = USB_DESCR_UNSUPPORTED;
SetupReqCode = INVALID_REQ_CODE;
break;
}
len = SetupLen >= ENDP0_MAXPACK ? ENDP0_MAXPACK : SetupLen;
memcpy(endp0RTbuff, pDescr, len);
SetupLen -= len;
pDescr += len;
break;
case USB_SET_ADDRESS:
SetupLen = UsbSetupBuf->wValueL;
break;
case 0x31:
SetupLen = UsbSetupBuf->wValueL;
break;
case 0x30:
break;
case USB_SET_CONFIGURATION:
break;
case USB_GET_STATUS:
len = 2;
endp0RTbuff[0] = 0x01;
endp0RTbuff[1] = 0x00;
SetupLen = 0;
break;
case USB_CLEAR_FEATURE:
switch(UsbSetupBuf->wIndexL){
case 0x82:
USB30_IN_ClearIT( ENDP_2 );
USB30_IN_Set( ENDP_2 , ENABLE , ACK , 1 , 0);
USB30_Send_ERDY( ENDP_2 | IN , 1 );
break;
}
break;
case USB_SET_FEATURE:
break;
case USB_SET_INTERFACE:
break;
default:
len = USB_DESCR_UNSUPPORTED;
SetupReqCode = INVALID_REQ_CODE;
printf(" stall \n");
break;
}
}
return len;
}
/*******************************************************************************
* @fn EP0_IN_Callback
*
* @brief USB3.0 Endpoint 0 IN transaction callback
*
* @return Send length
*/
UINT16 EP0_IN_Callback(void) {
UINT16 len = 0;
switch (SetupReqCode) {
case USB_GET_DESCRIPTOR:
len = SetupLen >= ENDP0_MAXPACK ? ENDP0_MAXPACK : SetupLen;
memcpy(endp0RTbuff, pDescr, len);
SetupLen -= len;
pDescr += len;
break;
}
return len;
}
/*******************************************************************************
* @fn EP0_OUT_Callback
*
* @brief USB3.0 Endpoint 0 OUT transaction callback
*
* @return Length
*/
UINT16 EP0_OUT_Callback() {
UINT32 baudrate;
/* save bauds */
baudrate = endp0RTbuff[ 0 ];
baudrate += ((UINT32)endp0RTbuff[ 1 ] << 8 );
baudrate += ((UINT32)endp0RTbuff[ 2 ] << 16 );
baudrate += ((UINT32)endp0RTbuff[ 3 ] << 24 );
vitrul_buad = baudrate;
CDC_Uart_Init(baudrate);
return 0;
}
/*******************************************************************************
* @fn USB30_Setup_Status
*
* @brief USB3.0 Control transfer status stage callback
*
* @return None
*/
void USB30_Setup_Status(void) {
switch (SetupReqCode) {
case USB_SET_ADDRESS:
USB30_Device_Setaddress(SetupLen); // SET ADDRESS
break;
case 0x31:
break;
}
}
/*******************************************************************************
* @fn USBSS_IRQHandler
*
* @brief USB3.0 Interrupt Handler.
*
* @return None
*/
void USBSS_IRQHandler (void) //USBSS interrupt service
{
USB30_IRQHandler();
}
/*******************************************************************************
* @fn TMR0_IRQHandler
*
* @brief USB3.0 Connection failure timeout processing
*
* @return None
*/
void TMR0_IRQHandler( )
{
R8_TMR0_INTER_EN |= 1;
PFIC_DisableIRQ(TMR0_IRQn);
R8_TMR0_CTRL_MOD = RB_TMR_ALL_CLEAR;
if(Link_Sta == LINK_STA_1 )
{
Link_Sta =0;
PFIC_DisableIRQ(USBSS_IRQn);
PFIC_DisableIRQ(LINK_IRQn);
USB30D_init(DISABLE);
return;
}
if( Link_Sta != LINK_STA_3 )
{
PFIC_DisableIRQ(USBSS_IRQn);
PFIC_DisableIRQ(LINK_IRQn);
USB30D_init(DISABLE);
R32_USB_CONTROL = 0;
PFIC_EnableIRQ(USBHS_IRQn);
USB20_Device_Init(ENABLE);
}
Link_Sta = LINK_STA_1;
return;
}
/*******************************************************************************
* @fn LINK_IRQHandler
*
* @brief USB3.0 Link Interrupt Handler.
*
* @return None
*/
void LINK_IRQHandler() //USBSS link interrupt service
{
if(USBSS->LINK_INT_FLAG & LINK_Ux_EXIT_FLAG) // device enter U2
{
USBSS->LINK_CFG = CFG_EQ_EN | TX_SWING | DEEMPH_CFG | TERM_EN;
USB30_Switch_Powermode(POWER_MODE_0);
USBSS->LINK_INT_FLAG = LINK_Ux_EXIT_FLAG;
}
if(USBSS->LINK_INT_FLAG & LINK_RDY_FLAG) // POLLING SHAKE DONE
{
USBSS->LINK_INT_FLAG = LINK_RDY_FLAG;
if(Tx_Lmp_Port) // LMP, TX PORT_CAP & RX PORT_CAP
{
USBSS->LMP_TX_DATA0 = LINK_SPEED | PORT_CAP | LMP_HP;
USBSS->LMP_TX_DATA1 = UP_STREAM | NUM_HP_BUF;
USBSS->LMP_TX_DATA2 = 0x0;
Tx_Lmp_Port = 0;
}
/*Successful USB3.0 communication*/
Link_Sta = LINK_STA_3;
PFIC_DisableIRQ(TMR0_IRQn);
R8_TMR0_CTRL_MOD = RB_TMR_ALL_CLEAR;
R8_TMR0_INTER_EN = 0;
PFIC_DisableIRQ(USBHS_IRQn);
USB20_Device_Init(DISABLE);
}
if(USBSS->LINK_INT_FLAG & LINK_INACT_FLAG)
{
Link_Sta = 0;
PFIC_EnableIRQ(USBSS_IRQn);
PFIC_EnableIRQ(LINK_IRQn);
PFIC_EnableIRQ(TMR0_IRQn);
R8_TMR0_INTER_EN = RB_TMR_IE_CYC_END;
TMR0_TimerInit( 67000000 );
USB30D_init(ENABLE);
USBSS->LINK_INT_FLAG = LINK_INACT_FLAG;
USB30_Switch_Powermode(POWER_MODE_2);
}
if(USBSS->LINK_INT_FLAG & LINK_DISABLE_FLAG) // GO DISABLED
{
USBSS->LINK_INT_FLAG = LINK_DISABLE_FLAG;
Link_Sta = LINK_STA_1;
USB30D_init(DISABLE);
PFIC_DisableIRQ(USBSS_IRQn);
R8_TMR0_CTRL_MOD = RB_TMR_ALL_CLEAR;
R8_TMR0_INTER_EN = 0;
PFIC_DisableIRQ(TMR0_IRQn);
PFIC_EnableIRQ(USBHS_IRQn);
USB20_Device_Init(ENABLE);
}
if(USBSS->LINK_INT_FLAG & LINK_RX_DET_FLAG)
{
USBSS->LINK_INT_FLAG = LINK_RX_DET_FLAG;
USB30_Switch_Powermode(POWER_MODE_2);
}
if(USBSS->LINK_INT_FLAG & TERM_PRESENT_FLAG) // term present , begin POLLING
{
USBSS->LINK_INT_FLAG = TERM_PRESENT_FLAG;
if(USBSS->LINK_STATUS & LINK_PRESENT)
{
USB30_Switch_Powermode(POWER_MODE_2);
USBSS->LINK_CTRL |= POLLING_EN;
}
else
{
USBSS->LINK_INT_CTRL = 0;
}
}
if(USBSS->LINK_INT_FLAG & LINK_TXEQ_FLAG) // POLLING SHAKE DONE
{
Tx_Lmp_Port = 1;
USBSS->LINK_INT_FLAG = LINK_TXEQ_FLAG;
USB30_Switch_Powermode(POWER_MODE_0);
}
if(USBSS->LINK_INT_FLAG & WARM_RESET_FLAG)
{
USBSS->LINK_INT_FLAG = WARM_RESET_FLAG;
USB30_Switch_Powermode(POWER_MODE_2);
USBSS->LINK_CTRL |= TX_WARM_RESET;
while(USBSS->LINK_STATUS & RX_WARM_RESET);
USBSS->LINK_CTRL &= ~TX_WARM_RESET;
USB30_Device_Setaddress(0);
}
if(USBSS->LINK_INT_FLAG & HOT_RESET_FLAG) //The host may send hot reset,Note the configuration of the endpoint
{
USBSS->USB_CONTROL |= 1 << 31;
USBSS->LINK_INT_FLAG = HOT_RESET_FLAG; // HOT RESET begin
USBSS->UEP0_TX_CTRL = 0;
USB30_IN_Set(ENDP_1, DISABLE, NRDY, 0, 0);
USB30_IN_Set(ENDP_2, DISABLE, NRDY, 0, 0);
USB30_IN_Set(ENDP_3, DISABLE, NRDY, 0, 0);
USB30_IN_Set(ENDP_4, DISABLE, NRDY, 0, 0);
USB30_IN_Set(ENDP_5, DISABLE, NRDY, 0, 0);
USB30_IN_Set(ENDP_6, DISABLE, NRDY, 0, 0);
USB30_IN_Set(ENDP_7, DISABLE, NRDY, 0, 0);
USB30_OUT_Set(ENDP_1, NRDY, 0);
USB30_OUT_Set(ENDP_2, NRDY, 0);
USB30_OUT_Set(ENDP_3, NRDY, 0);
USB30_OUT_Set(ENDP_4, NRDY, 0);
USB30_OUT_Set(ENDP_5, NRDY, 0);
USB30_OUT_Set(ENDP_6, NRDY, 0);
USB30_OUT_Set(ENDP_7, NRDY, 0);
USB30_Device_Setaddress(0);
USBSS->LINK_CTRL &= ~TX_HOT_RESET; // HOT RESET end
}
if(USBSS->LINK_INT_FLAG & LINK_GO_U1_FLAG) // device enter U1
{
USB30_Switch_Powermode(POWER_MODE_1);
USBSS->LINK_INT_FLAG = LINK_GO_U1_FLAG;
}
if(USBSS->LINK_INT_FLAG & LINK_GO_U2_FLAG) // device enter U2
{
USB30_Switch_Powermode(POWER_MODE_2);
USBSS->LINK_INT_FLAG = LINK_GO_U2_FLAG;
}
if(USBSS->LINK_INT_FLAG & LINK_GO_U3_FLAG) // device enter U2
{
USB30_Switch_Powermode(POWER_MODE_2);
USBSS->LINK_INT_FLAG = LINK_GO_U3_FLAG;
}
}
/*******************************************************************************
* @fn EP2_OUT_Callback
*
* @brief USB3.0 endpoint2 out callback.
*
* @return None
*/
void EP2_OUT_Callback()
{
UINT16 rx_len;
UINT8 nump;
UINT8 status;
USB30_OUT_Status(ENDP_2,&nump,&rx_len,&status);
USBByteCount = rx_len;
USB30_OUT_ClearIT(ENDP_2);
USB30_OUT_Set( ENDP_2 , NRDY , 0 );
DownloadPoint2_Busy = 0;
}
/*******************************************************************************
* @fn EP2_IN_Callback
*
* @brief USB3.0 endpoint2 in callback.
*
* @return None
*/
void EP2_IN_Callback()
{
UINT8 nump;
USB30_IN_ClearIT( ENDP_2 );
USB30_IN_Set( ENDP_2 , ENABLE , NRDY , 0 , 0);
UploadPoint2_Busy = 0;
}
/***************Endpointn IN Transaction Processing*******************/
void EP1_IN_Callback()
{
}
void EP3_IN_Callback()
{
}
void EP4_IN_Callback()
{
}
void EP5_IN_Callback()
{
}
void EP6_IN_Callback()
{
}
void EP7_IN_Callback()
{
}
/***************Endpointn OUT Transaction Processing*******************/
void EP1_OUT_Callback()
{
}
void EP3_OUT_Callback()
{
}
void EP4_OUT_Callback()
{
}
void EP5_OUT_Callback()
{
}
void EP6_OUT_Callback()
{
}
void EP7_OUT_Callback()
{
}
/*******************************************************************************
* @fn USB30_ITP_Callback
*
* @brief USB3.0 ITP callback function
*
* @return None
*/
void USB30_ITP_Callback(UINT32 ITPCounter)
{
}

View File

@ -0,0 +1,58 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan
* PSL v2. You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY
* KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
* NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. See the
* Mulan PSL v2 for more details.
*/
/*
* @Note
* Example routine to emulate a simulate USB-CDC Device,Use UART2(PA2/PA3).
*/
#include "xizi.h"
#include "board.h"
#include "shell.h"
#include "CH56x_common.h"
#include "CH56x_usb30.h"
#include "cdc.h"
/*******************************************************************************
* @fn main
*
* @brief main program
*
* @return None
*/
int UsbdCdcTest()
{
KPrintf("UsbdCdcTest start\n");
KPrintf("CH56x USB3.0 & USB2.0 device test(80MHz) !\n");
/* USB initialization */
TMR2_TimerInit1();
R32_USB_CONTROL = 0;
PFIC_EnableIRQ(USBSS_IRQn);
PFIC_EnableIRQ(LINK_IRQn);
PFIC_EnableIRQ(TMR0_IRQn);
R8_TMR0_INTER_EN = 1;
TMR0_TimerInit( 67000000 );
USB30D_init(ENABLE);
KPrintf("UsbdCdcTest USB30D_init OK\n");
while(1)
{
CDC_Uart_Deal();
}
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN),
UsbdCdcTest, UsbdCdcTest, test usbd cdc);

View File

@ -0,0 +1,3 @@
SRC_FILES := connect_wdt.c
include $(KERNEL_ROOT)/compiler.mk

View File

@ -0,0 +1,71 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan
* PSL v2. You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY
* KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
* NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. See the
* Mulan PSL v2 for more details.
*/
/**
* @file connect_usart.c
* @brief support ch569 uart function and register to bus framework
* @version 1.0
* @author AIIT XUOS Lab
* @date 2025-04-07
*/
#include "CH56x_common.h"
#include "xizi.h"
#include "board.h"
#include "shell.h"
#define WDOG_MSECOND_MAX ( (0xff << 19) / (FREQ_SYS / 1000) ) // watchdog timer is clocked at Fsys/524288, arround 3~228Hz
int g_feed_wdt_stop = 0;
int InitHwWdt(void)
{
KPrintf("InitHwWdt WDOG_MSECOND_MAX is %d ms\n", WDOG_MSECOND_MAX);
WWDG_SetCounter(0);
WWDG_ClearFlag();
WWDG_ResetCfg(ENABLE);
while(1) {
WWDG_SetCounter(0);
//mDelaymS(100);
if (g_feed_wdt_stop == 1) {
KPrintf("%s watchdog feed stop!\n", __func__);
break;
}
}
return 0;
}
/**
* @description: Watchdog function
* @return success: EOK, failure: other
*/
int StartWatchdog(void)
{
int ret = EOK;
int32 WdtTask = KTaskCreate("WdtTask", (void *)InitHwWdt, NONE, 1024, 19);
StartupKTask(WdtTask);
return EOK;
}
int WdtTest(int argc, char *argv[])
{
KPrintf("WdtTest Start\n");
g_feed_wdt_stop = 1;
return 0;
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN),
WdtTest, WdtTest, test wdt);

View File

@ -3,7 +3,7 @@ OBJS := $(shell cat make.obj)
$(TARGET): $(OBJS)
@echo ------------------------------------------------
@echo link $(TARGET)
@$(CROSS_COMPILE)g++ -o $@ $($(LINK_FLAGS)) $(OBJS) $(LINK_LWIP) $(LINK_MUSLLIB) $(LINK_MONGOOSE) $(LINK_WCH_NET) $(LIBCC) $(LINK_WCH_BLE)
@$(CROSS_COMPILE)g++ -o $@ $($(LINK_FLAGS)) $(OBJS) $(LINK_LWIP) $(LINK_MUSLLIB) $(LINK_MONGOOSE) $(LINK_WCH_NET) $(LIBCC) $(LINK_WCH_BLE) $(LINK_BOARD)
@echo ------------------------------------------------
@$(CROSS_COMPILE)objcopy -O binary $@ XiZi-$(BOARD)$(COMPILE_TYPE).bin
@$(CROSS_COMPILE)objdump -S $@ > XiZi-$(BOARD)$(COMPILE_TYPE).asm