diff --git a/bootrom/bootrom.c b/bootrom/bootrom.c index 424258390..341205e17 100644 --- a/bootrom/bootrom.c +++ b/bootrom/bootrom.c @@ -84,11 +84,11 @@ static void Fatal(void) { } void UsbPacketReceived(uint8_t *packet, int len) { - int i, dont_ack=0; + int i, dont_ack = 0; UsbCommand* c = (UsbCommand *)packet; volatile uint32_t *p; - if ( len != sizeof(UsbCommand)) Fatal(); + //if ( len != sizeof(UsbCommand)) Fatal(); uint32_t arg0 = (uint32_t)c->arg[0]; diff --git a/common/usb_cdc.c b/common/usb_cdc.c index 17642625a..0744a7152 100644 --- a/common/usb_cdc.c +++ b/common/usb_cdc.c @@ -99,6 +99,38 @@ AT91SAM7S256 USB Device Port #define MS_WCID_GET_DESCRIPTOR 0xC0 #define MS_WCID_GET_FEATURE_DESCRIPTOR 0xC1 +/* USB standard request code */ +#define STD_GET_STATUS_ZERO 0x0080 +#define STD_GET_STATUS_INTERFACE 0x0081 +#define STD_GET_STATUS_ENDPOINT 0x0082 + +#define STD_CLEAR_FEATURE_ZERO 0x0100 +#define STD_CLEAR_FEATURE_INTERFACE 0x0101 +#define STD_CLEAR_FEATURE_ENDPOINT 0x0102 + +#define STD_SET_FEATURE_ZERO 0x0300 +#define STD_SET_FEATURE_INTERFACE 0x0301 +#define STD_SET_FEATURE_ENDPOINT 0x0302 + +#define STD_SET_ADDRESS 0x0500 +#define STD_GET_DESCRIPTOR 0x0680 +#define STD_SET_DESCRIPTOR 0x0700 +#define STD_GET_CONFIGURATION 0x0880 +#define STD_SET_CONFIGURATION 0x0900 +#define STD_GET_INTERFACE 0x0A81 +#define STD_SET_INTERFACE 0x0B01 +#define STD_SYNCH_FRAME 0x0C82 + +/* CDC Class Specific Request Code */ +#define GET_LINE_CODING 0x21A1 +#define SET_LINE_CODING 0x2021 +#define SET_CONTROL_LINE_STATE 0x2221 + +AT91PS_UDP pUdp = AT91C_BASE_UDP; +uint8_t btConfiguration = 0; +uint8_t btConnection = 0; +uint8_t btReceiveBank = AT91C_UDP_RX_DATA_BK0; + static const char devDescriptor[] = { /* Device descriptor */ 0x12, // Length @@ -127,7 +159,7 @@ static const char cfgDescriptor[] = { 2, // Number of Interfaces 1, // Index value of this Configuration (used in SetConfiguration from Host) 0, // Configuration string index - _DEFAULT, // Attributes 0xA0 + 0xC0, // Attributes 0xA0 0xFA, // Max Power consumption // IAD to associate the one CDC interface @@ -370,6 +402,7 @@ const char* getStringDescriptor(uint8_t idx) { } } + // Bitmap for all status bits in CSR which must be written as 1 to cause no effect #define REG_NO_EFFECT_1_ALL AT91C_UDP_RX_DATA_BK0 | AT91C_UDP_RX_DATA_BK1 \ |AT91C_UDP_STALLSENT | AT91C_UDP_RXSETUP \ @@ -395,33 +428,6 @@ const char* getStringDescriptor(uint8_t idx) { while ( ( pUdp->UDP_CSR[(endpoint)] & (flags)) != (flags)) {}; \ } \ - -/* USB standard request code */ -#define STD_GET_STATUS_ZERO 0x0080 -#define STD_GET_STATUS_INTERFACE 0x0081 -#define STD_GET_STATUS_ENDPOINT 0x0082 - -#define STD_CLEAR_FEATURE_ZERO 0x0100 -#define STD_CLEAR_FEATURE_INTERFACE 0x0101 -#define STD_CLEAR_FEATURE_ENDPOINT 0x0102 - -#define STD_SET_FEATURE_ZERO 0x0300 -#define STD_SET_FEATURE_INTERFACE 0x0301 -#define STD_SET_FEATURE_ENDPOINT 0x0302 - -#define STD_SET_ADDRESS 0x0500 -#define STD_GET_DESCRIPTOR 0x0680 -#define STD_SET_DESCRIPTOR 0x0700 -#define STD_GET_CONFIGURATION 0x0880 -#define STD_SET_CONFIGURATION 0x0900 -#define STD_GET_INTERFACE 0x0A81 -#define STD_SET_INTERFACE 0x0B01 -#define STD_SYNCH_FRAME 0x0C82 - -/* CDC Class Specific Request Code */ -#define GET_LINE_CODING 0x21A1 -#define SET_LINE_CODING 0x2021 -#define SET_CONTROL_LINE_STATE 0x2221 typedef struct { uint32_t BitRate; @@ -436,11 +442,6 @@ AT91S_CDC_LINE_CODING line = { 0, // None Parity 8}; // 8 Data bits -AT91PS_UDP pUdp = AT91C_BASE_UDP; -uint8_t btConfiguration = 0; -uint8_t btConnection = 0; -uint8_t btReceiveBank = AT91C_UDP_RX_DATA_BK0; - static void SpinDelay(int ms) { int us = ms * 1000; int ticks = (48 * us) >> 10; @@ -490,6 +491,9 @@ void usb_enable() { // Enables the 48MHz USB clock UDPCK and System Peripheral USB Clock AT91C_BASE_PMC->PMC_SCER = AT91C_PMC_UDP; AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_UDP); + + AT91C_BASE_UDP->UDP_FADDR = 0; + AT91C_BASE_UDP->UDP_GLBSTATE = 0; // Enable UDP PullUp (USB_DP_PUP) : enable & Clear of the corresponding PIO // Set in PIO mode and Configure in Output @@ -567,19 +571,18 @@ bool usb_check() { pUdp->UDP_FADDR = AT91C_UDP_FEN; // Configure endpoint 0 (enable control endpoint) pUdp->UDP_CSR[AT91C_EP_CONTROL] = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_CTRL); - // clear it - pUdp->UDP_ICR |= AT91C_UDP_ENDBUSRES; } else if (isr & AT91C_UDP_EPINT0) { pUdp->UDP_ICR = AT91C_UDP_EPINT0; AT91F_CDC_Enumerate(); - //pUdp->UDP_ICR |= AT91C_UDP_EPINT0; - } + } + /* else if (isr & AT91C_UDP_EPINT3 ) { pUdp->UDP_ICR = AT91C_UDP_EPINT3; AT91F_CDC_Enumerate(); - pUdp->UDP_ICR |= AT91C_UDP_EPINT3; + //pUdp->UDP_ICR |= AT91C_UDP_EPINT3; } + */ return (btConfiguration) ? true : false; } @@ -599,7 +602,7 @@ bool usb_poll() { bool usb_poll_validate_length() { if (!usb_check()) return false; if (!(pUdp->UDP_CSR[AT91C_EP_OUT] & btReceiveBank)) return false; - return (pUdp->UDP_CSR[AT91C_EP_OUT] >> 16) > 0; + return ((pUdp->UDP_CSR[AT91C_EP_OUT] & AT91C_UDP_RXBYTECNT) >> 16) > 0; } //*---------------------------------------------------------------------------- @@ -608,6 +611,8 @@ bool usb_poll_validate_length() { //*---------------------------------------------------------------------------- uint32_t usb_read(byte_t* data, size_t len) { + if ( len == 0 ) return 0; + uint8_t bank = btReceiveBank; uint32_t packetSize, nbBytesRcv = 0; uint32_t time_out = 0; @@ -616,11 +621,14 @@ uint32_t usb_read(byte_t* data, size_t len) { if (!usb_check()) break; if ( pUdp->UDP_CSR[AT91C_EP_OUT] & bank ) { - packetSize = MIN(pUdp->UDP_CSR[AT91C_EP_OUT] >> 16, len); + + packetSize = (pUdp->UDP_CSR[AT91C_EP_OUT] & AT91C_UDP_RXBYTECNT) >> 16; + packetSize = MIN( packetSize, len); len -= packetSize; while (packetSize--) data[nbBytesRcv++] = pUdp->UDP_FDR[AT91C_EP_OUT]; + // flip bank UDP_CLEAR_EP_FLAGS(AT91C_EP_OUT, bank) if (bank == AT91C_UDP_RX_DATA_BK0) @@ -643,19 +651,23 @@ uint32_t usb_write(const byte_t* data, const size_t len) { if (!len) return 0; if (!usb_check()) return 0; + + // can we write? + if ( (pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXPKTRDY) != 0 ) return 0; size_t length = len; uint32_t cpt = 0; + // send first chunk cpt = MIN(length, AT91C_EP_IN_SIZE); length -= cpt; while (cpt--) { pUdp->UDP_FDR[AT91C_EP_IN] = *data++; } - - UDP_SET_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXPKTRDY) - + + UDP_SET_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXPKTRDY); + while (length) { // Send next chunk cpt = MIN(length, AT91C_EP_IN_SIZE); @@ -664,13 +676,15 @@ uint32_t usb_write(const byte_t* data, const size_t len) { pUdp->UDP_FDR[AT91C_EP_IN] = *data++; } - // Wait for the first bank to be sent + // Wait for previous chunk to be sent + // (iceman) when is the bankswapping done? while (!(pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP)) { if (!usb_check()) return length; } - UDP_CLEAR_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXCOMP) - UDP_SET_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXPKTRDY) + UDP_CLEAR_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXCOMP); + UDP_SET_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXPKTRDY); + } // Wait for the end of transfer @@ -703,7 +717,7 @@ void AT91F_USB_SendData(AT91PS_UDP pUdp, const char *pData, uint32_t length) { UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_TXCOMP) } - UDP_SET_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_TXPKTRDY) + UDP_SET_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_TXPKTRDY); do { csr = pUdp->UDP_CSR[AT91C_EP_CONTROL]; @@ -766,7 +780,7 @@ void AT91F_CDC_Enumerate() { wLength |= (pUdp->UDP_FDR[AT91C_EP_CONTROL] << 8); if (bmRequestType & 0x80) { // Data Phase Transfer Direction Device to Host - UDP_SET_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_DIR) + UDP_SET_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_DIR); } UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_RXSETUP) @@ -813,10 +827,17 @@ void AT91F_CDC_Enumerate() { case STD_SET_CONFIGURATION: btConfiguration = wValue; AT91F_USB_SendZlp(pUdp); - pUdp->UDP_GLBSTATE = (wValue) ? AT91C_UDP_CONFG : AT91C_UDP_FADDEN; + pUdp->UDP_GLBSTATE = (wValue) ? AT91C_UDP_CONFG : AT91C_UDP_FADDEN; + + // make sure we are not stalled + UDP_CLEAR_EP_FLAGS(AT91C_EP_OUT , AT91C_UDP_FORCESTALL); + UDP_CLEAR_EP_FLAGS(AT91C_EP_IN , AT91C_UDP_FORCESTALL); + UDP_CLEAR_EP_FLAGS(AT91C_EP_NOTIFY, AT91C_UDP_FORCESTALL); + + // enable endpoints UDP_SET_EP_FLAGS(AT91C_EP_OUT, (wValue) ? (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_OUT) : 0 ); UDP_SET_EP_FLAGS(AT91C_EP_IN, (wValue) ? (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_IN) : 0 ); - UDP_SET_EP_FLAGS(AT91C_EP_NOTIFY, (wValue) ? (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_INT_IN) : 0 ); + UDP_SET_EP_FLAGS(AT91C_EP_NOTIFY, (wValue) ? AT91C_UDP_EPTYPE_INT_IN : 0 ); // pUdp->UDP_CSR[AT91C_EP_OUT] = (wValue) ? (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_OUT) : 0; // pUdp->UDP_CSR[AT91C_EP_IN] = (wValue) ? (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_IN) : 0; // pUdp->UDP_CSR[AT91C_EP_NOTIFY] = (wValue) ? (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_INT_IN) : 0; @@ -870,15 +891,15 @@ void AT91F_CDC_Enumerate() { case STD_CLEAR_FEATURE_ENDPOINT: wIndex &= 0x0F; if ((wValue == 0) && (wIndex >= AT91C_EP_OUT) && (wIndex <= AT91C_EP_NOTIFY)) { - if (wIndex == 1) { + if (wIndex == AT91C_EP_OUT) { //pUdp->UDP_CSR[AT91C_EP_OUT] = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_OUT); UDP_SET_EP_FLAGS(AT91C_EP_OUT, (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_OUT) ); } - else if (wIndex == 2) { + else if (wIndex == AT91C_EP_IN) { //pUdp->UDP_CSR[AT91C_EP_IN] = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_IN); UDP_SET_EP_FLAGS(AT91C_EP_IN, (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_IN) ); } - else if (wIndex == 3) { + else if (wIndex == AT91C_EP_NOTIFY) { //pUdp->UDP_CSR[AT91C_EP_NOTIFY] = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_INT_IN); UDP_SET_EP_FLAGS(AT91C_EP_NOTIFY, (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_INT_IN) ); }