summaryrefslogtreecommitdiffstats
path: root/firmware
diff options
context:
space:
mode:
authorcpldcpu <cpldcpu@gmail.com>2013-11-04 00:22:17 +0100
committercpldcpu <cpldcpu@gmail.com>2013-11-04 00:22:17 +0100
commitf3456ea1cfc56ebfa1fcea33be93856c0a71df37 (patch)
tree40fdff10bbd1bb0229cbb27062790ea87a18c041 /firmware
parent5b7617bfb1763f14a9e1e8792447d75cd076d2fa (diff)
downloadmicronucleus-f3456ea1cfc56ebfa1fcea33be93856c0a71df37.tar.gz
micronucleus-f3456ea1cfc56ebfa1fcea33be93856c0a71df37.tar.bz2
micronucleus-f3456ea1cfc56ebfa1fcea33be93856c0a71df37.zip
Updated USB Driver, nanite, oscal
Diffstat (limited to 'firmware')
-rw-r--r--firmware/bootloaderconfig.h20
-rw-r--r--firmware/libs-device/osccal.c114
-rw-r--r--firmware/main.c35
-rw-r--r--firmware/main_old.c487
-rw-r--r--firmware/usbdrv/Changelog.txt21
-rw-r--r--firmware/usbdrv/CommercialLicense.txt10
-rw-r--r--firmware/usbdrv/USB-ID-FAQ.txt6
-rw-r--r--firmware/usbdrv/USB-IDs-for-free.txt16
-rw-r--r--firmware/usbdrv/asmcommon.inc1
-rw-r--r--firmware/usbdrv/oddebug.c1
-rw-r--r--firmware/usbdrv/oddebug.h1
-rw-r--r--firmware/usbdrv/usbconfig-prototype.h10
-rw-r--r--firmware/usbdrv/usbdrv.c31
-rw-r--r--firmware/usbdrv/usbdrv.h37
-rw-r--r--firmware/usbdrv/usbdrvasm.S50
-rw-r--r--firmware/usbdrv/usbdrvasm.asm1
-rw-r--r--firmware/usbdrv/usbdrvasm12.inc45
-rw-r--r--firmware/usbdrv/usbdrvasm128.inc1
-rw-r--r--firmware/usbdrv/usbdrvasm15.inc1
-rw-r--r--firmware/usbdrv/usbdrvasm16.inc1
-rw-r--r--firmware/usbdrv/usbdrvasm165.inc43
-rw-r--r--firmware/usbdrv/usbdrvasm18-crc.inc1
-rw-r--r--firmware/usbdrv/usbdrvasm20.inc1
-rw-r--r--firmware/usbdrv/usbportability.h1
24 files changed, 730 insertions, 205 deletions
diff --git a/firmware/bootloaderconfig.h b/firmware/bootloaderconfig.h
index a23ea5a..d78a614 100644
--- a/firmware/bootloaderconfig.h
+++ b/firmware/bootloaderconfig.h
@@ -207,16 +207,25 @@ these macros are defined, the boot loader uses them.
/* max 6200ms to not overflow idlePolls variable */
-#define AUTO_EXIT_MS 5000
+#define AUTO_EXIT_MS 6000
//#define AUTO_EXIT_CONDITION() (idlePolls > (AUTO_EXIT_MS * 10UL))
// uncomment for chips with clkdiv8 enabled in fuses
//#define LOW_POWER_MODE 1
// restore cpu speed calibration back to 8/16mhz instead of 8.25/16.5mhz
-//#define RESTORE_OSCCAL 1
+// #define RESTORE_OSCCAL
// set clock prescaler to a value before running user program
//#define SET_CLOCK_PRESCALER _BV(CLKPS0) /* divide by 2 for 8mhz */
+// Specific configuration for the Nanite
+// Nanite has both LED and tactile button connected to control pin.
+// LED will turn on when output=low and act as external pull up otherwise
+// button shorts to GND
+
+// #define NANITE
+#define NANITE_CTRLPIN PB5
+
+
#ifdef BUILD_JUMPER_MODE
#define START_JUMPER_PIN 5
#define digitalRead(pin) (PINB & _BV(pin))
@@ -234,6 +243,13 @@ these macros are defined, the boot loader uses them.
PORTB = 0;
}
#endif /* __ASSEMBLER__ */
+
+#elif defined NANITE
+ #define bootLoaderInit()
+ #define bootLoaderExit()
+ #define bootLoaderCondition() (++idlePolls < (AUTO_EXIT_MS * 10UL))
+ #define bootLoaderStartCondition() (!(PINB & _BV(NANITE_CTRLPIN)))
+
#else
#define bootLoaderInit()
#define bootLoaderExit()
diff --git a/firmware/libs-device/osccal.c b/firmware/libs-device/osccal.c
index 939d5c3..b8d1bb5 100644
--- a/firmware/libs-device/osccal.c
+++ b/firmware/libs-device/osccal.c
@@ -8,49 +8,105 @@
*/
#include <avr/io.h>
-
#ifndef uchar
#define uchar unsigned char
#endif
+int usbMeasureFrameLengthDecreasing(int);
+
/* ------------------------------------------------------------------------- */
/* ------------------------ Oscillator Calibration ------------------------- */
/* ------------------------------------------------------------------------- */
/* Calibrate the RC oscillator. Our timing reference is the Start Of Frame
* signal (a single SE0 bit) repeating every millisecond immediately after
- * a USB RESET. We first do a binary search for the OSCCAL value and then
- * optimize this value with a neighboorhod search.
+ * a USB RESET.
+ *
+ *
+ * Optimized version by cpldcpu@gmail.com, Nov 3rd 2013.
+ *
+ * Benefits:
+ * - Codesize reduced by 54 bytes.
+ * - Improved robustness due to removing timeout from frame length measurement and
+ * inserted NOP after OSCCAL writes.
+ *
+ * Changes:
+ * - The new routine performs a combined binary and neighborhood search
+ * in a single loop.
+ * Note that the neighborhood search is necessary due to the quasi-monotonic
+ * nature of OSCCAL. (See Atmel application note AVR054).
+ * - Inserted NOP after writes to OSCCAL to avoid CPU errors during oscillator
+ * stabilization.
+ * - Implemented new routine to measure frame time "usbMeasureFrameLengthDecreasing".
+ * This routine takes the target time as a parameter and returns the deviation.
+ * - usbMeasureFrameLengthDecreasing measures in multiples of 5 cycles and is thus
+ * slighly more accurate.
+ * - usbMeasureFrameLengthDecreasing does not support time out anymore. The original
+ * implementation returned zero in case of time out, which would have caused the old
+ * calibrateOscillator() implementation to increase OSSCAL to 255, effictively
+ * overclocking and most likely crashing the CPU. The new implementation will enter
+ * an infinite loop when no USB activity is encountered. The user program should
+ * use the watchdog to escape from situations like this.
+ *
+ * This routine will work both on controllers with and without split OSCCAL range.
+ * The first trial value is 128 which is the lowest value of the upper OSCCAL range
+ * on Attiny85 and will effectively limit the search to the upper range, unless the
+ * RC oscillator frequency is unusually high. Under normal operation, the highest
+ * tested frequency setting is 192. This corresponds to ~20 Mhz core frequency and
+ * is still within spec for a 5V device.
*/
+
void calibrateOscillator(void)
{
-uchar step = 128;
-uchar trialValue = 0, optimumValue;
-int x, optimumDev, targetValue = (unsigned)(1499 * (double)F_CPU / 10.5e6 + 0.5);
-
- /* do a binary search: */
- do{
- OSCCAL = trialValue + step;
- x = usbMeasureFrameLength(); /* proportional to current real frequency */
- if(x < targetValue) /* frequency still too low */
- trialValue += step;
- step >>= 1;
- }while(step > 0);
- /* We have a precision of +/- 1 for optimum OSCCAL here */
- /* now do a neighborhood search for optimum value */
- optimumValue = trialValue;
- optimumDev = x; /* this is certainly far away from optimum */
- for(OSCCAL = trialValue - 1; OSCCAL <= trialValue + 1; OSCCAL++){
- x = usbMeasureFrameLength() - targetValue;
- if(x < 0)
- x = -x;
- if(x < optimumDev){
- optimumDev = x;
- optimumValue = OSCCAL;
- }
- }
- OSCCAL = optimumValue;
+ uchar step, trialValue, optimumValue;
+ int x, optimumDev, targetValue;
+ uchar i;
+
+ targetValue = (unsigned)((double)F_CPU * 999e-6 / 5.0 + 0.5); /* Time is measured in multiples of 5 cycles. Target is 0.999µs */
+ optimumDev = 0x7f00; // set to high positive value
+ optimumValue = OSCCAL;
+ step=64;
+ trialValue = 128;
+
+ /*
+ Performs seven iterations of a binary search (stepwidth decreasing9
+ with three additional steps of a neighborhood search (step=1, trialvalue will oscillate around target value to find optimum)
+ */
+
+ for(i=0; i<10; i++){
+ OSCCAL = trialValue;
+ asm volatile(" NOP");
+
+ x = usbMeasureFrameLengthDecreasing(targetValue);
+
+ if(x < 0) /* frequency too high */
+ {
+ trialValue -= step;
+ x = -x;
+ }
+ else /* frequency too low */
+ {
+ trialValue += step;
+ }
+
+ /*
+ Halve stepwidth to perform binary search. Logical oring with 1 to ensure step is never equal to zero.
+ This results in a neighborhood search with stepwidth 1 after binary search is finished.
+ */
+
+ step >>= 1;
+ step |=1;
+
+ if(x < optimumDev){
+ optimumDev = x;
+ optimumValue = OSCCAL;
+ }
+ }
+
+ OSCCAL = optimumValue;
+ asm volatile(" NOP");
}
+
/*
Note: This calibration algorithm may try OSCCAL values of up to 192 even if
the optimum value is far below 192. It may therefore exceed the allowed clock
diff --git a/firmware/main.c b/firmware/main.c
index 527923e..948b880 100644
--- a/firmware/main.c
+++ b/firmware/main.c
@@ -395,7 +395,7 @@ static inline void leaveBootloader(void) {
//DBG1(0x01, 0, 0);
bootLoaderExit();
cli();
- usbDeviceDisconnect(); /* do this while interrupts are disabled */
+ usbDeviceDisconnect(); /* Disconnect micronucleus */
USB_INTR_ENABLE = 0;
USB_INTR_CFG = 0; /* also reset config bits */
@@ -410,11 +410,8 @@ static inline void leaveBootloader(void) {
// TODO: Test this and find out, do we need the +1 offset?
unsigned char stored_osc_calibration = pgm_read_byte(BOOTLOADER_ADDRESS - TINYVECTOR_OSCCAL_OFFSET);
if (stored_osc_calibration != 0xFF && stored_osc_calibration != 0x00) {
- //OSCCAL = stored_osc_calibration; // this should really be a gradual change, but maybe it's alright anyway?
- // do the gradual change - failed to score extra free bytes anyway in 1.06
-
- while (OSCCAL > stored_osc_calibration) OSCCAL--;
- while (OSCCAL < stored_osc_calibration) OSCCAL++;
+ OSCCAL=stored_osc_calibration;
+ asm volatile("nop");
}
#endif
// jump to application reset vector at end of flash
@@ -429,13 +426,12 @@ int main(void) {
#if (!SET_CLOCK_PRESCALER) && LOW_POWER_MODE
uint8_t prescaler_default = CLKPR;
#endif
-
- MCUSR=0;
+
+ MCUSR=0; /* clean wdt reset bit if reset occured due to wdt */
wdt_disable(); /* main app may have enabled watchdog */
tiny85FlashInit();
bootLoaderInit();
-
-
+
if (bootLoaderStartCondition()) {
#if LOW_POWER_MODE
// turn off clock prescalling - chip must run at full speed for usb
@@ -444,9 +440,13 @@ int main(void) {
CLKPR = 0;
#endif
+ #ifdef NANITE
+ PORTB &=~_BV(NANITE_CTRLPIN);
+ #endif
initForUsbConnectivity();
do {
- usbPoll();
+
+ usbPoll();
_delay_us(100);
// these next two freeze the chip for ~ 4.5ms, breaking usb protocol
@@ -455,6 +455,11 @@ int main(void) {
if (isEvent(EVENT_ERASE_APPLICATION)) eraseApplication();
if (isEvent(EVENT_WRITE_PAGE)) tiny85FlashWrites();
+ #ifdef NANITE
+ DDRB |= _BV(NANITE_CTRLPIN);
+ if (((unsigned char*)&idlePolls)[1]&0xd) DDRB &=~_BV(NANITE_CTRLPIN);
+ #endif
+
# if BOOTLOADER_CAN_EXIT
if (isEvent(EVENT_EXECUTE)) { // when host requests device run uploaded program
break;
@@ -462,7 +467,7 @@ int main(void) {
# endif
clearEvents();
-
+
} while(bootLoaderCondition()); /* main event loop runs so long as bootLoaderCondition remains truthy */
}
@@ -476,10 +481,12 @@ int main(void) {
CLKPR = prescaler_default;
#endif
#endif
+
- // slowly bring down OSCCAL to it's original value before launching in to user program
#ifdef RESTORE_OSCCAL
- while (OSCCAL > osccal_default) { OSCCAL -= 1; }
+
+ OSCCAL=osccal_default;
+ asm volatile("nop"); // NOP to avoid CPU hickup during osccillator stabilization
#endif
leaveBootloader();
}
diff --git a/firmware/main_old.c b/firmware/main_old.c
new file mode 100644
index 0000000..527923e
--- /dev/null
+++ b/firmware/main_old.c
@@ -0,0 +1,487 @@
+/* Name: main.c
+ * Project: Micronucleus
+ * Author: Jenna Fox
+ * Creation Date: 2007-12-08
+ * Tabsize: 4
+ * Copyright: (c) 2012 Jenna Fox
+ * Portions Copyright: (c) 2007 by OBJECTIVE DEVELOPMENT Software GmbH (USBaspLoader)
+ * Portions Copyright: (c) 2012 Louis Beaudoin (USBaspLoader-tiny85)
+ * License: GNU GPL v2 (see License.txt)
+ */
+
+#define MICRONUCLEUS_VERSION_MAJOR 1
+#define MICRONUCLEUS_VERSION_MINOR 6
+// how many milliseconds should host wait till it sends another erase or write?
+// needs to be above 4.5 (and a whole integer) as avr freezes for 4.5ms
+#define MICRONUCLEUS_WRITE_SLEEP 8
+
+// Use the old delay routines without NOP padding. This saves memory.
+#define __DELAY_BACKWARD_COMPATIBLE__
+
+
+#include <avr/io.h>
+#include <avr/interrupt.h>
+#include <avr/pgmspace.h>
+#include <avr/wdt.h>
+#include <avr/boot.h>
+//#include <avr/eeprom.h>
+#include <util/delay.h>
+//#include <string.h>
+
+static void leaveBootloader() __attribute__((__noreturn__));
+
+#include "bootloaderconfig.h"
+#include "usbdrv/usbdrv.c"
+
+/* ------------------------------------------------------------------------ */
+
+#ifndef ulong
+# define ulong unsigned long
+#endif
+#ifndef uint
+# define uint unsigned int
+#endif
+
+#ifndef BOOTLOADER_CAN_EXIT
+# define BOOTLOADER_CAN_EXIT 0
+#endif
+
+/* allow compatibility with avrusbboot's bootloaderconfig.h: */
+#ifdef BOOTLOADER_INIT
+# define bootLoaderInit() BOOTLOADER_INIT
+# define bootLoaderExit()
+#endif
+#ifdef BOOTLOADER_CONDITION
+# define bootLoaderCondition() BOOTLOADER_CONDITION
+#endif
+
+/* device compatibility: */
+#ifndef GICR /* ATMega*8 don't have GICR, use MCUCR instead */
+# define GICR MCUCR
+#endif
+
+/* ------------------------------------------------------------------------ */
+
+#define addr_t uint
+
+// typedef union longConverter{
+// addr_t l;
+// uint w[sizeof(addr_t)/2];
+// uchar b[sizeof(addr_t)];
+// } longConverter_t;
+
+//////// Stuff Bluebie Added
+// postscript are the few bytes at the end of programmable memory which store tinyVectors
+// and used to in USBaspLoader-tiny85 store the checksum iirc
+#define POSTSCRIPT_SIZE 6
+#define PROGMEM_SIZE (BOOTLOADER_ADDRESS - POSTSCRIPT_SIZE) /* max size of user program */
+
+// verify the bootloader address aligns with page size
+#if BOOTLOADER_ADDRESS % SPM_PAGESIZE != 0
+# error "BOOTLOADER_ADDRESS in makefile must be a multiple of chip's pagesize"
+#endif
+
+#ifdef AUTO_EXIT_MS
+# if AUTO_EXIT_MS < (MICRONUCLEUS_WRITE_SLEEP * (BOOTLOADER_ADDRESS / SPM_PAGESIZE))
+# warning "AUTO_EXIT_MS is shorter than the time it takes to perform erase function - might affect reliability?"
+# warning "Try increasing AUTO_EXIT_MS if you have stability problems"
+# endif
+#endif
+
+// events system schedules functions to run in the main loop
+static uchar events = 0; // bitmap of events to run
+#define EVENT_ERASE_APPLICATION 1
+#define EVENT_WRITE_PAGE 2
+#define EVENT_EXECUTE 4
+
+// controls state of events
+#define fireEvent(event) events |= (event)
+#define isEvent(event) (events & (event))
+#define clearEvents() events = 0
+
+// length of bytes to write in to flash memory in upcoming usbFunctionWrite calls
+//static unsigned char writeLength;
+
+// becomes 1 when some programming happened
+// lets leaveBootloader know if needs to finish up the programming
+static uchar didWriteSomething = 0;
+
+uint16_t idlePolls = 0; // how long have we been idle?
+
+static uint16_t vectorTemp[2]; // remember data to create tinyVector table before BOOTLOADER_ADDRESS
+static addr_t currentAddress; // current progmem address, used for erasing and writing
+
+#ifdef RESTORE_OSCCAL
+ static uint8_t osccal_default; // due to compiler insanity, having this as global actually saves memory
+#endif
+
+/* ------------------------------------------------------------------------ */
+static inline void eraseApplication(void);
+static void writeFlashPage(void);
+static void writeWordToPageBuffer(uint16_t data);
+static void fillFlashWithVectors(void);
+static uchar usbFunctionSetup(uchar data[8]);
+static uchar usbFunctionWrite(uchar *data, uchar length);
+static inline void initForUsbConnectivity(void);
+static inline void tiny85FlashInit(void);
+static inline void tiny85FlashWrites(void);
+//static inline void tiny85FinishWriting(void);
+static inline void leaveBootloader(void);
+
+// erase any existing application and write in jumps for usb interrupt and reset to bootloader
+// - Because flash can be erased once and programmed several times, we can write the bootloader
+// - vectors in now, and write in the application stuff around them later.
+// - if vectors weren't written back in immediately, usb would fail.
+static inline void eraseApplication(void) {
+ // erase all pages until bootloader, in reverse order (so our vectors stay in place for as long as possible)
+ // while the vectors don't matter for usb comms as interrupts are disabled during erase, it's important
+ // to minimise the chance of leaving the device in a state where the bootloader wont run, if there's power failure
+ // during upload
+ addr_t ptr = BOOTLOADER_ADDRESS;
+
+ cli();
+ while (ptr) {
+ ptr -= SPM_PAGESIZE;
+
+ boot_page_erase(ptr);
+ boot_spm_busy_wait();
+ }
+
+ currentAddress = 0;
+ fillFlashWithVectors();
+ sei();
+}
+
+// simply write currently stored page in to already erased flash memory
+static void writeFlashPage(void) {
+ uint8_t previous_sreg = SREG; // backup current interrupt setting
+ didWriteSomething = 1;
+ cli();
+ boot_page_write(currentAddress - 2);
+ boot_spm_busy_wait(); // Wait until the memory is written.
+ SREG = previous_sreg; // restore interrupts to previous state
+}
+
+// clear memory which stores data to be written by next writeFlashPage call
+#define __boot_page_fill_clear() \
+(__extension__({ \
+ __asm__ __volatile__ \
+ ( \
+ "sts %0, %1\n\t" \
+ "spm\n\t" \
+ : \
+ : "i" (_SFR_MEM_ADDR(__SPM_REG)), \
+ "r" ((uint8_t)(__BOOT_PAGE_FILL | (1 << CTPB))) \
+ ); \
+}))
+
+// write a word in to the page buffer, doing interrupt table modifications where they're required
+static void writeWordToPageBuffer(uint16_t data) {
+ uint8_t previous_sreg;
+
+ // first two interrupt vectors get replaced with a jump to the bootloader's vector table
+ if (currentAddress == (RESET_VECTOR_OFFSET * 2) || currentAddress == (USBPLUS_VECTOR_OFFSET * 2)) {
+ data = 0xC000 + (BOOTLOADER_ADDRESS/2) - 1;
+ }
+
+ // at end of page just before bootloader, write in tinyVector table
+ // see http://embedded-creations.com/projects/attiny85-usb-bootloader-overview/avr-jtag-programmer/
+ // for info on how the tiny vector table works
+ if (currentAddress == BOOTLOADER_ADDRESS - TINYVECTOR_RESET_OFFSET) {
+ data = vectorTemp[0] + ((FLASHEND + 1) - BOOTLOADER_ADDRESS)/2 + 2 + RESET_VECTOR_OFFSET;
+ } else if (currentAddress == BOOTLOADER_ADDRESS - TINYVECTOR_USBPLUS_OFFSET) {
+ data = vectorTemp[1] + ((FLASHEND + 1) - BOOTLOADER_ADDRESS)/2 + 1 + USBPLUS_VECTOR_OFFSET;
+#ifndef RESTORE_OSCCAL
+ } else if (currentAddress == BOOTLOADER_ADDRESS - TINYVECTOR_OSCCAL_OFFSET) {
+ data = OSCCAL;
+#endif
+ }
+
+
+ // clear page buffer as a precaution before filling the buffer on the first page
+ // in case the bootloader somehow ran after user program and there was something
+ // in the page buffer already
+ if (currentAddress == 0x0000) __boot_page_fill_clear();
+
+ previous_sreg = SREG; // backup previous interrupt settings
+ cli(); // ensure interrupts are disabled
+ boot_page_fill(currentAddress, data);
+ SREG = previous_sreg; // restore previous interrupt setting
+
+ // only need to erase if there is data already in the page that doesn't match what we're programming
+ // TODO: what about this: if (pgm_read_word(currentAddress) & data != data) { ??? should work right?
+ //if (pgm_read_word(currentAddress) != data && pgm_read_word(currentAddress) != 0xFFFF) {
+ //if ((pgm_read_word(currentAddress) & data) != data) {
+ // fireEvent(EVENT_PAGE_NEEDS_ERASE);
+ //}
+
+ // increment progmem address by one word
+ currentAddress += 2;
+}
+
+// fills the rest of this page with vectors - interrupt vector or tinyvector tables where needed
+static void fillFlashWithVectors(void) {
+ //int16_t i;
+ //
+ // fill all or remainder of page with 0xFFFF (as if unprogrammed)
+ //for (i = currentAddress % SPM_PAGESIZE; i < SPM_PAGESIZE; i += 2) {
+ // writeWordToPageBuffer(0xFFFF); // is where vector tables are sorted out
+ //}
+
+ // TODO: Or more simply:
+
+
+#if SPM_PAGESIZE<256
+ do {
+ writeWordToPageBuffer(0xFFFF);
+ } while ((uchar)currentAddress % SPM_PAGESIZE);
+#else
+ do {
+ writeWordToPageBuffer(0xFFFF);
+ } while (currentAddress % SPM_PAGESIZE);
+#endif
+
+
+ writeFlashPage();
+}
+
+/* ------------------------------------------------------------------------ */
+
+static uchar usbFunctionSetup(uchar data[8]) {
+ usbRequest_t *rq = (void *)data;
+ idlePolls = 0; // reset idle polls when we get usb traffic
+
+ static uchar replyBuffer[4] = {
+ (((uint)PROGMEM_SIZE) >> 8) & 0xff,
+ ((uint)PROGMEM_SIZE) & 0xff,
+ SPM_PAGESIZE,
+ MICRONUCLEUS_WRITE_SLEEP
+ };
+
+ if (rq->bRequest == 0) { // get device info
+ usbMsgPtr = replyBuffer;
+ return 4;
+
+ } else if (rq->bRequest == 1) { // write page
+ //writeLength = rq->wValue.word;
+ currentAddress = rq->wIndex.word;
+
+ return USB_NO_MSG; // hands off work to usbFunctionWrite
+
+ } else if (rq->bRequest == 2) { // erase application
+ fireEvent(EVENT_ERASE_APPLICATION);
+
+ } else { // exit bootloader
+# if BOOTLOADER_CAN_EXIT
+ fireEvent(EVENT_EXECUTE);
+# endif
+ }
+
+ return 0;
+}
+
+
+// read in a page over usb, and write it in to the flash write buffer
+static uchar usbFunctionWrite(uchar *data, uchar length) {
+ //if (length > writeLength) length = writeLength; // test for missing final page bug
+ //writeLength -= length;
+
+ do {
+ // remember vectors or the tinyvector table
+ if (currentAddress == RESET_VECTOR_OFFSET * 2) {
+ vectorTemp[0] = *(short *)data;
+ }
+
+ if (currentAddress == USBPLUS_VECTOR_OFFSET * 2) {
+ vectorTemp[1] = *(short *)data;
+ }
+
+ // make sure we don't write over the bootloader!
+ if (currentAddress >= BOOTLOADER_ADDRESS) {
+ //__boot_page_fill_clear();
+ break;
+ }
+
+ writeWordToPageBuffer(*(uint16_t *) data);
+ data += 2; // advance data pointer
+ length -= 2;
+ } while(length);
+
+ // if we have now reached another page boundary, we're done
+ //uchar isLast = (writeLength == 0);
+
+#if SPM_PAGESIZE<256
+ // Hack to reduce code size
+ uchar isLast = ((((uchar)currentAddress) % SPM_PAGESIZE) == 0);
+#else
+ uchar isLast = ((currentAddress % SPM_PAGESIZE) == 0);
+#endif
+
+ // definitely need this if! seems usbFunctionWrite gets called again in future usbPoll's in the runloop!
+ if (isLast) fireEvent(EVENT_WRITE_PAGE); // ask runloop to write our page
+
+ return isLast; // let vusb know we're done with this request
+}
+
+/* ------------------------------------------------------------------------ */
+
+void PushMagicWord (void) __attribute__ ((naked)) __attribute__ ((section (".init3")));
+
+// put the word "B007" at the bottom of the stack (RAMEND - RAMEND-1)
+void PushMagicWord (void) {
+ asm volatile("ldi r16, 0xB0"::);
+ asm volatile("push r16"::);
+ asm volatile("ldi r16, 0x07"::);
+ asm volatile("push r16"::);
+}
+
+/* ------------------------------------------------------------------------ */
+
+static inline void initForUsbConnectivity(void) {
+ usbInit();
+ /* enforce USB re-enumerate: */
+ usbDeviceDisconnect(); /* do this while interrupts are disabled */
+ _delay_ms(500);
+ usbDeviceConnect();
+ sei();
+}
+
+static inline void tiny85FlashInit(void) {
+ // check for erased first page (no bootloader interrupt vectors), add vectors if missing
+ // this needs to happen for usb communication to work later - essential to first run after bootloader
+ // being installed
+
+ if(pgm_read_byte(RESET_VECTOR_OFFSET * 2+1) == 0xff) fillFlashWithVectors(); // write vectors if flash is empty
+
+ // TODO: necessary to reset currentAddress?
+ currentAddress = 0;
+}
+
+static inline void tiny85FlashWrites(void) {
+ _delay_us(2000); // TODO: why is this here? - it just adds pointless two level deep loops seems like?
+ // write page to flash, interrupts will be disabled for > 4.5ms including erase
+
+ // TODO: Do we need this? Wouldn't the programmer always send full sized pages?
+
+#if SPM_PAGESIZE<256
+ // Hack to reduce code size
+ if ((uchar)currentAddress % SPM_PAGESIZE)
+#else
+ if (currentAddress % SPM_PAGESIZE)
+#endif
+ {
+ // when we aren't perfectly aligned to a flash page boundary
+ fillFlashWithVectors(); // fill up the rest of the page with 0xFFFF (unprogrammed) bits
+ } else {
+ writeFlashPage(); // otherwise just write it
+ }
+}
+
+// finishes up writing to the flash, including adding the tinyVector tables at the end of memory
+// TODO: can this be simplified? EG: currentAddress = PROGMEM_SIZE; fillFlashWithVectors();
+// static inline void tiny85FinishWriting(void) {
+// // make sure remainder of flash is erased and write checksum and application reset vectors
+// if (didWriteSomething) {
+// while (currentAddress < BOOTLOADER_ADDRESS) {
+// fillFlashWithVectors();
+// }
+// }
+// }
+
+// reset system to a normal state and launch user program
+static inline void leaveBootloader(void) {
+ _delay_ms(10); // removing delay causes USB errors
+
+ //DBG1(0x01, 0, 0);
+ bootLoaderExit();
+ cli();
+ usbDeviceDisconnect(); /* do this while interrupts are disabled */
+
+ USB_INTR_ENABLE = 0;
+ USB_INTR_CFG = 0; /* also reset config bits */
+
+ // clear magic word from bottom of stack before jumping to the app
+ *(uint8_t*)(RAMEND) = 0x00; // A single write is sufficient to invalidate magic word
+ // *(uint8_t*)(RAMEND-1) = 0x00;
+
+#ifndef RESTORE_OSCCAL
+ // adjust clock to previous calibration value, so user program always starts with same calibration
+ // as when it was uploaded originally
+ // TODO: Test this and find out, do we need the +1 offset?
+ unsigned char stored_osc_calibration = pgm_read_byte(BOOTLOADER_ADDRESS - TINYVECTOR_OSCCAL_OFFSET);
+ if (stored_osc_calibration != 0xFF && stored_osc_calibration != 0x00) {
+ //OSCCAL = stored_osc_calibration; // this should really be a gradual change, but maybe it's alright anyway?
+ // do the gradual change - failed to score extra free bytes anyway in 1.06
+
+ while (OSCCAL > stored_osc_calibration) OSCCAL--;
+ while (OSCCAL < stored_osc_calibration) OSCCAL++;
+ }
+#endif
+ // jump to application reset vector at end of flash
+ asm volatile ("rjmp __vectors - 4");
+}
+
+int main(void) {
+ /* initialize */
+ #ifdef RESTORE_OSCCAL
+ osccal_default = OSCCAL;
+ #endif
+ #if (!SET_CLOCK_PRESCALER) && LOW_POWER_MODE
+ uint8_t prescaler_default = CLKPR;
+ #endif
+
+ MCUSR=0;
+ wdt_disable(); /* main app may have enabled watchdog */
+ tiny85FlashInit();
+ bootLoaderInit();
+
+
+ if (bootLoaderStartCondition()) {
+ #if LOW_POWER_MODE
+ // turn off clock prescalling - chip must run at full speed for usb
+ // if you might run chip at lower voltages, detect that in bootLoaderStartCondition
+ CLKPR = 1 << CLKPCE;
+ CLKPR = 0;
+ #endif
+
+ initForUsbConnectivity();
+ do {
+ usbPoll();
+ _delay_us(100);
+
+ // these next two freeze the chip for ~ 4.5ms, breaking usb protocol
+ // and usually both of these will activate in the same loop, so host
+ // needs to wait > 9ms before next usb request
+ if (isEvent(EVENT_ERASE_APPLICATION)) eraseApplication();
+ if (isEvent(EVENT_WRITE_PAGE)) tiny85FlashWrites();
+
+# if BOOTLOADER_CAN_EXIT
+ if (isEvent(EVENT_EXECUTE)) { // when host requests device run uploaded program
+ break;
+ }
+# endif
+
+ clearEvents();
+
+ } while(bootLoaderCondition()); /* main event loop runs so long as bootLoaderCondition remains truthy */
+ }
+
+ // set clock prescaler to desired clock speed (changing from clkdiv8, or no division, depending on fuses)
+ #if LOW_POWER_MODE
+ #ifdef SET_CLOCK_PRESCALER
+ CLKPR = 1 << CLKPCE;
+ CLKPR = SET_CLOCK_PRESCALER;
+ #else
+ CLKPR = 1 << CLKPCE;
+ CLKPR = prescaler_default;
+ #endif
+ #endif
+
+ // slowly bring down OSCCAL to it's original value before launching in to user program
+ #ifdef RESTORE_OSCCAL
+ while (OSCCAL > osccal_default) { OSCCAL -= 1; }
+ #endif
+ leaveBootloader();
+}
+
+/* ------------------------------------------------------------------------ */
diff --git a/firmware/usbdrv/Changelog.txt b/firmware/usbdrv/Changelog.txt
index 5c6354a..79b5215 100644
--- a/firmware/usbdrv/Changelog.txt
+++ b/firmware/usbdrv/Changelog.txt
@@ -306,3 +306,24 @@ Scroll down to the bottom to see the most recent changes.
endpoint now.
* Release 2010-07-15
+
+ - Fixed bug in usbDriverSetup() which prevented descriptor sizes above 255
+ bytes.
+ - Avoid a compiler warning for unused parameter in usbHandleResetHook() when
+ compiler option -Wextra is enabled.
+ - Fixed wrong hex value for some IDs in USB-IDs-for-free.txt.
+ - Keep a define for USBATTR_BUSPOWER, although the flag does not exist
+ in USB 1.1 any more. Set it to 0. This is for backward compatibility.
+
+* Release 2012-01-09
+
+ - Define a separate (defined) type for usbMsgPtr so that projects using a
+ tiny memory model can define it to an 8 bit type in usbconfig.h. This
+ change also saves a couple of bytes when using a scalar 16 bit type.
+ - Inserted "const" keyword for all PROGMEM declarations because new GCC
+ requires it.
+ - Fixed problem with dependence of usbportability.h on usbconfig.h. This
+ problem occurred with IAR CC only.
+ - Prepared repository for github.com.
+
+* Release 2012-12-06 \ No newline at end of file
diff --git a/firmware/usbdrv/CommercialLicense.txt b/firmware/usbdrv/CommercialLicense.txt
index 11d07d9..de1a2b0 100644
--- a/firmware/usbdrv/CommercialLicense.txt
+++ b/firmware/usbdrv/CommercialLicense.txt
@@ -1,5 +1,5 @@
V-USB Driver Software License Agreement
-Version 2009-08-03
+Version 2012-07-09
THIS LICENSE AGREEMENT GRANTS YOU CERTAIN RIGHTS IN A SOFTWARE. YOU CAN
ENTER INTO THIS AGREEMENT AND ACQUIRE THE RIGHTS OUTLINED BELOW BY PAYING
@@ -37,10 +37,10 @@ Product ID(s), sent to you in e-mail. These Product IDs are reserved
exclusively for you. OBJECTIVE DEVELOPMENT has obtained USB Product ID
ranges under the Vendor ID 5824 from Wouter van Ooijen (Van Ooijen
Technische Informatica, www.voti.nl) and under the Vendor ID 8352 from
-Jason Kotzin (Clay Logic, www.claylogic.com). Both owners of the Vendor IDs
-have obtained these IDs from the USB Implementers Forum, Inc.
-(www.usb.org). OBJECTIVE DEVELOPMENT disclaims all liability which might
-arise from the assignment of USB IDs.
+Jason Kotzin (now flirc.tv, Inc.). Both owners of the Vendor IDs have
+obtained these IDs from the USB Implementers Forum, Inc. (www.usb.org).
+OBJECTIVE DEVELOPMENT disclaims all liability which might arise from the
+assignment of USB IDs.
2.5 USB Certification. Although not part of this agreement, we want to make
it clear that you cannot become USB certified when you use V-USB or a USB
diff --git a/firmware/usbdrv/USB-ID-FAQ.txt b/firmware/usbdrv/USB-ID-FAQ.txt
index d1de8fb..a4a6bd6 100644
--- a/firmware/usbdrv/USB-ID-FAQ.txt
+++ b/firmware/usbdrv/USB-ID-FAQ.txt
@@ -1,4 +1,4 @@
-Version 2009-08-22
+Version 2012-07-09
==========================
WHY DO WE NEED THESE IDs?
@@ -107,8 +107,8 @@ WHO IS THE OWNER OF THE VENDOR-ID?
Objective Development has obtained ranges of USB Product-IDs under two
Vendor-IDs: Under Vendor-ID 5824 from Wouter van Ooijen (Van Ooijen
Technische Informatica, www.voti.nl) and under Vendor-ID 8352 from Jason
-Kotzin (Clay Logic, www.claylogic.com). Both VID owners have received their
-Vendor-ID directly from usb.org.
+Kotzin (now flirc.tv, Inc.). Both VID owners have received their Vendor-ID
+directly from usb.org.
=========================================================================
diff --git a/firmware/usbdrv/USB-IDs-for-free.txt b/firmware/usbdrv/USB-IDs-for-free.txt
index 2f4d59a..d46517d 100644
--- a/firmware/usbdrv/USB-IDs-for-free.txt
+++ b/firmware/usbdrv/USB-IDs-for-free.txt
@@ -86,8 +86,9 @@ If you use one of the IDs listed below, your device and host-side software
must conform to these rules:
(1) The USB device MUST provide a textual representation of the serial
-number. The serial number string MUST be available at least in USB language
-0x0409 (English/US).
+number, unless ONLY the operating system's default class driver is used.
+The serial number string MUST be available at least in USB language 0x0409
+(English/US).
(2) The serial number MUST start with either an Internet domain name (e.g.
"mycompany.com") registered and owned by you, or an e-mail address under your
@@ -108,6 +109,11 @@ driver for Vendor Class devices is needed, this driver must be libusb or
libusb-win32 (see http://libusb.org/ and
http://libusb-win32.sourceforge.net/).
+(7) If ONLY the operating system's default class driver is used, e.g. for
+mice, keyboards, joysticks, CDC or MIDI devices and no discrimination by an
+application is needed, the serial number may be omitted.
+
+
Table if IDs for discrimination by serial number string:
PID dec (hex) | VID dec (hex) | Description of use
@@ -121,11 +127,11 @@ PID dec (hex) | VID dec (hex) | Description of use
---------------+---------------+-------------------------------------------
10203 (0x27db) | 5824 (0x16c0) | For USB Keyboards
---------------+---------------+-------------------------------------------
-10204 (0x27db) | 5824 (0x16c0) | For USB Joysticks
+10204 (0x27dc) | 5824 (0x16c0) | For USB Joysticks
---------------+---------------+-------------------------------------------
-10205 (0x27dc) | 5824 (0x16c0) | For CDC-ACM class devices (modems)
+10205 (0x27dd) | 5824 (0x16c0) | For CDC-ACM class devices (modems)
---------------+---------------+-------------------------------------------
-10206 (0x27dd) | 5824 (0x16c0) | For MIDI class devices
+10206 (0x27de) | 5824 (0x16c0) | For MIDI class devices
---------------+---------------+-------------------------------------------
diff --git a/firmware/usbdrv/asmcommon.inc b/firmware/usbdrv/asmcommon.inc
index 07d692b..d2a4f7c 100644
--- a/firmware/usbdrv/asmcommon.inc
+++ b/firmware/usbdrv/asmcommon.inc
@@ -5,7 +5,6 @@
* 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$
*/
/* Do not link this file! Link usbdrvasm.S instead, which includes the
diff --git a/firmware/usbdrv/oddebug.c b/firmware/usbdrv/oddebug.c
index 945457c..19bf142 100644
--- a/firmware/usbdrv/oddebug.c
+++ b/firmware/usbdrv/oddebug.c
@@ -5,7 +5,6 @@
* 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 Revision: $Id: oddebug.c 692 2008-11-07 15:07:40Z cs $
*/
#include "oddebug.h"
diff --git a/firmware/usbdrv/oddebug.h b/firmware/usbdrv/oddebug.h
index d61309d..851f84d 100644
--- a/firmware/usbdrv/oddebug.h
+++ b/firmware/usbdrv/oddebug.h
@@ -5,7 +5,6 @@
* 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 Revision: $Id: oddebug.h 692 2008-11-07 15:07:40Z cs $
*/
#ifndef __oddebug_h_included__
diff --git a/firmware/usbdrv/usbconfig-prototype.h b/firmware/usbdrv/usbconfig-prototype.h
index 847710e..93721c2 100644
--- a/firmware/usbdrv/usbconfig-prototype.h
+++ b/firmware/usbdrv/usbconfig-prototype.h
@@ -5,7 +5,6 @@
* 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 Revision: $Id: usbconfig-prototype.h 785 2010-05-30 17:57:07Z cs $
*/
#ifndef __usbconfig_h_included__
@@ -356,6 +355,15 @@ section at the end of this file).
#define USB_CFG_DESCR_PROPS_HID_REPORT 0
#define USB_CFG_DESCR_PROPS_UNKNOWN 0
+
+#define usbMsgPtr_t unsigned short
+/* If usbMsgPtr_t is not defined, it defaults to 'uchar *'. We define it to
+ * a scalar type here because gcc generates slightly shorter code for scalar
+ * arithmetics than for pointer arithmetics. Remove this define for backward
+ * type compatibility or define it to an 8 bit type if you use data in RAM only
+ * and all RAM is below 256 bytes (tiny memory model in IAR CC).
+ */
+
/* ----------------------- Optional MCU Description ------------------------ */
/* The following configurations have working defaults in usbdrv.h. You
diff --git a/firmware/usbdrv/usbdrv.c b/firmware/usbdrv/usbdrv.c
index 21ed554..d838935 100644
--- a/firmware/usbdrv/usbdrv.c
+++ b/firmware/usbdrv/usbdrv.c
@@ -5,10 +5,8 @@
* 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 Revision: $Id: usbdrv.c 791 2010-07-15 15:56:13Z cs $
*/
-#include "usbportability.h"
#include "usbdrv.h"
#include "oddebug.h"
@@ -45,7 +43,7 @@ uchar usbCurrentDataToken;/* when we check data toggling to ignore duplica
#endif
/* USB status registers / not shared with asm code */
-uchar *usbMsgPtr; /* data to transmit next -- ROM or RAM address */
+usbMsgPtr_t usbMsgPtr; /* data to transmit next -- ROM or RAM address */
static usbMsgLen_t usbMsgLen = USB_NO_MSG; /* remaining number of bytes */
static uchar usbMsgFlags; /* flag values see below */
@@ -67,7 +65,7 @@ optimizing hints:
#if USB_CFG_DESCR_PROPS_STRING_0 == 0
#undef USB_CFG_DESCR_PROPS_STRING_0
#define USB_CFG_DESCR_PROPS_STRING_0 sizeof(usbDescriptorString0)
-PROGMEM char usbDescriptorString0[] = { /* language descriptor */
+PROGMEM const char usbDescriptorString0[] = { /* language descriptor */
4, /* sizeof(usbDescriptorString0): length of descriptor in bytes */
3, /* descriptor type */
0x09, 0x04, /* language index (0x0409 = US-English) */
@@ -77,7 +75,7 @@ PROGMEM char usbDescriptorString0[] = { /* language descriptor */
#if USB_CFG_DESCR_PROPS_STRING_VENDOR == 0 && USB_CFG_VENDOR_NAME_LEN
#undef USB_CFG_DESCR_PROPS_STRING_VENDOR
#define USB_CFG_DESCR_PROPS_STRING_VENDOR sizeof(usbDescriptorStringVendor)
-PROGMEM int usbDescriptorStringVendor[] = {
+PROGMEM const int usbDescriptorStringVendor[] = {
USB_STRING_DESCRIPTOR_HEADER(USB_CFG_VENDOR_NAME_LEN),
USB_CFG_VENDOR_NAME
};
@@ -86,7 +84,7 @@ PROGMEM int usbDescriptorStringVendor[] = {
#if USB_CFG_DESCR_PROPS_STRING_PRODUCT == 0 && USB_CFG_DEVICE_NAME_LEN
#undef USB_CFG_DESCR_PROPS_STRING_PRODUCT
#define USB_CFG_DESCR_PROPS_STRING_PRODUCT sizeof(usbDescriptorStringDevice)
-PROGMEM int usbDescriptorStringDevice[] = {
+PROGMEM const int usbDescriptorStringDevice[] = {
USB_STRING_DESCRIPTOR_HEADER(USB_CFG_DEVICE_NAME_LEN),
USB_CFG_DEVICE_NAME
};
@@ -95,7 +93,7 @@ PROGMEM int usbDescriptorStringDevice[] = {
#if USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER == 0 && USB_CFG_SERIAL_NUMBER_LEN
#undef USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER
#define USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER sizeof(usbDescriptorStringSerialNumber)
-PROGMEM int usbDescriptorStringSerialNumber[] = {
+PROGMEM const int usbDescriptorStringSerialNumber[] = {
USB_STRING_DESCRIPTOR_HEADER(USB_CFG_SERIAL_NUMBER_LEN),
USB_CFG_SERIAL_NUMBER
};
@@ -108,7 +106,7 @@ PROGMEM int usbDescriptorStringSerialNumber[] = {
#if USB_CFG_DESCR_PROPS_DEVICE == 0
#undef USB_CFG_DESCR_PROPS_DEVICE
#define USB_CFG_DESCR_PROPS_DEVICE sizeof(usbDescriptorDevice)
-PROGMEM char usbDescriptorDevice[] = { /* USB device descriptor */
+PROGMEM const char usbDescriptorDevice[] = { /* USB device descriptor */
18, /* sizeof(usbDescriptorDevice): length of descriptor in bytes */
USBDESCR_DEVICE, /* descriptor type */
0x10, 0x01, /* USB version supported */
@@ -139,7 +137,7 @@ PROGMEM char usbDescriptorDevice[] = { /* USB device descriptor */
#if USB_CFG_DESCR_PROPS_CONFIGURATION == 0
#undef USB_CFG_DESCR_PROPS_CONFIGURATION
#define USB_CFG_DESCR_PROPS_CONFIGURATION sizeof(usbDescriptorConfiguration)
-PROGMEM char usbDescriptorConfiguration[] = { /* USB configuration descriptor */
+PROGMEM const char usbDescriptorConfiguration[] = { /* USB configuration descriptor */
9, /* sizeof(usbDescriptorConfiguration): length of descriptor in bytes */
USBDESCR_CONFIG, /* descriptor type */
18 + 7 * USB_CFG_HAVE_INTRIN_ENDPOINT + 7 * USB_CFG_HAVE_INTRIN_ENDPOINT3 +
@@ -301,7 +299,7 @@ USB_PUBLIC void usbSetInterrupt3(uchar *data, uchar len)
len = usbFunctionDescriptor(rq); \
}else{ \
len = USB_PROP_LENGTH(cfgProp); \
- usbMsgPtr = (uchar *)(staticName); \
+ usbMsgPtr = (usbMsgPtr_t)(staticName); \
} \
}
@@ -361,7 +359,8 @@ uchar flags = USB_FLG_MSGPTR_IS_ROM;
*/
static inline usbMsgLen_t usbDriverSetup(usbRequest_t *rq)
{
-uchar len = 0, *dataPtr = usbTxBuf + 9; /* there are 2 bytes free space at the end of the buffer */
+usbMsgLen_t len = 0;
+uchar *dataPtr = usbTxBuf + 9; /* there are 2 bytes free space at the end of the buffer */
uchar value = rq->wValue.bytes[0];
#if USB_CFG_IMPLEMENT_HALT
uchar index = rq->wIndex.bytes[0];
@@ -408,7 +407,7 @@ uchar index = rq->wIndex.bytes[0];
SWITCH_DEFAULT /* 7=SET_DESCRIPTOR, 12=SYNC_FRAME */
/* Should we add an optional hook here? */
SWITCH_END
- usbMsgPtr = dataPtr;
+ usbMsgPtr = (usbMsgPtr_t)dataPtr;
skipMsgPtrAssignment:
return len;
}
@@ -498,7 +497,8 @@ static uchar usbDeviceRead(uchar *data, uchar len)
}else
#endif
{
- uchar i = len, *r = usbMsgPtr;
+ uchar i = len;
+ usbMsgPtr_t r = usbMsgPtr;
if(usbMsgFlags & USB_FLG_MSGPTR_IS_ROM){ /* ROM data */
do{
uchar c = USB_READ_FLASH(r); /* assign to char size variable to enforce byte ops */
@@ -507,7 +507,8 @@ static uchar usbDeviceRead(uchar *data, uchar len)
}while(--i);
}else{ /* RAM data */
do{
- *data++ = *r++;
+ *data++ = *((uchar *)r);
+ r++;
}while(--i);
}
usbMsgPtr = r;
@@ -557,6 +558,8 @@ uchar isReset = !notResetState;
USB_RESET_HOOK(isReset);
wasReset = isReset;
}
+#else
+ notResetState = notResetState; // avoid compiler warning
#endif
}
diff --git a/firmware/usbdrv/usbdrv.h b/firmware/usbdrv/usbdrv.h
index d8a4a16..3fe84d5 100644
--- a/firmware/usbdrv/usbdrv.h
+++ b/firmware/usbdrv/usbdrv.h
@@ -5,7 +5,6 @@
* 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 Revision: $Id: usbdrv.h 793 2010-07-15 15:58:11Z cs $
*/
#ifndef __usbdrv_h_included__
@@ -122,7 +121,7 @@ USB messages, even if they address another (low-speed) device on the same bus.
/* --------------------------- Module Interface ---------------------------- */
/* ------------------------------------------------------------------------- */
-#define USBDRV_VERSION 20100715
+#define USBDRV_VERSION 20121206
/* This define uniquely identifies a driver version. It is a decimal number
* constructed from the driver's release date in the form YYYYMMDD. If the
* driver's behavior or interface changes, you can use this constant to
@@ -163,6 +162,17 @@ USB messages, even if they address another (low-speed) device on the same bus.
*/
#define USB_NO_MSG ((usbMsgLen_t)-1) /* constant meaning "no message" */
+#ifndef usbMsgPtr_t
+#define usbMsgPtr_t uchar *
+#endif
+/* Making usbMsgPtr_t a define allows the user of this library to define it to
+ * an 8 bit type on tiny devices. This reduces code size, especially if the
+ * compiler supports a tiny memory model.
+ * The type can be a pointer or scalar type, casts are made where necessary.
+ * Although it's paradoxical, Gcc 4 generates slightly better code for scalar
+ * types than for pointers.
+ */
+
struct usbRequest; /* forward declaration */
USB_PUBLIC void usbInit(void);
@@ -178,7 +188,7 @@ USB_PUBLIC void usbPoll(void);
* Please note that debug outputs through the UART take ~ 0.5ms per byte
* at 19200 bps.
*/
-extern uchar *usbMsgPtr;
+extern usbMsgPtr_t usbMsgPtr;
/* This variable may be used to pass transmit data to the driver from the
* implementation of usbFunctionWrite(). It is also used internally by the
* driver for standard control requests.
@@ -210,7 +220,7 @@ USB_PUBLIC usbMsgLen_t usbFunctionSetup(uchar data[8]);
* Note that calls to the functions usbFunctionRead() and usbFunctionWrite()
* are only done if enabled by the configuration in usbconfig.h.
*/
-//USB_PUBLIC usbMsgLen_t usbFunctionDescriptor(struct usbRequest *rq);
+USB_PUBLIC usbMsgLen_t usbFunctionDescriptor(struct usbRequest *rq);
/* You need to implement this function ONLY if you provide USB descriptors at
* runtime (which is an expert feature). It is very similar to
* usbFunctionSetup() above, but it is called only to request USB descriptor
@@ -390,13 +400,13 @@ extern volatile schar usbRxLen;
* about the various methods to define USB descriptors. If you do nothing,
* the default descriptors will be used.
*/
-#define USB_PROP_IS_DYNAMIC (1 << 14)
+#define USB_PROP_IS_DYNAMIC (1u << 14)
/* If this property is set for a descriptor, usbFunctionDescriptor() will be
* used to obtain the particular descriptor. Data directly returned via
* usbMsgPtr are FLASH data by default, combine (OR) with USB_PROP_IS_RAM to
* return RAM data.
*/
-#define USB_PROP_IS_RAM (1 << 15)
+#define USB_PROP_IS_RAM (1u << 15)
/* If this property is set for a descriptor, the data is read from RAM
* memory instead of Flash. The property is used for all methods to provide
* external descriptors.
@@ -450,43 +460,43 @@ extern volatile schar usbRxLen;
#ifndef __ASSEMBLER__
extern
#if !(USB_CFG_DESCR_PROPS_DEVICE & USB_PROP_IS_RAM)
-PROGMEM
+PROGMEM const
#endif
char usbDescriptorDevice[];
extern
#if !(USB_CFG_DESCR_PROPS_CONFIGURATION & USB_PROP_IS_RAM)
-PROGMEM
+PROGMEM const
#endif
char usbDescriptorConfiguration[];
extern
#if !(USB_CFG_DESCR_PROPS_HID_REPORT & USB_PROP_IS_RAM)
-PROGMEM
+PROGMEM const
#endif
char usbDescriptorHidReport[];
extern
#if !(USB_CFG_DESCR_PROPS_STRING_0 & USB_PROP_IS_RAM)
-PROGMEM
+PROGMEM const
#endif
char usbDescriptorString0[];
extern
#if !(USB_CFG_DESCR_PROPS_STRING_VENDOR & USB_PROP_IS_RAM)
-PROGMEM
+PROGMEM const
#endif
int usbDescriptorStringVendor[];
extern
#if !(USB_CFG_DESCR_PROPS_STRING_PRODUCT & USB_PROP_IS_RAM)
-PROGMEM
+PROGMEM const
#endif
int usbDescriptorStringDevice[];
extern
#if !(USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER & USB_PROP_IS_RAM)
-PROGMEM
+PROGMEM const
#endif
int usbDescriptorStringSerialNumber[];
@@ -719,6 +729,7 @@ typedef struct usbRequest{
#define USBDESCR_HID_PHYS 0x23
//#define USBATTR_BUSPOWER 0x80 // USB 1.1 does not define this value any more
+#define USBATTR_BUSPOWER 0
#define USBATTR_SELFPOWER 0x40
#define USBATTR_REMOTEWAKE 0x20
diff --git a/firmware/usbdrv/usbdrvasm.S b/firmware/usbdrv/usbdrvasm.S
index 45fcf18..b03b709 100644
--- a/firmware/usbdrv/usbdrvasm.S
+++ b/firmware/usbdrv/usbdrvasm.S
@@ -5,7 +5,6 @@
* 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 785 2010-05-30 17:57:07Z cs $
*/
/*
@@ -285,7 +284,7 @@ usbCrc16Append:
#if USB_CFG_HAVE_MEASURE_FRAME_LENGTH
#ifdef __IAR_SYSTEMS_ASM__
-/* Register assignments for usbMeasureFrameLength on IAR cc */
+/* Register assignments for usbMeasureFrameLengthDecreasing 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)
@@ -314,33 +313,28 @@ usbCrc16Append:
#endif
# define cnt16 cnt16L
-; extern unsigned usbMeasurePacketLength(void);
-; returns time between two idle strobes in multiples of 7 CPU clocks
-.global usbMeasureFrameLength
-usbMeasureFrameLength:
- ldi cntH, 6 ; wait ~ 10 ms for D- == 0
- clr cnt16L
- clr cnt16H
-usbMFTime16:
- dec cntH
- breq usbMFTimeout
-usbMFWaitStrobe: ; first wait for D- == 0 (idle strobe)
- sbiw cnt16, 1 ;[0] [6]
- breq usbMFTime16 ;[2]
- sbic USBIN, USBMINUS ;[3]
- rjmp usbMFWaitStrobe ;[4]
-usbMFWaitIdle: ; then wait until idle again
+; extern int usbMeasurePacketLengthDecreasing(int);
+; input: timer start value
+; return: counts down time between two idle strobes in multiples of 5 CPU clocks
+.global usbMeasureFrameLengthDecreasing
+usbMeasureFrameLengthDecreasing:
+
+#if resL != cnt16L
+ mov cnt16L, resL
+ mov cnt16H, resH
+#endif
+
+usbDFWaitStrobe: ; first wait for D- == 0 (idle strobe)
+ sbic USBIN, USBMINUS ;
+ rjmp usbDFWaitStrobe ;
+usbDFWaitIdle: ; then wait until idle again
sbis USBIN, USBMINUS ;1 wait for D- == 1
- rjmp usbMFWaitIdle ;2
- ldi cnt16L, 1 ;1 represents cycles so far
- clr cnt16H ;1
-usbMFWaitLoop:
- in cntH, USBIN ;[0] [7]
- adiw cnt16, 1 ;[1]
- breq usbMFTimeout ;[3]
- andi cntH, USBMASK ;[4]
- brne usbMFWaitLoop ;[5]
-usbMFTimeout:
+ rjmp usbDFWaitIdle ;2
+usbDFWaitLoop:
+ sbiw cnt16,1 ;[0] [5]
+ sbic USBIN, USBMINUS ;[2]
+ rjmp usbDFWaitLoop ;[3]
+
#if resL != cnt16L
mov resL, cnt16L
mov resH, cnt16H
diff --git a/firmware/usbdrv/usbdrvasm.asm b/firmware/usbdrv/usbdrvasm.asm
index 9cc4e4d..fb66934 100644
--- a/firmware/usbdrv/usbdrvasm.asm
+++ b/firmware/usbdrv/usbdrvasm.asm
@@ -5,7 +5,6 @@
* Tabsize: 4
* Copyright: (c) 2006 by OBJECTIVE DEVELOPMENT Software GmbH
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
- * This Revision: $Id$
*/
/*
diff --git a/firmware/usbdrv/usbdrvasm12.inc b/firmware/usbdrv/usbdrvasm12.inc
index 78a14e0..d3bd056 100644
--- a/firmware/usbdrv/usbdrvasm12.inc
+++ b/firmware/usbdrv/usbdrvasm12.inc
@@ -5,7 +5,6 @@
* Tabsize: 4
* Copyright: (c) 2007 by OBJECTIVE DEVELOPMENT Software GmbH
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
- * This Revision: $Id: usbdrvasm12.inc 740 2009-04-13 18:23:31Z cs $
*/
/* Do not link this file! Link usbdrvasm.S instead, which includes the
@@ -41,50 +40,8 @@ DATAx (rx) to ACK/NAK/STALL (tx) 2 7.5 16-60
USB_INTR_VECTOR:
;order of registers pushed: YL, SREG [sofError], YH, shift, x1, x2, x3, cnt
push YL ;2 [35] push only what is necessary to sync with edge ASAP
-
in YL, SREG ;1 [37]
push YL ;2 [39]
-
- in YL, TIMSK
- cpi YL, 0
- breq compare2 ; don't go to app if equal (possible bootloader)
-
- ; prep and jump to app vector
- pop YL
- out SREG, YL
- pop YL
- rjmp __vectors - 2
-
-compare2:
- in YL, TCNT2
- cpi YL, 0xFF
- breq bootloaderExt0 ; don't go to app if equal (bootloader)
-
- ; prep and jump to app vector
- pop YL
- out SREG, YL
- pop YL
-
- ; some errors with 1 nop
- ;nop
- ;nop
- ;nop
- ;nop
- ;nop
- ;nop
- ;nop
- ;nop
- ;nop
- ;nop
-
-
- rjmp __vectors - 2
-
-
-bootloaderExt0:
- ldi YL, 0
-
-
;----------------------------------------------------------------------------
; Synchronize with sync pattern:
;----------------------------------------------------------------------------
@@ -432,4 +389,4 @@ skipAddrAssign:
out USBOUT, x1 ;[16] <-- out J (idle) -- end of SE0 (EOP signal)
out USBDDR, x2 ;[17] <-- release bus now
out USBOUT, x3 ;[18] <-- ensure no pull-up resistors are active
- rjmp doReturn \ No newline at end of file
+ rjmp doReturn
diff --git a/firmware/usbdrv/usbdrvasm128.inc b/firmware/usbdrv/usbdrvasm128.inc
index bcd6621..8f67bcc 100644
--- a/firmware/usbdrv/usbdrvasm128.inc
+++ b/firmware/usbdrv/usbdrvasm128.inc
@@ -5,7 +5,6 @@
* Tabsize: 4
* Copyright: (c) 2008 by OBJECTIVE DEVELOPMENT Software GmbH
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
- * This Revision: $Id: usbdrvasm128.inc 758 2009-08-06 10:12:54Z cs $
*/
/* Do not link this file! Link usbdrvasm.S instead, which includes the
diff --git a/firmware/usbdrv/usbdrvasm15.inc b/firmware/usbdrv/usbdrvasm15.inc
index 401b7f8..33bcf0e 100644
--- a/firmware/usbdrv/usbdrvasm15.inc
+++ b/firmware/usbdrv/usbdrvasm15.inc
@@ -5,7 +5,6 @@
* 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: usbdrvasm15.inc 740 2009-04-13 18:23:31Z cs $
*/
/* Do not link this file! Link usbdrvasm.S instead, which includes the
diff --git a/firmware/usbdrv/usbdrvasm16.inc b/firmware/usbdrv/usbdrvasm16.inc
index 207b6e4..25b84e6 100644
--- a/firmware/usbdrv/usbdrvasm16.inc
+++ b/firmware/usbdrv/usbdrvasm16.inc
@@ -5,7 +5,6 @@
* 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: usbdrvasm16.inc 760 2009-08-09 18:59:43Z cs $
*/
/* Do not link this file! Link usbdrvasm.S instead, which includes the
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]
diff --git a/firmware/usbdrv/usbdrvasm18-crc.inc b/firmware/usbdrv/usbdrvasm18-crc.inc
index f83347d..0ff2f42 100644
--- a/firmware/usbdrv/usbdrvasm18-crc.inc
+++ b/firmware/usbdrv/usbdrvasm18-crc.inc
@@ -5,7 +5,6 @@
* Tabsize: 4
* Copyright: (c) 2008 by Lukas Schrittwieser and OBJECTIVE DEVELOPMENT Software GmbH
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
- * Revision: $Id: usbdrvasm18-crc.inc 740 2009-04-13 18:23:31Z cs $
*/
/* Do not link this file! Link usbdrvasm.S instead, which includes the
diff --git a/firmware/usbdrv/usbdrvasm20.inc b/firmware/usbdrv/usbdrvasm20.inc
index 303abaf..5027edd 100644
--- a/firmware/usbdrv/usbdrvasm20.inc
+++ b/firmware/usbdrv/usbdrvasm20.inc
@@ -6,7 +6,6 @@
* Tabsize: 4
* Copyright: (c) 2008 by Jeroen Benschop and OBJECTIVE DEVELOPMENT Software GmbH
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
- * Revision: $Id: usbdrvasm20.inc 740 2009-04-13 18:23:31Z cs $
*/
/* Do not link this file! Link usbdrvasm.S instead, which includes the
diff --git a/firmware/usbdrv/usbportability.h b/firmware/usbdrv/usbportability.h
index 476184d..0a861d0 100644
--- a/firmware/usbdrv/usbportability.h
+++ b/firmware/usbdrv/usbportability.h
@@ -5,7 +5,6 @@
* Tabsize: 4
* Copyright: (c) 2008 by OBJECTIVE DEVELOPMENT Software GmbH
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
- * This Revision: $Id: usbportability.h 785 2010-05-30 17:57:07Z cs $
*/
/*