您的位置:首页 > 其它

AT89C5131实现U盘

2016-08-08 22:06 447 查看
初始化USB外设:

// created by perry.peng 2012/04/21
void
main (void)
{
LEDCON = 0xff;		// 10 mA current source.
CKCON0 |= 7;			// Set the system and the T0 working in X2 mode.
TMOD = 0x01; //
M10=0;
M00=1; 16bit-timer
TH0 = 0; // init values
TL0 = 0;
TF0 = 0; // reset interrupt flag (already done by hardware)
TR0 = 1; // timer0

run ms_multiple_drive = 0;

USBCON |= MSK_USBE; ///< Suspend USB Clock
PLLDIV = PLL_12MHz; ///< PLL clock source is 12MHz
PLLCON |= MSK_PLLEN; ///< enable PLL
USBCON &= ~MSK_SUSPCLK;
USBINT &= ~MSK_SPINT;
USBCON |= MSK_DETACH; /* Attach Command, Vref pin at high level. */

while (!TF0);
TF0 = 0;
TR0 = 0; /* timer0 stop */

P3 = 0;
USBCON &= ~MSK_DETACH; /* Attach Command, Vref pin at high level. */
USBIEN = MSK_ESPINT | MSK_EWUPCPU | MSK_EEORINT | MSK_ESOFINT;
IEN1 |= MSK_EUSB;
sei ();
Usb_ep_setup (EP_CTRL, EP_ENABLE | EP_TYPE_CONTROL | EP_DIR_OUT);
USBCON &= ~MSK_DETACH; /* Attach Command, Vref pin at high level. */
UsbConnected = TRUE;处理USB协议中的Setup包:

void Usb_setup_packet_handler (void)
{
#define D2H(x)                  ((x) << 8 | 0x80)	///< 设备到主机包
#define D2HX(x, n)              (((x) << 8) | (n))	///< 设备到主机包,子功能。
#define H2D(x)                  ((x) << 8)	///< 主机到设备包
#define H2DX(x, n)              (((x) << 8) | (n))	///< 主机到设备包,子功能

#define GDT(x)                  ((x) << 8)
#define GDTS(x, n)              (((x) << 8) | (n))

UEPNUM = EP_CTRL;		                  // select control endport.
if (!(UEPSTAX & MSK_RXSETUP))	        /* Check if a Setup packet is received. */
return;

cfgPacket.bytes[1] = UEPDATX;         //!< bmRequestType
cfgPacket.bytes[0] = UEPDATX;         //!< bRequest

/* SETUP packet:
bmRequestType   bRequest    wValue           wIndex    wLength
GET_DESCRIPTOR: 0x80            0x06        DType & DIndex   Lang ID   DLength    *D=Descriptor
GET_DESCRIPTOR: 0x80            0x06
*/
switch (cfgPacket.reqId) {
case D2H (GET_DESCRIPTOR):
cfgPacket.bytes[3] = UEPDATX; /* read LSB of wValue    */
cfgPacket.bytes[2] = UEPDATX; /* read MSB of wValue    */
cfgPacket.bytes[5] = UEPDATX; /* read LSB of wValue    */
cfgPacket.bytes[4] = UEPDATX; /* read MSB of wValue    */
cfgPacket.bytes[7] = UEPDATX; /* read LSB of wLength    */
cfgPacket.bytes[6] = UEPDATX; /* read MSB of wLength    */
switch (cfgPacket.R.wValue) {
case GDT(DEVICE_DESCRIPTOR):
TransferDataSize = DeviceDescriptor[0];	          //!< sizeof (DeviceDescriptor);
TransferDataPtr = &DeviceDescriptor[0];
break;
case GDT(CONFIGURATION_DESCRIPTOR):
TransferDataSize = ConfigurationDescriptor[2];	  //!< sizeof (ConfigurationDescriptor);
TransferDataPtr = &ConfigurationDescriptor[0];
break;
case GDTS(STRING_DESCRIPTOR, USB_STRING_LANG):
TransferDataSize = StringDescriptorLanguageID[0];	//!< sizeof (StringDescriptorLanguageID);
TransferDataPtr = &StringDescriptorLanguageID[0];
break;
case GDTS(STRING_DESCRIPTOR, USB_STRING_MANU):
TransferDataSize = StringDescriptorManuf[0];	    //!< sizeof (StringDescriptorManuf);
TransferDataPtr = &StringDescriptorManuf[0];
break;
case GDTS(STRING_DESCRIPTOR, USB_STRING_PROD):
TransferDataSize = StringDescriptorProduct[0];	  //!< sizeof (StringDescriptorProduct);
TransferDataPtr = &StringDescriptorProduct[0];
break;
case GDTS(STRING_DESCRIPTOR, USB_STRING_SN):
TransferDataSize = StringDescriptorSerialNumber[0];	//!< sizeof (StringDescriptorSerialNumber);
TransferDataPtr = &StringDescriptorSerialNumber[0];
break;
default:
UEPSTAX |= MSK_STALLRQ;
UEPSTAX &= ~MSK_RXSETUP;
return;
}

NeedZeroPacket = FALSE;			/* no zero length packet */
UEPSTAX &= ~MSK_RXSETUP;	                          //!< clear the receive setup flag
UEPSTAX |= MSK_DIR;		/* set out on EP0 */

if (cfgPacket.R.wLength > TransferDataSize) {
if ((TransferDataSize % EP_CONTROL_LENGTH) == 0)
NeedZeroPacket = TRUE;
else
NeedZeroPacket = FALSE;                       //!< no need of zero length packet
} else {
TransferDataSize = (uint8_t) cfgPacket.R.wLength;	//!< send only requested number of data
}

while ((TransferDataSize != 0) && (!(UEPSTAX & MSK_RXOUTB0B1))) {
uint8_t c;			// New
if (TransferDataSize > EP_CONTROL_LENGTH)
c = EP_CONTROL_LENGTH;
else
c = TransferDataSize;
TransferDataSize -= c;
while (c != 0) {
UEPDATX = *TransferDataPtr;
TransferDataPtr++;
c--;
}
UEPSTAX |= MSK_TXRDY;
while ((!(UEPSTAX & MSK_TXCMPL)) && (!(UEPSTAX & MSK_RXOUTB0B1)));
UEPSTAX &= ~MSK_TXCMPL;
}

if (UEPSTAX & MSK_RXOUTB0B1) {	//!< abort from Host
UEPSTAX &= ~MSK_RXOUT;
return;
}

if (NeedZeroPacket == TRUE) {
UEPSTAX |= MSK_TXRDY;
while ((!(UEPSTAX & MSK_TXCMPL)) && (!(UEPSTAX & MSK_RXOUTB0B1)));
UEPSTAX &= ~MSK_TXCMPL;
}

while (!(UEPSTAX & MSK_RXOUTB0B1));
UEPSTAX &= ~MSK_RXOUT;
break;
case D2H (GET_CONFIGURATION):
UEPSTAX &= ~MSK_RXSETUP;
UEPSTAX |= MSK_DIR;	/* set out on EP0 */
UEPDATX = UsbCurrentConfig;
UEPSTAX |= MSK_TXRDY;
while (!UEPSTAX & MSK_TXCMPL);
UEPSTAX &= ~MSK_TXCMPL;
while (!UEPSTAX & MSK_RXOUTB0B1);
UEPSTAX &= ~MSK_RXOUT;
break;
case H2D (SET_ADDRESS):
UEPSTAX &= ~MSK_RXSETUP;
UEPSTAX |= MSK_TXRDY;	//!< send a ZLP for STATUS phase
while (!(UEPSTAX & MSK_TXCMPL));	//!< waits for status phase done
//!< before using the new address
UEPSTAX &= ~MSK_TXCMPL;	// for Tiger compatibility
USBADDR &= ~MSK_FEN;
USBADDR = cfgPacket.bytes[2];
USBADDR |= MSK_FEN;
break;
case H2D (SET_CONFIGURATION):
cfgPacket.bytes[3] = UEPDATX;
cfgPacket.bytes[2] = UEPDATX;
if (cfgPacket.bytes[3] > NB_CONFIGURATIONS) {
UEPSTAX |= MSK_STALLRQ;
UEPSTAX &= ~MSK_RXSETUP;
break;
}

UEPSTAX &= ~MSK_RXSETUP;
UsbCurrentConfig = cfgPacket.bytes[3];

UEPSTAX |= MSK_TXRDY;	//!< send a ZLP for STATUS phase
while (!UEPSTAX & MSK_TXCMPL);
UEPSTAX &= ~MSK_TXCMPL;

Usb_ep_setup (EP_MS_IN, EP_ENABLE | EP_TYPE_BULK | EP_DIR_IN);
Usb_ep_setup (EP_MS_OUT, EP_ENABLE | EP_TYPE_BULK | EP_DIR_OUT);
break;
case H2DX (SET_FEATURE, ENDPOINT_TYPE):
cfgPacket.bytes[3] = UEPDATX;
cfgPacket.bytes[2] = UEPDATX;
cfgPacket.bytes[5] = UEPDATX;
cfgPacket.bytes[4] = UEPDATX;
if (cfgPacket.R.wValue == FEATURE_ENDPOINT_HALT) {
uint8_t wIndex;
wIndex = cfgPacket.R.wIndex & EP_DIR;

UEPNUM = wIndex;
if (wIndex != EP_CTRL && UEPCONX & MSK_EPEN) {
UEPSTAX |= MSK_STALLRQ;
UEPNUM = EP_CTRL;
endpoint_status[wIndex] = 0x01;
UEPSTAX &= ~MSK_RXSETUP;
UEPSTAX |= MSK_TXRDY;
break;
}
}
UEPSTAX |= MSK_STALLRQ;
UEPSTAX &= ~MSK_RXSETUP;
break;
case D2HX (GET_STATUS, REQUEST_DEVICE_STATUS):
UEPSTAX &= ~MSK_RXSETUP;
UEPSTAX |= MSK_DIR;
UEPDATX = DEVICE_STATUS;
UEPDATX = 0x00;
UEPSTAX |= MSK_TXRDY;
while (!UEPSTAX & MSK_TXCMPL);
UEPSTAX &= ~MSK_TXCMPL;
while (!UEPSTAX & MSK_RXOUTB0B1);
UEPSTAX &= ~MSK_RXOUT;
break;
case D2HX (GET_STATUS, REQUEST_INTERFACE_STATUS):
UEPSTAX &= ~MSK_RXSETUP;
UEPSTAX |= MSK_DIR;
UEPDATX = INTERFACE_STATUS;
UEPDATX = 0x00;
UEPSTAX |= MSK_TXRDY;
while (!UEPSTAX & MSK_TXCMPL);
UEPSTAX &= ~MSK_TXCMPL;
while (!UEPSTAX & MSK_RXOUTB0B1);
UEPSTAX &= ~MSK_RXOUT;
break;
case D2HX (GET_STATUS, REQUEST_ENDPOINT_STATUS):
cfgPacket.bytes[3] = UEPDATX;
cfgPacket.bytes[2] = UEPDATX;
cfgPacket.bytes[5] = UEPDATX;
cfgPacket.bytes[4] = UEPDATX;
UEPSTAX &= ~MSK_RXSETUP;
UEPSTAX |= MSK_DIR;
UEPDATX = endpoint_status[cfgPacket.R.wIndex & EP_DIR];
UEPDATX = 0x00;
UEPSTAX |= MSK_TXRDY;
while (!UEPSTAX & MSK_TXCMPL);
UEPSTAX &= ~MSK_TXCMPL;
while (!UEPSTAX & MSK_RXOUTB0B1);
UEPSTAX &= ~MSK_RXOUT;
break;
case H2DX (CLEAR_FEATURE, ENDPOINT_TYPE):
cfgPacket.bytes[3] = UEPDATX;
cfgPacket.bytes[2] = UEPDATX;
cfgPacket.bytes[5] = UEPDATX;
cfgPacket.bytes[4] = UEPDATX;

if (cfgPacket.R.wValue == FEATURE_ENDPOINT_HALT) {
cfgPacket.R.wIndex &= EP_DIR;

UEPNUM = cfgPacket.R.wIndex;
if (UEPCONX & MSK_EPEN) {
if (cfgPacket.R.wIndex != EP_CTRL) {
UEPSTAX &= ~MSK_STALLRQ;
UEPRST = 1 << (uint8_t) cfgPacket.R.wIndex;
UEPRST = 0;
}
UEPNUM = EP_CTRL;
endpoint_status[cfgPacket.R.wIndex] = 0x00;
UEPSTAX &= ~MSK_RXSETUP;
UEPSTAX |= MSK_TXRDY;
break;
}
}
UEPSTAX |= MSK_STALLRQ;
UEPSTAX &= ~MSK_RXSETUP;
break;
//case D2H (MASS_STORAGE_RESET):
case H2D (MASS_STORAGE_RESET):
UEPSTAX &= ~MSK_RXSETUP;
UEPSTAX |= MSK_TXRDY;
break;
//case D2H (GET_MAX_LUN):
case H2D (GET_MAX_LUN):
UEPSTAX &= ~MSK_RXSETUP;
UEPSTAX |= MSK_DIR;	/* set out on EP0 */
UEPDATX = MAX_LUN - 1;
UEPSTAX |= MSK_TXRDY;
while (!UEPSTAX & MSK_TXCMPL);
UEPSTAX &= ~MSK_TXCMPL;
ms_multiple_drive = 1;
break;
case H2D (SET_DESCRIPTOR):
case H2D (SET_INTERFACE):
case H2DX (SET_FEATURE, ZERO_TYPE):
case H2DX (SET_FEATURE, INTERFACE_TYPE):
case H2DX (CLEAR_FEATURE, ZERO_TYPE):
case H2DX (CLEAR_FEATURE, INTERFACE_TYPE):
case D2H (SYNCH_FRAME):
case D2H (GET_INTERFACE):
default:
UEPSTAX |= MSK_STALLRQ;
UEPSTAX &= ~MSK_RXSETUP;
break;
}
}


定义一堆USB协议中定义的描述符:

//! Usb Device Descriptor
static const uint8_t const __code DeviceDescriptor[] = {
/* bLength = */           0x12,                         //!< Size of this descriptor in bytes
/* bDescriptorType = */   DEVICE_DESCRIPTOR,   	        //!< DEVICE descriptor type
/* bscUSB = */            0x02,                	        //!< Binay Coded Decimal Spec. release
0x00,
/* bDeviceClass = */		  0x00,                         //!< Class code assigned by the USB
/* bDeviceSubClass = */	  0x00,                         //!< Sub-class code assigned by the USB
/* bDeviceProtocol = */	  0x00,                         //!< Protocol code assigned by the USB
/* bMaxPacketSize0 = */	  EP_CONTROL_LENGTH,            //!< Max packet size for EP0
/* idVender = */          0x03,                         //!< ??ID?,ATMEL?ID?0xeb03,??????,??????*/
0xeb,
/* idProduct = */         0x13,                         //!< ??ID?,HID??0x2013, ??????,??????*/
0x20,
/* bcdDevice = */         0x00,                         //!< ????USB??????,???1.0??,?0x0100?*/
0x01,
/* iManufacturer = */     USB_STRING_MANU,              //!< ?????????,?????????,???????1????*/
/* iProduct = */          USB_STRING_PROD,              //!< ??????????????1,????2???????????????????*/
/* iSerialNumber = */     USB_STRING_SN,                //!< ????????????????3?????*/
/* bNumConfigurations=*/  0x01                          //!< ???????????????????????,???????1?*/
};

//! Usb Device Descriptor
__code uint8_t DeviceQualifierDescriptor[] = {
/* bLength = */           0x0a,                         //!< Size of this descriptor in bytes
/* bDescriptorType = */   DEVICE_QUALIFIER_DESCRIPTOR,  //!< DEVICEQUALIFIER descriptor type
/* bscUSB = */		        0x02,                         //!< Binay Coded Decimal Spec. release
0x00,
/* bDeviceClass = */		  0x00,                         //!< Class code assigned by the USB
/* bDeviceSubClass = */	  0x00,                         //!< Sub-class code assigned by the USB
/* bDeviceProtocol = */	  0x00,                         //!< Protocol code assigned by the USB
/* bMaxPacketSize0 = */	  EP_CONTROL_LENGTH,            //!< Max packet size for EP0
/* bNumConfigurations = */0x01,                         //!< Number of possible configurations
/* bReserved = */		      0x00                          //!< Reserved for future use, must be zero
};

//! Configuration Descriptor
__code uint8_t ConfigurationDescriptor[] = {
/* bLength = */		        0x09,                         //!< size of this descriptor in bytes
/* bDescriptorType = */	  CONFIGURATION_DESCRIPTOR,     //!< CONFIGURATION descriptor type
/* wTotalLength = */	    (0x09+0x09+0x07+0x07),        //!< total length of data returned
0x00,
/* bNumInterfaces = */	  0x01,                         //!< number of interfaces for this conf.
/* bConfigurationValue = */0x01,                        //!< value for SetConfiguration resquest
/* iConfiguration = */	  0x00,                         //!< index of string descriptor
/* bmAttibutes = */		    USB_CONFIG_BUSPOWERED,      	//!< Configuration characteristics
/* MaxPower = */		      50,                           //!< 50 = 100mA, maximum power consumption

/* bLength = */		        0x09,                         //!< size of this descriptor in bytes
/* bDescriptorType = */	  INTERFACE_DESCRIPTOR,         //!< INTERFACE descriptor type
/* bInterfaceNumber = */	0x00,                         //!< Number of interface
/* bAlternateSetting = */	0x00,                         //!< value to select alternate setting
/* bNumEndpoints = */	    0x02,                         //!< Number of EP except EP 0
/* bInterfaceClass = */	  0x08,                         //!< 0x08 = Mass Storage, Class code assigned by the USB
/* bInterfaceSubClass = */0x06,                         //!< 0x06 = SCSI transparent Cammand Set, Sub-class code assigned by the USB
/* bInterfaceProtocol = */0x50,                         //!< 0x50 = Bulk-Only Transport, Protocol code assigned by the USB
/* iInterface = */		    0x00,                         //!< Index of string descriptor

/* bLength = */		        0x07,                         //!< size of this descriptor in bytes
/* bDescriptorType = */	  ENDPOINT_DESCRIPTOR,          //!< ENDPOINT descriptor type
/* bEndpointAddress = */	(EP_MS_IN | 0x80),            //!< Address of the endpoint
/* bmAttributes = */		  EP_TYPE_BULK,                 //!< Endpoint's attributes
/* wMaxPacketSize = */	  64,                           //!< Maximum packet size for this EP
0x00,
/* bInterval = */		      0x00,                         //!< Interval for polling EP in ms

/* bLength = */		        0x07,                         //!< size of this descriptor in bytes
/* bDescriptorType = */	  ENDPOINT_DESCRIPTOR,          //!< ENDPOINT descriptor type
/* bEndpointAddress = */	EP_MS_OUT,                    //!< Address of the endpoint
/* bmAttributes = */		  EP_TYPE_BULK,                 //!< Endpoint's attributes
/* wMaxPacketSize = */	  64,                           //!< Maximum packet size for this EP
0x00,
/* bInterval = */		      0x00                          //!< Interval for polling EP in ms
};

// StringDescriptor LanguageID
__code uint8_t StringDescriptorLanguageID[] = {
/* bLength = */		        0x04,                         //!< size of this descriptor in bytes
/* bDescriptorType = */   STRING_DESCRIPTOR,            //!< STRING_DESCRIPTOR descriptor type
/* wLanguageID = */       0x09,                         //!< wLanguageID = 0x0409
0x04
};

// StringDescriptor Manufacture
__code uint8_t StringDescriptorManuf[] = {
/* bLength = */		        24,                           //!< size of this descriptor in bytes
/* bDescriptorType = */   STRING_DESCRIPTOR,            //!< STRING_DESCRIPTOR descriptor type
WCHAR('F'),
WCHAR('l'),
WCHAR('e'),
WCHAR('x'),
WCHAR('t'),
WCHAR('r'),
WCHAR('o'),
WCHAR('n'),
WCHAR('i'),
WCHAR('c'),
WCHAR('s') };

// StringDescriptor Product
__code uint8_t StringDescriptorProduct[] = {
/* bLength = */		        14,                           //!< size of this descriptor in bytes
/* bDescriptorType = */   STRING_DESCRIPTOR,            //!< STRING_DESCRIPTOR descriptor type
WCHAR('U'),
WCHAR('S'),
WCHAR('B'),
WCHAR('D'),
WCHAR('i'),
WCHAR('s'),
WCHAR('k') };

// StringDescriptor SerialNumber, Serial Number should be at least 12 characters long
__code uint8_t StringDescriptorSerialNumber[] = {
/* bLength = */		        16,                           //!< size of this descriptor in bytes
/* bDescriptorType = */   STRING_DESCRIPTOR,            //!< STRING_DESCRIPTOR descriptor type
WCHAR('2'),
WCHAR('A'),
WCHAR('S'),
WCHAR('4'),
WCHAR('2'),
WCHAR('5'),
WCHAR('6') };


处理CBW和CSW:

void usb_mass_storage_cbw (void)
{
__bit cbw_error;
uint8_t c;

cbw_error = FALSE;
UEPNUM = EP_MS_OUT;		//! check if dCBWSignature is correct
if (0x55 != UEPDATX) cbw_error = TRUE; //! 'U'
if (0x53 != UEPDATX) cbw_error = TRUE; //! 'S'
if (0x42 != UEPDATX) cbw_error = TRUE; //! 'B'
if (0x43 != UEPDATX) cbw_error = TRUE; //! 'C'

dCBWTag[0] = UEPDATX;		//! Store CBW Tag to be repeated in CSW
dCBWTag[1] = UEPDATX;
dCBWTag[2] = UEPDATX;
dCBWTag[3] = UEPDATX;

((uint8_t *) & g_scsi_data_remaining)[3] = UEPDATX;
((uint8_t *) & g_scsi_data_remaining)[2] = UEPDATX;
((uint8_t *) & g_scsi_data_remaining)[1] = UEPDATX;
((uint8_t *) & g_scsi_data_remaining)[0] = UEPDATX;

if (UEPDATX != 0x00) {
ms_data_direction = 1;
if (cbw_error) {
Usb_ack_receive_out_ms ();
UEPNUM = EP_MS_IN;
UEPSTAX |= MSK_STALLRQ;
return;
}
} else {
ms_data_direction = 0;
if (cbw_error) {
UEPSTAX |= MSK_STALLRQ;
Usb_ack_receive_out_ms ();
return;
}
}

usb_LUN = UEPDATX;

if (!ms_multiple_drive) {
usb_LUN = 0;
}

ACC = UEPDATX;		//! dummy CBWCBLength read

for (c = 0; c < 16; c++)	// store scsi_command
{
g_scsi_command[c] = UEPDATX;
}

Usb_ack_receive_out_ms ();

if (ms_data_direction == 1) {
UEPNUM = EP_MS_IN;
}

if (TRUE != scsi_decode_command ()) {
if (g_scsi_data_remaining != 0) {
UEPSTAX |= MSK_STALLRQ;
}
}
}

void usb_mass_storage_csw (void)
{
UEPNUM = EP_MS_IN;
while (UEPSTAX & MSK_STALLRQ) {
Usb_setup_packet_handler ();
UEPNUM = EP_MS_IN;
}

UEPNUM = EP_MS_OUT;
while (UEPSTAX & MSK_STALLRQ) {
Usb_setup_packet_handler ();
UEPNUM = EP_MS_OUT;
}
UEPNUM = EP_MS_IN;
//! write CSW Signature
Usb_write_byte (0x55);	//! 'U'
Usb_write_byte (0x53);	//! 'S'
Usb_write_byte (0x42);	//! 'B'
Usb_write_byte (0x53);	//! 'S'
//! write stored CBW Tag
Usb_write_byte (dCBWTag[0]);
Usb_write_byte (dCBWTag[1]);
Usb_write_byte (dCBWTag[2]);
Usb_write_byte (dCBWTag[3]);
//! write data residue value
Usb_write_byte (((uint8_t *) & g_scsi_data_remaining)[3]);
Usb_write_byte (((uint8_t *) & g_scsi_data_remaining)[2]);
Usb_write_byte (((uint8_t *) & g_scsi_data_remaining)[1]);
Usb_write_byte (((uint8_t *) & g_scsi_data_remaining)[0]);

//! write command status
Usb_write_byte (g_scsi_status);	//! 0 -> PASS, 1 -> FAIL
Usb_send_in ();
}


LEDCON = 0xff;		// 10 mA current source.
CKCON0 |= 7;			// Set the system and the T0 working in X2 mode.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: