summaryrefslogtreecommitdiffstats
path: root/firmware/usbdrv
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/usbdrv')
-rw-r--r--firmware/usbdrv/asmcommon.inc31
-rw-r--r--firmware/usbdrv/usbdrv.c70
-rw-r--r--firmware/usbdrv/usbdrvasm165.inc43
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]