Merge branch 'prepare_for_master' of https://gitlink.org.cn/hc0014/xiuos into prepare_for_master

This commit is contained in:
huang 2024-04-03 16:37:36 +08:00
commit 104791dbbe
32 changed files with 5575 additions and 3 deletions

View File

@ -28,6 +28,7 @@
* @date 2022-08-08
*/
#include "ch32v30x.h"
#include "connect_can.h"
#include "connect_ether.h"
#include "connect_uart.h"
#include "core_riscv.h"
@ -71,6 +72,11 @@ void InitBoardHardware()
#ifdef BSP_USING_ETH
InitHwEth();
#endif
#ifdef BSP_USING_CAN
InitHwCan();
#endif
KPrintf("consle init completed.\n");
KPrintf("board initialization......\n");

View File

@ -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

View File

@ -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

View File

@ -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"

View File

@ -0,0 +1,4 @@
SRC_FILES := connect_can.c
SRC_DIR := test
include $(KERNEL_ROOT)/compiler.mk

View File

@ -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;
}

View File

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

View File

@ -0,0 +1,174 @@
/*
* 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 can_test.c
* @brief test ch32v307 can
* @version 1.0
* @author AIIT XUOS Lab
* @date 2024-03-14
*/
#include "shell.h"
#include "ch32v30x.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);

View File

@ -0,0 +1,55 @@
0.该测试在Ubiquitous中测试通过将驱动中静态的收发初始化操作在测试文件中实现在APP_Framework的测试中BusFindBusFindDriverBusFindDevice可找到相应的设备但无法通过其进行读写等操作
```
// APP_Framework/Applications/main.c
#include <stdio.h>
#include <string.h>
#include <transform.h>
#include <bus.h>
#define CAN_BUS "can1"
#define CAN_DRIVER "can1_drv"
#define CAN_DEVICE "can1_dev1"
void TestCAN(void)
{
KPrintf("Test can start\n");
struct Bus *bus;
struct HardwareDev *dev;
struct Driver *drv;
char test_str[] = "Hello AIIT!\r\n";
/* find the serial bus pointer */
bus = BusFind(CAN_BUS);
if (NONE == bus)
{
KPrintf("BusFind %s failed\n", CAN_BUS);
return;
}
/* find the serial driver pointer */
drv = BusFindDriver(bus, CAN_DRIVER);
if (NONE == drv)
{
KPrintf("BusFindDriver %s failed\n", CAN_DRIVER);
return;
}
/* find the serial device pointer */
dev = BusFindDevice(bus, CAN_DEVICE);
if (NONE == dev)
{
KPrintf("BusFindDevice %s failed\n", CAN_DEVICE);
return;
}
}
PRIV_SHELL_CMD_FUNCTION(TestCAN, a can test sample, PRIV_SHELL_CMD_MAIN_ATTR);
```
1.make BOARD=ch32v307vct6 menuconfig中配置can相关参数 ch32v307vct6 feature ---> Using CAN device --->
2.在can_test.c中can_initstruction.CAN_Mode表示can的收发模式修改该参数可实现不同的收发方式有CAN_Mode_Normal,CAN_Mode_LoopBack,CAN_Mode_Silent,CAN_Mode_Silent_LoopBack四种模式此处用CAN_Mode_Silent_LoopBack该模式实现自收自发如果需要通过主机收发可修改为CAN_Mode_Normal
3.编译后将其烧录至开发板上执行test_can命令运行can测试。

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

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

View File

@ -0,0 +1,84 @@
0.该测试在Ubiquitous中测试通过将驱动中静态的收发操作在测试文件中实现在APP_Framework的测试中BusFindBusFindDriverBusFindDevice可找到相应的设备但无法通过其进行读写等操作
```
// APP_Framework/Applications/main.c
#include <stdio.h>
#include <string.h>
#include <transform.h>
#include <bus.h>
#define RS485_UART_BUS "uart5"
#define RS485_UART_DRV "uart5_drv"
#define RS485_UART_DEV "uart5_dev5"
void Test485(void)
{
/*
485的驱动使用UART5在connect_uart.c中添加UART5的初始化添加UART5的Kconfigborad.c中使用InstallConsole用uart5串口正常输出控制台信息在app_famework中加入app_test的485测试用例后出现
HardFault_Handler.
mepc :000f448
mcause:0000007
mtval :200100d4
报错控制台停止运行最后将Test485用例摘出放置main.c中发现将PrivOpen编译进bin就会报错没有实际执行
试了试busfindbus,bus_drv,bus_dev都能找到但是BusDevWriteData(dev, &write_param)编译进去后无法运行OS无法起来/没有实际执行Busdevclose导致程序崩溃
Test 485 start
[ERR][x_free] Freeing a unallocated address.
HardFault_Handler.
mepc :0000012
mcause:0000002
mtval :0000000
在Ubiquitous/XiZi_IIoT/board/ch32v307vct6/third_party_driver/uart/test测试中
可以通过485串口正常输出接收
*/
KPrintf("Test 485 start\n");
struct Bus *bus;
struct HardwareDev *dev;
struct Driver *drv;
char test_str[] = "Hello AIIT!\r\n";
/* find the serial bus pointer */
bus = BusFind(RS485_UART_BUS);
if (NONE == bus)
{
KPrintf("BusFind %s failed\n", RS485_UART_BUS);
return;
}
/* find the serial driver pointer */
drv = BusFindDriver(bus, RS485_UART_DRV);
if (NONE == drv)
{
KPrintf("BusFindDriver %s failed\n", RS485_UART_DRV);
return;
}
/* find the serial device pointer */
dev = BusFindDevice(bus, RS485_UART_DEV);
if (NONE == dev)
{
KPrintf("BusFindDevice %s failed\n", RS485_UART_DEV);
return;
}
struct BusBlockWriteParam write_param;
write_param.pos = 0;
write_param.buffer = (void *)test_str;
write_param.size = sizeof(test_str) - 1;
// BusDevWriteData(dev, &write_param);
// BusDevClose(dev);
return;
}
PRIV_SHELL_CMD_FUNCTION(Test485, a 485 test sample, PRIV_SHELL_CMD_MAIN_ATTR);
```
1.make BOARD=ch32v307vct6 menuconfig中配置UART相关参数 ch32v307vct6 feature ---> Enable UART5 --->
2.编译后将其烧录至开发板上连接485转USB硬件至主机主机使用串口工具打开执行test_rs485命令运行485收发测试。

View File

@ -0,0 +1,115 @@
/*
* 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 rs485_test.c
* @brief test ch32v307 485
* @version 1.0
* @author AIIT XUOS Lab
* @date 2024-03-14
*/
#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);

View File

@ -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

View File

@ -0,0 +1,9 @@
SRC_FILES := connect_usb.c
SRC_DIR += usb_drv/src
include $(KERNEL_ROOT)/compiler.mk

View File

@ -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;
}

View File

@ -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

View File

@ -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_ */

View File

@ -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 */

View File

@ -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

View File

@ -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

View File

@ -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之前定义一个全局变量为0FileOpen回调本程序后CHRV3vFdtOffset得到结构FAT_DIR_INFO
DIR_Attr以及DIR_Name判断是否为所需文件名或者目录名
FileOpen返回后ERR_MISS_FILE或ERR_FOUND_NAME都视为操作成功
xFileNameEnumer中将CHRV3vFileSize置为1FileOpen提前结束搜索 */
#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);
}

View File

@ -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

View File

@ -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 );
}
}

View File

@ -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; // 返回错误
}

View File

@ -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;
}

View File

@ -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" );
}
}

View File

@ -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;
}

View File

@ -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 #