| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385 | 
							- /* Name: usbdrvasm.S
 -  * Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers
 -  * Author: Christian Starkjohann
 -  * Creation Date: 2007-06-13
 -  * Tabsize: 4
 -  * Copyright: (c) 2007 by OBJECTIVE DEVELOPMENT Software GmbH
 -  * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
 -  * Revision: $Id: usbdrvasm.S 761 2009-08-12 16:30:23Z cs $
 -  */
 - 
 - /*
 - General Description:
 - This module is the assembler part of the USB driver. This file contains
 - general code (preprocessor acrobatics and CRC computation) and then includes
 - the file appropriate for the given clock rate.
 - */
 - 
 - #define __SFR_OFFSET 0      /* used by avr-libc's register definitions */
 - #include "usbportability.h"
 - #include "usbdrv.h"         /* for common defs */
 - 
 - /* register names */
 - #define x1      r16
 - #define x2      r17
 - #define shift   r18
 - #define cnt     r19
 - #define x3      r20
 - #define x4      r21
 - #define x5		r22
 - #define bitcnt  x5
 - #define phase   x4
 - #define leap    x4
 - 
 - /* Some assembler dependent definitions and declarations: */
 - 
 - #ifdef __IAR_SYSTEMS_ASM__
 -     extern  usbRxBuf, usbDeviceAddr, usbNewDeviceAddr, usbInputBufOffset
 -     extern  usbCurrentTok, usbRxLen, usbRxToken, usbTxLen
 -     extern  usbTxBuf, usbTxStatus1, usbTxStatus3
 - #   if USB_COUNT_SOF
 -         extern usbSofCount
 - #   endif
 -     public  usbCrc16
 -     public  usbCrc16Append
 - 
 -     COMMON  INTVEC
 - #   ifndef USB_INTR_VECTOR
 -         ORG     INT0_vect
 - #   else /* USB_INTR_VECTOR */
 -         ORG     USB_INTR_VECTOR
 - #       undef   USB_INTR_VECTOR
 - #   endif /* USB_INTR_VECTOR */
 - #   define  USB_INTR_VECTOR usbInterruptHandler
 -     rjmp    USB_INTR_VECTOR
 -     RSEG    CODE
 - 
 - #else /* __IAR_SYSTEMS_ASM__ */
 - 
 - #   ifndef USB_INTR_VECTOR /* default to hardware interrupt INT0 */
 - #       define USB_INTR_VECTOR  SIG_INTERRUPT0
 - #   endif
 -     .text
 -     .global USB_INTR_VECTOR
 -     .type   USB_INTR_VECTOR, @function
 -     .global usbCrc16
 -     .global usbCrc16Append
 - #endif /* __IAR_SYSTEMS_ASM__ */
 - 
 - 
 - #if USB_INTR_PENDING < 0x40 /* This is an I/O address, use in and out */
 - #   define  USB_LOAD_PENDING(reg)   in reg, USB_INTR_PENDING
 - #   define  USB_STORE_PENDING(reg)  out USB_INTR_PENDING, reg
 - #else   /* It's a memory address, use lds and sts */
 - #   define  USB_LOAD_PENDING(reg)   lds reg, USB_INTR_PENDING
 - #   define  USB_STORE_PENDING(reg)  sts USB_INTR_PENDING, reg
 - #endif
 - 
 - #define usbTxLen1   usbTxStatus1
 - #define usbTxBuf1   (usbTxStatus1 + 1)
 - #define usbTxLen3   usbTxStatus3
 - #define usbTxBuf3   (usbTxStatus3 + 1)
 - 
 - 
 - ;----------------------------------------------------------------------------
 - ; Utility functions
 - ;----------------------------------------------------------------------------
 - 
 - #ifdef __IAR_SYSTEMS_ASM__
 - /* Register assignments for usbCrc16 on IAR cc */
 - /* Calling conventions on IAR:
 -  * First parameter passed in r16/r17, second in r18/r19 and so on.
 -  * Callee must preserve r4-r15, r24-r29 (r28/r29 is frame pointer)
 -  * Result is passed in r16/r17
 -  * In case of the "tiny" memory model, pointers are only 8 bit with no
 -  * padding. We therefore pass argument 1 as "16 bit unsigned".
 -  */
 - RTMODEL "__rt_version", "3"
 - /* The line above will generate an error if cc calling conventions change.
 -  * The value "3" above is valid for IAR 4.10B/W32
 -  */
 - #   define argLen   r18 /* argument 2 */
 - #   define argPtrL  r16 /* argument 1 */
 - #   define argPtrH  r17 /* argument 1 */
 - 
 - #   define resCrcL  r16 /* result */
 - #   define resCrcH  r17 /* result */
 - 
 - #   define ptrL     ZL
 - #   define ptrH     ZH
 - #   define ptr      Z
 - #   define byte     r22
 - #   define bitCnt   r19
 - #   define polyL    r20
 - #   define polyH    r21
 - #   define scratch  r23
 - 
 - #else  /* __IAR_SYSTEMS_ASM__ */ 
 - /* Register assignments for usbCrc16 on gcc */
 - /* Calling conventions on gcc:
 -  * First parameter passed in r24/r25, second in r22/23 and so on.
 -  * Callee must preserve r1-r17, r28/r29
 -  * Result is passed in r24/r25
 -  */
 - #   define argLen   r22 /* argument 2 */
 - #   define argPtrL  r24 /* argument 1 */
 - #   define argPtrH  r25 /* argument 1 */
 - 
 - #   define resCrcL  r24 /* result */
 - #   define resCrcH  r25 /* result */
 - 
 - #   define ptrL     XL
 - #   define ptrH     XH
 - #   define ptr      x
 - #   define byte     r18
 - #   define bitCnt   r19
 - #   define polyL    r20
 - #   define polyH    r21
 - #   define scratch  r23
 - 
 - #endif
 - 
 - #if USB_USE_FAST_CRC
 - 
 - ; This implementation is faster, but has bigger code size
 - ; Thanks to Slawomir Fras (BoskiDialer) for this code!
 - ; It implements the following C pseudo-code:
 - ; unsigned table(unsigned char x)
 - ; {
 - ; unsigned    value;
 - ; 
 - ;     value = (unsigned)x << 6;
 - ;     value ^= (unsigned)x << 7;
 - ;     if(parity(x))
 - ;         value ^= 0xc001;
 - ;     return value;
 - ; }
 - ; unsigned usbCrc16(unsigned char *argPtr, unsigned char argLen)
 - ; {
 - ; unsigned crc = 0xffff;
 - ; 
 - ;     while(argLen--)
 - ;         crc = table(lo8(crc) ^ *argPtr++) ^ hi8(crc);
 - ;     return ~crc;
 - ; }
 - 
 - ; extern unsigned usbCrc16(unsigned char *argPtr, unsigned char argLen);
 - ;   argPtr  r24+25 / r16+r17
 - ;   argLen  r22 / r18
 - ; temp variables:
 - ;   byte    r18 / r22
 - ;   scratch r23
 - ;   resCrc  r24+r25 / r16+r17
 - ;   ptr     X / Z
 - usbCrc16:
 -     mov     ptrL, argPtrL
 -     mov     ptrH, argPtrH
 -     ldi     resCrcL, 0xFF
 -     ldi     resCrcH, 0xFF
 -     rjmp    usbCrc16LoopTest
 - usbCrc16ByteLoop:
 -     ld      byte, ptr+
 -     eor     resCrcL, byte   ; resCrcL is now 'x' in table()
 -     mov     byte, resCrcL   ; compute parity of 'x'
 -     swap    byte
 -     eor     byte, resCrcL
 -     mov     scratch, byte
 -     lsr     byte
 -     lsr     byte
 -     eor     byte, scratch
 -     inc     byte
 -     lsr     byte
 -     andi    byte, 1         ; byte is now parity(x)
 -     mov     scratch, resCrcL
 -     mov     resCrcL, resCrcH
 -     eor     resCrcL, byte   ; low byte of if(parity(x)) value ^= 0xc001;
 -     neg     byte
 -     andi    byte, 0xc0
 -     mov     resCrcH, byte   ; high byte of if(parity(x)) value ^= 0xc001;
 -     clr     byte
 -     lsr     scratch
 -     ror     byte
 -     eor     resCrcH, scratch
 -     eor     resCrcL, byte
 -     lsr     scratch
 -     ror     byte
 -     eor     resCrcH, scratch
 -     eor     resCrcL, byte
 - usbCrc16LoopTest:
 -     subi    argLen, 1
 -     brsh    usbCrc16ByteLoop
 -     com     resCrcL
 -     com     resCrcH
 -     ret
 - 
 - #else   /* USB_USE_FAST_CRC */
 - 
 - ; This implementation is slower, but has less code size
 - ;
 - ; extern unsigned usbCrc16(unsigned char *argPtr, unsigned char argLen);
 - ;   argPtr  r24+25 / r16+r17
 - ;   argLen  r22 / r18
 - ; temp variables:
 - ;   byte    r18 / r22
 - ;   bitCnt  r19
 - ;   poly    r20+r21
 - ;   scratch r23
 - ;   resCrc  r24+r25 / r16+r17
 - ;   ptr     X / Z
 - usbCrc16:
 -     mov     ptrL, argPtrL
 -     mov     ptrH, argPtrH
 -     ldi     resCrcL, 0
 -     ldi     resCrcH, 0
 -     ldi     polyL, lo8(0xa001)
 -     ldi     polyH, hi8(0xa001)
 -     com     argLen      ; argLen = -argLen - 1: modified loop to ensure that carry is set
 -     ldi     bitCnt, 0   ; loop counter with starnd condition = end condition
 -     rjmp    usbCrcLoopEntry
 - usbCrcByteLoop:
 -     ld      byte, ptr+
 -     eor     resCrcL, byte
 - usbCrcBitLoop:
 -     ror     resCrcH     ; carry is always set here (see brcs jumps to here)
 -     ror     resCrcL
 -     brcs    usbCrcNoXor
 -     eor     resCrcL, polyL
 -     eor     resCrcH, polyH
 - usbCrcNoXor:
 -     subi    bitCnt, 224 ; (8 * 224) % 256 = 0; this loop iterates 8 times
 -     brcs    usbCrcBitLoop
 - usbCrcLoopEntry:
 -     subi    argLen, -1
 -     brcs    usbCrcByteLoop
 - usbCrcReady:
 -     ret
 - ; Thanks to Reimar Doeffinger for optimizing this CRC routine!
 - 
 - #endif /* USB_USE_FAST_CRC */
 - 
 - ; extern unsigned usbCrc16Append(unsigned char *data, unsigned char len);
 - usbCrc16Append:
 -     rcall   usbCrc16
 -     st      ptr+, resCrcL
 -     st      ptr+, resCrcH
 -     ret
 - 
 - #undef argLen
 - #undef argPtrL
 - #undef argPtrH
 - #undef resCrcL
 - #undef resCrcH
 - #undef ptrL
 - #undef ptrH
 - #undef ptr
 - #undef byte
 - #undef bitCnt
 - #undef polyL
 - #undef polyH
 - #undef scratch
 - 
 - 
 - #if USB_CFG_HAVE_MEASURE_FRAME_LENGTH
 - #ifdef __IAR_SYSTEMS_ASM__
 - /* Register assignments for usbMeasureFrameLength on IAR cc */
 - /* Calling conventions on IAR:
 -  * First parameter passed in r16/r17, second in r18/r19 and so on.
 -  * Callee must preserve r4-r15, r24-r29 (r28/r29 is frame pointer)
 -  * Result is passed in r16/r17
 -  * In case of the "tiny" memory model, pointers are only 8 bit with no
 -  * padding. We therefore pass argument 1 as "16 bit unsigned".
 -  */
 - #   define resL     r16
 - #   define resH     r17
 - #   define cnt16L   r30
 - #   define cnt16H   r31
 - #   define cntH     r18
 - 
 - #else  /* __IAR_SYSTEMS_ASM__ */ 
 - /* Register assignments for usbMeasureFrameLength on gcc */
 - /* Calling conventions on gcc:
 -  * First parameter passed in r24/r25, second in r22/23 and so on.
 -  * Callee must preserve r1-r17, r28/r29
 -  * Result is passed in r24/r25
 -  */
 - #   define resL     r24
 - #   define resH     r25
 - #   define cnt16L   r24
 - #   define cnt16H   r25
 - #   define cntH     r26
 - #endif
 - #   define cnt16    cnt16L
 - 
 - ; extern unsigned usbMeasurePacketLength(void);
 - ; returns time between two idle strobes in multiples of 7 CPU clocks
 - .global usbMeasureFrameLength
 - usbMeasureFrameLength:
 -     ldi     cntH, 6         ; wait ~ 10 ms for D- == 0
 -     clr     cnt16L
 -     clr     cnt16H
 - usbMFTime16:
 -     dec     cntH
 -     breq    usbMFTimeout
 - usbMFWaitStrobe:            ; first wait for D- == 0 (idle strobe)
 -     sbiw    cnt16, 1        ;[0] [6]
 -     breq    usbMFTime16     ;[2]
 -     sbic    USBIN, USBMINUS ;[3]
 -     rjmp    usbMFWaitStrobe ;[4]
 - usbMFWaitIdle:              ; then wait until idle again
 -     sbis    USBIN, USBMINUS ;1 wait for D- == 1
 -     rjmp    usbMFWaitIdle   ;2
 -     ldi     cnt16L, 1       ;1 represents cycles so far
 -     clr     cnt16H          ;1
 - usbMFWaitLoop:
 -     in      cntH, USBIN     ;[0] [7]
 -     adiw    cnt16, 1        ;[1]
 -     breq    usbMFTimeout    ;[3]
 -     andi    cntH, USBMASK   ;[4]
 -     brne    usbMFWaitLoop   ;[5]
 - usbMFTimeout:
 - #if resL != cnt16L
 -     mov     resL, cnt16L
 -     mov     resH, cnt16H
 - #endif
 -     ret
 - 
 - #undef resL
 - #undef resH
 - #undef cnt16
 - #undef cnt16L
 - #undef cnt16H
 - #undef cntH
 - 
 - #endif  /* USB_CFG_HAVE_MEASURE_FRAME_LENGTH */
 - 
 - ;----------------------------------------------------------------------------
 - ; Now include the clock rate specific code
 - ;----------------------------------------------------------------------------
 - 
 - #ifndef USB_CFG_CLOCK_KHZ
 - #   define USB_CFG_CLOCK_KHZ 12000
 - #endif
 - 
 - #if USB_CFG_CHECK_CRC   /* separate dispatcher for CRC type modules */
 - #   if USB_CFG_CLOCK_KHZ == 18000
 - #       include "usbdrvasm18-crc.inc"
 - #   else
 - #       error "USB_CFG_CLOCK_KHZ is not one of the supported crc-rates!"
 - #   endif
 - #else   /* USB_CFG_CHECK_CRC */
 - #   if USB_CFG_CLOCK_KHZ == 12000
 - #       include "usbdrvasm12.inc"
 - #   elif USB_CFG_CLOCK_KHZ == 12800
 - #       include "usbdrvasm128.inc"
 - #   elif USB_CFG_CLOCK_KHZ == 15000
 - #       include "usbdrvasm15.inc"
 - #   elif USB_CFG_CLOCK_KHZ == 16000
 - #       include "usbdrvasm16.inc"
 - #   elif USB_CFG_CLOCK_KHZ == 16500
 - #       include "usbdrvasm165.inc"
 - #   elif USB_CFG_CLOCK_KHZ == 20000
 - #       include "usbdrvasm20.inc"
 - #   else
 - #       error "USB_CFG_CLOCK_KHZ is not one of the supported non-crc-rates!"
 - #   endif
 - #endif /* USB_CFG_CHECK_CRC */
 
 
  |