📄 usbdrvasm.s
字号:
/* 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), GNU GPL v3 or proprietary (CommercialLicense.txt) * Revision: $Id: usbdrvasm.S 692 2008-11-07 15:07:40Z cs $ *//*General Description:This module is the assembler part of the USB driver. This file containsgeneral code (preprocessor acrobatics and CRC computation) and then includesthe 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 bitcnt r22#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; 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: ptrusbCrc16: mov ptrL, argPtrL mov ptrH, argPtrH ldi resCrcL, 0 ldi resCrcH, 0 ldi polyL, lo8(0xa001) ldi polyH, hi8(0xa001) com argLen ; argLen = -argLen - 1crcByteLoop: 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, bytecrcBitLoop: ror resCrcH ; carry is always set here ror resCrcL brcs crcNoXor eor resCrcL, polyL eor resCrcH, polyHcrcNoXor: subi bitCnt, -1 brcs crcBitLoop rjmp crcByteLoopcrcReady: 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 usbMeasureFrameLengthusbMeasureFrameLength: ldi cntH, 6 ; wait ~ 10 ms for D- == 0 clr cnt16L clr cnt16HusbMFTime16: dec cntH breq usbMFTimeoutusbMFWaitStrobe: ; 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 ;1usbMFWaitLoop: 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 == 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 rates!"#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -