forked from xuos/xiuos
				
			移植并验证:can驱动485驱动;未验证:USB驱动
This commit is contained in:
		
							parent
							
								
									814a742260
								
							
						
					
					
						commit
						1e6f366843
					
				| 
						 | 
				
			
			@ -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 <board.h>
 | 
			
		||||
| 
						 | 
				
			
			@ -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);
 | 
			
		||||
    // }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -19,4 +19,23 @@ menuconfig BSP_USING_ETH
 | 
			
		|||
    bool "Using Ethernet"
 | 
			
		||||
    default y
 | 
			
		||||
 
 | 
			
		||||
    
 | 
			
		||||
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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			@ -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"
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,4 @@
 | 
			
		|||
SRC_FILES := connect_can.c
 | 
			
		||||
SRC_DIR := test
 | 
			
		||||
 | 
			
		||||
include $(KERNEL_ROOT)/compiler.mk
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,249 @@
 | 
			
		|||
 | 
			
		||||
#include <connect_can.h>
 | 
			
		||||
#include <ch32v30x_gpio.h>
 | 
			
		||||
#include <ch32v30x_rcc.h>
 | 
			
		||||
#include <ch32v30x_misc.h>
 | 
			
		||||
 | 
			
		||||
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;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,4 @@
 | 
			
		|||
SRC_FILES := can_test.c
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
include $(KERNEL_ROOT)/compiler.mk
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,160 @@
 | 
			
		|||
 | 
			
		||||
#include "shell.h"
 | 
			
		||||
#include "ch32v30x.h"
 | 
			
		||||
 | 
			
		||||
#include "connect_can.h"
 | 
			
		||||
 | 
			
		||||
#include <connect_can.h>
 | 
			
		||||
#include <ch32v30x_gpio.h>
 | 
			
		||||
#include <ch32v30x_rcc.h>
 | 
			
		||||
#include <ch32v30x_misc.h>
 | 
			
		||||
 | 
			
		||||
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);
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,33 @@
 | 
			
		|||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#ifndef CONNECT_CAN_H
 | 
			
		||||
#define CONNECT_CAN_H
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#include <bus_can.h>
 | 
			
		||||
#include <dev_can.h>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#include <ch32v30x.h>
 | 
			
		||||
#include <ch32v30x_can.h>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
struct CanDev
 | 
			
		||||
{
 | 
			
		||||
    CAN_TypeDef *instance;
 | 
			
		||||
 | 
			
		||||
    char *bus_name;
 | 
			
		||||
 | 
			
		||||
    // CAN_InitTypeDef init;
 | 
			
		||||
 | 
			
		||||
    uint8 can_flag;
 | 
			
		||||
    struct CanBus can_bus;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
int InitHwCan(void);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -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 <bus_usb.h>
 | 
			
		||||
#include <dev_usb.h>
 | 
			
		||||
#ifdef RESOURCES_USB_HOST
 | 
			
		||||
#ifdef BSP_USING_USBH
 | 
			
		||||
#include <ch32v30x_usbhs_host.h>
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
int InitHwUsb(void);
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,4 +1,4 @@
 | 
			
		|||
SRC_FILES := connect_uart.c
 | 
			
		||||
 | 
			
		||||
SRC_DIR := test
 | 
			
		||||
 | 
			
		||||
include $(KERNEL_ROOT)/compiler.mk
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,4 @@
 | 
			
		|||
SRC_FILES := rs485_test.c
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
include $(KERNEL_ROOT)/compiler.mk
 | 
			
		||||
| 
						 | 
				
			
			@ -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);
 | 
			
		||||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,9 @@
 | 
			
		|||
SRC_FILES := connect_usb.c
 | 
			
		||||
SRC_DIR += usb_drv/src
 | 
			
		||||
 | 
			
		||||
include $(KERNEL_ROOT)/compiler.mk
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -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 <board.h>
 | 
			
		||||
#include <ch32v30x_usbhs_host.h>
 | 
			
		||||
#include <connect_usb.h>
 | 
			
		||||
 | 
			
		||||
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;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			@ -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_ */
 | 
			
		||||
| 
						 | 
				
			
			@ -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 */
 | 
			
		||||
| 
						 | 
				
			
			@ -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  
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			@ -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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -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 );
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -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;                // 返回错误
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -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; tmp<sizeof( MY_DATA_BUF ); tmp++)
 | 
			
		||||
                {
 | 
			
		||||
                printf("%02X ",(uint16_t)MY_DATA_BUF[tmp]);
 | 
			
		||||
                }
 | 
			
		||||
                printf("\n");
 | 
			
		||||
                */
 | 
			
		||||
            }
 | 
			
		||||
            tmp = (CHRV3vFileSize-(sizeof( MY_DATA_BUF )-1))%sizeof( MY_DATA_BUF );
 | 
			
		||||
            if((tmp == 0)&&(CHRV3vFileSize != 0)) tmp = sizeof( MY_DATA_BUF );
 | 
			
		||||
            CHRV3vFileSize = CHRV3vFileSize-(sizeof( MY_DATA_BUF )-1);    //恢复原文件的长度
 | 
			
		||||
            /*
 | 
			
		||||
            for(i=0; i<tmp; i++)
 | 
			
		||||
            {
 | 
			
		||||
              printf("%02X ",(uint16_t)MY_DATA_BUF[i]);
 | 
			
		||||
            }
 | 
			
		||||
            printf("\n");
 | 
			
		||||
            */
 | 
			
		||||
            /*
 | 
			
		||||
                         如果文件比较大,一次读不完,可以再调用CHRV3FileRead继续读取,文件指针自动向后移动
 | 
			
		||||
             while ( 1 )
 | 
			
		||||
             {
 | 
			
		||||
               c = 4;   每次读取4个扇区,缓冲区定义的越大,一次读取的扇区数越多
 | 
			
		||||
               mCmdParam.Read.mSectorCount = c;   指定读取的扇区数
 | 
			
		||||
               mCmdParam.Read.mDataBuffer = &MY_DATA_BUF[0];  指向文件数据缓冲区的起始地址
 | 
			
		||||
               CHRV3FileRead();   读完后文件指针自动后移 处理数据
 | 
			
		||||
               if ( mCmdParam.Read.mSectorCount < c ) break;   实际读出的扇区数较小则说明文件已经结束
 | 
			
		||||
             }
 | 
			
		||||
                                               如果希望从指定位置开始读写,可以移动文件指针
 | 
			
		||||
              mCmdParam.Locate.mSectorOffset = 3;  跳过文件的前3个扇区开始读写
 | 
			
		||||
              i = CHRV3FileLocate( );
 | 
			
		||||
              mCmdParam.Read.mSectorCount = 10;
 | 
			
		||||
              mCmdParam.Read.mDataBuffer = &MY_DATA_BUF[0];  指向文件数据缓冲区的起始地址
 | 
			
		||||
              CHRV3FileRead();   直接读取从文件的第(CHRV3vSectorSizeH*256*3)个字节开始的数据,前3个扇区被跳过
 | 
			
		||||
                                               如果希望将新数据添加到原文件的尾部,可以移动文件指针
 | 
			
		||||
              i = CHRV3FileOpen( );
 | 
			
		||||
              mCmdParam.Locate.mSectorOffset = 0xffffffff;  移到文件的尾部,以扇区为单位,如果原文件是3字节,则从CHRV3vSectorSizeH个字节处开始添加
 | 
			
		||||
              i = CHRV3FileLocate( );
 | 
			
		||||
              mCmdParam.Write.mSectorCount = 10;
 | 
			
		||||
              mCmdParam.Write.mDataBuffer = &MY_DATA_BUF[0];
 | 
			
		||||
              CHRV3FileWrite();   在原文件的后面添加数据
 | 
			
		||||
                                               使用CHRV3FileRead可以自行定义数据缓冲区的起始地址
 | 
			
		||||
              mCmdParam.Read.mSectorCount = 2;
 | 
			
		||||
              mCmdParam.Read.mDataBuffer = 0x50;  将读出的数据放到50H开始的缓冲区中,需要指定缓冲区的起始地址
 | 
			
		||||
              CHRV3FileRead();   从文件中读取2个扇区到指定缓冲区
 | 
			
		||||
                                                使用CHRV3FileWrite可以自行定义数据缓冲区的起始地址
 | 
			
		||||
              mCmdParam.Wiite.mSectorCount = 2;
 | 
			
		||||
              mCmdParam.Write.mDataBuffer = 0x50;  将50H开始的缓冲区中的数据写入
 | 
			
		||||
              CHRV3FileWrite();   将指定缓冲区中的数据写入2个扇区到文件中
 | 
			
		||||
            */
 | 
			
		||||
            printf( "Close\r\n" );
 | 
			
		||||
            i = CHRV3FileClose( );                            //关闭文件
 | 
			
		||||
            mStopIfError( i );
 | 
			
		||||
        }
 | 
			
		||||
        printf( "Create\r\n" );
 | 
			
		||||
        strcpy( mCmdParam.Create.mPathName, "/NEWFILE.TXT" );//新文件名,在根目录下,中文文件名
 | 
			
		||||
        s = CHRV3FileCreate( );                               //新建文件并打开,如果文件已经存在则先删除后再新建 */
 | 
			
		||||
        mStopIfError( s );
 | 
			
		||||
        printf( "Write\r\n" );
 | 
			
		||||
        strcpy( tmpbuf, "0000ABCDEFGHIJKLMNOPQRSTUVWXYZ\xd\xa" );//准备写文件数据
 | 
			
		||||
        for(i=0; i<(DISK_BASE_BUF_LEN/sizeof(tmpbuf)); i++)
 | 
			
		||||
        {
 | 
			
		||||
            tmp=i*sizeof(tmpbuf);
 | 
			
		||||
            strcpy(&MY_DATA_BUF[tmp],tmpbuf);
 | 
			
		||||
        }
 | 
			
		||||
        for(tmp=0; tmp<sizeof(MY_DATA_BUF); tmp++)
 | 
			
		||||
        {
 | 
			
		||||
            printf("%02X",(uint16_t)MY_DATA_BUF[tmp]);
 | 
			
		||||
        }
 | 
			
		||||
        printf("\r\n");
 | 
			
		||||
        for(s=0; s<10; s++)
 | 
			
		||||
        {
 | 
			
		||||
            mCmdParam.Write.mSectorCount = 1;                 //写入所有扇区的数据
 | 
			
		||||
            mCmdParam.Write.mDataBuffer = &MY_DATA_BUF[0];    //指向文件数据缓冲区的起始地址
 | 
			
		||||
            i = CHRV3FileWrite( );                            //向文件写入数据
 | 
			
		||||
            mStopIfError( i );
 | 
			
		||||
            printf("成功写入 %02X次\r\n",(uint16_t)s);
 | 
			
		||||
        }
 | 
			
		||||
        /* printf( "Modify\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( mCmdParam.Create.mPathName, "/OLD.TXT" );  将被删除的文件名,在根目录下
 | 
			
		||||
          i = CHRV3FileErase( );  删除文件并关闭
 | 
			
		||||
          if ( i != ERR_SUCCESS ) printf( "Error File not exist: %02X\n", (uint16_t)i );  显示错误
 | 
			
		||||
        */
 | 
			
		||||
        printf( "U盘演示完成\r\n" );
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*********************************************************************
 | 
			
		||||
 * @fn      UDisk_USBH_EnumFiles
 | 
			
		||||
 *
 | 
			
		||||
 * @brief   Demo Function For Enumerating files in UDisk(EXAM11)
 | 
			
		||||
 *
 | 
			
		||||
 * @return  none
 | 
			
		||||
 */
 | 
			
		||||
void UDisk_USBH_EnumFiles( void )
 | 
			
		||||
{
 | 
			
		||||
    uint8_t  i, s, ret;
 | 
			
		||||
    uint16_t j;
 | 
			
		||||
 | 
			
		||||
    ret = UDisk_USBH_DiskReady( );
 | 
			
		||||
    if( ( ret == DISK_READY )&&( UDisk_Opeation_Flag == 1 ) )
 | 
			
		||||
    {
 | 
			
		||||
        UDisk_Opeation_Flag = 0;
 | 
			
		||||
        /* 读取原文件 */
 | 
			
		||||
        printf( "Open\r\n" );
 | 
			
		||||
        strcpy( mCmdParam.Open.mPathName, "/C51/CHRV3HFT.C" );//文件名,该文件在C51子目录下
 | 
			
		||||
        s = CHRV3FileOpen( );                        //打开文件
 | 
			
		||||
        /* 列出文件 */
 | 
			
		||||
        if ( s == ERR_MISS_DIR )
 | 
			
		||||
        {
 | 
			
		||||
            printf("不存在该文件则列出所有文件\r\n");  //C51子目录不存在则列出根目录下的所有文件
 | 
			
		||||
            pCodeStr = "/*";
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            pCodeStr = "/C51/*";                     //CHRV3HFT.C文件不存在则列出\C51子目录下的以CHRV3开头的文件
 | 
			
		||||
        }
 | 
			
		||||
        printf( "List file %s\r\n", pCodeStr );
 | 
			
		||||
        for ( j = 0; j < 10000; j ++ )               //最多搜索前10000个文件,实际上没有限制
 | 
			
		||||
        {
 | 
			
		||||
            strcpy( (char *)mCmdParam.Open.mPathName, pCodeStr );//搜索文件名,*为通配符,适用于所有文件或者子目录
 | 
			
		||||
            i = strlen( mCmdParam.Open.mPathName );
 | 
			
		||||
            mCmdParam.Open.mPathName[ i ] = 0xFF;    //根据字符串长度将结束符替换为搜索的序号,从0到254,如果是0xFF即255则说明搜索序号在CHRV3vFileSize变量中
 | 
			
		||||
            CHRV3vFileSize = j;                      //指定搜索/枚举的序号
 | 
			
		||||
            i = CHRV3FileOpen( );                    //打开文件,如果文件名中含有通配符*,则为搜索文件而不打开
 | 
			
		||||
            /* CHRV3FileEnum 与 CHRV3FileOpen 的唯一区别是当后者返回ERR_FOUND_NAME时那么对应于前者返回ERR_SUCCESS */
 | 
			
		||||
            if ( i == ERR_MISS_FILE )
 | 
			
		||||
            {
 | 
			
		||||
                break;                                //再也搜索不到匹配的文件,已经没有匹配的文件名
 | 
			
		||||
            }
 | 
			
		||||
            if ( i == ERR_FOUND_NAME )
 | 
			
		||||
            {
 | 
			
		||||
                /* 搜索到与通配符相匹配的文件名,文件名及其完整路径在命令缓冲区中 */
 | 
			
		||||
                printf( "  match file %04d#: %s\r\n", (unsigned int)j, mCmdParam.Open.mPathName );//显示序号和搜索到的匹配文件名或者子目录名
 | 
			
		||||
                continue;                             //继续搜索下一个匹配的文件名,下次搜索时序号会加1
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                /* 出错 */
 | 
			
		||||
                mStopIfError( i );
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        printf( "Close\r\n" );
 | 
			
		||||
        CHRV3FileClose( );                            //关闭文件
 | 
			
		||||
        printf( "U盘演示完成\r\n" );
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,680 @@
 | 
			
		|||
/********************************** (C) COPYRIGHT *******************************
 | 
			
		||||
* File Name          : ch32v30x_usbhs_host.c
 | 
			
		||||
* Author             : WCH
 | 
			
		||||
* Version            : V1.0.0
 | 
			
		||||
* Date               : 2021/06/06
 | 
			
		||||
* Description        : This file provides all the USB firmware 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 "usb_host_config.h"
 | 
			
		||||
#include "ch32v30x_usb.h"
 | 
			
		||||
#include "ch32v30x_rcc.h"
 | 
			
		||||
#include "ch32v30x_usbhs_host.h"
 | 
			
		||||
 | 
			
		||||
/*******************************************************************************/
 | 
			
		||||
/* Variable Definition */
 | 
			
		||||
__attribute__((aligned(4))) uint8_t  RxBuffer[ MAX_PACKET_SIZE ];           // IN, must even address
 | 
			
		||||
__attribute__((aligned(4))) uint8_t  TxBuffer[ MAX_PACKET_SIZE ];           // OUT, must even address
 | 
			
		||||
 | 
			
		||||
/*********************************************************************
 | 
			
		||||
 * @fn      USBHS_RCC_Init
 | 
			
		||||
 *
 | 
			
		||||
 * @brief   USB RCC initialized
 | 
			
		||||
 *
 | 
			
		||||
 * @return  none
 | 
			
		||||
 */
 | 
			
		||||
void USBHS_RCC_Init( void )
 | 
			
		||||
{
 | 
			
		||||
    RCC_USBCLK48MConfig( RCC_USBCLK48MCLKSource_USBPHY );
 | 
			
		||||
    RCC_USBHSPLLCLKConfig( RCC_HSBHSPLLCLKSource_HSE );
 | 
			
		||||
    RCC_USBHSConfig( RCC_USBPLL_Div2 );
 | 
			
		||||
    RCC_USBHSPLLCKREFCLKConfig( RCC_USBHSPLLCKREFCLK_4M );
 | 
			
		||||
    RCC_USBHSPHYPLLALIVEcmd( ENABLE );
 | 
			
		||||
    RCC_AHBPeriphClockCmd( RCC_AHBPeriph_USBHS, ENABLE );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*********************************************************************
 | 
			
		||||
 * @fn      USBHS_Host_Init
 | 
			
		||||
 *
 | 
			
		||||
 * @brief   USB host mode initialized.
 | 
			
		||||
 *
 | 
			
		||||
 * @param   sta - ENABLE or DISABLE
 | 
			
		||||
 *
 | 
			
		||||
 * @return  none
 | 
			
		||||
 */
 | 
			
		||||
void USBHS_Host_Init( FunctionalState sta )
 | 
			
		||||
{
 | 
			
		||||
    if( sta )
 | 
			
		||||
    {
 | 
			
		||||
        USBHSH->CONTROL = 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;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -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 #
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue