X-Git-Url: http://git.linex4red.de/pub/USBasp.git/blobdiff_plain/39f1c0c136520a3f4746ad6381d1242979125ff3..refs/heads/master:/firmware/usbdrv/usbdrvasm.S?ds=inline diff --git a/firmware/usbdrv/usbdrvasm.S b/firmware/usbdrv/usbdrvasm.S index c3fc0bbcd..80f497010 100644 --- a/firmware/usbdrv/usbdrvasm.S +++ b/firmware/usbdrv/usbdrvasm.S @@ -1,11 +1,10 @@ /* Name: usbdrvasm.S - * Project: AVR USB driver + * 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 692 2008-11-07 15:07:40Z cs $ */ /* @@ -26,7 +25,8 @@ the file appropriate for the given clock rate. #define cnt r19 #define x3 r20 #define x4 r21 -#define bitcnt r22 +#define x5 r22 +#define bitcnt x5 #define phase x4 #define leap x4 @@ -56,7 +56,11 @@ the file appropriate for the given clock rate. #else /* __IAR_SYSTEMS_ASM__ */ # ifndef USB_INTR_VECTOR /* default to hardware interrupt INT0 */ -# define USB_INTR_VECTOR SIG_INTERRUPT0 +# ifdef INT0_vect +# define USB_INTR_VECTOR INT0_vect // this is the "new" define for the vector +# else +# define USB_INTR_VECTOR SIG_INTERRUPT0 // this is the "old" vector +# endif # endif .text .global USB_INTR_VECTOR @@ -138,16 +142,88 @@ RTMODEL "__rt_version", "3" #endif -; extern unsigned usbCrc16(unsigned char *data, unsigned char len); -; data: r24/25 -; len: r22 +#if USB_USE_FAST_CRC + +; This implementation is faster, but has bigger code size +; Thanks to Slawomir Fras (BoskiDialer) for this code and to Shay Green for +; even further optimizations! +; 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: -; r18: data byte -; r19: bit counter -; r20/21: polynomial -; r23: scratch -; r24/25: crc-sum -; r26/27=X: ptr +; byte r18 / r22 +; scratch r23 +; resCrc r24+r25 / r16+r17 +; ptr X / Z +usbCrc16: + movw ptrL, argPtrL + ldi resCrcL, 0xFF + ldi resCrcH, 0xFF + clr bitCnt ; zero reg + rjmp usbCrc16LoopTest +usbCrc16ByteLoop: + ld byte, ptr+ + eor byte, resCrcL ; scratch is now 'x' in table() + mov scratch, byte ; compute parity of 'x' + swap byte + eor byte, scratch + mov resCrcL, byte + lsr byte + lsr byte + eor byte, resCrcL + inc byte + andi byte, 2 ; byte is now parity(x) << 1 + cp bitCnt, byte ; c = (byte != 0), then put in high bit + ror scratch ; so that after xoring, shifting, and xoring, it gives + ror byte ; the desired 0xC0 with resCrcH + mov resCrcL, byte + eor resCrcL, resCrcH + mov resCrcH, scratch + 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 @@ -155,27 +231,30 @@ usbCrc16: 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 + 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+ - 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 +usbCrcBitLoop: + ror resCrcH ; carry is always set here (see brcs jumps to here) ror resCrcL - brcs crcNoXor + brcs usbCrcNoXor eor resCrcL, polyL eor resCrcH, polyH -crcNoXor: - subi bitCnt, -1 - brcs crcBitLoop - rjmp crcByteLoop -crcReady: +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 @@ -276,21 +355,35 @@ usbMFTimeout: ;---------------------------------------------------------------------------- #ifndef USB_CFG_CLOCK_KHZ -# define USB_CFG_CLOCK_KHZ 12000 +# ifdef F_CPU +# define USB_CFG_CLOCK_KHZ (F_CPU/1000) +# else +# error "USB_CFG_CLOCK_KHZ not defined in usbconfig.h and no F_CPU set!" +# endif #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 +#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 rates for USB_CFG_CHECK_CRC!" +# 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 == 18000 +# include "usbdrvasm18.inc" +# elif USB_CFG_CLOCK_KHZ == 20000 +# include "usbdrvasm20.inc" +# else +# error "USB_CFG_CLOCK_KHZ is not one of the supported rates!" +# endif +#endif /* USB_CFG_CHECK_CRC */