2 * Project: AVR USB driver
3 * Author: Christian Starkjohann
4 * Creation Date: 2007-06-13
6 * Copyright: (c) 2007 by OBJECTIVE DEVELOPMENT Software GmbH
7 * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
8 * Revision: $Id: usbdrvasm.S 692 2008-11-07 15:07:40Z cs $
13 This module is the assembler part of the USB driver. This file contains
14 general code (preprocessor acrobatics and CRC computation) and then includes
15 the file appropriate for the given clock rate.
18 #define __SFR_OFFSET 0 /* used by avr-libc's register definitions */
19 #include "usbportability.h"
20 #include "usbdrv.h" /* for common defs */
33 /* Some assembler dependent definitions and declarations: */
35 #ifdef __IAR_SYSTEMS_ASM__
36 extern usbRxBuf, usbDeviceAddr, usbNewDeviceAddr, usbInputBufOffset
37 extern usbCurrentTok, usbRxLen, usbRxToken, usbTxLen
38 extern usbTxBuf, usbTxStatus1, usbTxStatus3
46 # ifndef USB_INTR_VECTOR
48 # else /* USB_INTR_VECTOR */
50 # undef USB_INTR_VECTOR
51 # endif /* USB_INTR_VECTOR */
52 # define USB_INTR_VECTOR usbInterruptHandler
56 #else /* __IAR_SYSTEMS_ASM__ */
58 # ifndef USB_INTR_VECTOR /* default to hardware interrupt INT0 */
59 # define USB_INTR_VECTOR SIG_INTERRUPT0
62 .global USB_INTR_VECTOR
63 .type USB_INTR_VECTOR, @function
65 .global usbCrc16Append
66 #endif /* __IAR_SYSTEMS_ASM__ */
69 #if USB_INTR_PENDING < 0x40 /* This is an I/O address, use in and out */
70 # define USB_LOAD_PENDING(reg) in reg, USB_INTR_PENDING
71 # define USB_STORE_PENDING(reg) out USB_INTR_PENDING, reg
72 #else /* It's a memory address, use lds and sts */
73 # define USB_LOAD_PENDING(reg) lds reg, USB_INTR_PENDING
74 # define USB_STORE_PENDING(reg) sts USB_INTR_PENDING, reg
77 #define usbTxLen1 usbTxStatus1
78 #define usbTxBuf1 (usbTxStatus1 + 1)
79 #define usbTxLen3 usbTxStatus3
80 #define usbTxBuf3 (usbTxStatus3 + 1)
83 ;----------------------------------------------------------------------------
85 ;----------------------------------------------------------------------------
87 #ifdef __IAR_SYSTEMS_ASM__
88 /* Register assignments for usbCrc16 on IAR cc */
89 /* Calling conventions on IAR:
90 * First parameter passed in r16/r17, second in r18/r19 and so on.
91 * Callee must preserve r4-r15, r24-r29 (r28/r29 is frame pointer)
92 * Result is passed in r16/r17
93 * In case of the "tiny" memory model, pointers are only 8 bit with no
94 * padding. We therefore pass argument 1 as "16 bit unsigned".
96 RTMODEL "__rt_version", "3"
97 /* The line above will generate an error if cc calling conventions change.
98 * The value "3" above is valid for IAR 4.10B/W32
100 # define argLen r18 /* argument 2 */
101 # define argPtrL r16 /* argument 1 */
102 # define argPtrH r17 /* argument 1 */
104 # define resCrcL r16 /* result */
105 # define resCrcH r17 /* result */
116 #else /* __IAR_SYSTEMS_ASM__ */
117 /* Register assignments for usbCrc16 on gcc */
118 /* Calling conventions on gcc:
119 * First parameter passed in r24/r25, second in r22/23 and so on.
120 * Callee must preserve r1-r17, r28/r29
121 * Result is passed in r24/r25
123 # define argLen r22 /* argument 2 */
124 # define argPtrL r24 /* argument 1 */
125 # define argPtrH r25 /* argument 1 */
127 # define resCrcL r24 /* result */
128 # define resCrcH r25 /* result */
141 ; extern unsigned usbCrc16(unsigned char *data, unsigned char len);
156 ldi polyL, lo8(0xa001)
157 ldi polyH, hi8(0xa001)
158 com argLen ; argLen = -argLen - 1
161 brcc crcReady ; modified loop to ensure that carry is set below
163 ldi bitCnt, -8 ; strange loop counter to ensure that carry is set where we need it
166 ror resCrcH ; carry is always set here
177 ; Thanks to Reimar Doeffinger for optimizing this CRC routine!
179 ; extern unsigned usbCrc16Append(unsigned char *data, unsigned char len);
201 #if USB_CFG_HAVE_MEASURE_FRAME_LENGTH
202 #ifdef __IAR_SYSTEMS_ASM__
203 /* Register assignments for usbMeasureFrameLength on IAR cc */
204 /* Calling conventions on IAR:
205 * First parameter passed in r16/r17, second in r18/r19 and so on.
206 * Callee must preserve r4-r15, r24-r29 (r28/r29 is frame pointer)
207 * Result is passed in r16/r17
208 * In case of the "tiny" memory model, pointers are only 8 bit with no
209 * padding. We therefore pass argument 1 as "16 bit unsigned".
217 #else /* __IAR_SYSTEMS_ASM__ */
218 /* Register assignments for usbMeasureFrameLength on gcc */
219 /* Calling conventions on gcc:
220 * First parameter passed in r24/r25, second in r22/23 and so on.
221 * Callee must preserve r1-r17, r28/r29
222 * Result is passed in r24/r25
230 # define cnt16 cnt16L
232 ; extern unsigned usbMeasurePacketLength(void);
233 ; returns time between two idle strobes in multiples of 7 CPU clocks
234 .global usbMeasureFrameLength
235 usbMeasureFrameLength:
236 ldi cntH, 6 ; wait ~ 10 ms for D- == 0
242 usbMFWaitStrobe: ; first wait for D- == 0 (idle strobe)
243 sbiw cnt16, 1 ;[0] [6]
244 breq usbMFTime16 ;[2]
245 sbic USBIN, USBMINUS ;[3]
246 rjmp usbMFWaitStrobe ;[4]
247 usbMFWaitIdle: ; then wait until idle again
248 sbis USBIN, USBMINUS ;1 wait for D- == 1
249 rjmp usbMFWaitIdle ;2
250 ldi cnt16L, 1 ;1 represents cycles so far
253 in cntH, USBIN ;[0] [7]
255 breq usbMFTimeout ;[3]
256 andi cntH, USBMASK ;[4]
257 brne usbMFWaitLoop ;[5]
272 #endif /* USB_CFG_HAVE_MEASURE_FRAME_LENGTH */
274 ;----------------------------------------------------------------------------
275 ; Now include the clock rate specific code
276 ;----------------------------------------------------------------------------
278 #ifndef USB_CFG_CLOCK_KHZ
279 # define USB_CFG_CLOCK_KHZ 12000
282 #if USB_CFG_CLOCK_KHZ == 12000
283 # include "usbdrvasm12.inc"
284 #elif USB_CFG_CLOCK_KHZ == 12800
285 # include "usbdrvasm128.inc"
286 #elif USB_CFG_CLOCK_KHZ == 15000
287 # include "usbdrvasm15.inc"
288 #elif USB_CFG_CLOCK_KHZ == 16000
289 # include "usbdrvasm16.inc"
290 #elif USB_CFG_CLOCK_KHZ == 16500
291 # include "usbdrvasm165.inc"
292 #elif USB_CFG_CLOCK_KHZ == 20000
293 # include "usbdrvasm20.inc"
295 # error "USB_CFG_CLOCK_KHZ is not one of the supported rates!"