diff --git a/Ubiquitous/XiZi_IIoT/board/ch32v307vct6/board.c b/Ubiquitous/XiZi_IIoT/board/ch32v307vct6/board.c index addee633a..5a50a1571 100644 --- a/Ubiquitous/XiZi_IIoT/board/ch32v307vct6/board.c +++ b/Ubiquitous/XiZi_IIoT/board/ch32v307vct6/board.c @@ -30,6 +30,7 @@ #include "ch32v30x.h" #include "connect_ether.h" #include "connect_uart.h" +#include "connect_can.h" #include "core_riscv.h" #include "xsconfig.h" #include @@ -75,27 +76,32 @@ void InitBoardHardware() #ifdef BSP_USING_ETH InitHwEth(); #endif + +#ifdef BSP_USING_CAN + InitHwCan(); +#endif + KPrintf("consle init completed.\n"); KPrintf("board initialization......\n"); KPrintf("board init done.\n"); KPrintf("start okernel...\n"); - uint16_t ans = 0; - uint16_t recv_data = 0; - uint16_t send_data = 0; - int cnt = 0; - while (1) { + // uint16_t ans = 0; + // uint16_t recv_data = 0; + // uint16_t send_data = 0; + // int cnt = 0; + // while (1) { - recv_data = UART_ReceiveData(USART3); + // recv_data = UART_ReceiveData(USART3); - if (recv_data < 58 && recv_data > 47) { - ans = recv_data; + // if (recv_data < 58 && recv_data > 47) { + // ans = recv_data; - KPrintf("recv data: %d\n", ans - 48); - } - send_data = ans + 17; - KPrintf("send data: %d\n", send_data); - UART_SendData(USART3, send_data); - } + // KPrintf("recv data: %d\n", ans - 48); + // } + // send_data = ans + 17; + // KPrintf("send data: %d\n", send_data); + // UART_SendData(USART3, send_data); + // } } diff --git a/Ubiquitous/XiZi_IIoT/board/ch32v307vct6/config.mk b/Ubiquitous/XiZi_IIoT/board/ch32v307vct6/config.mk index 630327afc..2f25dce5b 100755 --- a/Ubiquitous/XiZi_IIoT/board/ch32v307vct6/config.mk +++ b/Ubiquitous/XiZi_IIoT/board/ch32v307vct6/config.mk @@ -11,7 +11,7 @@ export APPLFLAGS := -nostartfiles -Wl,--gc-sections,-Map=XiZi-app.map,-cref,-u, export CXXFLAGS := -fmessage-length=0 -fsigned-char -ffunction-sections -fdata-sections -fno-common # -std=gnu99 -export CROSS_COMPILE ?=/opt/riscv-embedded-gcc/bin/riscv-none-embed- +export CROSS_COMPILE ?=/home/user1623/riscv64-unknown-elf-toolchain/bin/riscv64-unknown-elf- export DEFINES := -DHAVE_CCONFIG_H -DHAVE_SIGINFO diff --git a/Ubiquitous/XiZi_IIoT/board/ch32v307vct6/third_party_driver/Kconfig b/Ubiquitous/XiZi_IIoT/board/ch32v307vct6/third_party_driver/Kconfig index 64a20aaa9..2d37f65b0 100755 --- a/Ubiquitous/XiZi_IIoT/board/ch32v307vct6/third_party_driver/Kconfig +++ b/Ubiquitous/XiZi_IIoT/board/ch32v307vct6/third_party_driver/Kconfig @@ -19,4 +19,23 @@ menuconfig BSP_USING_ETH bool "Using Ethernet" default y - \ No newline at end of file +menuconfig BSP_USING_CAN + bool "Using CAN device" + default y + select RESOURCES_CAN + if BSP_USING_CAN + source "$BSP_DIR/third_party_driver/can/Kconfig" + endif + + +menuconfig BSP_USING_USB + bool "Using USB device" + default y + select BSP_USING_USBH + select RESOURCES_USB + select RESOURCES_USB_HOST + select USBH_MSTORAGE + select RESOURCES_USB_DEVICE + if BSP_USING_USB + source "$BSP_DIR/third_party_driver/usb/Kconfig" + endif diff --git a/Ubiquitous/XiZi_IIoT/board/ch32v307vct6/third_party_driver/Makefile b/Ubiquitous/XiZi_IIoT/board/ch32v307vct6/third_party_driver/Makefile index 7167d1e93..df748c38d 100644 --- a/Ubiquitous/XiZi_IIoT/board/ch32v307vct6/third_party_driver/Makefile +++ b/Ubiquitous/XiZi_IIoT/board/ch32v307vct6/third_party_driver/Makefile @@ -13,4 +13,12 @@ ifeq ($(CONFIG_BSP_USING_ETH),y) SRC_DIR += ethernet endif +ifeq ($(CONFIG_BSP_USING_CAN),y) + SRC_DIR += can +endif + +ifeq ($(CONFIG_BSP_USING_USB),y) + SRC_DIR += usb +endif + include $(KERNEL_ROOT)/compiler.mk \ No newline at end of file diff --git a/Ubiquitous/XiZi_IIoT/board/ch32v307vct6/third_party_driver/can/Kconfig b/Ubiquitous/XiZi_IIoT/board/ch32v307vct6/third_party_driver/can/Kconfig new file mode 100755 index 000000000..34fb7d247 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/ch32v307vct6/third_party_driver/can/Kconfig @@ -0,0 +1,11 @@ +config CAN_BUS_NAME_1 + string "can bus name" + default "can1" + +config CAN_DRIVER_NAME + string "can driver name" + default "can1_drv" + +config CAN_1_DEVICE_NAME_1 + string "can bus 1 device 1 name" + default "can1_dev1" \ No newline at end of file diff --git a/Ubiquitous/XiZi_IIoT/board/ch32v307vct6/third_party_driver/can/Makefile b/Ubiquitous/XiZi_IIoT/board/ch32v307vct6/third_party_driver/can/Makefile new file mode 100755 index 000000000..f3fd6ea31 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/ch32v307vct6/third_party_driver/can/Makefile @@ -0,0 +1,4 @@ +SRC_FILES := connect_can.c +SRC_DIR := test + +include $(KERNEL_ROOT)/compiler.mk \ No newline at end of file diff --git a/Ubiquitous/XiZi_IIoT/board/ch32v307vct6/third_party_driver/can/connect_can.c b/Ubiquitous/XiZi_IIoT/board/ch32v307vct6/third_party_driver/can/connect_can.c new file mode 100644 index 000000000..403eb42df --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/ch32v307vct6/third_party_driver/can/connect_can.c @@ -0,0 +1,249 @@ + +#include +#include +#include +#include + +static struct CanSendConfigure can_send_deconfig = +{ + .stdid = 0x12, + .exdid = 0x12, + .ide = 0 , + .rtr = 0, + .data_lenth = 8 +}; + +static void CanGPIOInit(void) +{ + CAN_FilterInitTypeDef can1_filter; + GPIO_InitTypeDef gpio_initstructure; + CAN_InitTypeDef can_initstruction; + + RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO |RCC_APB2Periph_GPIOB, ENABLE); + RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE); + + GPIO_PinRemapConfig(GPIO_Remap1_CAN1, ENABLE); + + gpio_initstructure.GPIO_Pin = GPIO_Pin_9; + gpio_initstructure.GPIO_Mode = GPIO_Mode_AF_PP; + gpio_initstructure.GPIO_Speed = GPIO_Speed_50MHz; + GPIO_Init( GPIOB, &gpio_initstructure); + + gpio_initstructure.GPIO_Pin = GPIO_Pin_8; + gpio_initstructure.GPIO_Mode = GPIO_Mode_IPU; + GPIO_Init( GPIOB, &gpio_initstructure); +} + +static void Can1NvicConfig(void) +{ + NVIC_InitTypeDef can_nvic_config; + + can_nvic_config.NVIC_IRQChannel = CAN1_RX1_IRQn; + can_nvic_config.NVIC_IRQChannelPreemptionPriority = 2; + can_nvic_config.NVIC_IRQChannelSubPriority = 2; + can_nvic_config.NVIC_IRQChannelCmd = ENABLE; + CAN_ITConfig(CAN1, CAN_IT_FMP0, ENABLE); + NVIC_Init(&can_nvic_config); +} + +static uint32 CanModeInit(void *drv, struct BusConfigureInfo *configure_info) +{ + NULL_PARAM_CHECK(drv); + NULL_PARAM_CHECK(configure_info); + CAN_FilterInitTypeDef can1_filter; + CAN_InitTypeDef can_initstruction; + + struct CanDriverConfigure *config = ( struct CanDriverConfigure *)configure_info->private_data; + + can_initstruction.CAN_TTCM = DISABLE; + can_initstruction.CAN_ABOM = DISABLE; + can_initstruction.CAN_AWUM = DISABLE; + can_initstruction.CAN_NART = ENABLE; + can_initstruction.CAN_TXFP = DISABLE; + can_initstruction.CAN_Mode = config->mode; + can_initstruction.CAN_RFLM = DISABLE; + can_initstruction.CAN_SJW = config->tsjw; + can_initstruction.CAN_BS1 = config->tbs1; + can_initstruction.CAN_BS2 = config->tbs2; + can_initstruction.CAN_Prescaler = config->brp; + + CAN_Init(CAN1, &can_initstruction); + + can1_filter.CAN_FilterNumber=0; + can1_filter.CAN_FilterMode=CAN_FilterMode_IdMask; + can1_filter.CAN_FilterScale=CAN_FilterScale_32bit; + can1_filter.CAN_FilterIdHigh=0x0000; + can1_filter.CAN_FilterIdLow=0x0000; + can1_filter.CAN_FilterMaskIdHigh=0x0000; + can1_filter.CAN_FilterMaskIdLow=0x0006; + can1_filter.CAN_FilterFIFOAssignment=CAN_Filter_FIFO1; + can1_filter.CAN_FilterActivation=ENABLE; + CAN_FilterInit(&can1_filter); + + #ifdef CAN_USING_INTERRUPT + Can1NvicConfig(); + #endif + + return 0; +} + +static uint32 CanSendMsg(void * dev , struct BusBlockWriteParam *write_param ) +{ + NULL_PARAM_CHECK(write_param); + + uint8 *data = (uint8 * ) write_param->buffer; + u8 messege_box; + u16 i = 0; + u16 timer_count = 1000; + CanTxMsg tx_data; + tx_data.StdId = 0x55; + tx_data.ExtId = 0x00; + tx_data.IDE = 0; + tx_data.RTR = 0; + tx_data.DLC = write_param->size; + + for(i = 0;i < tx_data.DLC;i ++) { + tx_data.Data[i] = data[i]; + } + + messege_box = CAN_Transmit(CAN1,&tx_data); + + while (CAN_TransmitStatus(CAN1,messege_box)== CAN_TxStatus_Failed &&timer_count) { + timer_count--; + } + + if (timer_count<=0) { + return ERROR; + } + return EOK; +} + +static uint32 CanRecvMsg(void *dev , struct BusBlockReadParam *databuf) +{ + NULL_PARAM_CHECK(dev); + int i; + uint8 * buf = (uint8 *)databuf->buffer; + CanRxMsg msg; + if (CAN_MessagePending(CAN1, CAN_FIFO0) == 0) + return 0; + CAN_Receive(CAN1, CAN_FIFO0, &msg); + for(i = 0 ;i < msg.DLC;i ++) + buf[i] = msg.Data[i]; + databuf->size = msg.DLC ; + + return msg.DLC; +} + +static struct CanDevDone dev_done = +{ + .open = NONE, + .close = NONE, + .write = CanSendMsg, + .read = CanRecvMsg +}; + +static struct CanHardwareDevice dev; + +#ifdef CAN_USING_INTERRUPT +void CAN1_RX0_IRQHandler(void) +{ + CanRxMsg rxmsg; + int i = 0; + CAN_Receive(CAN1, 0, &rxmsg); + for (i = 0;i < 8;i ++) + KPrintf("rxbuf [%d] = :%d",i,rxmsg.Data[i]); +} +DECLARE_HW_IRQ(CAN1_RX0_IRQn, CAN1_RX0_IRQHandler, NONE); +#endif + +static int BoardCanBusInit(struct CanDev *CanDev_bus, struct CanDriver *can_driver) +{ + x_err_t ret = EOK; + + /*Init the can bus */ + ret = CanBusInit(&CanDev_bus->can_bus, CanDev_bus->bus_name); + if (EOK != ret) { + KPrintf("Board_can_init canBusInit error %d\n", ret); + return ERROR; + } + + /*Init the can driver*/ + ret = CanDriverInit(can_driver, CAN_DRIVER_NAME); + if (EOK != ret) { + KPrintf("Board_can_init canDriverInit error %d\n", ret); + return ERROR; + } + + /*Attach the can driver to the can bus*/ + ret = CanDriverAttachToBus(CAN_DRIVER_NAME, CanDev_bus->bus_name); + if (EOK != ret) { + KPrintf("Board_can_init CanDriverAttachToBus error %d\n", ret); + return ERROR; + } + + return ret; +} + +static x_err_t HwCanDeviceAttach(const char *bus_name, const char *device_name) +{ + NULL_PARAM_CHECK(bus_name); + NULL_PARAM_CHECK(device_name); + + x_err_t result; + struct CanHardwareDevice *can_device; + + /* attach the device to can bus*/ + can_device = (struct CanHardwareDevice *)x_malloc(sizeof(struct CanHardwareDevice)); + CHECK(can_device); + memset(can_device, 0, sizeof(struct CanHardwareDevice)); + can_device->dev_done = &dev_done; + + result = CanDeviceRegister(can_device, NONE, device_name); + if (EOK != result) { + KPrintf("board_can_init canDeviceInit device %s error %d\n", "can1", result); + return ERROR; + } + + result = CanDeviceAttachToBus(device_name, bus_name); + if (result != EOK) { + SYS_ERR("%s attach to %s faild, %d\n", device_name, bus_name, result); + } + + CHECK(result == EOK); + + KPrintf("%s attach to %s done\n", device_name, bus_name); + + return result; +} + +struct CanDev can1; + +int InitHwCan(void) +{ + x_err_t ret = EOK; + struct CanDev *can_bus; + + static struct CanDriver can_driver; + memset(&can_driver, 0, sizeof(struct CanDriver)); + can_driver.configure = CanModeInit; + + CanGPIOInit(); + can_bus = &can1; + can_bus->instance = CAN1; + can_bus->bus_name = CAN_BUS_NAME_1; + can_bus->can_bus.private_data = &can1; + + ret = BoardCanBusInit(can_bus, &can_driver); + + if (EOK != ret) { + KPrintf(" can_bus_init %s error ret %u\n", can_bus->bus_name, ret); + return ERROR; + } + + ret = HwCanDeviceAttach(CAN_BUS_NAME_1,CAN_1_DEVICE_NAME_1); + if (EOK != ret) { + KPrintf(" HwCanDeviceAttach %s error ret %u\n", can_bus->bus_name, ret); + return ERROR; + } + return EOK; +} \ No newline at end of file diff --git a/Ubiquitous/XiZi_IIoT/board/ch32v307vct6/third_party_driver/can/test/Makefile b/Ubiquitous/XiZi_IIoT/board/ch32v307vct6/third_party_driver/can/test/Makefile new file mode 100755 index 000000000..44c989594 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/ch32v307vct6/third_party_driver/can/test/Makefile @@ -0,0 +1,4 @@ +SRC_FILES := can_test.c + + +include $(KERNEL_ROOT)/compiler.mk diff --git a/Ubiquitous/XiZi_IIoT/board/ch32v307vct6/third_party_driver/can/test/can_test.c b/Ubiquitous/XiZi_IIoT/board/ch32v307vct6/third_party_driver/can/test/can_test.c new file mode 100644 index 000000000..bfb45facb --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/ch32v307vct6/third_party_driver/can/test/can_test.c @@ -0,0 +1,160 @@ + +#include "shell.h" +#include "ch32v30x.h" + +#include "connect_can.h" + +#include +#include +#include +#include + +static int init_can() +{ + + KPrintf("init can\r\n"); + + CAN_FilterInitTypeDef can1_filter; + CAN_InitTypeDef can_initstruction; + + can_initstruction.CAN_TTCM = DISABLE; + can_initstruction.CAN_ABOM = DISABLE; + can_initstruction.CAN_AWUM = DISABLE; + can_initstruction.CAN_NART = ENABLE; + can_initstruction.CAN_TXFP = DISABLE; + can_initstruction.CAN_Mode = CAN_Mode_Silent_LoopBack; + can_initstruction.CAN_RFLM = DISABLE; + can_initstruction.CAN_SJW = CAN_SJW_1tq; + can_initstruction.CAN_BS1 = CAN_BS1_6tq; + can_initstruction.CAN_BS2 = CAN_BS2_5tq; + can_initstruction.CAN_Prescaler = 12; + CAN_Init(CAN1, &can_initstruction); + + can1_filter.CAN_FilterNumber = 0; + can1_filter.CAN_FilterMode = CAN_FilterMode_IdMask; + can1_filter.CAN_FilterScale = CAN_FilterScale_32bit; + can1_filter.CAN_FilterIdHigh = 0x0000; + can1_filter.CAN_FilterIdLow = 0x0000; + can1_filter.CAN_FilterMaskIdHigh = 0x0000; + can1_filter.CAN_FilterMaskIdLow = 0x0006; + can1_filter.CAN_FilterFIFOAssignment = CAN_Filter_FIFO1; + can1_filter.CAN_FilterActivation = ENABLE; + CAN_FilterInit(&can1_filter); + + return 0; +} + +static u8 CAN_Send_Msg(u8 *msg, u8 len) +{ + u8 mbox; + u16 i = 0; + + CanTxMsg CanTxStructure; + + CanTxStructure.StdId = 0x317; + CanTxStructure.IDE = CAN_Id_Standard; + CanTxStructure.RTR = CAN_RTR_Data; + CanTxStructure.DLC = len; + + for (i = 0; i < len; i++) + { + CanTxStructure.Data[i] = msg[i]; + } + + mbox = CAN_Transmit(CAN1, &CanTxStructure); + + i = 0; + + while ((CAN_TransmitStatus(CAN1, mbox) != CAN_TxStatus_Ok) && (i < 0xFFF)) + { + i++; + } + + if (i == 0xFFF) + { + return 1; + } + else + { + return 0; + } +} + +static u8 CAN_Receive_Msg(u8 *buf) +{ + u8 i; + + CanRxMsg CanRxStructure; + + if (CAN_MessagePending(CAN1, CAN_FIFO1) == 0) + { + return 0; + } + + CAN_Receive(CAN1, CAN_FIFO1, &CanRxStructure); + + for (i = 0; i < 8; i++) + { + buf[i] = CanRxStructure.Data[i]; + } + + return CanRxStructure.DLC; +} + +int test_can(int argc, char *argv[]) +{ + u8 i; + u8 cnt = 0; + u8 tx, rx; + u8 txbuf[8]; + u8 rxbuf[8]; + init_can(); + + for (i = 0; i < 8; i++) + { + txbuf[i] = cnt + i; + } + tx = CAN_Send_Msg(txbuf, 8); + + if (tx) + { + KPrintf("CAN1 Send Failed\r\n"); + } + else + { + KPrintf("CAN1 Send Success\r\n"); + KPrintf("CAN1 Send Data:\r\n"); + + for (i = 0; i < 8; i++) + { + KPrintf("%02x\r\n", txbuf[i]); + } + } + + rx = CAN_Receive_Msg(rxbuf); + + if (rx) + { + KPrintf("CAN1 Receive Data:\r\n"); + + for (i = 0; i < 8; i++) + { + KPrintf("%02x\r\n", txbuf[i]); + } + } + else + { + KPrintf("CAN1 No Receive Data\r\n"); + } + + cnt++; + if (cnt == 0xFF) + { + cnt = 0; + } + + return 0; +} + +SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN), + test_can, test_can, test CAN); \ No newline at end of file diff --git a/Ubiquitous/XiZi_IIoT/board/ch32v307vct6/third_party_driver/include/connect_can.h b/Ubiquitous/XiZi_IIoT/board/ch32v307vct6/third_party_driver/include/connect_can.h new file mode 100644 index 000000000..0c5d64a12 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/ch32v307vct6/third_party_driver/include/connect_can.h @@ -0,0 +1,33 @@ + + + + + + +#ifndef CONNECT_CAN_H +#define CONNECT_CAN_H + + +#include +#include + + +#include +#include + + +struct CanDev +{ + CAN_TypeDef *instance; + + char *bus_name; + + // CAN_InitTypeDef init; + + uint8 can_flag; + struct CanBus can_bus; +}; + +int InitHwCan(void); + +#endif \ No newline at end of file diff --git a/Ubiquitous/XiZi_IIoT/board/ch32v307vct6/third_party_driver/include/connect_usb.h b/Ubiquitous/XiZi_IIoT/board/ch32v307vct6/third_party_driver/include/connect_usb.h new file mode 100644 index 000000000..fba9fffa3 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/ch32v307vct6/third_party_driver/include/connect_usb.h @@ -0,0 +1,46 @@ +/* +* 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 + + +#include +#include +#ifdef RESOURCES_USB_HOST +#ifdef BSP_USING_USBH +#include +#endif +#endif + + + + +#ifdef __cplusplus +extern "C" { +#endif + +int InitHwUsb(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Ubiquitous/XiZi_IIoT/board/ch32v307vct6/third_party_driver/uart/Kconfig b/Ubiquitous/XiZi_IIoT/board/ch32v307vct6/third_party_driver/uart/Kconfig index a2471e432..6ddc3f577 100755 --- a/Ubiquitous/XiZi_IIoT/board/ch32v307vct6/third_party_driver/uart/Kconfig +++ b/Ubiquitous/XiZi_IIoT/board/ch32v307vct6/third_party_driver/uart/Kconfig @@ -1,6 +1,6 @@ menuconfig BSP_USING_UART1 bool "Enable UART1" - default y + default n if BSP_USING_UART1 config SERIAL_BUS_NAME_1 string "serial bus name" @@ -15,7 +15,7 @@ menuconfig BSP_USING_UART1 menuconfig BSP_USING_UART2 bool "Enable UART2" - default y + default n if BSP_USING_UART2 config SERIAL_BUS_NAME_2 string "serial bus name" @@ -42,3 +42,18 @@ menuconfig BSP_USING_UART4 string "serial bus device name" default "uart4_dev4" endif + +menuconfig BSP_USING_UART5 + bool "Enable UART5" + default y + if BSP_USING_UART5 + config SERIAL_BUS_NAME_5 + string "serial bus name" + default "uart5" + config SERIAL_DRV_NAME_5 + string "serial bus driver name" + default "uart5_drv" + config SERIAL_5_DEVICE_NAME_0 + string "serial bus device name" + default "uart5_dev5" + endif diff --git a/Ubiquitous/XiZi_IIoT/board/ch32v307vct6/third_party_driver/uart/Makefile b/Ubiquitous/XiZi_IIoT/board/ch32v307vct6/third_party_driver/uart/Makefile index d75c1d8bc..f3f42f614 100755 --- a/Ubiquitous/XiZi_IIoT/board/ch32v307vct6/third_party_driver/uart/Makefile +++ b/Ubiquitous/XiZi_IIoT/board/ch32v307vct6/third_party_driver/uart/Makefile @@ -1,4 +1,4 @@ SRC_FILES := connect_uart.c - +SRC_DIR := test include $(KERNEL_ROOT)/compiler.mk diff --git a/Ubiquitous/XiZi_IIoT/board/ch32v307vct6/third_party_driver/uart/connect_uart.c b/Ubiquitous/XiZi_IIoT/board/ch32v307vct6/third_party_driver/uart/connect_uart.c index e3e2b50d0..7ed1fbf42 100644 --- a/Ubiquitous/XiZi_IIoT/board/ch32v307vct6/third_party_driver/uart/connect_uart.c +++ b/Ubiquitous/XiZi_IIoT/board/ch32v307vct6/third_party_driver/uart/connect_uart.c @@ -325,6 +325,28 @@ void UART4_IRQHandler(void) } #endif +#ifdef BSP_USING_UART5 +struct SerialDriver serial_driver_5; +struct SerialHardwareDevice serial_device_5; + +#define TxSize5 100 +uint16_t RxBuffer5[TxSize5] = { 0 }; +uint16_t TxCnt5 = 0, RxCnt5 = 0; + +void USART5_IRQHandler(void) __attribute__((interrupt())); + +void USART5_IRQHandler(void) +{ + if (USART_GetITStatus(UART5, USART_IT_RXNE) != RESET) { + RxBuffer5[RxCnt5++] = UART_ReceiveData(UART5); + if (RxCnt5 == 100) { + USART_ITConfig(UART5, USART_IT_RXNE, DISABLE); + } + } +} +#endif + + int InitHwUart(void) { x_err_t ret = EOK; @@ -519,5 +541,69 @@ int InitHwUart(void) USART_Cmd((USART_TypeDef*)serial_cfg_4.hw_cfg.serial_register_base, ENABLE); #endif +#ifdef BSP_USING_UART5 + static struct SerialBus serial_bus_5; + memset(&serial_bus_5, 0, sizeof(struct SerialBus)); + + memset(&serial_driver_5, 0, sizeof(struct SerialDriver)); + + memset(&serial_device_5, 0, sizeof(struct SerialHardwareDevice)); + + static struct SerialCfgParam serial_cfg_5; + memset(&serial_cfg_5, 0, sizeof(struct SerialCfgParam)); + + static struct SerialDevParam serial_dev_param_5; + memset(&serial_dev_param_5, 0, sizeof(struct SerialDevParam)); + + serial_driver_5.drv_done = &drv_done; + serial_driver_5.configure = &SerialDrvConfigure; + serial_device_5.hwdev_done = &hwdev_done; + + serial_cfg_5.data_cfg = data_cfg_init; + + serial_cfg_5.hw_cfg.serial_register_base = (uint32)UART5; + serial_cfg_5.hw_cfg.serial_irq_interrupt = UART5_IRQn; + + serial_driver_5.private_data = (void*)&serial_cfg_5; + + serial_dev_param_5.serial_work_mode = SIGN_OPER_INT_RX; + serial_device_5.haldev.private_data = (void*)&serial_dev_param_5; + + ret = BoardSerialBusInit(&serial_bus_5, &serial_driver_5, SERIAL_BUS_NAME_5, SERIAL_DRV_NAME_5); + if (EOK != ret) { + KPrintf("InitHwUart 5 uarths error ret %u\n", ret); + return ERROR; + } + + ret = BoardSerialDevBend(&serial_device_5, (void*)&serial_cfg_5, SERIAL_BUS_NAME_5, SERIAL_5_DEVICE_NAME_0); + if (EOK != ret) { + KPrintf("InitHwUart 5 uarths error ret %u\n", ret); + return ERROR; + } + + GPIO_InitTypeDef gpio_init_struct_5; + RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART5, ENABLE); + RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD, ENABLE); + + gpio_init_struct_5.GPIO_Pin = GPIO_Pin_12; + gpio_init_struct_5.GPIO_Speed = GPIO_Speed_50MHz; + gpio_init_struct_5.GPIO_Mode = GPIO_Mode_AF_PP; + GPIO_Init(GPIOC, &gpio_init_struct_5); + gpio_init_struct_5.GPIO_Pin = GPIO_Pin_2; + gpio_init_struct_5.GPIO_Speed = GPIO_Speed_50MHz; + gpio_init_struct_5.GPIO_Mode = GPIO_Mode_IN_FLOATING; + GPIO_Init(GPIOD, &gpio_init_struct_5); + + USART_InitTypeDef usart_init_struct_5; + usart_init_struct_5.USART_BaudRate = 9600; + usart_init_struct_5.USART_HardwareFlowControl = USART_HardwareFlowControl_None; + usart_init_struct_5.USART_Mode = USART_Mode_Tx | USART_Mode_Rx; + usart_init_struct_5.USART_WordLength = USART_WordLength_8b; + usart_init_struct_5.USART_StopBits = USART_StopBits_1; + usart_init_struct_5.USART_Parity = USART_Parity_No; + USART_Init((USART_TypeDef*)serial_cfg_5.hw_cfg.serial_register_base, &usart_init_struct_5); + USART_Cmd((USART_TypeDef*)serial_cfg_5.hw_cfg.serial_register_base, ENABLE); +#endif + return ret; } diff --git a/Ubiquitous/XiZi_IIoT/board/ch32v307vct6/third_party_driver/uart/test/Makefile b/Ubiquitous/XiZi_IIoT/board/ch32v307vct6/third_party_driver/uart/test/Makefile new file mode 100755 index 000000000..7b33f7977 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/ch32v307vct6/third_party_driver/uart/test/Makefile @@ -0,0 +1,4 @@ +SRC_FILES := rs485_test.c + + +include $(KERNEL_ROOT)/compiler.mk diff --git a/Ubiquitous/XiZi_IIoT/board/ch32v307vct6/third_party_driver/uart/test/rs485_test.c b/Ubiquitous/XiZi_IIoT/board/ch32v307vct6/third_party_driver/uart/test/rs485_test.c new file mode 100644 index 000000000..0027caa92 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/ch32v307vct6/third_party_driver/uart/test/rs485_test.c @@ -0,0 +1,97 @@ + +#include "shell.h" +#include "ch32v30x.h" +#include "ch32v30x_usart.h" +#include "connect_uart.h" + +// UART5发送数据 +static void UART5_SendData(uint8_t data) +{ + // 等待发送缓冲区为空 + while (USART_GetFlagStatus(UART5, USART_FLAG_TXE) == RESET) + { + } + + // 发送数据 + USART_SendData(UART5, data); +} + +// UART5接收数据 +static uint8_t UART5_ReceiveData(void) +{ + // 等待接收缓冲区非空 + while (USART_GetFlagStatus(UART5, USART_FLAG_RXNE) == RESET) + { + } + + // 读取接收数据 + return USART_ReceiveData(UART5); +} + +static void UART5_SendString(const char *buffer) +{ + size_t len = strlen(buffer); + for (size_t i = 0; i < len; i++) + { + if (buffer[i] != '\r' || buffer[i] != '\n') + { + UART5_SendData(buffer[i]); + } + } +} + +static void UART5_ReceiveString(char *buffer, size_t bufferSize) +{ + size_t i = 0; + + while (i < bufferSize - 1) + { + char receivedChar = UART5_ReceiveData(); + + if (receivedChar == '\n') + { + // 收到回车或换行符,表示字符串接收完毕 + break; + } + + buffer[i] = receivedChar; + i++; + } + + buffer[i] = '\0'; // 在字符串末尾添加空字符,表示字符串结束 + + while (USART_GetFlagStatus(UART5, USART_FLAG_RXNE) != RESET) + { + char dummy = USART_ReceiveData(UART5); + (void)dummy; // 避免编译器警告 + } +} + +int test_rs485(int argc, char *argv[]) +{ + KPrintf("485 Test\r\n"); + char receiveBuffer[100]; + char *sendString = " hello aiit 485\r\n"; + int n = 10; + UART5_SendString(sendString); + while (n--) + { + // 接收字符串 + UART5_ReceiveString(receiveBuffer, sizeof(receiveBuffer)); + KPrintf("%s\r\n", receiveBuffer); + if (receiveBuffer[0] == 0xfd) + { + UART5_SendString(sendString); + } + else + { + USART_ClearFlag(UART5, USART_FLAG_TC); + UART5_SendString(receiveBuffer); + } + } + + return 0; +} + +SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN), + test_rs485, test_rs485, test rs485); \ No newline at end of file diff --git a/Ubiquitous/XiZi_IIoT/board/ch32v307vct6/third_party_driver/usb/Kconfig b/Ubiquitous/XiZi_IIoT/board/ch32v307vct6/third_party_driver/usb/Kconfig new file mode 100755 index 000000000..eab1bac92 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/ch32v307vct6/third_party_driver/usb/Kconfig @@ -0,0 +1,26 @@ + +menuconfig BSP_USING_USBH + bool "Using usb host" + default y + if BSP_USING_USBH + config USB_BUS_NAME + string "usb bus name" + default "usb" + config USB_DRIVER_NAME + string "usb bus driver name" + default "usb_drv" + config USB_DEVICE_NAME + string "usb bus device name" + default "usb_dev" + config MOUNT_USB_FS + bool "mount usb file system" + default y + select MOUNT_USB + + if MOUNT_USB_FS + config MOUNT_USB_FS_TYPE + int "choose file system type : FATFS(0) LWEXT4(3)" + default 0 + endif + endif + diff --git a/Ubiquitous/XiZi_IIoT/board/ch32v307vct6/third_party_driver/usb/Makefile b/Ubiquitous/XiZi_IIoT/board/ch32v307vct6/third_party_driver/usb/Makefile new file mode 100644 index 000000000..a748aa85f --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/ch32v307vct6/third_party_driver/usb/Makefile @@ -0,0 +1,9 @@ +SRC_FILES := connect_usb.c +SRC_DIR += usb_drv/src + +include $(KERNEL_ROOT)/compiler.mk + + + + + diff --git a/Ubiquitous/XiZi_IIoT/board/ch32v307vct6/third_party_driver/usb/connect_usb.c b/Ubiquitous/XiZi_IIoT/board/ch32v307vct6/third_party_driver/usb/connect_usb.c new file mode 100644 index 000000000..e31332174 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/ch32v307vct6/third_party_driver/usb/connect_usb.c @@ -0,0 +1,134 @@ +/* +* 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.c +* @brief support aiit-arm32-board usb function and register to bus framework +* @version 1.0 +* @author AIIT XUOS Lab +* @date 2021-04-25 +*/ + +#include +#include +#include + +uint32 UdiskRead_new_api(void *dev, struct BusBlockReadParam *read_param); +uint32 UdiskWirte_new_api(void *dev, struct BusBlockWriteParam *write_param); + +#ifdef MOUNT_USB +#define DISABLE 0 +#define ENABLE 1 + +int MountUsb(void) +{ + Udisk_USBH_Initialization(); + return 0; +} +#endif + +static uint32 UdiskOpenNewApi(void *dev) +{ + return EOK; +} + +static uint32 UdiskCloseNewApi(void *dev) +{ + return EOK; +} + +/*manage the usb device operations*/ +static const struct UsbDevDone dev_done = +{ + .open = UdiskOpenNewApi, + .close = UdiskCloseNewApi, + .write = UdiskWirte_new_api, + .read = UdiskRead_new_api, +}; + +/*Init usb bus*/ +static int BoardUsbBusInit(struct UsbBus *usb_bus, struct UsbDriver *usb_driver) +{ + x_err_t ret = EOK; + + /*Init the usb bus */ + ret = UsbBusInit(usb_bus, USB_BUS_NAME); + if (EOK != ret) { + KPrintf("board_usb_init UsbBusInit error %d\n", ret); + return ERROR; + } + + /*Init the usb driver*/ + ret = UsbDriverInit(usb_driver, USB_DRIVER_NAME); + if (EOK != ret){ + KPrintf("board_usb_init UsbDriverInit error %d\n", ret); + return ERROR; + } + + /*Attach the usb driver to the usb bus*/ + ret = UsbDriverAttachToBus(USB_DRIVER_NAME, USB_BUS_NAME); + if (EOK != ret) { + KPrintf("board_usb_init USEDriverAttachToBus error %d\n", ret); + return ERROR; + } + + return ret; +} + +/*Attach the usb device to the usb bus*/ +static int BoardUsbDevBend(void) +{ + x_err_t ret = EOK; + static struct UsbHardwareDevice usb_device1; + memset(&usb_device1, 0, sizeof(struct UsbHardwareDevice)); + + usb_device1.dev_done = &dev_done; + + ret = USBDeviceRegister(&usb_device1, NONE, USB_DEVICE_NAME); + if (EOK != ret) { + KPrintf("board_usb_init USBDeviceInit device %s error %d\n", USB_DEVICE_NAME, ret); + return ERROR; + } + + ret = USBDeviceAttachToBus(USB_DEVICE_NAME, USB_BUS_NAME); + if (EOK != ret) { + KPrintf("board_usb_init USBDeviceAttachToBus device %s error %d\n", USB_DEVICE_NAME, ret); + return ERROR; + } + + return ret; +} + +/*BOARD USB INIT*/ +int InitHwUsb(void) +{ + x_err_t ret = EOK; + static struct UsbBus usb_bus; + memset(&usb_bus, 0, sizeof(struct UsbBus)); + + static struct UsbDriver usb_driver; + memset(&usb_driver, 0, sizeof(struct UsbDriver)); + + ret = BoardUsbBusInit(&usb_bus, &usb_driver); + if (EOK != ret) { + KPrintf("board_usb_Init error ret %u\n", ret); + return ERROR; + } + + ret = BoardUsbDevBend(); + if (EOK != ret) { + KPrintf("board_usb_Init error ret %u\n", ret); + return ERROR; + } + + return ret; +} diff --git a/Ubiquitous/XiZi_IIoT/board/ch32v307vct6/third_party_driver/usb/usb_drv/inc/CHRV3UFI.h b/Ubiquitous/XiZi_IIoT/board/ch32v307vct6/third_party_driver/usb/usb_drv/inc/CHRV3UFI.h new file mode 100644 index 000000000..a84044b7a --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/ch32v307vct6/third_party_driver/usb/usb_drv/inc/CHRV3UFI.h @@ -0,0 +1,366 @@ +/* 2014.09.09 +***************************************** +** Copyright (C) W.ch 1999-2019 ** +** Web: http://wch.cn ** +***************************************** +** USB-flash File Interface for CHRV3 ** +** KEIL423, gcc 8.20 ** +***************************************** +*/ +/* CHRV3 U盘主机文件系统接口, 支持: FAT12/FAT16/FAT32 */ + +//#include "CHRV3BAS.H" + +#ifndef __CHRV3UFI_H__ +#define __CHRV3UFI_H__ + + + +#define CHRV3_LIB_VER 0x10 + +//#define DISK_BASE_BUF_LEN 512 /* 默认的磁盘数据缓冲区大小为512字节(可以选择为2048甚至4096以支持某些大扇区的U盘),为0则禁止在本文件中定义缓冲区并由应用程序在pDISK_BASE_BUF中指定 */ +/* 如果需要复用磁盘数据缓冲区以节约RAM,那么可将DISK_BASE_BUF_LEN定义为0以禁止在本文件中定义缓冲区,而由应用程序在调用CHRV3LibInit之前将与其它程序合用的缓冲区起始地址置入pDISK_BASE_BUF变量 */ + +//#define NO_DEFAULT_ACCESS_SECTOR 1 /* 禁止默认的磁盘扇区读写子程序,下面用自行编写的程序代替它 */ +//#define NO_DEFAULT_DISK_CONNECT 1 /* 禁止默认的检查磁盘连接子程序,下面用自行编写的程序代替它 */ +//#define NO_DEFAULT_FILE_ENUMER 1 /* 禁止默认的文件名枚举回调程序,下面用自行编写的程序代替它 */ +#define FOR_ROOT_UDISK_ONLY 1 +#ifdef __cplusplus +extern "C" { +#endif + +/* ********************************************************************************************************************* */ + +/* FILE: CHRV3UF.H */ + +/* 错误码 */ +#ifndef ERR_SUCCESS +#define ERR_SUCCESS 0x00 /* 操作成功 */ +#endif +#ifndef ERR_DISK_DISCON +#define ERR_CHRV3_ERROR 0x81 /* CHRV3硬件错误,可能需要复位CHRV3 */ +//#define ERR_DISK_DISCON 0x82 /* 磁盘尚未连接,可能磁盘已经断开 */ +#define ERR_STATUS_ERR 0x83 /* 磁盘状态错误,可能正在连接或者断开磁盘 */ +#define ERR_HUB_PORT_FREE 0x84 /* USB-HUB已经连接但是HUB端口尚未连接磁盘,可能磁盘已经断开 */ +#define ERR_MBR_ERROR 0x91 /* 磁盘的主引导记录无效,可能磁盘尚未分区或者尚未格式化 */ +#define ERR_TYPE_ERROR 0x92 /* 磁盘分区类型不支持,只支持FAT12/FAT16/BigDOS/FAT32,需要由磁盘管理工具重新分区 */ +#define ERR_BPB_ERROR 0xA1 /* 磁盘尚未格式化,或者参数错误,需要由WINDOWS采用默认参数重新格式化 */ +#define ERR_TOO_LARGE 0xA2 /* 磁盘非正常格式化并且容量大于4GB,或者容量大于250GB,需要由WINDOWS采用默认参数重新格式化 */ +#define ERR_FAT_ERROR 0xA3 /* 磁盘的文件系统不支持,只支持FAT12/FAT16/FAT32,需要由WINDOWS采用默认参数重新格式化 */ +#define ERR_DISK_FULL 0xB1 /* 磁盘文件太满,剩余空间太少或者已经没有,需要磁盘整理 */ +#define ERR_FDT_OVER 0xB2 /* 目录内文件太多,没有空闲的目录项,FAT12/FAT16根目录下的文件数应该少于500个,需要磁盘整理 */ +#define ERR_MISS_DIR 0xB3 /* 指定路径的某个子目录没有找到,可能是目录名称错误 */ +#define ERR_FILE_CLOSE 0xB4 /* 文件已经关闭,如果需要使用,应该重新打开文件 */ +#define ERR_OPEN_DIR 0x41 /* 指定路径的目录被打开 */ +#define ERR_MISS_FILE 0x42 /* 指定路径的文件没有找到,可能是文件名称错误 */ +#define ERR_FOUND_NAME 0x43 /* 搜索到与通配符相匹配的文件名,文件名及其完整路径在命令缓冲区中,如果需要使用,应该打开该文件 */ +#endif +/* 代码2XH-3XH用于USB主机方式的通讯失败代码,由CHRV3子程序模仿CH375的返回 */ +/* 代码1XH用于USB主机方式的操作状态代码,由CHRV3子程序模仿CH375的返回 */ +#ifndef ERR_USB_CONNECT +#define ERR_USB_CONNECT_LS 0x13 /* 检测到低速USB设备连接事件 */ +#define ERR_USB_CONNECT 0x15 /* 检测到USB设备连接事件,磁盘已经连接 */ +#define ERR_USB_DISCON 0x16 /* 检测到USB设备断开事件,磁盘已经断开 */ +#define ERR_USB_BUF_OVER 0x17 /* USB传输的数据有误或者数据太多缓冲区溢出 */ +#define ERR_USB_DISK_ERR 0x1F /* USB存储器操作失败,在初始化时可能是USB存储器不支持,在读写操作中可能是磁盘损坏或者已经断开 */ +#define ERR_USB_TRANSFER 0x20 /* NAK/STALL等更多错误码在0x20~0x2F */ +#endif + +/* 磁盘及文件状态 */ +#define DISK_UNKNOWN 0x00 /* 尚未初始化,未知状态 */ +#define DISK_DISCONNECT 0x01 /* 磁盘没有连接或者已经断开 */ +#define DISK_CONNECT 0x02 /* 磁盘已经连接,但是尚未初始化或者无法识别该磁盘 */ +#define DISK_USB_ADDR 0x04 /* 磁盘已经分配USB设备地址,但是尚未配置USB和初始化磁盘 */ +#define DISK_MOUNTED 0x05 /* 磁盘已经初始化成功,但是尚未分析文件系统或者文件系统不支持 */ +#define DISK_READY 0x10 /* 已经分析磁盘的文件系统并且能够支持 */ +#define DISK_OPEN_ROOT 0x12 /* 已经打开根目录,扇区模式,只能以扇区为单位读写目录的内容,使用后必须关闭,注意FAT12/FAT16根目录是固定长度 */ +#define DISK_OPEN_DIR 0x13 /* 已经打开子目录,扇区模式,只能以扇区为单位读写目录的内容 */ +#define DISK_OPEN_FILE 0x14 /* 已经打开文件,扇区模式,可以以扇区为单位进行数据读写 */ +#define DISK_OPEN_FILE_B 0x15 /* 已经打开文件,字节模式,可以以字节为单位进行数据读写 */ + +/* FAT类型标志 */ +#ifndef DISK_FAT16 +#define DISK_FS_UNKNOWN 0 /* 未知的文件系统 */ +#define DISK_FAT12 1 /* FAT12文件系统 */ +#define DISK_FAT16 2 /* FAT16文件系统 */ +#define DISK_FAT32 3 /* FAT32文件系统 */ +#endif + +/* FAT数据区中文件目录信息 */ +typedef struct _FAT_DIR_INFO { + uint8_t DIR_Name[11]; /* 00H,文件名,共11字节,不足处填空格 */ + uint8_t DIR_Attr; /* 0BH,文件属性,参考下面的说明 */ + uint8_t DIR_NTRes; /* 0CH */ + uint8_t DIR_CrtTimeTenth; /* 0DH,文件创建的时间,以0.1秒单位计数 */ + uint16_t DIR_CrtTime; /* 0EH,文件创建的时间 */ + uint16_t DIR_CrtDate; /* 10H,文件创建的日期 */ + uint16_t DIR_LstAccDate; /* 12H,最近一次存取操作的日期 */ + uint16_t DIR_FstClusHI; /* 14H */ + uint16_t DIR_WrtTime; /* 16H,文件修改时间,参考宏MAKE_FILE_TIME */ + uint16_t DIR_WrtDate; /* 18H,文件修改日期,参考宏MAKE_FILE_DATA */ + uint16_t DIR_FstClusLO; /* 1AH */ + uint32_t DIR_FileSize; /* 1CH,文件长度 */ +} FAT_DIR_INFO; /* 20H */ + +typedef FAT_DIR_INFO *PX_FAT_DIR_INFO; + +/* 文件属性 */ +#define ATTR_READ_ONLY 0x01 /* 文件为只读属性 */ +#define ATTR_HIDDEN 0x02 /* 文件为隐含属性 */ +#define ATTR_SYSTEM 0x04 /* 文件为系统属性 */ +#define ATTR_VOLUME_ID 0x08 /* 卷标 */ +#define ATTR_DIRECTORY 0x10 /* 子目录 */ +#define ATTR_ARCHIVE 0x20 /* 文件为存档属性 */ +#define ATTR_LONG_NAME ( ATTR_READ_ONLY | ATTR_HIDDEN | ATTR_SYSTEM | ATTR_VOLUME_ID ) +/* 文件属性 uint8_t */ +/* bit0 bit1 bit2 bit3 bit4 bit5 bit6 bit7 */ +/* 只 隐 系 卷 目 存 未定义 */ +/* 读 藏 统 标 录 档 */ +/* 文件时间 uint16_t */ +/* Time = (Hour<<11) + (Minute<<5) + (Second>>1) */ +#define MAKE_FILE_TIME( h, m, s ) ( (h<<11) + (m<<5) + (s>>1) ) /* 生成指定时分秒的文件时间数据 */ +/* 文件日期 uint16_t */ +/* Date = ((Year-1980)<<9) + (Month<<5) + Day */ +#define MAKE_FILE_DATE( y, m, d ) ( ((y-1980)<<9) + (m<<5) + d ) /* 生成指定年月日的文件日期数据 */ + +/* 文件名 */ +#define PATH_WILDCARD_CHAR 0x2A /* 路径名的通配符 '*' */ +#define PATH_SEPAR_CHAR1 0x5C /* 路径名的分隔符 '\' */ +#define PATH_SEPAR_CHAR2 0x2F /* 路径名的分隔符 '/' */ +#ifndef MAX_PATH_LEN +#define MAX_PATH_LEN 64 /* 最大路径长度,含所有斜杠分隔符和小数点间隔符以及路径结束符00H */ +#endif + +/* 外部命令参数 */ +typedef union _CMD_PARAM +{ + struct + { + uint8_t mBuffer[ MAX_PATH_LEN ]; + } Other; + struct + { + uint32_t mTotalSector; /* 返回: 当前逻辑盘的总扇区数 */ + uint32_t mFreeSector; /* 返回: 当前逻辑盘的剩余扇区数 */ + uint32_t mSaveValue; + } Query; /* CMD_DiskQuery, 查询磁盘信息 */ + struct + { + uint8_t mPathName[ MAX_PATH_LEN ]; /* 输入参数: 路径: [盘符,冒号,斜杠,目录名或者文件名及扩展名...,结束符00H], 其中盘符和冒号可以省略, 例如"C:\DIR1.EXT\DIR2\FILENAME.EXT",00H */ + } Open; /* CMD_FileOpen, 打开文件 */ +// struct +// { +// uint8_t mPathName[ MAX_PATH_LEN ]; /* 输入参数: 路径: [盘符,冒号,斜杠,目录名或者文件名及扩展名(含通配符*)...,结束符00H], 其中盘符和冒号可以省略, 例如"C:\DIR1.EXT\DIR2\FILE*",00H */ +// } Open; /* CMD_FileOpen, 枚举文件, CHRV3vFileSize最高位为1则各调用xFileNameEnumer,为0则返回指定序号的文件名 */ + struct + { + uint8_t mUpdateLen; /* 输入参数: 是否允许更新长度: 0禁止,1允许 */ + } Close; /* CMD_FileClose, 关闭当前文件 */ + struct + { + uint8_t mPathName[ MAX_PATH_LEN ]; /* 输入参数: 路径: [盘符,冒号,斜杠,目录名或者文件名及扩展名...,结束符00H], 其中盘符和冒号可以省略, 例如"C:\DIR1.EXT\DIR2\FILENAME.EXT",00H */ + } Create; /* CMD_FileCreate, 新建文件并打开,如果文件已经存在则先删除后再新建 */ + struct + { + uint8_t mPathName[ MAX_PATH_LEN ]; /* 输入参数: 路径: [盘符,冒号,斜杠,目录名或者文件名及扩展名...,结束符00H], 其中盘符和冒号可以省略, 例如"C:\DIR1.EXT\DIR2\FILENAME.EXT",00H */ + } Erase; /* CMD_FileErase, 删除文件并关闭 */ + struct + { + uint32_t mFileSize; /* 输入参数: 新的文件长度,为0FFFFFFFFH则不修改, 返回: 原长度 */ + uint16_t mFileDate; /* 输入参数: 新的文件日期,为0FFFFH则不修改, 返回: 原日期 */ + uint16_t mFileTime; /* 输入参数: 新的文件时间,为0FFFFH则不修改, 返回: 原时间 */ + uint8_t mFileAttr; /* 输入参数: 新的文件属性,为0FFH则不修改, 返回: 原属性 */ + } Modify; /* CMD_FileQuery, 查询当前文件的信息; CMD_FileModify, 查询或者修改当前文件的信息 */ + struct + { + uint32_t mSaveCurrClus; + uint32_t mSaveLastClus; + } Alloc; /* CMD_FileAlloc, 根据文件长度调整为文件分配的磁盘空间 */ + struct + { + uint32_t mSectorOffset; /* 输入参数: 扇区偏移,0则移动到文件头,0FFFFFFFFH则移动到文件尾, 返回: 当前文件指针对应的绝对线性扇区号, 0FFFFFFFFH则已到文件尾 */ + uint32_t mLastOffset; + } Locate; /* CMD_FileLocate, 移动当前文件指针 */ + struct + { + uint8_t mSectorCount; /* 输入参数: 读取扇区数, 返回: 实际读取扇区数 */ + uint8_t mActCnt; + uint8_t mLbaCount; + uint8_t mRemainCnt; + uint8_t *mDataBuffer; /* 输入参数: 缓冲区起始地址, 返回: 缓冲区当前地址 */ + uint32_t mLbaStart; + } Read; /* CMD_FileRead, 从当前文件读取数据 */ + struct + { + uint8_t mSectorCount; /* 输入参数: 写入扇区数, 返回: 实际写入扇区数 */ + uint8_t mActCnt; + uint8_t mLbaCount; + uint8_t mAllocCnt; + uint8_t *mDataBuffer; /* 输入参数: 缓冲区起始地址, 返回: 缓冲区当前地址 */ + uint32_t mLbaStart; + uint32_t mSaveValue; + } Write; /* CMD_FileWrite, 向当前文件写入数据 */ + struct + { + uint32_t mDiskSizeSec; /* 返回: 整个物理磁盘的总扇区数, 仅首次调用时返回 */ + } DiskReady; /* CMD_DiskReady, 查询磁盘就绪 */ + struct + { + uint32_t mByteOffset; /* 输入参数: 以字节为单位的偏移量, 以字节为单位的文件指针, 返回: 当前文件指针对应的绝对线性扇区号, 0FFFFFFFFH则已到文件尾 */ + uint32_t mLastOffset; + } ByteLocate; /* CMD_ByteLocate, 以字节为单位移动当前文件指针 */ + struct + { + uint16_t mByteCount; /* 输入参数: 准备读取的字节数, 返回: 实际读出的字节数 */ + uint8_t *mByteBuffer; /* 输入参数: 指向存放读出数据块的缓冲区 */ + uint16_t mActCnt; + } ByteRead; /* CMD_ByteRead, 以字节为单位从当前文件读取数据块 */ + struct + { + uint16_t mByteCount; /* 输入参数: 准备写入的字节数, 返回: 实际写入的字节数 */ + uint8_t *mByteBuffer; /* 输入参数: 指向存放读出数据块的缓冲区 */ + uint16_t mActCnt; + } ByteWrite; /* CMD_ByteWrite, 以字节为单位向当前文件写入数据块 */ + struct + { + uint8_t mSaveVariable; /* 输入参数: 为0则恢复单个U盘的变量,为0x80则恢复多个U盘的变量,其它值则备份/保存变量 */ + uint8_t mReserved[3]; + uint8_t *mBuffer; /* 输入参数: 指向子程序库的变量的备份缓冲区,长度不小于80个字节 */ + } SaveVariable; /* CMD_SaveVariable, 备份/保存/恢复子程序库的变量 */ +} CMD_PARAM; + +typedef CMD_PARAM CMD_PARAM_I; +//typedef CMD_PARAM *P_CMD_PARAM; + +/* SCSI命令码 */ +#ifndef SPC_CMD_INQUIRY +#define SPC_CMD_INQUIRY 0x12 +#define SPC_CMD_READ_CAPACITY 0x25 +#define SPC_CMD_READ10 0x28 +#define SPC_CMD_WRITE10 0x2A +#define SPC_CMD_TEST_READY 0x00 +#define SPC_CMD_REQUEST_SENSE 0x03 +#define SPC_CMD_MODESENSE6 0x1A +#define SPC_CMD_MODESENSE10 0x5A +#define SPC_CMD_START_STOP 0x1B +#endif + +/* FILE: CHRV3UFI.C */ +#define EN_DISK_WRITE 1 + +#ifndef DISK_BASE_BUF_LEN +#define DISK_BASE_BUF_LEN 512 /* 默认的磁盘数据缓冲区大小为512字节,建议选择为2048甚至4096以支持某些大扇区的U盘,为0则禁止在.H文件中定义缓冲区并由应用程序在pDISK_BASE_BUF中指定 */ +#endif + +/* 子程序库中提供的变量 */ +extern volatile uint8_t CHRV3IntStatus; /* CHRV3操作的中断状态 */ +extern volatile uint8_t CHRV3DiskStatus; /* 磁盘及文件状态 */ +extern uint8_t CHRV3vDiskFat; /* 逻辑盘的FAT标志:1=FAT12,2=FAT16,3=FAT32 */ +extern uint8_t CHRV3vSecPerClus; /* 逻辑盘的每簇扇区数 */ +extern uint8_t CHRV3vSectorSizeB; /* log2(CHRV3vSectorSize) */ +extern uint32_t CHRV3vStartLba; /* 逻辑盘的起始绝对扇区号LBA */ +extern uint32_t CHRV3vDiskRoot; /* 对于FAT16盘为根目录占用扇区数,对于FAT32盘为根目录起始簇号 */ +extern uint32_t CHRV3vDataStart; /* 逻辑盘的数据区域的起始LBA */ +extern uint32_t CHRV3vStartCluster; /* 当前文件或者目录的起始簇号 */ +extern uint32_t CHRV3vFileSize; /* 当前文件的长度 */ +extern uint32_t CHRV3vCurrentOffset; /* 当前文件指针,当前读写位置的字节偏移 */ +extern uint32_t CHRV3vFdtLba; /* 当前FDT所在的LBA地址 */ +extern uint32_t CHRV3vLbaCurrent; /* 当前读写的磁盘起始LBA地址 */ +extern uint16_t CHRV3vFdtOffset; /* 当前FDT在扇区内的偏移地址 */ +extern uint16_t CHRV3vSectorSize; /* 磁盘的扇区大小 */ +extern uint8_t CHRV3vCurrentLun; /* 磁盘当前操作逻辑单元号 */ +extern uint8_t CHRV3vSubClassIs6; /* USB存储类设备的子类为6,0则非6 */ +extern uint8_t *pDISK_BASE_BUF; /* 指向外部RAM的磁盘数据缓冲区,缓冲区长度不小于CHRV3vSectorSize,由应用程序初始化 */ +extern uint8_t *pDISK_FAT_BUF; /* 指向外部RAM的磁盘FAT数据缓冲区,缓冲区长度不小于CHRV3vSectorSize,由应用程序初始化 */ +extern uint16_t CHRV3vPacketSize; /* USB存储类设备的最大包长度:64@FS,512@HS/SS,由应用程序初始化 */ +extern uint32_t *pTX_DMA_A_REG; /* 指向发送DMA地址寄存器,由应用程序初始化 */ +extern uint32_t *pRX_DMA_A_REG; /* 指向接收DMA地址寄存器,由应用程序初始化 */ +extern uint16_t *pTX_LEN_REG; /* 指向发送长度寄存器,由应用程序初始化 */ +extern uint16_t *pRX_LEN_REG; /* 指向接收长度寄存器,由应用程序初始化 */ + +extern CMD_PARAM_I mCmdParam; /* 命令参数 */ + +extern __attribute__ ((aligned(4))) uint8_t RxBuffer[ ]; // IN, must even address +extern __attribute__ ((aligned(4))) uint8_t TxBuffer[ ]; // OUT, must even address + +//#define PXUDISK_BOC_CBW PUDISK_BOC_CBW +//#define PXUDISK_BOC_CSW PUDISK_BOC_CSW + +#ifndef pSetupReq +#define pSetupReq ((PUSB_SETUP_REQ)TxBuffer) +#endif + +#ifndef pCBW +#define pCBW ((PXUDISK_BOC_CBW)TxBuffer) +#define pCSW ((PXUDISK_BOC_CSW)RxBuffer) +#endif +#ifndef pBOC_buf +#define pBOC_buf (TxBuffer+((USB_BO_CBW_SIZE+4)&0xFE)) +#endif + +#if DISK_BASE_BUF_LEN > 0 +extern uint8_t DISK_BASE_BUF[ DISK_BASE_BUF_LEN ]; /* 外部RAM的磁盘数据缓冲区,缓冲区长度为一个扇区的长度 */ +#endif +extern uint8_t CHRV3ReadSector( uint8_t SectCount, uint8_t * DataBuf ); /* 从磁盘读取多个扇区的数据到缓冲区中 */ +#ifdef EN_DISK_WRITE +extern uint8_t CHRV3WriteSector( uint8_t SectCount, uint8_t * DataBuf ); /* 将缓冲区中的多个扇区的数据块写入磁盘 */ +#endif + +extern uint8_t CHRV3DiskConnect( void ); /* 检查磁盘是否连接并更新磁盘状态 */ +extern void xFileNameEnumer( void ); /* 调用外部定义的子程序,文件名枚举回调子程序 */ + +extern uint8_t CHRV3LibInit( void ); /* 初始化CHRV3程序库,操作成功返回0 */ + +/* 子程序库中提供的子程序 */ +/* 下述子程序中, 文件操作子程序CHRV3File*和磁盘查询子程序CHRV3DiskQuery都可能会用到磁盘数据缓冲区pDISK_BASE_BUF, + 并且有可能在pDISK_BASE_BUF中保存了磁盘信息, 所以必须保证pDISK_BASE_BUF不被用于其它用途, + 如果RAM较少, 要将pDISK_BASE_BUF临时用于其它用途, 那么在临时用完后必须调用CHRV3DirtyBuffer清除磁盘缓冲区 */ +extern uint8_t CHRV3GetVer( void ); /* 获取当前子程序库的版本号 */ +extern void CHRV3DirtyBuffer( void ); /* 清除磁盘缓冲区 */ +extern uint8_t CHRV3BulkOnlyCmd( uint8_t * DataBuf ); /* 执行基于BulkOnly协议的命令 */ +extern uint8_t CHRV3DiskReady( void ); /* 查询磁盘是否准备好 */ +extern uint8_t CHRV3AnalyzeError( uint8_t iMode ); /* USB操作失败分析CHRV3IntStatus返回错误状态 */ +extern uint8_t CHRV3FileOpen( void ); /* 打开文件或者枚举文件 */ +extern uint8_t CHRV3FileClose( void ); /* 关闭当前文件 */ +#ifdef EN_DISK_WRITE +extern uint8_t CHRV3FileErase( void ); /* 删除文件并关闭 */ +extern uint8_t CHRV3FileCreate( void ); /* 新建文件并打开,如果文件已经存在则先删除后再新建 */ +extern uint8_t CHRV3FileAlloc( void ); /* 根据文件长度调整为文件分配的磁盘空间 */ +#endif +extern uint8_t CHRV3FileModify( void ); /* 查询或者修改当前文件的信息 */ +extern uint8_t CHRV3FileQuery( void ); /* 查询当前文件的信息 */ +extern uint8_t CHRV3FileLocate( void ); /* 移动当前文件指针 */ +extern uint8_t CHRV3FileRead( void ); /* 从当前文件读取数据到指定缓冲区 */ +#ifdef EN_DISK_WRITE +extern uint8_t CHRV3FileWrite( void ); /* 向当前文件写入指定缓冲区的数据 */ +#endif +extern uint8_t CHRV3ByteLocate( void ); /* 以字节为单位移动当前文件指针 */ +extern uint8_t CHRV3ByteRead( void ); /* 以字节为单位从当前位置读取数据块 */ +#ifdef EN_DISK_WRITE +extern uint8_t CHRV3ByteWrite( void ); /* 以字节为单位向当前位置写入数据块 */ +#endif +extern uint8_t CHRV3DiskQuery( void ); /* 查询磁盘信息 */ +extern void CHRV3SaveVariable( void ); /* 备份/保存/恢复子程序库的变量,用于子程序库在多个芯片或者U盘之间进行切换 */ + +extern void mDelayuS( uint16_t n ); // 以uS为单位延时 +extern void mDelaymS( uint16_t n ); // 以mS为单位延时 +extern uint8_t USBHostTransact( uint8_t endp_pid, uint8_t tog, uint32_t timeout ); // CHRV3传输事务,输入目的端点地址/PID令牌,同步标志,NAK重试时间,返回0成功,超时/出错重试 +extern uint8_t HostCtrlTransfer( uint8_t * DataBuf, uint8_t * RetLen ); // 执行控制传输,8字节请求码在pSetupReq中,DataBuf为可选的收发缓冲区,实际收发长度返回在ReqLen指向的变量中 +extern void CopySetupReqPkg( const char * pReqPkt ); // 复制控制传输的请求包 +extern uint8_t CtrlGetDeviceDescrTB( void ); // 获取设备描述符,返回在TxBuffer中 +extern uint8_t CtrlGetConfigDescrTB( void ); // 获取配置描述符,返回在TxBuffer中 +extern uint8_t CtrlSetUsbAddress( uint8_t addr ); // 设置USB设备地址 +extern uint8_t CtrlSetUsbConfig( uint8_t cfg ); // 设置USB设备配置 +extern uint8_t CtrlClearEndpStall( uint8_t endp ); // 清除端点STALL +#ifndef FOR_ROOT_UDISK_ONLY +//extern uint8_t CtrlGetHubDescr( void ); // 获取HUB描述符,返回在TxBuffer中 +extern uint8_t HubGetPortStatus( uint8_t HubPortIndex ); // 查询HUB端口状态,返回在TxBuffer中 +//extern uint8_t HubSetPortFeature( uint8_t HubPortIndex, uint8_t FeatureSelt ); // 设置HUB端口特性 +extern uint8_t HubClearPortFeature( uint8_t HubPortIndex, uint8_t FeatureSelt ); // 清除HUB端口特性 +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Ubiquitous/XiZi_IIoT/board/ch32v307vct6/third_party_driver/usb/usb_drv/inc/Udisk_Operation.h b/Ubiquitous/XiZi_IIoT/board/ch32v307vct6/third_party_driver/usb/usb_drv/inc/Udisk_Operation.h new file mode 100644 index 000000000..9fc77dfac --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/ch32v307vct6/third_party_driver/usb/usb_drv/inc/Udisk_Operation.h @@ -0,0 +1,78 @@ +/********************************** (C) COPYRIGHT ******************************* +* File Name : UDisk_Operation.h +* Author : WCH +* Version : V1.0.0 +* Date : 2022/11/20 +* Description : This file contains all the functions prototypes for the Udisk + host operation. +********************************************************************************* +* 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 USER_UDISK_OPERATION_H_ +#define USER_UDISK_OPERATION_H_ + +#include "debug.h" +#include "string.h" +#include "CHRV3UFI.h" +#include "ch32v30x_usbhs_host.h" +#include "usb_host_config.h" + +/*******************************************************************************/ +/* Public Extern Variables */ +extern volatile uint8_t UDisk_Opeation_Flag; +extern struct _ROOT_HUB_DEVICE RootHubDev[ DEF_TOTAL_ROOT_HUB ]; +extern struct __HOST_CTL HostCtl[ DEF_TOTAL_ROOT_HUB * DEF_ONE_USB_SUP_DEV_TOTAL ]; +extern volatile uint8_t UDisk_Opeation_Flag; +extern uint8_t *pCodeStr; + +extern __attribute__((aligned(4))) uint8_t Com_Buffer[ DEF_COM_BUF_LEN ]; // even address , used for host enumcation and udisk operation +extern __attribute__((aligned(4))) uint8_t DevDesc_Buf[ 18 ]; // Device Descriptor Buffer + +/*******************************************************************************/ +/* 长文件名相关的宏定义极其全局变量 */ +// 长文件名缓冲区从(0到20)*26 +#define LONG_NAME_BUF_LEN (20*26) +#define UNICODE_ENDIAN 0 // 1为UNICDOE大端编码 0为小端 +// 长文件名存放缓冲区(Unicode编码) +extern uint8_t LongNameBuf[ ]; +// 长文件名(Unicode编码) +extern uint8_t LongName[ ]; +#define LongName_Len 124 +#define TRUE 1 +#define FALSE 0 + +// 函数返回 +#define ERR_NO_NAME 0X44 // 此短文件名没有长文件名或错误的长文件 +#define ERR_BUF_OVER 0X45 // 长文件缓冲区溢出 +#define ERR_LONG_NAME 0X46 // 错误的长文件名 +#define ERR_NAME_EXIST 0X47 // 此短文件名存在 + +/*******************************************************************************/ +/* Extern UDisk Operation Functions */ +extern void mStopIfError( uint8_t iError ); +extern void Udisk_USBH_Initialization( void ); +extern uint8_t Udisk_USBH_EnumRootDevice( uint8_t usb_port ); +extern uint8_t UDisk_USBH_PreDeal( void ); +extern uint8_t UDisk_USBH_DiskReady( void ); + +/* Extern Long-name Operation Functions */ +extern void UDisk_USBH_Longname( void ); +extern uint8_t CHRV3GetLongName( void ); +extern uint8_t GetUpSectorData( uint32_t *NowSector ); +extern uint8_t CHRV3CreateLongName( void ); +extern uint8_t AnalyzeLongName( void ); +extern uint8_t CheckNameSum( uint8_t *p ); + +/* Extern Creating Directory Functions */ +extern void UDisk_USBH_CreatDirectory( void ); +extern uint8_t CreateDirectory( void ); + +/* Extern Byte/Sector Open/Read/Modify/Delete and File-Enumeration Functions */ +extern void UDisk_USBH_ByteOperation( void ); +extern void UDisk_USBH_SectorOperation( void ); +extern void UDisk_USBH_EnumFiles( void ); + +#endif /* USER_UDISK_OPERATION_H_ */ diff --git a/Ubiquitous/XiZi_IIoT/board/ch32v307vct6/third_party_driver/usb/usb_drv/inc/ch32v30x_usb.h b/Ubiquitous/XiZi_IIoT/board/ch32v307vct6/third_party_driver/usb/usb_drv/inc/ch32v30x_usb.h new file mode 100644 index 000000000..f1f6da6f6 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/ch32v307vct6/third_party_driver/usb/usb_drv/inc/ch32v30x_usb.h @@ -0,0 +1,833 @@ +/********************************** (C) COPYRIGHT ******************************* +* File Name : system_ch32v30x.h +* Author : WCH +* Version : V1.0.0 +* Date : 2022/08/20 +* Description : CH32V30x Device Peripheral Access Layer System Header File. +********************************************************************************* +* 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 __CH32V30x_USB_H +#define __CH32V30x_USB_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*******************************************************************************/ +/* Header File */ +#include "stdint.h" + +/*******************************************************************************/ +/* USB Communication Related Macro Definition */ +/* USB Endpoint0 Size */ +#ifndef DEFAULT_ENDP0_SIZE +#define DEFAULT_ENDP0_SIZE 8 // default maximum packet size for endpoint 0 +#endif +#ifndef MAX_PACKET_SIZE +#define MAX_PACKET_SIZE 64 // maximum packet size +#endif + +/* USB PID */ +#ifndef USB_PID_SETUP +#define USB_PID_NULL 0x00 +#define USB_PID_SOF 0x05 +#define USB_PID_SETUP 0x0D +#define USB_PID_IN 0x09 +#define USB_PID_OUT 0x01 +#define USB_PID_NYET 0x06 +#define USB_PID_ACK 0x02 +#define USB_PID_NAK 0x0A +#define USB_PID_STALL 0x0E +#define USB_PID_DATA0 0x03 +#define USB_PID_DATA1 0x0B +#define USB_PID_DATA2 0x07 +#define USB_PID_MDATA 0x0F +#define USB_PID_PRE 0x0C +#endif + +/* USB standard device request code */ +#ifndef USB_GET_DESCRIPTOR +#define USB_GET_STATUS 0x00 +#define USB_CLEAR_FEATURE 0x01 +#define USB_SET_FEATURE 0x03 +#define USB_SET_ADDRESS 0x05 +#define USB_GET_DESCRIPTOR 0x06 +#define USB_SET_DESCRIPTOR 0x07 +#define USB_GET_CONFIGURATION 0x08 +#define USB_SET_CONFIGURATION 0x09 +#define USB_GET_INTERFACE 0x0A +#define USB_SET_INTERFACE 0x0B +#define USB_SYNCH_FRAME 0x0C +#endif + +#define DEF_STRING_DESC_LANG 0x00 +#define DEF_STRING_DESC_MANU 0x01 +#define DEF_STRING_DESC_PROD 0x02 +#define DEF_STRING_DESC_SERN 0x03 + +/* USB hub class request code */ +#ifndef HUB_GET_DESCRIPTOR +#define HUB_GET_STATUS 0x00 +#define HUB_CLEAR_FEATURE 0x01 +#define HUB_GET_STATE 0x02 +#define HUB_SET_FEATURE 0x03 +#define HUB_GET_DESCRIPTOR 0x06 +#define HUB_SET_DESCRIPTOR 0x07 +#endif + +/* USB HID class request code */ +#ifndef HID_GET_REPORT +#define HID_GET_REPORT 0x01 +#define HID_GET_IDLE 0x02 +#define HID_GET_PROTOCOL 0x03 +#define HID_SET_REPORT 0x09 +#define HID_SET_IDLE 0x0A +#define HID_SET_PROTOCOL 0x0B +#endif + +/* USB CDC Class request code */ +#ifndef CDC_GET_LINE_CODING +#define CDC_GET_LINE_CODING 0x21 /* This request allows the host to find out the currently configured line coding */ +#define CDC_SET_LINE_CODING 0x20 /* Configures DTE rate, stop-bits, parity, and number-of-character */ +#define CDC_SET_LINE_CTLSTE 0x22 /* This request generates RS-232/V.24 style control signals */ +#define CDC_SEND_BREAK 0x23 /* Sends special carrier modulation used to specify RS-232 style break */ +#endif + +/* Bit Define for USB Request Type */ +#ifndef USB_REQ_TYP_MASK +#define USB_REQ_TYP_IN 0x80 +#define USB_REQ_TYP_OUT 0x00 +#define USB_REQ_TYP_READ 0x80 +#define USB_REQ_TYP_WRITE 0x00 +#define USB_REQ_TYP_MASK 0x60 +#define USB_REQ_TYP_STANDARD 0x00 +#define USB_REQ_TYP_CLASS 0x20 +#define USB_REQ_TYP_VENDOR 0x40 +#define USB_REQ_TYP_RESERVED 0x60 +#define USB_REQ_RECIP_MASK 0x1F +#define USB_REQ_RECIP_DEVICE 0x00 +#define USB_REQ_RECIP_INTERF 0x01 +#define USB_REQ_RECIP_ENDP 0x02 +#define USB_REQ_RECIP_OTHER 0x03 +#define USB_REQ_FEAT_REMOTE_WAKEUP 0x01 +#define USB_REQ_FEAT_ENDP_HALT 0x00 +#endif + +/* USB Descriptor Type */ +#ifndef USB_DESCR_TYP_DEVICE +#define USB_DESCR_TYP_DEVICE 0x01 +#define USB_DESCR_TYP_CONFIG 0x02 +#define USB_DESCR_TYP_STRING 0x03 +#define USB_DESCR_TYP_INTERF 0x04 +#define USB_DESCR_TYP_ENDP 0x05 +#define USB_DESCR_TYP_QUALIF 0x06 +#define USB_DESCR_TYP_SPEED 0x07 +#define USB_DESCR_TYP_OTG 0x09 +#define USB_DESCR_TYP_BOS 0X0F +#define USB_DESCR_TYP_HID 0x21 +#define USB_DESCR_TYP_REPORT 0x22 +#define USB_DESCR_TYP_PHYSIC 0x23 +#define USB_DESCR_TYP_CS_INTF 0x24 +#define USB_DESCR_TYP_CS_ENDP 0x25 +#define USB_DESCR_TYP_HUB 0x29 +#endif + +/* USB Device Class */ +#ifndef USB_DEV_CLASS_HUB +#define USB_DEV_CLASS_RESERVED 0x00 +#define USB_DEV_CLASS_AUDIO 0x01 +#define USB_DEV_CLASS_COMMUNIC 0x02 +#define USB_DEV_CLASS_HID 0x03 +#define USB_DEV_CLASS_MONITOR 0x04 +#define USB_DEV_CLASS_PHYSIC_IF 0x05 +#define USB_DEV_CLASS_POWER 0x06 +#define USB_DEV_CLASS_IMAGE 0x06 +#define USB_DEV_CLASS_PRINTER 0x07 +#define USB_DEV_CLASS_STORAGE 0x08 +#define USB_DEV_CLASS_HUB 0x09 +#define USB_DEV_CLASS_VEN_SPEC 0xFF +#endif + +/* USB Hub Class Request */ +#ifndef HUB_GET_HUB_DESCRIPTOR +#define HUB_CLEAR_HUB_FEATURE 0x20 +#define HUB_CLEAR_PORT_FEATURE 0x23 +#define HUB_GET_BUS_STATE 0xA3 +#define HUB_GET_HUB_DESCRIPTOR 0xA0 +#define HUB_GET_HUB_STATUS 0xA0 +#define HUB_GET_PORT_STATUS 0xA3 +#define HUB_SET_HUB_DESCRIPTOR 0x20 +#define HUB_SET_HUB_FEATURE 0x20 +#define HUB_SET_PORT_FEATURE 0x23 +#endif + +/* Hub Class Feature Selectors */ +#ifndef HUB_PORT_RESET +#define HUB_C_HUB_LOCAL_POWER 0 +#define HUB_C_HUB_OVER_CURRENT 1 +#define HUB_PORT_CONNECTION 0 +#define HUB_PORT_ENABLE 1 +#define HUB_PORT_SUSPEND 2 +#define HUB_PORT_OVER_CURRENT 3 +#define HUB_PORT_RESET 4 +#define HUB_PORT_POWER 8 +#define HUB_PORT_LOW_SPEED 9 +#define HUB_C_PORT_CONNECTION 16 +#define HUB_C_PORT_ENABLE 17 +#define HUB_C_PORT_SUSPEND 18 +#define HUB_C_PORT_OVER_CURRENT 19 +#define HUB_C_PORT_RESET 20 +#endif + +/* USB UDisk */ +#ifndef USB_BO_CBW_SIZE +#define USB_BO_CBW_SIZE 0x1F +#define USB_BO_CSW_SIZE 0x0D +#endif +#ifndef USB_BO_CBW_SIG0 +#define USB_BO_CBW_SIG0 0x55 +#define USB_BO_CBW_SIG1 0x53 +#define USB_BO_CBW_SIG2 0x42 +#define USB_BO_CBW_SIG3 0x43 +#define USB_BO_CSW_SIG0 0x55 +#define USB_BO_CSW_SIG1 0x53 +#define USB_BO_CSW_SIG2 0x42 +#define USB_BO_CSW_SIG3 0x53 +#endif + + +/******************************************************************************/ +/* USBHS Clock Configuration Related Macro Definition */ +#define USB_CLK_SRC 0x80000000 +#define USBHS_PLL_ALIVE 0x40000000 +#define USBHS_PLL_CKREF_MASK 0x30000000 +#define USBHS_PLL_CKREF_3M 0x00000000 +#define USBHS_PLL_CKREF_4M 0x10000000 +#define USBHS_PLL_CKREF_8M 0x20000000 +#define USBHS_PLL_CKREF_5M 0x30000000 +#define USBHS_PLL_SRC 0x08000000 +#define USBHS_PLL_SRC_PRE_MASK 0x07000000 +#define USBHS_PLL_SRC_PRE_DIV1 0x00000000 +#define USBHS_PLL_SRC_PRE_DIV2 0x01000000 +#define USBHS_PLL_SRC_PRE_DIV3 0x02000000 +#define USBHS_PLL_SRC_PRE_DIV4 0x03000000 +#define USBHS_PLL_SRC_PRE_DIV5 0x04000000 +#define USBHS_PLL_SRC_PRE_DIV6 0x05000000 +#define USBHS_PLL_SRC_PRE_DIV7 0x06000000 +#define USBHS_PLL_SRC_PRE_DIV8 0x07000000 + + +/*******************************************************************************/ +/* USBHS Related Register Macro Definition */ + +/* R8_USB_CTRL */ +#define USBHS_UC_HOST_MODE 0x80 +#define USBHS_UC_SPEED_TYPE 0x60 +#define USBHS_UC_SPEED_LOW 0x40 +#define USBHS_UC_SPEED_FULL 0x00 +#define USBHS_UC_SPEED_HIGH 0x20 +#define USBHS_UC_DEV_PU_EN 0x10 +#define USBHS_UC_INT_BUSY 0x08 +#define USBHS_UC_RESET_SIE 0x04 +#define USBHS_UC_CLR_ALL 0x02 +#define USBHS_UC_DMA_EN 0x01 + +/* R8_USB_INT_EN */ +#define USBHS_UIE_DEV_NAK 0x80 +#define USBHS_UIE_ISO_ACT 0x40 +#define USBHS_UIE_SETUP_ACT 0x20 +#define USBHS_UIE_FIFO_OV 0x10 +#define USBHS_UIE_SOF_ACT 0x08 +#define USBHS_UIE_SUSPEND 0x04 +#define USBHS_UIE_TRANSFER 0x02 +#define USBHS_UIE_DETECT 0x01 +#define USBHS_UIE_BUS_RST 0x01 + +/* R16_USB_DEV_AD */ +#define USBHS_MASK_USB_ADDR 0x7F + +/* R16_USB_FRAME_NO */ +#define USBHS_MICRO_FRAME_NUM 0xE000 +#define USBHS_SOF_FRAME_NUM 0x07FF + +/* R8_USB_SUSPEND */ +#define USBHS_USB_LINESTATE 0x30 +#define USBHS_USB_WAKEUP_ST 0x04 +#define USBHS_USB_SYS_MOD 0x03 + +/* R8_USB_SPEED_TYPE */ +#define USBHS_USB_SPEED_TYPE 0x03 +#define USBHS_USB_SPEED_LOW 0x02 +#define USBHS_USB_SPEED_FULL 0x00 +#define USBHS_USB_SPEED_HIGH 0x01 + +/* R8_USB_MIS_ST */ +#define USBHS_UMS_SOF_PRES 0x80 +#define USBHS_UMS_SOF_ACT 0x40 +#define USBHS_UMS_SIE_FREE 0x20 +#define USBHS_UMS_R_FIFO_RDY 0x10 +#define USBHS_UMS_BUS_RESET 0x08 +#define USBHS_UMS_SUSPEND 0x04 +#define USBHS_UMS_DEV_ATTACH 0x02 +#define USBHS_UMS_SPLIT_CAN 0x01 + +/* R8_USB_INT_FG */ +#define USBHS_UIF_ISO_ACT 0x40 +#define USBHS_UIF_SETUP_ACT 0x20 +#define USBHS_UIF_FIFO_OV 0x10 +#define USBHS_UIF_HST_SOF 0x08 +#define USBHS_UIF_SUSPEND 0x04 +#define USBHS_UIF_TRANSFER 0x02 +#define USBHS_UIF_DETECT 0x01 +#define USBHS_UIF_BUS_RST 0x01 + +/* R8_USB_INT_ST */ +#define USBHS_UIS_IS_NAK 0x80 +#define USBHS_UIS_TOG_OK 0x40 +#define USBHS_UIS_TOKEN_MASK 0x30 +#define USBHS_UIS_TOKEN_OUT 0x00 +#define USBHS_UIS_TOKEN_SOF 0x10 +#define USBHS_UIS_TOKEN_IN 0x20 +#define USBHS_UIS_TOKEN_SETUP 0x30 +#define USBHS_UIS_ENDP_MASK 0x0F +#define USBHS_UIS_H_RES_MASK 0x0F + +/* R16_USB_RX_LEN */ +#define USBHS_USB_RX_LEN 0xFFFF + +/* R32_UEP_CONFIG */ +#define USBHS_UEP15_R_EN 0x80000000 +#define USBHS_UEP14_R_EN 0x40000000 +#define USBHS_UEP13_R_EN 0x20000000 +#define USBHS_UEP12_R_EN 0x10000000 +#define USBHS_UEP11_R_EN 0x08000000 +#define USBHS_UEP10_R_EN 0x04000000 +#define USBHS_UEP9_R_EN 0x02000000 +#define USBHS_UEP8_R_EN 0x01000000 +#define USBHS_UEP7_R_EN 0x00800000 +#define USBHS_UEP6_R_EN 0x00400000 +#define USBHS_UEP5_R_EN 0x00200000 +#define USBHS_UEP4_R_EN 0x00100000 +#define USBHS_UEP3_R_EN 0x00080000 +#define USBHS_UEP2_R_EN 0x00040000 +#define USBHS_UEP1_R_EN 0x00020000 +#define USBHS_UEP0_R_EN 0x00010000 +#define USBHS_UEP15_T_EN 0x00008000 +#define USBHS_UEP14_T_EN 0x00004000 +#define USBHS_UEP13_T_EN 0x00002000 +#define USBHS_UEP12_T_EN 0x00001000 +#define USBHS_UEP11_T_EN 0x00000800 +#define USBHS_UEP10_T_EN 0x00000400 +#define USBHS_UEP9_T_EN 0x00000200 +#define USBHS_UEP8_T_EN 0x00000100 +#define USBHS_UEP7_T_EN 0x00000080 +#define USBHS_UEP6_T_EN 0x00000040 +#define USBHS_UEP5_T_EN 0x00000020 +#define USBHS_UEP4_T_EN 0x00000010 +#define USBHS_UEP3_T_EN 0x00000008 +#define USBHS_UEP2_T_EN 0x00000004 +#define USBHS_UEP1_T_EN 0x00000002 +#define USBHS_UEP0_T_EN 0x00000001 + +/* R32_UEP_TYPE */ +#define USBHS_UEP15_R_TYPE 0x80000000 +#define USBHS_UEP14_R_TYPE 0x40000000 +#define USBHS_UEP13_R_TYPE 0x20000000 +#define USBHS_UEP12_R_TYPE 0x10000000 +#define USBHS_UEP11_R_TYPE 0x08000000 +#define USBHS_UEP10_R_TYPE 0x04000000 +#define USBHS_UEP9_R_TYPE 0x02000000 +#define USBHS_UEP8_R_TYPE 0x01000000 +#define USBHS_UEP7_R_TYPE 0x00800000 +#define USBHS_UEP6_R_TYPE 0x00400000 +#define USBHS_UEP5_R_TYPE 0x00200000 +#define USBHS_UEP4_R_TYPE 0x00100000 +#define USBHS_UEP3_R_TYPE 0x00080000 +#define USBHS_UEP2_R_TYPE 0x00040000 +#define USBHS_UEP1_R_TYPE 0x00020000 +#define USBHS_UEP0_R_TYPE 0x00010000 +#define USBHS_UEP15_T_TYPE 0x00008000 +#define USBHS_UEP14_T_TYPE 0x00004000 +#define USBHS_UEP13_T_TYPE 0x00002000 +#define USBHS_UEP12_T_TYPE 0x00001000 +#define USBHS_UEP11_T_TYPE 0x00000800 +#define USBHS_UEP10_T_TYPE 0x00000400 +#define USBHS_UEP9_T_TYPE 0x00000200 +#define USBHS_UEP8_T_TYPE 0x00000100 +#define USBHS_UEP7_T_TYPE 0x00000080 +#define USBHS_UEP6_T_TYPE 0x00000040 +#define USBHS_UEP5_T_TYPE 0x00000020 +#define USBHS_UEP4_T_TYPE 0x00000010 +#define USBHS_UEP3_T_TYPE 0x00000008 +#define USBHS_UEP2_T_TYPE 0x00000004 +#define USBHS_UEP1_T_TYPE 0x00000002 +#define USBHS_UEP0_T_TYPE 0x00000001 + +/* R32_UEP_BUF_MOD */ +#define USBHS_UEP15_ISO_BUF_MOD 0x80000000 +#define USBHS_UEP14_ISO_BUF_MOD 0x40000000 +#define USBHS_UEP13_ISO_BUF_MOD 0x20000000 +#define USBHS_UEP12_ISO_BUF_MOD 0x10000000 +#define USBHS_UEP11_ISO_BUF_MOD 0x08000000 +#define USBHS_UEP10_ISO_BUF_MOD 0x04000000 +#define USBHS_UEP9_ISO_BUF_MOD 0x02000000 +#define USBHS_UEP8_ISO_BUF_MOD 0x01000000 +#define USBHS_UEP7_ISO_BUF_MOD 0x00800000 +#define USBHS_UEP6_ISO_BUF_MOD 0x00400000 +#define USBHS_UEP5_ISO_BUF_MOD 0x00200000 +#define USBHS_UEP4_ISO_BUF_MOD 0x00100000 +#define USBHS_UEP3_ISO_BUF_MOD 0x00080000 +#define USBHS_UEP2_ISO_BUF_MOD 0x00040000 +#define USBHS_UEP1_ISO_BUF_MOD 0x00020000 +#define USBHS_UEP0_ISO_BUF_MOD 0x00010000 +#define USBHS_UEP15_BUF_MOD 0x00008000 +#define USBHS_UEP14_BUF_MOD 0x00004000 +#define USBHS_UEP13_BUF_MOD 0x00002000 +#define USBHS_UEP12_BUF_MOD 0x00001000 +#define USBHS_UEP11_BUF_MOD 0x00000800 +#define USBHS_UEP10_BUF_MOD 0x00000400 +#define USBHS_UEP9_BUF_MOD 0x00000200 +#define USBHS_UEP8_BUF_MOD 0x00000100 +#define USBHS_UEP7_BUF_MOD 0x00000080 +#define USBHS_UEP6_BUF_MOD 0x00000040 +#define USBHS_UEP5_BUF_MOD 0x00000020 +#define USBHS_UEP4_BUF_MOD 0x00000010 +#define USBHS_UEP3_BUF_MOD 0x00000008 +#define USBHS_UEP2_BUF_MOD 0x00000004 +#define USBHS_UEP1_BUF_MOD 0x00000002 +#define USBHS_UEP0_BUF_MOD 0x00000001 + +/* R32_UEP0_DMA */ +#define USBHS_UEP0_DMA 0x0000FFFF + +/* R32_UEPn_TX_DMA, n=1-15 */ +#define USBHS_UEPn_TX_DMA 0x0000FFFF + +/* R32_UEPn_RX_DMA, n=1-15 */ +#define USBHS_UEPn_RX_DMA 0x0000FFFF + +/* R16_UEPn_MAX_LEN, n=0-15 */ +#define USBHS_UEPn_MAX_LEN 0x07FF + +/* R16_UEPn_T_LEN, n=0-15 */ +#define USBHS_UEPn_T_LEN 0x07FF + +/* R8_UEPn_TX_CTRL, n=0-15 */ +#define USBHS_UEP_T_TOG_AUTO 0x20 +#define USBHS_UEP_T_TOG_MASK 0x18 +#define USBHS_UEP_T_TOG_DATA0 0x00 +#define USBHS_UEP_T_TOG_DATA1 0x08 +#define USBHS_UEP_T_TOG_DATA2 0x10 +#define USBHS_UEP_T_TOG_MDATA 0x18 +#define USBHS_UEP_T_RES_MASK 0x03 +#define USBHS_UEP_T_RES_ACK 0x00 +#define USBHS_UEP_T_RES_NYET 0x01 +#define USBHS_UEP_T_RES_NAK 0x02 +#define USBHS_UEP_T_RES_STALL 0x03 + +/* R8_UEPn_TX_CTRL, n=0-15 */ +#define USBHS_UEP_R_TOG_AUTO 0x20 +#define USBHS_UEP_R_TOG_MASK 0x18 +#define USBHS_UEP_R_TOG_DATA0 0x00 +#define USBHS_UEP_R_TOG_DATA1 0x08 +#define USBHS_UEP_R_TOG_DATA2 0x10 +#define USBHS_UEP_R_TOG_MDATA 0x18 +#define USBHS_UEP_R_RES_MASK 0x03 +#define USBHS_UEP_R_RES_ACK 0x00 +#define USBHS_UEP_R_RES_NYET 0x01 +#define USBHS_UEP_R_RES_NAK 0x02 +#define USBHS_UEP_R_RES_STALL 0x03 + +/* R8_UHOST_CTRL */ +#define USBHS_UH_SOF_EN 0x80 +#define USBHS_UH_SOF_FREE 0x40 +#define USBHS_UH_PHY_SUSPENDM 0x10 +#define USBHS_UH_REMOTE_WKUP 0x08 +#define USBHS_UH_TX_BUS_RESUME 0x04 +#define USBHS_UH_TX_BUS_SUSPEND 0x02 +#define USBHS_UH_TX_BUS_RESET 0x01 + +/* R32_UH_CONFIG */ +#define USBHS_UH_EP_RX_EN 0x00040000 +#define USBHS_UH_EP_TX_EN 0x00000008 + +/* R32_UH_EP_TYPE */ +#define USBHS_UH_EP_RX_TYPE 0x00040000 +#define USBHS_UH_EP_TX_TYPE 0x00000008 + +/* R32_UH_RX_DMA */ +#define USBHS_UH_RX_DMA 0x0000FFFC + +/* R32_UH_TX_DMA */ +#define USBHS_UH_TX_DMA 0x0000FFFF + +/* R16_UH_RX_MAX_LEN */ +#define USBHS_UH_RX_MAX_LEN 0x07FF + +/* R8_UH_EP_PID */ +#define USBHS_UH_TOKEN_MASK 0xF0 +#define USBHS_UH_ENDP_MASK 0x0F + +/* R8_UH_RX_CTRL */ +#define USBHS_UH_R_DATA_NO 0x40 +#define USBHS_UH_R_TOG_AUTO 0x20 +#define USBHS_UH_R_TOG_MASK 0x18 +#define USBHS_UH_R_TOG_DATA0 0x00 +#define USBHS_UH_R_TOG_DATA1 0x08 +#define USBHS_UH_R_TOG_DATA2 0x10 +#define USBHS_UH_R_TOG_MDATA 0x18 +#define USBHS_UH_R_RES_NO 0x04 +#define USBHS_UH_R_RES_MASK 0x03 +#define USBHS_UH_R_RES_ACK 0x00 +#define USBHS_UH_R_RES_NYET 0x01 +#define USBHS_UH_R_RES_NAK 0x02 +#define USBHS_UH_R_RES_STALL 0x03 + +/* R16_UH_TX_LEN */ +#define USBHS_UH_TX_LEN 0x07FF + +/* R8_UH_TX_CTRL */ +#define USBHS_UH_T_DATA_NO 0x40 +#define USBHS_UH_T_AUTO_TOG 0x20 +#define USBHS_UH_T_TOG_MASK 0x18 +#define USBHS_UH_T_TOG_DATA0 0x00 +#define USBHS_UH_T_TOG_DATA1 0x08 +#define USBHS_UH_T_TOG_DATA2 0x10 +#define USBHS_UH_T_TOG_MDATA 0x18 +#define USBHS_UH_T_RES_NO 0x04 +#define USBHS_UH_T_RES_MASK 0x03 +#define USBHS_UH_T_RES_ACK 0x00 +#define USBHS_UH_T_RES_NYET 0x01 +#define USBHS_UH_T_RES_NAK 0x02 +#define USBHS_UH_T_RES_STALL 0x03 + +/* R16_UH_SPLIT_DATA */ +#define USBHS_UH_SPLIT_DATA 0x0FFF + + +/*******************************************************************************/ +/* USBFS Related Register Macro Definition */ + +/* R8_USB_CTRL */ +#define USBFS_UC_HOST_MODE 0x80 +#define USBFS_UC_LOW_SPEED 0x40 +#define USBFS_UC_DEV_PU_EN 0x20 +#define USBFS_UC_SYS_CTRL_MASK 0x30 +#define USBFS_UC_SYS_CTRL0 0x00 +#define USBFS_UC_SYS_CTRL1 0x10 +#define USBFS_UC_SYS_CTRL2 0x20 +#define USBFS_UC_SYS_CTRL3 0x30 +#define USBFS_UC_INT_BUSY 0x08 +#define USBFS_UC_RESET_SIE 0x04 +#define USBFS_UC_CLR_ALL 0x02 +#define USBFS_UC_DMA_EN 0x01 + +/* R8_USB_INT_EN */ +#define USBFS_UIE_DEV_SOF 0x80 +#define USBFS_UIE_DEV_NAK 0x40 +#define USBFS_UIE_FIFO_OV 0x10 +#define USBFS_UIE_HST_SOF 0x08 +#define USBFS_UIE_SUSPEND 0x04 +#define USBFS_UIE_TRANSFER 0x02 +#define USBFS_UIE_DETECT 0x01 +#define USBFS_UIE_BUS_RST 0x01 + +/* R8_USB_DEV_AD */ +#define USBFS_UDA_GP_BIT 0x80 +#define USBFS_USB_ADDR_MASK 0x7F + +/* R8_USB_MIS_ST */ +#define USBFS_UMS_SOF_PRES 0x80 +#define USBFS_UMS_SOF_ACT 0x40 +#define USBFS_UMS_SIE_FREE 0x20 +#define USBFS_UMS_R_FIFO_RDY 0x10 +#define USBFS_UMS_BUS_RESET 0x08 +#define USBFS_UMS_SUSPEND 0x04 +#define USBFS_UMS_DM_LEVEL 0x02 +#define USBFS_UMS_DEV_ATTACH 0x01 + +/* R8_USB_INT_FG */ +#define USBFS_U_IS_NAK 0x80 // RO, indicate current USB transfer is NAK received +#define USBFS_U_TOG_OK 0x40 // RO, indicate current USB transfer toggle is OK +#define USBFS_U_SIE_FREE 0x20 // RO, indicate USB SIE free status +#define USBFS_UIF_FIFO_OV 0x10 // FIFO overflow interrupt flag for USB, direct bit address clear or write 1 to clear +#define USBFS_UIF_HST_SOF 0x08 // host SOF timer interrupt flag for USB host, direct bit address clear or write 1 to clear +#define USBFS_UIF_SUSPEND 0x04 // USB suspend or resume event interrupt flag, direct bit address clear or write 1 to clear +#define USBFS_UIF_TRANSFER 0x02 // USB transfer completion interrupt flag, direct bit address clear or write 1 to clear +#define USBFS_UIF_DETECT 0x01 // device detected event interrupt flag for USB host mode, direct bit address clear or write 1 to clear +#define USBFS_UIF_BUS_RST 0x01 // bus reset event interrupt flag for USB device mode, direct bit address clear or write 1 to clear + +/* R8_USB_INT_ST */ +#define USBFS_UIS_IS_NAK 0x80 // RO, indicate current USB transfer is NAK received for USB device mode +#define USBFS_UIS_TOG_OK 0x40 // RO, indicate current USB transfer toggle is OK +#define USBFS_UIS_TOKEN_MASK 0x30 // RO, bit mask of current token PID code received for USB device mode +#define USBFS_UIS_TOKEN_OUT 0x00 +#define USBFS_UIS_TOKEN_SOF 0x10 +#define USBFS_UIS_TOKEN_IN 0x20 +#define USBFS_UIS_TOKEN_SETUP 0x30 +// bUIS_TOKEN1 & bUIS_TOKEN0: current token PID code received for USB device mode +// 00: OUT token PID received +// 01: SOF token PID received +// 10: IN token PID received +// 11: SETUP token PID received +#define USBFS_UIS_ENDP_MASK 0x0F // RO, bit mask of current transfer endpoint number for USB device mode +#define USBFS_UIS_H_RES_MASK 0x0F // RO, bit mask of current transfer handshake response for USB host mode: 0000=no response, time out from device, others=handshake response PID received + +/* R32_USB_OTG_CR */ +#define USBFS_CR_SESS_VTH 0x20 +#define USBFS_CR_VBUS_VTH 0x10 +#define USBFS_CR_OTG_EN 0x08 +#define USBFS_CR_IDPU 0x04 +#define USBFS_CR_CHARGE_VBUS 0x02 +#define USBFS_CR_DISCHAR_VBUS 0x01 + +/* R32_USB_OTG_SR */ +#define USBFS_SR_ID_DIG 0x08 +#define USBFS_SR_SESS_END 0x04 +#define USBFS_SR_SESS_VLD 0x02 +#define USBFS_SR_VBUS_VLD 0x01 + +/* R8_UDEV_CTRL */ +#define USBFS_UD_PD_DIS 0x80 // disable USB UDP/UDM pulldown resistance: 0=enable pulldown, 1=disable +#define USBFS_UD_DP_PIN 0x20 // ReadOnly: indicate current UDP pin level +#define USBFS_UD_DM_PIN 0x10 // ReadOnly: indicate current UDM pin level +#define USBFS_UD_LOW_SPEED 0x04 // enable USB physical port low speed: 0=full speed, 1=low speed +#define USBFS_UD_GP_BIT 0x02 // general purpose bit +#define USBFS_UD_PORT_EN 0x01 // enable USB physical port I/O: 0=disable, 1=enable + +/* R8_UEP4_1_MOD */ +#define USBFS_UEP1_RX_EN 0x80 // enable USB endpoint 1 receiving (OUT) +#define USBFS_UEP1_TX_EN 0x40 // enable USB endpoint 1 transmittal (IN) +#define USBFS_UEP1_BUF_MOD 0x10 // buffer mode of USB endpoint 1 +#define USBFS_UEP4_RX_EN 0x08 // enable USB endpoint 4 receiving (OUT) +#define USBFS_UEP4_TX_EN 0x04 // enable USB endpoint 4 transmittal (IN) +#define USBFS_UEP4_BUF_MOD 0x01 + +/* R8_UEP2_3_MOD */ +#define USBFS_UEP3_RX_EN 0x80 // enable USB endpoint 3 receiving (OUT) +#define USBFS_UEP3_TX_EN 0x40 // enable USB endpoint 3 transmittal (IN) +#define USBFS_UEP3_BUF_MOD 0x10 // buffer mode of USB endpoint 3 +#define USBFS_UEP2_RX_EN 0x08 // enable USB endpoint 2 receiving (OUT) +#define USBFS_UEP2_TX_EN 0x04 // enable USB endpoint 2 transmittal (IN) +#define USBFS_UEP2_BUF_MOD 0x01 // buffer mode of USB endpoint 2 + +/* R8_UEP5_6_MOD */ +#define USBFS_UEP6_RX_EN 0x80 // enable USB endpoint 6 receiving (OUT) +#define USBFS_UEP6_TX_EN 0x40 // enable USB endpoint 6 transmittal (IN) +#define USBFS_UEP6_BUF_MOD 0x10 // buffer mode of USB endpoint 6 +#define USBFS_UEP5_RX_EN 0x08 // enable USB endpoint 5 receiving (OUT) +#define USBFS_UEP5_TX_EN 0x04 // enable USB endpoint 5 transmittal (IN) +#define USBFS_UEP5_BUF_MOD 0x01 // buffer mode of USB endpoint 5 + +/* R8_UEP7_MOD */ +#define USBFS_UEP7_RX_EN 0x08 // enable USB endpoint 7 receiving (OUT) +#define USBFS_UEP7_TX_EN 0x04 // enable USB endpoint 7 transmittal (IN) +#define USBFS_UEP7_BUF_MOD 0x01 // buffer mode of USB endpoint 7 + +/* R8_UEPn_TX_CTRL */ +#define USBFS_UEP_T_AUTO_TOG 0x08 // enable automatic toggle after successful transfer completion on endpoint 1/2/3: 0=manual toggle, 1=automatic toggle +#define USBFS_UEP_T_TOG 0x04 // prepared data toggle flag of USB endpoint X transmittal (IN): 0=DATA0, 1=DATA1 +#define USBFS_UEP_T_RES_MASK 0x03 // bit mask of handshake response type for USB endpoint X transmittal (IN) +#define USBFS_UEP_T_RES_ACK 0x00 +#define USBFS_UEP_T_RES_NONE 0x01 +#define USBFS_UEP_T_RES_NAK 0x02 +#define USBFS_UEP_T_RES_STALL 0x03 +// bUEP_T_RES1 & bUEP_T_RES0: handshake response type for USB endpoint X transmittal (IN) +// 00: DATA0 or DATA1 then expecting ACK (ready) +// 01: DATA0 or DATA1 then expecting no response, time out from host, for non-zero endpoint isochronous transactions +// 10: NAK (busy) +// 11: STALL (error) +// host aux setup + +/* R8_UEPn_RX_CTRL, n=0-7 */ +#define USBFS_UEP_R_AUTO_TOG 0x08 // enable automatic toggle after successful transfer completion on endpoint 1/2/3: 0=manual toggle, 1=automatic toggle +#define USBFS_UEP_R_TOG 0x04 // expected data toggle flag of USB endpoint X receiving (OUT): 0=DATA0, 1=DATA1 +#define USBFS_UEP_R_RES_MASK 0x03 // bit mask of handshake response type for USB endpoint X receiving (OUT) +#define USBFS_UEP_R_RES_ACK 0x00 +#define USBFS_UEP_R_RES_NONE 0x01 +#define USBFS_UEP_R_RES_NAK 0x02 +#define USBFS_UEP_R_RES_STALL 0x03 +// RB_UEP_R_RES1 & RB_UEP_R_RES0: handshake response type for USB endpoint X receiving (OUT) +// 00: ACK (ready) +// 01: no response, time out to host, for non-zero endpoint isochronous transactions +// 10: NAK (busy) +// 11: STALL (error) + +/* R8_UHOST_CTRL */ +#define USBFS_UH_PD_DIS 0x80 // disable USB UDP/UDM pulldown resistance: 0=enable pulldown, 1=disable +#define USBFS_UH_DP_PIN 0x20 // ReadOnly: indicate current UDP pin level +#define USBFS_UH_DM_PIN 0x10 // ReadOnly: indicate current UDM pin level +#define USBFS_UH_LOW_SPEED 0x04 // enable USB port low speed: 0=full speed, 1=low speed +#define USBFS_UH_BUS_RESET 0x02 // control USB bus reset: 0=normal, 1=force bus reset +#define USBFS_UH_PORT_EN 0x01 // enable USB port: 0=disable, 1=enable port, automatic disabled if USB device detached + +/* R32_UH_EP_MOD */ +#define USBFS_UH_EP_TX_EN 0x40 // enable USB host OUT endpoint transmittal +#define USBFS_UH_EP_TBUF_MOD 0x10 // buffer mode of USB host OUT endpoint +// bUH_EP_TX_EN & bUH_EP_TBUF_MOD: USB host OUT endpoint buffer mode, buffer start address is UH_TX_DMA +// 0 x: disable endpoint and disable buffer +// 1 0: 64 bytes buffer for transmittal (OUT endpoint) +// 1 1: dual 64 bytes buffer by toggle bit bUH_T_TOG selection for transmittal (OUT endpoint), total=128bytes +#define USBFS_UH_EP_RX_EN 0x08 // enable USB host IN endpoint receiving +#define USBFS_UH_EP_RBUF_MOD 0x01 // buffer mode of USB host IN endpoint +// bUH_EP_RX_EN & bUH_EP_RBUF_MOD: USB host IN endpoint buffer mode, buffer start address is UH_RX_DMA +// 0 x: disable endpoint and disable buffer +// 1 0: 64 bytes buffer for receiving (IN endpoint) +// 1 1: dual 64 bytes buffer by toggle bit bUH_R_TOG selection for receiving (IN endpoint), total=128bytes + +/* R16_UH_SETUP */ +#define USBFS_UH_PRE_PID_EN 0x0400 // USB host PRE PID enable for low speed device via hub +#define USBFS_UH_SOF_EN 0x0004 // USB host automatic SOF enable + +/* R8_UH_EP_PID */ +#define USBFS_UH_TOKEN_MASK 0xF0 // bit mask of token PID for USB host transfer +#define USBFS_UH_ENDP_MASK 0x0F // bit mask of endpoint number for USB host transfer + +/* R8_UH_RX_CTRL */ +#define USBFS_UH_R_AUTO_TOG 0x08 // enable automatic toggle after successful transfer completion: 0=manual toggle, 1=automatic toggle +#define USBFS_UH_R_TOG 0x04 // expected data toggle flag of host receiving (IN): 0=DATA0, 1=DATA1 +#define USBFS_UH_R_RES 0x01 // prepared handshake response type for host receiving (IN): 0=ACK (ready), 1=no response, time out to device, for isochronous transactions + +/* R8_UH_TX_CTRL */ +#define USBFS_UH_T_AUTO_TOG 0x08 // enable automatic toggle after successful transfer completion: 0=manual toggle, 1=automatic toggle +#define USBFS_UH_T_TOG 0x04 // prepared data toggle flag of host transmittal (SETUP/OUT): 0=DATA0, 1=DATA1 +#define USBFS_UH_T_RES 0x01 // expected handshake response type for host transmittal (SETUP/OUT): 0=ACK (ready), 1=no response, time out from device, for isochronous transactions + + +/*******************************************************************************/ +/* Struct Definition */ + +/* USB Setup Request */ +typedef struct __attribute__((packed)) _USB_SETUP_REQ +{ + uint8_t bRequestType; + uint8_t bRequest; + uint16_t wValue; + uint16_t wIndex; + uint16_t wLength; +} USB_SETUP_REQ, *PUSB_SETUP_REQ; + +/* USB Device Descriptor */ +typedef struct __attribute__((packed)) _USB_DEVICE_DESCR +{ + uint8_t bLength; + uint8_t bDescriptorType; + uint16_t bcdUSB; + uint8_t bDeviceClass; + uint8_t bDeviceSubClass; + uint8_t bDeviceProtocol; + uint8_t bMaxPacketSize0; + uint16_t idVendor; + uint16_t idProduct; + uint16_t bcdDevice; + uint8_t iManufacturer; + uint8_t iProduct; + uint8_t iSerialNumber; + uint8_t bNumConfigurations; +} USB_DEV_DESCR, *PUSB_DEV_DESCR; + +/* USB Configuration Descriptor */ +typedef struct __attribute__((packed)) _USB_CONFIG_DESCR +{ + uint8_t bLength; + uint8_t bDescriptorType; + uint16_t wTotalLength; + uint8_t bNumInterfaces; + uint8_t bConfigurationValue; + uint8_t iConfiguration; + uint8_t bmAttributes; + uint8_t MaxPower; +} USB_CFG_DESCR, *PUSB_CFG_DESCR; + +/* USB Interface Descriptor */ +typedef struct __attribute__((packed)) _USB_INTERF_DESCR +{ + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bInterfaceNumber; + uint8_t bAlternateSetting; + uint8_t bNumEndpoints; + uint8_t bInterfaceClass; + uint8_t bInterfaceSubClass; + uint8_t bInterfaceProtocol; + uint8_t iInterface; +} USB_ITF_DESCR, *PUSB_ITF_DESCR; + +/* USB Endpoint Descriptor */ +typedef struct __attribute__((packed)) _USB_ENDPOINT_DESCR +{ + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bEndpointAddress; + uint8_t bmAttributes; + uint8_t wMaxPacketSizeL; + uint8_t wMaxPacketSizeH; + uint8_t bInterval; +} USB_ENDP_DESCR, *PUSB_ENDP_DESCR; + +/* USB Configuration Descriptor Set */ +typedef struct __attribute__((packed)) _USB_CONFIG_DESCR_LONG +{ + USB_CFG_DESCR cfg_descr; + USB_ITF_DESCR itf_descr; + USB_ENDP_DESCR endp_descr[ 1 ]; +} USB_CFG_DESCR_LONG, *PUSB_CFG_DESCR_LONG; + +/* USB HUB Descriptor */ +typedef struct __attribute__((packed)) _USB_HUB_DESCR +{ + uint8_t bDescLength; + uint8_t bDescriptorType; + uint8_t bNbrPorts; + uint8_t wHubCharacteristicsL; + uint8_t wHubCharacteristicsH; + uint8_t bPwrOn2PwrGood; + uint8_t bHubContrCurrent; + uint8_t DeviceRemovable; + uint8_t PortPwrCtrlMask; +} USB_HUB_DESCR, *PUSB_HUB_DESCR; + +/* USB HID Descriptor */ +typedef struct __attribute__((packed)) _USB_HID_DESCR +{ + uint8_t bLength; + uint8_t bDescriptorType; + uint16_t bcdHID; + uint8_t bCountryCode; + uint8_t bNumDescriptors; + uint8_t bDescriptorTypeX; + uint8_t wDescriptorLengthL; + uint8_t wDescriptorLengthH; +} USB_HID_DESCR, *PUSB_HID_DESCR; + +/* USB UDisk */ +typedef struct __attribute__((packed)) _UDISK_BOC_CBW +{ + uint32_t mCBW_Sig; + uint32_t mCBW_Tag; + uint32_t mCBW_DataLen; + uint8_t mCBW_Flag; + uint8_t mCBW_LUN; + uint8_t mCBW_CB_Len; + uint8_t mCBW_CB_Buf[ 16 ]; +} UDISK_BOC_CBW, *PXUDISK_BOC_CBW; + +/* USB UDisk */ +typedef struct __attribute__((packed)) _UDISK_BOC_CSW +{ + uint32_t mCBW_Sig; + uint32_t mCBW_Tag; + uint32_t mCSW_Residue; + uint8_t mCSW_Status; +} UDISK_BOC_CSW, *PXUDISK_BOC_CSW; + + +#ifdef __cplusplus +} +#endif + +#endif /* __CH32V30x_USB_H */ diff --git a/Ubiquitous/XiZi_IIoT/board/ch32v307vct6/third_party_driver/usb/usb_drv/inc/ch32v30x_usbhs_host.h b/Ubiquitous/XiZi_IIoT/board/ch32v307vct6/third_party_driver/usb/usb_drv/inc/ch32v30x_usbhs_host.h new file mode 100644 index 000000000..f7060ba9a --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/ch32v307vct6/third_party_driver/usb/usb_drv/inc/ch32v30x_usbhs_host.h @@ -0,0 +1,114 @@ +/********************************** (C) COPYRIGHT ******************************* +* File Name : ch32v30x_usbhs_host.h +* Author : WCH +* Version : V1.0.0 +* Date : 2021/06/06 +* Description : This file contains all the functions prototypes for the USB +* Host firmware library. +********************************************************************************* +* 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 __CH32V30x_USBHS_HOST_H +#define __CH32V30x_USBHS_HOST_H + +#ifdef __cplusplus +extern "C" { +#endif + +/*******************************************************************************/ +/* Header Files */ +#include "ch32v30x.h" +#include "ch32v30x_usb.h" + +/*******************************************************************************/ +/* USB Setup Request Macro Definition */ +#define pUSBHS_SetupRequest ( (PUSB_SETUP_REQ)USBHS_TX_Buf ) + +/*******************************************************************************/ +/* Constant Definition */ +#ifndef DEF_GET_USB_DEV_DESC +#define DEF_GET_USB_DEV_DESC +/* Get Device Descriptor Command Packet */ +__attribute__((aligned(4))) static const uint8_t SetupGetDevDesc[ ] = +{ + USB_REQ_TYP_IN, USB_GET_DESCRIPTOR, 0x00, USB_DESCR_TYP_DEVICE, 0x00, 0x00, sizeof( USB_DEV_DESCR ), 0x00 +}; + +/* Get Configuration Descriptor Command Packet */ +__attribute__((aligned(4))) static const uint8_t SetupGetCfgDesc[ ] = +{ + USB_REQ_TYP_IN, USB_GET_DESCRIPTOR, 0x00, USB_DESCR_TYP_CONFIG, 0x00, 0x00, 0x04, 0x00 +}; + +/* Get String Descriptor Command Packet */ +__attribute__((aligned(4))) static const uint8_t SetupGetStrDesc[ ] = +{ + USB_REQ_TYP_IN, USB_GET_DESCRIPTOR, 0x00, USB_DESCR_TYP_STRING, 0x09, 0x04, 0x04, 0x00 +}; + +/* Set USB Address Command Packet */ +__attribute__((aligned(4))) static const uint8_t SetupSetAddr[ ] = +{ + USB_REQ_TYP_OUT, USB_SET_ADDRESS, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +/* Set USB Configuration Command Packet */ +__attribute__((aligned(4))) static const uint8_t SetupSetConfig[ ] = +{ + USB_REQ_TYP_OUT, USB_SET_CONFIGURATION, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +/* Clear Endpoint STALL Command Packet */ +__attribute__((aligned(4))) static const uint8_t SetupClearEndpStall[ ] = +{ + USB_REQ_TYP_OUT | USB_REQ_RECIP_ENDP, USB_CLEAR_FEATURE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +/* Set Device Interface Command Packet */ +__attribute__((aligned(4))) static const uint8_t SetupSetInterface[ ] = +{ + USB_REQ_RECIP_INTERF, USB_SET_INTERFACE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; +#endif + +/*******************************************************************************/ +/* Variable Declaration */ +extern __attribute__((aligned(4))) uint8_t RxBuffer[ MAX_PACKET_SIZE ]; +extern __attribute__((aligned(4))) uint8_t TxBuffer[ MAX_PACKET_SIZE ]; + +#define USBHS_RX_Buf RxBuffer +#define USBHS_TX_Buf TxBuffer + +/*******************************************************************************/ +/* Function Declaration */ +extern void USBHS_RCC_Init( void ); +extern void USBHS_Host_Init( FunctionalState sta ); +extern uint8_t USBHSH_CheckRootHubPortStatus( uint8_t status ); +extern uint8_t USBHSH_CheckRootHubPortEnable( void ); +extern uint8_t USBHSH_CheckRootHubPortSpeed( void ); +extern void USBHSH_SetSelfAddr( uint8_t addr ); +extern void USBHSH_SetSelfSpeed( uint8_t speed ); +extern void USBHSH_ResetRootHubPort( uint8_t mode ); +extern uint8_t USBHSH_EnableRootHubPort( uint8_t *pspeed ); +extern uint8_t USBHSH_Transact( uint8_t endp_pid, uint8_t endp_tog, uint32_t timeout ); +extern uint8_t USBHSH_CtrlTransfer( uint8_t ep0_size, uint8_t *pbuf, uint16_t *plen ); +extern uint8_t USBHSH_GetDeviceDescr( uint8_t *pep0_size, uint8_t *pbuf ); +extern uint8_t USBHSH_GetConfigDescr( uint8_t ep0_size, uint8_t *pbuf, uint16_t buf_len, uint16_t *pcfg_len ); +extern uint8_t USBHSH_GetStrDescr( uint8_t ep0_size, uint8_t str_num, uint8_t *pbuf ); +extern uint8_t USBHSH_SetUsbAddress( uint8_t ep0_size, uint8_t addr ); +extern uint8_t USBHSH_SetUsbConfig( uint8_t ep0_size, uint8_t cfg_val ); +extern uint8_t USBHSH_ClearEndpStall( uint8_t ep0_size, uint8_t endp_num ); +extern uint8_t USBHSH_GetEndpData( uint8_t endp_num, uint8_t *pendp_tog, uint8_t *pbuf, uint16_t *plen ); +extern uint8_t USBHSH_SendEndpData( uint8_t endp_num, uint8_t *pendp_tog, uint8_t *pbuf, uint16_t len ); + + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/Ubiquitous/XiZi_IIoT/board/ch32v307vct6/third_party_driver/usb/usb_drv/inc/usb_host_config.h b/Ubiquitous/XiZi_IIoT/board/ch32v307vct6/third_party_driver/usb/usb_drv/inc/usb_host_config.h new file mode 100644 index 000000000..6e99c702a --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/ch32v307vct6/third_party_driver/usb/usb_drv/inc/usb_host_config.h @@ -0,0 +1,174 @@ +/********************************** (C) COPYRIGHT ******************************* + * File Name : usb_host_config.h + * Author : WCH + * Version : V1.0.0 + * Date : 2022/08/29 + * 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 __USB_HOST_CONFIG_H +#define __USB_HOST_CONFIG_H + +#ifdef __cplusplus +extern "C" { +#endif + +/******************************************************************************/ +/* Header File */ +#include "string.h" +#include "debug.h" +#include "ch32v30x_usb.h" +#include "ch32v30x_usbhs_host.h" + +/******************************************************************************/ +/* USB Host Communication Related Macro Definition */ + +/* USB Host Port General Control */ +/* CH32V303x, Support USBFS Host/Slave Only */ +/* CH32V305FB, Support USBHS Host/Slave Only */ +/* CH32V305RB, CH32V307, Support USBHS/USBFS Host/Slave */ +#define DEF_TOTAL_ROOT_HUB 2 +#define DEF_USB_PORT_FS_EN 0 +#define DEF_USB_PORT_HS_EN 1 +#define DEF_USB_PORT_FS 0x00 +#define DEF_USB_PORT_HS 0x01 + +/* USB Root Device Status */ +#define ROOT_DEV_DISCONNECT 0 +#define ROOT_DEV_CONNECTED 1 +#define ROOT_DEV_FAILED 2 +#define ROOT_DEV_SUCCESS 3 + +/* USB Device Address */ +#define USB_DEVICE_ADDR 0x02 + +/* USB Speed */ +#define USB_LOW_SPEED 0x00 +#define USB_FULL_SPEED 0x01 +#define USB_HIGH_SPEED 0x02 +#define USB_SPEED_CHECK_ERR 0xFF + +/* Configuration Descriptor Type */ +#define DEF_DECR_CONFIG 0x02 +#define DEF_DECR_INTERFACE 0x04 +#define DEF_DECR_ENDPOINT 0x05 +#define DEF_DECR_HID 0x21 + +/* USB Communication Status Code */ +#define ERR_SUCCESS 0x00 +#define ERR_USB_CONNECT 0x15 +#define ERR_USB_DISCON 0x16 +#define ERR_USB_BUF_OVER 0x17 +#define ERR_USB_DISK_ERR 0x1F +#define ERR_USB_TRANSFER 0x20 +#define ERR_USB_UNSUPPORT 0xFB +#define ERR_USB_UNAVAILABLE 0xFC +#define ERR_USB_UNKNOWN 0xFE + +/* USB Device Enumeration Status Code */ +#define DEF_DEV_DESCR_GETFAIL 0x45 +#define DEF_DEV_ADDR_SETFAIL 0x46 +#define DEF_CFG_DESCR_GETFAIL 0x47 +#define DEF_REP_DESCR_GETFAIL 0x48 +#define DEF_DEV_TYPE_UNKNOWN 0xFF + +/* USB Communication Time */ +#define DEF_BUS_RESET_TIME 11 // USB bus reset time +#define DEF_RE_ATTACH_TIMEOUT 100 // Wait for the USB device to reconnect after reset, 100mS timeout +#define DEF_WAIT_USB_TOUT_200US 1000 +#define DEF_CTRL_TRANS_TIMEOVER_CNT 60000 // Control transmission delay timing + +/* General */ +#define DEF_ONE_USB_SUP_DEV_TOTAL 1 +#define DEF_NEXT_HUB_PORT_NUM_MAX 4 +#define DEF_INTERFACE_NUM_MAX 4 +#define DEF_COM_BUF_LEN 255 + +/* Debug */ +#define DEF_DEBUG_PRINTF 1 +#if ( DEF_DEBUG_PRINTF == 1 ) +#define DUG_PRINTF( format, arg... ) printf( format, ##arg ) +#else +#define DUG_PRINTF( format, arg... ) do{ if( 0 )printf( format, ##arg ); }while( 0 ); +#endif + +/* HUB Port Device */ +typedef struct _HUB_DEVICE +{ + uint8_t bStatus; + uint8_t bType; + uint8_t bAddress; + uint8_t bSpeed; + uint8_t bEp0MaxPks; + uint8_t DeviceIndex; +}HUB_DEVICE, *PHUB_DEVICE; + +/* Root HUB Device Structure, Physical Interface */ +typedef struct _ROOT_HUB_DEVICE +{ + uint8_t bStatus; + uint8_t bType; + uint8_t bAddress; + uint8_t bSpeed; + uint8_t bEp0MaxPks; + uint8_t DeviceIndex; + uint8_t bPortNum; + HUB_DEVICE Device[ DEF_NEXT_HUB_PORT_NUM_MAX ]; +} ROOT_HUB_DEVICE, *PROOT_HUB_DEVICE; + +/* USB Host Control Structure */ +struct __HOST_CTL +{ + uint8_t InterfaceNum; + uint8_t ErrorCount; + + struct interface + { + uint8_t Type; + uint16_t HidDescLen; + uint8_t HidReportID; + uint8_t Full_KB_Flag; + + uint8_t InEndpNum; + uint8_t InEndpAddr[ 4 ]; + uint8_t InEndpType[ 4 ]; + uint16_t InEndpSize[ 4 ]; + uint8_t InEndpTog[ 4 ]; + uint8_t InEndpInterval[ 4 ]; + uint8_t InEndpTimeCount[ 4 ]; + + uint8_t OutEndpNum; + uint8_t OutEndpAddr[ 4 ]; + uint8_t OutEndpType[ 4 ]; + uint16_t OutEndpSize[ 4 ]; + uint8_t OutEndpTog[ 4 ]; + + uint8_t IDFlag; + uint8_t ReportID; + + uint8_t LED_Usage_Min; + uint8_t LED_Usage_Max; + + uint8_t SetReport_Swi; + uint8_t SetReport_Value; + uint8_t SetReport_Flag; + + }Interface[ DEF_INTERFACE_NUM_MAX ]; +}; + +/*******************************************************************************/ +/* Variable Declaration */ +extern uint8_t DevDesc_Buf[ ]; +extern uint8_t Com_Buf[ ]; +extern struct _ROOT_HUB_DEVICE RootHubDev[ ]; +extern struct __HOST_CTL HostCtl[ ]; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Ubiquitous/XiZi_IIoT/board/ch32v307vct6/third_party_driver/usb/usb_drv/src/CH32V103UFI.c b/Ubiquitous/XiZi_IIoT/board/ch32v307vct6/third_party_driver/usb/usb_drv/src/CH32V103UFI.c new file mode 100644 index 000000000..b806a4466 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/ch32v307vct6/third_party_driver/usb/usb_drv/src/CH32V103UFI.c @@ -0,0 +1,528 @@ +/* 2014.09.09 +***************************************** +** Copyright (C) W.ch 1999-2019 ** +** Web: http://wch.cn ** +***************************************** +** USB-flash File Interface for CHRV3 ** +** KEIL423, gcc 8.20 ** +***************************************** +*/ +/* CHRV3 U盘主机文件系统接口, 支持: FAT12/FAT16/FAT32 */ + +//#define DISK_BASE_BUF_LEN 512 /* 默认的磁盘数据缓冲区大小为512字节(可以选择为2048甚至4096以支持某些大扇区的U盘),为0则禁止在本文件中定义缓冲区并由应用程序在pDISK_BASE_BUF中指定 */ +/* 如果需要复用磁盘数据缓冲区以节约RAM,那么可将DISK_BASE_BUF_LEN定义为0以禁止在本文件中定义缓冲区,而由应用程序在调用CHRV3LibInit之前将与其它程序合用的缓冲区起始地址置入pDISK_BASE_BUF变量 */ + +//#define NO_DEFAULT_ACCESS_SECTOR 1 /* 禁止默认的磁盘扇区读写子程序,下面用自行编写的程序代替它 */ +//#define NO_DEFAULT_DISK_CONNECT 1 /* 禁止默认的检查磁盘连接子程序,下面用自行编写的程序代替它 */ +//#define NO_DEFAULT_FILE_ENUMER 1 /* 禁止默认的文件名枚举回调程序,下面用自行编写的程序代替它 */ +//#include "CHRV3SFR.H" + +#include "debug.h" +#include "ch32v30x.h" +#include "usb_host_config.h" +#include "CHRV3UFI.h" + +uint8_t USBHostTransact( uint8_t endp_pid, uint8_t tog, uint32_t timeout ) +{ +#if DEF_USB_PORT_FS_EN + uint8_t r, trans_rerty; + uint16_t i; + USBOTG_H_FS->HOST_TX_CTRL = USBOTG_H_FS->HOST_RX_CTRL = 0; + if( tog & 0x80 ) + { + USBOTG_H_FS->HOST_RX_CTRL = 1<<2; + } + if( tog & 0x40 ) + { + USBOTG_H_FS->HOST_TX_CTRL = 1<<2; + } + trans_rerty = 0; + do + { + USBOTG_H_FS->HOST_EP_PID = endp_pid; // Specify token PID and endpoint number + USBOTG_H_FS->INT_FG = USBFS_UIF_TRANSFER; // Allow transmission + for( i = DEF_WAIT_USB_TOUT_200US; ( i != 0 ) && ( ( USBOTG_H_FS->INT_FG & USBFS_UIF_TRANSFER ) == 0 ); i-- ) + { + Delay_Us( 1 ); + } + USBOTG_H_FS->HOST_EP_PID = 0x00; // Stop USB transfer + if( ( USBOTG_H_FS->INT_FG & USBFS_UIF_TRANSFER ) == 0 ) + { + return ERR_USB_UNKNOWN; + } + else + { + /* Complete transfer */ + if( USBOTG_H_FS->INT_ST & USBFS_UIS_TOG_OK ) + { + return ERR_SUCCESS; + } + r = USBOTG_H_FS->INT_ST & USBFS_UIS_H_RES_MASK; // USB device answer status + if( r == USB_PID_STALL ) + { + return ( r | ERR_USB_TRANSFER ); + } + if( r == USB_PID_NAK ) + { + if( timeout == 0 ) + { + return ( r | ERR_USB_TRANSFER ); + } + if( timeout < 0xFFFF ) + { + timeout--; + } + --trans_rerty; + } + else switch ( endp_pid >> 4 ) + { + case USB_PID_SETUP: + case USB_PID_OUT: + if( r ) + { + return ( r | ERR_USB_TRANSFER ); + } + break; + case USB_PID_IN: + if( ( r == USB_PID_DATA0 ) && ( r == USB_PID_DATA1 ) ) + { + ; + } + else if( r ) + { + return ( r | ERR_USB_TRANSFER ); + } + break; + default: + return ERR_USB_UNKNOWN; + } + } + Delay_Us( 15 ); + if( USBOTG_H_FS->INT_FG & USBFS_UIF_DETECT ) + { + Delay_Us( 200 ); + if( USBFSH_CheckRootHubPortEnable( ) == 0 ) + { + return ERR_USB_DISCON; // USB device disconnect event + } + } + }while( ++trans_rerty < 10 ); + + return ERR_USB_TRANSFER; // Reply timeout +#elif DEF_USB_PORT_HS_EN + uint8_t r, trans_retry; + uint16_t i; + USBHSH->HOST_TX_CTRL = USBHSH->HOST_RX_CTRL = 0; + if( tog & 0x80 ) + { + USBHSH->HOST_RX_CTRL = 1<<3; + } + if( tog & 0x40 ) + { + USBHSH->HOST_TX_CTRL = 1<<3; + } + trans_retry = 0; + do + { + USBHSH->HOST_EP_PID = endp_pid; // Set the token for the host to send the packet + USBHSH->INT_FG = USBHS_UIF_TRANSFER; + for( i = DEF_WAIT_USB_TOUT_200US; ( i != 0 ) && ( ( USBHSH->INT_FG & USBHS_UIF_TRANSFER ) == 0 ); i-- ) + { + Delay_Us( 1 ); + } + USBHSH->HOST_EP_PID = 0x00; + if( ( USBHSH->INT_FG & USBHS_UIF_TRANSFER ) == 0 ) + { + return ERR_USB_UNKNOWN; + } + + if( USBHSH->INT_FG & USBHS_UIF_DETECT ) + { + USBHSH->INT_FG = USBHS_UIF_DETECT; + Delay_Us( 200 ); + if( USBHSH->MIS_ST & USBHS_UIF_TRANSFER ) + { + if( USBHSH->HOST_CTRL & USBHS_UH_SOF_EN ) + { + return ERR_USB_CONNECT; + } + } + else + { + return ERR_USB_DISCON; + } + } + else if( USBHSH->INT_FG & USBHS_UIF_TRANSFER ) // The packet transmission was successful + { + r = USBHSH->INT_ST & USBHS_UIS_H_RES_MASK; + if( ( endp_pid >> 4 ) == USB_PID_IN ) + { + if( USBHSH->INT_ST & USBHS_UIS_TOG_OK ) + { + return ERR_SUCCESS; // Packet token match + } + } + else + { + if( ( r == USB_PID_ACK ) || ( r == USB_PID_NYET ) ) + { + return ERR_SUCCESS; + } + } + if( r == USB_PID_STALL ) + { + return ( r | ERR_USB_TRANSFER ); + } + + if( r == USB_PID_NAK ) + { + if( timeout == 0 ) + { + return ( r | ERR_USB_TRANSFER ); + } + if( timeout < 0xFFFF ) + { + timeout--; + } + --trans_retry; + } + else switch( endp_pid >> 4 ) + { + case USB_PID_SETUP: + + case USB_PID_OUT: + if( r ) + { + return ( r | ERR_USB_TRANSFER ); + } + break; + case USB_PID_IN: + if( ( r == USB_PID_DATA0 ) || ( r == USB_PID_DATA1 ) ) + { + ; + } + else if( r ) + { + return ( r | ERR_USB_TRANSFER ); + } + break; + default: + return ERR_USB_UNKNOWN; + } + } + else + { + USBHSH->INT_FG = USBHS_UIF_DETECT | USBHS_UIF_TRANSFER | USBHS_UIF_SUSPEND | USBHS_UIF_HST_SOF | USBHS_UIF_FIFO_OV | USBHS_UIF_SETUP_ACT; + } + Delay_Us( 15 ); + } while( ++trans_retry < 10 ); + + return ERR_USB_TRANSFER; +#endif +} + +uint8_t HostCtrlTransfer( uint8_t *DataBuf, uint8_t *RetLen ) +{ + uint8_t ret; + uint16_t retlen; + retlen = (uint16_t)(*RetLen); +#if DEF_USB_PORT_FS_EN + ret = USBFSH_CtrlTransfer( RootHubDev[ DEF_USB_PORT_HS ].bEp0MaxPks, DataBuf, &retlen ); +#elif DEF_USB_PORT_HS_EN + ret = USBHSH_CtrlTransfer( RootHubDev[ DEF_USB_PORT_HS ].bEp0MaxPks, DataBuf, &retlen ); +#endif + return ret; +} + +void CopySetupReqPkg( const char * pReqPkt ) +{ + uint8_t i; + for(i = 0; i != sizeof(USB_SETUP_REQ); i++) + { +#if DEF_USB_PORT_FS_EN + ((char *)pUSBFS_SetupRequest)[i] = *pReqPkt; +#elif DEF_USB_PORT_HS_EN + ((char *)pUSBHS_SetupRequest)[i] = *pReqPkt; +#endif + pReqPkt++; + } +} + +uint8_t CtrlGetDeviceDescrTB( void ) +{ + uint8_t ret; +#if DEF_USB_PORT_FS_EN + ret = USBFSH_GetDeviceDescr( &RootHubDev[ DEF_USB_PORT_HS ].bEp0MaxPks, TxBuffer ); +#elif DEF_USB_PORT_HS_EN + ret = USBHSH_GetDeviceDescr( &RootHubDev[ DEF_USB_PORT_HS ].bEp0MaxPks, TxBuffer ); +#endif + return ret; +} + +uint8_t CtrlGetConfigDescrTB( void ) +{ + uint16_t len; + uint8_t ret; +#if DEF_USB_PORT_FS_EN + ret = USBFSH_GetConfigDescr( RootHubDev[ DEF_USB_PORT_HS ].bEp0MaxPks, TxBuffer, 256, &len ); +#elif DEF_USB_PORT_HS_EN + ret = USBHSH_GetConfigDescr( RootHubDev[ DEF_USB_PORT_HS ].bEp0MaxPks, TxBuffer, 256, &len ); +#endif + return ret; +} + +uint8_t CtrlSetUsbConfig( uint8_t cfg ) +{ + uint8_t ret; +#if DEF_USB_PORT_FS_EN + ret = USBFSH_SetUsbConfig( RootHubDev[ DEF_USB_PORT_HS ].bEp0MaxPks, cfg ); +#elif DEF_USB_PORT_HS_EN + ret = USBHSH_SetUsbConfig( RootHubDev[ DEF_USB_PORT_HS ].bEp0MaxPks, cfg ); +#endif + return ret; +} + +uint8_t CtrlSetUsbAddress( uint8_t addr ) +{ + uint8_t ret; +#if DEF_USB_PORT_FS_EN + ret = USBFSH_SetUsbAddress( RootHubDev[ DEF_USB_PORT_HS ].bEp0MaxPks, addr ); +#elif DEF_USB_PORT_HS_EN + ret = USBHSH_SetUsbAddress( RootHubDev[ DEF_USB_PORT_HS ].bEp0MaxPks, addr ); +#endif + return ret; +} + +uint8_t CtrlClearEndpStall( uint8_t endp ) +{ + uint8_t ret; +#if DEF_USB_PORT_FS_EN + ret = USBFSH_ClearEndpStall( RootHubDev[ DEF_USB_PORT_HS ].bEp0MaxPks, endp ); +#elif DEF_USB_PORT_HS_EN + ret = USBHSH_ClearEndpStall( RootHubDev[ DEF_USB_PORT_HS ].bEp0MaxPks, endp ); +#endif + return ret; +} + +#ifndef FOR_ROOT_UDISK_ONLY +uint8_t CtrlGetHubDescr( void ) +{ + +} + +uint8_t HubGetPortStatus( uint8_t HubPortIndex ) +{ + +} + +uint8_t HubSetPortFeature( uint8_t HubPortIndex, uint8_t FeatureSelt ) +{ + +} + +uint8_t HubClearPortFeature( uint8_t HubPortIndex, uint8_t FeatureSelt ) +{ + +} +#endif + +CMD_PARAM_I mCmdParam; /* 命令参数 */ +#if DISK_BASE_BUF_LEN > 0 +//uint8_t DISK_BASE_BUF[ DISK_BASE_BUF_LEN ] __attribute__((at(BA_RAM+SZ_RAM/2))); /* 外部RAM的磁盘数据缓冲区,缓冲区长度为一个扇区的长度 */ +uint8_t DISK_BASE_BUF[ DISK_BASE_BUF_LEN ] __attribute__((aligned (4))); /* 外部RAM的磁盘数据缓冲区,缓冲区长度为一个扇区的长度 */ +//UINT8 DISK_FAT_BUF[ DISK_BASE_BUF_LEN ] __attribute__((aligned (4))); /* 外部RAM的磁盘FAT数据缓冲区,缓冲区长度为一个扇区的长度 */ +#endif + +/* 以下程序可以根据需要修改 */ + +#ifndef NO_DEFAULT_ACCESS_SECTOR /* 在应用程序中定义NO_DEFAULT_ACCESS_SECTOR可以禁止默认的磁盘扇区读写子程序,然后用自行编写的程序代替它 */ +//if ( use_external_interface ) { // 替换U盘扇区底层读写子程序 +// CHRV3vSectorSize=512; // 设置实际的扇区大小,必须是512的倍数,该值是磁盘的扇区大小 +// CHRV3vSectorSizeB=9; // 设置实际的扇区大小的位移数,512则对应9,1024对应10,2048对应11 +// CHRV3DiskStatus=DISK_MOUNTED; // 强制块设备连接成功(只差分析文件系统) +//} + +uint8_t CHRV3ReadSector( uint8_t SectCount, uint8_t *DataBuf ) /* 从磁盘读取多个扇区的数据到缓冲区中 */ +{ + uint8_t retry; +// if ( use_external_interface ) return( extReadSector( CHRV3vLbaCurrent, SectCount, DataBuf ) ); /* 外部接口 */ + for( retry = 0; retry < 3; retry ++ ) { /* 错误重试 */ + pCBW -> mCBW_DataLen = (uint32_t)SectCount << CHRV3vSectorSizeB; /* 数据传输长度 */ + pCBW -> mCBW_Flag = 0x80; + pCBW -> mCBW_LUN = CHRV3vCurrentLun; + pCBW -> mCBW_CB_Len = 10; + pCBW -> mCBW_CB_Buf[ 0 ] = SPC_CMD_READ10; + pCBW -> mCBW_CB_Buf[ 1 ] = 0x00; + pCBW -> mCBW_CB_Buf[ 2 ] = (uint8_t)( CHRV3vLbaCurrent >> 24 ); + pCBW -> mCBW_CB_Buf[ 3 ] = (uint8_t)( CHRV3vLbaCurrent >> 16 ); + pCBW -> mCBW_CB_Buf[ 4 ] = (uint8_t)( CHRV3vLbaCurrent >> 8 ); + pCBW -> mCBW_CB_Buf[ 5 ] = (uint8_t)( CHRV3vLbaCurrent ); + pCBW -> mCBW_CB_Buf[ 6 ] = 0x00; + pCBW -> mCBW_CB_Buf[ 7 ] = 0x00; + pCBW -> mCBW_CB_Buf[ 8 ] = SectCount; + pCBW -> mCBW_CB_Buf[ 9 ] = 0x00; + CHRV3BulkOnlyCmd( DataBuf ); /* 执行基于BulkOnly协议的命令 */ + if ( CHRV3IntStatus == ERR_SUCCESS ) { + return( ERR_SUCCESS ); + } + CHRV3IntStatus = CHRV3AnalyzeError( retry ); + if ( CHRV3IntStatus != ERR_SUCCESS ) { + return( CHRV3IntStatus ); + } + } + return( CHRV3IntStatus = ERR_USB_DISK_ERR ); /* 磁盘操作错误 */ +} + +#ifdef EN_DISK_WRITE +uint8_t CHRV3WriteSector( uint8_t SectCount, uint8_t *DataBuf ) /* 将缓冲区中的多个扇区的数据块写入磁盘 */ +{ + uint8_t retry; +// if ( use_external_interface ) return( extWriteSector( CHRV3vLbaCurrent, SectCount, DataBuf ) ); /* 外部接口 */ + for( retry = 0; retry < 3; retry ++ ) { /* 错误重试 */ + pCBW -> mCBW_DataLen = (uint32_t)SectCount << CHRV3vSectorSizeB; /* 数据传输长度 */ + pCBW -> mCBW_Flag = 0x00; + pCBW -> mCBW_LUN = CHRV3vCurrentLun; + pCBW -> mCBW_CB_Len = 10; + pCBW -> mCBW_CB_Buf[ 0 ] = SPC_CMD_WRITE10; + pCBW -> mCBW_CB_Buf[ 1 ] = 0x00; + pCBW -> mCBW_CB_Buf[ 2 ] = (uint8_t)( CHRV3vLbaCurrent >> 24 ); + pCBW -> mCBW_CB_Buf[ 3 ] = (uint8_t)( CHRV3vLbaCurrent >> 16 ); + pCBW -> mCBW_CB_Buf[ 4 ] = (uint8_t)( CHRV3vLbaCurrent >> 8 ); + pCBW -> mCBW_CB_Buf[ 5 ] = (uint8_t)( CHRV3vLbaCurrent ); + pCBW -> mCBW_CB_Buf[ 6 ] = 0x00; + pCBW -> mCBW_CB_Buf[ 7 ] = 0x00; + pCBW -> mCBW_CB_Buf[ 8 ] = SectCount; + pCBW -> mCBW_CB_Buf[ 9 ] = 0x00; + CHRV3BulkOnlyCmd( DataBuf ); /* 执行基于BulkOnly协议的命令 */ + if ( CHRV3IntStatus == ERR_SUCCESS ) { + Delay_Us( 200 ); /* 写操作后延时 */ + return( ERR_SUCCESS ); + } + CHRV3IntStatus = CHRV3AnalyzeError( retry ); + if ( CHRV3IntStatus != ERR_SUCCESS ) { + return( CHRV3IntStatus ); + } + } + return( CHRV3IntStatus = ERR_USB_DISK_ERR ); /* 磁盘操作错误 */ +} +#endif +#endif // NO_DEFAULT_ACCESS_SECTOR + +#ifndef NO_DEFAULT_DISK_CONNECT /* 在应用程序中定义NO_DEFAULT_DISK_CONNECT可以禁止默认的检查磁盘连接子程序,然后用自行编写的程序代替它 */ + +/* +约定: USB设备地址分配规则(参考USB_DEVICE_ADDR) +地址值 设备位置 +0x02 内置Root-HUB0下的USB设备或外部HUB +0x03 内置Root-HUB1下的USB设备或外部HUB +0x1x 内置Root-HUB0下的外部HUB的端口x下的USB设备,x为1~n +0x2x 内置Root-HUB1下的外部HUB的端口x下的USB设备,x为1~n +*/ + +#define UHUB_DEV_ADDR (USBHSH->DEV_AD) +#define UHUB_MIS_STAT (USBHSH->MIS_ST) +#define UHUB_HOST_CTRL (USBHSH->HOST_CTRL) +#define UHUB_INT_FLAG (USBHSH->INT_FG) +#define bUMS_ATTACH USBHS_UMS_DEV_ATTACH +#define bUMS_SUSPEND USBHS_UMS_SUSPEND + +/* 检查磁盘是否连接 */ +uint8_t CHRV3DiskConnect( void ) +{ + uint8_t ums, devaddr; + UHUB_DEV_ADDR = UHUB_DEV_ADDR & 0x7F; + ums = UHUB_MIS_STAT; + devaddr = UHUB_DEV_ADDR; + if ( devaddr == USB_DEVICE_ADDR+1 ) + { + /* 内置Root-HUB下的USB设备 */ + if ( ums & bUMS_ATTACH ) + { + /* 内置Root-HUB下的USB设备存在 */ + if ( ( ums & bUMS_SUSPEND ) == 0 ) + { + /* 内置Root-HUB下的USB设备存在且未插拔 */ + return( ERR_SUCCESS ); /* USB设备已经连接且未插拔 */ + } + else + { + /* 内置Root-HUB下的USB设备存在 */ + CHRV3DiskStatus = DISK_CONNECT; /* 曾经断开过 */ + return( ERR_SUCCESS ); /* 外部HUB或USB设备已经连接或者断开后重新连接 */ + } + } + else + { + /* USB设备断开 */ +mDiskDisconn: + CHRV3DiskStatus = DISK_DISCONNECT; + return( ERR_USB_DISCON ); + } + } + else + { + goto mDiskDisconn; + } +} +#endif // NO_DEFAULT_DISK_CONNECT + +#ifndef NO_DEFAULT_FILE_ENUMER /* 在应用程序中定义NO_DEFAULT_FILE_ENUMER可以禁止默认的文件名枚举回调程序,然后用自行编写的程序代替它 */ +void xFileNameEnumer( void ) /* 文件名枚举回调子程序 */ +{ +/* 如果指定枚举序号CHRV3vFileSize为0xFFFFFFFF后调用FileOpen,那么每搜索到一个文件FileOpen都会调用本回调程序, + 回调程序xFileNameEnumer返回后,FileOpen递减CHRV3vFileSize并继续枚举直到搜索不到文件或者目录。建议做法是, + 在调用FileOpen之前定义一个全局变量为0,当FileOpen回调本程序后,本程序由CHRV3vFdtOffset得到结构FAT_DIR_INFO, + 分析结构中的DIR_Attr以及DIR_Name判断是否为所需文件名或者目录名,记录相关信息,并将全局变量计数增量, + 当FileOpen返回后,判断返回值如果是ERR_MISS_FILE或ERR_FOUND_NAME都视为操作成功,全局变量为搜索到的有效文件数。 + 如果在本回调程序xFileNameEnumer中将CHRV3vFileSize置为1,那么可以通知FileOpen提前结束搜索。以下是回调程序例子 */ +#if 0 + uint8_t i; + uint16_t FileCount; + PX_FAT_DIR_INFO pFileDir; + uint8_t *NameBuf; + pFileDir = (PX_FAT_DIR_INFO)( pDISK_BASE_BUF + CHRV3vFdtOffset ); /* 当前FDT的起始地址 */ + FileCount = (UINT16)( 0xFFFFFFFF - CHRV3vFileSize ); /* 当前文件名的枚举序号,CHRV3vFileSize初值是0xFFFFFFFF,找到文件名后递减 */ + if ( FileCount < sizeof( FILE_DATA_BUF ) / 12 ) { /* 检查缓冲区是否足够存放,假定每个文件名需占用12个字节存放 */ + NameBuf = & FILE_DATA_BUF[ FileCount * 12 ]; /* 计算保存当前文件名的缓冲区地址 */ + for ( i = 0; i < 11; i ++ ) NameBuf[ i ] = pFileDir -> DIR_Name[ i ]; /* 复制文件名,长度为11个字符,未处理空格 */ +// if ( pFileDir -> DIR_Attr & ATTR_DIRECTORY ) NameBuf[ i ] = 1; /* 判断是目录名 */ + NameBuf[ i ] = 0; /* 文件名结束符 */ + } +#endif +} +#endif // NO_DEFAULT_FILE_ENUMER + +uint8_t CHRV3LibInit( void ) /* 初始化CHRV3程序库,操作成功返回0 */ +{ + uint8_t s; + s = CHRV3GetVer( ); + if( s < CHRV3_LIB_VER ) + { + return( 0xFF ); /* 获取当前子程序库的版本号,版本太低则返回错误 */ + } + printf( "lib vision:%02x\r\n",s ); +#if DISK_BASE_BUF_LEN > 0 + pDISK_BASE_BUF = & DISK_BASE_BUF[0]; /* 指向外部RAM的磁盘数据缓冲区 */ + pDISK_FAT_BUF = & DISK_BASE_BUF[0]; /* 指向外部RAM的磁盘FAT数据缓冲区,可以与pDISK_BASE_BUF合用以节约RAM */ +// pDISK_FAT_BUF = & DISK_FAT_BUF[0]; /* 指向外部RAM的磁盘FAT数据缓冲区,独立于pDISK_BASE_BUF以提高速度 */ +/* 如果希望提高文件存取速度,那么可以在主程序中调用CHRV3LibInit之后,将pDISK_FAT_BUF重新指向另一个独立分配的与pDISK_BASE_BUF同样大小的缓冲区 */ +#endif + CHRV3DiskStatus = DISK_UNKNOWN; /* 未知状态 */ + CHRV3vSectorSizeB = 9; /* 默认的物理磁盘的扇区是512B */ + CHRV3vSectorSize = 512; /* 默认的物理磁盘的扇区是512B,该值是磁盘的扇区大小 */ + CHRV3vStartLba = 0; /* 默认为自动分析FDD和HDD */ + CHRV3vPacketSize = 512; /* USB存储类设备的最大包长度:64@FS,512@HS/SS,由应用程序初始化,枚举U盘后如果是高速或者超速那么及时更新为512 */ + + pTX_DMA_A_REG = (uint32_t *)&(USBHSH->HOST_TX_DMA); /* 指向发送DMA地址寄存器,由应用程序初始化 */ + pRX_DMA_A_REG = (uint32_t *)&(USBHSH->HOST_RX_DMA); /* 指向接收DMA地址寄存器,由应用程序初始化 */ + pTX_LEN_REG = (uint16_t *)&(USBHSH->HOST_TX_LEN); /* 指向发送长度寄存器,由应用程序初始化 */ + pRX_LEN_REG = (uint16_t *)&(USBHSH->RX_LEN); /* 指向接收长度寄存器,由应用程序初始化 */ + + return( ERR_SUCCESS ); +} + +void mDelaymS( uint16_t n ) +{ + Delay_Ms(n); +} + diff --git a/Ubiquitous/XiZi_IIoT/board/ch32v307vct6/third_party_driver/usb/usb_drv/src/Makefile b/Ubiquitous/XiZi_IIoT/board/ch32v307vct6/third_party_driver/usb/usb_drv/src/Makefile new file mode 100644 index 000000000..d6d19a6b4 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/ch32v307vct6/third_party_driver/usb/usb_drv/src/Makefile @@ -0,0 +1,8 @@ +SRC_FILES := ch32v30x_usbhs_host.c Udisk_Func_BasicOp.c UDisk_Func_CreatDir.c UDisk_Func_LongName.c UDisk_HW.c CH32V103UFI.c + +include $(KERNEL_ROOT)/compiler.mk + + + + + diff --git a/Ubiquitous/XiZi_IIoT/board/ch32v307vct6/third_party_driver/usb/usb_drv/src/UDisk_Func_CreatDir.c b/Ubiquitous/XiZi_IIoT/board/ch32v307vct6/third_party_driver/usb/usb_drv/src/UDisk_Func_CreatDir.c new file mode 100644 index 000000000..d906b9e02 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/ch32v307vct6/third_party_driver/usb/usb_drv/src/UDisk_Func_CreatDir.c @@ -0,0 +1,195 @@ +/********************************** (C) COPYRIGHT ******************************* +* File Name : UDisk_Func_CreatDir.c +* Author : WCH +* Version : V1.0.0 +* Date : 2022/11/22 +* Description : USB full-speed port host operation functions. +********************************************************************************* +* 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. +*******************************************************************************/ + +/*******************************************************************************/ +/* Header File */ +#include "Udisk_Operation.h" + +/******************************************************************************* +* Function Name : CreateDirectory +* Description : 新建目录并打开,如果目录已经存在则直接打开,目录名在mCmdParam.Create.mPathName中,与文件名规则相同 +* Input : +* Output : None +* Return : ERR_SUCCESS = 打开目录成功或者创建目录成功, + ERR_FOUND_NAME = 已经存在同名文件, + ERR_MISS_DIR = 路径名无效或者上级目录不存在 +*******************************************************************************/ +uint8_t CreateDirectory( void ) +{ + uint8_t i, j; + uint32_t UpDirCluster; + uint8_t * DirXramBuf; + uint8_t *DirConstData; + j = 0xFF; + for ( i = 0; i != sizeof( mCmdParam.Create.mPathName ); i ++ ) //检查目录路径 + { + if ( mCmdParam.Create.mPathName[ i ] == 0 ) + { + break; + } + if ( mCmdParam.Create.mPathName[ i ] == PATH_SEPAR_CHAR1 || mCmdParam.Create.mPathName[ i ] == PATH_SEPAR_CHAR2 ) + { + j = i; //记录上级目录 + } + } + i = ERR_SUCCESS; + if ( j == 0 || (j == 2 && mCmdParam.Create.mPathName[1] == ':') ) + { + UpDirCluster = 0; //在根目录下创建子目录 + } + else + { + if ( j != 0xFF ) //对于绝对路径应该获取上级目录的起始簇号 + { + mCmdParam.Create.mPathName[ j ] = 0; + i = CHRV3FileOpen( ); //打开上级目录 + if ( i == ERR_SUCCESS ) + { + i = ERR_MISS_DIR; //是文件而非目录 + } + else if ( i == ERR_OPEN_DIR ) + { + i = ERR_SUCCESS; //成功打开上级目录 + } + mCmdParam.Create.mPathName[ j ] = PATH_SEPAR_CHAR1; //恢复目录分隔符 + } + UpDirCluster = CHRV3vStartCluster; //保存上级目录的起始簇号 + } + if ( i == ERR_SUCCESS ) //成功获取上级目录的起始簇号 + { + i = CHRV3FileOpen( ); //打开本级子目录 + if ( i == ERR_SUCCESS ) + { + i = ERR_FOUND_NAME; //是文件而非目录 + } + else if ( i == ERR_OPEN_DIR ) + { + i = ERR_SUCCESS; //目录已经存在 + } + else if ( i == ERR_MISS_FILE ) //目录不存在,可以新建 + { + i = CHRV3FileCreate( ); //以创建文件的方法创建目录 + if ( i == ERR_SUCCESS ) + { + if ( pDISK_FAT_BUF == pDISK_BASE_BUF ) + { + memset(pDISK_FAT_BUF,0,CHRV3vSectorSize); //如果FILE_DATA_BUF与DISK_BASE_BUF合用则必须清除磁盘缓冲区 + } + DirXramBuf = pDISK_FAT_BUF; //文件数据缓冲区 + DirConstData = ". \x10\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x21\x30\x0\x0\x0\x0\x0\x0.. \x10\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x21\x30\x0\x0\x0\x0\x0\x0"; + for ( i = 0x40; i != 0; i -- ) //目录的保留单元,分别指向自身和上级目录 + { + *DirXramBuf = *DirConstData; + DirXramBuf ++; + DirConstData ++; + } + *(pDISK_FAT_BUF+0x1A) = ( (uint8_t *)&CHRV3vStartCluster )[3];//自身的起始簇号 + *(pDISK_FAT_BUF+0x1B) = ( (uint8_t *)&CHRV3vStartCluster )[2]; + *(pDISK_FAT_BUF+0x14) = ( (uint8_t *)&CHRV3vStartCluster )[1]; + *(pDISK_FAT_BUF+0x15) = ( (uint8_t *)&CHRV3vStartCluster )[0]; + *(pDISK_FAT_BUF+0x20+0x1A) = ( (uint8_t *)&UpDirCluster )[3];//上级目录的起始簇号 + *(pDISK_FAT_BUF+0x20+0x1B) = ( (uint8_t *)&UpDirCluster )[2]; + *(pDISK_FAT_BUF+0x20+0x14) = ( (uint8_t *)&UpDirCluster )[1]; + *(pDISK_FAT_BUF+0x20+0x15) = ( (uint8_t *)&UpDirCluster )[0]; +// for ( count = 0x40; count != CHRV3vSectorSizeH*256; count ++ ) { /* 清空目录区剩余部分 */ +// *DirXramBuf = 0; +// DirXramBuf ++; +// } + mCmdParam.Write.mSectorCount = 1; + mCmdParam.Write.mDataBuffer = pDISK_FAT_BUF; //指向文件数据缓冲区的起始地址 + i = CHRV3FileWrite( ); //向文件写入数据 + if ( i == ERR_SUCCESS ) + { + DirXramBuf = pDISK_FAT_BUF; + for ( i = 0x40; i != 0; i -- ) //清空目录区 + { + *DirXramBuf = 0; + DirXramBuf ++; + } + for ( j = 1; j != CHRV3vSecPerClus; j ++ ) + { + if ( pDISK_FAT_BUF == pDISK_BASE_BUF ) + { + memset(pDISK_FAT_BUF,0,CHRV3vSectorSize); //如果FILE_DATA_BUF与DISK_BASE_BUF合用则必须清除磁盘缓冲区 + } + mCmdParam.Write.mSectorCount = 1; + mCmdParam.Write.mDataBuffer = pDISK_FAT_BUF; //指向文件数据缓冲区的起始地址 + i = CHRV3FileWrite( ); //清空目录的剩余扇区 + if ( i != ERR_SUCCESS ) + { + break; + } + } + if ( j == CHRV3vSecPerClus ) //成功清空目录 + { + mCmdParam.Modify.mFileSize = 0; //目录的长度总是0 + mCmdParam.Modify.mFileDate = 0xFFFF; + mCmdParam.Modify.mFileTime = 0xFFFF; + mCmdParam.Modify.mFileAttr = 0x10; //置目录属性 + i = CHRV3FileModify( ); //将文件信息修改为目录 + } + } + } + } + } + return( i ); +} + +/********************************************************************* + * @fn UDisk_USBH_CreatDirectory + * + * @brief Demo Function For UDisk Create Directory (EXAM9) + * + * @return none + */ +void UDisk_USBH_CreatDirectory( void ) +{ + uint8_t i; + uint8_t ret; + + ret = UDisk_USBH_DiskReady( ); + if( ( ret == DISK_READY )&&( UDisk_Opeation_Flag == 1 ) ) + { + UDisk_Opeation_Flag = 0; + printf("CHRV3DiskStatus:%02x\r\n",CHRV3DiskStatus); + printf( "Create Level 1 Directory /YEAR2004 \r\n" ); + strcpy( mCmdParam.Create.mPathName, "/YEAR2004" ); //目录名,该目录建在根目录下 + ret = CreateDirectory( ); //新建或者打开目录 + mStopIfError( ret ); + /* 目录新建或者打开成功,下面在这个子目录中新建一个演示文件 */ + printf( "Create New File /YEAR2004/DEMO2004.TXT \r\n" ); + strcpy( mCmdParam.Create.mPathName, "/YEAR2004/DEMO2004.TXT" );//文件名 + ret = CHRV3FileCreate( ); //新建文件并打开,如果文件已经存在则先删除后再新建 + mStopIfError( ret ); + printf( "Write some data to file DEMO2004.TXT \r\n" ); + i = sprintf( Com_Buffer, "演示文件\xd\xa" ); + mCmdParam.ByteWrite.mByteCount = i; //指定本次写入的字节数,单次读写的长度不能超过MAX_BYTE_IO + mCmdParam.ByteWrite.mByteBuffer = Com_Buffer; //指向缓冲区 + ret = CHRV3ByteWrite( ); //以字节为单位向文件写入数据,单次读写的长度不能超过MAX_BYTE_IO + mStopIfError( ret ); + printf( "Close file DEMO2004.TXT \r\n" ); + mCmdParam.Close.mUpdateLen = 1; //自动计算文件长度,以字节为单位写文件,建议让程序库关闭文件以便自动更新文件长度 + ret = CHRV3FileClose( ); + mStopIfError( ret ); + /* 下面新建二级子目录,方法与前面的一级子目录完全相同 */ + printf( "Create Level 2 Directory /YEAR2004/MONTH05 \r\n" ); + strcpy( mCmdParam.Create.mPathName, "/YEAR2004/MONTH05" ); //目录名,该目录建在YEAR2004子目录下,YEAR2004目录必须事先存在 + ret = CreateDirectory( ); //新建或者打开目录 + mStopIfError( ret ); + printf( "Close\r\n" ); + mCmdParam.Close.mUpdateLen = 0; //对于目录不需要自动更新文件长度 + ret = CHRV3FileClose( ); //关闭目录,目录不需要关闭,关闭只是为了防止下面误操作 + mStopIfError( ret ); + } +} + + diff --git a/Ubiquitous/XiZi_IIoT/board/ch32v307vct6/third_party_driver/usb/usb_drv/src/UDisk_Func_LongName.c b/Ubiquitous/XiZi_IIoT/board/ch32v307vct6/third_party_driver/usb/usb_drv/src/UDisk_Func_LongName.c new file mode 100644 index 000000000..bd9eb1673 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/ch32v307vct6/third_party_driver/usb/usb_drv/src/UDisk_Func_LongName.c @@ -0,0 +1,596 @@ +/********************************** (C) COPYRIGHT ******************************* +* File Name : Udisk_Func_longname.c +* Author : WCH +* Version : V1.0.0 +* Date : 2022/11/22 +* Description : USB full-speed port host operation functions. +********************************************************************************* +* 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. +*******************************************************************************/ + +/*******************************************************************************/ +/* Header File */ +#include "Udisk_Operation.h" + +/*******************************************************************************/ +/* Variable Definition */ +uint8_t LongNameBuf[ LONG_NAME_BUF_LEN ]; +/* +长文件名示例(UNICODE编码的大小端 必须与UNICODE_ENDIAN定义相同) +以下是LongName里编码内容: +建立长文件名,输入两个参数: 1.采用(unicode 大端),字符串末尾用两个0表示结束;2.ANSI编码短文件名.TXT +*/ +uint8_t LongName[ ] = +#if UNICODE_ENDIAN == 1 +{ + 0x5E, 0xFA, 0x7A, 0xCB, 0x95, 0x7F, 0x65, 0x87, 0x4E, 0xF6, 0x54, 0x0D, 0xFF, 0x0C, 0x8F, 0x93, + 0x51, 0x65, 0x4E, 0x24, 0x4E, 0x2A, 0x53, 0xC2, 0x65, 0x70, 0xFF, 0x1A, 0x00, 0x20, 0x00, 0x31, + 0x00, 0x2E, 0x91, 0xC7, 0x75, 0x28, 0x00, 0x28, 0x00, 0x75, 0x00, 0x6E, 0x00, 0x69, 0x00, 0x63, + 0x00, 0x6F, 0x00, 0x64, 0x00, 0x65, 0x00, 0x20, 0x59, 0x27, 0x7A, 0xEF, 0x00, 0x29, 0xFF, 0x0C, + 0x5B, 0x57, 0x7B, 0x26, 0x4E, 0x32, 0x67, 0x2B, 0x5C, 0x3E, 0x75, 0x28, 0x4E, 0x24, 0x4E, 0x2A, + 0x00, 0x30, 0x88, 0x68, 0x79, 0x3A, 0x7E, 0xD3, 0x67, 0x5F, 0x00, 0x3B, 0x00, 0x32, 0x00, 0x2E, + 0x00, 0x41, 0x00, 0x4E, 0x00, 0x53, 0x00, 0x49, 0x7F, 0x16, 0x78, 0x01, 0x77, 0xED, 0x65, 0x87, + 0x4E, 0xF6, 0x54, 0x0D, 0x00, 0x2E, 0x00, 0x54, 0x00, 0x58, 0x00, 0x54 +}; +#else +{ + 0xFA, 0x5E, 0xCB, 0x7A, 0x7F, 0x95, 0x87, 0x65, 0xF6, 0x4E, 0x0D, 0x54, 0x0C, 0xFF, 0x93, 0x8F, + 0x65, 0x51, 0x24, 0x4E, 0x2A, 0x4E, 0xC2, 0x53, 0x70, 0x65, 0x1A, 0xFF, 0x20, 0x00, 0x31, 0x00, + 0x2E, 0x00, 0xC7, 0x91, 0x28, 0x75, 0x28, 0x00, 0x75, 0x00, 0x6E, 0x00, 0x69, 0x00, 0x63, 0x00, + 0x6F, 0x00, 0x64, 0x00, 0x65, 0x00, 0x20, 0x00, 0x27, 0x59, 0xEF, 0x7A, 0x29, 0x00, 0x0C, 0xFF, + 0x57, 0x5B, 0x26, 0x7B, 0x32, 0x4E, 0x2B, 0x67, 0x3E, 0x5C, 0x28, 0x75, 0x24, 0x4E, 0x2A, 0x4E, + 0x30, 0x00, 0x68, 0x88, 0x3A, 0x79, 0xD3, 0x7E, 0x5F, 0x67, 0x3B, 0x00, 0x32, 0x00, 0x2E, 0x00, + 0x41, 0x00, 0x4E, 0x00, 0x53, 0x00, 0x49, 0x00, 0x16, 0x7F, 0x01, 0x78, 0xED, 0x77, 0x87, 0x65, + 0xF6, 0x4E, 0x0D, 0x54, 0x2E, 0x00, 0x54, 0x00, 0x58, 0x00, 0x54, 0x00 +}; +#endif + +/********************************************************************* + * @fn UDisk_USBH_Longname + * + * @brief Demo Function For UDisk long-name Operation(EXAM 13) + * + * @return none + */ +void UDisk_USBH_Longname( void ) +{ + uint8_t ret, i, len; + uint16_t j; + + ret = UDisk_USBH_DiskReady( ); + if( ( ret == DISK_READY )&&( UDisk_Opeation_Flag == 1 ) ) + { + UDisk_Opeation_Flag = 0; + /*==================== 以下演示创建及读取长文件名 ============================*/ + // 复制长文件名(UNICODE 大端)到LongNameBuf里 + len = LongName_Len; + memcpy( LongNameBuf, LongName, len ); + // 末尾用两个0表示结束 + LongNameBuf[len] = 0x00; + LongNameBuf[len + 1] = 0x00; + // 该长文件名的ANSI编码短文件名(8+3格式) + strcpy( mCmdParam.Create.mPathName, "\\长文件名.TXT" ); + i = CHRV3CreateLongName( ); + if( i == ERR_SUCCESS ) + { + DUG_PRINTF( "Created Long Name OK!\r\n" ); + } + else + { + /* Error code defined in "udisk_operaion.h" */ + DUG_PRINTF( "Error Code: %02X\r\n", (uint16_t)i ); + } + + DUG_PRINTF( "Get long Name#\r\n" ); + strcpy( mCmdParam.Open.mPathName, "\\长文件名.TXT" ); + // 以上需要输入文件名的完整路径 + i = CHRV3GetLongName( ); + if( i == ERR_SUCCESS ) + { + // 长文件名收集完成,以UNICODE编码方式(按UNICODE_ENDIAN定义) + // 存放在LongNameBuf缓冲里,长文件名最后用两个0结束. + // 以下显示缓冲区里所有数据 + DUG_PRINTF( "LongNameBuf: " ); + for( j=0; j!=LONG_NAME_BUF_LEN; j++ ) + { + DUG_PRINTF( "%02X ", (uint16_t)LongNameBuf[j] ); + } + DUG_PRINTF( "\r\n" ); + } + else + { + /* Error code defined in "udisk_operaion.h" */ + DUG_PRINTF( "Error Code: %02X\r\n", (uint16_t)i ); + } + } +} + +/********************************************************************* + * @fn CheckNameSum + * + * @brief 检查长文件名的短文件名检验和 + * + * @return 计算后的校验和 + */ +uint8_t CheckNameSum( uint8_t *p ) +{ +uint8_t FcbNameLen; +uint8_t Sum; + + Sum = 0; + for (FcbNameLen=0; FcbNameLen!=11; FcbNameLen++) + Sum = ((Sum & 1) ? 0x80 : 0) + (Sum >> 1) + *p++; + return Sum; +} + +/********************************************************************* + * @fn AnalyzeLongName + * + * @brief 整理长文件名 返回有几个的26长度 + * + * @return 返回有多少个26的长度 + */ +uint8_t AnalyzeLongName( void ) +{ +uint8_t i, j; +uint16_t index; + + i = FALSE; + for( index=0; index!=LONG_NAME_BUF_LEN; index = index + 2 ) + { + if( ( LongNameBuf[index] == 0 ) && ( LongNameBuf[index+1] == 0 ) ) + { + i = TRUE; + break; + } + } + if( ( i == FALSE ) || ( index == 0) ) + return 0; // 返回0表示错误的长文件名 + + i = index % 26; + if( i != 0 ) + { + index += 2; + if( index % 26 != 0 ) // 加0刚好结束 + { + for( j=i+2; j!=26; j++ )// 把剩余数据填为0XFF + LongNameBuf[index++] = 0xff; + } + } + return (index / 26); +} + +/********************************************************************* + * @fn CHRV3CreateLongName + * + * @brief 创建长文件名,需要输入短文件名的完整路径 + * + * @return 操作状态 + */ +uint8_t CHRV3CreateLongName( void ) +{ +// 分析 保留文件路径 创建一个空文件 得到FDT偏移和其所在扇区 删除文件 +// 向后偏移扇区 可能失败 如FAT12/16处在根目录处 填充完毕后再次创建文件 +uint8_t i; +uint8_t len; // 存放路径的长度 +uint16_t index; // 长文件偏移索引 +uint16_t indexBak; // 长文件偏移索引备份 +uint32_t Secoffset; // 扇区偏移 + +uint8_t Fbit; // 第一次进入写扇区 +uint8_t Mult; // 长文件名长度26的倍数 +uint8_t MultBak; // 长文件名长度26的倍数备份 + +uint16_t Backoffset; // 保存文件偏移备份 +uint16_t BackoffsetBak; // 保存偏移备份的备份 +uint32_t BackFdtSector; // 保寸偏移上一个扇区 +uint8_t sum; // 保存长文件名的校验和 + +uint8_t BackPathBuf[MAX_PATH_LEN]; // 保存文件路径 + + Mult = AnalyzeLongName( ); // 保存长文件名是26的倍数 + if( Mult == 0 ) + return ERR_LONG_NAME; + MultBak = Mult; + + i = CHRV3FileOpen(); // 短文件名存在则返回错误 + if( i == ERR_SUCCESS ) + return ERR_NAME_EXIST; + + i = CHRV3FileCreate( ); + if( i == ERR_SUCCESS ) + { + Backoffset = CHRV3vFdtOffset; + BackoffsetBak = Backoffset; + BackFdtSector = CHRV3vFdtLba; + sum = CheckNameSum( &DISK_BASE_BUF[Backoffset ] ); + for( i=0; i!=MAX_PATH_LEN; i++ ) // 对文件路径进行备份 + BackPathBuf[i] = mCmdParam.Open.mPathName[i]; + CHRV3FileErase( ); // 删除此文件 + + Secoffset = 0; // 从0开始偏移 + index = Mult*26; // 得到长文件名的长度 + indexBak = index; + Fbit = FALSE; // 默认没有进入 + // 打开上级 进行数据填充数据 + P_RETRY: + for(len=0; len!=MAX_PATH_LEN; len++) + { + if(mCmdParam.Open.mPathName[len] == 0) + break; // 得到字符串长度 + } + + for(i=len-1; i!=0xff; i--) // 得到上级目录位置 + { + if((mCmdParam.Open.mPathName[i] == '\\') || (mCmdParam.Open.mPathName[i] == '/')) + break; + } + mCmdParam.Open.mPathName[i] = 0x00; + + if( i==0 ) // 打开一级目录注意:处在根目录开始的特殊情况 + { + mCmdParam.Open.mPathName[0] = '/'; + mCmdParam.Open.mPathName[1] = 0; + } + + i = CHRV3FileOpen(); // 打开上级目录 + if( i == ERR_OPEN_DIR ) + { + while( 1 ) // 循环填写 直到完成 + { + mCmdParam.Locate.mSectorOffset = Secoffset; + i = CHRV3FileLocate( ); + if( i == ERR_SUCCESS ) + { + if( Fbit ) // 第二次进入次写扇区 + { + if( mCmdParam.Locate.mSectorOffset != 0x0FFFFFFFF ) + { + BackFdtSector = mCmdParam.Locate.mSectorOffset; + Backoffset = 0; + } + else + { + for( i=0; i!=MAX_PATH_LEN; i++ )// 还原文件路径 + mCmdParam.Open.mPathName[i] = BackPathBuf[i]; + i = CHRV3FileCreate( ); // 进行空间扩展 + if( i != ERR_SUCCESS ) + return i; + CHRV3FileErase( ); + goto P_RETRY; // 重新打开上级目录 + } + } + + if( BackFdtSector == mCmdParam.Locate.mSectorOffset ) + { + mCmdParam.Read.mSectorCount = 1; // 读一个扇区到磁盘缓冲区 + mCmdParam.Read.mDataBuffer = &DISK_BASE_BUF[0]; + i = CHRV3FileRead( ); + CHRV3DirtyBuffer( ); // 清除磁盘缓冲区 + if( i!= ERR_SUCCESS ) + return i; + + i = ( CHRV3vSectorSize - Backoffset ) / 32; + if( Mult > i ) + Mult = Mult - i; // 剩余的倍数 + else + { + i = Mult; + Mult = 0; + } + + for( len=i; len!=0; len-- ) + { + indexBak -= 26; + index = indexBak; + for( i=0; i!=5; i++) // 长文件名的1-5个字符 + { // 在磁盘上UNICODE用小端方式存放 + #if UNICODE_ENDIAN == 1 + DISK_BASE_BUF[Backoffset + i*2 + 2 ] = + LongNameBuf[index++]; + DISK_BASE_BUF[Backoffset + i*2 + 1 ] = + LongNameBuf[index++]; + #else + DISK_BASE_BUF[Backoffset + i*2 + 1 ] = + LongNameBuf[index++]; + DISK_BASE_BUF[Backoffset + i*2 + 2 ] = + LongNameBuf[index++]; + #endif + } + + for( i =0; i!=6; i++) // 长文件名的6-11个字符 + { + #if UNICODE_ENDIAN == 1 + DISK_BASE_BUF[Backoffset + 14 + i*2 + 1 ] = + LongNameBuf[index++]; + DISK_BASE_BUF[Backoffset + 14 + i*2 ] = + LongNameBuf[index++]; + #else + DISK_BASE_BUF[Backoffset + 14 + i*2 ] = + LongNameBuf[index++]; + DISK_BASE_BUF[Backoffset + 14 + i*2 + 1 ] = + LongNameBuf[index++]; + #endif + } + + for( i=0; i!=2; i++) // 长文件名的12-13个字符 + { + #if UNICODE_ENDIAN == 1 + DISK_BASE_BUF[Backoffset + 28 + i*2 + 1 ] = + LongNameBuf[index++]; + DISK_BASE_BUF[Backoffset + 28 + i*2 ] = + LongNameBuf[index++]; + #else + DISK_BASE_BUF[Backoffset + 28 + i*2 ] = + LongNameBuf[index++]; + DISK_BASE_BUF[Backoffset + 28 + i*2 + 1 ] = + LongNameBuf[index++]; + #endif + } + + DISK_BASE_BUF[Backoffset + 0x0b] = 0x0f; + DISK_BASE_BUF[Backoffset + 0x0c] = 0x00; + DISK_BASE_BUF[Backoffset + 0x0d] = sum; + DISK_BASE_BUF[Backoffset + 0x1a] = 0x00; + DISK_BASE_BUF[Backoffset + 0x1b] = 0x00; + DISK_BASE_BUF[Backoffset] = MultBak--; + Backoffset += 32; + } + + if( !Fbit ) + { + Fbit = TRUE; + DISK_BASE_BUF[ BackoffsetBak ] |= 0x40; + } + CHRV3vLbaCurrent = BackFdtSector; + i = CHRV3WriteSector( 1, DISK_BASE_BUF ); + if( i!= ERR_SUCCESS ) + return i; + + if( Mult==0 ) + { // 还原文件路径 + CHRV3FileClose( ); + for( i=0; i!=MAX_PATH_LEN; i++ ) + mCmdParam.Open.mPathName[i] = BackPathBuf[i]; + i = CHRV3FileCreate( ); + return i; + } + } + } + else + return i; + Secoffset++; + } + } + } + return i; +} + +/********************************************************************* + * @fn GetUpSectorData + * + * @brief 由当前扇区得到上一个扇区的数据,放在磁盘缓冲区 + * + * @return 操作状态 + */ +uint8_t GetUpSectorData( uint32_t *NowSector ) +{ +uint8_t i; +uint8_t len; // 存放路径的长度 +uint32_t index; // 目录扇区偏移扇区数 + + index = 0; + for(len=0; len!=MAX_PATH_LEN; len++) + { + if(mCmdParam.Open.mPathName[len] == 0) // 得到字符串长度 + break; + } + + for(i=len-1; i!=0xff; i--) // 得到上级目录位置 + { + if((mCmdParam.Open.mPathName[i] == '\\') || (mCmdParam.Open.mPathName[i] == '/')) + break; + } + mCmdParam.Open.mPathName[i] = 0x00; + + if( i==0 ) // 打开一级目录注意:处在根目录开始的特殊情况 + { + mCmdParam.Open.mPathName[0] = '/'; + mCmdParam.Open.mPathName[1] = 0; + i = CHRV3FileOpen(); + if ( i == ERR_OPEN_DIR ) + goto P_NEXT0; + } + else + { + i = CHRV3FileOpen(); + if ( i == ERR_OPEN_DIR ) + { + while( 1 ) + { + P_NEXT0: + mCmdParam.Locate.mSectorOffset = index; + i = CHRV3FileLocate( ); + if( i == ERR_SUCCESS ) + { + if( *NowSector == mCmdParam.Locate.mSectorOffset ) + { + if( index==0 ) // 处于根目录扇区的开始 + return ERR_NO_NAME; + mCmdParam.Locate.mSectorOffset = --index; + i = CHRV3FileLocate( ); // 读上一个扇区的数据 + if( i == ERR_SUCCESS ) + { // 以下保存当前所在扇区数 + *NowSector = mCmdParam.Locate.mSectorOffset; + mCmdParam.Read.mSectorCount = 1; // 读一个扇区到磁盘缓冲区 + mCmdParam.Read.mDataBuffer = &DISK_BASE_BUF[0]; + i = CHRV3FileRead( ); + CHRV3DirtyBuffer( ); // 清除磁盘缓冲区 + return i; + } + else + return i; + } + } + else + return i; + index++; + } + } + } + return i; +} + +/********************************************************************* + * @fn CHRV3GetLongName + * + * @brief 由完整短文件名路径(可以是文件或文件夹)得到相应的长文件名 + * + * @return 操作状态 + */ +uint8_t CHRV3GetLongName( void ) +{ +// 需要变量扇区大小 +// 第一步:打开文件是否找到文件,分析文件是否存在,并得到FDT在此扇区的偏移和所在扇区 +// 第二步:分析上面的信息看是否有长文件名存在,是否处于目录的第一个扇区的开始 +// 第三步:实现向后偏移一个扇区?读取长文件名(扇区512字节的U盘) +uint8_t i; +uint16_t index; // 在长文件名缓冲区内的索引 +uint32_t BackFdtSector; // 保寸偏移上一个扇区 +uint8_t sum; // 保存长文件名的校验和 +//uint16_t Backoffset; // 保存文件偏移备份 +uint16_t offset; // 扇区内文件偏移32倍数 +uint8_t FirstBit; // 长文件名跨越两个扇区标志位 +uint8_t BackPathBuf[MAX_PATH_LEN]; // 保存文件路径 + + i = CHRV3FileOpen( ); + if( ( i == ERR_SUCCESS ) || ( i == ERR_OPEN_DIR ) ) + { + for( i=0; i!=MAX_PATH_LEN; i++ ) + BackPathBuf[i] = mCmdParam.Open.mPathName[i]; + // 以上完成对路径的备份 + + sum = CheckNameSum( &DISK_BASE_BUF[CHRV3vFdtOffset] ); + index = 0; + FirstBit = FALSE; +// Backoffset = CHRV3vFdtOffset; + BackFdtSector = CHRV3vFdtLba; + if( CHRV3vFdtOffset == 0 ) + { + // 先判断是否处于一个扇区开始 是否处于根目录开始 ,否则向后偏移 + if( FirstBit == FALSE ) + FirstBit = TRUE; + i = GetUpSectorData( &BackFdtSector ); + if( i == ERR_SUCCESS ) + { + CHRV3vFdtOffset = CHRV3vSectorSize; + goto P_NEXT1; + } + } + else + { + // 读取偏移后的数据,直到结束。如果不够则向后偏移 + P_NEXT1: + offset = CHRV3vFdtOffset; + while( 1 ) + { + if( offset != 0 ) + { + offset = offset - 32; + if( ( DISK_BASE_BUF[offset + 11] == ATTR_LONG_NAME ) + && ( DISK_BASE_BUF[offset + 13] == sum ) ) + { + if( (index + 26) > LONG_NAME_BUF_LEN ) + return ERR_BUF_OVER; + + for( i=0; i!=5; i++) // 长文件名的1-5个字符 + { // 在磁盘上UNICODE用小端方式存放 + #if UNICODE_ENDIAN == 1 + LongNameBuf[index++] = + DISK_BASE_BUF[offset + i*2 + 2]; + LongNameBuf[index++] = + DISK_BASE_BUF[offset + i*2 + 1]; + #else + LongNameBuf[index++] = + DISK_BASE_BUF[offset + i*2 + 1]; + LongNameBuf[index++] = + DISK_BASE_BUF[offset + i*2 + 2]; + #endif + } + + for( i =0; i!=6; i++) // 长文件名的6-11个字符 + { + #if UNICODE_ENDIAN == 1 + LongNameBuf[index++] = + DISK_BASE_BUF[offset + 14 + i*2 + 1]; + LongNameBuf[index++] = + DISK_BASE_BUF[offset + + 14 + i*2 ]; + #else + LongNameBuf[index++] = + DISK_BASE_BUF[offset + + 14 + i*2 ]; + LongNameBuf[index++] = + DISK_BASE_BUF[offset + 14 + i*2 + 1]; + #endif + + } + + for( i=0; i!=2; i++) // 长文件名的12-13个字符 + { + #if UNICODE_ENDIAN == 1 + LongNameBuf[index++] = + DISK_BASE_BUF[offset + 28 + i*2 + 1]; + LongNameBuf[index++] = + DISK_BASE_BUF[offset + 28 + i*2 ]; + #else + LongNameBuf[index++] = + DISK_BASE_BUF[offset + 28 + i*2 ]; + LongNameBuf[index++] = + DISK_BASE_BUF[offset + 28 + i*2 + 1]; + #endif + } + + if( DISK_BASE_BUF[offset] & 0X40 ) + { + if( ! (((LongNameBuf[index -1] ==0x00) + && (LongNameBuf[index -2] ==0x00)) + || ((LongNameBuf[index -1] ==0xFF) + && (LongNameBuf[index -2 ] ==0xFF)))) + { // 处理刚好为26字节长倍数的文件名 + if(index + 52 >LONG_NAME_BUF_LEN ) + return ERR_BUF_OVER; + LongNameBuf[ index ] = 0x00; + LongNameBuf[ index + 1] = 0x00; + } + return ERR_SUCCESS; // 成功完成长文件名收集完成 + } + } + else + return ERR_NO_NAME; // 错误的长文件名,程序返回 + } + else + { + if( FirstBit == FALSE ) + FirstBit = TRUE; + else // 否则第二次进入 + { + for( i=0; i!=MAX_PATH_LEN; i++ )// 还原路径 + mCmdParam.Open.mPathName[i] = BackPathBuf[i]; + } + i = GetUpSectorData( &BackFdtSector ); + if( i == ERR_SUCCESS ) + { + CHRV3vFdtOffset = CHRV3vSectorSize; + goto P_NEXT1; + } + else + return i; + // 向后偏移扇区 + } + } + } + } + return i; // 返回错误 +} + diff --git a/Ubiquitous/XiZi_IIoT/board/ch32v307vct6/third_party_driver/usb/usb_drv/src/UDisk_HW.c b/Ubiquitous/XiZi_IIoT/board/ch32v307vct6/third_party_driver/usb/usb_drv/src/UDisk_HW.c new file mode 100644 index 000000000..84db4cc22 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/ch32v307vct6/third_party_driver/usb/usb_drv/src/UDisk_HW.c @@ -0,0 +1,572 @@ +/********************************** (C) COPYRIGHT ******************************* +* File Name : UDisk_HW.c +* Author : WCH +* Version : V1.0.0 +* Date : 2022/09/01 +* Description : USB full-speed port host operation functions. +********************************************************************************* +* 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. +*******************************************************************************/ + +/*******************************************************************************/ +/* Header File */ +#include "Udisk_Operation.h" + +/*******************************************************************************/ +/* Variable Definition */ +__attribute__((aligned(4))) uint8_t Com_Buffer[ DEF_COM_BUF_LEN ]; // even address , used for host enumcation and udisk operation +__attribute__((aligned(4))) uint8_t DevDesc_Buf[ 18 ]; // Device Descriptor Buffer +struct _ROOT_HUB_DEVICE RootHubDev[ DEF_TOTAL_ROOT_HUB ]; +struct __HOST_CTL HostCtl[ DEF_TOTAL_ROOT_HUB * DEF_ONE_USB_SUP_DEV_TOTAL ]; +volatile uint8_t UDisk_Opeation_Flag = 0; + +/* For Udisk Lib */ +uint8_t *pHOST_RX_RAM_Addr; +uint8_t *pHOST_TX_RAM_Addr; + +/********************************************************************* + * @fn mStopIfError + * + * @brief Checking the operation status, displaying the error code and stopping if there is an error + * input : iError - Error code input + * + * @return none + */ +// void mStopIfError( uint8_t iError ) +// { +// if ( iError == ERR_SUCCESS ) +// { +// /* operation success, return */ +// return; +// } +// /* Display the errors */ +// DUG_PRINTF( "Error:%02x\r\n", iError ); +// /* After encountering an error, you should analyze the error code and CH103DiskReday status, for example, +// * call CH103DiskReday to check whether the current USB disk is connected or not, +// * if the disk is disconnected then wait for the disk to be plugged in again and operate again, +// * Suggested steps to follow after an error: +// * 1,call CH103DiskReday once, if successful, then continue the operation, such as Open, Read/Write, etc. +// * 2,If CH103DiskReday is not successful, then the operation will be forced to start from the beginning. +// */ +// while(1) +// { } +// } + +/********************************************************************* + * @fn Udisk_USBH_Initialization + * + * @brief USB Host Udisk process Initialization, include usb-host initialization + * usb libs initialization, udisk-related values Initialization + and the others + * + * @para none + * + * @return none + */ +void Udisk_USBH_Initialization( void ) +{ + /* USB Host Initialization */ + printf( "USB Host & UDisk Lib Initialization. \r\n" ); + /* Initialize USBHS host */ + /* Note: Only CH32F205/CH32F207 support USB high-speed port. */ +#if DEF_USB_PORT_HS_EN + DUG_PRINTF( "USBHS Host Init\r\n" ); + USBHS_RCC_Init( ); + USBHS_Host_Init( ENABLE ); + /* For Udisk Lib */ + pHOST_TX_RAM_Addr = USBHS_TX_Buf; + pHOST_RX_RAM_Addr = USBHS_RX_Buf; + /* Clear Struct */ + memset( &RootHubDev[ DEF_USB_PORT_HS ].bStatus, 0, sizeof( struct _ROOT_HUB_DEVICE ) ); + memset( &HostCtl[ DEF_USB_PORT_HS ].InterfaceNum, 0, sizeof( struct __HOST_CTL ) ); +#endif + + /* Initialize USBFS host */ +#if DEF_USB_PORT_FS_EN + DUG_PRINTF( "USBFS Host Init\r\n" ); + USBFS_RCC_Init( ); + USBFS_Host_Init( ENABLE ); + /* For Udisk Lib */ + pHOST_TX_RAM_Addr = USBFS_TX_Buf; + pHOST_RX_RAM_Addr = USBFS_RX_Buf; + /* Clear Struct */ + memset( &RootHubDev[ DEF_USB_PORT_FS ].bStatus, 0, sizeof( struct _ROOT_HUB_DEVICE ) ); + memset( &HostCtl[ DEF_USB_PORT_FS ].InterfaceNum, 0, sizeof( struct __HOST_CTL ) ); +#endif + + /* USB Libs Initialization */ + printf( "UDisk library Initialization. \r\n" ); + CHRV3LibInit( ); +} + +/********************************************************************* + * @fn USBH_CheckRootHubPortStatus + * + * @brief Check status of USB port. + * + * @para index: USB host port + * + * @return The current status of the port. + */ +uint8_t USBH_CheckRootHubPortStatus( uint8_t usb_port ) +{ + uint8_t s = ERR_USB_UNSUPPORT; + + if( usb_port == DEF_USB_PORT_FS ) + { +#if DEF_USB_PORT_FS_EN + s = USBFSH_CheckRootHubPortStatus( RootHubDev[ usb_port ].bStatus ); +#endif + } + else if( usb_port == DEF_USB_PORT_HS ) + { +#if DEF_USB_PORT_HS_EN + s = USBHSH_CheckRootHubPortStatus( RootHubDev[ usb_port ].bStatus ); +#endif + } + + return s; +} + +/********************************************************************* + * @fn USBH_ResetRootHubPort + * + * @brief Reset USB port. + * + * @para index: USB host port + * mod: Reset host port operating mode. + * 0 -> reset and wait end + * 1 -> begin reset + * 2 -> end reset + * + * @return none + */ +void USBH_ResetRootHubPort( uint8_t usb_port, uint8_t mode ) +{ + if( usb_port == DEF_USB_PORT_FS ) + { +#if DEF_USB_PORT_FS_EN + USBFSH_ResetRootHubPort( mode ); +#endif + } + else if( usb_port == DEF_USB_PORT_HS ) + { +#if DEF_USB_PORT_HS_EN + USBHSH_ResetRootHubPort( mode ); +#endif + } +} + +/********************************************************************* + * @fn USBH_EnableRootHubPort + * + * @brief Enable USB host port. + * + * @para index: USB host port + * + * @return none + */ +uint8_t USBH_EnableRootHubPort( uint8_t usb_port ) +{ + uint8_t s = ERR_USB_UNSUPPORT; + + if( usb_port == DEF_USB_PORT_FS ) + { +#if DEF_USB_PORT_FS_EN + s = USBFSH_EnableRootHubPort( &RootHubDev[ usb_port ].bSpeed ); +#endif + } + else if( usb_port == DEF_USB_PORT_HS ) + { +#if DEF_USB_PORT_HS_EN + s = USBHSH_EnableRootHubPort( &RootHubDev[ usb_port ].bSpeed ); +#endif + } + + return s; +} + +/********************************************************************* + * @fn USBH_SetSelfSpeed + * + * @brief Set USB speed. + * + * @para index: USB host port + * + * @return none + */ +void USBH_SetSelfSpeed( uint8_t usb_port ) +{ + if( usb_port == DEF_USB_PORT_FS ) + { +#if DEF_USB_PORT_FS_EN + USBFSH_SetSelfSpeed( RootHubDev[ usb_port].bSpeed ); +#endif + } + else if( usb_port == DEF_USB_PORT_HS ) + { +#if DEF_USB_PORT_HS_EN + USBHSH_SetSelfSpeed( RootHubDev[ usb_port ].bSpeed ); +#endif + } +} + +/********************************************************************* + * @fn USBH_GetDeviceDescr + * + * @brief Get the device descriptor of the USB device. + * + * @para index: USB host port + * + * @return none + */ +uint8_t USBH_GetDeviceDescr( uint8_t usb_port ) +{ + uint8_t s = ERR_USB_UNSUPPORT; + + if( usb_port == DEF_USB_PORT_FS ) + { +#if DEF_USB_PORT_FS_EN + s = USBFSH_GetDeviceDescr( &RootHubDev[ usb_port ].bEp0MaxPks, DevDesc_Buf ); +#endif + } + else if( usb_port == DEF_USB_PORT_HS ) + { +#if DEF_USB_PORT_HS_EN + s = USBHSH_GetDeviceDescr( &RootHubDev[ usb_port ].bEp0MaxPks, DevDesc_Buf ); +#endif + } + + return s; +} + +/********************************************************************* + * @fn USBH_SetUsbAddress + * + * @brief Set USB device address. + * + * @para index: USB host port + * + * @return none + */ +uint8_t USBH_SetUsbAddress( uint8_t usb_port ) +{ + uint8_t s = ERR_USB_UNSUPPORT; + + if( usb_port == DEF_USB_PORT_FS ) + { +#if DEF_USB_PORT_FS_EN + RootHubDev[ usb_port ].bAddress = (uint8_t)( DEF_USB_PORT_FS + USB_DEVICE_ADDR ); + s = USBFSH_SetUsbAddress( RootHubDev[ usb_port ].bEp0MaxPks, RootHubDev[ usb_port ].bAddress ); +#endif + } + else if( usb_port == DEF_USB_PORT_HS ) + { +#if DEF_USB_PORT_HS_EN + RootHubDev[ usb_port ].bAddress = (uint8_t)( DEF_USB_PORT_HS + USB_DEVICE_ADDR ); + s = USBHSH_SetUsbAddress( RootHubDev[ usb_port ].bEp0MaxPks, RootHubDev[ usb_port ].bAddress ); +#endif + } + + return s; +} + +/********************************************************************* + * @fn USBH_GetConfigDescr + * + * @brief Get the configuration descriptor of the USB device. + * + * @para index: USB host port + * + * @return none + */ +uint8_t USBH_GetConfigDescr( uint8_t usb_port, uint16_t *pcfg_len ) +{ + uint8_t s = ERR_USB_UNSUPPORT; + + if( usb_port == DEF_USB_PORT_FS ) + { +#if DEF_USB_PORT_FS_EN + s = USBFSH_GetConfigDescr( RootHubDev[ usb_port ].bEp0MaxPks, Com_Buffer, DEF_COM_BUF_LEN, pcfg_len ); +#endif + } + else if( usb_port == DEF_USB_PORT_HS ) + { +#if DEF_USB_PORT_HS_EN + s = USBHSH_GetConfigDescr( RootHubDev[ usb_port ].bEp0MaxPks, Com_Buffer, DEF_COM_BUF_LEN, pcfg_len ); +#endif + } + return s; +} + +/********************************************************************* + * @fn USBFSH_SetUsbConfig + * + * @brief Set USB configuration. + * + * @para index: USB host port + * + * @return none + */ +uint8_t USBH_SetUsbConfig( uint8_t usb_port, uint8_t cfg_val ) +{ + uint8_t s = ERR_USB_UNSUPPORT; + + if( usb_port == DEF_USB_PORT_FS ) + { +#if DEF_USB_PORT_FS_EN + s = USBFSH_SetUsbConfig( RootHubDev[ usb_port ].bEp0MaxPks, cfg_val ); +#endif + } + else if( usb_port == DEF_USB_PORT_HS ) + { +#if DEF_USB_PORT_HS_EN + s = USBHSH_SetUsbConfig( RootHubDev[ usb_port ].bEp0MaxPks, cfg_val ); +#endif + } + + return s; +} + +/********************************************************************* + * @fn Udisk_USBH_EnumRootDevice + * + * @brief Generally enumerate a device connected to host port. + * + * @para index: USB host port + * + * @return Enumeration result + */ +uint8_t Udisk_USBH_EnumRootDevice( uint8_t usb_port ) +{ + uint8_t s; + uint8_t enum_cnt; + uint8_t cfg_val; + uint16_t i; + uint16_t len; + + DUG_PRINTF( "Enum:\r\n" ); + + enum_cnt = 0; +ENUM_START: + /* Delay and wait for the device to stabilize */ + Delay_Ms( 100 ); + enum_cnt++; + Delay_Ms( 8 << enum_cnt ); + + /* Reset the USB device and wait for the USB device to reconnect */ + USBH_ResetRootHubPort( usb_port, 0 ); + for( i = 0, s = 0; i < DEF_RE_ATTACH_TIMEOUT; i++ ) + { + if( USBH_EnableRootHubPort( usb_port ) == ERR_SUCCESS ) + { + i = 0; + s++; + if( s > 6 ) + { + break; + } + } + Delay_Ms( 1 ); + } + if( i ) + { + /* Determine whether the maximum number of retries has been reached, and retry if not reached */ + if( enum_cnt <= 5 ) + { + goto ENUM_START; + } + return ERR_USB_DISCON; + } + + /* Select USB speed */ + USBH_SetSelfSpeed( usb_port ); + + /* Get USB device device descriptor */ + DUG_PRINTF("Get DevDesc: "); + s = USBH_GetDeviceDescr( usb_port ); + if( s == ERR_SUCCESS ) + { + /* Print USB device device descriptor */ +#if DEF_DEBUG_PRINTF + for( i = 0; i < 18; i++ ) + { + DUG_PRINTF( "%02x ", DevDesc_Buf[ i ] ); + } + DUG_PRINTF("\n"); +#endif + } + else + { + /* Determine whether the maximum number of retries has been reached, and retry if not reached */ + DUG_PRINTF( "Err(%02x)\n", s ); + if( enum_cnt <= 5 ) + { + goto ENUM_START; + } + return DEF_DEV_DESCR_GETFAIL; + } + + /* Set the USB device address */ + DUG_PRINTF("Set DevAddr: "); + s = USBH_SetUsbAddress( usb_port ); + if( s == ERR_SUCCESS ) + { + DUG_PRINTF( "OK\n" ); + } + else + { + /* Determine whether the maximum number of retries has been reached, and retry if not reached */ + DUG_PRINTF( "Err(%02x)\n", s ); + if( enum_cnt <= 5 ) + { + goto ENUM_START; + } + return DEF_DEV_ADDR_SETFAIL; + } + Delay_Ms( 5 ); + + /* Get the USB device configuration descriptor */ + DUG_PRINTF("Get CfgDesc: "); + s = USBH_GetConfigDescr( usb_port, &len ); + if( s == ERR_SUCCESS ) + { + cfg_val = ( (PUSB_CFG_DESCR)Com_Buffer )->bConfigurationValue; + + /* Print USB device configuration descriptor */ +#if DEF_DEBUG_PRINTF + for( i = 0; i < len; i++ ) + { + DUG_PRINTF( "%02x ", Com_Buffer[ i ] ); + } + DUG_PRINTF("\n"); +#endif + } + else + { + /* Determine whether the maximum number of retries has been reached, and retry if not reached */ + DUG_PRINTF( "Err(%02x)\n", s ); + if( enum_cnt <= 5 ) + { + goto ENUM_START; + } + return DEF_CFG_DESCR_GETFAIL; + } + + /* Set USB device configuration value */ + DUG_PRINTF("Set Cfg: "); + s = USBH_SetUsbConfig( usb_port, cfg_val ); + if( s == ERR_SUCCESS ) + { + DUG_PRINTF( "OK\n" ); + } + else + { + /* Determine whether the maximum number of retries has been reached, and retry if not reached */ + DUG_PRINTF( "Err(%02x)\n", s ); + if( enum_cnt <= 5 ) + { + goto ENUM_START; + } + return ERR_USB_UNSUPPORT; + } + + return ERR_SUCCESS; +} + +/********************************************************************* + * @fn IAP_USBH_PreDeal + * + * @brief usb host preemption operations, + * including detecting device insertion and enumerating device information + * + * @return none + */ +uint8_t UDisk_USBH_PreDeal( void ) +{ + uint8_t usb_port; + uint8_t index; + uint8_t ret; +#if DEF_USB_PORT_FS_EN + usb_port = DEF_USB_PORT_FS; +#elif DEF_USB_PORT_HS_EN + usb_port = DEF_USB_PORT_HS; +#endif + ret = USBH_CheckRootHubPortStatus( usb_port ); + if( ret == ROOT_DEV_CONNECTED ) + { + DUG_PRINTF("USB Dev In.\n"); + USBH_CheckRootHubPortStatus( usb_port ); + RootHubDev[ usb_port ].bStatus = ROOT_DEV_CONNECTED; // Set connection status_ + RootHubDev[ usb_port ].DeviceIndex = usb_port * DEF_ONE_USB_SUP_DEV_TOTAL; + + /* Enumerate root device */ + ret = Udisk_USBH_EnumRootDevice( usb_port ); + if( ret == ERR_SUCCESS ) + { + DUG_PRINTF( "USB Port %02x Device Enumeration Succeed\r\n", usb_port ); + RootHubDev[ usb_port ].bStatus = ROOT_DEV_SUCCESS; + return ERR_SUCCESS; + } + else + { + DUG_PRINTF( "USB Port %02x Device Enumeration ERR %02x.\r\n", usb_port, ret ); + RootHubDev[ usb_port ].bStatus = ROOT_DEV_FAILED; + return ERR_USB_UNAVAILABLE; + } + } + else if( ret == ROOT_DEV_DISCONNECT ) + { + DUG_PRINTF("USB Port %02x Device Out.\r\n", usb_port ); + /* Clear parameters */ + index = RootHubDev[ usb_port ].DeviceIndex; + memset( &RootHubDev[ usb_port ].bStatus, 0, sizeof( struct _ROOT_HUB_DEVICE ) ); + memset( &HostCtl[ index ].InterfaceNum, 0, sizeof( struct __HOST_CTL ) ); + CHRV3DiskStatus = DISK_UNKNOWN; + return ERR_USB_DISCON; + } + return ERR_USB_UNKNOWN; +} + +/********************************************************************* + * @fn UDisk_USBH_DiskReady + * + * @brief Check if UDisk is Ready and update status in 'CHRV3DiskStatus' + * + * @return none + */ +uint8_t UDisk_USBH_DiskReady( void ) +{ + uint8_t ret, i; + + /* Detect USB Device & Enumeration processing */ + ret = UDisk_USBH_PreDeal( ); + if( ret == ERR_SUCCESS ) + { + /* Wait for uDisk Ready */ + CHRV3DiskStatus = DISK_USB_ADDR; + for ( i = 0; i != 10; i ++ ) + { + DUG_PRINTF( "Wait Disk Ready...\r\n" ); + ret = CHRV3DiskReady( ); + if ( ret == ERR_SUCCESS ) + { + /* Disk Ready */ + DUG_PRINTF( "Disk Ready Code:%02x.\r\n", ret ); + DUG_PRINTF( "CH103DiskStatus:%02x\n", CHRV3DiskStatus); + UDisk_Opeation_Flag = 1; + return DISK_READY; + } + else + { + DUG_PRINTF("Not Ready Code :%02x.\r\n", ret); + DUG_PRINTF("CH103DiskStatus:%02x.\n", CHRV3DiskStatus); + } + Delay_Ms( 50 ); + } + } + return CHRV3DiskStatus; +} + diff --git a/Ubiquitous/XiZi_IIoT/board/ch32v307vct6/third_party_driver/usb/usb_drv/src/Udisk_Func_BasicOp.c b/Ubiquitous/XiZi_IIoT/board/ch32v307vct6/third_party_driver/usb/usb_drv/src/Udisk_Func_BasicOp.c new file mode 100644 index 000000000..6dd079165 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/ch32v307vct6/third_party_driver/usb/usb_drv/src/Udisk_Func_BasicOp.c @@ -0,0 +1,345 @@ +/********************************** (C) COPYRIGHT ******************************* +* File Name : Udisk_Func_BasicOp.c +* Author : WCH +* Version : V1.0.0 +* Date : 2022/11/22 +* Description : USB full-speed port host operation functions. +********************************************************************************* +* 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. +*******************************************************************************/ + +/*******************************************************************************/ +/* Header File */ +#include "Udisk_Operation.h" +uint8_t *pCodeStr; +/*******************************************************************************/ +/* Variable Definition */ +__attribute__((aligned(4))) uint8_t MY_DATA_BUF[ DISK_BASE_BUF_LEN ]; /* MY_DATA_BUF指向外部RAM的磁盘数据缓冲区,缓冲区长度为至少一个扇区的长度,用于用户数据缓存 */ +uint8_t *pCodeStr; + +/********************************************************************* + * @fn UDisk_USBH_ByteOperation + * + * @brief Demo Function For UDisk File Byte-operation + * including Create\Modify\Read\Erase (EXAM1) + * + * @return none + */ +void UDisk_USBH_ByteOperation( void ) +{ + uint8_t ret; + uint8_t i,t; + uint16_t TotalCount = 0; + + UDisk_USBH_DiskReady( ); + if( (CHRV3DiskStatus >= DISK_MOUNTED)&&( UDisk_Opeation_Flag == 1 ) ) + { + UDisk_Opeation_Flag = 0; + printf("CHRV3DiskStatus:%02x\r\n",CHRV3DiskStatus); + /* 读文件 */ + strcpy( (char *)mCmdParam.Open.mPathName, "/C51/NEWFILE.C" ); //设置将要操作的文件路径和文件名/C51/NEWFILE.C + ret = CHRV3FileOpen( ); //打开文件 + if ( ret == ERR_MISS_DIR || ret == ERR_MISS_FILE ) //没有找到文件 + { + //创建文件演示 + printf( "Find No File And Create\r\n" ); + strcpy( (char *)mCmdParam.Create.mPathName, "/C51/NEWFILE.C" ); //新文件名,在根目录下,中文文件名 + ret = CHRV3FileCreate( ); //新建文件并打开,如果文件已经存在则先删除后再新建 + mStopIfError( ret ); + printf( "ByteWrite\r\n" ); + //实际应该判断写数据长度和定义缓冲区长度是否相符,如果大于缓冲区长度则需要多次写入 + i = sprintf( (char *)Com_Buffer,"Note: \xd\xa这个程序是以字节为单位进行U盘文件读写,简单演示功能。\xd\xa"); + for(t=0; t<10; t++) + { + mCmdParam.ByteWrite.mByteCount = i; //指定本次写入的字节数 + mCmdParam.ByteWrite.mByteBuffer = Com_Buffer; //指向缓冲区 + ret = CHRV3ByteWrite( ); //以字节为单位向文件写入数据 + mStopIfError( ret ); + printf("成功写入 %02X次\r\n",(uint16_t)t); + } + //演示修改文件属性 + printf( "Modify\r\n" ); + mCmdParam.Modify.mFileAttr = 0xff; //输入参数: 新的文件属性,为0FFH则不修改 + mCmdParam.Modify.mFileTime = 0xffff; //输入参数: 新的文件时间,为0FFFFH则不修改,使用新建文件产生的默认时间 + mCmdParam.Modify.mFileDate = MAKE_FILE_DATE( 2015, 5, 18 ); //输入参数: 新的文件日期: 2015.05.18 + mCmdParam.Modify.mFileSize = 0xffffffff; // 输入参数: 新的文件长度,以字节为单位写文件应该由程序库关闭文件时自动更新长度,所以此处不修改 + i = CHRV3FileModify( ); //修改当前文件的信息,修改日期 + mStopIfError( i ); + printf( "Close\r\n" ); + mCmdParam.Close.mUpdateLen = 1; //自动计算文件长度,以字节为单位写文件,建议让程序库关闭文件以便自动更新文件长度 + i = CHRV3FileClose( ); + mStopIfError( i ); + + /* 删除某文件 */ +// printf( "Erase\n" ); +// strcpy( (char *)mCmdParam.Create.mPathName, "/OLD" ); //将被删除的文件名,在根目录下 +// i = CHRV3FileErase( ); //删除文件并关闭 +// if ( i != ERR_SUCCESS ) printf( "Error: %02X\n", (uint16_t)i ); //显示错误 + } + else + { + /* 一、写入文件 */ + printf( "ByteWrite\r\n" ); //如果希望将新数据添加到原文件的尾部,可以移动文件指针 + mCmdParam.ByteLocate.mByteOffset = 0xffffffff; //移到文件的尾部 + CHRV3ByteLocate( ); //实际应该判断写数据长度和定义缓冲区长度是否相符,如果大于缓冲区长度则需要多次写入 + i = sprintf( (char *)Com_Buffer,"Note: \xd\xa这个程序是以字节为单位进行U盘文件读写,简单演示功能。\xd\xa"); //演示文字 + for(t=0; t<10; t++) + { + mCmdParam.ByteWrite.mByteCount = i; //指定本次写入的字节数 + mCmdParam.ByteWrite.mByteBuffer = Com_Buffer; // 指向缓冲区 + ret = CHRV3ByteWrite( ); // 以字节为单位向文件写入数据 + mStopIfError( ret ); + printf("成功写入 %02X次\r\n",(uint16_t)t); + } + /* 二、读取文件前N字节 */ + TotalCount = 60; //设置准备读取总长度100字节 + strcpy( (char *)mCmdParam.Open.mPathName, "/C51/NEWFILE.C" ); //设置将要操作的文件路径和文件名/C51/NEWFILE.C + CHRV3FileOpen( ); //打开文件 + printf( "读出的前%d个字符是:\r\n",TotalCount ); + while ( TotalCount ) + { + //如果文件比较大,一次读不完,可以再调用CH103ByteRead继续读取,文件指针自动向后移动 + if ( TotalCount > (MAX_PATH_LEN-1) ) + { + t = MAX_PATH_LEN-1; // 剩余数据较多,限制单次读写的长度不能超过 sizeof( mCmdParam.Other.mBuffer ) + } + else + { + t = TotalCount; //最后剩余的字节数 + } + mCmdParam.ByteRead.mByteCount = t; //请求读出几十字节数据 + mCmdParam.ByteRead.mByteBuffer= &Com_Buffer[0]; + ret = CHRV3ByteRead( ); //以字节为单位读取数据块,单次读写的长度不能超过MAX_BYTE_IO,第二次调用时接着刚才的向后读 + TotalCount -= mCmdParam.ByteRead.mByteCount; //计数,减去当前实际已经读出的字符数 + for ( i=0; i!=mCmdParam.ByteRead.mByteCount; i++ ) + { + printf( "%c", mCmdParam.ByteRead.mByteBuffer[i] ); //显示读出的字符 + } + printf( "\r\n" ); + + if ( mCmdParam.ByteRead.mByteCount < t ) //实际读出的字符数少于要求读出的字符数,说明已经到文件的结尾 + { + printf( "\r\n" ); + printf( "文件已经结束\r\n" ); + break; + } + } + i = CHRV3FileClose( ); //关闭文件 + mStopIfError( i ); + } + } +} + +/********************************************************************* + * @fn UDisk_USBH_SectorOperation + * + * @brief Demo Function For UDisk File Sector-operation + * including Create\Modify\Read\Erase (EXAM6) + * + * @return none + */ +void UDisk_USBH_SectorOperation( void ) +{ + uint8_t ret, SecCount, s; + uint8_t i; + uint16_t tmp; + uint8_t tmpbuf[64]; + + ret = UDisk_USBH_DiskReady( ); + if( ( ret == DISK_READY )&&( UDisk_Opeation_Flag == 1 ) ) + { + UDisk_Opeation_Flag = 0; + /* 查询磁盘物理容量 */ + printf( "DiskSize\r\n" ); + i = CHRV3DiskQuery( ); + mStopIfError( i ); + printf( "TotalSize = %u MB \n", (unsigned int)( mCmdParam.Query.mTotalSector * CHRV3vSectorSizeB / 2 ) ); //显示为以MB为单位的容量 + + /* 读取原文件 */ + printf( "Open\r\n" ); + strcpy( mCmdParam.Open.mPathName, "/NEWFILE.TXT" );//文件名,该文件在C51子目录下 + s = CHRV3FileOpen( ); //打开文件 + if ( s == ERR_MISS_DIR || s == ERR_MISS_FILE )//没有找到文件 + { + printf( "没有找到文件\r\n" ); + } + else //找到文件或者出错 + { + printf( "Query\r\n" ); + i = CHRV3FileQuery( ); //查询当前文件的信息 + mStopIfError( i ); + printf( "Read\r\n" ); + CHRV3vFileSize = CHRV3vFileSize+(sizeof( MY_DATA_BUF )-1); //原文件的长度 + SecCount = CHRV3vFileSize/ sizeof( MY_DATA_BUF ) ;//计算文件的扇区数,因为读写是以扇区为单位的,先加CHRV3vSectorSize-1是为了读出文件尾部不足1个扇区的部分 + printf( "Size=%ld, Sec=%d\r\n", CHRV3vFileSize, (uint16_t)SecCount ); + while(SecCount--) + { + mCmdParam.Read.mSectorCount = sizeof( MY_DATA_BUF )/512; //读取全部数据,如果超过2个扇区则只读取2个扇区 + mCmdParam.Read.mDataBuffer = &MY_DATA_BUF[0];//指向文件数据缓冲区的起始地址 + i = CHRV3FileRead( ); //从文件读取数据 + mStopIfError( i ); + if(SecCount == 0) break; + /* + for(tmp=0; tmpCONTROL = USBHS_UC_INT_BUSY | USBHS_UC_DMA_EN | USBHS_UC_SPEED_HIGH | USBHS_UC_HOST_MODE; + USBHSH->HOST_CTRL = USBHS_UH_PHY_SUSPENDM | USBHS_UH_SOF_EN; + USBHSH->HOST_EP_CONFIG = USBHS_UH_EP_TX_EN | USBHS_UH_EP_RX_EN; + USBHSH->HOST_RX_MAX_LEN = 512; + USBHSH->HOST_RX_DMA = (uint32_t)USBHS_RX_Buf; + USBHSH->HOST_TX_DMA = (uint32_t)USBHS_TX_Buf; + } + else + { + USBHSH->CONTROL = USBHS_UC_RESET_SIE | USBHS_UC_CLR_ALL; + } +} + +/********************************************************************* + * @fn USBHSH_CheckRootHubPortStatus + * + * @brief Check status of USB port. + * + * @para dev_sta: The status of the root device connected to this port. + * + * @return The current status of the port. + */ +uint8_t USBHSH_CheckRootHubPortStatus( uint8_t status ) +{ + /* Detect USB devices plugged or unplugged */ + if( USBHSH->INT_FG & USBHS_UIF_DETECT ) + { + USBHSH->INT_FG = USBHS_UIF_DETECT; // Clear flag + if( USBHSH->MIS_ST & USBHS_UMS_DEV_ATTACH ) // Detect that the USB device has been connected to the port + { + if( ( status == ROOT_DEV_DISCONNECT ) || ( ( status != ROOT_DEV_FAILED ) && ( USBHSH_CheckRootHubPortEnable( ) == 0x00 ) ) ) + { + return ROOT_DEV_CONNECTED; + } + else + { + return ROOT_DEV_FAILED; + } + } + else + { + return ROOT_DEV_DISCONNECT; + } + } + else + { + return ROOT_DEV_FAILED; + } +} + +/********************************************************************* + * @fn USBHSH_CheckRootHubPortEnable + * + * @brief Check the enable status of the USB port. + * + * @return The current enable status of the port. + */ +uint8_t USBHSH_CheckRootHubPortEnable( void ) +{ + return ( USBHSH->MIS_ST & USBHS_UMS_DEV_ATTACH ); +} + +/********************************************************************* + * @fn USBHSH_CheckRootHubPortSpeed + * + * @brief Check the speed of the USB port. + * + * @return The current speed of the port. + */ +uint8_t USBHSH_CheckRootHubPortSpeed( void ) +{ + uint8_t speed; + + speed = USBHSH->SPEED_TYPE & USBHS_USB_SPEED_TYPE; + + if( speed == USBHS_USB_SPEED_LOW ) + { + return USB_LOW_SPEED; + } + else if( speed == USBHS_USB_SPEED_FULL ) + { + return USB_FULL_SPEED; + } + else if( speed == USBHS_USB_SPEED_HIGH ) + { + return USB_HIGH_SPEED; + } + + return USB_SPEED_CHECK_ERR; +} + +/********************************************************************* + * @fn USBHSH_SetSelfAddr + * + * @brief Set the USB device address. + * + * @para addr: USB device address. + * + * @return none + */ +void USBHSH_SetSelfAddr( uint8_t addr ) +{ + USBHSH->DEV_AD = addr & USBHS_MASK_USB_ADDR; +} + +/********************************************************************* + * @fn USBHSH_SetSelfSpeed + * + * @brief Set USB speed. + * + * @para speed: USB speed. + * + * @return none + */ +void USBHSH_SetSelfSpeed( uint8_t speed ) +{ + if( speed == USB_HIGH_SPEED ) + { + USBHSH->CONTROL = ( USBHSH->CONTROL & ~USBHS_UC_SPEED_TYPE ) | USBHS_UC_SPEED_HIGH; + } + else if( speed == USB_FULL_SPEED ) + { + USBHSH->CONTROL = ( USBHSH->CONTROL & ~USBHS_UC_SPEED_TYPE ) | USBHS_UC_SPEED_FULL; + } + else + { + USBHSH->CONTROL = ( USBHSH->CONTROL & ~USBHS_UC_SPEED_TYPE ) | USBHS_UC_SPEED_LOW; + } +} + +/********************************************************************* + * @fn USBHSH_ResetRootHubPort + * + * @brief Reset USB port. + * + * @para mod: Reset host port operating mode. + * 0 -> reset and wait end + * 1 -> begin reset + * 2 -> end reset + * + * @return none + */ +void USBHSH_ResetRootHubPort( uint8_t mode ) +{ + USBHSH_SetSelfAddr( 0x00 ); + USBHSH_SetSelfSpeed( USB_HIGH_SPEED ); + if( mode <= 1 ) + { + USBHSH->HOST_CTRL |= USBHS_UH_TX_BUS_RESET; + } + if( mode == 0 ) + { + Delay_Ms( DEF_BUS_RESET_TIME ); + } + if( mode != 1 ) + { + USBHSH->HOST_CTRL &= ~USBHS_UH_TX_BUS_RESET; + } + Delay_Ms( 2 ); +} + +/********************************************************************* + * @fn USBHSH_EnableRootHubPort + * + * @brief Enable USB host port. + * + * @para *pspeed: USB speed. + * + * @return Operation result of the enabled port. + */ +uint8_t USBHSH_EnableRootHubPort( uint8_t *pspeed ) +{ + if( USBHSH->MIS_ST & USBHS_UMS_DEV_ATTACH ) + { + *pspeed = USBHSH_CheckRootHubPortSpeed( ); + USBHSH->HOST_CTRL |= USBHS_UH_SOF_EN; + + return ERR_SUCCESS; + } + + return ERR_USB_DISCON; +} + +/********************************************************************* + * @fn USBHSH_Transact + * + * @brief Perform USB transaction. + * + * @para endp_pid: Token PID. + * endp_tog: Toggle + * timeout: Timeout time. + * + * @return USB transfer result. + */ +uint8_t USBHSH_Transact( uint8_t endp_pid, uint8_t endp_tog, uint32_t timeout ) +{ + uint8_t r, trans_retry; + uint16_t i; + USBHSH->HOST_TX_CTRL = USBHSH->HOST_RX_CTRL = endp_tog; + trans_retry = 0; + do + { + USBHSH->HOST_EP_PID = endp_pid; // Set the token for the host to send the packet + USBHSH->INT_FG = USBHS_UIF_TRANSFER; + for( i = DEF_WAIT_USB_TOUT_200US; ( i != 0 ) && ( ( USBHSH->INT_FG & USBHS_UIF_TRANSFER ) == 0 ); i-- ) + { + Delay_Us( 1 ); + } + USBHSH->HOST_EP_PID = 0x00; + if( ( USBHSH->INT_FG & USBHS_UIF_TRANSFER ) == 0 ) + { + return ERR_USB_UNKNOWN; + } + + if( USBHSH->INT_FG & USBHS_UIF_DETECT ) + { + USBHSH->INT_FG = USBHS_UIF_DETECT; + Delay_Us( 200 ); + if( USBHSH->MIS_ST & USBHS_UIF_TRANSFER ) + { + if( USBHSH->HOST_CTRL & USBHS_UH_SOF_EN ) + { + return ERR_USB_CONNECT; + } + } + else + { + return ERR_USB_DISCON; + } + } + else if( USBHSH->INT_FG & USBHS_UIF_TRANSFER ) // The packet transmission was successful + { + r = USBHSH->INT_ST & USBHS_UIS_H_RES_MASK; + if( ( endp_pid >> 4 ) == USB_PID_IN ) + { + if( USBHSH->INT_ST & USBHS_UIS_TOG_OK ) + { + return ERR_SUCCESS; // Packet token match + } + } + else + { + if( ( r == USB_PID_ACK ) || ( r == USB_PID_NYET ) ) + { + return ERR_SUCCESS; + } + } + if( r == USB_PID_STALL ) + { + return ( r | ERR_USB_TRANSFER ); + } + + if( r == USB_PID_NAK ) + { + if( timeout == 0 ) + { + return ( r | ERR_USB_TRANSFER ); + } + if( timeout < 0xFFFF ) + { + timeout--; + } + --trans_retry; + } + else switch( endp_pid >> 4 ) + { + case USB_PID_SETUP: + + case USB_PID_OUT: + if( r ) + { + return ( r | ERR_USB_TRANSFER ); + } + break; + case USB_PID_IN: + if( ( r == USB_PID_DATA0 ) || ( r == USB_PID_DATA1 ) ) + { + ; + } + else if( r ) + { + return ( r | ERR_USB_TRANSFER ); + } + break; + default: + return ERR_USB_UNKNOWN; + } + } + else + { + USBHSH->INT_FG = USBHS_UIF_DETECT | USBHS_UIF_TRANSFER | USBHS_UIF_SUSPEND | USBHS_UIF_HST_SOF | USBHS_UIF_FIFO_OV | USBHS_UIF_SETUP_ACT; + } + Delay_Us( 15 ); + } while( ++trans_retry < 10 ); + + return ERR_USB_TRANSFER; +} + +/********************************************************************* + * @fn USBHSH_CtrlTransfer + * + * @brief Host control transfer. + * + * @brief USB host control transfer. + * + * @para ep0_size: Device endpoint 0 size + * pbuf: Data buffer + * plen: Data length + * + * @return USB control transfer result. + */ +uint8_t USBHSH_CtrlTransfer( uint8_t ep0_size, uint8_t *pbuf, uint16_t *plen ) +{ + uint8_t s, tog = 1; + uint16_t rem_len, rx_len, rx_cnt, tx_cnt; + + if( plen ) + { + *plen = 0; + } + USBHSH->HOST_TX_LEN = 8; + s = USBHSH_Transact( ( USB_PID_SETUP << 4 ) | 0x00, 0, 200000 ); + if( s != ERR_SUCCESS ) + { + return s; + } + + rem_len = pUSBHS_SetupRequest->wLength; + if( rem_len && pbuf ) //data stage + { + if( pUSBHS_SetupRequest->bRequestType & USB_REQ_TYP_IN ) //device to host + { + while( rem_len ) + { + s = USBHSH_Transact( ( USB_PID_IN << 4 ) | 0x00, tog << 3, 20000 ); + if( s != ERR_SUCCESS ) + { + return s; + } + tog ^=1; + rx_len = ( USBHSH->RX_LEN < rem_len )? USBHSH->RX_LEN : rem_len; + rem_len -= rx_len; + if( plen ) + { + *plen += rx_len; + } + for( rx_cnt = 0; rx_cnt != rx_len; rx_cnt++ ) + { + *pbuf = USBHS_RX_Buf[ rx_cnt ]; + pbuf++; + } + if( ( USBHSH->RX_LEN == 0 ) || ( USBHSH->RX_LEN & ( ep0_size - 1 ) ) ) + { + break; + } + } + USBHSH->HOST_TX_LEN = 0; + } + else + { // host to device + while( rem_len ) + { + USBHSH->HOST_TX_LEN = ( rem_len >= ep0_size )? ep0_size : rem_len; + for( tx_cnt = 0; tx_cnt != USBHSH->HOST_TX_LEN; tx_cnt++ ) + { + USBHS_TX_Buf[ tx_cnt ] = *pbuf; + pbuf++; + } + s = USBHSH_Transact( ( USB_PID_OUT << 4 ) | 0x00, tog << 3, 20000 ); + if( s != ERR_SUCCESS ) + { + return s; + } + tog ^=1; + rem_len -= USBHSH->HOST_TX_LEN; + if( plen ) + { + *plen += USBHSH->HOST_TX_LEN; + } + } + } + } + + s = USBHSH_Transact( ( USBHSH->HOST_TX_LEN )? ( USB_PID_IN << 4 | 0x00 ) : ( USB_PID_OUT << 4 | 0x00 ), USBHS_UEP_R_TOG_DATA1 | USBHS_UEP_T_TOG_DATA1, 20000 ); + if( s != ERR_SUCCESS ) + { + return s; + } + + if( USBHSH->HOST_TX_LEN == 0 ) + { + return ERR_SUCCESS; //status stage is out, send a zero-length packet. + } + + if( USBHSH->RX_LEN == 0 ) + { + return ERR_SUCCESS; //status stage is in, a zero-length packet is returned indicating success. + } + + return ERR_USB_BUF_OVER; +} + +/********************************************************************* + * @fn USBHSH_GetDeviceDescr + * + * @brief Get the device descriptor of the USB device. + * + * @para pep0_size: Device endpoint 0 size + * pbuf: Data buffer + * + * @return The result of getting the device descriptor. + */ +uint8_t USBHSH_GetDeviceDescr( uint8_t *pep0_size, uint8_t *pbuf ) +{ + uint8_t s; + uint16_t len; + + *pep0_size = DEFAULT_ENDP0_SIZE; + memcpy( pUSBHS_SetupRequest, SetupGetDevDesc, sizeof( USB_SETUP_REQ ) ); + s = USBHSH_CtrlTransfer( *pep0_size, pbuf, &len ); + if( s != ERR_SUCCESS ) + { + return s; + } + + *pep0_size = ( (PUSB_DEV_DESCR)pbuf )->bMaxPacketSize0; + if( len < ( (PUSB_SETUP_REQ)SetupGetDevDesc )->wLength ) + { + return ERR_USB_BUF_OVER; + } + return ERR_SUCCESS; +} + +/********************************************************************* + * @fn USBHSH_GetConfigDescr + * + * @brief Get the configuration descriptor of the USB device. + * + * @para ep0_size: Device endpoint 0 size + * pbuf: Data buffer + * buf_len: Data buffer length + * pcfg_len: The length of the device configuration descriptor + * + * @return The result of getting the configuration descriptor. + */ +uint8_t USBHSH_GetConfigDescr( uint8_t ep0_size, uint8_t *pbuf, uint16_t buf_len, uint16_t *pcfg_len ) +{ + uint8_t s; + + /* Get the string descriptor of the first 4 bytes */ + memcpy( pUSBHS_SetupRequest, SetupGetCfgDesc, sizeof( USB_SETUP_REQ ) ); + s = USBHSH_CtrlTransfer( ep0_size, pbuf, pcfg_len ); + if( s != ERR_SUCCESS ) + { + return s; + } + if( *pcfg_len < ( (PUSB_SETUP_REQ)SetupGetCfgDesc )->wLength ) + { + return ERR_USB_BUF_OVER; + } + + /* Get the complete string descriptor */ + *pcfg_len = ((PUSB_CFG_DESCR)pbuf)->wTotalLength; + if( *pcfg_len > buf_len ) + { + *pcfg_len = buf_len; + } + memcpy( pUSBHS_SetupRequest, SetupGetCfgDesc, sizeof( USB_SETUP_REQ ) ); + pUSBHS_SetupRequest->wLength = *pcfg_len; + s = USBHSH_CtrlTransfer( ep0_size, pbuf, pcfg_len ); + return s; +} + +/********************************************************************* + * @fn USBH_GetStrDescr + * + * @brief Get the string descriptor of the USB device. + * + * @para ep0_size: Device endpoint 0 size + * str_num: Index of string descriptor + * pbuf: Data buffer + * + * @return The result of getting the string descriptor. + */ +uint8_t USBHSH_GetStrDescr( uint8_t ep0_size, uint8_t str_num, uint8_t *pbuf ) +{ + uint8_t s; + uint16_t len; + + /* Get the string descriptor of the first 4 bytes */ + memcpy( pUSBHS_SetupRequest, SetupGetStrDesc, sizeof( USB_SETUP_REQ ) ); + pUSBHS_SetupRequest->wValue = ( (uint16_t)USB_DESCR_TYP_STRING << 8 ) | str_num; + s = USBHSH_CtrlTransfer( ep0_size, pbuf, &len ); + if( s != ERR_SUCCESS ) + { + return s; + } + + /* Get the complete string descriptor */ + len = pbuf[ 0 ]; + memcpy( pUSBHS_SetupRequest, SetupGetStrDesc, sizeof( USB_SETUP_REQ ) ); + pUSBHS_SetupRequest->wValue = ( (uint16_t)USB_DESCR_TYP_STRING << 8 ) | str_num; + pUSBHS_SetupRequest->wLength = len; + s = USBHSH_CtrlTransfer( ep0_size, pbuf, &len ); + if( s != ERR_SUCCESS ) + { + return s; + } + return ERR_SUCCESS; +} + +/********************************************************************* + * @fn USBH_SetUsbAddress + * + * @brief Set USB device address. + * + * @para ep0_size: Device endpoint 0 size + * addr: Device address + * + * @return The result of setting device address. + */ +uint8_t USBHSH_SetUsbAddress( uint8_t ep0_size, uint8_t addr ) +{ + uint8_t s; + + memcpy( pUSBHS_SetupRequest, SetupSetAddr, sizeof( USB_SETUP_REQ ) ); + pUSBHS_SetupRequest->wValue = (uint16_t)addr; + s = USBHSH_CtrlTransfer( ep0_size, NULL, NULL ); + if( s != ERR_SUCCESS ) + { + return s; + } + USBHSH_SetSelfAddr( addr ); + Delay_Ms( DEF_BUS_RESET_TIME >> 1 ); // Wait for the USB device to complete its operation. + return ERR_SUCCESS; +} + +/********************************************************************* + * @fn USBH_SetUsbConfig + * + * @brief Set USB configuration. + * + * @para ep0_size: Device endpoint 0 size + * cfg: Device configuration value + * + * @return The result of setting device configuration. + */ +uint8_t USBHSH_SetUsbConfig( uint8_t ep0_size, uint8_t cfg_val ) +{ + memcpy( pUSBHS_SetupRequest, SetupSetConfig, sizeof( USB_SETUP_REQ ) ); + pUSBHS_SetupRequest->wValue = (uint16_t)cfg_val; + return USBHSH_CtrlTransfer( ep0_size, NULL, NULL ); +} + +/********************************************************************* + * @fn USBH_ClearEndpStall + * + * @brief Clear endpoint stall. + * + * @para ep0_size: Device endpoint 0 size + * endp_num: Endpoint number. + * + * @return The result of clearing endpoint stall. + */ +uint8_t USBHSH_ClearEndpStall( uint8_t ep0_size, uint8_t endp_num ) +{ + memcpy( pUSBHS_SetupRequest, SetupClearEndpStall, sizeof( USB_SETUP_REQ ) ); + pUSBHS_SetupRequest->wIndex = (uint16_t)endp_num; + return ( USBHSH_CtrlTransfer( ep0_size, NULL, NULL ) ); +} + +/********************************************************************* + * @fn USBHSH_GetEndpData + * + * @brief Get data from USB device input endpoint. + * + * @para endp_num: Endpoint number + * pendp_tog: Endpoint toggle + * pbuf: Data Buffer + * plen: Data length + * + * @return The result of getting data. + */ +uint8_t USBHSH_GetEndpData( uint8_t endp_num, uint8_t *pendp_tog, uint8_t *pbuf, uint16_t *plen ) +{ + uint8_t s; + + s = USBHSH_Transact( ( USB_PID_IN << 4 ) | endp_num, *pendp_tog, 0 ); + if( s == ERR_SUCCESS ) + { + *pendp_tog ^= USBHS_UH_T_TOG_DATA1 | USBHS_UH_R_TOG_DATA1; + *plen = USBHSH->RX_LEN; + memcpy( pbuf, USBHS_RX_Buf, *plen ); + } + + return s; +} + +/********************************************************************* + * @fn USBHSH_SendEndpData + * + * @brief Send data to the USB device output endpoint. + * + * @para endp_num: Endpoint number + * pendp_tog: Endpoint toggle + * pbuf: Data Buffer + * plen: Data length + * + * @return The result of sending data. + */ +uint8_t USBHSH_SendEndpData( uint8_t endp_num, uint8_t *pendp_tog, uint8_t *pbuf, uint16_t len ) +{ + uint8_t s; + + memcpy( USBHS_TX_Buf, pbuf, len ); + USBHSH->HOST_TX_LEN = len; + + s = USBHSH_Transact( ( USB_PID_OUT << 4 ) | endp_num, *pendp_tog, 0 ); + if( s == ERR_SUCCESS ) + { + *pendp_tog ^= USBHS_UH_T_TOG_DATA1 | USBHS_UH_R_TOG_DATA1; + } + + return s; +} diff --git a/Ubiquitous/XiZi_IIoT/path_kernel.mk b/Ubiquitous/XiZi_IIoT/path_kernel.mk index adb080b5d..896c4c0f3 100755 --- a/Ubiquitous/XiZi_IIoT/path_kernel.mk +++ b/Ubiquitous/XiZi_IIoT/path_kernel.mk @@ -238,6 +238,7 @@ KERNELPATHS += \ -I$(KERNEL_ROOT)/arch/risc-v/ch32v307vct6/User \ -I$(KERNEL_ROOT)/arch/risc-v/ch32v307vct6 \ -I$(BSP_ROOT)/third_party_driver/include \ + -I$(BSP_ROOT)/third_party_driver/usb/usb_drv/inc \ -I$(BSP_ROOT)/third_party_driver/Peripheral/inc \ -I$(BSP_ROOT)/include \ -I$(KERNEL_ROOT)/include #