From e214c1bdee0d5c982b3f02ca86f75e7db35525d1 Mon Sep 17 00:00:00 2001 From: songyanguang <345810377@qq.com> Date: Fri, 8 Aug 2025 19:06:09 +0800 Subject: [PATCH 1/8] Modify TICK_PER_SECOND --- Ubiquitous/XiZi_IIoT/board/ch569w/.defconfig | 293 +++++++++++++++++++ Ubiquitous/XiZi_IIoT/board/ch569w/board.c | 3 +- 2 files changed, 294 insertions(+), 2 deletions(-) create mode 100644 Ubiquitous/XiZi_IIoT/board/ch569w/.defconfig diff --git a/Ubiquitous/XiZi_IIoT/board/ch569w/.defconfig b/Ubiquitous/XiZi_IIoT/board/ch569w/.defconfig new file mode 100644 index 000000000..2c4f13ba0 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/ch569w/.defconfig @@ -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 diff --git a/Ubiquitous/XiZi_IIoT/board/ch569w/board.c b/Ubiquitous/XiZi_IIoT/board/ch569w/board.c index 03c951fa6..b146dc3f2 100644 --- a/Ubiquitous/XiZi_IIoT/board/ch569w/board.c +++ b/Ubiquitous/XiZi_IIoT/board/ch569w/board.c @@ -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 */ From 7f899a34463a233ec574c7a53a3674bcf7ef5899 Mon Sep 17 00:00:00 2001 From: songyanguang <345810377@qq.com> Date: Fri, 8 Aug 2025 19:08:45 +0800 Subject: [PATCH 2/8] Add sys code from rt-thread --- .../board/ch569w/third_party_driver/Makefile | 2 + .../Peripheral/inc/CH56xSFR.h | 2 + .../third_party_driver/include/connect_soc.h | 98 +++++ .../third_party_driver/include/connect_sys.h | 396 ++++++++++++++++++ .../ch569w/third_party_driver/sys/Makefile | 3 + .../third_party_driver/sys/connect_sys.c | 280 +++++++++++++ 6 files changed, 781 insertions(+) create mode 100644 Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/include/connect_soc.h create mode 100644 Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/include/connect_sys.h create mode 100644 Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/sys/Makefile create mode 100644 Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/sys/connect_sys.c diff --git a/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/Makefile b/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/Makefile index 7b5f34c94..0bf187997 100644 --- a/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/Makefile +++ b/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/Makefile @@ -1,5 +1,7 @@ SRC_DIR := Peripheral +SRC_DIR += sys + ifeq ($(CONFIG_BSP_USING_UART),y) SRC_DIR += uart endif diff --git a/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/Peripheral/inc/CH56xSFR.h b/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/Peripheral/inc/CH56xSFR.h index 8555a966d..6bbaf7021 100644 --- a/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/Peripheral/inc/CH56xSFR.h +++ b/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/Peripheral/inc/CH56xSFR.h @@ -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 diff --git a/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/include/connect_soc.h b/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/include/connect_soc.h new file mode 100644 index 000000000..fde7751fb --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/include/connect_soc.h @@ -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 +#include +#include + +#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 diff --git a/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/include/connect_sys.h b/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/include/connect_sys.h new file mode 100644 index 000000000..450e162f8 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/include/connect_sys.h @@ -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 diff --git a/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/sys/Makefile b/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/sys/Makefile new file mode 100644 index 000000000..c56958110 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/sys/Makefile @@ -0,0 +1,3 @@ +SRC_FILES := connect_sys.c + +include $(KERNEL_ROOT)/compiler.mk diff --git a/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/sys/connect_sys.c b/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/sys/connect_sys.c new file mode 100644 index 000000000..c5d43e6db --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/sys/connect_sys.c @@ -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 +#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; +} From fe3733ac17e5a80bd3f0cdef0b4713284616937c Mon Sep 17 00:00:00 2001 From: songyanguang <345810377@qq.com> Date: Fri, 8 Aug 2025 21:04:41 +0800 Subject: [PATCH 3/8] Add spi flash --- Ubiquitous/XiZi_IIoT/board/ch569w/board.c | 5 + .../board/ch569w/third_party_driver/Kconfig | 7 + .../board/ch569w/third_party_driver/Makefile | 4 + .../ch569w/third_party_driver/spi/Kconfig | 3 + .../ch569w/third_party_driver/spi/Makefile | 5 + .../spi/connect_spi_flash.c | 450 ++++++++++++++++++ 6 files changed, 474 insertions(+) create mode 100644 Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/spi/Kconfig create mode 100644 Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/spi/Makefile create mode 100644 Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/spi/connect_spi_flash.c diff --git a/Ubiquitous/XiZi_IIoT/board/ch569w/board.c b/Ubiquitous/XiZi_IIoT/board/ch569w/board.c index b146dc3f2..293141fa1 100644 --- a/Ubiquitous/XiZi_IIoT/board/ch569w/board.c +++ b/Ubiquitous/XiZi_IIoT/board/ch569w/board.c @@ -44,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); diff --git a/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/Kconfig b/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/Kconfig index 6fdbc2813..927598866 100644 --- a/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/Kconfig +++ b/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/Kconfig @@ -5,3 +5,10 @@ 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 diff --git a/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/Makefile b/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/Makefile index 0bf187997..035498017 100644 --- a/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/Makefile +++ b/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/Makefile @@ -6,4 +6,8 @@ ifeq ($(CONFIG_BSP_USING_UART),y) SRC_DIR += uart endif +ifeq ($(CONFIG_BSP_USING_SPI),y) + SRC_DIR += spi +endif + include $(KERNEL_ROOT)/compiler.mk diff --git a/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/spi/Kconfig b/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/spi/Kconfig new file mode 100644 index 000000000..701b1335d --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/spi/Kconfig @@ -0,0 +1,3 @@ +menuconfig BSP_USING_SPI0_FLASH + bool "Enable SPI0 FLASH" + default y diff --git a/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/spi/Makefile b/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/spi/Makefile new file mode 100644 index 000000000..73c862fab --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/spi/Makefile @@ -0,0 +1,5 @@ +ifeq ($(CONFIG_BSP_USING_SPI0_FLASH),y) + SRC_FILES += connect_spi_flash.c +endif + +include $(KERNEL_ROOT)/compiler.mk diff --git a/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/spi/connect_spi_flash.c b/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/spi/connect_spi_flash.c new file mode 100644 index 000000000..3aea6b50a --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/spi/connect_spi_flash.c @@ -0,0 +1,450 @@ +/* + * 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 +#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 */ + KPrintf("START SPI FLASH\n"); + return 0; +} + +int SpiFlashTest(int argc, char *argv[]) +{ + UINT8 buf[1024]; + UINT8 i; + + 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; + } + + 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), + test_spi, SpiFlashTest, test spi); From 18264a638c0a868899613d9e6f344f8cd9350505 Mon Sep 17 00:00:00 2001 From: songyanguang <345810377@qq.com> Date: Mon, 11 Aug 2025 11:01:50 +0800 Subject: [PATCH 4/8] Modify spi flash test --- .../spi/connect_spi_flash.c | 22 +++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/spi/connect_spi_flash.c b/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/spi/connect_spi_flash.c index 3aea6b50a..7378911a2 100644 --- a/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/spi/connect_spi_flash.c +++ b/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/spi/connect_spi_flash.c @@ -423,8 +423,9 @@ int InitHwSpi(void) { int SpiFlashTest(int argc, char *argv[]) { - UINT8 buf[1024]; - UINT8 i; + UINT8 buf[1024]; + UINT8 i; + int read_only = 0; KPrintf("SpiFlashTest Start\n"); @@ -434,8 +435,21 @@ int SpiFlashTest(int argc, char *argv[]) buf[i] = i; } - EraseExternal4KFlash_SPI(0); - BlukWriteExternalFlash_SPI(0,255,buf); + 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++){ From d512b49a6a744c00aa8db816ef0e46de5ddec514 Mon Sep 17 00:00:00 2001 From: songyanguang <345810377@qq.com> Date: Mon, 11 Aug 2025 18:02:00 +0800 Subject: [PATCH 5/8] Add watchdog --- .../board/ch569w/third_party_driver/Kconfig | 4 ++ .../board/ch569w/third_party_driver/Makefile | 4 ++ .../spi/connect_spi_flash.c | 2 +- .../ch569w/third_party_driver/wdt/Makefile | 3 + .../third_party_driver/wdt/connect_wdt.c | 71 +++++++++++++++++++ 5 files changed, 83 insertions(+), 1 deletion(-) create mode 100644 Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/wdt/Makefile create mode 100644 Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/wdt/connect_wdt.c diff --git a/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/Kconfig b/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/Kconfig index 927598866..ccc8dac9c 100644 --- a/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/Kconfig +++ b/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/Kconfig @@ -12,3 +12,7 @@ menuconfig BSP_USING_SPI if BSP_USING_SPI source "$BSP_DIR/third_party_driver/spi/Kconfig" endif + +menuconfig BSP_USING_WDT + bool "Using watchdog timer device" + default y diff --git a/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/Makefile b/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/Makefile index 035498017..b4644627d 100644 --- a/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/Makefile +++ b/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/Makefile @@ -10,4 +10,8 @@ ifeq ($(CONFIG_BSP_USING_SPI),y) SRC_DIR += spi endif +ifeq ($(CONFIG_BSP_USING_WDT),y) + SRC_DIR += wdt +endif + include $(KERNEL_ROOT)/compiler.mk diff --git a/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/spi/connect_spi_flash.c b/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/spi/connect_spi_flash.c index 7378911a2..e2babe5e1 100644 --- a/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/spi/connect_spi_flash.c +++ b/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/spi/connect_spi_flash.c @@ -461,4 +461,4 @@ int SpiFlashTest(int argc, char *argv[]) } SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN), - test_spi, SpiFlashTest, test spi); + SpiFlashTest, SpiFlashTest, test spi); diff --git a/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/wdt/Makefile b/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/wdt/Makefile new file mode 100644 index 000000000..9be59f003 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/wdt/Makefile @@ -0,0 +1,3 @@ +SRC_FILES := connect_wdt.c + +include $(KERNEL_ROOT)/compiler.mk diff --git a/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/wdt/connect_wdt.c b/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/wdt/connect_wdt.c new file mode 100644 index 000000000..29d1056c5 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/wdt/connect_wdt.c @@ -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); From b175f77b1045232dacd9c0dd7ccd0db2c1a81644 Mon Sep 17 00:00:00 2001 From: songyanguang <345810377@qq.com> Date: Wed, 13 Aug 2025 15:21:27 +0800 Subject: [PATCH 6/8] Add SerDes --- Ubiquitous/XiZi_IIoT/board/ch569w/config.mk | 5 +- .../board/ch569w/third_party_driver/Kconfig | 9 +- .../board/ch569w/third_party_driver/Makefile | 4 + .../include/connect_serdes.h | 196 ++++++++++++++++++ .../ch569w/third_party_driver/serdes/Kconfig | 7 + .../ch569w/third_party_driver/serdes/Makefile | 3 + .../serdes/connect_serdes.c | 154 ++++++++++++++ .../third_party_driver/serdes/libSERDES.a | Bin 0 -> 64430 bytes Ubiquitous/XiZi_IIoT/link.mk | 2 +- 9 files changed, 376 insertions(+), 4 deletions(-) create mode 100644 Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/include/connect_serdes.h create mode 100644 Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/serdes/Kconfig create mode 100644 Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/serdes/Makefile create mode 100644 Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/serdes/connect_serdes.c create mode 100644 Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/serdes/libSERDES.a diff --git a/Ubiquitous/XiZi_IIoT/board/ch569w/config.mk b/Ubiquitous/XiZi_IIoT/board/ch569w/config.mk index 6db9c93c7..d87b3d1d1 100644 --- a/Ubiquitous/XiZi_IIoT/board/ch569w/config.mk +++ b/Ubiquitous/XiZi_IIoT/board/ch569w/config.mk @@ -14,5 +14,6 @@ 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 diff --git a/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/Kconfig b/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/Kconfig index ccc8dac9c..0b8a591b2 100644 --- a/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/Kconfig +++ b/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/Kconfig @@ -13,6 +13,13 @@ menuconfig 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_WDT bool "Using watchdog timer device" - default y + default n diff --git a/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/Makefile b/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/Makefile index b4644627d..6cc73d828 100644 --- a/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/Makefile +++ b/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/Makefile @@ -10,6 +10,10 @@ ifeq ($(CONFIG_BSP_USING_SPI),y) SRC_DIR += spi endif +ifeq ($(CONFIG_BSP_USING_SPI),y) + SRC_DIR += serdes +endif + ifeq ($(CONFIG_BSP_USING_WDT),y) SRC_DIR += wdt endif diff --git a/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/include/connect_serdes.h b/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/include/connect_serdes.h new file mode 100644 index 000000000..4d125cc3b --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/include/connect_serdes.h @@ -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 diff --git a/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/serdes/Kconfig b/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/serdes/Kconfig new file mode 100644 index 000000000..47ea6f04b --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/serdes/Kconfig @@ -0,0 +1,7 @@ +config SERDES_TRANS + bool "Config serdes transmit mode." + default y + +config SERIAL_RECEI + bool "Config serdes receive mode." + default y \ No newline at end of file diff --git a/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/serdes/Makefile b/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/serdes/Makefile new file mode 100644 index 000000000..2b985267c --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/serdes/Makefile @@ -0,0 +1,3 @@ +SRC_FILES := connect_serdes.c + +include $(KERNEL_ROOT)/compiler.mk diff --git a/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/serdes/connect_serdes.c b/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/serdes/connect_serdes.c new file mode 100644 index 000000000..06d6b68e1 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/serdes/connect_serdes.c @@ -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); diff --git a/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/serdes/libSERDES.a b/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/serdes/libSERDES.a new file mode 100644 index 0000000000000000000000000000000000000000..1d9b91a31e77ba69da119161961f9b69f4be027e GIT binary patch literal 64430 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 Bs-XY? literal 0 HcmV?d00001 diff --git a/Ubiquitous/XiZi_IIoT/link.mk b/Ubiquitous/XiZi_IIoT/link.mk index fa76da46c..00e8eb95b 100644 --- a/Ubiquitous/XiZi_IIoT/link.mk +++ b/Ubiquitous/XiZi_IIoT/link.mk @@ -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 From 0da14e6546ee5ad8a4acdd9e383e20b9ab4627f3 Mon Sep 17 00:00:00 2001 From: songyanguang <345810377@qq.com> Date: Wed, 13 Aug 2025 20:00:06 +0800 Subject: [PATCH 7/8] Add usbd cdc --- Ubiquitous/XiZi_IIoT/board/ch569w/config.mk | 4 + .../board/ch569w/third_party_driver/Kconfig | 7 + .../board/ch569w/third_party_driver/Makefile | 6 +- .../third_party_driver/include/CH56x_usb20.h | 56 ++ .../third_party_driver/include/CH56x_usb30.h | 61 ++ .../include/CH56x_usb30_LIB.h | 482 ++++++++++ .../ch569w/third_party_driver/include/cdc.h | 27 + .../third_party_driver/include/connect_usb.h | 37 + .../ch569w/third_party_driver/usb/Kconfig | 6 + .../ch569w/third_party_driver/usb/Makefile | 5 + .../third_party_driver/usb/usbd/Kconfig | 3 + .../third_party_driver/usb/usbd/Makefile | 5 + .../usb/usbd/simulate_cdc/CDC/cdc.c | 337 +++++++ .../usb/usbd/simulate_cdc/Makefile | 3 + .../usb/usbd/simulate_cdc/USB20/CH56x_usb20.c | 756 ++++++++++++++++ .../usb/usbd/simulate_cdc/USB30/CH56x_usb30.c | 832 ++++++++++++++++++ .../USB30/libCH56x_USB30_device_lib.a | Bin 0 -> 44868 bytes .../usb/usbd/simulate_cdc/connect_cdc.c | 58 ++ 18 files changed, 2684 insertions(+), 1 deletion(-) create mode 100644 Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/include/CH56x_usb20.h create mode 100644 Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/include/CH56x_usb30.h create mode 100644 Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/include/CH56x_usb30_LIB.h create mode 100644 Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/include/cdc.h create mode 100644 Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/include/connect_usb.h create mode 100644 Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/usb/Kconfig create mode 100644 Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/usb/Makefile create mode 100644 Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/usb/usbd/Kconfig create mode 100644 Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/usb/usbd/Makefile create mode 100644 Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/usb/usbd/simulate_cdc/CDC/cdc.c create mode 100644 Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/usb/usbd/simulate_cdc/Makefile create mode 100644 Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/usb/usbd/simulate_cdc/USB20/CH56x_usb20.c create mode 100644 Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/usb/usbd/simulate_cdc/USB30/CH56x_usb30.c create mode 100644 Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/usb/usbd/simulate_cdc/USB30/libCH56x_USB30_device_lib.a create mode 100644 Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/usb/usbd/simulate_cdc/connect_cdc.c diff --git a/Ubiquitous/XiZi_IIoT/board/ch569w/config.mk b/Ubiquitous/XiZi_IIoT/board/ch569w/config.mk index d87b3d1d1..6a4afcfce 100644 --- a/Ubiquitous/XiZi_IIoT/board/ch569w/config.mk +++ b/Ubiquitous/XiZi_IIoT/board/ch569w/config.mk @@ -17,3 +17,7 @@ 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 diff --git a/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/Kconfig b/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/Kconfig index 0b8a591b2..1177c855b 100644 --- a/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/Kconfig +++ b/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/Kconfig @@ -20,6 +20,13 @@ menuconfig 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 diff --git a/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/Makefile b/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/Makefile index 6cc73d828..0d445e3a7 100644 --- a/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/Makefile +++ b/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/Makefile @@ -10,10 +10,14 @@ ifeq ($(CONFIG_BSP_USING_SPI),y) SRC_DIR += spi endif -ifeq ($(CONFIG_BSP_USING_SPI),y) +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 diff --git a/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/include/CH56x_usb20.h b/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/include/CH56x_usb20.h new file mode 100644 index 000000000..c9eebe5f7 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/include/CH56x_usb20.h @@ -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 + diff --git a/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/include/CH56x_usb30.h b/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/include/CH56x_usb30.h new file mode 100644 index 000000000..8ef6d0217 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/include/CH56x_usb30.h @@ -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_ */ + + diff --git a/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/include/CH56x_usb30_LIB.h b/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/include/CH56x_usb30_LIB.h new file mode 100644 index 000000000..95c04564b --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/include/CH56x_usb30_LIB.h @@ -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_ */ + diff --git a/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/include/cdc.h b/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/include/cdc.h new file mode 100644 index 000000000..107d17f02 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/include/cdc.h @@ -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_ */ diff --git a/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/include/connect_usb.h b/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/include/connect_usb.h new file mode 100644 index 000000000..66e5c5f19 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/include/connect_usb.h @@ -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 diff --git a/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/usb/Kconfig b/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/usb/Kconfig new file mode 100644 index 000000000..5f473df64 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/usb/Kconfig @@ -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 diff --git a/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/usb/Makefile b/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/usb/Makefile new file mode 100644 index 000000000..3358dc1a0 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/usb/Makefile @@ -0,0 +1,5 @@ +ifeq ($(CONFIG_BSP_USING_USBD),y) + SRC_DIR += usbd +endif + +include $(KERNEL_ROOT)/compiler.mk diff --git a/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/usb/usbd/Kconfig b/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/usb/usbd/Kconfig new file mode 100644 index 000000000..31c0c6fd6 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/usb/usbd/Kconfig @@ -0,0 +1,3 @@ +menuconfig BSP_USING_USBD_CDC + bool "Using usbd cdc device" + default y diff --git a/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/usb/usbd/Makefile b/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/usb/usbd/Makefile new file mode 100644 index 000000000..3ca5a9b37 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/usb/usbd/Makefile @@ -0,0 +1,5 @@ +ifeq ($(CONFIG_BSP_USING_USBD_CDC),y) + SRC_DIR += simulate_cdc +endif + +include $(KERNEL_ROOT)/compiler.mk diff --git a/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/usb/usbd/simulate_cdc/CDC/cdc.c b/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/usb/usbd/simulate_cdc/CDC/cdc.c new file mode 100644 index 000000000..5b0ce329c --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/usb/usbd/simulate_cdc/CDC/cdc.c @@ -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; + } +} diff --git a/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/usb/usbd/simulate_cdc/Makefile b/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/usb/usbd/simulate_cdc/Makefile new file mode 100644 index 000000000..aba78b0ef --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/usb/usbd/simulate_cdc/Makefile @@ -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 diff --git a/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/usb/usbd/simulate_cdc/USB20/CH56x_usb20.c b/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/usb/usbd/simulate_cdc/USB20/CH56x_usb20.c new file mode 100644 index 000000000..5d8204ec4 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/usb/usbd/simulate_cdc/USB20/CH56x_usb20.c @@ -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; +} + + diff --git a/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/usb/usbd/simulate_cdc/USB30/CH56x_usb30.c b/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/usb/usbd/simulate_cdc/USB30/CH56x_usb30.c new file mode 100644 index 000000000..0fc14fb61 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/usb/usbd/simulate_cdc/USB30/CH56x_usb30.c @@ -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) +{ + +} diff --git a/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/usb/usbd/simulate_cdc/USB30/libCH56x_USB30_device_lib.a b/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/usb/usbd/simulate_cdc/USB30/libCH56x_USB30_device_lib.a new file mode 100644 index 0000000000000000000000000000000000000000..eaf065736457199e6d770310212775f0992082c4 GIT binary patch literal 44868 zcmeHw34Bylp6;n6l?sRu5(LC(7Zh7F37w4u9NVdogd(gl35$w`P$>d-SSEz6pV)yA z5EP=u1r;4!o-nrKvlXq3qfG=!P!SheL9tt0Fx@`8M;$_9KbQA?XQ?_V5=Eb{b>5qk z->Lh3|MNe~J@?$RpPRuKl~wr{T-@_#?#?DHD?4j!_P8-=16-9-5FV_W0jA& zJ%tcY3(Z|SvMYWk1nn=6 zEBmV&AtLSii9-A>>@9PJ_&U3Nq!8c5-g~nUe>*#)czi}`X>jv?NlD9EL&}~OA1T# z7njYe3`pgv)ARC6i%W7!W)y3M=`%`7i>u43moKvg0h0te=T-*FstQUhcPS}E%nKJ+ zbaE&tnO|8}Vd9=vs#6peAmw4wWiSQPA|iw!GT3R$7cJGnAV8S~rON{UxOn-Zc>$B1 z#YkRheo@|~T2W^@^vlZ2s{+f+{T8oWSnXd>TDW9oplZ>Q@_<&a2voyIj#gb(4KM#_ zQeJe)#InWZm56F-{?dZQ)uqTK0}G~!(o%RXoiJfaj;|PGnN6fi(NrUrNXl}Hi;Pe~ zN~h{ar2+{v=~hsjqkT+OP)YMcLLw`A!@sZ z{1zzZknfrK)AFVl737)Fa*A>%hFQVX!Z4YbQ&a*ren#=wQeR=g^iug!N-9zD>Sfh| zMH2b~)nK`mOZ>kOc{2-33#OIi&aaSgDoYb(6y)dTeSqV>8UcH+yw#uFLI~mC>J414+yt7PZS3#1O94Ca?7g9MNy!vTxzNs zLwg#(eA%pp<<$#JAQKl>EGS+Y2$V}f!Ss@;uXJ=&n7%kr9PoD%OwSC zd?%KJTBoyXXI{8)aZzAV*;46ss(*=?SX@{jLr_Q;gu+=GOW-O&_%953`W-65rFT^I6RaS@HiYo(wr2^5XmQF2W zNy!V$SLKwVyt3*tSrjb=R*vIWqnKH;qJV!zq)a}!NF|%2B%Y=N8N*U)#g%0%0^!6+ z+BqgE>YSjEmK8=QnzYkzGOg218U;H{BeSD6veQB~sW%GtOovLQt|?5z*U{INaE$iLV-oaqWIEcb_xm>&tHOeTT=OU=dTLLieuKSJRgcK z3y*}-F~nq(JArL<$<(6M(vpRX0#)+qfTne(>78k6Y5wez;)NB9%PM7sWBcpQCB0ie zsik-o!Vy~}-F8VW%`HO#=p}M^85&b!)UpCT@6v9OZ3~eufTV7U-qmiBGENq_sx@U-2C(ho`+qr zo`+x`aK(A{E zx8*wW6DvlDZTqrY;vqlMvaO{D;$2s>X22!w&ir*XiO%?_bu|qG>KyNEY*?{eWV?j$ zzwHu1mvB6G+Yxd5bJ-h&H}kUB>MwfJBX){)HP2L>2nHd0>It(kRDBIQX)tUjH)hE5`sfpD-8#ZoqB{(m> zB`GKIh|A%LKPA>&_erg%=7hNGI^~z)hqcDXe(0RK^@^?W�KgF4?Z*(FprA`36^A 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 L@^a6v$1DFEsWG_~ literal 0 HcmV?d00001 diff --git a/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/usb/usbd/simulate_cdc/connect_cdc.c b/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/usb/usbd/simulate_cdc/connect_cdc.c new file mode 100644 index 000000000..c624dd333 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/usb/usbd/simulate_cdc/connect_cdc.c @@ -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); From caa3fc3bb5d8e8ada7a7ecc99f3a182e85ffbb99 Mon Sep 17 00:00:00 2001 From: songyanguang <345810377@qq.com> Date: Thu, 14 Aug 2025 10:22:00 +0800 Subject: [PATCH 8/8] Add driver README.md --- Ubiquitous/XiZi_IIoT/board/ch569w/README.md | 151 +++++++++--------- .../ch569w/imgs/image_xitongqidongrizhi.png | Bin 21104 -> 21067 bytes .../board/ch569w/third_party_driver/README.md | 61 +++++++ .../third_party_driver/imgs/SerdesTestRx.png | Bin 0 -> 14683 bytes .../third_party_driver/imgs/SerdesTxTest.png | Bin 0 -> 5929 bytes .../third_party_driver/imgs/SpiFlashTest.png | Bin 0 -> 8366 bytes .../imgs/UsbdCdcTestCmd.png | Bin 0 -> 2727 bytes .../imgs/UsbdCdcTestUSB20.png | Bin 0 -> 33853 bytes .../third_party_driver/imgs/WdtTest.png | Bin 0 -> 6050 bytes .../imgs/make-menuconfig.png | Bin 0 -> 18553 bytes .../spi/connect_spi_flash.c | 1 - 11 files changed, 135 insertions(+), 78 deletions(-) create mode 100644 Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/README.md create mode 100644 Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/imgs/SerdesTestRx.png create mode 100644 Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/imgs/SerdesTxTest.png create mode 100644 Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/imgs/SpiFlashTest.png create mode 100644 Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/imgs/UsbdCdcTestCmd.png create mode 100644 Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/imgs/UsbdCdcTestUSB20.png create mode 100644 Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/imgs/WdtTest.png create mode 100644 Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/imgs/make-menuconfig.png diff --git a/Ubiquitous/XiZi_IIoT/board/ch569w/README.md b/Ubiquitous/XiZi_IIoT/board/ch569w/README.md index 89e770521..1ab572cf3 100644 --- a/Ubiquitous/XiZi_IIoT/board/ch569w/README.md +++ b/Ubiquitous/XiZi_IIoT/board/ch569w/README.md @@ -1,78 +1,75 @@ -# 1. 简介 - -| 硬件 | 描述 | -| --------- | ----------------------------------------- | -| 芯片型号 | CH569W | -| CPU | 单核RISC-V3A | -| 主频 | 120MHz | -| 片内SRAM | 32/64/96KB 可配置的 128 位宽 SRAM(RAMX) | -| 片内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-gcc(xpack-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 芯片。最后点击“下载”,即可使程序下载到评估版上的主芯片。 - -image_shaolukaifabanpaizhao - -image_shaoluruanjianjietu - - - -# 6. 启动 - -烧录完成后,并且将串口连接至电脑。 - -将评估板上电重新,即可看到操作系统启动的信息,如下: - +# 1. 简介 + +| 硬件 | 描述 | +| --------- | ------------------------------------------------- | +| 芯片型号 | CH569W | +| CPU | 单核RISC-V3A | +| 主频 | 120MHz | +| 片内SRAM | 32/64/96KB 可配置的 128 位宽 SRAM(RAMX) | +| 片内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-gcc(xpack-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 芯片。最后点击“下载”,即可使程序下载到评估版上的主芯片。 + +image_shaolukaifabanpaizhao + +image_shaoluruanjianjietu + + + +# 6. 启动 + +烧录完成后,并且将串口连接至电脑。 + +将评估板上电重新,即可看到操作系统启动的信息,如下: + ![image_xitongqidongrizhi](imgs/image_xitongqidongrizhi.png) \ No newline at end of file diff --git a/Ubiquitous/XiZi_IIoT/board/ch569w/imgs/image_xitongqidongrizhi.png b/Ubiquitous/XiZi_IIoT/board/ch569w/imgs/image_xitongqidongrizhi.png index 2813913a89094c5f253852c407d9e164e1cae03f..9b0265fd363bb275da1914475790c6f415b8ba98 100644 GIT binary patch literal 21067 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 literal 21104 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 diff --git a/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/README.md b/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/README.md new file mode 100644 index 000000000..09e8feab0 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/README.md @@ -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 CDC(USB 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) + diff --git a/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/imgs/SerdesTestRx.png b/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/imgs/SerdesTestRx.png new file mode 100644 index 0000000000000000000000000000000000000000..f93f603661dc2ba3ae071025587119aafe9e6b33 GIT binary patch literal 14683 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 U{0Y5)KL literal 0 HcmV?d00001 diff --git a/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/imgs/SerdesTxTest.png b/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/imgs/SerdesTxTest.png new file mode 100644 index 0000000000000000000000000000000000000000..704915edc57b2d95cee48dba469d85f0afdf9a98 GIT binary patch literal 5929 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 literal 0 HcmV?d00001 diff --git a/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/imgs/UsbdCdcTestUSB20.png b/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/imgs/UsbdCdcTestUSB20.png new file mode 100644 index 0000000000000000000000000000000000000000..48ab50459f67c0223e5b7f8d482f156781dd7be9 GIT binary patch literal 33853 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 R!QGRPSF$QHrBZJK{y&)BXF>n~ literal 0 HcmV?d00001 diff --git a/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/imgs/WdtTest.png b/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/imgs/WdtTest.png new file mode 100644 index 0000000000000000000000000000000000000000..fbae2c308ef7c306adb4cc33b05ceb30d21cc96d GIT binary patch literal 6050 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 literal 0 HcmV?d00001 diff --git a/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/spi/connect_spi_flash.c b/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/spi/connect_spi_flash.c index e2babe5e1..193dc112a 100644 --- a/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/spi/connect_spi_flash.c +++ b/Ubiquitous/XiZi_IIoT/board/ch569w/third_party_driver/spi/connect_spi_flash.c @@ -417,7 +417,6 @@ UINT16 SPIFlash_ReadID(void) */ int InitHwSpi(void) { SPI_MASTER_INIT ( ); /* SPI0 master mode initialization */ - KPrintf("START SPI FLASH\n"); return 0; }