aboutsummaryrefslogtreecommitdiffstats
path: root/usbdrv/usbdrvasm.S
diff options
context:
space:
mode:
authorChristian Starkjohann <cs+github@obdev.at>2008-04-17 19:28:18 +0000
committerChristian Starkjohann <cs+github@obdev.at>2008-04-17 19:28:18 +0000
commit1c8a62d484550aba8db26ffb7202daa3d3a76396 (patch)
tree0dfde649d9e2b96bb4c029548082dac861fe13c1 /usbdrv/usbdrvasm.S
parentc45ef28d96f1eed5c5d06dd42b937c0b751d9a72 (diff)
downloadv-usb-1c8a62d484550aba8db26ffb7202daa3d3a76396.tar.gz
v-usb-1c8a62d484550aba8db26ffb7202daa3d3a76396.tar.bz2
v-usb-1c8a62d484550aba8db26ffb7202daa3d3a76396.zip
- used wrong name in copy -- fixed this
Diffstat (limited to 'usbdrv/usbdrvasm.S')
-rw-r--r--usbdrv/usbdrvasm.S307
1 files changed, 307 insertions, 0 deletions
diff --git a/usbdrv/usbdrvasm.S b/usbdrv/usbdrvasm.S
new file mode 100644
index 0000000..518037e
--- /dev/null
+++ b/usbdrv/usbdrvasm.S
@@ -0,0 +1,307 @@
+/* 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 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
+
+
+;----------------------------------------------------------------------------
+; 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