📄 mx1_usb.c
字号:
{
U32 fifoWord;
U8 i, j,tmp;
/* read device request data from FIFO */
j = 0;
for (i=0; i<2; i++)
{
fifoWord = _reg_USBD_EP0_FDAT;
tmp = (U8)(fifoWord >> 24);
// EUARTputHex(tmp);
_gUsbDevReq[j++] = tmp;
tmp = (U8)(fifoWord >> 16);
// EUARTputHex(tmp);
_gUsbDevReq[j++] = tmp;
tmp = (U8)(fifoWord >> 8);
// EUARTputHex(tmp);
_gUsbDevReq[j++] = tmp;
tmp = (U8)(fifoWord);
// EUARTputHex(tmp);
_gUsbDevReq[j++] = tmp;
}
/* decode device request */
if ((_gUsbDevReq[0] = 0x80) && (_gUsbDevReq[1] = 0x06))
{
switch (_gUsbDevReq[3])
{
case 0x01: // device descriptor
handleGetDevDscptr();
break;
case 0x02: // configuration descriptor
handleGetConfDscptr();
break;
}
}
_reg_USBD_EP0_INTR_STAT = 0x1FF; // clear all interrupt flags
}
void readSectors()
{
U8 done, i;
done = 0;
while (!done)
{
while (!(_reg_USBD_EP1_INTR_STAT & EOF_MASK)); // wait for EOF flag
--_gUsbPacketCount;
if (_gUsbPacketCount > 0)
{
for (i=0; i<31; i++)
*((volatile U8 *)((U32)&_reg_USBD_EP1_FDAT+3)) = *(_gpUsbBufPtr++);
_reg_USBD_EP1_FCTRL |= 0x20000000; // next is last word in packet
*((volatile U8 *)((U32)&_reg_USBD_EP1_FDAT+3)) = *(_gpUsbBufPtr++);
}
else
{
// now the CSW
_reg_USBD_EP1_FDAT = 0x55534253; // signature in BIG endian
for (i=0; i<4; i++)
*((volatile U8 *)((U32)&_reg_USBD_EP1_FDAT+3)) = _gCBW[4+i]; // CSWtag
_reg_USBD_EP1_FDAT = 0; // data residue
_reg_USBD_EP1_FCTRL |= 0x20000000; // next is last word in packet
*((volatile U8 *)((U32)&_reg_USBD_EP1_FDAT+3)) = 0; // status: passed
done = 1;
}
_reg_USBD_EP1_INTR_STAT |= EOF_MASK; // clear EOF flag
}
}
void writeSectors()
{
U8 i;
while (_gUsbPacketCount > 0)
{
while (!(_reg_USBD_EP2_INTR_STAT & EOF_MASK)); // wait for EOF flag
while (((_reg_USBD_EP2_STAT >> 16) & 0x7F) >= 0x20)
{
for (i=0; i<32; i++)
*(_gpUsbBufPtr++) = *((volatile U8 *)((U32)&_reg_USBD_EP2_FDAT+3));
--_gUsbPacketCount;
}
}
// now the CSW
_reg_USBD_EP1_FDAT = 0x55534253; // signature in BIG endian
for (i=0; i<4; i++)
*((volatile U8 *)((U32)&_reg_USBD_EP1_FDAT+3)) = _gCBW[4+i]; // CSWtag
_reg_USBD_EP1_FDAT = 0; // data residue
_reg_USBD_EP1_FCTRL |= 0x20000000; // next is last word in packet
*((volatile U8 *)((U32)&_reg_USBD_EP1_FDAT+3)) = 0; // status: passed
}
void processCommand()
{
U8 i;
for (i=0; i<31; i++)
_gCBW[i] = *((volatile U8 *)((U32)&_reg_USBD_EP2_FDAT+3));
_reg_USBD_EP2_INTR_STAT |= EOT_MASK; // clear EOT flag
//printf( "\r\n" );
//MX1_UART_OutputHex( MX1_UART1, _gCBW[15] );
//printf( "\r\n" );
switch(_gCBW[15])
{
case 0x12: // inquiry
_reg_USBD_EP1_FDAT = 0x00800001;
_reg_USBD_EP1_FDAT = 0x5B000000;
// vendor identification (8 bytes)
_reg_USBD_EP1_FDAT = 0xc6d5ccec; // "MOTO"
_reg_USBD_EP1_FDAT = 0xbbdbd1b6; // "ROLA"
// product identification (16 bytes)
_reg_USBD_EP1_FDAT = 0x454D2D41; // "MX1 "
_reg_USBD_EP1_FDAT = 0x524D3920; // "ADS "
_reg_USBD_EP1_FDAT = 0x332E3220;
_reg_USBD_EP1_FCTRL |= 0x20000000; // next is last word in packet
_reg_USBD_EP1_FDAT = 0x20202020; // " "
// product revision level (4 bytes)
*((volatile U8 *)((U32)&_reg_USBD_EP1_FDAT+3)) = 0x30;
*((volatile U8 *)((U32)&_reg_USBD_EP1_FDAT+3)) = 0x31;
*((volatile U8 *)((U32)&_reg_USBD_EP1_FDAT+3)) = 0x30;
_reg_USBD_EP1_FCTRL |= 0x20000000; // next is last word in packet
*((volatile U8 *)((U32)&_reg_USBD_EP1_FDAT+3)) = 0x30;
// now the CSW
_reg_USBD_EP1_FDAT = 0x55534253; // signature in BIG endian
for (i=0; i<4; i++)
*((volatile U8 *)((U32)&_reg_USBD_EP1_FDAT+3)) = _gCBW[4+i]; // CSWtag
_reg_USBD_EP1_FDAT = 0; // data residue
_reg_USBD_EP1_FCTRL |= 0x20000000; // next is last word in packet
*((volatile U8 *)((U32)&_reg_USBD_EP1_FDAT+3)) = 0; // status: passed
// SerialOutputString("0x12\n\r");
break;
case 0x23://EUARTputString("0x23\n "); // READ FORMAT CAPACITIES, not supported, return STALL
case 0x1A://EUARTputString("0x1a\n "); // MODE SENSE, not supported, return STALL
case 0x5A: // MODE SENSE, not supported, return STALL
_reg_USBD_EP1_STAT |= FORCE_STALL_MASK;
// now the CSW
_reg_USBD_EP1_FDAT = 0x55534253; // signature in BIG endian
for (i=0; i<8; i++)
*((volatile U8 *)((U32)&_reg_USBD_EP1_FDAT+3)) = _gCBW[4+i]; // CSWtag
_reg_USBD_EP1_FCTRL |= 0x20000000; // next is last word in packet
*((volatile U8 *)((U32)&_reg_USBD_EP1_FDAT+3)) = 0x01; // status: failed
// SerialOutputString("0x5a\n\r");
break;
case 0x03: // REQUEST SENSE, return error
_reg_USBD_EP1_FDAT = 0x70000500;
_reg_USBD_EP1_FDAT = 0x0000000C;
_reg_USBD_EP1_FDAT = 0x00000000;
_reg_USBD_EP1_FDAT = 0x20000000;
*((volatile U8 *)((U32)&_reg_USBD_EP1_FDAT+3)) = 0x00;
_reg_USBD_EP1_FCTRL |= 0x20000000; // next is last word in packet
*((volatile U8 *)((U32)&_reg_USBD_EP1_FDAT+3)) = 0x00;
// now the CSW
_reg_USBD_EP1_FDAT = 0x55534253; // signature in BIG endian
for (i=0; i<4; i++)
*((volatile U8 *)((U32)&_reg_USBD_EP1_FDAT+3)) = _gCBW[4+i]; // CSWtag
_reg_USBD_EP1_FDAT = 0; // data residue
_reg_USBD_EP1_FCTRL |= 0x20000000; // next is last word in packet
*((volatile U8 *)((U32)&_reg_USBD_EP1_FDAT+3)) = 0; // status: passed
// SerialOutputString("0x03\n\r");
break;
case 0x25: // READ CAPACITY
_reg_USBD_EP1_FDAT = DISK_LAST_SECTOR; // last sector of disk
_reg_USBD_EP1_FCTRL |= 0x20000000; // next is last word in packet
_reg_USBD_EP1_FDAT = 0x00000200; // block size
// now the CSW
_reg_USBD_EP1_FDAT = 0x55534253; // signature in BIG endian
for (i=0; i<4; i++)
*((volatile U8 *)((U32)&_reg_USBD_EP1_FDAT+3)) = _gCBW[4+i]; // CSWtag
_reg_USBD_EP1_FDAT = 0; // data residue
_reg_USBD_EP1_FCTRL |= 0x20000000; // next is last word in packet
*((volatile U8 *)((U32)&_reg_USBD_EP1_FDAT+3)) = 0; // status: passed
// SerialOutputString("0x25\n\r");
break;
case 0x28: // READ
// extract start sector
_gUsbCurSector = 0;
for (i=0; i<4; i++)
_gUsbCurSector = (_gUsbCurSector << 8) | (U32)_gCBW[17+i];
// extract number of sectors
_gUsbNumSector = (((U32)_gCBW[22]) << 8) | ((U32)_gCBW[23]);
_gUsbPacketCount = _gUsbNumSector * 16;
_gpUsbBufPtr = (unsigned char *)(USB_DISK_START + _gUsbCurSector * 512);
// fill up the 1st packet
for (i=0; i<31; i++)
*((volatile U8 *)((U32)&_reg_USBD_EP1_FDAT+3)) = *(_gpUsbBufPtr++);
_reg_USBD_EP1_FCTRL |= 0x20000000; // next is last word in packet
*((volatile U8 *)((U32)&_reg_USBD_EP1_FDAT+3)) = *(_gpUsbBufPtr++);
// read sectors
readSectors();
// SerialOutputString("0x28\n\r");
break;
case 0x00://EUARTputString("0x00\n "); // NULL COMMAND, return CSW with pass
case 0x1E://EUARTputString("0x1e\n "); // PREVENT-ALLOW MEDIUM REMOVAL, return CSW with pass
case 0x2F://EUARTputString("0x2f\n "); // VERIFY
// now the CSW
_reg_USBD_EP1_FDAT = 0x55534253; // signature in BIG endian
for (i=0; i<4; i++)
*((volatile U8 *)((U32)&_reg_USBD_EP1_FDAT+3)) = _gCBW[4+i]; // CSWtag
_reg_USBD_EP1_FDAT = 0; // data residue
_reg_USBD_EP1_FCTRL |= 0x20000000; // next is last word in packet
*((volatile U8 *)((U32)&_reg_USBD_EP1_FDAT+3)) = 0; // status: passed
break;
case 0x1B: // START-STOP UNIT (when host EJECT)
// printk("\nEJECT from host detected.\n");
//printf("\n\rEJECT from host detected.\n\r");
// now the CSW
_reg_USBD_EP1_FDAT = 0x55534253; // signature in BIG endian
for (i=0; i<4; i++)
*((volatile U8 *)((U32)&_reg_USBD_EP1_FDAT+3)) = _gCBW[4+i]; // CSWtag
_reg_USBD_EP1_FDAT = 0; // data residue
_reg_USBD_EP1_FCTRL |= 0x20000000; // next is last word in packet
*((volatile U8 *)((U32)&_reg_USBD_EP1_FDAT+3)) = 0; // status: passed
quit = 1;
// SerialOutputString("File transfer completed.\n\r");
//printf("File transfer completed.\n\r");
break;
case 0x2A: // WRITE
// extract start sector
_gUsbCurSector = 0;
for (i=0; i<4; i++)
_gUsbCurSector = (_gUsbCurSector << 8) | (U32)_gCBW[17+i];
// extract number of sectors
_gUsbNumSector = (((U32)_gCBW[22]) << 8) | ((U32)_gCBW[23]);
/*
EUARTputData('(');
EUARTputHex((U8)(_gUsbCurSector>>8));
EUARTputHex((U8)_gUsbCurSector);
EUARTputData('/');
EUARTputHex((U8)_gUsbNumSector);
EUARTputData(')');
*/
_gUsbPacketCount = _gUsbNumSector * 16;
_gpUsbBufPtr = (unsigned char *)(USB_DISK_START + _gUsbCurSector * 512);
// check last sector
{
U32 lastSector = _gUsbCurSector + _gUsbNumSector - 1;
if (lastSector == DISK_LAST_SECTOR) // host is formatting disk
gLastSector = 54;
else if (lastSector > gLastSector)
gLastSector = lastSector;
}
// write sectors
writeSectors();
// SerialOutputString("0x2a\n\r");
break;
// default:
// SerialOutputString("Unknown command : 0x");
// EUARTputHex(_gCBW[15]);
// EUARTputString(" !\n");
}
// _reg_USBD_EP2_INTR_STAT |= EOT_MASK; // clear EOT flag
}
// This poll-only driver make use of the last 16M of the SDRAM (i.e. 0x0B000000 - 0x0BFFFFFF) to
// simulate a removable disk. The File Explorer on the Windows 2000 will see this 16M drive and copy
// a single file to it.
// The file will be stored starting from sector 55 and following consecutive sectors.
// The file size is estimated by the number of sectors written.
// There is one trip here: if the Windows 2000 File Explorer format this disk, their will be 2 cases:
// 1. a true format - write every sector of disk
// 2. a quick format - only FAT is written
// For case 1, we reset the variable gLastSector to 54 if sector 0x7FFF is written
// For case 2, we don't have to do anything since FAT is at sectors < 55.
#define SerialOutputString( str ) printf( (str) )
U32 usbrx( void )
{
USB_DISK_START=USBDISK_RAM_BASE;
DISK_LAST_SECTOR=USBDISK_RAM_LEN/512;
gLastSector = 54; // to make the return value 0, if no file is downloaded
formatDrive();
// SerialOutputString("USB drive end format disk.\n\r");
initUSB();
SerialOutputString("USB drive ready for transfer.\n\r");
SerialOutputString("step1: Connect usb line to your PC side, and in PC explore,\r\n you will see a removable disk,\r\n and then Copy file image under it.\n\rstep2. Eject the removable disk in PC explore\r\n");
quit = 0;
while (!quit)
{
// we need to clear USBD CFG_CHG interrupt flag, or else the module won't work after a
// CFG_CHG setup packet is received
_reg_USBD_INTR_STAT = 1;
// handle DEVREQ to EP0
if (_reg_USBD_EP0_INTR_STAT & DEVREQ_MASK)
{
// SerialOutputString("DEVREQ detected.\n\r");
handleDevReq();
}
// handle COMMAND send to EP2
if (_reg_USBD_EP2_INTR_STAT & EOT_MASK)
{
// SerialOutputString("EP2 EOT detected.\n\r");
processCommand();
}
// since there is a bug in the current silicon that the CMD_OVER is mistakenly cleared
// by control transfer of other addresses, so we'll set CMD_OVER bit repeatedly as
// a work-around
_reg_USBD_CTRL |= CMD_OVER_MASK; // signal CMD_OVER
}
return ((gLastSector - 54) * 512);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -