224 lines
6.3 KiB
ArmAsm
224 lines
6.3 KiB
ArmAsm
|
/* 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: usbdrvasm.S,v 1.1 2008/07/09 20:47:11 rschaten Exp $
|
||
|
*/
|
||
|
|
||
|
/*
|
||
|
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, 0xff
|
||
|
ldi resCrcH, 0xff
|
||
|
ldi polyL, lo8(0xa001)
|
||
|
ldi polyH, hi8(0xa001)
|
||
|
crcByteLoop:
|
||
|
subi argLen, 1
|
||
|
brcs crcReady
|
||
|
ld byte, ptr+
|
||
|
ldi bitCnt, 8
|
||
|
crcBitLoop:
|
||
|
mov scratch, byte
|
||
|
eor scratch, resCrcL
|
||
|
lsr resCrcH
|
||
|
ror resCrcL
|
||
|
lsr byte
|
||
|
sbrs scratch, 0
|
||
|
rjmp crcNoXor
|
||
|
eor resCrcL, polyL
|
||
|
eor resCrcH, polyH
|
||
|
crcNoXor:
|
||
|
dec bitCnt
|
||
|
brne crcBitLoop
|
||
|
rjmp crcByteLoop
|
||
|
crcReady:
|
||
|
com resCrcL
|
||
|
com resCrcH
|
||
|
ret
|
||
|
|
||
|
; extern unsigned usbCrc16Append(unsigned char *data, unsigned char len);
|
||
|
usbCrc16Append:
|
||
|
rcall usbCrc16
|
||
|
st ptr+, resCrcL
|
||
|
st ptr+, resCrcH
|
||
|
ret
|
||
|
|
||
|
|
||
|
;----------------------------------------------------------------------------
|
||
|
; 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
|