📄 usb-pxa250.c
字号:
/* * $Id: usb-pxa250.c,v 1.10 2003/09/24 12:13:35 jfabo Exp $ * * Copyright (C) 2002, 2003 ETC s.r.o. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. * * Written by Daniel Samek <dano@etc.sk>, 2002. * Juraj Fabo <vinco@etc.sk>, 2003. * */#include <.config.h>#include "board.h"#if CPU == PXA250#include <_windows.h>#include "download.h"#include "format.h"#if defined(USB_VID) && defined(USB_PID)#include <pxa2x0/gpio.h>#include <pxa2x0/udc.h>#include <pxa2x0/pmrc.h>#include "except.h"#include "usb.h"#include "splash.h"#define UDCCR_FLAGS (UDCCR_RSTIR | UDCCR_SUSIR | UDCCR_RESIR | UDCCR_RSM)#define UDCCR_SET(x) UDCCR = (UDCCR & (~UDCCR_FLAGS)) | x#define UDCCR_CLEAR(x) UDCCR = UDCCR & (~(UDCCR_FLAGS | x))#define UDCCS0_FLAGS (UDCCS0_OPR | UDCCS0_IPR | UDCCS0_SST | UDCCS0_FST | UDCCS0_SA)#define UDCCS0_SET(x) UDCCS0 = (UDCCS0 & (~UDCCS0_FLAGS)) | x#define UDCCS1_FLAGS (UDCCS1_TPC | UDCCS1_FTF | UDCCS1_TUR | UDCCS1_SST | UDCCS1_TSP)#define UDCCS1_SET(x) UDCCS1 = (UDCCS1 & (~UDCCS1_FLAGS)) | x#define UDCCS2_FLAGS (UDCCS2_RPC | UDCCS2_SST)#define UDCCS2_SET(x) UDCCS2 = (UDCCS2 & (~UDCCS2_FLAGS)) | x#define UDCCS2_CLEAR(x) UDCCS2 = UDCCS2 & (~(UDCCS2_FLAGS | x))#define SETUP_MAXPACKET 8#define EP0_MAXPACKET 16#define EP1_MAXPACKET 64#define EP2_MAXPACKET 64static const struct usb_dev_desc wep_dev_desc = { 18, /* length */ 1, /* descriptortype */ 0x0110, /* usb */ -1, /* deviceclass */ -1, /* devicesubclass */ -1, /* deviceprotocol */ EP0_MAXPACKET, /* maxpacketsize */ USB_VID, /* idvendor */ USB_PID, /* idproduct */ 0, /* device */ 0, /* manufacturer */ 0, /* product */ 0, /* serialnumber */ 1, /* numconfigurations */};static const struct usb_conf_desc wep_conf_desc = { { 9, /* length */ 2, /* descriptortype (CONFIGURATION) */ 32, /* total length */ 1, /* numinterfaces */ 1, /* configurationvalue */ 0, /* configuration */ -64, /* attributes */ 0, /* maxpower */ } , { 9, /* length */ 4, /* descriptortype (INTERFACE) */ 0, /* interfacenumber */ 0, /* alternatesetting */ 2, /* numendpoints */ -1, /* interfaceclass */ -1, /* interfacesubclass */ -1, /* interfaceprotocol */ 0, /* interface */ } , { 7, /* length */ 5, /* descriptortype (ENDPOINT) */ -127, /* endpointaddress (ep1, in) */ 0x02, /* attributes (0010 = bulk) */ EP1_MAXPACKET, /* maxpacketsize */ 0, /* interval (ignored for bulk) */ } , { 7, /* length */ 5, /* descriptortype (ENDPOINT) */ 0x02, /* endpointaddress (ep2, out) */ 0x02, /* attributes (0010 = bulk) */ EP2_MAXPACKET, /* maxpacketsize */ 0, /* interval (ignored for bulk) */ }};#define EP0_IDLE 1#define EP0_IN_DATA_PHASE 2#define EP0_WAIT_XFER 3#define EP0_END_XFER 4static int status;static int index;static int length;static unsigned char *packet;static int get_descriptor_flag;static int usb_ready;static intusbcable_wait( void ){ int i, in; uint32_t timeout = 0; EdbgOutputDebugString( "* Please connect USB cable between PC and wep.\n" ); for (i = 9, in = 0; i && !in; i--) { EdbgOutputDebugString( "%d\r", i ); for (timeout = 0x200000; timeout; timeout--) if (GPLR0 & GPIO0_GP11) { in = 1; break; } } return timeout ? 1 : 0;}static intusbcable_in( void ){ if (GPLR0 & GPIO0_GP11) return 1; UDCCR_CLEAR( UDCCR_UDE ); /* disable UDC */ /* high speed usb device disable */ GPDR2 &= ~GPIO2_GP79; return 0;}static intget_descriptor( struct usb_dev_req *req ){ switch (req->value_hi) { case 1: /* device descriptor */ length = sizeof (struct usb_dev_desc); if (req->length < length) { EdbgOutputDebugString( "device decriptor is short: %d\n", req->length ); return 0; } index = 0; packet = (unsigned char *) &wep_dev_desc; return 1; case 2: /* configuration descriptor */ length = sizeof (struct usb_conf_desc); if (req->length < length) length = req->length; index = 0; packet = (unsigned char *) &wep_conf_desc; return 1; default: EdbgOutputDebugString( "unknown descriptor: %d\n", req->value_hi ); return 0; }}static intset_configuration( void ){ UICR0 &= ~UICR0_IM2; /* enable ep2 interrupt */ UDCCS2_CLEAR( UDCCS2_DME ); usb_ready = 1; return 1;}static intstandard_request( struct usb_dev_req *req ){ switch (req->request) { case 6: /* get descriptor */ get_descriptor_flag = get_descriptor( req ); return get_descriptor_flag; case 9: /* set configuration */ return set_configuration(); default: EdbgOutputDebugString( "unknown standard request: %d\n", req->request ); return 0; }}static intclass_request( struct usb_dev_req *req ){ switch (req->request) { case 34: /* set control line state */ index = length = 0; return 1; default: EdbgOutputDebugString( "unknown class request: %d\n", req->request ); return 0; }}static intparse_command( struct usb_dev_req *req ){ unsigned char req_type; req_type = (unsigned char) req->m_request; req_type >>= 5; req_type &= 0x3; switch (req_type) { case 0: /* standard request */ return standard_request( req ); case 1: /* class request */ return class_request( req ); default: EdbgOutputDebugString( "unknown request type: 0x%X\n", req->m_request ); return 0; }}static intep0_idle( void ){ unsigned char out_packet[SETUP_MAXPACKET] ; int setup_command_valid; int i; index = -1; if (!((UDCCS0 & UDCCS0_SA) && (UDCCS0 & UDCCS0_OPR))) { EdbgOutputDebugString( "SA & OPR not set: UDCCS0: 0x%X\n", UDCCS0 ); return 0; } if (UDCCS0 & UDCCS0_RNE) { for (i = 0; (i < SETUP_MAXPACKET) && (UDCCS0 & UDCCS0_RNE); i++) out_packet[i] = (unsigned char) UDDR0; if (i < SETUP_MAXPACKET) { EdbgOutputDebugString( "short out packet: %d\n", i ); return 0; } } else /* errata 131 */ for (i = 0; i < SETUP_MAXPACKET; i++) out_packet[i] = (unsigned char) UDDR0; setup_command_valid = parse_command( (struct usb_dev_req *) out_packet ); if (index != -1) { /* no data */ for (i = 0; (i < EP0_MAXPACKET) && (index < length); i++, index++) UDDR0 = (unsigned char) packet[index]; status = EP0_IN_DATA_PHASE; } UDCCS0_SET( UDCCS0_SA | UDCCS0_OPR ); if (!setup_command_valid) { status = EP0_IDLE; get_descriptor_flag = 0; /* stall */ UDCCS0_SET( UDCCS0_FST ); while (!(UDCCS0 & UDCCS0_SST)) ; UDCCS0_SET( UDCCS0_SST ); return 1; } if (index == -1) /* no data */ return 1; if (i < EP0_MAXPACKET) { status = EP0_END_XFER; get_descriptor_flag = 0; UDCCS0_SET( UDCCS0_IPR ); return 1; } if (index == length) { status = EP0_WAIT_XFER; get_descriptor_flag = 0; UDCCS0_SET( UDCCS0_IPR ); } return 1;}static intep0_in_data_phase( void ){ int i; if (get_descriptor_flag && (UDCCS0 & UDCCS0_OPR) && (!(UDCCS0 & UDCCS0_SA))) { /* premature status stage */ UDCCS0_SET( UDCCS0_OPR ); status = EP0_IDLE; get_descriptor_flag = 0; UDCCS0_SET( UDCCS0_FTF ); return 1; } if (index == length) { EdbgOutputDebugString( "no data\n" ); return 0; } for (i = 0; (i < EP0_MAXPACKET) && (index < length); i++, index++) UDDR0 = (unsigned char) packet[index]; if (i < EP0_MAXPACKET) { status = EP0_END_XFER; get_descriptor_flag = 0; UDCCS0_SET( UDCCS0_IPR ); return 1; } if (index == length) { status = EP0_WAIT_XFER; get_descriptor_flag = 0; UDCCS0_SET( UDCCS0_IPR ); } return 1;}static intep0_wait_xfer(){ UDCCS0_SET( UDCCS0_IPR ); status = EP0_END_XFER; return 1;}static intep0_end_xfer(){ if ((UDCCS0 & UDCCS0_OPR) && (!(UDCCS0 & UDCCS0_SA))) { UDCCS0_SET( UDCCS0_OPR ); status = EP0_IDLE; get_descriptor_flag = 0; } return 1;}static voidep0_intr( void ){ int retval = 0; while (!retval) { /* new setup command */ if ((UDCCS0 & UDCCS0_SA) && (UDCCS0 & UDCCS0_OPR)) { status = EP0_IDLE; get_descriptor_flag = 0; } switch (status) { case EP0_IDLE: retval = ep0_idle(); break; case EP0_IN_DATA_PHASE: retval = ep0_in_data_phase(); break; case EP0_WAIT_XFER: retval = ep0_wait_xfer(); break; case EP0_END_XFER: retval = ep0_end_xfer(); break; default: EdbgOutputDebugString( "unknown status: %d\n", status ); } } USIR0 = USIR0_IR0;}static intusb_init( void ){ status = EP0_IDLE; get_descriptor_flag = 0; usb_ready = 0; UDCCR_SET( UDCCR_UDE ); /* enable UDC */#ifdef CONFIG_EP250_B1_B2 /* FIXME: turn off double buffer for ep0 and ep1 (intel driver) */ ((volatile uint32_t *) UDC_pointer)[1] &= ~0x06;#endif if (UDCCR & UDCCR_UDA) UICR0 &= ~UICR0_IM0; /* enable ep0 interrupt */ else UDCCR_SET( UDCCR_RSTIR ); /* high speed usb device enable */ GPSR2 = GPIO2_GP79; GPDR2 |= GPIO2_GP79; while (!usb_ready) { if (!usbcable_in()) break; if (UDCCR & UDCCR_RSTIR) { /* reset */ UDCCR_SET( UDCCR_RSTIR ); if (UDCCR & UDCCR_UDA) { UICR0 &= ~UICR0_IM0; /* enable ep0 interrupt */ status = EP0_IDLE; get_descriptor_flag = 0; } continue; } /* endpoint 0 */ if ((!(UICR0 & UICR0_IM0)) && (USIR0 & USIR0_IR0)) ep0_intr(); } return usb_ready;}static voidusb_write_maxpack( char *buff){ uint32_t timeout; int i = 0; if (!usb_ready) Throw E_USBUNINITIALIZED; /* process control command */ while (USIR0 & USIR0_IR0) ep0_intr(); /* copy data from buffer to FIFO */ for (i = 0; i < EP1_MAXPACKET; i++) { UDDR1 = buff[i] & 0xFF; } if (i < EP1_MAXPACKET) UDCCS1_SET( UDCCS1_TSP | UDCCS1_TPC ); else UDCCS1_SET( UDCCS1_TPC ); UICR0 &= ~UICR0_IM1; /* enable ep1 interrupt */ for (timeout = 0x200000; timeout; timeout--) if (USIR0 & USIR0_IR1) break; UICR0 |= UICR0_IM1; /* disable ep1 interrupt */ USIR0 = USIR0_IR1; /* clear ep1 interrupt */ if (!timeout) Throw E_WRITETIMEOUT;}static voidusb_write_terminate(){ uint32_t timeout; if (!usb_ready) Throw E_USBUNINITIALIZED; /* process control command */ while (USIR0 & USIR0_IR0) ep0_intr(); UDCCS1_SET( UDCCS1_TSP ); UDCCS1_SET( UDCCS1_TPC ); UICR0 &= ~UICR0_IM1; /* enable ep1 interrupt */ for (timeout = 0x200000; timeout; timeout--) if (USIR0 & USIR0_IR1) break; UICR0 |= UICR0_IM1; /* disable ep1 interrupt */ USIR0 = USIR0_IR1; /* clear ep1 interrupt */ if (!timeout) Throw E_WRITETIMEOUT; }static voidusb_writechar( char c ){ uint32_t timeout; if (!usb_ready) Throw E_USBUNINITIALIZED; /* process control command */ while (USIR0 & USIR0_IR0) ep0_intr(); UDDR1 = c & 0xFF; UDCCS1_SET( UDCCS1_TSP ); UDCCS1_SET( UDCCS1_TPC ); UICR0 &= ~UICR0_IM1; /* enable ep1 interrupt */ for (timeout = 0x200000; timeout; timeout--) if (USIR0 & USIR0_IR1) break; UICR0 |= UICR0_IM1; /* disable ep1 interrupt */ USIR0 = USIR0_IR1; /* clear ep1 interrupt */ if (!timeout) Throw E_WRITETIMEOUT;}#define MIN(a,b) (a < b) ? a : bstatic charusb_read( unsigned char *buff, int len ){ static int buffer_index = 0, fifo_top = 0; static unsigned char buffer[EP2_MAXPACKET]; uint32_t timeout; int minimum; minimum = MIN(buffer_index, len); if (buffer_index) { memcpy(buff, buffer + fifo_top - buffer_index, minimum); } len -= minimum; buffer_index -= minimum; if (!len) { return 1; } if (!usb_ready) Throw E_USBUNINITIALIZED; while (len) { for (timeout = 0x200000; timeout; timeout--) if ((USIR0 & USIR0_IR2) && (UDCCS2 & UDCCS2_RNE)) break; if (!timeout) { Throw E_READTIMEOUT; } while (UDCCS2 & UDCCS2_RNE) { buffer[buffer_index++] = (char) (UDDR2 & 0xFF); } fifo_top = buffer_index; if (!(UDCCS2 & UDCCS2_RNE)) { UDCCS2_SET( UDCCS2_RPC ); USIR0 = USIR0_IR2; } buff += minimum; minimum = MIN(buffer_index, len); if (buffer_index) { memcpy(buff, buffer + fifo_top - buffer_index, minimum); } len -= minimum; buffer_index -= minimum; } return 1;}int USB_upload( void ){ unsigned int i, upload_start = 0, upload_end = 0; unsigned int size = 0;#ifdef CONFIG_SPLASH_SCREEN unsigned char progress_percentage = 0; uint32_t total_len = 0;#endif int e; /* exception */ Try { usb_read(&((unsigned char)(upload_start)), 4); usb_read(&((unsigned char)(size)), 4); upload_end = upload_start + size; } Catch(e) { EdbgOutputDebugString("exception %d",e); } EdbgOutputDebugString("\nSynchronized, starting data transfer from: 0x%x to 0x%x\n", upload_start, upload_end); upload_start += MEM_VIRT_FLASH; upload_end += MEM_VIRT_FLASH; i = upload_start; while (i < upload_end) { Try { for (i = upload_start; i < upload_end; i += 64 ) { usb_write_maxpack((char *)(i));#ifdef CONFIG_SPLASH_SCREEN total_len += 64; if (((total_len * 100 )/size ) > progress_percentage ){ progress_percentage = (unsigned char)((total_len * 100 )/ size ); progress_bar(progress_percentage, 1); }#endif } } Catch(e) { EdbgOutputDebugString("exception %d\n",e); } }#ifdef CONFIG_EP250_C0_A0 usb_write_terminate();#endif usb_write_terminate();#ifdef CONFIG_SPLASH_SCREEN progress_bar(100, 1);#endif return -2;} intUSB_download( struct imginfo *img ){ int i; int e; /* exception */ struct fntable fn = { usb_writechar, usb_read }; int retval = -2; int upload = 0; /* init usb hw connection. See: 12.4 UDC Hardware Connection */ GPDR0 &= ~GPIO0_GP11; GPDR2 &= ~GPIO2_GP79; EdbgOutputDebugString( "Ready to download image via USB\n" ); if (!usbcable_wait() || !usb_init()) return retval; EdbgOutputDebugString( "\nUSB ready.\n" ); for (i = 0; i < 10; i++) { EdbgOutputDebugString( "." ); Try { download( &fn, img, 0 ); retval = 0; } Catch(e) { if (e == E_UPLOADREQUEST) { i = 10; upload = retval = 1; } else continue; }; if (upload) { USB_upload(); } UDCCR_CLEAR( UDCCR_UDE ); /* disable UDC */ /* high speed usb device disable */ GPDR2 &= ~GPIO2_GP79; return retval; } EdbgOutputDebugString( "\nFail to synchonize with the host\n" ); UDCCR_CLEAR( UDCCR_UDE ); /* disable UDC */ /* high speed usb device disable */ GPDR2 &= ~GPIO2_GP79; return retval;}#else /* defined(USB_VID) && defined(USB_PID) */intUSB_download( struct imginfo *img ){ UNREFERENCED_PARAMETER( img ); return -2;}#endif /* defined(USB_VID) && defined(USB_PID) */#endif /* CPU == PXA250 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -