📄 usb.c
字号:
}
/*由于USBN9603 的中断为电平触发型,而有些MCU的中断触发为边沿型 */
/*为了使程序有更好的移植性,先禁止USBN9603中断输出,然后再使能它 */
/*从而得到下一次中断产生时的触发边沿。 */
evnt=read_usb(MAMSK); /*保存原来的中断设置 */
write_usb(MAMSK,0); /*禁止USBN9603的中断输出*/
write_usb(MAMSK,evnt); /*恢复原来的中断设置 */
evnt=0; /*clear the evnt flag*/
}
/*******************************************************************
***** 初始化USBN9603 *****
*******************************************************************/
void init_usb(void)
{
/*toss out any previous state ***********************************/
CLR_MLTIPKT;/*exit multi-packet mode */
usb_cfg =0;
/*对USBN9603进行一次软件复位*/
write_usb(MCNTRL,SRST); /*写 0x01 到 MCNTRL*/
/*INTOC(1-0)=00 :禁止中断输出 */
/*NAT=0 :禁止被USB总线检测 */
/*VEG=0 :禁止内部3.3V稳压 */
/*SRST=1 :进行软件复位 */
/*等待软件复位完成*/
while(read_usb(MCNTRL)&0x01==0x00)
{
usb_cfg=0;
}
evnt=read_usb(RID); /*读取USBN9603的版本识别号*/
/*该数值因为0x02,由此可判断USBN9603是否被正确地挂在总线上*/
if(evnt==0x02)
{
Uart_Printf("\n* USBN9603 is found! *");
Uart_Printf("\n* USB interface is active now! *");
Uart_Printf("\n*-----------------------------------------------------------------------*");
}
else
Uart_Printf("\nUSBN9603 is not found!Pls check your hardware!");
write_usb(MCNTRL,VGE+INT_L_O); /*写0x04+0x40=0x44 到 MCNTRL(该句能否省略?)*/
/*INTOC(1-0)=01 :中断为低电平有效输出*/
/*VEG=0 :使能内部3.3V稳压 */
/*设置USBN9603的时钟输出*/
write_usb(CCONF,CLKDIV); /*输出时钟频率为4MHZ */
/* CLKDIV=5=0x0101=11,so frequency=48MHz/(CLKDIV+1)=4MHZ*/
/*set default address, enable EP0 only **************************/
write_usb(FAR,AD_EN+0); /*FAR is "Function Address Register"*/
/*write 0x80+0x00=0x80 to FAR*/
/*AD_EN=1 :Address Enable. When set to 1, bits AD6-0 are used in address comparison.*/
/* When cleared, the device does not respond to any token on the USB bus. */
/*采用寻址方式访问端点*/
write_usb(EPC0,0x00); /*设置端点0的寻址地址*/
/* 设置USBN9603的中断屏蔽位 */
write_usb(NAKMSK,NAK_O0); /*NAK evnts*/
/*NAK_O0=0x10*/
/*当EndPoint0收到OUT token时,MAEV中的NAK位将被置位*/
// write_usb(TXMSK,TXFIFO0);
write_usb(TXMSK,TXFIFO0+TXFIFO1+TXFIFO2+TXFIFO3); /*TX events*/
/*使能EndPoint0的发送中断*/
// write_usb(RXMSK,RXFIFO0);
write_usb(RXMSK,RXFIFO0+RXFIFO1+RXFIFO2+RXFIFO3); /*RX events*/
/*使能EndPoint0的接收中断*/
write_usb(ALTMSK,NORMAL_ALTMSK);
/*NORMAL_ALTMSK=SD3+RESET_A*/
/*使能Reset和SD3中断*/
/*SD3 :Suspend Detect 3 mS. This bit is set after 3 mS of IDLE is detected */
/* on the upstream port, indicating that the device should be */
/* suspended. The suspend occurs under firmware control by writing */
/* the suspend value to the Node Functional State (NF-SR) register. */
/* This bit is cleared when the register is read. */
/*RESET :This bit is set when 2.5 mS of SEO is detected on the upstream port.*/
/* In response, the functional state should be reset (NFS in the NFSR */
/* register is set to RESET), where it must remain for at least 100 mS.*/
/* The functional state can then return to Op-erational state. This bit*/
/* is cleared when the register is read. */
write_usb(MAMSK,(INTR_E+RX_EV+NAK+TX_EV+ALT));
/*向MAMSK写入INTR_E=0x80(master interrupt enable)*/
/* 和RX_EV=0x40(receive event) */
/* 和NAK=0x10(NAK event) */
/* 和TX_EV=0x04(transmit event) */
/* 和ALT=0x02(alternate event) */
/*enable the receiver and go operational ************************/
FLUSHTX0; /*置TX0为Idle,并清除其FIFO的读写指针*/
write_usb(RXC0,RX_EN); /*使能 RX0接收 */
write_usb(NFSR,OPR_ST); /*将OPR_ST=0x02写到NFSR中,置USBN9603为Operational State*/
write_usb(MCNTRL,VGE+INT_L_O+NAT); /*允许USB总线检测到USBN9603的接入*/
// LED1=0;
}
/**********************************************************************/
/* Following are vendor specific command */
/**********************************************************************/
/*vendor defined request: send command ane read device status*/
void sendcommand(void)
{
SET_SENDCMD; /*enter SENDCMD mode */
cmd_sze = 0;
usb_status = WaitForData; //wait for data
memset(cmd_buf, 0, 64);
}
void readstatus(void)
{
SET_READSTA; /*enter READSTA mode */
cmd_sze = 0;
memset(cmd_buf, 0, 64);
cmd_buf[0] = usb_status;
cmd_buf[1] = CF_NO;
cmd_buf[2] = OnBoardFalsh_YES;
cmd_buf[3] = Player_OK;
/*send the !!first data chunk back */
mlti_pkt(); mlti_pkt(); mlti_pkt(); mlti_pkt();
mlti_pkt(); mlti_pkt(); mlti_pkt(); mlti_pkt();
}
void root_information(void)
{
U32 page_num,Pointer,i;
U8 Page_Buf[512+16];
SET_ROOT;
/*读入Root informatiom*/
for(page_num=0;page_num<32;page_num++)
{
/*将Root information读到root_buf中*/
ReadPage(Root_Cluster,page_num,&(Page_Buf[0]));
for(Pointer=0;Pointer<512;Pointer++)
{
root_buf[page_num*16+Pointer/32][Pointer%32]=Page_Buf[Pointer];
}
}
n_size = 256; //256*64=16*1024
for(i = 0; i < 64; i++)
{
Pointer=(256-n_size)*64+i;
write_usb(TXD1,root_buf[Pointer/32][Pointer%32]); /*send data to the tx1 FIFO */
}
n_size--;
}
void memory_size(void)
{
char temp[64];
int i;
SET_MEM;
/* because of edian */
temp[0] = Disk_Size%256; //LS byte
temp[1] = Disk_Size/256;
temp[2] = 0x00;
temp[3] = 0x00;
for(i = 0; i < 64; i++)
write_usb(TXD1, temp[i]); /*send data to the tx1 FIFO */
//usb_status = 0xFF;
}
void download_file(void)
{
SET_DOWNLOAD; //enter download state!
if(comp_filename(BIOS_BIN,(U8 *)&cmd_buf[10])==0)
{
File2Sdram=1; //set the File2Sdram flag ,this file is BIOS.bin,and it should load to SDRAM then run in SDRAM
Uart_Printf("\nBios.bin is under downloading!");
}
else
creat_file((U8 *)&cmd_buf[10]); //将文件信息添加到Root information
/*计算文件的大小(单位:字节)*/
fsize = (int)cmd_buf[38] + (int)cmd_buf[39]*256 + (int)cmd_buf[40]*256*256 + (int)cmd_buf[41]*256*256*256;
/*将文件的大小换算为扇区数(Sector),并圆整*/
n_size = (fsize%512 == 0) ? fsize/512 : fsize/512+1;
total = 0; //清除已接收字节数计数器
}
void upload_file(void)
{
int i;
U32 root_location;
SET_UPLOAD; //enter upload state!
// get the location of this file via look for its file name in Root Directory //
root_location=find_file((U8 *)&cmd_buf[10]);
current_block=root_buf[root_location][27]*256+root_buf[root_location][26];
/* Get file length(:sector) */
n_size = cmd_buf[21] + cmd_buf[22]*256 + cmd_buf[23]*256*256 + cmd_buf[24]*256*256*256;
/* send the first chunk */
read_file(tx_buf);
total = 0;
for(i = 0; i < 64; i++)
write_usb(TXD1, tx_buf[i]); /*send data to the tx1 FIFO */
total += 64;
}
/*
USB通讯协议
一 总体思路
1.在USB通讯时,除了USB规定的缺省的endpoint0以外,另外开辟2个endpoint进行数据传送.
endpoint0用来传递USB命令和扩展的命令
地址01H的endpoint1用来传递上传数据
地址81H的endpoint2用来传递下传数据。
这3个endpoint的最大数据包长度都为64字节(对于Host而言)
2.下传命令基本格式
主机通过endpoint0向播放机传递命令,除了USB规定的标准的REQUEST以外,我们扩展两个命
令(Vendor):下传命令和读设备状态.其格式如下:
bmRequestType bRequest wValue wIndex wLength
下传命令: 40H F0H 0H 0H 40H
读设备状态:C0H F1H 0H 0H 40H
二 下传命令集:
主机下发的F0H命令的64字节的数据含义如下:
1.格式化命令:
A.格式化ON-BOARD FLASH芯片
8000H+其余为 20 H
B.格式化扩展CF卡
8001H+其余为 20 H
C.格式化扩展SMC卡
8002H+其余为 20 H
D.格式化扩展MMC卡
8003H+其余为 20 H
2.读取根目录信息:
A.读取ON-BOARD FLASH根目录信息
8200H+其余为 20 H
B.读取扩展CF卡根录信息
8201H+其余为 20 H
C.读取扩展SMC卡根目录信息
8202H+其余为 20 H
D.读取扩展MMC卡根目录信息
8203H+其余为 20 H
3.拷贝文件到播放器:
A.拷贝到ON-BOARD FLASH
8400H+8字节目录名+32字节文件名+其余为 20 H
B.拷贝到扩展CF卡
8401H+8字节目录名+32字节文件信息+其余为 20 H
C.拷贝到扩展SMC卡
8402H+8字节目录名+32字节文件信息+其余为 20 H
D.拷贝到扩展MMC卡
8403H+8字节目录名+32字节文件信息+其余为 20 H
4.删除文件:
A.删除ON-BOARD FLASH文件
8500H+8字节目录名+32字节文件信息+其余为 20 H
B.删除扩展CF卡文件
8501H+8字节目录名+32字节文件信息+其余为 20 H
C.删除扩展SMC卡文件
8502H+8字节目录名+32字节文件信息+其余为 20 H
D.删除扩展MMC卡文件
8503H+8字节目录名+32字节文件信息+其余为 20 H
5.重命名文件名:
A.重命名ON-BOARD FLASH 文件
8800H+8字节目录名+8字节旧文件名+8字节新文件名+其余为 20 H
B.重命名扩展CF卡文件
8801H+8字节目录名+8字节旧文件名+8字节新文件名+其余为 20 H
C.重命名扩展SMC卡文件
8802H+8字节目录名+8字节旧文件名+8字节新文件名+其余为 20 H
D.重命名扩展MMC卡文件
8803H+8字节目录名+8字节旧文件名+8字节新文件名+其余为 20 H
6.读取文件到PC机:
A.读取ON-BOARD FLASH
8900H+8字节目录名+11字节文件名+4字节文件大小(单位:扇区)+其余为 20 H
B.读取扩展CF卡
8901H+8字节目录名+11字节文件名+4字节文件大小(单位:扇区)+其余为 20 H
C.读取扩展SMC卡
8902H+8字节目录名+11字节文件名+4字节文件大小(单位:扇区)+其余为 20 H
D.读取扩展MMC卡
8903H+8字节目录名+11字节文件名+4字节文件大小(单位:扇区)+其余为 20 H
7.程序升级:
8A00 + 62字节20H
8.读卡的大小(以1个sector=512B为基本单位)
A.读取ON-BOARD FLASH 的容量大小
8c00H+其余为 20 H
B.读取扩展CF卡的容量大小
8c01H+其余为 20 H
C.读取扩展SMC卡的容量大小
8c02H+其余为 20 H
D.读取扩展MMC卡的容量大小
8c03H+其余为 20 H
9.上下传取消
8B00 + 62字节20H
三 读取设备状态命令
主机向播放器发送读取设备状态命令后(1s 读一次),播放器应答播放器对主机发来的最后
一条下传命令的执行情况.这条命令的数据长度为固定长度64字节,具体格式如下:
第一字节:0XFF PC机可以发送命令
0X10 PC机可以发送数据
第二字节:0X00 播放器没有外部CF卡
0X01 播放器有外部CF卡
第三字节:0X00 播放器没有内部FLASH
0X01 播放器有内部FLASH
第四字节:0X00 播放器运行正常
0X01 播放器运行出错
四. 其他
1.启动PC程序,自动刷新
2.刷新包括读根目录命令,读卡的大小命令
3.任何的命令完成(例如下传,删除,重命名等)后,都需要运行一遍刷新命令
4.下传文件的文件名(11byte)需要转化成大写
5.下载升级程序时,须对选中的二进制文件进行校验,最后16字节为校验码,比较其中前面7
个字节应为MPF2000,最后一个字节应为对文件的每个字节异或得出的校验码是否相同。
*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -