diff options
Diffstat (limited to 'firmware/usbdrv')
-rw-r--r-- | firmware/usbdrv/asmcommon.inc | 31 | ||||
-rw-r--r-- | firmware/usbdrv/usbdrv.c | 70 | ||||
-rw-r--r-- | firmware/usbdrv/usbdrvasm165.inc | 43 |
3 files changed, 88 insertions, 56 deletions
diff --git a/firmware/usbdrv/asmcommon.inc b/firmware/usbdrv/asmcommon.inc index d2a4f7c..5f269af 100644 --- a/firmware/usbdrv/asmcommon.inc +++ b/firmware/usbdrv/asmcommon.inc @@ -5,6 +5,9 @@ * Tabsize: 4 * Copyright: (c) 2007 by OBJECTIVE DEVELOPMENT Software GmbH * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt) + * + * Modified to an interrupt-less driver for micronucleus V2. (c) 2014 T. Bo"scke + * */ /* Do not link this file! Link usbdrvasm.S instead, which includes the @@ -84,7 +87,20 @@ se0: ;Setup and Out are followed by a data packet two bit times (16 cycles) after ;the end of SE0. The sync code allows up to 40 cycles delay from the start of ;the sync pattern until the first bit is sampled. That's a total of 56 cycles. +; +;TB 2014-02-02 +;The interrupt-less driver always has to wait for the next packet at this point +;or usbpoll() will get confused. + handleSetupOrOut: ;[32] + ldi YL,10 ; Time out +waitForData: + USB_LOAD_PENDING(x2) ;[xx] + sbrc x2, USB_INTR_PENDING_BIT;[xx] check whether data is already arriving + rjmp storeTokenAndReturn + dec YL + brne waitForData + #if USB_CFG_IMPLEMENT_FN_WRITEOUT /* if we have data for endpoint != 0, set usbCurrentTok to address */ andi x3, 0xf ;[32] breq storeTokenAndReturn ;[33] @@ -99,7 +115,9 @@ doReturn: rjmp waitForJ ;[51] save the pops and pushes -- a new interrupt is already pending sofError: POP_RETI ;macro call - reti + + ret ;02-02-2014 not called from INT in micronucleus. +; reti handleData: #if USB_CFG_CHECK_CRC @@ -120,10 +138,13 @@ handleData: #endif sts usbRxLen, cnt ;[28] store received data, swap buffers sts usbRxToken, shift ;[30] - lds x2, usbInputBufOffset;[32] swap buffers - ldi cnt, USB_BUFSIZE ;[34] - sub cnt, x2 ;[35] - sts usbInputBufOffset, cnt;[36] buffers now swapped + +; Microncleus V2 does not need double buffering due to in-order processing of USB-rx +; TB 2014-01-04 +; lds x2, usbInputBufOffset;[32] swap buffers +; ldi cnt, USB_BUFSIZE ;[34] +; sub cnt, x2 ;[35] +; sts usbInputBufOffset, cnt;[36] buffers now swapped rjmp sendAckAndReti ;[38] 40 + 17 = 57 until SOP handleIn: diff --git a/firmware/usbdrv/usbdrv.c b/firmware/usbdrv/usbdrv.c index d838935..354dce7 100644 --- a/firmware/usbdrv/usbdrv.c +++ b/firmware/usbdrv/usbdrv.c @@ -3,10 +3,25 @@ * Author: Christian Starkjohann * Creation Date: 2004-12-29 * Tabsize: 4 + * + * Copyright: (c) 2005 by OBJECTIVE DEVELOPMENT Software GmbH * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt) */ +/* This copy of usbdrv.c was optimized to reduce the memory footprint with micronucleus V2 + * + * Changes: + * a) Replies to USB SETUP IN Packets are now only possible from Flash + * * Commented out routines to copy from SRAM + * * remove msgflag variable and all handling involving it + */ +#define MNHACK_ONLY_FLASH_MSGPTR +/* b) Do not use preinitialized global variables to avoid having to initialize + * the data section. + */ +#define MNHACK_NO_DATASECTION + #include "usbdrv.h" #include "oddebug.h" @@ -27,7 +42,11 @@ uchar usbConfiguration; /* currently selected configuration. Administere volatile schar usbRxLen; /* = 0; number of bytes in usbRxBuf; 0 means free, -1 for flow control */ uchar usbCurrentTok; /* last token received or endpoint number for last OUT token if != 0 */ 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 */ +#ifdef MNHACK_NO_DATASECTION + volatile uchar usbTxLen; /* number of bytes to transmit with next IN token or handshake token */ +#else + volatile uchar usbTxLen = USBPID_NAK; /* number of bytes to transmit with next IN token or handshake token */ +#endif uchar usbTxBuf[USB_BUFSIZE];/* data to transmit with next IN, free if usbTxLen contains handshake token */ #if USB_COUNT_SOF volatile uchar usbSofCount; /* incremented by assembler module every SOF */ @@ -44,8 +63,15 @@ uchar usbCurrentDataToken;/* when we check data toggling to ignore duplica /* USB status registers / not shared with asm code */ usbMsgPtr_t usbMsgPtr; /* data to transmit next -- ROM or RAM address */ -static usbMsgLen_t usbMsgLen = USB_NO_MSG; /* remaining number of bytes */ +#ifdef MNHACK_NO_DATASECTION + static usbMsgLen_t usbMsgLen; /* remaining number of bytes */ +#else + static usbMsgLen_t usbMsgLen = USB_NO_MSG; /* remaining number of bytes */ +#endif + +#ifndef MNHACK_ONLY_FLASH_MSGPTR static uchar usbMsgFlags; /* flag values see below */ +#endif #define USB_FLG_MSGPTR_IS_ROM (1<<6) #define USB_FLG_USE_USER_RW (1<<7) @@ -291,17 +317,18 @@ USB_PUBLIC void usbSetInterrupt3(uchar *data, uchar len) * This may cause problems with undefined symbols if compiled without * optimizing! */ -#define GET_DESCRIPTOR(cfgProp, staticName) \ - if(cfgProp){ \ - if((cfgProp) & USB_PROP_IS_RAM) \ - flags = 0; \ - if((cfgProp) & USB_PROP_IS_DYNAMIC){ \ - len = usbFunctionDescriptor(rq); \ - }else{ \ - len = USB_PROP_LENGTH(cfgProp); \ - usbMsgPtr = (usbMsgPtr_t)(staticName); \ - } \ - } + + #define GET_DESCRIPTOR(cfgProp, staticName) \ + if(cfgProp){ \ + if((cfgProp) & USB_PROP_IS_RAM) \ + flags = 0; \ + if((cfgProp) & USB_PROP_IS_DYNAMIC){ \ + len = usbFunctionDescriptor(rq); \ + }else{ \ + len = USB_PROP_LENGTH(cfgProp); \ + usbMsgPtr = (usbMsgPtr_t)(staticName); \ + } \ + } /* usbDriverDescriptor() is similar to usbFunctionDescriptor(), but used * internally for all types of descriptors. @@ -348,7 +375,11 @@ uchar flags = USB_FLG_MSGPTR_IS_ROM; len = usbFunctionDescriptor(rq); } SWITCH_END + + flags=flags; // Make compiler shut up about unused variable +#ifndef MNHACK_ONLY_FLASH_MSGPTR usbMsgFlags = flags; +#endif return len; } @@ -441,7 +472,9 @@ usbRequest_t *rq = (void *)data; usbMsgLen_t replyLen; usbTxBuf[0] = USBPID_DATA0; /* initialize data toggling */ usbTxLen = USBPID_NAK; /* abort pending transmit */ +#ifndef MNHACK_ONLY_FLASH_MSGPTR usbMsgFlags = 0; +#endif uchar type = rq->bmRequestType & USBRQ_TYPE_MASK; if(type != USBRQ_TYPE_STANDARD){ /* standard requests are handled by driver */ replyLen = usbFunctionSetup(data); @@ -499,18 +532,22 @@ static uchar usbDeviceRead(uchar *data, uchar len) { uchar i = len; usbMsgPtr_t r = usbMsgPtr; +#ifndef MNHACK_ONLY_FLASH_MSGPTR if(usbMsgFlags & USB_FLG_MSGPTR_IS_ROM){ /* ROM data */ +#endif do{ uchar c = USB_READ_FLASH(r); /* assign to char size variable to enforce byte ops */ *data++ = c; r++; }while(--i); - }else{ /* RAM data */ +#ifndef MNHACK_ONLY_FLASH_MSGPTR + }else{ // RAM data do{ *data++ = *((uchar *)r); r++; }while(--i); } +#endif usbMsgPtr = r; } } @@ -609,6 +646,11 @@ isNotReset: USB_PUBLIC void usbInit(void) { +#ifdef MNHACK_NO_DATASECTION + usbTxLen = USBPID_NAK; + usbMsgLen = USB_NO_MSG; +#endif + #if USB_INTR_CFG_SET != 0 USB_INTR_CFG |= USB_INTR_CFG_SET; #endif diff --git a/firmware/usbdrv/usbdrvasm165.inc b/firmware/usbdrv/usbdrvasm165.inc index 450d2fd..ae91588 100644 --- a/firmware/usbdrv/usbdrvasm165.inc +++ b/firmware/usbdrv/usbdrvasm165.inc @@ -4,9 +4,7 @@ * Creation Date: 2007-04-22 * Tabsize: 4 * Copyright: (c) 2007 by OBJECTIVE DEVELOPMENT Software GmbH - * Portions Copyright: (c) 2012 Louis Beaudoin * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt) - * Revision: $Id: usbdrvasm165.inc 740 2009-04-13 18:23:31Z cs $ */ /* Do not link this file! Link usbdrvasm.S instead, which includes the @@ -36,41 +34,12 @@ of CPU cycles, but even an exact number of cycles! ; Numbers in brackets are clocks counted from center of last sync bit ; when instruction starts -; the code enabled by TINY85MODE is inteded only for use with the tiny85-compatible USBaspLoader -; project. -; with TINY85MODE set, the beginning of the ISR checks for a magic word "B007" at the very bottom of the stack -; and jumps to the application's ISR if the magic word isn't present -; the max allowable interrupt latency is lower given this additional code before getting to the -; USB-specific portion of the ISR. USB_INTR_VECTOR: ;order of registers pushed: YL, SREG [sofError], r0, YH, shift, x1, x2, x3, x4, cnt - push YL ; push only what is necessary to sync with edge ASAP - in YL, SREG ; - push YL ; - -#ifdef TINY85MODE -; look for magic word "B007" at the bottom of the stack - lds YL, RAMEND - cpi YL, 0xB0 - brne cleanupAndJumpToApp - - lds YL, RAMEND-1 - cpi YL, 0x07 - breq cleanupBootloaderIntStack - -cleanupAndJumpToApp: -; magic word was not found, put registers back to where they were before this ISR ran, and jump to application ISR - pop YL - out SREG, YL - pop YL - - rjmp __vectors - TINYVECTOR_USBPLUS_OFFSET - -cleanupBootloaderIntStack: -; magic word was found, put registers - CLR YL ; [-19] ensure we meet below requirements for YL < 0x80 -#endif + push YL ;[-23] push only what is necessary to sync with edge ASAP + in YL, SREG ;[-21] + push YL ;[-20] ;---------------------------------------------------------------------------- ; Synchronize with sync pattern: ;---------------------------------------------------------------------------- @@ -80,9 +49,9 @@ cleanupBootloaderIntStack: ;YL is guarenteed to be < 0x80 because I flag is clear. When we jump to ;waitForJ, ensure that this prerequisite is met. waitForJ: - inc YL ; [-18] - sbis USBIN, USBMINUS ; [-17] - brne waitForJ ; [-16] just make sure we have ANY timeout + inc YL + sbis USBIN, USBMINUS + brne waitForJ ; just make sure we have ANY timeout waitForK: ;The following code results in a sampling window of < 1/4 bit which meets the spec. sbis USBIN, USBMINUS ;[-15] |