⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 usbdrvasm12.s

📁 AVRUSBIR红外遥控器信号波形显示器
💻 S
📖 第 1 页 / 共 2 页
字号:
/* 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 + -