first submission
This commit is contained in:
@@ -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,317 @@
|
||||
/********************************** (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;
|
||||
|
||||
/*********************************************************************
|
||||
* @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 CHRV3DiskStatus status, for example,
|
||||
* call CHRV3DiskReady 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 CHRV3DiskReady once, if successful, then continue the operation, such as Open, Read/Write, etc.
|
||||
* 2?If CHRV3DiskReady 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 USBFS host */
|
||||
DUG_PRINTF( "USBFS Host Init\r\n" );
|
||||
USBFS_RCC_Init( );
|
||||
USBFS_Host_Init( ENABLE );
|
||||
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 ) );
|
||||
|
||||
/* USB Libs Initialization */
|
||||
printf( "UDisk library Initialization. \r\n" );
|
||||
CHRV3LibInit( );
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @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 */
|
||||
USBFSH_ResetRootHubPort( 0 );
|
||||
for( i = 0, s = 0; i < DEF_RE_ATTACH_TIMEOUT; i++ )
|
||||
{
|
||||
if( USBFSH_EnableRootHubPort( &RootHubDev[ usb_port ].bSpeed ) == 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 */
|
||||
USBFSH_SetSelfSpeed( RootHubDev[ usb_port].bSpeed );
|
||||
|
||||
/* Get USB device device descriptor */
|
||||
DUG_PRINTF("Get DevDesc: ");
|
||||
s = USBFSH_GetDeviceDescr( &RootHubDev[ usb_port ].bEp0MaxPks, DevDesc_Buf );
|
||||
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: ");
|
||||
RootHubDev[ usb_port ].bAddress = (uint8_t)( DEF_USB_PORT_FS + USB_DEVICE_ADDR );
|
||||
s = USBFSH_SetUsbAddress( RootHubDev[ usb_port ].bEp0MaxPks, RootHubDev[ usb_port ].bAddress );
|
||||
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 = USBFSH_GetConfigDescr( RootHubDev[ usb_port ].bEp0MaxPks, Com_Buffer, DEF_COM_BUF_LEN, &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 = USBFSH_SetUsbConfig( RootHubDev[ usb_port ].bEp0MaxPks, 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 UDisk_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;
|
||||
usb_port = DEF_USB_PORT_FS;
|
||||
ret = USBFSH_CheckRootHubPortStatus( RootHubDev[ usb_port ].bStatus );
|
||||
if( ret == ROOT_DEV_CONNECTED )
|
||||
{
|
||||
DUG_PRINTF("USB Dev In.\n");
|
||||
USBFSH_CheckRootHubPortStatus( RootHubDev[ usb_port ].bStatus );
|
||||
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 ) );
|
||||
UDisk_Opeation_Flag = 1;
|
||||
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( "CHRV3DiskStatus:%02x\n", CHRV3DiskStatus);
|
||||
UDisk_Opeation_Flag = 1;
|
||||
return DISK_READY;
|
||||
}
|
||||
else
|
||||
{
|
||||
DUG_PRINTF("Not Ready Code :%02x.\r\n", ret);
|
||||
DUG_PRINTF("CHRV3DiskStatus:%02x.\n", CHRV3DiskStatus);
|
||||
}
|
||||
Delay_Ms( 50 );
|
||||
}
|
||||
}
|
||||
return CHRV3DiskStatus;
|
||||
}
|
||||
|
||||
@@ -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 "ch32v20x_usbfs_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,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;
|
||||
|
||||
ret = UDisk_USBH_DiskReady( );
|
||||
if( (ret == DISK_READY)&&( 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" );
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user