X-Git-Url: http://git.linex4red.de/pub/USBasp.git/blobdiff_plain/6764e064effd480d2843a1bd049623bec555ab28..77fd24511771873c246c56518e77f1aedde9f0b8:/firmware/usbdrv/usbdrvasm12.S diff --git a/firmware/usbdrv/usbdrvasm12.S b/firmware/usbdrv/usbdrvasm12.S new file mode 100644 index 000000000..b141e85e8 --- /dev/null +++ b/firmware/usbdrv/usbdrvasm12.S @@ -0,0 +1,555 @@ +/* Name: usbdrvasm12.S + * Project: AVR USB driver + * Author: Christian Starkjohann + * Creation Date: 2004-12-29 + * Tabsize: 4 + * Copyright: (c) 2007 by OBJECTIVE DEVELOPMENT Software GmbH + * License: GNU GPL v2 (see License.txt) or proprietary (CommercialLicense.txt) + * This Revision: $Id: usbdrvasm12.S 353 2007-06-21 19:05:08Z cs $ + */ + +/* Do not link this file! Link usbdrvasm.S instead, which includes the + * appropriate implementation! + */ + +/* +General Description: +This file is the 12 MHz version of the asssembler part of the USB driver. It +requires a 12 MHz crystal (not a ceramic resonator and not a calibrated RC +oscillator). + +See usbdrv.h for a description of the entire driver. + +Since almost all of this code is timing critical, don't change unless you +really know what you are doing! Many parts require not only a maximum number +of CPU cycles, but even an exact number of cycles! + + +Timing constraints according to spec (in bit times): +timing subject min max CPUcycles +--------------------------------------------------------------------------- +EOP of OUT/SETUP to sync pattern of DATA0 (both rx) 2 16 16-128 +EOP of IN to sync pattern of DATA0 (rx, then tx) 2 7.5 16-60 +DATAx (rx) to ACK/NAK/STALL (tx) 2 7.5 16-60 +*/ + +;Software-receiver engine. Strict timing! Don't change unless you can preserve timing! +;interrupt response time: 4 cycles + insn running = 7 max if interrupts always enabled +;max allowable interrupt latency: 34 cycles -> max 25 cycles interrupt disable +;max stack usage: [ret(2), YL, SREG, YH, shift, x1, x2, x3, cnt, x4] = 11 bytes +;Numbers in brackets are maximum cycles since SOF. +SIG_INTERRUPT0: +;order of registers pushed: YL, SREG [sofError], YH, shift, x1, x2, x3, cnt + push YL ;2 [35] push only what is necessary to sync with edge ASAP + in YL, SREG ;1 [37] + push YL ;2 [39] +;---------------------------------------------------------------------------- +; Synchronize with sync pattern: +;---------------------------------------------------------------------------- +;sync byte (D-) pattern LSb to MSb: 01010100 [1 = idle = J, 0 = K] +;sync up with J to K edge during sync pattern -- use fastest possible loops +;first part has no timeout because it waits for IDLE or SE1 (== disconnected) +waitForJ: + sbis USBIN, USBMINUS ;1 [40] wait for D- == 1 + rjmp waitForJ ;2 +waitForK: +;The following code results in a sampling window of 1/4 bit which meets the spec. + sbis USBIN, USBMINUS + rjmp foundK + sbis USBIN, USBMINUS + rjmp foundK + sbis USBIN, USBMINUS + rjmp foundK + sbis USBIN, USBMINUS + rjmp foundK + sbis USBIN, USBMINUS + rjmp foundK + rjmp sofError +foundK: +;{3, 5} after falling D- edge, average delay: 4 cycles [we want 4 for center sampling] +;we have 1 bit time for setup purposes, then sample again. Numbers in brackets +;are cycles from center of first sync (double K) bit after the instruction + push YH ;2 [2] + lds YL, usbInputBufOffset;2 [4] + clr YH ;1 [5] + subi YL, lo8(-(usbRxBuf));1 [6] + sbci YH, hi8(-(usbRxBuf));1 [7] + + sbis USBIN, USBMINUS ;1 [8] we want two bits K [sample 1 cycle too early] + rjmp haveTwoBitsK ;2 [10] + pop YH ;2 [11] undo the push from before + rjmp waitForK ;2 [13] this was not the end of sync, retry +haveTwoBitsK: +;---------------------------------------------------------------------------- +; push more registers and initialize values while we sample the first bits: +;---------------------------------------------------------------------------- + push shift ;2 [16] + push x1 ;2 [12] + push x2 ;2 [14] + + in x1, USBIN ;1 [17] <-- sample bit 0 + ldi shift, 0xff ;1 [18] + bst x1, USBMINUS ;1 [19] + bld shift, 0 ;1 [20] + push x3 ;2 [22] + push cnt ;2 [24] + + in x2, USBIN ;1 [25] <-- sample bit 1 + ser x3 ;1 [26] [inserted init instruction] + eor x1, x2 ;1 [27] + bst x1, USBMINUS ;1 [28] + bld shift, 1 ;1 [29] + ldi cnt, USB_BUFSIZE;1 [30] [inserted init instruction] + rjmp rxbit2 ;2 [32] + +;---------------------------------------------------------------------------- +; Receiver loop (numbers in brackets are cycles within byte after instr) +;---------------------------------------------------------------------------- + +unstuff0: ;1 (branch taken) + andi x3, ~0x01 ;1 [15] + mov x1, x2 ;1 [16] x2 contains last sampled (stuffed) bit + in x2, USBIN ;1 [17] <-- sample bit 1 again + ori shift, 0x01 ;1 [18] + rjmp didUnstuff0 ;2 [20] + +unstuff1: ;1 (branch taken) + mov x2, x1 ;1 [21] x1 contains last sampled (stuffed) bit + andi x3, ~0x02 ;1 [22] + ori shift, 0x02 ;1 [23] + nop ;1 [24] + in x1, USBIN ;1 [25] <-- sample bit 2 again + rjmp didUnstuff1 ;2 [27] + +unstuff2: ;1 (branch taken) + andi x3, ~0x04 ;1 [29] + ori shift, 0x04 ;1 [30] + mov x1, x2 ;1 [31] x2 contains last sampled (stuffed) bit + nop ;1 [32] + in x2, USBIN ;1 [33] <-- sample bit 3 + rjmp didUnstuff2 ;2 [35] + +unstuff3: ;1 (branch taken) + in x2, USBIN ;1 [34] <-- sample stuffed bit 3 [one cycle too late] + andi x3, ~0x08 ;1 [35] + ori shift, 0x08 ;1 [36] + rjmp didUnstuff3 ;2 [38] + +unstuff4: ;1 (branch taken) + andi x3, ~0x10 ;1 [40] + in x1, USBIN ;1 [41] <-- sample stuffed bit 4 + ori shift, 0x10 ;1 [42] + rjmp didUnstuff4 ;2 [44] + +unstuff5: ;1 (branch taken) + andi x3, ~0x20 ;1 [48] + in x2, USBIN ;1 [49] <-- sample stuffed bit 5 + ori shift, 0x20 ;1 [50] + rjmp didUnstuff5 ;2 [52] + +unstuff6: ;1 (branch taken) + andi x3, ~0x40 ;1 [56] + in x1, USBIN ;1 [57] <-- sample stuffed bit 6 + ori shift, 0x40 ;1 [58] + rjmp didUnstuff6 ;2 [60] + +; extra jobs done during bit interval: +; bit 0: store, clear [SE0 is unreliable here due to bit dribbling in hubs] +; bit 1: se0 check +; bit 2: overflow check +; bit 3: recovery from delay [bit 0 tasks took too long] +; bit 4: none +; bit 5: none +; bit 6: none +; bit 7: jump, eor +rxLoop: + eor x3, shift ;1 [0] reconstruct: x3 is 0 at bit locations we changed, 1 at others + in x1, USBIN ;1 [1] <-- sample bit 0 + st y+, x3 ;2 [3] store data + ser x3 ;1 [4] + nop ;1 [5] + eor x2, x1 ;1 [6] + bst x2, USBMINUS;1 [7] + bld shift, 0 ;1 [8] + in x2, USBIN ;1 [9] <-- sample bit 1 (or possibly bit 0 stuffed) + andi x2, USBMASK ;1 [10] + breq se0 ;1 [11] SE0 check for bit 1 + andi shift, 0xf9 ;1 [12] +didUnstuff0: + breq unstuff0 ;1 [13] + eor x1, x2 ;1 [14] + bst x1, USBMINUS;1 [15] + bld shift, 1 ;1 [16] +rxbit2: + in x1, USBIN ;1 [17] <-- sample bit 2 (or possibly bit 1 stuffed) + andi shift, 0xf3 ;1 [18] + breq unstuff1 ;1 [19] do remaining work for bit 1 +didUnstuff1: + subi cnt, 1 ;1 [20] + brcs overflow ;1 [21] loop control + eor x2, x1 ;1 [22] + bst x2, USBMINUS;1 [23] + bld shift, 2 ;1 [24] + in x2, USBIN ;1 [25] <-- sample bit 3 (or possibly bit 2 stuffed) + andi shift, 0xe7 ;1 [26] + breq unstuff2 ;1 [27] +didUnstuff2: + eor x1, x2 ;1 [28] + bst x1, USBMINUS;1 [29] + bld shift, 3 ;1 [30] +didUnstuff3: + andi shift, 0xcf ;1 [31] + breq unstuff3 ;1 [32] + in x1, USBIN ;1 [33] <-- sample bit 4 + eor x2, x1 ;1 [34] + bst x2, USBMINUS;1 [35] + bld shift, 4 ;1 [36] +didUnstuff4: + andi shift, 0x9f ;1 [37] + breq unstuff4 ;1 [38] + nop2 ;2 [40] + in x2, USBIN ;1 [41] <-- sample bit 5 + eor x1, x2 ;1 [42] + bst x1, USBMINUS;1 [43] + bld shift, 5 ;1 [44] +didUnstuff5: + andi shift, 0x3f ;1 [45] + breq unstuff5 ;1 [46] + nop2 ;2 [48] + in x1, USBIN ;1 [49] <-- sample bit 6 + eor x2, x1 ;1 [50] + bst x2, USBMINUS;1 [51] + bld shift, 6 ;1 [52] +didUnstuff6: + cpi shift, 0x02 ;1 [53] + brlo unstuff6 ;1 [54] + nop2 ;2 [56] + in x2, USBIN ;1 [57] <-- sample bit 7 + eor x1, x2 ;1 [58] + bst x1, USBMINUS;1 [59] + bld shift, 7 ;1 [60] +didUnstuff7: + cpi shift, 0x04 ;1 [61] + brsh rxLoop ;2 [63] loop control +unstuff7: + andi x3, ~0x80 ;1 [63] + ori shift, 0x80 ;1 [64] + in x2, USBIN ;1 [65] <-- sample stuffed bit 7 + nop ;1 [66] + rjmp didUnstuff7 ;2 [68] + + +;---------------------------------------------------------------------------- +; Processing of received packet (numbers in brackets are cycles after end of SE0) +;---------------------------------------------------------------------------- +;This is the only non-error exit point for the software receiver loop +;we don't check any CRCs here because there is no time left. +#define token x1 +se0: ; [0] + subi cnt, USB_BUFSIZE ;1 [1] + neg cnt ;1 [2] + cpi cnt, 3 ;1 [3] + ldi x2, 1<