00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041 #define token x1
00042
00043 overflow:
00044 ldi x2, 1<<USB_INTR_PENDING_BIT
00045 USB_STORE_PENDING(x2) ; clear any pending interrupts
00046 ignorePacket:
00047 clr token
00048 rjmp storeTokenAndReturn
00049
00050 ;----------------------------------------------------------------------------
00051 ; Processing of received packet (numbers in brackets are cycles after center of SE0)
00052 ;----------------------------------------------------------------------------
00053 ;This is the only non-error exit point for the software receiver loop
00054 ;we don't check any CRCs here because there is no time left.
00055 se0:
00056 subi cnt, USB_BUFSIZE ;[5]
00057 neg cnt ;[6]
00058 sub YL, cnt ;[7]
00059 sbci YH, 0 ;[8]
00060 ldi x2, 1<<USB_INTR_PENDING_BIT ;[9]
00061 USB_STORE_PENDING(x2) ;[10] clear pending intr and check flag later. SE0 should be over.
00062 ld token, y ;[11]
00063 cpi token, USBPID_DATA0 ;[13]
00064 breq handleData ;[14]
00065 cpi token, USBPID_DATA1 ;[15]
00066 breq handleData ;[16]
00067 lds shift, usbDeviceAddr;[17]
00068 ldd x2, y+1 ;[19] ADDR and 1 bit endpoint number
00069 lsl x2 ;[21] shift out 1 bit endpoint number
00070 cpse x2, shift ;[22]
00071 rjmp ignorePacket ;[23]
00072 /* only compute endpoint number in x3 if required later */
00073 #if USB_CFG_HAVE_INTRIN_ENDPOINT || USB_CFG_IMPLEMENT_FN_WRITEOUT
00074 ldd x3, y+2 ;[24] endpoint number + crc
00075 rol x3 ;[26] shift in LSB of endpoint
00076 #endif
00077 cpi token, USBPID_IN ;[27]
00078 breq handleIn ;[28]
00079 cpi token, USBPID_SETUP ;[29]
00080 breq handleSetupOrOut ;[30]
00081 cpi token, USBPID_OUT ;[31]
00082 brne ignorePacket ;[32] must be ack, nak or whatever
00083 ; rjmp handleSetupOrOut ; fallthrough
00084
00085 ;Setup and Out are followed by a data packet two bit times (16 cycles) after
00086 ;the end of SE0. The sync code allows up to 40 cycles delay from the start of
00087 ;the sync pattern until the first bit is sampled. That's a total of 56 cycles.
00088 handleSetupOrOut: ;[32]
00089 #if USB_CFG_IMPLEMENT_FN_WRITEOUT
00090 andi x3, 0xf ;[32]
00091 breq storeTokenAndReturn ;[33]
00092 mov token, x3 ;[34] indicate that this is endpoint x OUT
00093 #endif
00094 storeTokenAndReturn:
00095 sts usbCurrentTok, token;[35]
00096 doReturn:
00097 POP_STANDARD ;[37] 12...16 cycles
00098 USB_LOAD_PENDING(YL) ;[49]
00099 sbrc YL, USB_INTR_PENDING_BIT;[50] check whether data is already arriving
00100 rjmp waitForJ ;[51] save the pops and pushes -- a new interrupt is already pending
00101 sofError:
00102 POP_RETI ;macro call
00103 reti
00104
00105 handleData:
00106 #if USB_CFG_CHECK_CRC
00107 CRC_CLEANUP_AND_CHECK ; jumps to ignorePacket if CRC error
00108 #endif
00109 lds shift, usbCurrentTok;[18]
00110 tst shift ;[20]
00111 breq doReturn ;[21]
00112 lds x2, usbRxLen ;[22]
00113 tst x2 ;[24]
00114 brne sendNakAndReti ;[25]
00115 ; 2006-03-11: The following two lines fix a problem where the device was not
00116 ; recognized if usbPoll() was called less frequently than once every 4 ms.
00117 cpi cnt, 4 ;[26] zero sized data packets are status phase only -- ignore and ack
00118 brmi sendAckAndReti ;[27] keep rx buffer clean -- we must not NAK next SETUP
00119 #if USB_CFG_CHECK_DATA_TOGGLING
00120 sts usbCurrentDataToken, token ; store for checking by C code
00121 #endif
00122 sts usbRxLen, cnt ;[28] store received data, swap buffers
00123 sts usbRxToken, shift ;[30]
00124 lds x2, usbInputBufOffset;[32] swap buffers
00125 ldi cnt, USB_BUFSIZE ;[34]
00126 sub cnt, x2 ;[35]
00127 sts usbInputBufOffset, cnt;[36] buffers now swapped
00128 rjmp sendAckAndReti ;[38] 40 + 17 = 57 until SOP
00129
00130 handleIn:
00131 ;We don't send any data as long as the C code has not processed the current
00132 ;input data and potentially updated the output data. That's more efficient
00133 ;in terms of code size than clearing the tx buffers when a packet is received.
00134 lds x1, usbRxLen ;[30]
00135 cpi x1, 1 ;[32] negative values are flow control, 0 means "buffer free"
00136 brge sendNakAndReti ;[33] unprocessed input packet?
00137 ldi x1, USBPID_NAK ;[34] prepare value for usbTxLen
00138 #if USB_CFG_HAVE_INTRIN_ENDPOINT
00139 andi x3, 0xf ;[35] x3 contains endpoint
00140 #if USB_CFG_SUPPRESS_INTR_CODE
00141 brne sendNakAndReti ;[36]
00142 #else
00143 brne handleIn1 ;[36]
00144 #endif
00145 #endif
00146 lds cnt, usbTxLen ;[37]
00147 sbrc cnt, 4 ;[39] all handshake tokens have bit 4 set
00148 rjmp sendCntAndReti ;[40] 42 + 16 = 58 until SOP
00149 sts usbTxLen, x1 ;[41] x1 == USBPID_NAK from above
00150 ldi YL, lo8(usbTxBuf) ;[43]
00151 ldi YH, hi8(usbTxBuf) ;[44]
00152 rjmp usbSendAndReti ;[45] 57 + 12 = 59 until SOP
00153
00154 ; Comment about when to set usbTxLen to USBPID_NAK:
00155 ; We should set it back when we receive the ACK from the host. This would
00156 ; be simple to implement: One static variable which stores whether the last
00157 ; tx was for endpoint 0 or 1 and a compare in the receiver to distinguish the
00158 ; ACK. However, we set it back immediately when we send the package,
00159 ; assuming that no error occurs and the host sends an ACK. We save one byte
00160 ; RAM this way and avoid potential problems with endless retries. The rest of
00161 ; the driver assumes error-free transfers anyway.
00162
00163 #if !USB_CFG_SUPPRESS_INTR_CODE && USB_CFG_HAVE_INTRIN_ENDPOINT
00164 handleIn1: ;[38]
00165 #if USB_CFG_HAVE_INTRIN_ENDPOINT3
00166 ; 2006-06-10 as suggested by O.Tamura: support second INTR IN / BULK IN endpoint
00167 cpi x3, USB_CFG_EP3_NUMBER;[38]
00168 breq handleIn3 ;[39]
00169 #endif
00170 lds cnt, usbTxLen1 ;[40]
00171 sbrc cnt, 4 ;[42] all handshake tokens have bit 4 set
00172 rjmp sendCntAndReti ;[43] 47 + 16 = 63 until SOP
00173 sts usbTxLen1, x1 ;[44] x1 == USBPID_NAK from above
00174 ldi YL, lo8(usbTxBuf1) ;[46]
00175 ldi YH, hi8(usbTxBuf1) ;[47]
00176 rjmp usbSendAndReti ;[48] 50 + 12 = 62 until SOP
00177
00178 #if USB_CFG_HAVE_INTRIN_ENDPOINT3
00179 handleIn3:
00180 lds cnt, usbTxLen3 ;[41]
00181 sbrc cnt, 4 ;[43]
00182 rjmp sendCntAndReti ;[44] 49 + 16 = 65 until SOP
00183 sts usbTxLen3, x1 ;[45] x1 == USBPID_NAK from above
00184 ldi YL, lo8(usbTxBuf3) ;[47]
00185 ldi YH, hi8(usbTxBuf3) ;[48]
00186 rjmp usbSendAndReti ;[49] 51 + 12 = 63 until SOP
00187 #endif
00188 #endif