Rev 3332 Rev 3333
Line 1... Line 1...
1 /* Name: usbdrvasm.S 1 /* Name: usbdrvasm.S
2 * Project: AVR USB driver 2 * Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers
3 * Author: Christian Starkjohann 3 * Author: Christian Starkjohann
4 * Creation Date: 2004-12-29 4 * Creation Date: 2007-06-13
5 * Tabsize: 4 5 * Tabsize: 4
6 * Copyright: (c) 2007 by OBJECTIVE DEVELOPMENT Software GmbH 6 * Copyright: (c) 2007 by OBJECTIVE DEVELOPMENT Software GmbH
7 * License: GNU GPL v2 (see License.txt) or proprietary (CommercialLicense.txt) 7 * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
8 * This Revision: $Id: usbdrvasm.S,v 1.2 2007/05/19 12:30:11 harbaum Exp $ -  
9 */ 8 */
10   9  
11 /* 10 /*
12 General Description: 11 General Description:
13 This module implements the assembler part of the USB driver. See usbdrv.h 12 This module is the assembler part of the USB driver. This file contains
14 for a description of the entire driver. -  
15 Since almost all of this code is timing critical, don't change unless you 13 general code (preprocessor acrobatics and CRC computation) and then includes
16 really know what you are doing! Many parts require not only a maximum number -  
17 of CPU cycles, but even an exact number of cycles! -  
18   -  
19   -  
20 Timing constraints according to spec (in bit times): 14 the file appropriate for the given clock rate.
21 timing subject min max CPUcycles -  
22 --------------------------------------------------------------------------- -  
23 EOP of OUT/SETUP to sync pattern of DATA0 (both rx) 2 16 16-128 -  
24 EOP of IN to sync pattern of DATA0 (rx, then tx) 2 7.5 16-60 -  
25 DATAx (rx) to ACK/NAK/STALL (tx) 2 7.5 16-60 -  
26 */ 15 */
27   16  
28 #include "iarcompat.h" -  
29 #ifndef __IAR_SYSTEMS_ASM__ -  
30 /* configs for io.h */ -  
31 # define __SFR_OFFSET 0 -  
32 # define _VECTOR(N) __vector_ ## N /* io.h does not define this for asm */ 17 #define __SFR_OFFSET 0 /* used by avr-libc's register definitions */
33 # include <avr/io.h> /* for CPU I/O register definitions and vectors */ -  
34 #endif /* __IAR_SYSTEMS_ASM__ */ 18 #include "usbportability.h"
35 #include "usbdrv.h" /* for common defs */ 19 #include "usbdrv.h" /* for common defs */
36   -  
37   20  
38 /* register names */ 21 /* register names */
39 #define x1 r16 22 #define x1 r16
40 #define x2 r17 23 #define x2 r17
41 #define shift r18 24 #define shift r18
42 #define cnt r19 25 #define cnt r19
43 #define x3 r20 26 #define x3 r20
44 #define x4 r21 27 #define x4 r21
-   28 #define x5 r22
-   29 #define bitcnt x5
-   30 #define phase x4
-   31 #define leap x4
45   32  
46 /* Some assembler dependent definitions and declarations: */ 33 /* Some assembler dependent definitions and declarations: */
47   34  
48 #ifdef __IAR_SYSTEMS_ASM__ 35 #ifdef __IAR_SYSTEMS_ASM__
49   -  
50 # define nop2 rjmp $+2 /* jump to next instruction */ -  
51 # define XL r26 -  
52 # define XH r27 -  
53 # define YL r28 -  
54 # define YH r29 -  
55 # define ZL r30 -  
56 # define ZH r31 -  
57 # define lo8(x) LOW(x) -  
58 # define hi8(x) ((x)>>8) /* not HIGH to allow XLINK to make a proper range check */ -  
59   -  
60 extern usbRxBuf, usbDeviceAddr, usbNewDeviceAddr, usbInputBufOffset 36 extern usbRxBuf, usbDeviceAddr, usbNewDeviceAddr, usbInputBufOffset
61 extern usbCurrentTok, usbRxLen, usbRxToken, usbTxLen 37 extern usbCurrentTok, usbRxLen, usbRxToken, usbTxLen
62 extern usbTxBuf, usbMsgLen, usbTxLen1, usbTxBuf1, usbTxLen3, usbTxBuf3 38 extern usbTxBuf, usbTxStatus1, usbTxStatus3
-   39 # if USB_COUNT_SOF
-   40 extern usbSofCount
-   41 # endif
63 public usbCrc16 42 public usbCrc16
64 public usbCrc16Append 43 public usbCrc16Append
65   44  
66 COMMON INTVEC 45 COMMON INTVEC
-   46 # ifndef USB_INTR_VECTOR
67 ORG INT0_vect 47 ORG INT0_vect
-   48 # else /* USB_INTR_VECTOR */
-   49 ORG USB_INTR_VECTOR
-   50 # undef USB_INTR_VECTOR
-   51 # endif /* USB_INTR_VECTOR */
-   52 # define USB_INTR_VECTOR usbInterruptHandler
68 rjmp SIG_INTERRUPT0 53 rjmp USB_INTR_VECTOR
69 RSEG CODE 54 RSEG CODE
70   55  
71 #else /* __IAR_SYSTEMS_ASM__ */ 56 #else /* __IAR_SYSTEMS_ASM__ */
72   57  
73 # define nop2 rjmp .+0 /* jump to next instruction */ 58 # ifndef USB_INTR_VECTOR /* default to hardware interrupt INT0 */
-   59 # ifdef INT0_vect
-   60 # define USB_INTR_VECTOR INT0_vect // this is the "new" define for the vector
-   61 # else
-   62 # define USB_INTR_VECTOR SIG_INTERRUPT0 // this is the "old" vector
-   63 # endif
74   64 # endif
75 .text 65 .text
76 .global SIG_INTERRUPT0 66 .global USB_INTR_VECTOR
77 .type SIG_INTERRUPT0, @function 67 .type USB_INTR_VECTOR, @function
78 .global usbCrc16 68 .global usbCrc16
79 .global usbCrc16Append 69 .global usbCrc16Append
80   -  
81 #endif /* __IAR_SYSTEMS_ASM__ */ 70 #endif /* __IAR_SYSTEMS_ASM__ */
82   71  
83   72  
84 ;Software-receiver engine. Strict timing! Don't change unless you can preserve timing! -  
85 ;interrupt response time: 4 cycles + insn running = 7 max if interrupts always enabled -  
86 ;max allowable interrupt latency: 34 cycles -> max 25 cycles interrupt disable -  
87 ;max stack usage: [ret(2), YL, SREG, YH, shift, x1, x2, x3, cnt, x4] = 11 bytes -  
88 ;Numbers in brackets are maximum cycles since SOF. -  
89 SIG_INTERRUPT0: -  
90 ;order of registers pushed: YL, SREG [sofError], YH, shift, x1, x2, x3, cnt -  
91 push YL ;2 [35] push only what is necessary to sync with edge ASAP -  
92 in YL, SREG ;1 [37] -  
93 push YL ;2 [39] -  
94 ;---------------------------------------------------------------------------- -  
95 ; Synchronize with sync pattern: -  
96 ;---------------------------------------------------------------------------- -  
97 ;sync byte (D-) pattern LSb to MSb: 01010100 [1 = idle = J, 0 = K] -  
98 ;sync up with J to K edge during sync pattern -- use fastest possible loops -  
99 ;first part has no timeout because it waits for IDLE or SE1 (== disconnected) -  
100 waitForJ: -  
101 sbis USBIN, USBMINUS ;1 [40] wait for D- == 1 -  
102 rjmp waitForJ ;2 -  
103 waitForK: -  
104 ;The following code results in a sampling window of 1/4 bit which meets the spec. -  
105 sbis USBIN, USBMINUS -  
106 rjmp foundK -  
107 sbis USBIN, USBMINUS -  
108 rjmp foundK -  
109 sbis USBIN, USBMINUS -  
110 rjmp foundK -  
111 sbis USBIN, USBMINUS -  
112 rjmp foundK -  
113 sbis USBIN, USBMINUS -  
114 rjmp foundK -  
115 rjmp sofError -  
116 foundK: -  
117 ;{3, 5} after falling D- edge, average delay: 4 cycles [we want 4 for center sampling] -  
118 ;we have 1 bit time for setup purposes, then sample again. Numbers in brackets -  
119 ;are cycles from center of first sync (double K) bit after the instruction -  
120 push YH ;2 [2] -  
121 lds YL, usbInputBufOffset;2 [4] -  
122 clr YH ;1 [5] -  
123 subi YL, lo8(-(usbRxBuf));1 [6] -  
124 sbci YH, hi8(-(usbRxBuf));1 [7] -  
125   -  
126 sbis USBIN, USBMINUS ;1 [8] we want two bits K [sample 1 cycle too early] -  
127 rjmp haveTwoBitsK ;2 [10] -  
128 pop YH ; undo the push from before -  
129 rjmp waitForK ; this was not the end of sync, retry 73 #if USB_INTR_PENDING < 0x40 /* This is an I/O address, use in and out */
130 haveTwoBitsK: -  
131 ;---------------------------------------------------------------------------- -  
132 ; push more registers and initialize values while we sample the first bits: -  
133 ;---------------------------------------------------------------------------- -  
134 push shift ;2 [16] -  
135 push x1 ;2 [12] -  
136 push x2 ;2 [14] -  
137   -  
138 in x1, USBIN ;1 [17] <-- sample bit 0 -  
139 ldi shift, 0xff ;1 [18] -  
140 bst x1, USBMINUS ;1 [19] -  
141 bld shift, 0 ;1 [20] -  
142 push x3 ;2 [22] -  
143 push cnt ;2 [24] -  
144 -  
145 in x2, USBIN ;1 [25] <-- sample bit 1 74 # define USB_LOAD_PENDING(reg) in reg, USB_INTR_PENDING
146 ser x3 ;1 [26] [inserted init instruction] -  
147 eor x1, x2 ;1 [27] -  
148 bst x1, USBMINUS ;1 [28] -  
149 bld shift, 1 ;1 [29] -  
150 ldi cnt, USB_BUFSIZE;1 [30] [inserted init instruction] -  
151 rjmp rxbit2 ;2 [32] -  
152   -  
153 ;---------------------------------------------------------------------------- -  
154 ; Receiver loop (numbers in brackets are cycles within byte after instr) -  
155 ;---------------------------------------------------------------------------- -  
156   -  
157 unstuff0: ;1 (branch taken) -  
158 andi x3, ~0x01 ;1 [15] -  
159 mov x1, x2 ;1 [16] x2 contains last sampled (stuffed) bit -  
160 in x2, USBIN ;1 [17] <-- sample bit 1 again -  
161 ori shift, 0x01 ;1 [18] -  
162 rjmp didUnstuff0 ;2 [20] -  
163   -  
164 unstuff1: ;1 (branch taken) -  
165 mov x2, x1 ;1 [21] x1 contains last sampled (stuffed) bit -  
166 andi x3, ~0x02 ;1 [22] -  
167 ori shift, 0x02 ;1 [23] -  
168 nop ;1 [24] -  
169 in x1, USBIN ;1 [25] <-- sample bit 2 again -  
170 rjmp didUnstuff1 ;2 [27] -  
171   -  
172 unstuff2: ;1 (branch taken) -  
173 andi x3, ~0x04 ;1 [29] -  
174 ori shift, 0x04 ;1 [30] -  
175 mov x1, x2 ;1 [31] x2 contains last sampled (stuffed) bit -  
176 nop ;1 [32] -  
177 in x2, USBIN ;1 [33] <-- sample bit 3 -  
178 rjmp didUnstuff2 ;2 [35] -  
179   -  
180 unstuff3: ;1 (branch taken) -  
181 in x2, USBIN ;1 [34] <-- sample stuffed bit 3 [one cycle too late] -  
182 andi x3, ~0x08 ;1 [35] -  
183 ori shift, 0x08 ;1 [36] -  
184 rjmp didUnstuff3 ;2 [38] -  
185   -  
186 unstuff4: ;1 (branch taken) -  
187 andi x3, ~0x10 ;1 [40] -  
188 in x1, USBIN ;1 [41] <-- sample stuffed bit 4 -  
189 ori shift, 0x10 ;1 [42] -  
190 rjmp didUnstuff4 ;2 [44] -  
191   -  
192 unstuff5: ;1 (branch taken) -  
193 andi x3, ~0x20 ;1 [48] -  
194 in x2, USBIN ;1 [49] <-- sample stuffed bit 5 -  
195 ori shift, 0x20 ;1 [50] -  
196 rjmp didUnstuff5 ;2 [52] -  
197   -  
198 unstuff6: ;1 (branch taken) -  
199 andi x3, ~0x40 ;1 [56] -  
200 in x1, USBIN ;1 [57] <-- sample stuffed bit 6 -  
201 ori shift, 0x40 ;1 [58] -  
202 rjmp didUnstuff6 ;2 [60] -  
203   -  
204 ; extra jobs done during bit interval: -  
205 ; bit 0: store, clear [SE0 is unreliable here due to bit dribbling in hubs] -  
206 ; bit 1: se0 check -  
207 ; bit 2: overflow check -  
208 ; bit 3: recovery from delay [bit 0 tasks took too long] -  
209 ; bit 4: none -  
210 ; bit 5: none -  
211 ; bit 6: none -  
212 ; bit 7: jump, eor -  
213 rxLoop: -  
214 eor x3, shift ;1 [0] reconstruct: x3 is 0 at bit locations we changed, 1 at others -  
215 in x1, USBIN ;1 [1] <-- sample bit 0 -  
216 st y+, x3 ;2 [3] store data -  
217 ser x3 ;1 [4] -  
218 nop ;1 [5] -  
219 eor x2, x1 ;1 [6] -  
220 bst x2, USBMINUS;1 [7] -  
221 bld shift, 0 ;1 [8] -  
222 in x2, USBIN ;1 [9] <-- sample bit 1 (or possibly bit 0 stuffed) -  
223 andi x2, USBMASK ;1 [10] -  
224 breq se0 ;1 [11] SE0 check for bit 1 -  
225 andi shift, 0xf9 ;1 [12] -  
226 didUnstuff0: -  
227 breq unstuff0 ;1 [13] -  
228 eor x1, x2 ;1 [14] -  
229 bst x1, USBMINUS;1 [15] -  
230 bld shift, 1 ;1 [16] -  
231 rxbit2: -  
232 in x1, USBIN ;1 [17] <-- sample bit 2 (or possibly bit 1 stuffed) -  
233 andi shift, 0xf3 ;1 [18] -  
234 breq unstuff1 ;1 [19] do remaining work for bit 1 -  
235 didUnstuff1: -  
236 subi cnt, 1 ;1 [20] -  
237 brcs overflow ;1 [21] loop control -  
238 eor x2, x1 ;1 [22] -  
239 bst x2, USBMINUS;1 [23] -  
240 bld shift, 2 ;1 [24] -  
241 in x2, USBIN ;1 [25] <-- sample bit 3 (or possibly bit 2 stuffed) -  
242 andi shift, 0xe7 ;1 [26] -  
243 breq unstuff2 ;1 [27] -  
244 didUnstuff2: -  
245 eor x1, x2 ;1 [28] -  
246 bst x1, USBMINUS;1 [29] -  
247 bld shift, 3 ;1 [30] -  
248 didUnstuff3: -  
249 andi shift, 0xcf ;1 [31] -  
250 breq unstuff3 ;1 [32] -  
251 in x1, USBIN ;1 [33] <-- sample bit 4 -  
252 eor x2, x1 ;1 [34] -  
253 bst x2, USBMINUS;1 [35] -  
254 bld shift, 4 ;1 [36] -  
255 didUnstuff4: -  
256 andi shift, 0x9f ;1 [37] -  
257 breq unstuff4 ;1 [38] -  
258 nop2 ;2 [40] -  
259 in x2, USBIN ;1 [41] <-- sample bit 5 -  
260 eor x1, x2 ;1 [42] -  
261 bst x1, USBMINUS;1 [43] -  
262 bld shift, 5 ;1 [44] -  
263 didUnstuff5: -  
264 andi shift, 0x3f ;1 [45] -  
265 breq unstuff5 ;1 [46] -  
266 nop2 ;2 [48] -  
267 in x1, USBIN ;1 [49] <-- sample bit 6 -  
268 eor x2, x1 ;1 [50] -  
269 bst x2, USBMINUS;1 [51] -  
270 bld shift, 6 ;1 [52] -  
271 didUnstuff6: -  
272 cpi shift, 0x02 ;1 [53] -  
273 brlo unstuff6 ;1 [54] -  
274 nop2 ;2 [56] -  
275 in x2, USBIN ;1 [57] <-- sample bit 7 -  
276 eor x1, x2 ;1 [58] -  
277 bst x1, USBMINUS;1 [59] -  
278 bld shift, 7 ;1 [60] -  
279 didUnstuff7: -  
280 cpi shift, 0x04 ;1 [61] -  
281 brsh rxLoop ;2 [63] loop control -  
282 unstuff7: -  
283 andi x3, ~0x80 ;1 [63] -  
284 ori shift, 0x80 ;1 [64] -  
285 in x2, USBIN ;1 [65] <-- sample stuffed bit 7 -  
286 nop ;1 [66] -  
287 rjmp didUnstuff7 ;2 [68] -  
288   -  
289   -  
290 ;---------------------------------------------------------------------------- -  
291 ; Processing of received packet (numbers in brackets are cycles after end of SE0) -  
292 ;---------------------------------------------------------------------------- -  
293 ;This is the only non-error exit point for the software receiver loop -  
294 ;we don't check any CRCs here because there is no time left. -  
295 #define token x1 -  
296 se0: ; [0] -  
297 subi cnt, USB_BUFSIZE ;1 [1] -  
298 neg cnt ;1 [2] -  
299 cpi cnt, 3 ;1 [3] -  
300 ldi x2, 1<<USB_INTR_PENDING_BIT ;1 [4] 75 # define USB_STORE_PENDING(reg) out USB_INTR_PENDING, reg
301 out USB_INTR_PENDING, x2;1 [5] clear pending intr and check flag later. SE0 should be over. -  
302 brlo doReturn ;1 [6] this is probably an ACK, NAK or similar packet -  
303 sub YL, cnt ;1 [7] -  
304 sbci YH, 0 ;1 [8] -  
305 ld token, y ;2 [10] -  
306 cpi token, USBPID_DATA0 ;1 [11] -  
307 breq handleData ;1 [12] -  
308 cpi token, USBPID_DATA1 ;1 [13] -  
309 breq handleData ;1 [14] -  
310 ldd x2, y+1 ;2 [16] ADDR and 1 bit endpoint number -  
311 mov x3, x2 ;1 [17] store for endpoint number -  
312 andi x2, 0x7f ;1 [18] x2 is now ADDR 76 #else /* It's a memory address, use lds and sts */
313 lds shift, usbDeviceAddr;2 [20] -  
314 cp x2, shift ;1 [21] -  
315 overflow: ; This is a hack: brcs overflow will never have Z flag set -  
316 brne ignorePacket ;1 [22] packet for different address -  
317 cpi token, USBPID_IN ;1 [23] -  
318 breq handleIn ;1 [24] -  
319 cpi token, USBPID_SETUP ;1 [25] -  
320 breq handleSetupOrOut ;1 [26] -  
321 cpi token, USBPID_OUT ;1 [27] -  
322 breq handleSetupOrOut ;1 [28] -  
323 ; rjmp ignorePacket ;fallthrough, should not happen anyway. -  
324   -  
325 ignorePacket: -  
326 clr shift -  
327 sts usbCurrentTok, shift -  
328 doReturn: -  
329 pop cnt -  
330 pop x3 -  
331 pop x2 -  
332 pop x1 -  
333 pop shift -  
334 pop YH -  
335 sofError: -  
336 pop YL -  
337 out SREG, YL -  
338 pop YL -  
339 reti -  
340   -  
341 #if USB_CFG_HAVE_INTRIN_ENDPOINT && USB_CFG_HAVE_INTRIN_ENDPOINT3 77 # define USB_LOAD_PENDING(reg) lds reg, USB_INTR_PENDING
342 handleIn3: ;1 [38] (branch taken) -  
343 lds cnt, usbTxLen3 ;2 [40] -  
344 sbrc cnt, 4 ;2 [42] -  
345 rjmp sendCntAndReti ;0 43 + 17 = 60 until SOP -  
346 sts usbTxLen3, x1 ;2 [44] x1 == USBPID_NAK from above -  
347 ldi YL, lo8(usbTxBuf3) ;1 [45] -  
348 ldi YH, hi8(usbTxBuf3) ;1 [46] -  
349 rjmp usbSendAndReti ;2 [48] + 13 = 61 until SOP (violates the spec by 1 cycle) -  
350 #endif -  
351   -  
352 ;Setup and Out are followed by a data packet two bit times (16 cycles) after -  
353 ;the end of SE0. The sync code allows up to 40 cycles delay from the start of -  
354 ;the sync pattern until the first bit is sampled. That's a total of 56 cycles. -  
355 handleSetupOrOut: ;1 [29] (branch taken) -  
356 #if USB_CFG_IMPLEMENT_FN_WRITEOUT /* if we have data for second OUT endpoint, set usbCurrentTok to -1 */ -  
357 sbrc x3, 7 ;1 [30] skip if endpoint 0 -  
358 ldi token, -1 ;1 [31] indicate that this is endpoint 1 OUT -  
359 #endif -  
360 sts usbCurrentTok, token;2 [33] -  
361 pop cnt ;2 [35] -  
362 pop x3 ;2 [37] -  
363 pop x2 ;2 [39] -  
364 pop x1 ;2 [41] -  
365 pop shift ;2 [43] -  
366 pop YH ;2 [45] -  
367 in YL, USB_INTR_PENDING;1 [46] 78 # define USB_STORE_PENDING(reg) sts USB_INTR_PENDING, reg
368 sbrc YL, USB_INTR_PENDING_BIT;1 [47] check whether data is already arriving -  
369 rjmp waitForJ ;2 [49] save the pops and pushes -- a new interrupt is aready pending -  
370 rjmp sofError ;2 not an error, but it does the pops and reti we want -  
371   -  
372   -  
373 handleData: ;1 [15] (branch taken) -  
374 lds token, usbCurrentTok;2 [17] -  
375 tst token ;1 [18] -  
376 breq doReturn ;1 [19] -  
377 lds x2, usbRxLen ;2 [21] -  
378 tst x2 ;1 [22] -  
379 brne sendNakAndReti ;1 [23] -  
380 ; 2006-03-11: The following two lines fix a problem where the device was not -  
381 ; recognized if usbPoll() was called less frequently than once every 4 ms. -  
382 cpi cnt, 4 ;1 [24] zero sized data packets are status phase only -- ignore and ack -  
383 brmi sendAckAndReti ;1 [25] keep rx buffer clean -- we must not NAK next SETUP -  
384 sts usbRxLen, cnt ;2 [27] store received data, swap buffers -  
385 sts usbRxToken, token ;2 [29] -  
386 lds x2, usbInputBufOffset;2 [31] swap buffers -  
387 ldi cnt, USB_BUFSIZE ;1 [32] -  
388 sub cnt, x2 ;1 [33] -  
389 sts usbInputBufOffset, cnt;2 [35] buffers now swapped -  
390 rjmp sendAckAndReti ;2 [37] + 19 = 56 until SOP -  
391   -  
392 handleIn: ;1 [25] (branch taken) -  
393 ;We don't send any data as long as the C code has not processed the current -  
394 ;input data and potentially updated the output data. That's more efficient -  
395 ;in terms of code size than clearing the tx buffers when a packet is received. -  
396 lds x1, usbRxLen ;2 [27] -  
397 cpi x1, 1 ;1 [28] negative values are flow control, 0 means "buffer free" -  
398 brge sendNakAndReti ;1 [29] unprocessed input packet? -  
399 ldi x1, USBPID_NAK ;1 [30] prepare value for usbTxLen -  
400 #if USB_CFG_HAVE_INTRIN_ENDPOINT -  
401 sbrc x3, 7 ;2 [33] x3 contains addr + endpoint -  
402 rjmp handleIn1 ;0 -  
403 #endif -  
404 lds cnt, usbTxLen ;2 [34] -  
405 sbrc cnt, 4 ;2 [36] all handshake tokens have bit 4 set -  
406 rjmp sendCntAndReti ;0 37 + 17 = 54 until SOP -  
407 sts usbTxLen, x1 ;2 [38] x1 == USBPID_NAK from above -  
408 ldi YL, lo8(usbTxBuf) ;1 [39] -  
409 ldi YH, hi8(usbTxBuf) ;1 [40] -  
410 rjmp usbSendAndReti ;2 [42] + 14 = 56 until SOP -  
411   -  
412 ; Comment about when to set usbTxLen to USBPID_NAK: -  
413 ; We should set it back when we receive the ACK from the host. This would -  
414 ; be simple to implement: One static variable which stores whether the last -  
415 ; tx was for endpoint 0 or 1 and a compare in the receiver to distinguish the -  
416 ; ACK. However, we set it back immediately when we send the package, -  
417 ; assuming that no error occurs and the host sends an ACK. We save one byte -  
418 ; RAM this way and avoid potential problems with endless retries. The rest of -  
419 ; the driver assumes error-free transfers anyway. -  
420   -  
421 #if USB_CFG_HAVE_INTRIN_ENDPOINT /* placed here due to relative jump range */ -  
422 handleIn1: ;1 [33] (branch taken) -  
423 #if USB_CFG_HAVE_INTRIN_ENDPOINT3 -  
424 ; 2006-06-10 as suggested by O.Tamura: support second INTR IN / BULK IN endpoint -  
425 ldd x2, y+2 ;2 [35] -  
426 sbrc x2, 0 ;2 [37] -  
427 rjmp handleIn3 ;0 -  
428 #endif 79 #endif
429 lds cnt, usbTxLen1 ;2 [39] -  
430 sbrc cnt, 4 ;2 [41] all handshake tokens have bit 4 set -  
431 rjmp sendCntAndReti ;0 42 + 17 = 59 until SOP -  
432 sts usbTxLen1, x1 ;2 [43] x1 == USBPID_NAK from above -  
433 ldi YL, lo8(usbTxBuf1) ;1 [44] -  
434 ldi YH, hi8(usbTxBuf1) ;1 [45] -  
435 rjmp usbSendAndReti ;2 [47] + 13 = 60 until SOP -  
436 #endif -  
437   -  
438   80  
439 ;---------------------------------------------------------------------------- -  
440 ; Transmitting data -  
441 ;---------------------------------------------------------------------------- -  
442   -  
443 bitstuff0: ;1 (for branch taken) -  
444 eor x1, x4 ;1 -  
445 ldi x2, 0 ;1 81 #define usbTxLen1 usbTxStatus1
446 out USBOUT, x1 ;1 <-- out -  
447 rjmp didStuff0 ;2 branch back 2 cycles earlier -  
448 bitstuff1: ;1 (for branch taken) -  
449 eor x1, x4 ;1 -  
450 rjmp didStuff1 ;2 we know that C is clear, jump back to do OUT and ror 0 into x2 -  
451 bitstuff2: ;1 (for branch taken) -  
452 eor x1, x4 ;1 -  
453 rjmp didStuff2 ;2 jump back 4 cycles earlier and do out and ror 0 into x2 -  
454 bitstuff3: ;1 (for branch taken) -  
455 eor x1, x4 ;1 -  
456 rjmp didStuff3 ;2 jump back earlier and ror 0 into x2 -  
457 bitstuff4: ;1 (for branch taken) -  
458 eor x1, x4 ;1 -  
459 ldi x2, 0 ;1 -  
460 out USBOUT, x1 ;1 <-- out -  
461 rjmp didStuff4 ;2 jump back 2 cycles earlier -  
462   -  
463 sendNakAndReti: ;0 [-19] 19 cycles until SOP -  
464 ldi x3, USBPID_NAK ;1 [-18] -  
465 rjmp usbSendX3 ;2 [-16] -  
466 sendAckAndReti: ;0 [-19] 19 cycles until SOP -  
467 ldi x3, USBPID_ACK ;1 [-18] -  
468 rjmp usbSendX3 ;2 [-16] -  
469 sendCntAndReti: ;0 [-17] 17 cycles until SOP -  
470 mov x3, cnt ;1 [-16] -  
471 usbSendX3: ;0 [-16] -  
472 ldi YL, 20 ;1 [-15] 'x3' is R20 -  
473 ldi YH, 0 ;1 [-14] -  
474 ldi cnt, 2 ;1 [-13] -  
475 ; rjmp usbSendAndReti fallthrough -  
476   -  
477 ; USB spec says: -  
478 ; idle = J -  
479 ; J = (D+ = 0), (D- = 1) or USBOUT = 0x01 -  
480 ; K = (D+ = 1), (D- = 0) or USBOUT = 0x02 -  
481 ; Spec allows 7.5 bit times from EOP to SOP for replies (= 60 cycles) -  
482   -  
483 ;usbSend: -  
484 ;pointer to data in 'Y' -  
485 ;number of bytes in 'cnt' -- including sync byte -  
486 ;uses: x1...x4, shift, cnt, Y -  
487 ;Numbers in brackets are time since first bit of sync pattern is sent -  
488 usbSendAndReti: ;0 [-13] timing: 13 cycles until SOP -  
489 in x2, USBDDR ;1 [-12] -  
490 ori x2, USBMASK ;1 [-11] -  
491 sbi USBOUT, USBMINUS;2 [-9] prepare idle state; D+ and D- must have been 0 (no pullups) -  
492 in x1, USBOUT ;1 [-8] port mirror for tx loop -  
493 out USBDDR, x2 ;1 [-7] <- acquire bus -  
494 ; need not init x2 (bitstuff history) because sync starts with 0 -  
495 push x4 ;2 [-5] -  
496 ldi x4, USBMASK ;1 [-4] exor mask -  
497 ldi shift, 0x80 ;1 [-3] sync byte is first byte sent -  
498 txLoop: ; [62] -  
499 sbrs shift, 0 ;1 [-2] [62] -  
500 eor x1, x4 ;1 [-1] [63] -  
501 out USBOUT, x1 ;1 [0] <-- out bit 0 -  
502 ror shift ;1 [1] -  
503 ror x2 ;1 [2] -  
504 didStuff0: -  
505 cpi x2, 0xfc ;1 [3] -  
506 brsh bitstuff0 ;1 [4] -  
507 sbrs shift, 0 ;1 [5] -  
508 eor x1, x4 ;1 [6] -  
509 ror shift ;1 [7] -  
510 didStuff1: -  
511 out USBOUT, x1 ;1 [8] <-- out bit 1 -  
512 ror x2 ;1 [9] -  
513 cpi x2, 0xfc ;1 [10] -  
514 brsh bitstuff1 ;1 [11] -  
515 sbrs shift, 0 ;1 [12] -  
516 eor x1, x4 ;1 [13] -  
517 ror shift ;1 [14] -  
518 didStuff2: -  
519 ror x2 ;1 [15] -  
520 out USBOUT, x1 ;1 [16] <-- out bit 2 -  
521 cpi x2, 0xfc ;1 [17] -  
522 brsh bitstuff2 ;1 [18] -  
523 sbrs shift, 0 ;1 [19] -  
524 eor x1, x4 ;1 [20] -  
525 ror shift ;1 [21] -  
526 didStuff3: -  
527 ror x2 ;1 [22] -  
528 cpi x2, 0xfc ;1 [23] -  
529 out USBOUT, x1 ;1 [24] <-- out bit 3 -  
530 brsh bitstuff3 ;1 [25] -  
531 nop2 ;2 [27] -  
532 ld x3, y+ ;2 [29] -  
533 sbrs shift, 0 ;1 [30] -  
534 eor x1, x4 ;1 [31] -  
535 out USBOUT, x1 ;1 [32] <-- out bit 4 -  
536 ror shift ;1 [33] -  
537 ror x2 ;1 [34] -  
538 didStuff4: -  
539 cpi x2, 0xfc ;1 [35] -  
540 brsh bitstuff4 ;1 [36] -  
541 sbrs shift, 0 ;1 [37] -  
542 eor x1, x4 ;1 [38] -  
543 ror shift ;1 [39] -  
544 didStuff5: -  
545 out USBOUT, x1 ;1 [40] <-- out bit 5 -  
546 ror x2 ;1 [41] 82 #define usbTxBuf1 (usbTxStatus1 + 1)
547 cpi x2, 0xfc ;1 [42] -  
548 brsh bitstuff5 ;1 [43] -  
549 sbrs shift, 0 ;1 [44] -  
550 eor x1, x4 ;1 [45] -  
551 ror shift ;1 [46] -  
552 didStuff6: -  
553 ror x2 ;1 [47] -  
554 out USBOUT, x1 ;1 [48] <-- out bit 6 -  
555 cpi x2, 0xfc ;1 [49] -  
556 brsh bitstuff6 ;1 [50] -  
557 sbrs shift, 0 ;1 [51] -  
558 eor x1, x4 ;1 [52] -  
559 ror shift ;1 [53] -  
560 didStuff7: -  
561 ror x2 ;1 [54] -  
562 cpi x2, 0xfc ;1 [55] -  
563 out USBOUT, x1 ;1 [56] <-- out bit 7 -  
564 brsh bitstuff7 ;1 [57] -  
565 mov shift, x3 ;1 [58] -  
566 dec cnt ;1 [59] 83 #define usbTxLen3 usbTxStatus3
567 brne txLoop ;1/2 [60/61] 84 #define usbTxBuf3 (usbTxStatus3 + 1)
568 ;make SE0: -  
569 cbr x1, USBMASK ;1 [61] prepare SE0 [spec says EOP may be 15 to 18 cycles] -  
570 pop x4 ;2 [63] -  
571 ;brackets are cycles from start of SE0 now -  
572 out USBOUT, x1 ;1 [0] <-- out SE0 -- from now 2 bits = 16 cycles until bus idle -  
573 nop2 ;2 [2] -  
574 ;2006-03-06: moved transfer of new address to usbDeviceAddr from C-Code to asm: -  
575 ;set address only after data packet was sent, not after handshake -  
576 lds x2, usbNewDeviceAddr;2 [4] -  
577 subi YL, 20 + 2 ;1 [5] -  
578 sbci YH, 0 ;1 [6] -  
579 breq skipAddrAssign ;2 [8] -  
580 sts usbDeviceAddr, x2;0 if not skipped: SE0 is one cycle longer -  
581 skipAddrAssign: -  
582 ;end of usbDeviceAddress transfer -  
583 ldi x2, 1<<USB_INTR_PENDING_BIT;1 [9] int0 occurred during TX -- clear pending flag -  
584 out USB_INTR_PENDING, x2;1 [10] -  
585 ori x1, USBIDLE ;1 [11] -  
586 in x2, USBDDR ;1 [12] -  
587 cbr x2, USBMASK ;1 [13] set both pins to input -  
588 mov x3, x1 ;1 [14] -  
589 cbr x3, USBMASK ;1 [15] configure no pullup on both pins -  
590 out USBOUT, x1 ;1 [16] <-- out J (idle) -- end of SE0 (EOP signal) -  
591 out USBDDR, x2 ;1 [17] <-- release bus now -  
592 out USBOUT, x3 ;1 [18] <-- ensure no pull-up resistors are active -  
593 rjmp doReturn -  
594   -  
595 bitstuff5: ;1 (for branch taken) -  
596 eor x1, x4 ;1 -  
597 rjmp didStuff5 ;2 same trick as above... -  
598 bitstuff6: ;1 (for branch taken) -  
599 eor x1, x4 ;1 -  
600 rjmp didStuff6 ;2 same trick as above... -  
601 bitstuff7: ;1 (for branch taken) -  
602 eor x1, x4 ;1 -  
603 rjmp didStuff7 ;2 same trick as above... -  
604   85  
605   86  
606 ;---------------------------------------------------------------------------- 87 ;----------------------------------------------------------------------------
607 ; Utility functions 88 ; Utility functions
608 ;---------------------------------------------------------------------------- 89 ;----------------------------------------------------------------------------
Line 659... Line 140...
659 # define polyH r21 140 # define polyH r21
660 # define scratch r23 141 # define scratch r23
661   142  
662 #endif 143 #endif
663   144  
-   145 #if USB_USE_FAST_CRC
-   146  
-   147 ; This implementation is faster, but has bigger code size
-   148 ; Thanks to Slawomir Fras (BoskiDialer) for this code!
-   149 ; It implements the following C pseudo-code:
-   150 ; unsigned table(unsigned char x)
-   151 ; {
-   152 ; unsigned value;
-   153 ;
-   154 ; value = (unsigned)x << 6;
-   155 ; value ^= (unsigned)x << 7;
-   156 ; if(parity(x))
-   157 ; value ^= 0xc001;
-   158 ; return value;
-   159 ; }
-   160 ; unsigned usbCrc16(unsigned char *argPtr, unsigned char argLen)
-   161 ; {
-   162 ; unsigned crc = 0xffff;
-   163 ;
-   164 ; while(argLen--)
-   165 ; crc = table(lo8(crc) ^ *argPtr++) ^ hi8(crc);
-   166 ; return ~crc;
-   167 ; }
-   168  
664 ; extern unsigned usbCrc16(unsigned char *data, unsigned char len); 169 ; extern unsigned usbCrc16(unsigned char *argPtr, unsigned char argLen);
-   170 ; argPtr r24+25 / r16+r17
-   171 ; argLen r22 / r18
-   172 ; temp variables:
-   173 ; byte r18 / r22
665 ; data: r24/25 174 ; scratch r23
-   175 ; resCrc r24+r25 / r16+r17
-   176 ; ptr X / Z
-   177 usbCrc16:
-   178 mov ptrL, argPtrL
-   179 mov ptrH, argPtrH
-   180 ldi resCrcL, 0xFF
-   181 ldi resCrcH, 0xFF
-   182 rjmp usbCrc16LoopTest
-   183 usbCrc16ByteLoop:
-   184 ld byte, ptr+
-   185 eor resCrcL, byte ; resCrcL is now 'x' in table()
-   186 mov byte, resCrcL ; compute parity of 'x'
-   187 swap byte
-   188 eor byte, resCrcL
-   189 mov scratch, byte
-   190 lsr byte
-   191 lsr byte
-   192 eor byte, scratch
-   193 inc byte
-   194 lsr byte
-   195 andi byte, 1 ; byte is now parity(x)
-   196 mov scratch, resCrcL
-   197 mov resCrcL, resCrcH
-   198 eor resCrcL, byte ; low byte of if(parity(x)) value ^= 0xc001;
-   199 neg byte
-   200 andi byte, 0xc0
-   201 mov resCrcH, byte ; high byte of if(parity(x)) value ^= 0xc001;
-   202 clr byte
-   203 lsr scratch
-   204 ror byte
-   205 eor resCrcH, scratch
-   206 eor resCrcL, byte
-   207 lsr scratch
-   208 ror byte
-   209 eor resCrcH, scratch
-   210 eor resCrcL, byte
-   211 usbCrc16LoopTest:
-   212 subi argLen, 1
-   213 brsh usbCrc16ByteLoop
-   214 com resCrcL
-   215 com resCrcH
666 ; len: r22 216 ret
-   217  
-   218 #else /* USB_USE_FAST_CRC */
-   219  
-   220 ; This implementation is slower, but has less code size
-   221 ;
-   222 ; extern unsigned usbCrc16(unsigned char *argPtr, unsigned char argLen);
-   223 ; argPtr r24+25 / r16+r17
-   224 ; argLen r22 / r18
667 ; temp variables: 225 ; temp variables:
668 ; r18: data byte 226 ; byte r18 / r22
669 ; r19: bit counter 227 ; bitCnt r19
670 ; r20/21: polynomial 228 ; poly r20+r21
671 ; r23: scratch 229 ; scratch r23
672 ; r24/25: crc-sum 230 ; resCrc r24+r25 / r16+r17
673 ; r26/27=X: ptr 231 ; ptr X / Z
674 usbCrc16: 232 usbCrc16:
675 mov ptrL, argPtrL 233 mov ptrL, argPtrL
676 mov ptrH, argPtrH 234 mov ptrH, argPtrH
677 ldi resCrcL, 0xff 235 ldi resCrcL, 0
678 ldi resCrcH, 0xff 236 ldi resCrcH, 0
679 ldi polyL, lo8(0xa001) 237 ldi polyL, lo8(0xa001)
680 ldi polyH, hi8(0xa001) 238 ldi polyH, hi8(0xa001)
-   239 com argLen ; argLen = -argLen - 1: modified loop to ensure that carry is set
681 crcByteLoop: 240 ldi bitCnt, 0 ; loop counter with starnd condition = end condition
682 subi argLen, 1 241 rjmp usbCrcLoopEntry
683 brcs crcReady 242 usbCrcByteLoop:
684 ld byte, ptr+ 243 ld byte, ptr+
685 ldi bitCnt, 8 244 eor resCrcL, byte
686 crcBitLoop: 245 usbCrcBitLoop:
687 mov scratch, byte -  
688 eor scratch, resCrcL 246 ror resCrcH ; carry is always set here (see brcs jumps to here)
689 lsr resCrcH -  
690 ror resCrcL 247 ror resCrcL
691 lsr byte -  
692 sbrs scratch, 0 -  
693 rjmp crcNoXor 248 brcs usbCrcNoXor
694 eor resCrcL, polyL 249 eor resCrcL, polyL
695 eor resCrcH, polyH 250 eor resCrcH, polyH
696 crcNoXor: 251 usbCrcNoXor:
-   252 subi bitCnt, 224 ; (8 * 224) % 256 = 0; this loop iterates 8 times
697 dec bitCnt 253 brcs usbCrcBitLoop
-   254 usbCrcLoopEntry:
698 brne crcBitLoop 255 subi argLen, -1
699 rjmp crcByteLoop 256 brcs usbCrcByteLoop
700 crcReady: 257 usbCrcReady:
701 com resCrcL -  
702 com resCrcH -  
703 ret 258 ret
-   259 ; Thanks to Reimar Doeffinger for optimizing this CRC routine!
-   260  
-   261 #endif /* USB_USE_FAST_CRC */
704   262  
705 ; extern unsigned usbCrc16Append(unsigned char *data, unsigned char len); 263 ; extern unsigned usbCrc16Append(unsigned char *data, unsigned char len);
706 usbCrc16Append: 264 usbCrc16Append:
707 rcall usbCrc16 265 rcall usbCrc16
708 st ptr+, resCrcL 266 st ptr+, resCrcL
709 st ptr+, resCrcH 267 st ptr+, resCrcH
710 ret 268 ret
-   269  
-   270 #undef argLen
-   271 #undef argPtrL
-   272 #undef argPtrH
-   273 #undef resCrcL
-   274 #undef resCrcH
-   275 #undef ptrL
-   276 #undef ptrH
-   277 #undef ptr
-   278 #undef byte
-   279 #undef bitCnt
-   280 #undef polyL
-   281 #undef polyH
-   282 #undef scratch
-   283  
-   284  
-   285 #if USB_CFG_HAVE_MEASURE_FRAME_LENGTH
-   286 #ifdef __IAR_SYSTEMS_ASM__
-   287 /* Register assignments for usbMeasureFrameLength on IAR cc */
-   288 /* Calling conventions on IAR:
-   289 * First parameter passed in r16/r17, second in r18/r19 and so on.
-   290 * Callee must preserve r4-r15, r24-r29 (r28/r29 is frame pointer)
-   291 * Result is passed in r16/r17
-   292 * In case of the "tiny" memory model, pointers are only 8 bit with no
-   293 * padding. We therefore pass argument 1 as "16 bit unsigned".
-   294 */
-   295 # define resL r16
-   296 # define resH r17
-   297 # define cnt16L r30
-   298 # define cnt16H r31
-   299 # define cntH r18
-   300  
-   301 #else /* __IAR_SYSTEMS_ASM__ */
-   302 /* Register assignments for usbMeasureFrameLength on gcc */
-   303 /* Calling conventions on gcc:
-   304 * First parameter passed in r24/r25, second in r22/23 and so on.
-   305 * Callee must preserve r1-r17, r28/r29
-   306 * Result is passed in r24/r25
-   307 */
-   308 # define resL r24
-   309 # define resH r25
-   310 # define cnt16L r24
-   311 # define cnt16H r25
-   312 # define cntH r26
-   313 #endif
-   314 # define cnt16 cnt16L
-   315  
-   316 ; extern unsigned usbMeasurePacketLength(void);
-   317 ; returns time between two idle strobes in multiples of 7 CPU clocks
-   318 .global usbMeasureFrameLength
-   319 usbMeasureFrameLength:
-   320 ldi cntH, 6 ; wait ~ 10 ms for D- == 0
-   321 clr cnt16L
-   322 clr cnt16H
-   323 usbMFTime16:
-   324 dec cntH
-   325 breq usbMFTimeout
-   326 usbMFWaitStrobe: ; first wait for D- == 0 (idle strobe)
-   327 sbiw cnt16, 1 ;[0] [6]
-   328 breq usbMFTime16 ;[2]
-   329 sbic USBIN, USBMINUS ;[3]
-   330 rjmp usbMFWaitStrobe ;[4]
-   331 usbMFWaitIdle: ; then wait until idle again
-   332 sbis USBIN, USBMINUS ;1 wait for D- == 1
-   333 rjmp usbMFWaitIdle ;2
-   334 ldi cnt16L, 1 ;1 represents cycles so far
-   335 clr cnt16H ;1
-   336 usbMFWaitLoop:
-   337 in cntH, USBIN ;[0] [7]
-   338 adiw cnt16, 1 ;[1]
-   339 breq usbMFTimeout ;[3]
-   340 andi cntH, USBMASK ;[4]
-   341 brne usbMFWaitLoop ;[5]
-   342 usbMFTimeout:
-   343 #if resL != cnt16L
-   344 mov resL, cnt16L
-   345 mov resH, cnt16H
-   346 #endif
-   347 ret
-   348  
-   349 #undef resL
-   350 #undef resH
-   351 #undef cnt16
-   352 #undef cnt16L
-   353 #undef cnt16H
-   354 #undef cntH
-   355  
-   356 #endif /* USB_CFG_HAVE_MEASURE_FRAME_LENGTH */
-   357  
-   358 ;----------------------------------------------------------------------------
-   359 ; Now include the clock rate specific code
-   360 ;----------------------------------------------------------------------------
-   361  
-   362 #ifndef USB_CFG_CLOCK_KHZ
-   363 # ifdef F_CPU
-   364 # define USB_CFG_CLOCK_KHZ (F_CPU/1000)
-   365 # else
-   366 # error "USB_CFG_CLOCK_KHZ not defined in usbconfig.h and no F_CPU set!"
-   367 # endif
-   368 #endif
-   369  
-   370 #if USB_CFG_CHECK_CRC /* separate dispatcher for CRC type modules */
-   371 # if USB_CFG_CLOCK_KHZ == 18000
-   372 # include "usbdrvasm18-crc.inc"
-   373 # else
-   374 # error "USB_CFG_CLOCK_KHZ is not one of the supported crc-rates!"
-   375 # endif
-   376 #else /* USB_CFG_CHECK_CRC */
-   377 # if USB_CFG_CLOCK_KHZ == 12000
-   378 # include "usbdrvasm12.inc"
-   379 # elif USB_CFG_CLOCK_KHZ == 12800
-   380 # include "usbdrvasm128.inc"
-   381 # elif USB_CFG_CLOCK_KHZ == 15000
-   382 # include "usbdrvasm15.inc"
-   383 # elif USB_CFG_CLOCK_KHZ == 16000
-   384 # include "usbdrvasm16.inc"
-   385 # elif USB_CFG_CLOCK_KHZ == 16500
-   386 # include "usbdrvasm165.inc"
-   387 # elif USB_CFG_CLOCK_KHZ == 20000
-   388 # include "usbdrvasm20.inc"
-   389 # else
-   390 # error "USB_CFG_CLOCK_KHZ is not one of the supported non-crc-rates!"
-   391 # endif
-   392 #endif /* USB_CFG_CHECK_CRC */