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

📄 asmcommon.inc

📁 AVR单片机模拟USB代码.可实现中断,控制传输,低速设备
💻 INC
字号:
/* Name: asmcommon.inc * Project: AVR USB driver * Author: Christian Starkjohann * Creation Date: 2007-11-05 * Tabsize: 4 * Copyright: (c) 2007 by OBJECTIVE DEVELOPMENT Software GmbH * License: GNU GPL v2 (see License.txt) or proprietary (CommercialLicense.txt) * Revision: $Id$ *//* Do not link this file! Link usbdrvasm.S instead, which includes the * appropriate implementation! *//*General Description:This file contains assembler code which is shared among the USB driverimplementations for different CPU cocks. Since the code must be insertedin the middle of the module, it's split out into this file and #included.Jump destinations called from outside:    sofError: Called when no start sequence was found.    se0: Called when a package has been successfully received.    overflow: Called when receive buffer overflows.    doReturn: Called after sending data.Outside jump destinations used by this module:    waitForJ: Called to receive an already arriving packet.    sendAckAndReti:    sendNakAndReti:    sendCntAndReti:    usbSendAndReti:The following macros must be defined before this file is included:    .macro POP_STANDARD    .endm    .macro POP_RETI    .endm*/#define token   x1overflow:    ldi     x2, 1<<USB_INTR_PENDING_BIT    USB_STORE_PENDING(x2)       ; clear any pending interruptsignorePacket:    clr     token    rjmp    storeTokenAndReturn;----------------------------------------------------------------------------; Processing of received packet (numbers in brackets are cycles after center 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.se0:    subi    cnt, USB_BUFSIZE    ;[5]    neg     cnt                 ;[6]    sub     YL, cnt             ;[7]    sbci    YH, 0               ;[8]    ldi     x2, 1<<USB_INTR_PENDING_BIT ;[9]    USB_STORE_PENDING(x2)       ;[10] clear pending intr and check flag later. SE0 should be over.    ld      token, y            ;[11]    cpi     token, USBPID_DATA0 ;[13]    breq    handleData          ;[14]    cpi     token, USBPID_DATA1 ;[15]    breq    handleData          ;[16]    lds     shift, usbDeviceAddr;[17]    ldd     x2, y+1             ;[19] ADDR and 1 bit endpoint number    lsl     x2                  ;[21] shift out 1 bit endpoint number    cpse    x2, shift           ;[22]    rjmp    ignorePacket        ;[23]/* only compute endpoint number in x3 if required later */#if USB_CFG_HAVE_INTRIN_ENDPOINT || USB_CFG_IMPLEMENT_FN_WRITEOUT    ldd     x3, y+2             ;[24] endpoint number + crc    rol     x3                  ;[26] shift in LSB of endpoint#endif    cpi     token, USBPID_IN    ;[27]    breq    handleIn            ;[28]    cpi     token, USBPID_SETUP ;[29]    breq    handleSetupOrOut    ;[30]    cpi     token, USBPID_OUT   ;[31]    brne    ignorePacket        ;[32] must be ack, nak or whatever;   rjmp    handleSetupOrOut    ; fallthrough;Setup and Out are followed by a data packet two bit times (16 cycles) after;the end of SE0. The sync code allows up to 40 cycles delay from the start of;the sync pattern until the first bit is sampled. That's a total of 56 cycles.handleSetupOrOut:               ;[32]#if USB_CFG_IMPLEMENT_FN_WRITEOUT   /* if we have data for endpoint != 0, set usbCurrentTok to address */    andi    x3, 0xf             ;[32]    breq    storeTokenAndReturn ;[33]    mov     token, x3           ;[34] indicate that this is endpoint x OUT#endifstoreTokenAndReturn:    sts     usbCurrentTok, token;[35]doReturn:    POP_STANDARD                ;[37] 12...16 cycles    USB_LOAD_PENDING(YL)        ;[49]    sbrc    YL, USB_INTR_PENDING_BIT;[50] check whether data is already arriving    rjmp    waitForJ            ;[51] save the pops and pushes -- a new interrupt is already pendingsofError:    POP_RETI                    ;macro call    retihandleData:    lds     token, usbCurrentTok;[18]    tst     token               ;[20]    breq    doReturn            ;[21]    lds     x2, usbRxLen        ;[22]    tst     x2                  ;[24]    brne    sendNakAndReti      ;[25]; 2006-03-11: The following two lines fix a problem where the device was not; recognized if usbPoll() was called less frequently than once every 4 ms.    cpi     cnt, 4              ;[26] zero sized data packets are status phase only -- ignore and ack    brmi    sendAckAndReti      ;[27] keep rx buffer clean -- we must not NAK next SETUP    sts     usbRxLen, cnt       ;[28] store received data, swap buffers    sts     usbRxToken, token   ;[30]    lds     x2, usbInputBufOffset;[32] swap buffers    ldi     cnt, USB_BUFSIZE    ;[34]    sub     cnt, x2             ;[35]    sts     usbInputBufOffset, cnt;[36] buffers now swapped    rjmp    sendAckAndReti      ;[38] 40 + 17 = 57 until SOPhandleIn:;We don't send any data as long as the C code has not processed the current;input data and potentially updated the output data. That's more efficient;in terms of code size than clearing the tx buffers when a packet is received.    lds     x1, usbRxLen        ;[30]    cpi     x1, 1               ;[32] negative values are flow control, 0 means "buffer free"    brge    sendNakAndReti      ;[33] unprocessed input packet?    ldi     x1, USBPID_NAK      ;[34] prepare value for usbTxLen#if USB_CFG_HAVE_INTRIN_ENDPOINT    andi    x3, 0xf             ;[35] x3 contains endpoint    brne    handleIn1           ;[36]#endif    lds     cnt, usbTxLen       ;[37]    sbrc    cnt, 4              ;[39] all handshake tokens have bit 4 set    rjmp    sendCntAndReti      ;[40] 42 + 16 = 58 until SOP    sts     usbTxLen, x1        ;[41] x1 == USBPID_NAK from above    ldi     YL, lo8(usbTxBuf)   ;[43]    ldi     YH, hi8(usbTxBuf)   ;[44]    rjmp    usbSendAndReti      ;[45] 57 + 12 = 59 until SOP; Comment about when to set usbTxLen to USBPID_NAK:; We should set it back when we receive the ACK from the host. This would; be simple to implement: One static variable which stores whether the last; tx was for endpoint 0 or 1 and a compare in the receiver to distinguish the; ACK. However, we set it back immediately when we send the package,; assuming that no error occurs and the host sends an ACK. We save one byte; RAM this way and avoid potential problems with endless retries. The rest of; the driver assumes error-free transfers anyway.#if USB_CFG_HAVE_INTRIN_ENDPOINT    /* placed here due to relative jump range */handleIn1:                      ;[38]#if USB_CFG_HAVE_INTRIN_ENDPOINT3; 2006-06-10 as suggested by O.Tamura: support second INTR IN / BULK IN endpoint    cpi     x3, USB_CFG_EP3_NUMBER;[38]    breq    handleIn3           ;[39]#endif    lds     cnt, usbTxLen1      ;[40]    sbrc    cnt, 4              ;[42] all handshake tokens have bit 4 set    rjmp    sendCntAndReti      ;[43] 47 + 16 = 63 until SOP    sts     usbTxLen1, x1       ;[44] x1 == USBPID_NAK from above    ldi     YL, lo8(usbTxBuf1)  ;[46]    ldi     YH, hi8(usbTxBuf1)  ;[47]    rjmp    usbSendAndReti      ;[48] 50 + 12 = 62 until SOP#endif#if USB_CFG_HAVE_INTRIN_ENDPOINT && USB_CFG_HAVE_INTRIN_ENDPOINT3handleIn3:    lds     cnt, usbTxLen3      ;[41]    sbrc    cnt, 4              ;[43]    rjmp    sendCntAndReti      ;[44] 49 + 16 = 65 until SOP    sts     usbTxLen3, x1       ;[45] x1 == USBPID_NAK from above    ldi     YL, lo8(usbTxBuf3)  ;[47]    ldi     YH, hi8(usbTxBuf3)  ;[48]    rjmp    usbSendAndReti      ;[49] 51 + 12 = 63 until SOP#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -