diff --git a/avr/bootloader/Makefile b/avr/bootloader/Makefile index ec188a2..49eda74 100644 --- a/avr/bootloader/Makefile +++ b/avr/bootloader/Makefile @@ -1,7 +1,7 @@ # microcontroller and project specific settings TARGET = bootloader -F_CPU = 20000000 +F_CPU = 20000000UL MCU = atmega644 SRC = bootloader.c @@ -11,7 +11,7 @@ OBJECTS += $(patsubst %.S,%.o,${ASRC}) HEADERS += $(shell echo *.h) # CFLAGS += -Werror LDFLAGS += -L/usr/local/avr/avr/lib -CFLAGS += -Iusbdrv -I. -Os +CFLAGS += -Iusbdrv -I. CFLAGS += -DHARDWARE_REV=$(HARDWARE_REV) ASFLAGS += -x assembler-with-cpp ASFLAGS += -Iusbdrv -I. @@ -36,12 +36,9 @@ else ifeq ($(MCU),atmega88) # bootloader section starts at 0xc00 (word-address) == 0x1800 (byte-address) BOOT_SECTION_START = 0x1800 else ifeq ($(MCU),atmega644) - # atmega88 with 1024 words bootloader: - # bootloader section starts at 0x7c00 (word-address) == 0xF800 (byte-address) - - # atmega88 with 2024 words bootloader: - # bootloader section starts at 0x7800 (word-address) == 0xF000 (byte-address) - BOOT_SECTION_START = 0xf000 + # atmega88 with 2048 words bootloader: + # bootloader section starts at 0x7800 (word-address) == 0xF000 (byte-address) + BOOT_SECTION_START = 0xf000 endif LDFLAGS += -Wl,--section-start=.text=$(BOOT_SECTION_START) @@ -57,59 +54,23 @@ all: $(TARGET).hex $(TARGET).lss @echo "$(TARGET) compiled for: $(MCU)" @echo -n "size is: " @$(SIZE) -A $(TARGET).hex | grep "\.sec1" | tr -s " " | cut -d" " -f2 - @echo "max size:4096 bytes" @echo "===============================" $(TARGET): $(OBJECTS) $(TARGET).o %.o: $(HEADERS) -.PHONY: install lock fuses-atmega168-unzap bootstrap +.PHONY: clean clean-$(TARGET) -# install: program-serial-$(TARGET) program-serial-eeprom-$(TARGET) -install: program-isp-$(TARGET) - -lock: - $(AVRDUDE) $(AVRDUDE_FLAGS) -c $(ISP_PROG) -P $(ISP_DEV) -U lock:w:0x2f:m - -fuses-atmega168-unzap: - echo "sck 5" | $(AVRDUDE) $(AVRDUDE_FLAGS) -c $(ISP_PROG) -P $(ISP_DEV) -F -u -t - $(AVRDUDE) $(AVRDUDE_FLAGS) -c $(ISP_PROG) -P $(ISP_DEV) -U lfuse:w:0xe7:m -U hfuse:w:0xd5:m -U efuse:w:0x00:m - echo "sck 0.2" | $(AVRDUDE) $(AVRDUDE_FLAGS) -c $(ISP_PROG) -P $(ISP_DEV) -F -u -t - -fuses-atmega168-rumpus: - echo "sck 5" | $(AVRDUDE) $(AVRDUDE_FLAGS) -c $(ISP_PROG) -P $(ISP_DEV) -F -u -t - $(AVRDUDE) $(AVRDUDE_FLAGS) -c $(ISP_PROG) -P $(ISP_DEV) -U lfuse:w:0xe7:m -U efuse:w:0x00:m - echo "sck 0.2" | $(AVRDUDE) $(AVRDUDE_FLAGS) -c $(ISP_PROG) -P $(ISP_DEV) -F -u -t - -bootstrap: fuses-atmega168-unzap install lock - -.PHONY: clean clean-$(TARGET) clean-uploadtest - -clean: clean-$(TARGET) clean-uploadtest +clean: clean-$(TARGET) clean-$(TARGET): $(RM) $(TARGET) $(OBJECTS) -clean-uploadtest: - rm -f datatestfile{512,14k}.raw -.PHONY: depend test uploadtest +.PHONY: depend test depend: $(CC) $(CFLAGS) -M $(CDEFS) $(CINCS) $(SRC) >> $(MAKEFILE).dep -datatestfile14k.raw: - dd if=/dev/urandom of=datatestfile14k.raw bs=1 count=14336 - -datatestfile512.raw: - dd if=/dev/urandom of=datatestfile512.raw bs=1 count=512 - -test/test.hex: - $(MAKE) -C test test.hex - -uploadtest: datatestfile14k.raw datatestfile512.raw - $(AVRDUDE) -p $(AVRDUDE_MCU) -c usbasp -P usb -U flash:w:datatestfile14k.raw -U eeprom:w:datatestfile512.raw - $(AVRDUDE) $(AVRDUDE_FLAGS) -c $(ISP_PROG) -P $(ISP_DEV) -U flash:v:datatestfile14k.raw -U eeprom:v:datatestfile512.raw - -include $(MAKEFILE).dep diff --git a/avr/bootloader/avr.mk b/avr/bootloader/avr.mk index de2aec8..e93c6ee 100644 --- a/avr/bootloader/avr.mk +++ b/avr/bootloader/avr.mk @@ -1,7 +1,7 @@ # Programmer used for In System Programming ISP_PROG = usbasp # device the ISP programmer is connected to -ISP_DEV = /dev/tty.PL2303-00002126 +ISP_DEV = # Programmer used for serial programming (using the bootloader) SERIAL_PROG = avr109 # device the serial programmer is connected to @@ -38,7 +38,6 @@ ifeq ($(MCU),atmega644) endif - AVRDUDE_FLAGS += -p $(AVRDUDE_MCU) # flags for the compiler @@ -67,27 +66,14 @@ $(OBJECTS): clean: $(RM) *.hex *.eep.hex *.o *.lst *.lss -interactive-isp: - $(AVRDUDE) $(AVRDUDE_FLAGS) -c $(ISP_PROG) -P $(ISP_DEV) -t - -interactive-serial: - $(AVRDUDE) $(AVRDUDE_FLAGS) -c $(SERIAL_PROG) -P $(SERIAL_DEV) -t - - .PHONY: all clean interactive-isp interactive-serial launch-bootloader -flash: bootloader.hex +flash: $(AVRDUDE) $(AVRDUDE_FLAGS) -c $(ISP_PROG) -U flash:w:$< -program-isp-eeprom-%: %.eep.hex +flash-eeprom-%: %.eep.hex $(AVRDUDE) $(AVRDUDE_FLAGS) -c $(ISP_PROG) -P $(ISP_DEV) -U eeprom:w:$< -program-serial-%: %.hex - $(AVRDUDE) $(AVRDUDE_FLAGS) -c $(SERIAL_PROG) -P $(SERIAL_DEV) -U flash:w:$< - -program-serial-eeprom-%: %.eep.hex launch-bootloader - $(AVRDUDE) $(AVRDUDE_FLAGS) -c $(SERIAL_PROG) -P $(SERIAL_DEV) -U eeprom:w:$< - %.hex: % $(OBJCOPY) -O ihex -R .eeprom $< $@ @@ -99,6 +85,3 @@ program-serial-eeprom-%: %.eep.hex launch-bootloader %-size: %.hex $(SIZE) $< - -launch-bootloader: - launch-bootloader $(SERIAL_DEV) $(AVRDUDE_BAUDRATE) diff --git a/avr/bootloader/bootloader.c b/avr/bootloader/bootloader.c index 949b2cd..7442d4c 100644 --- a/avr/bootloader/bootloader.c +++ b/avr/bootloader/bootloader.c @@ -85,7 +85,7 @@ static const uint8_t signature[4] = { #elif defined (__AVR_ATmega328P__) 0x1e, 0x95, 0x0f, 0 #elif defined (__AVR_ATmega644__) - 0x1e, 0x96, 0x06, 0 + 0x1e, 0x96, 0x09, 0 #else # error "Device signature is not known, please edit config.h!" #endif @@ -109,7 +109,7 @@ static __attribute__ (( __noinline__ )) void putc(uint8_t data) { * which turn the interrupt on and off at the right times, * and prevent the execution of an interrupt while the pullup resistor * is switched off */ -/* + #ifdef USB_CFG_PULLUP_IOPORTNAME #undef usbDeviceConnect #define usbDeviceConnect() do { \ @@ -124,7 +124,7 @@ static __attribute__ (( __noinline__ )) void putc(uint8_t data) { USB_PULLUP_OUT &= ~(1< +#endif #ifndef uchar # define uchar unsigned char diff --git a/avr/bootloader/usbdrv/usbconfig-prototype.h b/avr/bootloader/usbdrv/usbconfig-prototype.h index aeb2c73..242d140 100644 --- a/avr/bootloader/usbdrv/usbconfig-prototype.h +++ b/avr/bootloader/usbdrv/usbconfig-prototype.h @@ -1,11 +1,11 @@ /* Name: usbconfig.h - * Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers + * Project: AVR USB driver * Author: Christian Starkjohann * Creation Date: 2005-04-01 * 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 740 2009-04-13 18:23:31Z cs $ + * License: GNU GPL v2 (see License.txt) or proprietary (CommercialLicense.txt) + * This Revision: $Id: usbconfig-prototype.h 600 2008-05-13 10:34:56Z cs $ */ #ifndef __usbconfig_h_included__ @@ -14,7 +14,7 @@ /* General Description: This file is an example configuration (with inline documentation) for the USB -driver. It configures V-USB for USB D+ connected to Port D bit 2 (which is +driver. It configures AVR-USB for USB D+ connected to Port D bit 2 (which is also hardware interrupt 0 on many devices) and USB D- to Port D bit 4. You may wire the lines to any other port, as long as D+ is also wired to INT0 (or any other hardware interrupt, as long as it is the highest level interrupt, see @@ -44,18 +44,12 @@ section at the end of this file). * markers every millisecond.] */ #define USB_CFG_CLOCK_KHZ (F_CPU/1000) -/* Clock rate of the AVR in kHz. Legal values are 12000, 12800, 15000, 16000, - * 16500 and 20000. The 12.8 MHz and 16.5 MHz versions of the code require no - * crystal, they tolerate +/- 1% deviation from the nominal frequency. All - * other rates require a precision of 2000 ppm and thus a crystal! +/* Clock rate of the AVR in MHz. Legal values are 12000, 15000, 16000, 16500 + * and 20000. The 16.5 MHz version of the code requires no crystal, it + * tolerates +/- 1% deviation from the nominal frequency. All other rates + * require a precision of 2000 ppm and thus a crystal! * Default if not specified: 12 MHz */ -#define USB_CFG_CHECK_CRC 0 -/* Define this to 1 if you want that the driver checks integrity of incoming - * data packets (CRC checks). CRC checks cost quite a bit of code size and are - * currently only available for 18 MHz crystal clock. You must choose - * USB_CFG_CLOCK_KHZ = 18000 if you enable this option. - */ /* ----------------------- Optional Hardware Config ------------------------ */ @@ -100,14 +94,6 @@ section at the end of this file). * it is required by the standard. We have made it a config option because it * bloats the code considerably. */ -#define USB_CFG_SUPPRESS_INTR_CODE 0 -/* Define this to 1 if you want to declare interrupt-in endpoints, but don't - * want to send any data over them. If this macro is defined to 1, functions - * usbSetInterrupt() and usbSetInterrupt3() are omitted. This is useful if - * you need the interrupt-in endpoints in order to comply to an interface - * (e.g. HID), but never want to send any data. This option saves a couple - * of bytes in flash memory and the transmit buffers in RAM. - */ #define USB_CFG_INTR_POLL_INTERVAL 10 /* If you compile a version with endpoint 1 (interrupt-in), this is the poll * interval. The value is in milliseconds and must not be less than 10 ms for @@ -170,33 +156,6 @@ section at the end of this file). * counts SOF packets. This feature requires that the hardware interrupt is * connected to D- instead of D+. */ -/* #ifdef __ASSEMBLER__ - * macro myAssemblerMacro - * in YL, TCNT0 - * sts timer0Snapshot, YL - * endm - * #endif - * #define USB_SOF_HOOK myAssemblerMacro - * This macro (if defined) is executed in the assembler module when a - * Start Of Frame condition is detected. It is recommended to define it to - * the name of an assembler macro which is defined here as well so that more - * than one assembler instruction can be used. The macro may use the register - * YL and modify SREG. If it lasts longer than a couple of cycles, USB messages - * immediately after an SOF pulse may be lost and must be retried by the host. - * What can you do with this hook? Since the SOF signal occurs exactly every - * 1 ms (unless the host is in sleep mode), you can use it to tune OSCCAL in - * designs running on the internal RC oscillator. - * Please note that Start Of Frame detection works only if D- is wired to the - * interrupt, not D+. THIS IS DIFFERENT THAN MOST EXAMPLES! - */ -#define USB_CFG_CHECK_DATA_TOGGLING 0 -/* define this macro to 1 if you want to filter out duplicate data packets - * sent by the host. Duplicates occur only as a consequence of communication - * errors, when the host does not receive an ACK. Please note that you need to - * implement the filtering yourself in usbFunctionWriteOut() and - * usbFunctionWrite(). Use the global usbCurrentDataToken and a static variable - * for each control- and out-endpoint to check for duplicate packets. - */ #define USB_CFG_HAVE_MEASURE_FRAME_LENGTH 0 /* 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. @@ -284,9 +243,7 @@ section at the end of this file). * no properties are defined or if they are 0, the default descriptor is used. * Possible properties are: * + USB_PROP_IS_DYNAMIC: The data for the descriptor should be fetched - * at runtime via usbFunctionDescriptor(). If the usbMsgPtr mechanism is - * used, the data is in FLASH by default. Add property USB_PROP_IS_RAM if - * you want RAM pointers. + * at runtime via usbFunctionDescriptor(). * + USB_PROP_IS_RAM: The data returned by usbFunctionDescriptor() or found * in static memory is in RAM, not in flash memory. * + USB_PROP_LENGTH(len): If the data is in static memory (RAM or flash), @@ -318,12 +275,6 @@ section at the end of this file). * USB_CFG_DESCR_PROPS_HID_REPORT * USB_CFG_DESCR_PROPS_UNKNOWN (for all descriptors not handled by the driver) * - * Note about string descriptors: String descriptors are not just strings, they - * are Unicode strings prefixed with a 2 byte header. Example: - * int serialNumberDescriptor[] = { - * USB_STRING_DESCRIPTOR_HEADER(6), - * 'S', 'e', 'r', 'i', 'a', 'l' - * }; */ #define USB_CFG_DESCR_PROPS_DEVICE 0 diff --git a/avr/bootloader/usbdrv/usbdrv.c b/avr/bootloader/usbdrv/usbdrv.c index f3a6cde..a1ca892 100644 --- a/avr/bootloader/usbdrv/usbdrv.c +++ b/avr/bootloader/usbdrv/usbdrv.c @@ -1,14 +1,18 @@ /* Name: usbdrv.c - * Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers + * Project: AVR USB driver * Author: Christian Starkjohann * Creation Date: 2004-12-29 * Tabsize: 4 * Copyright: (c) 2005 by OBJECTIVE DEVELOPMENT Software GmbH - * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt) - * This Revision: $Id: usbdrv.c 740 2009-04-13 18:23:31Z cs $ + * License: GNU GPL v2 (see License.txt) or proprietary (CommercialLicense.txt) + * This Revision: $Id: usbdrv.c 591 2008-05-03 20:21:19Z cs $ */ -#include "usbportability.h" +#include "iarcompat.h" +#ifndef __IAR_SYSTEMS_ICC__ +# include +# include +#endif #include "usbdrv.h" #include "oddebug.h" @@ -34,15 +38,12 @@ uchar usbTxBuf[USB_BUFSIZE];/* data to transmit with next IN, free if usbT #if USB_COUNT_SOF volatile uchar usbSofCount; /* incremented by assembler module every SOF */ #endif -#if USB_CFG_HAVE_INTRIN_ENDPOINT && !USB_CFG_SUPPRESS_INTR_CODE +#if USB_CFG_HAVE_INTRIN_ENDPOINT usbTxStatus_t usbTxStatus1; # if USB_CFG_HAVE_INTRIN_ENDPOINT3 usbTxStatus_t usbTxStatus3; # endif #endif -#if USB_CFG_CHECK_DATA_TOGGLING -uchar usbCurrentDataToken;/* when we check data toggling to ignore duplicate packets */ -#endif /* USB status registers / not shared with asm code */ uchar *usbMsgPtr; /* data to transmit next -- ROM or RAM address */ @@ -55,7 +56,7 @@ static uchar usbMsgFlags; /* flag values see below */ /* optimizing hints: - do not post/pre inc/dec integer values in operations -- assign value of USB_READ_FLASH() to register variables and don't use side effects in arg +- assign value of PRG_RDB() to register variables and don't use side effects in arg - use narrow scope for variables which should be in X/Y/Z register - assign char sized expressions to variables to force 8 bit arithmetics */ @@ -194,9 +195,18 @@ PROGMEM char usbDescriptorConfiguration[] = { /* USB configuration descriptor /* ------------------------------------------------------------------------- */ +/* We don't use prog_int or prog_int16_t for compatibility with various libc + * versions. Here's an other compatibility hack: + */ +#ifndef PRG_RDB +#define PRG_RDB(addr) pgm_read_byte(addr) +#endif + +/* ------------------------------------------------------------------------- */ + static inline void usbResetDataToggling(void) { -#if USB_CFG_HAVE_INTRIN_ENDPOINT && !USB_CFG_SUPPRESS_INTR_CODE +#if USB_CFG_HAVE_INTRIN_ENDPOINT USB_SET_DATATOKEN1(USB_INITIAL_DATATOKEN); /* reset data toggling for interrupt endpoint */ # if USB_CFG_HAVE_INTRIN_ENDPOINT3 USB_SET_DATATOKEN3(USB_INITIAL_DATATOKEN); /* reset data toggling for interrupt endpoint */ @@ -216,7 +226,6 @@ static inline void usbResetStall(void) /* ------------------------------------------------------------------------- */ -#if !USB_CFG_SUPPRESS_INTR_CODE #if USB_CFG_HAVE_INTRIN_ENDPOINT static void usbGenericSetInterrupt(uchar *data, uchar len, usbTxStatus_t *txStatus) { @@ -254,7 +263,6 @@ USB_PUBLIC void usbSetInterrupt3(uchar *data, uchar len) usbGenericSetInterrupt(data, len, &usbTxStatus3); } #endif -#endif /* USB_CFG_SUPPRESS_INTR_CODE */ /* ------------------ utilities for code following below ------------------- */ @@ -400,7 +408,7 @@ uchar index = rq->wIndex.bytes[0]; usbResetStall(); SWITCH_CASE(USBRQ_GET_INTERFACE) /* 10 */ len = 1; -#if USB_CFG_HAVE_INTRIN_ENDPOINT && !USB_CFG_SUPPRESS_INTR_CODE +#if USB_CFG_HAVE_INTRIN_ENDPOINT SWITCH_CASE(USBRQ_SET_INTERFACE) /* 11 */ usbResetDataToggling(); usbResetStall(); @@ -428,7 +436,7 @@ usbRequest_t *rq = (void *)data; * 0xe1 11100001 (USBPID_OUT: data phase of setup transfer) * 0...0x0f for OUT on endpoint X */ - DBG2(0x10 + (usbRxToken & 0xf), data, len + 2); /* SETUP=1d, SETUP-DATA=11, OUTx=1x */ + DBG2(0x10 + (usbRxToken & 0xf), data, len); /* SETUP=1d, SETUP-DATA=11, OUTx=1x */ USB_RX_USER_HOOK(data, len) #if USB_CFG_IMPLEMENT_FN_WRITEOUT if(usbRxToken < 0x10){ /* OUT to endpoint != 0: endpoint number in usbRxToken */ @@ -451,13 +459,9 @@ usbRequest_t *rq = (void *)data; } #if USB_CFG_IMPLEMENT_FN_READ || USB_CFG_IMPLEMENT_FN_WRITE if(replyLen == USB_NO_MSG){ /* use user-supplied read/write function */ - /* do some conditioning on replyLen, but on IN transfers only */ + /* do some conditioning on replyLen */ if((rq->bmRequestType & USBRQ_DIR_MASK) != USBRQ_DIR_HOST_TO_DEVICE){ - if(sizeof(replyLen) < sizeof(rq->wLength.word)){ /* help compiler with optimizing */ - replyLen = rq->wLength.bytes[0]; - }else{ - replyLen = rq->wLength.word; - } + replyLen = rq->wLength.bytes[0]; /* IN transfers only */ } usbMsgFlags = USB_FLG_USE_USER_RW; }else /* The 'else' prevents that we limit a replyLen of USB_NO_MSG to the maximum transfer len. */ @@ -501,7 +505,7 @@ static uchar usbDeviceRead(uchar *data, uchar len) uchar i = len, *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 */ + uchar c = PRG_RDB(r); /* assign to char size variable to enforce byte ops */ *data++ = c; r++; }while(--i); @@ -588,17 +592,17 @@ uchar i; usbBuildTxBlock(); } } - for(i = 20; i > 0; i--){ + for(i = 10; i > 0; i--){ uchar usbLineStatus = USBIN & USBMASK; if(usbLineStatus != 0) /* SE0 has ended */ - goto isNotReset; + break; + } + if(i == 0){ /* RESET condition, called multiple times during reset */ + usbNewDeviceAddr = 0; + usbDeviceAddr = 0; + usbResetStall(); + DBG1(0xff, 0, 0); } - /* RESET condition, called multiple times during reset */ - usbNewDeviceAddr = 0; - usbDeviceAddr = 0; - usbResetStall(); - DBG1(0xff, 0, 0); -isNotReset: usbHandleResetHook(i); } @@ -614,7 +618,7 @@ USB_PUBLIC void usbInit(void) #endif USB_INTR_ENABLE |= (1 << USB_INTR_ENABLE_BIT); usbResetDataToggling(); -#if USB_CFG_HAVE_INTRIN_ENDPOINT && !USB_CFG_SUPPRESS_INTR_CODE +#if USB_CFG_HAVE_INTRIN_ENDPOINT usbTxLen1 = USBPID_NAK; #if USB_CFG_HAVE_INTRIN_ENDPOINT3 usbTxLen3 = USBPID_NAK; diff --git a/avr/bootloader/usbdrv/usbdrv.h b/avr/bootloader/usbdrv/usbdrv.h index c0fb569..ca7392f 100644 --- a/avr/bootloader/usbdrv/usbdrv.h +++ b/avr/bootloader/usbdrv/usbdrv.h @@ -1,17 +1,17 @@ /* Name: usbdrv.h - * Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers + * Project: AVR USB driver * Author: Christian Starkjohann * Creation Date: 2004-12-29 * Tabsize: 4 * Copyright: (c) 2005 by OBJECTIVE DEVELOPMENT Software GmbH - * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt) - * This Revision: $Id: usbdrv.h 748 2009-04-15 15:05:07Z cs $ + * License: GNU GPL v2 (see License.txt) or proprietary (CommercialLicense.txt) + * This Revision: $Id: usbdrv.h 607 2008-05-13 15:57:28Z cs $ */ #ifndef __usbdrv_h_included__ #define __usbdrv_h_included__ #include "usbconfig.h" -#include "usbportability.h" +#include "iarcompat.h" /* Hardware Prerequisites: @@ -34,8 +34,8 @@ usbDeviceConnect() and usbDeviceDisconnect() further down in this file. Please adapt the values in usbconfig.h according to your hardware! -The device MUST be clocked at exactly 12 MHz, 15 MHz, 16 MHz or 20 MHz -or at 12.8 MHz resp. 16.5 MHz +/- 1%. See usbconfig-prototype.h for details. +The device MUST be clocked at exactly 12 MHz, 15 MHz or 16 MHz +or at 16.5 MHz +/- 1%. See usbconfig-prototype.h for details. Limitations: @@ -122,7 +122,7 @@ USB messages, even if they address another (low-speed) device on the same bus. /* --------------------------- Module Interface ---------------------------- */ /* ------------------------------------------------------------------------- */ -#define USBDRV_VERSION 20090415 +#define USBDRV_VERSION 20080513 /* 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 @@ -273,8 +273,6 @@ USB_PUBLIC uchar usbFunctionRead(uchar *data, uchar len); * to 1 in usbconfig.h and return 0xff in usbFunctionSetup().. */ #endif /* USB_CFG_IMPLEMENT_FN_READ */ - -extern uchar usbRxToken; /* may be used in usbFunctionWriteOut() below */ #if USB_CFG_IMPLEMENT_FN_WRITEOUT USB_PUBLIC void usbFunctionWriteOut(uchar *data, uchar len); /* This function is called by the driver when data is received on an interrupt- @@ -341,12 +339,6 @@ extern volatile uchar usbSofCount; * the macro USB_COUNT_SOF is defined to a value != 0. */ #endif -#if USB_CFG_CHECK_DATA_TOGGLING -extern uchar usbCurrentDataToken; -/* This variable can be checked in usbFunctionWrite() and usbFunctionWriteOut() - * to ignore duplicate packets. - */ -#endif #define USB_STRING_DESCRIPTOR_HEADER(stringLength) ((2*(stringLength)+2) | (3<<8)) /* This macro builds a descriptor header for a string descriptor given the @@ -390,9 +382,7 @@ extern volatile schar usbRxLen; */ #define USB_PROP_IS_DYNAMIC (1 << 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. + * used to obtain the particular descriptor. */ #define USB_PROP_IS_RAM (1 << 15) /* If this property is set for a descriptor, the data is read from RAM @@ -556,10 +546,6 @@ int usbDescriptorStringSerialNumber[]; #define USB_CFG_EP3_NUMBER 3 #endif -#ifndef USB_CFG_HAVE_INTRIN_ENDPOINT3 -#define USB_CFG_HAVE_INTRIN_ENDPOINT3 0 -#endif - #define USB_BUFSIZE 11 /* PID, 8 bytes data, 2 bytes CRC */ /* ----- Try to find registers and bits responsible for ext interrupt 0 ----- */ @@ -572,14 +558,7 @@ int usbDescriptorStringSerialNumber[]; # endif #endif #ifndef USB_INTR_CFG_SET /* allow user to override our default */ -# if defined(USB_COUNT_SOF) || defined(USB_SOF_HOOK) -# define USB_INTR_CFG_SET (1 << ISC01) /* cfg for falling edge */ - /* If any SOF logic is used, the interrupt must be wired to D- where - * we better trigger on falling edge - */ -# else -# define USB_INTR_CFG_SET ((1 << ISC00) | (1 << ISC01)) /* cfg for rising edge */ -# endif +# define USB_INTR_CFG_SET ((1 << ISC00) | (1 << ISC01)) /* cfg for rising edge */ #endif #ifndef USB_INTR_CFG_CLR /* allow user to override our default */ # define USB_INTR_CFG_CLR 0 /* no bits to clear */ diff --git a/avr/bootloader/usbdrv/usbdrvasm.S b/avr/bootloader/usbdrv/usbdrvasm.S index 84121be..2c06421 100644 --- a/avr/bootloader/usbdrv/usbdrvasm.S +++ b/avr/bootloader/usbdrv/usbdrvasm.S @@ -1,11 +1,11 @@ /* Name: usbdrvasm.S - * Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers + * Project: AVR USB driver * Author: Christian Starkjohann * Creation Date: 2007-06-13 * 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 740 2009-04-13 18:23:31Z cs $ + * License: GNU GPL v2 (see License.txt) or proprietary (CommercialLicense.txt) + * Revision: $Id$ */ /* @@ -15,9 +15,16 @@ general code (preprocessor acrobatics and CRC computation) and then includes the file appropriate for the given clock rate. */ -#define __SFR_OFFSET 0 /* used by avr-libc's register definitions */ -#include "usbportability.h" -#include "usbdrv.h" /* for common defs */ +#include "iarcompat.h" +#ifndef __IAR_SYSTEMS_ASM__ + /* configs for io.h */ +# define __SFR_OFFSET 0 +# define _VECTOR(N) __vector_ ## N /* io.h does not define this for asm */ +# include /* for CPU I/O register definitions and vectors */ +# define macro .macro /* GNU Assembler macro definition */ +# define endm .endm /* End of GNU Assembler macro definition */ +#endif /* __IAR_SYSTEMS_ASM__ */ +#include "usbdrv.h" /* for common defs */ /* register names */ #define x1 r16 @@ -26,14 +33,24 @@ the file appropriate for the given clock rate. #define cnt r19 #define x3 r20 #define x4 r21 -#define x5 r22 -#define bitcnt x5 +#define bitcnt r22 #define phase x4 #define leap x4 /* Some assembler dependent definitions and declarations: */ #ifdef __IAR_SYSTEMS_ASM__ + +# define nop2 rjmp $+2 /* jump to next instruction */ +# define XL r26 +# define XH r27 +# define YL r28 +# define YH r29 +# define ZL r30 +# define ZH r31 +# define lo8(x) LOW(x) +# define hi8(x) (((x)>>8) & 0xff) /* not HIGH to allow XLINK to make a proper range check */ + extern usbRxBuf, usbDeviceAddr, usbNewDeviceAddr, usbInputBufOffset extern usbCurrentTok, usbRxLen, usbRxToken, usbTxLen extern usbTxBuf, usbTxStatus1, usbTxStatus3 @@ -56,6 +73,8 @@ the file appropriate for the given clock rate. #else /* __IAR_SYSTEMS_ASM__ */ +# define nop2 rjmp .+0 /* jump to next instruction */ + # ifndef USB_INTR_VECTOR /* default to hardware interrupt INT0 */ # define USB_INTR_VECTOR SIG_INTERRUPT0 # endif @@ -280,26 +299,16 @@ usbMFTimeout: # define USB_CFG_CLOCK_KHZ 12000 #endif -#if USB_CFG_CHECK_CRC /* separate dispatcher for CRC type modules */ -# if USB_CFG_CLOCK_KHZ == 18000 -# include "usbdrvasm18-crc.inc" -# else -# error "USB_CFG_CLOCK_KHZ is not one of the supported crc-rates!" -# endif -#else /* USB_CFG_CHECK_CRC */ -# if USB_CFG_CLOCK_KHZ == 12000 -# include "usbdrvasm12.inc" -# elif USB_CFG_CLOCK_KHZ == 12800 -# include "usbdrvasm128.inc" -# elif USB_CFG_CLOCK_KHZ == 15000 -# include "usbdrvasm15.inc" -# elif USB_CFG_CLOCK_KHZ == 16000 -# include "usbdrvasm16.inc" -# elif USB_CFG_CLOCK_KHZ == 16500 -# include "usbdrvasm165.inc" -# elif USB_CFG_CLOCK_KHZ == 20000 -# include "usbdrvasm20.inc" -# else -# error "USB_CFG_CLOCK_KHZ is not one of the supported non-crc-rates!" -# endif -#endif /* USB_CFG_CHECK_CRC */ +#if USB_CFG_CLOCK_KHZ == 12000 +# include "usbdrvasm12.inc" +#elif USB_CFG_CLOCK_KHZ == 15000 +# include "usbdrvasm15.inc" +#elif USB_CFG_CLOCK_KHZ == 16000 +# include "usbdrvasm16.inc" +#elif USB_CFG_CLOCK_KHZ == 16500 +# include "usbdrvasm165.inc" +#elif USB_CFG_CLOCK_KHZ == 20000 +# include "usbdrvasm20.inc" +#else +# error "USB_CFG_CLOCK_KHZ is not one of the supported rates!" +#endif diff --git a/avr/bootloader/usbdrv/usbdrvasm.asm b/avr/bootloader/usbdrv/usbdrvasm.asm index 9cc4e4d..4a5486f 100644 --- a/avr/bootloader/usbdrv/usbdrvasm.asm +++ b/avr/bootloader/usbdrv/usbdrvasm.asm @@ -1,10 +1,10 @@ /* Name: usbdrvasm.asm - * Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers + * Project: AVR USB driver * Author: Christian Starkjohann * Creation Date: 2006-03-01 * Tabsize: 4 * Copyright: (c) 2006 by OBJECTIVE DEVELOPMENT Software GmbH - * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt) + * License: GNU GPL v2 (see License.txt) or proprietary (CommercialLicense.txt) * This Revision: $Id$ */ diff --git a/avr/bootloader/usbdrv/usbdrvasm12.inc b/avr/bootloader/usbdrv/usbdrvasm12.inc index c116758..23b988c 100644 --- a/avr/bootloader/usbdrv/usbdrvasm12.inc +++ b/avr/bootloader/usbdrv/usbdrvasm12.inc @@ -1,11 +1,11 @@ /* Name: usbdrvasm12.inc - * Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers + * Project: AVR USB driver * Author: Christian Starkjohann * Creation Date: 2004-12-29 * 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 $ + * License: GNU GPL v2 (see License.txt) or proprietary (CommercialLicense.txt) + * This Revision: $Id: usbdrvasm12.inc 483 2008-02-05 15:05:32Z cs $ */ /* Do not link this file! Link usbdrvasm.S instead, which includes the @@ -48,13 +48,10 @@ USB_INTR_VECTOR: ;---------------------------------------------------------------------------- ;sync byte (D-) pattern LSb to MSb: 01010100 [1 = idle = J, 0 = K] ;sync up with J to K edge during sync pattern -- use fastest possible loops -;The first part waits at most 1 bit long since we must be in sync pattern. -;YL is guarenteed to be < 0x80 because I flag is clear. When we jump to -;waitForJ, ensure that this prerequisite is met. +;first part has no timeout because it waits for IDLE or SE1 (== disconnected) waitForJ: - inc YL - sbis USBIN, USBMINUS - brne waitForJ ; just make sure we have ANY timeout + sbis USBIN, USBMINUS ;1 [40] wait for D- == 1 + rjmp waitForJ ;2 waitForK: ;The following code results in a sampling window of 1/4 bit which meets the spec. sbis USBIN, USBMINUS @@ -72,9 +69,6 @@ waitForK: inc YL sts usbSofCount, YL #endif /* USB_COUNT_SOF */ -#ifdef USB_SOF_HOOK - USB_SOF_HOOK -#endif rjmp sofError foundK: ;{3, 5} after falling D- edge, average delay: 4 cycles [we want 4 for center sampling] @@ -256,12 +250,12 @@ macro POP_STANDARD ; 12 cycles pop x1 pop shift pop YH - endm +endm macro POP_RETI ; 5 cycles pop YL out SREG, YL pop YL - endm +endm #include "asmcommon.inc" @@ -269,16 +263,25 @@ macro POP_RETI ; 5 cycles ; Transmitting data ;---------------------------------------------------------------------------- -txByteLoop: -txBitloop: -stuffN1Delay: ; [03] - ror shift ;[-5] [11] [59] - brcc doExorN1 ;[-4] [60] - subi x4, 1 ;[-3] - brne commonN1 ;[-2] - lsl shift ;[-1] compensate ror after rjmp stuffDelay - nop ;[00] stuffing consists of just waiting 8 cycles - rjmp stuffN1Delay ;[01] after ror, C bit is reliably clear +bitstuff0: ;1 (for branch taken) + eor x1, x4 ;1 + ldi x2, 0 ;1 + out USBOUT, x1 ;1 <-- out + rjmp didStuff0 ;2 branch back 2 cycles earlier +bitstuff1: ;1 (for branch taken) + eor x1, x4 ;1 + rjmp didStuff1 ;2 we know that C is clear, jump back to do OUT and ror 0 into x2 +bitstuff2: ;1 (for branch taken) + eor x1, x4 ;1 + rjmp didStuff2 ;2 jump back 4 cycles earlier and do out and ror 0 into x2 +bitstuff3: ;1 (for branch taken) + eor x1, x4 ;1 + rjmp didStuff3 ;2 jump back earlier and ror 0 into x2 +bitstuff4: ;1 (for branch taken) + eor x1, x4 ;1 + ldi x2, 0 ;1 + out USBOUT, x1 ;1 <-- out + rjmp didStuff4 ;2 jump back 2 cycles earlier sendNakAndReti: ;0 [-19] 19 cycles until SOP ldi x3, USBPID_NAK ;1 [-18] @@ -303,91 +306,122 @@ usbSendX3: ;0 [-16] ;usbSend: ;pointer to data in 'Y' ;number of bytes in 'cnt' -- including sync byte -;uses: x1...x2, x4, shift, cnt, Y [x1 = mirror USBOUT, x2 = USBMASK, x4 = bitstuff cnt] -;Numbers in brackets are time since first bit of sync pattern is sent (start of instruction) -usbSendAndReti: - in x2, USBDDR ;[-12] 12 cycles until SOP - ori x2, USBMASK ;[-11] - sbi USBOUT, USBMINUS ;[-10] prepare idle state; D+ and D- must have been 0 (no pullups) - out USBDDR, x2 ;[-8] <--- acquire bus - in x1, USBOUT ;[-7] port mirror for tx loop - ldi shift, 0x40 ;[-6] sync byte is first byte sent (we enter loop after ror) - ldi x2, USBMASK ;[-5] - push x4 ;[-4] -doExorN1: - eor x1, x2 ;[-2] [06] [62] - ldi x4, 6 ;[-1] [07] [63] -commonN1: -stuffN2Delay: - out USBOUT, x1 ;[00] [08] [64] <--- set bit - ror shift ;[01] - brcc doExorN2 ;[02] - subi x4, 1 ;[03] - brne commonN2 ;[04] - lsl shift ;[05] compensate ror after rjmp stuffDelay - rjmp stuffN2Delay ;[06] after ror, C bit is reliably clear -doExorN2: - eor x1, x2 ;[04] [12] - ldi x4, 6 ;[05] [13] -commonN2: - nop ;[06] [14] - subi cnt, 171 ;[07] [15] trick: (3 * 171) & 0xff = 1 - out USBOUT, x1 ;[08] [16] <--- set bit - brcs txBitloop ;[09] [25] [41] - -stuff6Delay: - ror shift ;[42] [50] - brcc doExor6 ;[43] - subi x4, 1 ;[44] - brne common6 ;[45] - lsl shift ;[46] compensate ror after rjmp stuffDelay - nop ;[47] stuffing consists of just waiting 8 cycles - rjmp stuff6Delay ;[48] after ror, C bit is reliably clear -doExor6: - eor x1, x2 ;[45] [53] - ldi x4, 6 ;[46] -common6: -stuff7Delay: - ror shift ;[47] [55] - out USBOUT, x1 ;[48] <--- set bit - brcc doExor7 ;[49] - subi x4, 1 ;[50] - brne common7 ;[51] - lsl shift ;[52] compensate ror after rjmp stuffDelay - rjmp stuff7Delay ;[53] after ror, C bit is reliably clear -doExor7: - eor x1, x2 ;[51] [59] - ldi x4, 6 ;[52] -common7: - ld shift, y+ ;[53] - tst cnt ;[55] - out USBOUT, x1 ;[56] <--- set bit - brne txByteLoop ;[57] - +;uses: x1...x4, shift, cnt, Y +;Numbers in brackets are time since first bit of sync pattern is sent +usbSendAndReti: ;0 [-13] timing: 13 cycles until SOP + in x2, USBDDR ;1 [-12] + ori x2, USBMASK ;1 [-11] + sbi USBOUT, USBMINUS;2 [-9] prepare idle state; D+ and D- must have been 0 (no pullups) + in x1, USBOUT ;1 [-8] port mirror for tx loop + out USBDDR, x2 ;1 [-7] <- acquire bus +; need not init x2 (bitstuff history) because sync starts with 0 + push x4 ;2 [-5] + ldi x4, USBMASK ;1 [-4] exor mask + ldi shift, 0x80 ;1 [-3] sync byte is first byte sent +txLoop: ; [62] + sbrs shift, 0 ;1 [-2] [62] + eor x1, x4 ;1 [-1] [63] + out USBOUT, x1 ;1 [0] <-- out bit 0 + ror shift ;1 [1] + ror x2 ;1 [2] +didStuff0: + cpi x2, 0xfc ;1 [3] + brsh bitstuff0 ;1 [4] + sbrs shift, 0 ;1 [5] + eor x1, x4 ;1 [6] + ror shift ;1 [7] +didStuff1: + out USBOUT, x1 ;1 [8] <-- out bit 1 + ror x2 ;1 [9] + cpi x2, 0xfc ;1 [10] + brsh bitstuff1 ;1 [11] + sbrs shift, 0 ;1 [12] + eor x1, x4 ;1 [13] + ror shift ;1 [14] +didStuff2: + ror x2 ;1 [15] + out USBOUT, x1 ;1 [16] <-- out bit 2 + cpi x2, 0xfc ;1 [17] + brsh bitstuff2 ;1 [18] + sbrs shift, 0 ;1 [19] + eor x1, x4 ;1 [20] + ror shift ;1 [21] +didStuff3: + ror x2 ;1 [22] + cpi x2, 0xfc ;1 [23] + out USBOUT, x1 ;1 [24] <-- out bit 3 + brsh bitstuff3 ;1 [25] + nop2 ;2 [27] + ld x3, y+ ;2 [29] + sbrs shift, 0 ;1 [30] + eor x1, x4 ;1 [31] + out USBOUT, x1 ;1 [32] <-- out bit 4 + ror shift ;1 [33] + ror x2 ;1 [34] +didStuff4: + cpi x2, 0xfc ;1 [35] + brsh bitstuff4 ;1 [36] + sbrs shift, 0 ;1 [37] + eor x1, x4 ;1 [38] + ror shift ;1 [39] +didStuff5: + out USBOUT, x1 ;1 [40] <-- out bit 5 + ror x2 ;1 [41] + cpi x2, 0xfc ;1 [42] + brsh bitstuff5 ;1 [43] + sbrs shift, 0 ;1 [44] + eor x1, x4 ;1 [45] + ror shift ;1 [46] +didStuff6: + ror x2 ;1 [47] + out USBOUT, x1 ;1 [48] <-- out bit 6 + cpi x2, 0xfc ;1 [49] + brsh bitstuff6 ;1 [50] + sbrs shift, 0 ;1 [51] + eor x1, x4 ;1 [52] + ror shift ;1 [53] +didStuff7: + ror x2 ;1 [54] + cpi x2, 0xfc ;1 [55] + out USBOUT, x1 ;1 [56] <-- out bit 7 + brsh bitstuff7 ;1 [57] + mov shift, x3 ;1 [58] + dec cnt ;1 [59] + brne txLoop ;1/2 [60/61] ;make SE0: - cbr x1, USBMASK ;[58] prepare SE0 [spec says EOP may be 15 to 18 cycles] - lds x2, usbNewDeviceAddr;[59] - lsl x2 ;[61] we compare with left shifted address - subi YL, 2 + 20 ;[62] Only assign address on data packets, not ACK/NAK in x3 - sbci YH, 0 ;[63] - out USBOUT, x1 ;[00] <-- out SE0 -- from now 2 bits = 16 cycles until bus idle + cbr x1, USBMASK ;1 [61] prepare SE0 [spec says EOP may be 15 to 18 cycles] + pop x4 ;2 [63] +;brackets are cycles from start of SE0 now + out USBOUT, x1 ;1 [0] <-- out SE0 -- from now 2 bits = 16 cycles until bus idle ;2006-03-06: moved transfer of new address to usbDeviceAddr from C-Code to asm: ;set address only after data packet was sent, not after handshake - breq skipAddrAssign ;[01] - sts usbDeviceAddr, x2 ; if not skipped: SE0 is one cycle longer + lds x2, usbNewDeviceAddr;2 [2] + lsl x2; ;1 [3] we compare with left shifted address + subi YL, 20 + 2 ;1 [4] Only assign address on data packets, not ACK/NAK in x3 + sbci YH, 0 ;1 [5] + breq skipAddrAssign ;2 [7] + sts usbDeviceAddr, x2; if not skipped: SE0 is one cycle longer skipAddrAssign: ;end of usbDeviceAddress transfer - ldi x2, 1<