first submission

This commit is contained in:
qiyongshuang
2023-02-01 14:19:13 +08:00
parent d534aad004
commit b79c6ac80d
3711 changed files with 745432 additions and 2 deletions
+410
View File
@@ -0,0 +1,410 @@
/* 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 "ch32v20x.h"
#include "usb_host_config.h"
#include "CHRV3UFI.h"
uint8_t USBHostTransact( uint8_t endp_pid, uint8_t tog, uint32_t timeout )
{
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
}
uint8_t HostCtrlTransfer( uint8_t *DataBuf, uint8_t *RetLen )
{
uint8_t ret;
uint16_t retlen;
retlen = (uint16_t)(*RetLen);
ret = USBFSH_CtrlTransfer( RootHubDev[ DEF_USB_PORT_FS ].bEp0MaxPks, DataBuf, &retlen );
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;
ret = USBFSH_GetDeviceDescr( &RootHubDev[ DEF_USB_PORT_FS ].bEp0MaxPks, TxBuffer );
return ret;
}
uint8_t CtrlGetConfigDescrTB( void )
{
uint16_t len;
uint8_t ret;
ret = USBFSH_GetConfigDescr( RootHubDev[ DEF_USB_PORT_FS ].bEp0MaxPks, TxBuffer, 256, &len );
return ret;
}
uint8_t CtrlSetUsbConfig( uint8_t cfg )
{
uint8_t ret;
ret = USBFSH_SetUsbConfig( RootHubDev[ DEF_USB_PORT_FS ].bEp0MaxPks, cfg );
return ret;
}
uint8_t CtrlSetUsbAddress( uint8_t addr )
{
uint8_t ret;
ret = USBFSH_SetUsbAddress( RootHubDev[ DEF_USB_PORT_FS ].bEp0MaxPks, addr );
return ret;
}
uint8_t CtrlClearEndpStall( uint8_t endp )
{
uint8_t ret;
ret = USBFSH_ClearEndpStall( RootHubDev[ DEF_USB_PORT_FS ].bEp0MaxPks, endp );
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
*/
#if DEF_USB_PORT_FS_EN
#define UHUB_DEV_ADDR (USBOTG_H_FS->DEV_ADDR)
#define UHUB_MIS_STAT (USBOTG_H_FS->MIS_ST)
#define UHUB_HOST_CTRL (USBOTG_H_FS->HOST_CTRL)
#define UHUB_INT_FLAG (USBOTG_H_FS->INT_FG)
#define bUMS_ATTACH USBFS_UMS_DEV_ATTACH
#define bUMS_SUSPEND USBFS_UMS_SUSPEND
#define DEF_ADR_OFFSET 0
#elif DEF_USB_PORT_HSS_EN
#define UHUB_DEV_ADDR (USBHSH->DEV_ADDR)
#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
#define DEF_ADR_OFFSET 1
#endif
/* 检查磁盘是否连接 */
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 + DEF_ADR_OFFSET) )
{
/* 内置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 */
#if DEF_USB_PORT_FS_EN
CHRV3vPacketSize = 64; /* USB存储类设备的最大包长度:64@FS,512@HS/SS,由应用程序初始化,枚举U盘后如果是高速或者超速那么及时更新为512 */
pTX_DMA_A_REG = (uint32_t *)&(USBOTG_H_FS->HOST_TX_DMA); /* 指向发送DMA地址寄存器,由应用程序初始化 */
pRX_DMA_A_REG = (uint32_t *)&(USBOTG_H_FS->HOST_RX_DMA); /* 指向接收DMA地址寄存器,由应用程序初始化 */
pTX_LEN_REG = (uint16_t *)&(USBOTG_H_FS->HOST_TX_LEN); /* 指向发送长度寄存器,由应用程序初始化 */
pRX_LEN_REG = (uint16_t *)&(USBOTG_H_FS->RX_LEN); /* 指向接收长度寄存器,由应用程序初始化 */
#elif DEF_USB_PORT_HS_EN
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); /* 指向接收长度寄存器,由应用程序初始化 */
#endif
return( ERR_SUCCESS );
}
void mDelaymS( uint16_t n )
{
Delay_Ms(n);
}
+366
View File
@@ -0,0 +1,366 @@
/* 2014.09.09
*****************************************
** Copyright (C) W.ch 1999-2019 **
** Web: http://wch.cn **
*****************************************
** USB-flash File Interface for CHRV3 **
** KEIL423, gcc 8.20 **
*****************************************
*/
/* CHRV3 U盘主机文件系统接口, 支持: FAT12/FAT16/FAT32 */
//#include "CHRV3BAS.H"
#ifndef __CHRV3UFI_H__
#define __CHRV3UFI_H__
#define CHRV3_LIB_VER 0x10
//#define DISK_BASE_BUF_LEN 512 /* 默认的磁盘数据缓冲区大小为512字节(可以选择为2048甚至4096以支持某些大扇区的U盘),为0则禁止在本文件中定义缓冲区并由应用程序在pDISK_BASE_BUF中指定 */
/* 如果需要复用磁盘数据缓冲区以节约RAM,那么可将DISK_BASE_BUF_LEN定义为0以禁止在本文件中定义缓冲区,而由应用程序在调用CHRV3LibInit之前将与其它程序合用的缓冲区起始地址置入pDISK_BASE_BUF变量 */
//#define NO_DEFAULT_ACCESS_SECTOR 1 /* 禁止默认的磁盘扇区读写子程序,下面用自行编写的程序代替它 */
//#define NO_DEFAULT_DISK_CONNECT 1 /* 禁止默认的检查磁盘连接子程序,下面用自行编写的程序代替它 */
//#define NO_DEFAULT_FILE_ENUMER 1 /* 禁止默认的文件名枚举回调程序,下面用自行编写的程序代替它 */
#define FOR_ROOT_UDISK_ONLY 1
#ifdef __cplusplus
extern "C" {
#endif
/* ********************************************************************************************************************* */
/* FILE: CHRV3UF.H */
/* 错误码 */
#ifndef ERR_SUCCESS
#define ERR_SUCCESS 0x00 /* 操作成功 */
#endif
#ifndef ERR_DISK_DISCON
#define ERR_CHRV3_ERROR 0x81 /* CHRV3硬件错误,可能需要复位CHRV3 */
//#define ERR_DISK_DISCON 0x82 /* 磁盘尚未连接,可能磁盘已经断开 */
#define ERR_STATUS_ERR 0x83 /* 磁盘状态错误,可能正在连接或者断开磁盘 */
#define ERR_HUB_PORT_FREE 0x84 /* USB-HUB已经连接但是HUB端口尚未连接磁盘,可能磁盘已经断开 */
#define ERR_MBR_ERROR 0x91 /* 磁盘的主引导记录无效,可能磁盘尚未分区或者尚未格式化 */
#define ERR_TYPE_ERROR 0x92 /* 磁盘分区类型不支持,只支持FAT12/FAT16/BigDOS/FAT32,需要由磁盘管理工具重新分区 */
#define ERR_BPB_ERROR 0xA1 /* 磁盘尚未格式化,或者参数错误,需要由WINDOWS采用默认参数重新格式化 */
#define ERR_TOO_LARGE 0xA2 /* 磁盘非正常格式化并且容量大于4GB,或者容量大于250GB,需要由WINDOWS采用默认参数重新格式化 */
#define ERR_FAT_ERROR 0xA3 /* 磁盘的文件系统不支持,只支持FAT12/FAT16/FAT32,需要由WINDOWS采用默认参数重新格式化 */
#define ERR_DISK_FULL 0xB1 /* 磁盘文件太满,剩余空间太少或者已经没有,需要磁盘整理 */
#define ERR_FDT_OVER 0xB2 /* 目录内文件太多,没有空闲的目录项,FAT12/FAT16根目录下的文件数应该少于500个,需要磁盘整理 */
#define ERR_MISS_DIR 0xB3 /* 指定路径的某个子目录没有找到,可能是目录名称错误 */
#define ERR_FILE_CLOSE 0xB4 /* 文件已经关闭,如果需要使用,应该重新打开文件 */
#define ERR_OPEN_DIR 0x41 /* 指定路径的目录被打开 */
#define ERR_MISS_FILE 0x42 /* 指定路径的文件没有找到,可能是文件名称错误 */
#define ERR_FOUND_NAME 0x43 /* 搜索到与通配符相匹配的文件名,文件名及其完整路径在命令缓冲区中,如果需要使用,应该打开该文件 */
#endif
/* 代码2XH-3XH用于USB主机方式的通讯失败代码,由CHRV3子程序模仿CH375的返回 */
/* 代码1XH用于USB主机方式的操作状态代码,由CHRV3子程序模仿CH375的返回 */
#ifndef ERR_USB_CONNECT
#define ERR_USB_CONNECT_LS 0x13 /* 检测到低速USB设备连接事件 */
#define ERR_USB_CONNECT 0x15 /* 检测到USB设备连接事件,磁盘已经连接 */
#define ERR_USB_DISCON 0x16 /* 检测到USB设备断开事件,磁盘已经断开 */
#define ERR_USB_BUF_OVER 0x17 /* USB传输的数据有误或者数据太多缓冲区溢出 */
#define ERR_USB_DISK_ERR 0x1F /* USB存储器操作失败,在初始化时可能是USB存储器不支持,在读写操作中可能是磁盘损坏或者已经断开 */
#define ERR_USB_TRANSFER 0x20 /* NAK/STALL等更多错误码在0x20~0x2F */
#endif
/* 磁盘及文件状态 */
#define DISK_UNKNOWN 0x00 /* 尚未初始化,未知状态 */
#define DISK_DISCONNECT 0x01 /* 磁盘没有连接或者已经断开 */
#define DISK_CONNECT 0x02 /* 磁盘已经连接,但是尚未初始化或者无法识别该磁盘 */
#define DISK_USB_ADDR 0x04 /* 磁盘已经分配USB设备地址,但是尚未配置USB和初始化磁盘 */
#define DISK_MOUNTED 0x05 /* 磁盘已经初始化成功,但是尚未分析文件系统或者文件系统不支持 */
#define DISK_READY 0x10 /* 已经分析磁盘的文件系统并且能够支持 */
#define DISK_OPEN_ROOT 0x12 /* 已经打开根目录,扇区模式,只能以扇区为单位读写目录的内容,使用后必须关闭,注意FAT12/FAT16根目录是固定长度 */
#define DISK_OPEN_DIR 0x13 /* 已经打开子目录,扇区模式,只能以扇区为单位读写目录的内容 */
#define DISK_OPEN_FILE 0x14 /* 已经打开文件,扇区模式,可以以扇区为单位进行数据读写 */
#define DISK_OPEN_FILE_B 0x15 /* 已经打开文件,字节模式,可以以字节为单位进行数据读写 */
/* FAT类型标志 */
#ifndef DISK_FAT16
#define DISK_FS_UNKNOWN 0 /* 未知的文件系统 */
#define DISK_FAT12 1 /* FAT12文件系统 */
#define DISK_FAT16 2 /* FAT16文件系统 */
#define DISK_FAT32 3 /* FAT32文件系统 */
#endif
/* FAT数据区中文件目录信息 */
typedef struct _FAT_DIR_INFO {
uint8_t DIR_Name[11]; /* 00H,文件名,共11字节,不足处填空格 */
uint8_t DIR_Attr; /* 0BH,文件属性,参考下面的说明 */
uint8_t DIR_NTRes; /* 0CH */
uint8_t DIR_CrtTimeTenth; /* 0DH,文件创建的时间,以0.1秒单位计数 */
uint16_t DIR_CrtTime; /* 0EH,文件创建的时间 */
uint16_t DIR_CrtDate; /* 10H,文件创建的日期 */
uint16_t DIR_LstAccDate; /* 12H,最近一次存取操作的日期 */
uint16_t DIR_FstClusHI; /* 14H */
uint16_t DIR_WrtTime; /* 16H,文件修改时间,参考宏MAKE_FILE_TIME */
uint16_t DIR_WrtDate; /* 18H,文件修改日期,参考宏MAKE_FILE_DATA */
uint16_t DIR_FstClusLO; /* 1AH */
uint32_t DIR_FileSize; /* 1CH,文件长度 */
} FAT_DIR_INFO; /* 20H */
typedef FAT_DIR_INFO *PX_FAT_DIR_INFO;
/* 文件属性 */
#define ATTR_READ_ONLY 0x01 /* 文件为只读属性 */
#define ATTR_HIDDEN 0x02 /* 文件为隐含属性 */
#define ATTR_SYSTEM 0x04 /* 文件为系统属性 */
#define ATTR_VOLUME_ID 0x08 /* 卷标 */
#define ATTR_DIRECTORY 0x10 /* 子目录 */
#define ATTR_ARCHIVE 0x20 /* 文件为存档属性 */
#define ATTR_LONG_NAME ( ATTR_READ_ONLY | ATTR_HIDDEN | ATTR_SYSTEM | ATTR_VOLUME_ID )
/* 文件属性 uint8_t */
/* bit0 bit1 bit2 bit3 bit4 bit5 bit6 bit7 */
/* 只 隐 系 卷 目 存 未定义 */
/* 读 藏 统 标 录 档 */
/* 文件时间 uint16_t */
/* Time = (Hour<<11) + (Minute<<5) + (Second>>1) */
#define MAKE_FILE_TIME( h, m, s ) ( (h<<11) + (m<<5) + (s>>1) ) /* 生成指定时分秒的文件时间数据 */
/* 文件日期 uint16_t */
/* Date = ((Year-1980)<<9) + (Month<<5) + Day */
#define MAKE_FILE_DATE( y, m, d ) ( ((y-1980)<<9) + (m<<5) + d ) /* 生成指定年月日的文件日期数据 */
/* 文件名 */
#define PATH_WILDCARD_CHAR 0x2A /* 路径名的通配符 '*' */
#define PATH_SEPAR_CHAR1 0x5C /* 路径名的分隔符 '\' */
#define PATH_SEPAR_CHAR2 0x2F /* 路径名的分隔符 '/' */
#ifndef MAX_PATH_LEN
#define MAX_PATH_LEN 64 /* 最大路径长度,含所有斜杠分隔符和小数点间隔符以及路径结束符00H */
#endif
/* 外部命令参数 */
typedef union _CMD_PARAM
{
struct
{
uint8_t mBuffer[ MAX_PATH_LEN ];
} Other;
struct
{
uint32_t mTotalSector; /* 返回: 当前逻辑盘的总扇区数 */
uint32_t mFreeSector; /* 返回: 当前逻辑盘的剩余扇区数 */
uint32_t mSaveValue;
} Query; /* CMD_DiskQuery, 查询磁盘信息 */
struct
{
uint8_t mPathName[ MAX_PATH_LEN ]; /* 输入参数: 路径: [盘符,冒号,斜杠,目录名或者文件名及扩展名...,结束符00H], 其中盘符和冒号可以省略, 例如"C:\DIR1.EXT\DIR2\FILENAME.EXT",00H */
} Open; /* CMD_FileOpen, 打开文件 */
// struct
// {
// uint8_t mPathName[ MAX_PATH_LEN ]; /* 输入参数: 路径: [盘符,冒号,斜杠,目录名或者文件名及扩展名(含通配符*)...,结束符00H], 其中盘符和冒号可以省略, 例如"C:\DIR1.EXT\DIR2\FILE*",00H */
// } Open; /* CMD_FileOpen, 枚举文件, CHRV3vFileSize最高位为1则各调用xFileNameEnumer,为0则返回指定序号的文件名 */
struct
{
uint8_t mUpdateLen; /* 输入参数: 是否允许更新长度: 0禁止,1允许 */
} Close; /* CMD_FileClose, 关闭当前文件 */
struct
{
uint8_t mPathName[ MAX_PATH_LEN ]; /* 输入参数: 路径: [盘符,冒号,斜杠,目录名或者文件名及扩展名...,结束符00H], 其中盘符和冒号可以省略, 例如"C:\DIR1.EXT\DIR2\FILENAME.EXT",00H */
} Create; /* CMD_FileCreate, 新建文件并打开,如果文件已经存在则先删除后再新建 */
struct
{
uint8_t mPathName[ MAX_PATH_LEN ]; /* 输入参数: 路径: [盘符,冒号,斜杠,目录名或者文件名及扩展名...,结束符00H], 其中盘符和冒号可以省略, 例如"C:\DIR1.EXT\DIR2\FILENAME.EXT",00H */
} Erase; /* CMD_FileErase, 删除文件并关闭 */
struct
{
uint32_t mFileSize; /* 输入参数: 新的文件长度,为0FFFFFFFFH则不修改, 返回: 原长度 */
uint16_t mFileDate; /* 输入参数: 新的文件日期,为0FFFFH则不修改, 返回: 原日期 */
uint16_t mFileTime; /* 输入参数: 新的文件时间,为0FFFFH则不修改, 返回: 原时间 */
uint8_t mFileAttr; /* 输入参数: 新的文件属性,为0FFH则不修改, 返回: 原属性 */
} Modify; /* CMD_FileQuery, 查询当前文件的信息; CMD_FileModify, 查询或者修改当前文件的信息 */
struct
{
uint32_t mSaveCurrClus;
uint32_t mSaveLastClus;
} Alloc; /* CMD_FileAlloc, 根据文件长度调整为文件分配的磁盘空间 */
struct
{
uint32_t mSectorOffset; /* 输入参数: 扇区偏移,0则移动到文件头,0FFFFFFFFH则移动到文件尾, 返回: 当前文件指针对应的绝对线性扇区号, 0FFFFFFFFH则已到文件尾 */
uint32_t mLastOffset;
} Locate; /* CMD_FileLocate, 移动当前文件指针 */
struct
{
uint8_t mSectorCount; /* 输入参数: 读取扇区数, 返回: 实际读取扇区数 */
uint8_t mActCnt;
uint8_t mLbaCount;
uint8_t mRemainCnt;
uint8_t *mDataBuffer; /* 输入参数: 缓冲区起始地址, 返回: 缓冲区当前地址 */
uint32_t mLbaStart;
} Read; /* CMD_FileRead, 从当前文件读取数据 */
struct
{
uint8_t mSectorCount; /* 输入参数: 写入扇区数, 返回: 实际写入扇区数 */
uint8_t mActCnt;
uint8_t mLbaCount;
uint8_t mAllocCnt;
uint8_t *mDataBuffer; /* 输入参数: 缓冲区起始地址, 返回: 缓冲区当前地址 */
uint32_t mLbaStart;
uint32_t mSaveValue;
} Write; /* CMD_FileWrite, 向当前文件写入数据 */
struct
{
uint32_t mDiskSizeSec; /* 返回: 整个物理磁盘的总扇区数, 仅首次调用时返回 */
} DiskReady; /* CMD_DiskReady, 查询磁盘就绪 */
struct
{
uint32_t mByteOffset; /* 输入参数: 以字节为单位的偏移量, 以字节为单位的文件指针, 返回: 当前文件指针对应的绝对线性扇区号, 0FFFFFFFFH则已到文件尾 */
uint32_t mLastOffset;
} ByteLocate; /* CMD_ByteLocate, 以字节为单位移动当前文件指针 */
struct
{
uint16_t mByteCount; /* 输入参数: 准备读取的字节数, 返回: 实际读出的字节数 */
uint8_t *mByteBuffer; /* 输入参数: 指向存放读出数据块的缓冲区 */
uint16_t mActCnt;
} ByteRead; /* CMD_ByteRead, 以字节为单位从当前文件读取数据块 */
struct
{
uint16_t mByteCount; /* 输入参数: 准备写入的字节数, 返回: 实际写入的字节数 */
uint8_t *mByteBuffer; /* 输入参数: 指向存放读出数据块的缓冲区 */
uint16_t mActCnt;
} ByteWrite; /* CMD_ByteWrite, 以字节为单位向当前文件写入数据块 */
struct
{
uint8_t mSaveVariable; /* 输入参数: 为0则恢复单个U盘的变量,为0x80则恢复多个U盘的变量,其它值则备份/保存变量 */
uint8_t mReserved[3];
uint8_t *mBuffer; /* 输入参数: 指向子程序库的变量的备份缓冲区,长度不小于80个字节 */
} SaveVariable; /* CMD_SaveVariable, 备份/保存/恢复子程序库的变量 */
} CMD_PARAM;
typedef CMD_PARAM CMD_PARAM_I;
//typedef CMD_PARAM *P_CMD_PARAM;
/* SCSI命令码 */
#ifndef SPC_CMD_INQUIRY
#define SPC_CMD_INQUIRY 0x12
#define SPC_CMD_READ_CAPACITY 0x25
#define SPC_CMD_READ10 0x28
#define SPC_CMD_WRITE10 0x2A
#define SPC_CMD_TEST_READY 0x00
#define SPC_CMD_REQUEST_SENSE 0x03
#define SPC_CMD_MODESENSE6 0x1A
#define SPC_CMD_MODESENSE10 0x5A
#define SPC_CMD_START_STOP 0x1B
#endif
/* FILE: CHRV3UFI.C */
#define EN_DISK_WRITE 1
#ifndef DISK_BASE_BUF_LEN
#define DISK_BASE_BUF_LEN 512 /* 默认的磁盘数据缓冲区大小为512字节,建议选择为2048甚至4096以支持某些大扇区的U盘,为0则禁止在.H文件中定义缓冲区并由应用程序在pDISK_BASE_BUF中指定 */
#endif
/* 子程序库中提供的变量 */
extern volatile uint8_t CHRV3IntStatus; /* CHRV3操作的中断状态 */
extern volatile uint8_t CHRV3DiskStatus; /* 磁盘及文件状态 */
extern uint8_t CHRV3vDiskFat; /* 逻辑盘的FAT标志:1=FAT12,2=FAT16,3=FAT32 */
extern uint8_t CHRV3vSecPerClus; /* 逻辑盘的每簇扇区数 */
extern uint8_t CHRV3vSectorSizeB; /* log2(CHRV3vSectorSize) */
extern uint32_t CHRV3vStartLba; /* 逻辑盘的起始绝对扇区号LBA */
extern uint32_t CHRV3vDiskRoot; /* 对于FAT16盘为根目录占用扇区数,对于FAT32盘为根目录起始簇号 */
extern uint32_t CHRV3vDataStart; /* 逻辑盘的数据区域的起始LBA */
extern uint32_t CHRV3vStartCluster; /* 当前文件或者目录的起始簇号 */
extern uint32_t CHRV3vFileSize; /* 当前文件的长度 */
extern uint32_t CHRV3vCurrentOffset; /* 当前文件指针,当前读写位置的字节偏移 */
extern uint32_t CHRV3vFdtLba; /* 当前FDT所在的LBA地址 */
extern uint32_t CHRV3vLbaCurrent; /* 当前读写的磁盘起始LBA地址 */
extern uint16_t CHRV3vFdtOffset; /* 当前FDT在扇区内的偏移地址 */
extern uint16_t CHRV3vSectorSize; /* 磁盘的扇区大小 */
extern uint8_t CHRV3vCurrentLun; /* 磁盘当前操作逻辑单元号 */
extern uint8_t CHRV3vSubClassIs6; /* USB存储类设备的子类为6,0则非6 */
extern uint8_t *pDISK_BASE_BUF; /* 指向外部RAM的磁盘数据缓冲区,缓冲区长度不小于CHRV3vSectorSize,由应用程序初始化 */
extern uint8_t *pDISK_FAT_BUF; /* 指向外部RAM的磁盘FAT数据缓冲区,缓冲区长度不小于CHRV3vSectorSize,由应用程序初始化 */
extern uint16_t CHRV3vPacketSize; /* USB存储类设备的最大包长度:64@FS,512@HS/SS,由应用程序初始化 */
extern uint32_t *pTX_DMA_A_REG; /* 指向发送DMA地址寄存器,由应用程序初始化 */
extern uint32_t *pRX_DMA_A_REG; /* 指向接收DMA地址寄存器,由应用程序初始化 */
extern uint16_t *pTX_LEN_REG; /* 指向发送长度寄存器,由应用程序初始化 */
extern uint16_t *pRX_LEN_REG; /* 指向接收长度寄存器,由应用程序初始化 */
extern CMD_PARAM_I mCmdParam; /* 命令参数 */
extern __attribute__ ((aligned(4))) uint8_t RxBuffer[ ]; // IN, must even address
extern __attribute__ ((aligned(4))) uint8_t TxBuffer[ ]; // OUT, must even address
//#define PXUDISK_BOC_CBW PUDISK_BOC_CBW
//#define PXUDISK_BOC_CSW PUDISK_BOC_CSW
#ifndef pSetupReq
#define pSetupReq ((PUSB_SETUP_REQ)TxBuffer)
#endif
#ifndef pCBW
#define pCBW ((PXUDISK_BOC_CBW)TxBuffer)
#define pCSW ((PXUDISK_BOC_CSW)RxBuffer)
#endif
#ifndef pBOC_buf
#define pBOC_buf (TxBuffer+((USB_BO_CBW_SIZE+4)&0xFE))
#endif
#if DISK_BASE_BUF_LEN > 0
extern uint8_t DISK_BASE_BUF[ DISK_BASE_BUF_LEN ]; /* 外部RAM的磁盘数据缓冲区,缓冲区长度为一个扇区的长度 */
#endif
extern uint8_t CHRV3ReadSector( uint8_t SectCount, uint8_t * DataBuf ); /* 从磁盘读取多个扇区的数据到缓冲区中 */
#ifdef EN_DISK_WRITE
extern uint8_t CHRV3WriteSector( uint8_t SectCount, uint8_t * DataBuf ); /* 将缓冲区中的多个扇区的数据块写入磁盘 */
#endif
extern uint8_t CHRV3DiskConnect( void ); /* 检查磁盘是否连接并更新磁盘状态 */
extern void xFileNameEnumer( void ); /* 调用外部定义的子程序,文件名枚举回调子程序 */
extern uint8_t CHRV3LibInit( void ); /* 初始化CHRV3程序库,操作成功返回0 */
/* 子程序库中提供的子程序 */
/* 下述子程序中, 文件操作子程序CHRV3File*和磁盘查询子程序CHRV3DiskQuery都可能会用到磁盘数据缓冲区pDISK_BASE_BUF,
并且有可能在pDISK_BASE_BUF中保存了磁盘信息, 所以必须保证pDISK_BASE_BUF不被用于其它用途,
如果RAM较少, 要将pDISK_BASE_BUF临时用于其它用途, 那么在临时用完后必须调用CHRV3DirtyBuffer清除磁盘缓冲区 */
extern uint8_t CHRV3GetVer( void ); /* 获取当前子程序库的版本号 */
extern void CHRV3DirtyBuffer( void ); /* 清除磁盘缓冲区 */
extern uint8_t CHRV3BulkOnlyCmd( uint8_t * DataBuf ); /* 执行基于BulkOnly协议的命令 */
extern uint8_t CHRV3DiskReady( void ); /* 查询磁盘是否准备好 */
extern uint8_t CHRV3AnalyzeError( uint8_t iMode ); /* USB操作失败分析CHRV3IntStatus返回错误状态 */
extern uint8_t CHRV3FileOpen( void ); /* 打开文件或者枚举文件 */
extern uint8_t CHRV3FileClose( void ); /* 关闭当前文件 */
#ifdef EN_DISK_WRITE
extern uint8_t CHRV3FileErase( void ); /* 删除文件并关闭 */
extern uint8_t CHRV3FileCreate( void ); /* 新建文件并打开,如果文件已经存在则先删除后再新建 */
extern uint8_t CHRV3FileAlloc( void ); /* 根据文件长度调整为文件分配的磁盘空间 */
#endif
extern uint8_t CHRV3FileModify( void ); /* 查询或者修改当前文件的信息 */
extern uint8_t CHRV3FileQuery( void ); /* 查询当前文件的信息 */
extern uint8_t CHRV3FileLocate( void ); /* 移动当前文件指针 */
extern uint8_t CHRV3FileRead( void ); /* 从当前文件读取数据到指定缓冲区 */
#ifdef EN_DISK_WRITE
extern uint8_t CHRV3FileWrite( void ); /* 向当前文件写入指定缓冲区的数据 */
#endif
extern uint8_t CHRV3ByteLocate( void ); /* 以字节为单位移动当前文件指针 */
extern uint8_t CHRV3ByteRead( void ); /* 以字节为单位从当前位置读取数据块 */
#ifdef EN_DISK_WRITE
extern uint8_t CHRV3ByteWrite( void ); /* 以字节为单位向当前位置写入数据块 */
#endif
extern uint8_t CHRV3DiskQuery( void ); /* 查询磁盘信息 */
extern void CHRV3SaveVariable( void ); /* 备份/保存/恢复子程序库的变量,用于子程序库在多个芯片或者U盘之间进行切换 */
extern void mDelayuS( uint16_t n ); // 以uS为单位延时
extern void mDelaymS( uint16_t n ); // 以mS为单位延时
extern uint8_t USBHostTransact( uint8_t endp_pid, uint8_t tog, uint32_t timeout ); // CHRV3传输事务,输入目的端点地址/PID令牌,同步标志,NAK重试时间,返回0成功,超时/出错重试
extern uint8_t HostCtrlTransfer( uint8_t * DataBuf, uint8_t * RetLen ); // 执行控制传输,8字节请求码在pSetupReq中,DataBuf为可选的收发缓冲区,实际收发长度返回在ReqLen指向的变量中
extern void CopySetupReqPkg( const char * pReqPkt ); // 复制控制传输的请求包
extern uint8_t CtrlGetDeviceDescrTB( void ); // 获取设备描述符,返回在TxBuffer中
extern uint8_t CtrlGetConfigDescrTB( void ); // 获取配置描述符,返回在TxBuffer中
extern uint8_t CtrlSetUsbAddress( uint8_t addr ); // 设置USB设备地址
extern uint8_t CtrlSetUsbConfig( uint8_t cfg ); // 设置USB设备配置
extern uint8_t CtrlClearEndpStall( uint8_t endp ); // 清除端点STALL
#ifndef FOR_ROOT_UDISK_ONLY
//extern uint8_t CtrlGetHubDescr( void ); // 获取HUB描述符,返回在TxBuffer中
extern uint8_t HubGetPortStatus( uint8_t HubPortIndex ); // 查询HUB端口状态,返回在TxBuffer中
//extern uint8_t HubSetPortFeature( uint8_t HubPortIndex, uint8_t FeatureSelt ); // 设置HUB端口特性
extern uint8_t HubClearPortFeature( uint8_t HubPortIndex, uint8_t FeatureSelt ); // 清除HUB端口特性
#endif
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,9 @@
有关WCH-RISC-V3处理器的U盘文件级子程序库的接口说明以及例子程序
请参考CHxxx评估板资料和相关PDF文档
*****************************************************************************************
CHRV3UFI V1.0 最新更新 2020.05
支持FS全速、HS高速、SS超速USB主机,支持内置root-hub或外置hub
*****************************************************************************************
Binary file not shown.