?? usbdrvasm12.s
字號:
/* 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. Itrequires a 12 MHz crystal (not a ceramic resonator and not a calibrated RCoscillator).See usbdrv.h for a description of the entire driver.Since almost all of this code is timing critical, don't change unless youreally know what you are doing! Many parts require not only a maximum numberof 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-128EOP of IN to sync pattern of DATA0 (rx, then tx) 2 7.5 16-60DATAx (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 ;2waitForK:;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 sofErrorfoundK:;{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, retryhaveTwoBitsK:;----------------------------------------------------------------------------; 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, eorrxLoop: 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 1didUnstuff1: 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 controlunstuff7: 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 x1se0: ; [0] subi cnt, USB_BUFSIZE ;1 [1] neg cnt ;1 [2] cpi cnt, 3 ;1 [3] ldi x2, 1<<USB_INTR_PENDING_BIT ;1 [4] out USB_INTR_PENDING, x2;1 [5] clear pending intr and check flag later. SE0 should be over. brlo doReturn ;1 [6] this is probably an ACK, NAK or similar packet sub YL, cnt ;1 [7] sbci YH, 0 ;1 [8] ld token, y ;2 [10] cpi token, USBPID_DATA0 ;1 [11] breq handleData ;1 [12] cpi token, USBPID_DATA1 ;1 [13] breq handleData ;1 [14] ldd x2, y+1 ;2 [16] ADDR and 1 bit endpoint number mov x3, x2 ;1 [17] store for endpoint number andi x2, 0x7f ;1 [18] x2 is now ADDR lds shift, usbDeviceAddr;2 [20] cp x2, shift ;1 [21]overflow: ; This is a hack: brcs overflow will never have Z flag set brne ignorePacket ;1 [22] packet for different address cpi token, USBPID_IN ;1 [23] breq handleIn ;1 [24] cpi token, USBPID_SETUP ;1 [25] breq handleSetupOrOut ;1 [26] cpi token, USBPID_OUT ;1 [27] breq handleSetupOrOut ;1 [28]; rjmp ignorePacket ;fallthrough, should not happen anyway.ignorePacket: clr shift sts usbCurrentTok, shift
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -