📄 myudisk.c
字号:
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include "def.h"
#include "2410addr.h"
#include "2410lib.h"
#include "2410usb.h"
#include "MyUDisk.h"
#include "usblib.h"
#define MY_UDISK_STARTADDR 0x31500000 //划出32M的SDRAM来模拟FLASH
#define MY_UDISK_ENDADDR 0x33500000
unsigned char Device_Descriptor[18] = {
0x12, //0x12
0x01, //设备描述符类型
0x10, 0x01, //spec rev level (BCD) 1.0
0x0, //设备类型代码
0x0, //设备子类型代码
0x0, //设备协议
0x08, //控制端点的最大包个数 max packet size
0x45, 0x53,
0x34, 0x12,
0x00, 0x01,
0,
0,
0,
0x01 //配置数量
};
unsigned char Configuration_Descriptor_All[32] = {
/*配置描述符*/
9, //描述符长度
2, //配置描述符 (0x02)
0x20, //总长32 字节
0x00,
1, //设备接口数量
1, //配置标示值
0,
0xc0, //供电方式
25, //50ma
/*接口描述符*/
9, //描述符长度
4, //接口描述符
0,
0,
2, //设备中用到的端口数目
8, //设备类代码--海量存储设备
6, //6=SCSI
0x50, //bulk 0nly 传输
0,
/*端口描述符*/
0x07, //端口描述符长度.
0x05, //描述符类型---端口
0x81, //IN端口
0x02, //BULK端口
0x20, 0x00, //最大传输量
0x0,
0x07, //端口描述符长度.
0x05, //描述符类型---端口
0x03, //OUT端口
0x02, //BULK端口
0x20, 0x00, //最大传输量
0x0
};
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 //
'X', 'I', 'N', 'Z', 'X', ' ', ' ', ' ', //Vendor Information
'U', 'S', 'B', '-', 'M', 'A', 'S', 'S', 'S', 'T', 'O', 'R', 'A', 'G', 'E', ' ',//Product Identification
0, 0, 0, 0 //
};
/*SCSI-Read_Format_capacities命令的返回数据 */
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
//注:这里的Block和下面的不一样,1Block=32Page=32*512byte
//即2037*32*512==32M
//???但是和我在BusHound上监控到的aigo的优盘上的数据不一致//在哪里,1Block=1Page
0x00, 0x00, 0x07, 0xfd, 0x00, 0x00, 0x02, 0x00 //Formattable Capacity Descriptors
//???BlockNum不一样呢,好奇怪呀???
};
//SCSI-Read_Capacity命令的返回数据
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命令的返回数据
unsigned char B_Mode_Sense_ALL[] = {0x0b, 0x00, //Mode Data Length
0x00, 0x08, 0x00, 0x00,
0x7d, 0, 0, 0, 0x02, 0x00
};
//SCSI-Mode_Sense命令的返回数据
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命令的返回数据
unsigned char B_Mode_Sense_ZERO[] = {0x00, 0x06, //Mode Data Length
0x00, //Medium Type Code
0, //write enabled
0, 0, 0, 0 //reserved
};
unsigned char 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.
struct_CBW bulk_CBW;
U8 ep3Buf[EP3_PKT_SIZE];
int ep0State;
struct USB_SETUP_DATA descSetup;
//为了实现IN端点和OUT端点的协调工作,增加这些信息
//IN端点中用到的状态信息
unsigned char * g_pIN_NextData; //指向需要的发送数据区的指针
int g_iIN_NextCount; //剩余的需要发送的数据的长度
int g_iInNeeded; //在数据结束之后,需要一个CSW数据包
//OUT端点中用到的状态信息
unsigned char * g_pOUT_NextData;
int g_iOUT_NextCount;
// int g_iOUT_Count;
// int g_iOutNeeded; //表示在OUT的数据接收阶段如Write10的处理
/**********************************************************************
// 描 述: USB中断服务函数
// 返 回: void __irq
// 参 数: void
**********************************************************************/
void __irq IsrUsbd(void)
{
U8 usbdIntpnd,epIntpnd;
U8 saveIndexReg=rINDEX_REG;
usbdIntpnd=rUSB_INT_REG;
epIntpnd=rEP_INT_REG;
//DbgPrintf( "[INT:EP_I=%x,USBI=%x]",epIntpnd,usbIntpnd );
//注:需要明白各中断产生的条件
if(usbdIntpnd&SUSPEND_INT) //挂起中断
{
rUSB_INT_REG=SUSPEND_INT;
DbgPrintf( "<SUS]");
}
if(usbdIntpnd&RESUME_INT) //恢复中断
{
rUSB_INT_REG=RESUME_INT;
DbgPrintf("<RSM]");
}
if(usbdIntpnd&RESET_INT) //复位中断
{
DbgPrintf( "<RST]");
InitUsbd();
rUSB_INT_REG=RESET_INT;
//PrepareEp1Fifo();
}
if(epIntpnd&EP0_INT)
{
rEP_INT_REG=EP0_INT; //清除相应的中标志位断
Ep0Handler(); //
}
if(epIntpnd&EP1_INT)
{
rEP_INT_REG=EP1_INT;
Ep1Handler();
}
if(epIntpnd&EP2_INT)
{
rEP_INT_REG=EP2_INT; //Ep2没有使用
DbgPrintf("<2:TBD]"); //not implemented yet
}
if(epIntpnd&EP3_INT)
{
rEP_INT_REG=EP3_INT;
Ep3Handler();
}
if(epIntpnd&EP4_INT)
{
rEP_INT_REG=EP4_INT; //Ep4没有使用
DbgPrintf("<4:TBD]"); //not implemented yet
}
ClearPending(BIT_USBD);
rINDEX_REG=saveIndexReg; //恢复原来的中断寄存器状态
}
//**********************************************************************
// 描 述: 中断二次初始化函数
// 返 回: void
// 参 数: void
//**********************************************************************
void Isr_Init(void)
{
rINTMOD=0x0; // All=IRQ mode
rINTMSK=BIT_ALLMSK; // All interrupt is masked.
pISR_USBD =(unsigned)IsrUsbd; //USB设备中断处理程序
ClearPending(BIT_USBD); //
}
/**********************************************************************/
// 描 述: 初始化USB相关结构
// 返 回: void
// 参 数: void
/**********************************************************************/
void InitUsbd(void)
{
//初始设备描述表
//配置端点信息//这些寄存器的设置的含义必须要搞清楚//主要是和数据处理相关的设置
// *** End point information ***
// EP0: control
// EP1: bulk in end point
// EP2: not used
// EP3: bulk out end point
// EP4: not used
rPWR_REG=PWR_REG_DEFAULT_VALUE; //disable suspend mode
rINDEX_REG =0;
rMAXP_REG =FIFO_SIZE_8; //EP0 max packit size = 8 //因为EndPoint0 的FIFO缓冲也就只有8个Byte
rEP0_CSR =EP0_SERVICED_OUT_PKT_RDY|EP0_SERVICED_SETUP_END;
//EP0:clear OUT_PKT_RDY & SETUP_END
rINDEX_REG=1;
#if (EP1_PKT_SIZE==32)
rMAXP_REG=FIFO_SIZE_32; //EP1:max packit size = 32
#else
rMAXP_REG=FIFO_SIZE_64; //EP1:max packit size = 64
#endif
rIN_CSR1_REG=EPI_FIFO_FLUSH|EPI_CDT;
rIN_CSR2_REG=EPI_MODE_IN|EPI_IN_DMA_INT_MASK|EPI_BULK; //IN mode, IN_DMA_INT=masked
rOUT_CSR1_REG=EPO_CDT;
rOUT_CSR2_REG=EPO_BULK|EPO_OUT_DMA_INT_MASK;
rINDEX_REG=3;
#if (EP3_PKT_SIZE==32)
rMAXP_REG=FIFO_SIZE_32; //EP3:max packit size = 32
#else
rMAXP_REG=FIFO_SIZE_64; //EP3:max packit size = 64
#endif
rIN_CSR1_REG=EPI_FIFO_FLUSH|EPI_CDT;
rIN_CSR2_REG=EPI_MODE_OUT|EPI_IN_DMA_INT_MASK|EPI_BULK; //OUT mode, IN_DMA_INT=masked
rOUT_CSR1_REG=EPO_CDT;
//clear OUT_PKT_RDY, data_toggle_bit.
//The data toggle bit should be cleared when initialization.
rOUT_CSR2_REG=EPO_BULK|EPO_OUT_DMA_INT_MASK;
//Clear all usbd pending bits//现将中断清掉
rEP_INT_REG=EP0_INT|EP1_INT|EP2_INT|EP3_INT|EP4_INT;
rUSB_INT_REG=RESET_INT|SUSPEND_INT|RESUME_INT;//
//EP0,1,3 & reset interrupt are enabled
rEP_INT_EN_REG=EP0_INT|EP1_INT|EP3_INT;
rUSB_INT_EN_REG=RESET_INT;
//使能USB中断
rINTMSK&=~(BIT_USBD);
}
/**********************************************************************
// 描 述: USB处理的主函数
// 返 回: void
// 参 数: void
**********************************************************************/
void Main(void)
{
int i;
//设定时钟分频值
ChangeClockDivider(1,1); //1:2:4
ChangeMPllValue(82,1,1); //FCLK=180.0Mhz
//IO管脚的基本功能的初始化
Port_Init();
//把GPH10和GPH9中的两个引脚设置成输出OutPut
rGPHCON = rGPHCON&~(0xf<<18)|(0x5<<18); //=>等价于rGPHCON = (rGPHCON&(~(0xf<<18)))|(0x5<<18)
//To enhance the USB signal quality.
//CLKOUT 0,1=OUTPUT to reduce the power consumption.
//???也没有看出这个引脚就连接到USB的使能端呀,在哪里看出来的???
//注:看看底板的原理图可知//当然还要看看USB的电气规范可知,对于高速设备D+端要接高电平
rGPHDAT = rGPHDAT | (1<<9); //USB_EN(device) //所以此处要接上拉电阻
//设置USB的中断处理函数
Isr_Init();
//初始化串口,以供通讯使用
Uart_Init(0,115200);
Uart_Select(0);
//???????????????????????????选择USB设备??????????????????????????
rMISCCR=rMISCCR&~(1<<3); // USBD is selected instead of USBH1??
rMISCCR=rMISCCR&~(1<<13); // USB port 1 is enabled. ??????????
//MMU_EnableICache(); //???使能cache
InitUsbd(); //完成各数据结构以及USB寄存器的初始化,并且将EP1的FIFO缓冲区中准备好数据以等待发送
while (1) //一切事情由中断服务程序去处理
{
if(DbgPrintfLoop())continue;
Delay(5000);
if((i++%2)==0)Led_Display(0x8);
else Led_Display(0x0);
}
}
#define DBGSTR_LENGTH (0x1000)
U8 dbgStrFifo[DBGSTR_LENGTH];
volatile U32 dbgStrRdPt=0;
volatile U32 dbgStrWrPt=0;
int DbgPrintfLoop(void)
{
if(dbgStrRdPt==dbgStrWrPt)return 0;
Uart_SendByte(dbgStrFifo[dbgStrRdPt++]);
if(dbgStrRdPt==DBGSTR_LENGTH)dbgStrRdPt=0;
return 1;
}
void _WrDbgStrFifo(U8 c)
{
dbgStrFifo[dbgStrWrPt++]=c;
if(dbgStrWrPt==DBGSTR_LENGTH)dbgStrWrPt=0;
}
void DbgPrintf(char *fmt,...)
{
int i,slen;
va_list ap;
char string[256];
va_start(ap,fmt);
vsprintf(string,fmt,ap);
slen=strlen(string);
for(i=0;i<slen;i++)
_WrDbgStrFifo(string[i]);
va_end(ap);
}
//打印出USB控制端点收到的SETUP包的8个字节的内容
void PrintEp0Pkt(U8 *pt)
{
int i;
DbgPrintf("[RCV:");
for(i=0;i<EP0_PKT_SIZE;i++)
DbgPrintf("%x,",pt[i]);
DbgPrintf("]");
}
void RdPktEp0(U8 *buf,int num)
{
int i;
for(i=0;i<num;i++)
{
buf[i]=(U8)rEP0_FIFO;
}
}
void WrPktEp0(U8 *buf,int num)
{
int i;
for(i=0;i<num;i++)
{
rEP0_FIFO=buf[i];
}
}
void WrByteEp0(U8 value)
{
rEP0_FIFO= value;
}
void WrPktEp1(U8 *buf,int num)
{
int i;
for(i=0;i<num;i++)
{
rEP1_FIFO=buf[i];
}
}
void WrPktEp2(U8 *buf,int num)
{
int i;
for(i=0;i<num;i++)
{
rEP2_FIFO=buf[i];
}
}
void RdPktEp3(U8 *buf,int num)
{
int i;
for(i=0;i<num;i++)
{
buf[i]=(U8)rEP3_FIFO;
}
}
void RdPktEp4(U8 *buf,int num)
{
int i;
for(i=0;i<num;i++)
{
buf[i]=(U8)rEP4_FIFO;
}
}
/**********************************************************************
// 描 述: 端口0处理函数
// 返 回: void
// 注: 我觉得这里才是重点和难点!!!!!//状态机的处理相一致。
// 这 个处理函数表征了对USB标准协议中的请求命令的支持
**********************************************************************/
void Ep0Handler(void)
{
U8 ep0_csr;
U8 temp ;
int save = 0;
save = rINDEX_REG ;
rINDEX_REG=0;
ep0_csr=rEP0_CSR;
DbgPrintf("<0:%x]",ep0_csr);
//DATAEND interrupt(ep0_csr==0x0) will be ignored
//because ep0State==EP0_STATE_INIT when the DATAEND interrupt is issued.
if(ep0_csr & EP0_SETUP_END)
{
// Host may end GET_DESCRIPTOR operation without completing the IN data stage.
// If host does that, SETUP_END bit will be set.
// OUT_PKT_RDY has to be also cleared because status stage sets OUT_PKT_RDY to 1.
DbgPrintf("[SETUPEND]"); //表示USB在SetUp阶段异常中止
CLR_EP0_SETUP_END();
if(ep0_csr & EP0_OUT_PKT_READY)
{
FLUSH_EP0_FIFO(); //(将缓冲区中的数据全部清除掉)
//I think this isn't needed because EP0 flush is done automatically.
CLR_EP0_OUT_PKT_RDY();
}
ep0State=EP0_STATE_INIT; //状态机回到初始态
return;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -