📄 usb.c
字号:
#include "REGSND1.H"
#include "USBDEF.H"
#include "UART.h"
//时钟参数宏
#define Rdiv 11
//USB寄存器设置相关的宏定义
#define PLLRES (0x1<<3) //PLLCON
#define PLLEN (0x1<<1)
#define USBE (0x1<<7) //USBCON
#define EEOFINT (0x1<<4)
#define FEN (0x1<<7)
#define FADDEN (0x1)
#define CONFG (0x1<<1)
#define DIR (0x1<<7) //UEPSTAX
#define RXOUTB1 (0x1<<6)
#define STALLRQ (0x1<<5)
#define TXRDY (0x1<<4)
#define STLCRC (0x1<<3)
#define RXSETUP (0x1<<2)
#define RXOUTB0 (0x1<<1)
#define TXCMP (0x1<<0)
//USB 请求的bRequert的含意宏
#define get_status 0x00 //取得状态
#define clear_feature 0x01 //清除特性
#define reserved 0x02 //保留
#define set_feature 0x03 //设置特性
#define set_address 0x05 //设置地址
#define get_descriptor 0x06 //取得描述符
#define get_configuration 0x08 //取得配置
#define set_configuration 0x09 //设置配置
#define get_interface 0x0a //取得接口
#define set_interface 0x0b //设置接口
/**---------------------------------------------------------------------------------
----------------------------------------------------------------------------------**/
void AtmelUSBInit() //用于USB的PLL时钟20M晶振时如下设置
{
int data i;
PLLNDIV = 0x04; //设置PLL时钟
PLLCON |= (0x3&Rdiv)<<6;
PLLRDIV = (0x3ff&Rdiv)>>2;
USBCLK=0;
PLLCON&=(~PLLRES); //使能PLL
PLLCON|=PLLEN;
USBCON&=(~USBE); //关闭USB并复位USB
for(i=0;i<3000;i++); //等待PLL工作稳定
USBCON|=USBE; //开启USB控制器
}
void EpEnable(void) //初始化USB端点
{
UEPNUM=0x00; UEPCONX=0x80;
UEPNUM=0x01; UEPCONX=0x86;
UEPNUM=0x02; UEPCONX=0x82;
UEPRST=0x07; UEPRST= 0x00;
UEPIEN=0x07; USBIEN|=EEOFINT;
USBADDR=FEN;
}
unsigned char ReadEp(unsigned char EpNum,unsigned char *Data) //读取端口数据
{
unsigned char data i=0;
UEPNUM=EpNum; //指端口号
while(i<UBYCTLX) //读数据到缓冲//UBYCTX得到数据长度
{
Data[i++]=UEPDATX;
}
UEPSTAX&=~(RXOUTB0|RXOUTB1|RXSETUP); //清除相关位
return(i);
}
void WriteEp(unsigned char EpNum,unsigned char nLength,unsigned char *Data) //写端口数据
{
unsigned char data i=0;
UEPNUM=EpNum; //选择端口
UEPSTAX|=DIR; //控制方向
while(nLength--) UEPDATX=Data[i++]; //写入FIFO
UEPSTAX|=TXRDY; //开始发送
while(!(UEPSTAX&TXCMP)) ;
UEPSTAX&=(~(TXCMP)); //清除TXCMP
}
//-------------以下用于对端点进行处理
void Set_Address(unsigned char EpNum) //设置USB地址1-127
{
WriteEp(0,0,0); //在Status阶段过后才能改变设备地址
USBADDR|=EpNum;
USBADDR|=FEN; //设置地址
USBCON|=FADDEN; //地址使能
}
//设备描述符
code unsigned char Device_Descriptor[18] = {
0x12, //0x12
0x01, //DEVICE descriptor
0x10, 0x01, //spec rev level (BCD) 1.0
0x0, //device class
0x0, //device subclass
0x0, //device protocol
0x20, //max packet size
0x05, 0x82, //National's vendor ID
0x00, 0x11, //National's product ID
0x00, 0x00, //National's revision ID
0, //index of manuf. string
0, //index of prod. string
0, //index of ser. # string
0x01 //number of configs.
};
//配置描述符
code unsigned char Configuration_Descriptor_All[32] = {
9, //Size of Descriptor in Bytes
2, //Configuration Descriptor (0x02)
0x20, //Total length in bytes of data returned LSB
0x00, //MSB
1, //Number of Interfaces
1, //Value to use as an argument to select this configuration
0, //Index of String Descriptor describing this configuration
0x80,
0xfa, //Maximum Power Consumption in 2mA units //recerive 500ma
9,
4,
0, //the index of the interface descriptor Number of Interface
0, //Value used to select alternative setting
2, //EndPoint Number Used in this Descriptor
8, //Class Code (Assigned by USB Org)
6, //interface subclass1=RBC,2=SFF,3=QIC,4=UFI,5=SFF,6=SCSI
0x50, //bulk 0nly Transport
0, //Index of String Descriptor Describing this interface
//Bulk-in Endpoint
0x07, //length of this desc.
0x05, //ENDPOINT descriptor TYPE
0x81, //address (IN) Endpoint 4 84
0x02, //attributes (BULK)
0x40, 0x00, //max packet size (64)
0x0, //Does not apply to Bulk endpoints
//Bulk-out Endpoint
0x07, //length of this desc.
0x05, //ENDPOINT descriptor TYPE
0x02, //address (OUT) Endpoint 5 05
0x02, //attributes (BULK)
0x40, 0x00, //max packet size (64)
0x0 //Does not apply to Bulk endpoints
};
void Get_Descriptor(unsigned char DesType,unsigned char nLength) //???? //得到描述符
{
if(DesType==0x01) //取设备描述符
WriteEp(0,18,Device_Descriptor);
if((DesType==0x02)&&(nLength==0x09)) //取端口描述符
WriteEp(0,9,Configuration_Descriptor_All);
if((DesType==0x02)&&(nLength==0xff)) //取端点描述符
{
WriteEp(0,32,Configuration_Descriptor_All);
WriteEp(0,2,&Device_Descriptor[4]);
}
if((DesType==0x02)&&(nLength==0x20))
WriteEp(0,32,Configuration_Descriptor_All); //取配置描述符
}
void Set_Configuration(unsigned char wValue) //设置配置
{
if(wValue == 0)
{
UEPNUM=0x00; UEPCONX=0x80;
UEPNUM=0x01; UEPCONX=0x86;
UEPNUM=0x02; UEPCONX=0x82;
USBCON&=(~CONFG);
WriteEp(0,0,0); //状态传送阶段之前完成指定操作
}
else if(wValue == 1)
{
UEPNUM=0x00; UEPCONX=0x80;
UEPNUM=0x01; UEPCONX=0x86;
UEPNUM=0x02; UEPCONX=0x82;
USBCON|=CONFG;
WriteEp(0,0,0); //状态传送阶段之前完成指定操作
}
}
void Ep0() //????????? //---端点0处理主函数
{
unsigned char data DT[32]={0,};
unsigned char data i;
i = ReadEp(0,DT);
if (((DT[0] & 0x60)==0) && i)
{
switch (DT[1])
{
case set_address :Set_Address(DT[2]); break; //设置地址
case get_descriptor :Get_Descriptor(DT[3],DT[6]); break; //取描述符
case set_configuration :Set_Configuration(DT[2]); break; //设置配置
default :; break;
}
}
else if(DT[0]==0xa1) //非标准USB请求
{
WriteEp(0,0,0);
}
}
/******************************************************************************/
/** 以下为利用Bulk_Only传输协议的函数部分 **/
/******************************************************************************/
unsigned char data bulk_CSW[]={0x55,0x53,0x42,0x53, // bytes 4 dCSWSignature
0x00,0x00,0x00,0x00, //bytes 4 dCSWTag
0x00,0x00,0x00,0x00, //bytes 4 dDataResiduce
0x00}; //bCSWStatus 00=good state.
typedef struct _STRUCT_CBW
{
unsigned char CBWCB[12]; //for UFI Command all have 12bit
} struct_CBW;
struct_CBW data bulk_CBW;
void WriteEpBulk(unsigned char EpNum,unsigned char nLength,unsigned char *Data)
{
unsigned char data i;
UEPNUM=EpNum; //---设置端点号
UEPSTAX|=DIR; //...设置为In模式
for(i=0;i<nLength;i++) UEPDATX=Data[i]; //---填缓冲区
UEPSTAX|=TXRDY; //---发送数据
}
void TransmitCSW() //向Host返回CSW
{
WriteEpBulk(1, sizeof(bulk_CSW), bulk_CSW);
while(!(UEPSTAX&TXCMP)) ;
UEPSTAX&=(~(TXCMP)); //清除TXCMP
UEPINT = 0;
}
void main_txdone() //数据发送完毕给出回复
{
UEPSTAX&=(~(TXCMP)); //清除TXCMP
TransmitCSW();
}
//////////////////////////////////有关输出端点的调用//////////////////////////////////////////////
#define Inquiry 0x12
#define Mode_Sense 0x1A
#define Read10 0x28
#define Read_Capacity 0x25
#define Read_Format_Capacities 0x23
#define Test_Unit_Ready 0x00
#define Verify 0x2F
#define Write10 0x2A
#define Medium_Removal 0x1E
#define SCSI_MSPGCD_TPP 0x1C
#define SCSI_MSPGCD_RETALL 0x3F
//SCSI-Inquiry命令的返回数据
code unsigned char B_InquiryData[] = {
0x00, //Direct Access Device
0x80, //RMB
0x00, //ISO/ECMA/ANSI
0x01, //Response Data Format
0x1f, //Additional Length
0x00, //Reserved
0x00, //Reserved
0x00, //Reserved
'U', 'E', 'S', 'T', 'C', '-', 'Z', 'H', //Vendor Information
'a', 'n', 'g', ' ', 'T', 'i', 'a', 'n', ' ', 'y', 'i',' ', 'V', '1', '.', '0', //Product Identification
0, 0, 0, 0}; //Product Revision Level n.nn
//SCSI-Read_Format_capacities命令的返回数据
code unsigned char B_Read_Format_capacities[] = {0x00, 0x00, 0x00, 0x10, //capacity list header
0x00, 0x00, 0x07, 0xf5, 0x01, 0x00, 0x02, 0x00, //capacity descriptor
//Number of Blocks =2037,unformatted media,blocklength = 512Bytes
0x00, 0x00, 0x07, 0xfd, 0x00, 0x00, 0x02, 0x00 //Formattable Capacity Descriptors
};
//SCSI-Read_Capacity命令的返回数据
code unsigned char B_Read_Capacity[] = {
0x00, 0x00, 0xfe, 0xa0, //Last Logical Block Address for 32MB
0x00, 0x00, 0x02, 0x00 //block length in bytes
};
//SCSI-Mode_Sense命令的返回数据
code unsigned char B_Mode_Sense_ALL[] = {0x0b, 0x00, //Mode Data Length
0x00, 0x08, 0x00, 0x00,
0x7d, 0, 0, 0, 0x02, 0x00
};
//SCSI-Mode_Sense命令的返回数据
code unsigned char B_Mode_Sense_TPP[] = {0xf0, 0x00, //Mode Data Length
05, 00, 00, 00, 00, 0x0b, 00, 00, 00, 00, 0x24, 00, 00, 00, 00, 00
};
//SCSI-Mode_Sense命令的返回数据
code unsigned char B_Mode_Sense_ZERO[] = {0x00, 0x06, //Mode Data Length
0x00, //Medium Type Code
0, //write enabled
0, 0, 0, 0 //reserved
};
void SCSI_Mode_Sense()
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -