//2008.12.11 修改mDiskCapacity返回错误的问题
//2009.1.4 修改TestReady函数错误处理,有些U盘不支持TestReady函数,这个函数可有可无
//2009.1.19 mDiskCapcity之前增加100毫秒延时,HostTransactInter函数中对死循环分支进行计数
#include <std.h>
#include <stdio.h>
#include <csl.h>
#include <csl_irq.h>
#include <que.h>
#include <csl_timer.h>
#include <clk.h>
#include "resource.h"
#include "appThreads.h"
#include "TYPE.H"
#include "fat32_WR.h"
#include "ch375driver.h"
#include "ch375cmd.h"
#include "drvLED.h"
//#include "fatsys.h"
extern QUE_Obj QUE_key;
extern QUE_Obj Freequeue;
volatile UINT32 USBEventId;
UINT8 UDiskID = 0;
void drvUSBIsr(UINT32 funcArg, UINT32 eventId);
// 获取设备描述符
UINT8 SetupGetDevDescr[] = { 0x80, 0x06, 0x00, 0x01, 0x00, 0x00, 0x12, 0x00 };
// 获取配置描述符
UINT8 SetupGetCfgDescr[] = { 0x80, 0x06, 0x00, 0x02, 0x00, 0x00, 0x04, 0x00 };
// 设置USB地址
UINT8 SetupSetUsbAddr[] = { 0x00, 0x05, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00 };
// 设置USB配置
UINT8 SetupSetUsbConfig[] = { 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
UINT8 SetupClrEndpStall[] = { 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
UINT8 BoResetUsbDisk[] = { 0x21, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
UINT8 UsbDevEndpSize = DEFAULT_ENDP0_SIZE; /* USB设备的端点0的最大包尺寸 */
UINT8 FlagDeviceStatus; /* 当前USB设备状态,通常用于中断方式的全局变量,本程序中未使用 */
BULK_ONLY_CMD mBOC; /* BulkOnly传输结构 */
UINT8 mSaveUsbPid; /* 保存最近一次执行的事务PID */
UINT8 mSaveDevEndpTog; /* 保存当前批量端点的同步标志 */
UINT8 mDiskBulkInEndp; /* IN端点地址 */
UINT8 mDiskBulkOutEndp; /* OUT端点地址 */
UINT8 mDiskInterfNumber; /* 接口号 */
UINT16 SectorSize; /* 扇区大小 */
static UINT8 Query374DeviceIn(void);
/*基础接口函数*/
/*
void CH374_PORT_INIT(void )
{
}由于使用标准并口读写时序,所以无需初始化 */
#define Write374Index(a) { CH374_IDX_PORT = a; } /* 向索引端口写入索引地址 */
//void Write374Index( UINT8 mIndex ) /* 向CH374写索引地址 */
//{
// CH374_IDX_PORT = mIndex;
//}
#define Write374Data(d) { CH374_DAT_PORT = d; } /* 向数据端口写入数据,索引地址自动加1 */
//void Write374Data( UINT8 mData ) /* 向CH374写数据 */
//{
// CH374_DAT_PORT = mData;
//}
#define Read374Data() ( CH374_DAT_PORT ) /* 从数据端口读出数据,索引地址自动加1 */
//UINT8 Read374Data( void ) /* 从CH374读数据 */
//{
// return( CH374_DAT_PORT );
//}
#define Read374Data0() ( CH374_IDX_PORT ) /* 从索引端口读出数据,索引地址不变,适用于[读出->修改->写回]操作 */
//UINT8 Read374Data0( void ) /* 从CH374读数据 */
//{
// return( CH374_IDX_PORT );
//}
UINT8 Read374Byte( UINT8 mAddr ) /* 从指定寄存器读取数据 */
{
UINT8 nTemp8;
Write374Index(mAddr);
nTemp8 = Read374Data();
return nTemp8;
}
void Write374Byte( UINT8 mAddr, UINT8 mData ) /* 向指定寄存器写入数据 */
{
Write374Index(mAddr);
Write374Data(mData);
}
/*
void Modify374Byte( UINT8 mAddr, UINT8 mAndData, UINT8 mOrData )
{
Write374Index( mAddr );
Write374Data( Read374Data0( ) & mAndData | mOrData );
}修改指定寄存器的数据,先与再或,比Write374Byte再Read374Byte效率高 */
void Read374Block( UINT8 mAddr, UINT8 mLen, PUINT8 mBuf )
{
Write374Index( mAddr );
while ( mLen -- ) *mBuf++ = Read374Data( );
}/* 从指定起始地址读出数据块 */
void Write374Block( UINT8 mAddr, UINT8 mLen, PUINT8 mBuf )
{
Write374Index( mAddr );
while ( mLen -- ) Write374Data( *mBuf++ );
}/* 向指定起始地址写入数据块 */
/*delay time of designation microsecond ,it basis of main frequency of SCM to adjust,not exactitude*/
void mDelayuS( UINT8 us )
{
volatile int i;
int count = us*20;
if(us==0)
return;
for(i = 0 ; i<count;i++)
{
_nop();
}
}
/*延时及中断函数*/
void mDelaymS( UINT8 ms )
{
while ( ms -- ) {
mDelayuS( 250 );
mDelayuS( 250 );
mDelayuS( 250 );
mDelayuS( 250 );
}
}/* 延时指定毫秒时间 */
void CH374DelaymS( UINT8 iDelay )
{
while ( Read374Byte( REG_SYS_INFO ) & BIT_INFO_SOF_PRES )
;/* 等待SOF结束,BIT_INFO_SOF_PRES=0 */
while ( iDelay -- ) { /* 延时指定毫秒 */
while ( ( Read374Byte( REG_SYS_INFO ) & BIT_INFO_SOF_PRES ) == 0 )
;/* 等待SOF开始,BIT_INFO_SOF_PRES=1 */
while ( Read374Byte( REG_SYS_INFO ) & BIT_INFO_SOF_PRES )
;/* 等待SOF结束,BIT_INFO_SOF_PRES=0 */
}
}
Bool Query374Interrupt( void )
{
// Write374Byte( REG_INTER_EN,0xf0 );//开启插拔中断使能
#ifdef CH374_INT_WIRE
return( CH374_INT_WIRE ? FALSE : TRUE ); /* 如果连接了CH374的中断引脚则直接查询中断引脚 */
#else
return( Read374Byte( REG_INTER_FLAG ) & BIT_IF_INTER_FLAG ? TRUE : FALSE ); /* 如果未连接CH374的中断引脚则查询中断标志寄存器 */
#endif
// Write374Byte( REG_INTER_EN,0xf2 );//开启插拔中断使能
}// 查询CH374中断(INT#低电平)
UINT8 Wait374Interrupt( void )
{
UINT16 i;
for ( i = 0; i < 65000; i ++ ) { // 计数防止超时
if ( Query374Interrupt( ) ) return( 0 );
}
return( ERR_USB_UNKNOWN ); // 不应该发生的情况
}// 等待CH374中断(INT#低电平),超时则返回ERR_USB_UNKNOWN
// CH374传输事务,输入目的端点地址/PID令牌/同步标志,返回同CH375,NAK不重试,超时/出错重试
UINT8 HostTransact374( UINT8 endp_addr, UINT8 pid, Bool tog )
{ // 本子程序着重于易理解,而在实际应用中,为了提供运行速度,应该对本子程序代码进行优化
UINT8 retry;
UINT8 s, r, u;
for ( retry = 0; retry < 20; retry ++ ) {
Write374Byte( REG_USB_H_PID, M_MK_HOST_PID_ENDP( pid, endp_addr ) ); // 指定令牌PID和目的端点号
// Write374Byte( REG_USB_H_CTRL, BIT_HOST_START | ( tog ? ( BIT_HOST_TRAN_TOG | BIT_HOST_RECV_TOG ) : 0x00 ) ); // 设置同步标志并启动传输
Write374Byte( REG_USB_H_CTRL, ( tog ? ( BIT_HOST_START | BIT_HOST_TRAN_TOG | BIT_HOST_RECV_TOG ) : BIT_HOST_START ) ); // 设置同步标志并启动传输
mDelayuS(200);
s = Wait374Interrupt( );
if ( s == ERR_USB_UNKNOWN ) return( s ); // 中断超时,可能是硬件异常
s = Read374Byte( REG_INTER_FLAG ); // 获取中断状态
if ( s & BIT_IF_DEV_DETECT ) { // USB设备插拔事件
mDelayuS( 200 ); // 等待传输完成
Write374Byte( REG_INTER_FLAG, BIT_IF_USB_PAUSE | BIT_IF_DEV_DETECT | BIT_IF_TRANSFER ); // 清中断标志
if ( s & BIT_IF_DEV_ATTACH ) { // USB设备连接事件
#ifdef DEBUG_NOW
printf( "*In\n" );
#endif
u = Read374Byte( REG_USB_SETUP );
if ( s & BIT_IF_USB_DX_IN ) { // 速度匹配,不需要切换速度
if ( u & BIT_SETP_USB_SPEED ) return( USB_INT_CONNECT_LS ); // 低速USB设备
return( USB_INT_CONNECT ); // 全速USB设备
}
else { // 速度失配,需要切换速度
if ( u & BIT_SETP_USB_SPEED ) return( USB_INT_CONNECT ); // 全速USB设备
return( USB_INT_CONNECT_LS ); // 低速USB设备
}
}
else { // USB设备断开事件
#ifdef DEBUG_NOW
printf( "*Out\n" );
#endif
return( USB_INT_DISCONNECT );
}
}
else if ( s & BIT_IF_TRANSFER ) { // 传输完成
mDelayuS( 200 ); // 等待传输完成
Write374Byte( REG_INTER_FLAG, BIT_IF_USB_PAUSE | BIT_IF_TRANSFER ); // 清中断标志
s = Read374Byte( REG_USB_STATUS ); // USB状态
r = s & BIT_STAT_DEV_RESP; // USB设备应答状态
switch ( pid ) {
case DEF_USB_PID_SETUP:
case DEF_USB_PID_OUT:
if ( r == DEF_USB_PID_ACK ) return( USB_INT_SUCCESS );
else if ( r == DEF_USB_PID_STALL || r == DEF_USB_PID_NAK ) return( r | 0x20 );
else if ( ! M_IS_HOST_TIMEOUT( s ) ) return( r | 0x20 ); // 不是超时/出错,意外应答
break;
case DEF_USB_PID_IN:
if ( M_IS_HOST_IN_DATA( s ) ) { // DEF_USB_PID_DATA0 or DEF_USB_PID_DATA1
if ( s & BIT_STAT_TOG_MATCH ) return( USB_INT_SUCCESS ); // 不同步则需丢弃后重试
}
else if ( r == DEF_USB_PID_STALL || r == DEF_USB_PID_NAK ) return( r | 0x20 );
else if ( ! M_IS_HOST_TIMEOUT( s ) ) return( r | 0x20 );