From 96f99ed9e623357b105bb16882460162bf0827e1 Mon Sep 17 00:00:00 2001 From: Sjors Gielen Date: Fri, 20 Nov 2020 11:45:10 +0100 Subject: [PATCH] Adjust usbdrvasm16.inc to support AVR 1-series. Tested on attiny1614. Can't be merged immediately, since it would break usbdrvasm16 for older AVR devices, so this is a first version. --- usbdrv/usbdrv.c | 1 + usbdrv/usbdrv.h | 7 ++-- usbdrv/usbdrvasm.S | 2 +- usbdrv/usbdrvasm16.inc | 81 +++++++++++++++++++++++++++--------------- 4 files changed, 59 insertions(+), 32 deletions(-) diff --git a/usbdrv/usbdrv.c b/usbdrv/usbdrv.c index 1d80ac6..865dd40 100644 --- a/usbdrv/usbdrv.c +++ b/usbdrv/usbdrv.c @@ -29,6 +29,7 @@ uchar usbCurrentTok; /* last token received or endpoint number for la uchar usbRxToken; /* token for data we received; or endpont number for last OUT */ volatile uchar usbTxLen = USBPID_NAK; /* number of bytes to transmit with next IN token or handshake token */ uchar usbTxBuf[USB_BUFSIZE];/* data to transmit with next IN, free if usbTxLen contains handshake token */ +uchar usbTxToken; #if USB_COUNT_SOF volatile uchar usbSofCount; /* incremented by assembler module every SOF */ #endif diff --git a/usbdrv/usbdrv.h b/usbdrv/usbdrv.h index f094120..1bfb0cf 100644 --- a/usbdrv/usbdrv.h +++ b/usbdrv/usbdrv.h @@ -531,11 +531,12 @@ int usbDescriptorStringSerialNumber[]; /* ------------------------------------------------------------------------- */ #define USB_CONCAT(a, b) a ## b +#define USB_CONCAT3(a, b, c) a ## b ## c #define USB_CONCAT_EXPANDED(a, b) USB_CONCAT(a, b) -#define USB_OUTPORT(name) USB_CONCAT(PORT, name) -#define USB_INPORT(name) USB_CONCAT(PIN, name) -#define USB_DDRPORT(name) USB_CONCAT(DDR, name) +#define USB_OUTPORT(name) USB_CONCAT3(VPORT, name, _OUT) +#define USB_INPORT(name) USB_CONCAT3(VPORT, name, _IN) +#define USB_DDRPORT(name) USB_CONCAT3(VPORT, name, _DIR) /* The double-define trick above lets us concatenate strings which are * defined by macros. */ diff --git a/usbdrv/usbdrvasm.S b/usbdrv/usbdrvasm.S index 3bda63c..64b17ca 100644 --- a/usbdrv/usbdrvasm.S +++ b/usbdrv/usbdrvasm.S @@ -34,7 +34,7 @@ the file appropriate for the given clock rate. #ifdef __IAR_SYSTEMS_ASM__ extern usbRxBuf, usbDeviceAddr, usbNewDeviceAddr, usbInputBufOffset - extern usbCurrentTok, usbRxLen, usbRxToken, usbTxLen + extern usbCurrentTok, usbRxLen, usbRxToken, usbTxLen, usbTxToken extern usbTxBuf, usbTxStatus1, usbTxStatus3 # if USB_COUNT_SOF extern usbSofCount diff --git a/usbdrv/usbdrvasm16.inc b/usbdrv/usbdrvasm16.inc index 25b84e6..0d9197d 100644 --- a/usbdrv/usbdrvasm16.inc +++ b/usbdrv/usbdrvasm16.inc @@ -24,6 +24,15 @@ really know what you are doing! Many parts require not only a maximum number of CPU cycles, but even an exact number of cycles! */ +/* +Timing differences between the original ASM and the attiny1614: + +PUSH: is 1 cycle, this code assumes 2 cycles, so add one NOP +ST with increment: is 1 cycle, this code assumes 2 cycles, so add one NOP +SBI: is 1 cycle, this code assumes 2 cycles, so add one NOP +LDS: is 3 cycles, this code assumes 2 cycles, so save one cycle somewhere else +*/ + ;max stack usage: [ret(2), YL, SREG, YH, bitcnt, shift, x1, x2, x3, x4, cnt] = 12 bytes ;nominal frequency: 16 MHz -> 10.6666666 cycles per bit, 85.333333333 cycles per byte ; Numbers in brackets are clocks counted from center of last sync bit @@ -32,9 +41,12 @@ of CPU cycles, but even an exact number of cycles! USB_INTR_VECTOR: ;order of registers pushed: YL, SREG YH, [sofError], bitcnt, shift, x1, x2, x3, x4, cnt push YL ;[-25] push only what is necessary to sync with edge ASAP + nop in YL, SREG ;[-23] push YL ;[-22] + nop push YH ;[-20] + nop ;---------------------------------------------------------------------------- ; Synchronize with sync pattern: ;---------------------------------------------------------------------------- @@ -75,14 +87,16 @@ foundK: ;[-12] ;we have 1 bit time for setup purposes, then sample again. Numbers in brackets ;are cycles from center of first sync (double K) bit after the instruction push bitcnt ;[-12] + nop ; [---] ;[-11] lds YL, usbInputBufOffset;[-10] ; [---] ;[-9] - clr YH ;[-8] - subi YL, lo8(-(usbRxBuf));[-7] [rx loop init] - sbci YH, hi8(-(usbRxBuf));[-6] [rx loop init] - push shift ;[-5] -; [---] ;[-4] +; [---] ;[-8] + clr YH ;[-7] + subi YL, lo8(-(usbRxBuf));[-6] [rx loop init] + sbci YH, hi8(-(usbRxBuf));[-5] [rx loop init] + push shift ;[-4] + ; no nop on 1-series to correct lds taking 1 cycle longer earlier ldi bitcnt, 0x55 ;[-3] [rx loop init] sbis USBIN, USBMINUS ;[-2] we want two bits K (sample 2 cycles too early) rjmp haveTwoBitsK ;[-1] @@ -97,17 +111,22 @@ foundK: ;[-12] ;---------------------------------------------------------------------------- haveTwoBitsK: push x1 ;[1] + nop push x2 ;[3] + nop push x3 ;[5] + nop ldi shift, 0 ;[7] ldi x3, 1<<4 ;[8] [rx loop init] first sample is inverse bit, compensate that push x4 ;[9] == leap + nop in x1, USBIN ;[11] <-- sample bit 0 andi x1, USBMASK ;[12] bst x1, USBMINUS ;[13] bld shift, 7 ;[14] push cnt ;[15] + nop ldi leap, 0 ;[17] [rx loop init] ldi cnt, USB_BUFSIZE;[18] [rx loop init] rjmp rxbit1 ;[19] arrives at [21] @@ -178,6 +197,7 @@ didUnstuff7: brcc unstuff7 ;[07] eor x3, shift ;[08] reconstruct: x3 is 1 at bit locations we changed, 0 at others st y+, x3 ;[09] store data + nop rxBitLoop: in x1, USBIN ;[00] [11] <-- sample bit 0/2/4 andi x1, USBMASK ;[01] @@ -253,17 +273,21 @@ bitstuff7: sendNakAndReti: ldi x3, USBPID_NAK ;[-18] - rjmp sendX3AndReti ;[-17] + ldi YL, lo8(usbTxToken) ;[-17] + ldi YH, hi8(usbTxToken) ;[-16] + st y, x3 ;[-15] + rjmp usbSendAndReti ;[-14] sendAckAndReti: ldi cnt, USBPID_ACK ;[-17] sendCntAndReti: - mov x3, cnt ;[-16] -sendX3AndReti: - ldi YL, 20 ;[-15] x3==r20 address is 20 - ldi YH, 0 ;[-14] + ldi YL, lo8(usbTxToken) ;[-16] + ldi YH, hi8(usbTxToken) ;[-15] + st y, cnt ;[-14] ldi cnt, 2 ;[-13] ; rjmp usbSendAndReti fallthrough + + ;usbSend: ;pointer to data in 'Y' ;number of bytes in 'cnt' -- including sync byte [range 2 ... 12] @@ -275,6 +299,7 @@ usbSendAndReti: ; 12 cycles until SOP in x2, USBDDR ;[-12] ori x2, USBMASK ;[-11] sbi USBOUT, USBMINUS;[-10] prepare idle state; D+ and D- must have been 0 (no pullups) + nop in x1, USBOUT ;[-8] port mirror for tx loop out USBDDR, x2 ;[-7] <- acquire bus ; need not init x2 (bitstuff history) because sync starts with 0 @@ -318,28 +343,28 @@ didStuff7: ;make SE0: cbr x1, USBMASK ;[5] prepare SE0 [spec says EOP may be 21 to 25 cycles] lds x2, usbNewDeviceAddr;[6] - lsl x2 ;[8] we compare with left shifted address - subi YL, 20 + 2 ;[9] Only assign address on data packets, not ACK/NAK in x3 - sbci YH, 0 ;[10] - out USBOUT, x1 ;[11] <-- out SE0 -- from now 2 bits = 22 cycles until bus idle + lsl x2 ;[9] we compare with left shifted address + subi YL, 20 + 2 ;[10] Only assign address on data packets, not ACK/NAK in x3 + sbci YH, 0 ;[0] [11] + out USBOUT, x1 ;[1] <-- out SE0 -- from now 2 bits = 22 cycles until bus idle ;2006-03-06: moved transfer of new address to usbDeviceAddr from C-Code to asm: ;set address only after data packet was sent, not after handshake - breq skipAddrAssign ;[0] + breq skipAddrAssign ;[2] sts usbDeviceAddr, x2; if not skipped: SE0 is one cycle longer skipAddrAssign: ;end of usbDeviceAddress transfer - ldi x2, 1<