📄 usb-sa1110.c
字号:
/* * $Id: usb-sa1110.c,v 1.2 2003/09/17 12:20:42 jfabo Exp $ * * Copyright (C) 2001, 2002 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 Marcel Telka <marcel@telka.sk>, 2001, 2002. * */#include "board.h"#if CPU == SA1110#include <_windows.h>#include <sa11x0/gpio.h>#include <sa11x0/udc.h>#include "download.h"#include "format.h"#if defined(USB_VID) && defined(USB_PID)#include "except.h"#include "usb.h"#define MAX_PACKET_SIZE 16#define RETRIES 100#define EP0_PACKET_SIZE 8/* if you want debug messages, remove this line */#define DEBUG_OUT(s)#ifndef DEBUG_OUT#define DEBUG_OUT(s) EdbgOutputDebugString(s)#define DEBUG_OUT2(s,p) EdbgOutputDebugString(s,p)#else#define DEBUG_OUT2(s,p)#endif/* * state * -1: udc not initialized * 0: default * 1: sending data via ep0 */static int state = -1;static int UDCService( void );static voidUSB_writechar( char c ){ static int first = 1; int Timeout = 0x200000; if (state) Throw E_USBUNINITIALIZED; while (Timeout--) { UDCService(); if (!(first || (UDCCS2 & TPC))) continue; if (!first) while (UDCCS2 & TPC) UDCCS2 = TPC; first = 0; while (UDCIMP != 0) UDCIMP = 0; UDCDR = c; while (UDCCS2 & 0x10) UDCCS2 = 0x10; /* SST */ return; } Throw E_WRITETIMEOUT;}static charUSB_read( void ){ int Timeout = 0x200000; if (state) Throw E_USBUNINITIALIZED; while (Timeout--) { UDCService(); if (!(UDCCS1 & RPC)) continue; if (UDCCS1 & RNE) return (char) UDCDR; else while (UDCCS1 & RPC) UDCCS1 = RPC; } Throw E_READTIMEOUT;}/* device descriptor */static const struct usb_dev_desc wid_dev_desc = { 18, /* length */ 1, /* descriptortype */ 0x0100, /* usb */ -1, /* deviceclass */ -1, /* devicesubclass */ -1, /* deviceprotocol */ 0x08, /* maxpacketsize0 */ USB_VID, /* idvendor */ USB_PID, /* idproduct */ 0, /* device */ 0, /* manufacturer */ 0, /* product */ 0, /* serialnumber */ 1, /* numconfigurations */};/* configuration descriptor */static const struct usb_conf_desc wid_conf_desc = { { 9, /* length */ 2, /* descriptortype (CONFIGURATION) */ 32, /* total length */ 1, /* numinterfaces */ 1, /* configurationvalue */ 0, /* configuration */ 0x40, /* attributes */ 1, /* 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) */ 0x01, /* endpointaddress (ep1, out) */ 2, /* mattributes (0010 = bulk) */ MAX_PACKET_SIZE, /* maxpacketsize */ 0, /* interval (ignored for bulk) */ } , { 7, /* length */ 5, /* descriptortype (ENDPOINT) */ '\x82', /* endpointaddress (ep2, in) */ 2, /* attributes (0010 = bulk) */ MAX_PACKET_SIZE, /* maxpacketsize */ 0, /* interval (ignored for bulk) */ }};/* FIXME: there are more possible neverending stories. discover & solve */static voidInitUDC( void ){ UDCCR = 0; /* enable UDC */ UDCSR = UDCSR; /* clear all interrupts */ GPDR &= ~GPIO_USP_MASK; /* set GPIO_USP as input */ /* TODO: add workaround with bit 7 of UDCCR for B5 stepping */ UDCIMP = MAX_PACKET_SIZE - 1; /* set in max packet size */ UDCOMP = MAX_PACKET_SIZE - 1; /* set out max packet size */ state = 0;}static voidDeinitUDC( void ){ UDCCR = 1; state = -1;}static voidEP0_SendData( int start, int len, const void *d, int maxlen ){ static int index = 0; static int reqlen = 0; static const char *data = NULL; unsigned int count; if (start) { index = 0; if ((reqlen = len) > maxlen) reqlen = maxlen; data = d; CLEAR_OPR( UDCCS0 ); } if (index == reqlen) { if (!(index % EP0_PACKET_SIZE)) { SET_IPR( UDCCS0 ); index++; DEBUG_OUT( "'" ); return; } index++; } if (index > reqlen) { state = 0; while (!(UDCCS0 & DE)) UDCCS0 = DE; DEBUG_OUT( "/" ); return; } DEBUG_OUT( "+" ); while (UDCWC) ; /* wait for empty FIFO */ while ((count = UDCWC) != EP0_PACKET_SIZE) { int retries = RETRIES; while ((count == UDCWC) && --retries) UDCD0 = data[index]; if (!retries) { while (!(UDCCS0 & FST)) UDCCS0 = FST; DEBUG_OUT( "F" ); state = 0; return; } if (++index == reqlen) break; } SET_IPR( UDCCS0 );}static intEP0_State0( void ){ struct usb_dev_req req; char *p = (char *) &req; unsigned int count; /* wait for full FIFO */ while (UDCWC != EP0_PACKET_SIZE) ; /* read request */ while ((count = UDCWC) != 0) { while (count == UDCWC) *p = (char) UDCD0; p++; } switch (req.request) { case 0x05: /* SET_ADDRESS */ CLEAR_OPR_DE( UDCCS0 ); UDCAR = req.value_lo; UDCAR = req.value_lo; DEBUG_OUT( "A" ); return 0; case 0x06: /* GET_DESCRIPTOR */ switch (req.value_hi) { case 1: /* DEVICE */ if (req.length == 0x12) state = 1; DEBUG_OUT2( "D(%d)", req.length ); EP0_SendData( 1, req.length, &wid_dev_desc, sizeof wid_dev_desc ); return 0; case 2: /* CONFIGURATION */ state = 1; DEBUG_OUT2( "C(%d)", req.length ); EP0_SendData( 1, req.length, &wid_conf_desc, sizeof wid_conf_desc ); return 0; default: EdbgOutputDebugString( "EP0/GET_DESCRIPTOR/value_hi = 0x%B\n", req.value_hi ); break; } break; case 0x09: /* SET_CONFIG */ CLEAR_OPR_DE( UDCCS0 ); DEBUG_OUT( "N" ); return 1; default: EdbgOutputDebugString( "EP0/request = 0x%B\n", req.request ); break; } CLEAR_OPR_DE( UDCCS0 ); return 0;}static intEP0( void ){ if (UDCCS0 & SE) { while (UDCCS0 & SE) UDCCS0 = SSE; state = 0; DEBUG_OUT( "S" ); return 0; } if (UDCCS0 & SST) { DEBUG_OUT( "T" ); while (UDCCS0 & SST) UDCCS0 = SST; return 0; } switch (state) { case -1: EdbgOutputDebugString( "UDC not initialized\n" ); break; case 0: if (UDCCS0 & OPR) return EP0_State0(); else { DEBUG_OUT( "x" ); return 0; } case 1: EP0_SendData( 0, 0, NULL, 0 ); return 0; default: EdbgOutputDebugString( "Unknown state: %d\n", state ); break; } return 0;}static intUDCService( void ){ int ret = 0; DWORD udcsr; UDCSR; udcsr = UDCSR; /* read twice for correct value */ UDCSR = udcsr; /* clears whole interrupts */ if (udcsr & RSTIR) { /* reset */ /* TODO: see doc 11-66 */ while (UDCCR & SUSIM) UDCCR &= ~SUSIM; while (UDCIMP != MAX_PACKET_SIZE - 1) UDCIMP = MAX_PACKET_SIZE - 1; /* set in max packet size */ while (UDCOMP != MAX_PACKET_SIZE - 1) UDCOMP = MAX_PACKET_SIZE - 1; /* set out max packet size */ DEBUG_OUT( "!" ); state = 0; return 0; } if (udcsr & EIR) { ret |= EP0(); return ret; }#if 0 if (udcsr & RIR) { EdbgOutputDebugString( "EP1\n" ); } if (udcsr & TIR) { EdbgOutputDebugString( "EP2\n" ); }#endif /* 0 */ if (udcsr & RESIR) { while (!(UDCCR & RESIM)) UDCCR |= RESIM; while (UDCCR & RESIM) UDCCR &= ~RESIM; while (UDCCR & SUSIM) UDCCR &= ~SUSIM; DEBUG_OUT( "RESIR\n" ); } if (udcsr & SUSIR) { while (!(UDCCR & SUSIM)) UDCCR |= SUSIM; DEBUG_OUT( "SUSIR\n" ); } return ret;}intUSB_download( struct imginfo *img ){ DWORD Timeout; int i; struct fntable fn = { USB_writechar, USB_read }; InitUDC(); EdbgOutputDebugString( "Ready to download image via USB\n" ); EdbgOutputDebugString( "* Please connect USB cable between PC and WID.\n" ); for (i = 4, Timeout = 0; i && !Timeout; i--) { EdbgOutputDebugString( "%d\r", i ); Timeout = 0x200000; while (Timeout) { if (GPLR & GPIO_USP_MASK) { if (UDCService()) break; } else Timeout--; } } if (!Timeout) { DeinitUDC(); return -2; } EdbgOutputDebugString( "\nUSB ready.\n" ); for (i = 0; i < 10; i++) { EdbgOutputDebugString( "." ); Try { download( &fn, img, 0 ); } Catch_anonymous { continue; }; return 0; } EdbgOutputDebugString( "\nFail to synchonize with the host\n" ); return -2;}#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 == SA1110 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -