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