diff options
28 files changed, 587 insertions, 246 deletions
diff --git a/firmware/Makefile b/firmware/Makefile index 8dfba5d..2f539b6 100644 --- a/firmware/Makefile +++ b/firmware/Makefile @@ -24,7 +24,7 @@ LOCKOPT = -U lock:w:0x2f:m # - for the size of your device (8kb = 1024 * 8 = 8192) subtract above value 2124... = 6068 # - How many pages in is that? 6068 / 64 (tiny85 page size in bytes) = 94.8125 # - round that down to 94 - our new bootloader address is 94 * 64 = 6016, in hex = 1780 -BOOTLOADER_ADDRESS = 1780 +BOOTLOADER_ADDRESS = 1840 PROGRAMMER = -c USBasp # PROGRAMMER contains AVRDUDE options to address your programmer @@ -148,12 +148,12 @@ CC = avr-gcc # Options: DEFINES = -DBOOTLOADER_ADDRESS=0x$(BOOTLOADER_ADDRESS) #-DDEBUG_LEVEL=2 # Remove the -fno-* options when you use gcc 3, it does not understand them -CFLAGS = -Wall -Os -fno-move-loop-invariants -fno-tree-scev-cprop -fno-inline-small-functions -I. -Ilibs-device -mmcu=$(DEVICE) -DF_CPU=$(F_CPU) $(DEFINES) +# +CFLAGS = -g2 -ffunction-sections -fdata-sections -fpack-struct -Wall -Os -fno-inline-small-functions -fno-move-loop-invariants -fno-tree-scev-cprop -I. -Ilibs-device -mmcu=$(DEVICE) -DF_CPU=$(F_CPU) $(DEFINES) LDFLAGS = -Wl,--relax,--gc-sections -Wl,--section-start=.text=$(BOOTLOADER_ADDRESS),-Map=main.map OBJECTS = usbdrv/usbdrvasm.o usbdrv/oddebug.o main.o -OBJECTS += libs-device/osccal.o - +OBJECTS += libs-device/osccalASM.o # symbolic targets: all: main.hex @@ -171,7 +171,7 @@ all: main.hex $(CC) $(CFLAGS) -S $< -o $@ flash: all - $(AVRDUDE) -U flash:w:main.hex:i + $(AVRDUDE) -U flash:w:main.hex:i -B 10 readflash: $(AVRDUDE) -U flash:r:read.hex:i @@ -201,7 +201,7 @@ main.hex: main.bin avr-size main.hex disasm: main.bin - avr-objdump -d main.bin + avr-objdump -d -S main.bin >main.lss cpp: $(CC) $(CFLAGS) -E main.c diff --git a/firmware/bootloaderconfig.h b/firmware/bootloaderconfig.h index 3133368..641a9e0 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,10 +243,17 @@ 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() - #define bootLoaderCondition() (idlePolls < (AUTO_EXIT_MS * 10UL)) + #define bootLoaderCondition() (++idlePolls < (AUTO_EXIT_MS * 10UL)) #if LOW_POWER_MODE // only starts bootloader if USB D- is pulled high on startup - by putting your pullup in to an external connector // you can avoid ever entering an out of spec clock speed or waiting on bootloader when that pullup isn't there diff --git a/firmware/libs-device/osccal.c b/firmware/libs-device/osccal.c index 939d5c3..8debe49 100644 --- a/firmware/libs-device/osccal.c +++ b/firmware/libs-device/osccal.c @@ -8,49 +8,169 @@ */ #include <avr/io.h> - +#include <avr/interrupt.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, targetValue; + uchar optimumDev; + uchar i,xl; + + 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 = 0xff; + // optimumValue = OSCCAL; + step=64; + trialValue = 128; + + cli(); // disable interrupts + + /* + 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; + xl=(uchar)-x; + } + else /* frequency too low */ + { + trialValue += step; + xl=(uchar)x; + } + + /* + 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. + Once the neighbourhood search stage is reached, x will be smaller than +-255, hence more code can be + saved by only working with the lower 8 bits. + */ + + step >>= 1; + + if (step==0) + { + step=1; + if(xl <= optimumDev){ + optimumDev = xl; + optimumValue = OSCCAL; + } + } + + } + + OSCCAL = optimumValue; + asm volatile(" NOP"); + + sei(); // enable interrupts } + +void calibrateOscillator_old(void) +{ + 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/libs-device/osccal.h b/firmware/libs-device/osccal.h index 710ce05..af37a43 100644 --- a/firmware/libs-device/osccal.h +++ b/firmware/libs-device/osccal.h @@ -1,10 +1,10 @@ /* Name: osccal.h * Author: Christian Starkjohann * Creation Date: 2008-04-10 + * Changes 2013-11-04 cpldcpu@gmail.com * 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: osccal.h 762 2009-08-12 17:10:30Z cs $ */ /* @@ -14,30 +14,18 @@ oscillator so that the CPU runs at F_CPU (F_CPU is a macro which must be defined when the module is compiled, best passed in the compiler command line). The time reference is the USB frame clock of 1 kHz available immediately after a USB RESET condition. Timing is done by counting CPU -cycles, so all interrupts must be disabled while the calibration runs. For -low level timing measurements, usbMeasureFrameLength() is called. This -function must be enabled in usbconfig.h by defining -USB_CFG_HAVE_MEASURE_FRAME_LENGTH to 1. It is recommended to call -calibrateOscillator() from the reset hook in usbconfig.h: -*/ +cycles, so all interrupts must be disabled while the calibration runs. +The size optimized assembler implementation includes its own implementation +of usbMeasureFrameLength. Therefore USB_CFG_HAVE_MEASURE_FRAME_LENGTH should +be set to 0 to avoid including unused code sections. It is recommended to call +calibrateOscillatorASM() from the reset hook in usbconfig.h by including osccal.h: -#ifndef __ASSEMBLER__ -#include <avr/interrupt.h> // for sei() -extern void calibrateOscillator(void); -#endif -#define USB_RESET_HOOK(resetStarts) if(!resetStarts){cli(); calibrateOscillator(); sei();} +#include "osccal.h" -/* This routine is an alternative to the continuous synchronization described in osctune.h. -Algorithm used: -calibrateOscillator() first does a binary search in the OSCCAL register for -the best matching oscillator frequency. Then it does a next neighbor search -to find the value with the lowest clock rate deviation. It is guaranteed to -find the best match among neighboring values, but for version 5 oscillators -(which have a discontinuous relationship between OSCCAL and frequency) a -better match might be available in another OSCCAL region. +Algorithm used: See osccalASM.x Limitations: This calibration algorithm may try OSCCAL values of up to 192 even if the @@ -53,7 +41,11 @@ deviation! All other frequency modules require at least 0.2% precision. #ifndef __OSCCAL_H_INCLUDED__ #define __OSCCAL_H_INCLUDED__ -//void calibrateOscillator(void); +#ifndef __ASSEMBLER__ + void calibrateOscillatorASM(void); +# define USB_RESET_HOOK(resetStarts) if(!resetStarts){ calibrateOscillatorASM();} +# define USB_CFG_HAVE_MEASURE_FRAME_LENGTH 0 +#endif /* This function calibrates the RC oscillator so that the CPU runs at F_CPU. * It MUST be called immediately after the end of a USB RESET condition! * Disable all interrupts during the call! diff --git a/firmware/libs-device/osccalASM.S b/firmware/libs-device/osccalASM.S new file mode 100644 index 0000000..9a317f1 --- /dev/null +++ b/firmware/libs-device/osccalASM.S @@ -0,0 +1,228 @@ +/* Name: osccalASM.S + * Author: cpldcpu@gmail.com + * Creation Date: 2013-11-3 + * Tabsize: 4 + * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt) + */ + +/* 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. + * + * + * Benefits: + * - Codesize reduced by 90 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. + */ + + +#define __SFR_OFFSET 0 /* used by avr-libc's register definitions */ +#include "./usbdrv/usbdrv.h" /* for common defs */ + +#ifdef __IAR_SYSTEMS_ASM__ +/* 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) + * 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". + */ + +//Untested + +# define i r20 +# define opV r19 +# define opD r18 +# define try r21 +# define stp r22 + +# define cnt16L r30 +# define cnt16H r31 + + +#else /* __IAR_SYSTEMS_ASM__ */ +/* Register assignments for usbMeasureFrameLength 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 i r20 +# define opV r19 +# define opD r18 +# define try r27 +# define stp r26 +# define cnt16L r24 +# define cnt16H r25 +#endif +# define cnt16 cnt16L + +; extern void calibrateOscillatorASM(void); + +.global calibrateOscillatorASM +calibrateOscillatorASM: + + cli + ldi opD, 255 + + ldi try, 128 ; calibration start value + ldi stp, 64 ; initial step width + ldi i, 10 ; 10 iterations + +usbCOloop: + + out OSCCAL, try + nop + + ; Delay values = F_CPU * 999e-6 / 5 + 0.5 + +#if (F_CPU == 16500000) + ldi cnt16L, lo8(3297) + ldi cnt16H, hi8(3297) +#elif (F_CPU == 12800000) + ldi cnt16L, lo8(2557) + ldi cnt16H, hi8(2557) +#else + #error "calibrateOscillatorASM: no delayvalues defined for this F_CPU setting" +#endif + +usbCOWaitStrobe: ; first wait for D- == 0 (idle strobe) + sbic USBIN, USBMINUS ; + rjmp usbCOWaitStrobe ; +usbCOWaitIdle: ; then wait until idle again + sbis USBIN, USBMINUS ;1 wait for D- == 1 + rjmp usbCOWaitIdle ;2 +usbCOWaitLoop: + sbiw cnt16,1 ;[0] [5] + sbic USBIN, USBMINUS ;[2] + rjmp usbCOWaitLoop ;[3] + + sbrs cnt16H, 7 ;delay overflow? + rjmp usbCOclocktoolow + sub try, stp + neg cnt16L + rjmp usbCOclocktoohigh +usbCOclocktoolow: + add try, stp +usbCOclocktoohigh: + lsr stp + brne usbCOnoneighborhoodsearch + cp opD, cnt16L + brcs usbCOnoimprovement + in opV, OSCCAL + mov opD, cnt16L +usbCOnoimprovement: + ldi stp, 1 +usbCOnoneighborhoodsearch: + subi i, 1 + brne usbCOloop + + out OSCCAL, opV + nop + sei + ret + +#undef i +#undef opV +#undef opD +#undef try +#undef stp +#undef cnt16 +#undef cnt16L +#undef cnt16H + +/* ------------------------------------------------------------------------- */ +/* ------ Original C Implementation of improved calibrateOscillator -------- */ +/* ---------------------- for Reference only ----------------------------- */ +/* ------------------------------------------------------------------------- */ + +#if 0 +void calibrateOscillator(void) +{ + uchar step, trialValue, optimumValue; + int x, targetValue; + uchar optimumDev; + uchar i,xl; + + 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 = 0xff; + // optimumValue = OSCCAL; + step=64; + trialValue = 128; + + cli(); // disable interrupts + + /* + 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; + xl=(uchar)-x; + } + else /* frequency too low */ + { + trialValue += step; + xl=(uchar)x; + } + + /* + Halve stepwidth to perform binary search. At step=1 the mode changes to neighbourhood search. + Once the neighbourhood search stage is reached, x will be smaller than +-255, hence more code can be + saved by only working with the lower 8 bits. + */ + + step >>= 1; + + if (step==0) // Enter neighborhood search mode + { + step=1; + if(xl <= optimumDev){ + optimumDev = xl; + optimumValue = OSCCAL; + } + } + } + + OSCCAL = optimumValue; + asm volatile(" NOP"); + + sei(); // enable interrupts +} +#endif
\ No newline at end of file diff --git a/firmware/libs-device/osccalASM.o b/firmware/libs-device/osccalASM.o Binary files differnew file mode 100644 index 0000000..1dac9d8 --- /dev/null +++ b/firmware/libs-device/osccalASM.o diff --git a/firmware/main.c b/firmware/main.c index e56de62..ad08895 100644 --- a/firmware/main.c +++ b/firmware/main.c @@ -15,6 +15,9 @@ // 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> @@ -96,20 +99,14 @@ static uchar events = 0; // bitmap of events to run #define isEvent(event) (events & (event)) #define clearEvents() events = 0 -// length of bytes to write in to flash memory in upcomming 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); @@ -127,21 +124,23 @@ 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 immidately, usb would fail. +// - 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 - currentAddress = BOOTLOADER_ADDRESS; + addr_t ptr = BOOTLOADER_ADDRESS; + cli(); - while (currentAddress) { - currentAddress -= SPM_PAGESIZE; + while (ptr) { + ptr -= SPM_PAGESIZE; - boot_page_erase(currentAddress); + boot_page_erase(ptr); boot_spm_busy_wait(); } + currentAddress = 0; fillFlashWithVectors(); sei(); } @@ -149,7 +148,6 @@ static inline void eraseApplication(void) { // 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. @@ -185,8 +183,10 @@ static void writeWordToPageBuffer(uint16_t data) { 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 } @@ -221,9 +221,18 @@ static void fillFlashWithVectors(void) { //} // TODO: Or more simply: + + +#if SPM_PAGESIZE<256 do { - writeWordToPageBuffer(0xFFFF); + writeWordToPageBuffer(0xFFFF); + } while ((uchar)currentAddress % SPM_PAGESIZE); +#else + do { + writeWordToPageBuffer(0xFFFF); } while (currentAddress % SPM_PAGESIZE); +#endif + writeFlashPage(); } @@ -292,7 +301,14 @@ static uchar usbFunctionWrite(uchar *data, uchar 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 @@ -326,12 +342,9 @@ 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_word(RESET_VECTOR_OFFSET * 2) != 0xC000 + (BOOTLOADER_ADDRESS/2) - 1 || - pgm_read_word(USBPLUS_VECTOR_OFFSET * 2) != 0xC000 + (BOOTLOADER_ADDRESS/2) - 1) { - - fillFlashWithVectors(); - } - + + if(pgm_read_byte(RESET_VECTOR_OFFSET * 2+1) == 0xff) fillFlashWithVectors(); // write vectors if flash is empty + // TODO: necessary to reset currentAddress? currentAddress = 0; } @@ -341,24 +354,21 @@ static inline void tiny85FlashWrites(void) { // 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 (currentAddress % SPM_PAGESIZE) { // when we aren't perfectly aligned to a flash page boundary + +#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 @@ -366,24 +376,25 @@ static inline void leaveBootloader(void) { //DBG1(0x01, 0, 0); bootLoaderExit(); cli(); + usbDeviceDisconnect(); /* Disconnect micronucleus */ + 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; - *(uint8_t*)(RAMEND-1) = 0x00; + *(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++; + OSCCAL=stored_osc_calibration; + asm volatile("nop"); } - +#endif // jump to application reset vector at end of flash asm volatile ("rjmp __vectors - 4"); } @@ -391,17 +402,18 @@ static inline void leaveBootloader(void) { int main(void) { /* initialize */ #ifdef RESTORE_OSCCAL - uint8_t osccal_default = OSCCAL; + osccal_default = OSCCAL; #endif #if (!SET_CLOCK_PRESCALER) && LOW_POWER_MODE uint8_t prescaler_default = CLKPR; #endif - + + + 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 @@ -410,11 +422,14 @@ int main(void) { CLKPR = 0; #endif + #ifdef NANITE + PORTB &=~_BV(NANITE_CTRLPIN); + #endif initForUsbConnectivity(); do { - usbPoll(); + + usbPoll(); _delay_us(100); - idlePolls++; // 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 @@ -422,6 +437,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; @@ -429,7 +449,7 @@ int main(void) { # endif clearEvents(); - + } while(bootLoaderCondition()); /* main event loop runs so long as bootLoaderCondition remains truthy */ } @@ -443,10 +463,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/usbconfig.h b/firmware/usbconfig.h index 55707cb..bba210d 100644 --- a/firmware/usbconfig.h +++ b/firmware/usbconfig.h @@ -158,11 +158,10 @@ * for each control- and out-endpoint to check for duplicate packets. */ //#if USB_CFG_CLOCK_KHZ==16500 -#define USB_CFG_HAVE_MEASURE_FRAME_LENGTH 1 + + #include "osccal.h" -//#else -//#define USB_CFG_HAVE_MEASURE_FRAME_LENGTH 0 -//#endif + /* define this macro to 1 if you want the function usbMeasureFrameLength() * compiled in. This function can be used to calibrate the AVR's RC oscillator. */ 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..32ce8ef 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 $ */ /* 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 $ */ /* |