123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307 |
- /* Name: usbdrvasm.S
- * Project: AVR USB driver
- * 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) or proprietary (CommercialLicense.txt)
- * Revision: $Id$
- */
-
- /*
- 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.
- */
-
- #include "iarcompat.h"
- #ifndef __IAR_SYSTEMS_ASM__
- /* configs for io.h */
- # define __SFR_OFFSET 0
- # define _VECTOR(N) __vector_ ## N /* io.h does not define this for asm */
- # include <avr/io.h> /* for CPU I/O register definitions and vectors */
- # define macro .macro /* GNU Assembler macro definition */
- # define endm .endm /* End of GNU Assembler macro definition */
- #endif /* __IAR_SYSTEMS_ASM__ */
- #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 bitcnt r22
- #define phase x4
- #define leap x4
-
- /* Some assembler dependent definitions and declarations: */
-
- #ifdef __IAR_SYSTEMS_ASM__
-
- # define nop2 rjmp $+2 /* jump to next instruction */
- # define XL r26
- # define XH r27
- # define YL r28
- # define YH r29
- # define ZL r30
- # define ZH r31
- # define lo8(x) LOW(x)
- # define hi8(x) (((x)>>8) & 0xff) /* not HIGH to allow XLINK to make a proper range check */
-
- extern usbRxBuf, usbDeviceAddr, usbNewDeviceAddr, usbInputBufOffset
- extern usbCurrentTok, usbRxLen, usbRxToken, usbTxLen
- extern usbTxBuf, usbMsgLen, usbTxLen1, usbTxBuf1, usbTxLen3, usbTxBuf3
- # 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__ */
-
- # define nop2 rjmp .+0 /* jump to next instruction */
-
- # ifndef USB_INTR_VECTOR /* default to hardware interrupt INT0 */
- # define USB_INTR_VECTOR INT0_vect
- # 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
-
-
- ;----------------------------------------------------------------------------
- ; 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
-
- ; extern unsigned usbCrc16(unsigned char *data, unsigned char len);
- ; data: r24/25
- ; len: r22
- ; temp variables:
- ; r18: data byte
- ; r19: bit counter
- ; r20/21: polynomial
- ; r23: scratch
- ; r24/25: crc-sum
- ; r26/27=X: ptr
- 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
- crcByteLoop:
- subi argLen, -1
- brcc crcReady ; modified loop to ensure that carry is set below
- ld byte, ptr+
- ldi bitCnt, -8 ; strange loop counter to ensure that carry is set where we need it
- eor resCrcL, byte
- crcBitLoop:
- ror resCrcH ; carry is always set here
- ror resCrcL
- brcs crcNoXor
- eor resCrcL, polyL
- eor resCrcH, polyH
- crcNoXor:
- subi bitCnt, -1
- brcs crcBitLoop
- rjmp crcByteLoop
- crcReady:
- ret
- ; Thanks to Reimar Doeffinger for optimizing this CRC routine!
-
- ; 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_CLOCK_KHZ == 12000
- # include "usbdrvasm12.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"
- #else
- # error "USB_CFG_CLOCK_KHZ is not one of the supported rates!"
- #endif
|