diff options
Diffstat (limited to 'usb_boot')
-rw-r--r-- | usb_boot/Makefile | 212 | ||||
-rw-r--r-- | usb_boot/df10ch_usb_boot.c (renamed from usb_boot/10ch_usb_boot.c) | 646 | ||||
-rw-r--r-- | usb_boot/usbconfig.h | 60 |
3 files changed, 459 insertions, 459 deletions
diff --git a/usb_boot/Makefile b/usb_boot/Makefile index 6f63ffa..db3beb5 100644 --- a/usb_boot/Makefile +++ b/usb_boot/Makefile @@ -1,106 +1,106 @@ -#
-# Copyright (C) 2010 Andreas Auras
-#
-# This file is part of the DF10CH Atmolight controller project.
-#
-# DF10CH Atmolight controller is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# DF10CH Atmolight controller is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
-#
-#
-###############################################################################
-# Makefile for the bootloader firmware of USB processor
-###############################################################################
-
-## General Flags
-PROJECT = 10ch_usb_boot
-MCU = atmega8
-TARGET = 10ch_usb_boot.elf
-CC = avr-gcc
-AVRDUDE ?= avrdude -c stk500v2 -P avrdoper
-USBDRV ?= ../usbdrv
-F_CPU ?= 16000000UL
-FIRMWARE_VERSION ?= 1
-
-## Options common to compile, link and assembly rules
-COMMON = -mmcu=$(MCU)
-
-## Compile options common for all C compilation units.
-CFLAGS = $(COMMON)
-CFLAGS += -Wall -gdwarf-2 -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums
-CFLAGS += -DF_CPU=$(F_CPU) -DFIRMWARE_VERSION=$(FIRMWARE_VERSION)
-
-## Assembly specific flags
-ASMFLAGS = $(COMMON)
-ASMFLAGS += $(CFLAGS)
-ASMFLAGS += -x assembler-with-cpp -Wa,-gdwarf2
-
-## Linker flags
-LDFLAGS = $(COMMON)
-LDFLAGS += -Wl,-Map=10ch_usb_boot.map
-LDFLAGS += -Wl,-section-start=.text=0x1800
-
-
-## Intel Hex file production flags
-HEX_FLASH_FLAGS = -R .eeprom -R .fuse -R .lock -R .signature
-
-HEX_EEPROM_FLAGS = -j .eeprom
-HEX_EEPROM_FLAGS += --set-section-flags=.eeprom="alloc,load"
-
-## Include Directories
-INCLUDES = -I. -I.. -I$(USBDRV)
-
-## Objects that must be built in order to link
-OBJECTS = 10ch_usb_boot.o usbdrvasm.o
-
-## Objects explicitly added by the user
-LINKONLYOBJECTS =
-
-## Build
-all: $(TARGET) 10ch_usb_boot.hex 10ch_usb_boot.lss size
-
-prog: flash
- $(AVRDUDE) -p $(MCU) -u -Ulfuse:w:0x1F:m -Uhfuse:w:0xC8:m -Ulock:w:0xEF:m
-
-flash: 10ch_usb_boot.hex
- $(AVRDUDE) -p $(MCU) -Uflash:w:10ch_usb_boot.hex:i
-
-
-## Compile
-usbdrvasm.o: $(USBDRV)/usbdrvasm.S usbconfig.h
- $(CC) $(INCLUDES) $(ASMFLAGS) -c $<
-
-10ch_usb_boot.o: 10ch_usb_boot.c usbconfig.h ../df10ch_usb_proto.h ../df10ch_common.h
- $(CC) $(INCLUDES) $(CFLAGS) -c $<
-
-##Link
-$(TARGET): $(OBJECTS)
- $(CC) $(LDFLAGS) $(OBJECTS) $(LINKONLYOBJECTS) $(LIBDIRS) $(LIBS) -o $(TARGET)
-
-%.hex: $(TARGET)
- avr-objcopy -O ihex $(HEX_FLASH_FLAGS) $< $@
-
-%.eep: $(TARGET)
- -avr-objcopy $(HEX_EEPROM_FLAGS) -O ihex $< $@ || exit 0
-
-%.lss: $(TARGET)
- avr-objdump -h -S $< > $@
-
-size: ${TARGET}
- @echo
- @avr-size -C --mcu=${MCU} ${TARGET}
-
-## Clean target
-.PHONY: clean
-clean:
- -rm -rf $(OBJECTS) 10ch_usb_boot.elf 10ch_usb_boot.hex 10ch_usb_boot.eep 10ch_usb_boot.lss 10ch_usb_boot.map
+# +# Copyright (C) 2010 Andreas Auras +# +# This file is part of the DF10CH Atmolight controller project. +# +# DF10CH Atmolight controller is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# DF10CH Atmolight controller is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA +# +# +############################################################################### +# Makefile for the bootloader firmware of USB processor +############################################################################### + +## General Flags +PROJECT = df10ch_usb_boot +MCU = atmega8 +TARGET = df10ch_usb_boot.elf +CC = avr-gcc +AVRDUDE ?= avrdude -c stk500v2 -P avrdoper +USBDRV ?= ../usbdrv +F_CPU ?= 16000000UL +FIRMWARE_VERSION ?= 1 + +## Options common to compile, link and assembly rules +COMMON = -mmcu=$(MCU) + +## Compile options common for all C compilation units. +CFLAGS = $(COMMON) +CFLAGS += -Wall -gdwarf-2 -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums +CFLAGS += -DF_CPU=$(F_CPU) -DFIRMWARE_VERSION=$(FIRMWARE_VERSION) + +## Assembly specific flags +ASMFLAGS = $(COMMON) +ASMFLAGS += $(CFLAGS) +ASMFLAGS += -x assembler-with-cpp -Wa,-gdwarf2 + +## Linker flags +LDFLAGS = $(COMMON) +LDFLAGS += -Wl,-Map=df10ch_usb_boot.map +LDFLAGS += -Wl,-section-start=.text=0x1800 + + +## Intel Hex file production flags +HEX_FLASH_FLAGS = -R .eeprom -R .fuse -R .lock -R .signature + +HEX_EEPROM_FLAGS = -j .eeprom +HEX_EEPROM_FLAGS += --set-section-flags=.eeprom="alloc,load" + +## Include Directories +INCLUDES = -I. -I.. -I$(USBDRV) + +## Objects that must be built in order to link +OBJECTS = df10ch_usb_boot.o usbdrvasm.o + +## Objects explicitly added by the user +LINKONLYOBJECTS = + +## Build +all: $(TARGET) df10ch_usb_boot.hex df10ch_usb_boot.lss size + +prog: flash + $(AVRDUDE) -p $(MCU) -u -Ulfuse:w:0x1F:m -Uhfuse:w:0xC8:m -Ulock:w:0xEF:m + +flash: df10ch_usb_boot.hex + $(AVRDUDE) -p $(MCU) -Uflash:w:df10ch_usb_boot.hex:i + + +## Compile +usbdrvasm.o: $(USBDRV)/usbdrvasm.S usbconfig.h + $(CC) $(INCLUDES) $(ASMFLAGS) -c $< + +df10ch_usb_boot.o: df10ch_usb_boot.c usbconfig.h ../df10ch_usb_proto.h ../df10ch_common.h + $(CC) $(INCLUDES) $(CFLAGS) -c $< + +##Link +$(TARGET): $(OBJECTS) + $(CC) $(LDFLAGS) $(OBJECTS) $(LINKONLYOBJECTS) $(LIBDIRS) $(LIBS) -o $(TARGET) + +%.hex: $(TARGET) + avr-objcopy -O ihex $(HEX_FLASH_FLAGS) $< $@ + +%.eep: $(TARGET) + -avr-objcopy $(HEX_EEPROM_FLAGS) -O ihex $< $@ || exit 0 + +%.lss: $(TARGET) + avr-objdump -h -S $< > $@ + +size: ${TARGET} + @echo + @avr-size -C --mcu=${MCU} ${TARGET} + +## Clean target +.PHONY: clean +clean: + -rm -rf $(OBJECTS) df10ch_usb_boot.elf df10ch_usb_boot.hex df10ch_usb_boot.eep df10ch_usb_boot.lss df10ch_usb_boot.map diff --git a/usb_boot/10ch_usb_boot.c b/usb_boot/df10ch_usb_boot.c index 4d90a4a..9e72810 100644 --- a/usb_boot/10ch_usb_boot.c +++ b/usb_boot/df10ch_usb_boot.c @@ -1,323 +1,323 @@ -/*
- * Copyright (C) 2010 Andreas Auras
- *
- * This file is part of the DF10CH Atmolight controller project.
- *
- * DF10CH Atmolight controller is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * DF10CH Atmolight controller is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
- *
- */
-
-// ======================================================================
-// Bootloader firmware for USB processor.
-//
-
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <avr/io.h>
-#include <avr/interrupt.h>
-#include <avr/wdt.h>
-#include <avr/eeprom.h>
-#include <avr/boot.h>
-#include <avr/pgmspace.h>
-
-#include "../df10ch_common.h"
-#include "../df10ch_usb_proto.h"
-#include "usbconfig.h"
-
-
-// ---
-// Fuse-Bit settings for the flash programmer (ATmega8):
-// RSTDISBL=1
-// WDTON=1
-// SPIEN=0
-// CKOPT=0
-// EESAVE=1
-// BOOTSZ1=0
-// BOOTSZ0=0
-// BOOTRST=0
-//
-// BODLEVEL=0
-// BODEN=0
-// SUT1=0
-// SUT0=1
-// CKSEL3=1
-// CKSEL2=1
-// CKSEL1=1
-// CKSEL0=1
-//
-// Memory-Lock Bits:
-// BL12=1, BL11=0, BL02=1, BL01=1, LB2=1, LB1=1
-//
-FUSES =
-{
- .low = (FUSE_BODLEVEL & FUSE_BODEN & FUSE_SUT1),
- .high = (FUSE_SPIEN & FUSE_CKOPT & FUSE_BOOTSZ1 & FUSE_BOOTSZ0 & FUSE_BOOTRST)
-};
-LOCKBITS = (LB_MODE_1 & BLB0_MODE_1 & BLB1_MODE_2);
-//SIGNATURE_DATA = { SIGNATURE_2, SIGNATURE_1, SIGNATURE_0 } ;
-
-
-// ---
-// System clock related.
-// System clock ist implemented with hardware timer 1
-//
-#define SYS_HWPRESCALE 1024 // Hardware Prescaler
-
- // useconds <-> timer ticks conversation
-#define US2TICKS(t) ((uint16_t)((double)(t) * (double)F_CPU / (1000000.0 * (double)SYS_HWPRESCALE) + 0.5))
-#define TICKS2US(t) ((uint16_t)((t) / (F_CPU / (1000000UL * SYS_HWPRESCALE))))
-
-
- // Input pin (Jumper) for enable/disable of bootloader
- // Enabled when Jumper set -> 0, Disabled if Jumper is away -> 1
-#define BL_SENSE_DDR DDRB
-#define BL_SENSE_PORT PORTB
-#define BL_SENSE_PIN PINB
-#define BL_SENSE_BIT 0
-
-#define APPL_START_VECT 0x0000
-
-static uint8_t leave_state; // Is true when bootloader should be leaved
-
-
-// ---
-// USB related.
-//
-#define USB_DISCONNECT_TIME US2TICKS(500000UL)
-#define USB_STALL_RC 0xFF
-
-static uint8_t usb_last_data_token NOMEMINIT; // Token PID of last usb packet received
-static uint8_t usb_last_rc = USB_STALL_RC; // Return status of last payload packet
-static uint8_t payload_req NOMEMINIT; // ID of actual proccessed USB request
-
-// ---
-// flash programming related.
-//
-static uint16_t page_address NOMEMINIT; // actual page address
-static uint8_t page_offset NOMEMINIT; // actual offset into page
-static uint8_t page_size_reply[2] = { (SPM_PAGESIZE & 0xFF), (SPM_PAGESIZE >> 8) };
-
-#include <usbdrv.c>
-
-
-// ---
-// ISR handler for IRQ's that do not have a dedicated handler.
-//
-EMPTY_INTERRUPT(BADISR_vect)
-
-
-// ---
-// Write request payload data.
-//
-USB_PUBLIC uint8_t usbFunctionWrite(uint8_t *data, uint8_t len)
-{
- uint8_t rc = USB_STALL_RC;
-
- if (usb_last_rc != USB_STALL_RC)
- {
- if (len != 8 || usbCrc16(data, 8) == ((uint16_t *)data)[4])
- {
- if (usbCurrentDataToken == usb_last_data_token)
- return usb_last_rc; // Ignore packet
-
- if (payload_req == BL_REQ_WRITE_PAGE)
- {
- rc = 0;
- while (len > 1)
- {
- bytes_word_t code;
- code.bytes[0] = *data++;
- code.bytes[1] = *data++;
-
- cli();
- boot_page_fill(page_address + page_offset, code.word);
- sei();
-
- page_offset += 2;
- len -= 2;
- if (page_offset >= SPM_PAGESIZE)
- {
- cli();
- boot_page_write(page_address);
- sei();
-
- while (boot_spm_busy())
- wdt_reset();
-
- rc = 1;
- }
- }
- }
- }
- }
-
- if (rc)
- usb_last_rc = USB_STALL_RC;
- usb_last_data_token = usbCurrentDataToken;
-
- return rc;
-}
-
-
-// ---
-// Read request payload data.
-//
-USB_PUBLIC uint8_t usbFunctionRead(uint8_t *data, uint8_t len)
-{
- uint8_t rc = USB_STALL_RC;
-
- if (usb_last_rc != USB_STALL_RC)
- {
- if (payload_req == BL_REQ_READ_FLASH)
- {
- if (len > page_offset)
- len = page_offset;
- rc = len;
- if (len)
- {
- page_offset -= len;
- PGM_P p = (PGM_P) page_address;
- page_address += len;
- memcpy_P(data, p, len);
- }
- }
-
- if (rc != 8)
- usb_last_rc = USB_STALL_RC;
- }
-
- return rc;
-}
-
-
-// ---
-// Handle a non-standard USB SETUP packet.
-//
-USB_PUBLIC usbMsgLen_t usbFunctionSetup(uint8_t data[8])
-{
- usbRequest_t *r = (usbRequest_t *) data;
-
- usb_last_data_token = USBPID_SETUP;
- usb_last_rc = USB_STALL_RC;
- uint8_t rc = USB_NO_MSG;
-
- if (leave_state || usbCrc16(data, 8) != ((uint16_t *)data)[4])
- return rc;
-
- uint8_t req = r->bRequest;
- payload_req = req;
-
- if (req == BL_REQ_WRITE_PAGE)
- {
- page_address = r->wIndex.word;
- page_offset = 0;
-
- while (!eeprom_is_ready())
- wdt_reset();
-
- cli();
- boot_page_erase(page_address);
- sei();
-
- while (boot_spm_busy())
- wdt_reset();
-
- usb_last_rc = 0;
- }
- else if (req == BL_REQ_LEAVE_BOOT)
- {
- if (boot_rww_busy())
- boot_rww_enable();
- leave_state = 1;
- rc = 0;
- }
- else if (req == BL_REQ_GET_PAGE_SIZE)
- {
- usbMsgPtr = page_size_reply;
- rc = sizeof(page_size_reply);
- }
- else if (req == BL_REQ_READ_FLASH)
- {
- if (boot_rww_busy())
- boot_rww_enable();
- page_address = r->wIndex.word;
- page_offset = r->wLength.bytes[0];
- usb_last_rc = 0;
- }
-
- return rc;
-}
-
-
-// ----
-// Main
-//
-void main(void) NORETURN;
-void main(void)
-{
- cli();
-
- wdt_enable(WDTO_120MS); // Set watchdog timeout
-
- // Note: If application calls bootloader it must set the enable pin to output and low level
- if (bit_is_clear(BL_SENSE_DDR, BL_SENSE_BIT))
- set_bit(BL_SENSE_PORT, BL_SENSE_BIT); // activate pullup
-
- if ((pgm_read_word(APPL_START_VECT) != 0xFFFF) && // Application reset vector programmed?
- bit_is_set(BL_SENSE_PIN, BL_SENSE_BIT))
- { // boot loader disabled -> start application
- void (*jump_to_app)(void) = APPL_START_VECT / 2; // Need flash word address!
- jump_to_app();
- }
-
- GICR = _BV(IVCE); // enable change of interrupt vectors
- GICR = _BV(IVSEL); // move interrupts to boot flash section
-
- // initialize boot loader disable pin: input + pullup
- clear_bit(BL_SENSE_DDR, BL_SENSE_BIT);
- set_bit(BL_SENSE_PORT, BL_SENSE_BIT);
-
- usbDeviceDisconnect();
-
- // Initialize Timer 1
- TIMSK = 0;
- TCCR1A = 0;
- TCCR1B = 0;
- TCNT1 = 0;
- TCCR1B = _BV(CS12) | _BV(CS10); // Start timer 1, Prescaler 1024
-
- while (TCNT1 < USB_DISCONNECT_TIME)
- wdt_reset();
-
- TCCR1B = 0; // Stop timer 1
-
- usbDeviceConnect();
- usbInit();
-
- sei();
-
- // Main loop
- for (;;)
- {
- // Note: Delayed boot loader exit is done via watchdog timer reset
- if (!leave_state)
- wdt_reset();
-
- usbPoll(); // process USB requests
- }
-}
-
+/* + * Copyright (C) 2010 Andreas Auras + * + * This file is part of the DF10CH Atmolight controller project. + * + * DF10CH Atmolight controller is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * DF10CH Atmolight controller is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + */ + +// ====================================================================== +// Bootloader firmware for USB processor. +// + +#include <stdint.h> +#include <stdlib.h> +#include <string.h> + +#include <avr/io.h> +#include <avr/interrupt.h> +#include <avr/wdt.h> +#include <avr/eeprom.h> +#include <avr/boot.h> +#include <avr/pgmspace.h> + +#include "../df10ch_common.h" +#include "../df10ch_usb_proto.h" +#include "usbconfig.h" + + +// --- +// Fuse-Bit settings for the flash programmer (ATmega8): +// RSTDISBL=1 +// WDTON=1 +// SPIEN=0 +// CKOPT=0 +// EESAVE=1 +// BOOTSZ1=0 +// BOOTSZ0=0 +// BOOTRST=0 +// +// BODLEVEL=0 +// BODEN=0 +// SUT1=0 +// SUT0=1 +// CKSEL3=1 +// CKSEL2=1 +// CKSEL1=1 +// CKSEL0=1 +// +// Memory-Lock Bits: +// BL12=1, BL11=0, BL02=1, BL01=1, LB2=1, LB1=1 +// +FUSES = +{ + .low = (FUSE_BODLEVEL & FUSE_BODEN & FUSE_SUT1), + .high = (FUSE_SPIEN & FUSE_CKOPT & FUSE_BOOTSZ1 & FUSE_BOOTSZ0 & FUSE_BOOTRST) +}; +LOCKBITS = (LB_MODE_1 & BLB0_MODE_1 & BLB1_MODE_2); +//SIGNATURE_DATA = { SIGNATURE_2, SIGNATURE_1, SIGNATURE_0 } ; + + +// --- +// System clock related. +// System clock ist implemented with hardware timer 1 +// +#define SYS_HWPRESCALE 1024 // Hardware Prescaler + + // useconds <-> timer ticks conversation +#define US2TICKS(t) ((uint16_t)((double)(t) * (double)F_CPU / (1000000.0 * (double)SYS_HWPRESCALE) + 0.5)) +#define TICKS2US(t) ((uint16_t)((t) / (F_CPU / (1000000UL * SYS_HWPRESCALE)))) + + + // Input pin (Jumper) for enable/disable of bootloader + // Enabled when Jumper set -> 0, Disabled if Jumper is away -> 1 +#define BL_SENSE_DDR DDRB +#define BL_SENSE_PORT PORTB +#define BL_SENSE_PIN PINB +#define BL_SENSE_BIT 0 + +#define APPL_START_VECT 0x0000 + +static uint8_t leave_state; // Is true when bootloader should be leaved + + +// --- +// USB related. +// +#define USB_DISCONNECT_TIME US2TICKS(500000UL) +#define USB_STALL_RC 0xFF + +static uint8_t usb_last_data_token NOMEMINIT; // Token PID of last usb packet received +static uint8_t usb_last_rc = USB_STALL_RC; // Return status of last payload packet +static uint8_t payload_req NOMEMINIT; // ID of actual proccessed USB request + +// --- +// flash programming related. +// +static uint16_t page_address NOMEMINIT; // actual page address +static uint8_t page_offset NOMEMINIT; // actual offset into page +static uint8_t page_size_reply[2] = { (SPM_PAGESIZE & 0xFF), (SPM_PAGESIZE >> 8) }; + +#include <usbdrv.c> + + +// --- +// ISR handler for IRQ's that do not have a dedicated handler. +// +EMPTY_INTERRUPT(BADISR_vect) + + +// --- +// Write request payload data. +// +USB_PUBLIC uint8_t usbFunctionWrite(uint8_t *data, uint8_t len) +{ + uint8_t rc = USB_STALL_RC; + + if (usb_last_rc != USB_STALL_RC) + { + if (len != 8 || usbCrc16(data, 8) == ((uint16_t *)data)[4]) + { + if (usbCurrentDataToken == usb_last_data_token) + return usb_last_rc; // Ignore packet + + if (payload_req == BL_REQ_WRITE_PAGE) + { + rc = 0; + while (len > 1) + { + bytes_word_t code; + code.bytes[0] = *data++; + code.bytes[1] = *data++; + + cli(); + boot_page_fill(page_address + page_offset, code.word); + sei(); + + page_offset += 2; + len -= 2; + if (page_offset >= SPM_PAGESIZE) + { + cli(); + boot_page_write(page_address); + sei(); + + while (boot_spm_busy()) + wdt_reset(); + + rc = 1; + } + } + } + } + } + + if (rc) + usb_last_rc = USB_STALL_RC; + usb_last_data_token = usbCurrentDataToken; + + return rc; +} + + +// --- +// Read request payload data. +// +USB_PUBLIC uint8_t usbFunctionRead(uint8_t *data, uint8_t len) +{ + uint8_t rc = USB_STALL_RC; + + if (usb_last_rc != USB_STALL_RC) + { + if (payload_req == BL_REQ_READ_FLASH) + { + if (len > page_offset) + len = page_offset; + rc = len; + if (len) + { + page_offset -= len; + PGM_P p = (PGM_P) page_address; + page_address += len; + memcpy_P(data, p, len); + } + } + + if (rc != 8) + usb_last_rc = USB_STALL_RC; + } + + return rc; +} + + +// --- +// Handle a non-standard USB SETUP packet. +// +USB_PUBLIC usbMsgLen_t usbFunctionSetup(uint8_t data[8]) +{ + usbRequest_t *r = (usbRequest_t *) data; + + usb_last_data_token = USBPID_SETUP; + usb_last_rc = USB_STALL_RC; + uint8_t rc = USB_NO_MSG; + + if (leave_state || usbCrc16(data, 8) != ((uint16_t *)data)[4]) + return rc; + + uint8_t req = r->bRequest; + payload_req = req; + + if (req == BL_REQ_WRITE_PAGE) + { + page_address = r->wIndex.word; + page_offset = 0; + + while (!eeprom_is_ready()) + wdt_reset(); + + cli(); + boot_page_erase(page_address); + sei(); + + while (boot_spm_busy()) + wdt_reset(); + + usb_last_rc = 0; + } + else if (req == BL_REQ_LEAVE_BOOT) + { + if (boot_rww_busy()) + boot_rww_enable(); + leave_state = 1; + rc = 0; + } + else if (req == BL_REQ_GET_PAGE_SIZE) + { + usbMsgPtr = page_size_reply; + rc = sizeof(page_size_reply); + } + else if (req == BL_REQ_READ_FLASH) + { + if (boot_rww_busy()) + boot_rww_enable(); + page_address = r->wIndex.word; + page_offset = r->wLength.bytes[0]; + usb_last_rc = 0; + } + + return rc; +} + + +// ---- +// Main +// +void main(void) NORETURN; +void main(void) +{ + cli(); + + wdt_enable(WDTO_120MS); // Set watchdog timeout + + // Note: If application calls bootloader it must set the enable pin to output and low level + if (bit_is_clear(BL_SENSE_DDR, BL_SENSE_BIT)) + set_bit(BL_SENSE_PORT, BL_SENSE_BIT); // activate pullup + + if ((pgm_read_word(APPL_START_VECT) != 0xFFFF) && // Application reset vector programmed? + bit_is_set(BL_SENSE_PIN, BL_SENSE_BIT)) + { // boot loader disabled -> start application + void (*jump_to_app)(void) = APPL_START_VECT / 2; // Need flash word address! + jump_to_app(); + } + + GICR = _BV(IVCE); // enable change of interrupt vectors + GICR = _BV(IVSEL); // move interrupts to boot flash section + + // initialize boot loader disable pin: input + pullup + clear_bit(BL_SENSE_DDR, BL_SENSE_BIT); + set_bit(BL_SENSE_PORT, BL_SENSE_BIT); + + usbDeviceDisconnect(); + + // Initialize Timer 1 + TIMSK = 0; + TCCR1A = 0; + TCCR1B = 0; + TCNT1 = 0; + TCCR1B = _BV(CS12) | _BV(CS10); // Start timer 1, Prescaler 1024 + + while (TCNT1 < USB_DISCONNECT_TIME) + wdt_reset(); + + TCCR1B = 0; // Stop timer 1 + + usbDeviceConnect(); + usbInit(); + + sei(); + + // Main loop + for (;;) + { + // Note: Delayed boot loader exit is done via watchdog timer reset + if (!leave_state) + wdt_reset(); + + usbPoll(); // process USB requests + } +} + diff --git a/usb_boot/usbconfig.h b/usb_boot/usbconfig.h index e9899b7..70f76f1 100644 --- a/usb_boot/usbconfig.h +++ b/usb_boot/usbconfig.h @@ -183,17 +183,17 @@ section at the end of this file). * Please note that Start Of Frame detection works only if D- is wired to the * interrupt, not D+. THIS IS DIFFERENT THAN MOST EXAMPLES! */ -
-/* Save timestamp of sof */
-#ifdef __ASSEMBLER__
-macro customSofHook
- ldi YL, 0
+/* Save timestamp of sof */ + +#ifdef __ASSEMBLER__ +macro customSofHook + ldi YL, 0 out TCNT1H, YL out TCNT1L, YL endm #endif -
+ #define USB_CFG_CHECK_DATA_TOGGLING 1 /* 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 @@ -206,15 +206,15 @@ endm /* 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. */ -#define USB_USE_FAST_CRC 1
-/* The assembler module has two implementations for the CRC algorithm. One is
- * faster, the other is smaller. This CRC routine is only used for transmitted
- * messages where timing is not critical. The faster routine needs 31 cycles
- * per byte while the smaller one needs 61 to 69 cycles. The faster routine
- * may be worth the 32 bytes bigger code size if you transmit lots of data and
- * run the AVR close to its limit.
- */
-
+#define USB_USE_FAST_CRC 1 +/* The assembler module has two implementations for the CRC algorithm. One is + * faster, the other is smaller. This CRC routine is only used for transmitted + * messages where timing is not critical. The faster routine needs 31 cycles + * per byte while the smaller one needs 61 to 69 cycles. The faster routine + * may be worth the 32 bytes bigger code size if you transmit lots of data and + * run the AVR close to its limit. + */ + /* -------------------------- Device Description --------------------------- */ #define USB_CFG_VENDOR_ID 0xc0, 0x16 @@ -360,9 +360,9 @@ endm */ #define USB_INTR_CFG MCUCR #if defined(USB_COUNT_SOF) || defined(USB_SOF_HOOK) || 1 -#define USB_INTR_CFG_SET ((1 << ISC11))
+#define USB_INTR_CFG_SET ((1 << ISC11)) #else -#define USB_INTR_CFG_SET ((1 << ISC10) | (1 << ISC11))
+#define USB_INTR_CFG_SET ((1 << ISC10) | (1 << ISC11)) #endif /* #define USB_INTR_CFG_CLR 0 */ /* #define USB_INTR_ENABLE GIMSK */ @@ -370,22 +370,22 @@ endm /* #define USB_INTR_PENDING GIFR */ #define USB_INTR_PENDING_BIT INTF1 #define USB_INTR_VECTOR SIG_INTERRUPT1 -
-
-/* This is a new macro that is executed and the beginning of the usb irq handler.
- * This needs a patch in the corresponding clock dependend assembler file of VUSB!!!
- * It is save to use register YH here
- */
-/*#define USB_START_IRQ_HOOK customTriggerHook*/
-
-
+ + +/* This is a new macro that is executed and the beginning of the usb irq handler. + * This needs a patch in the corresponding clock dependend assembler file of VUSB!!! + * It is save to use register YH here + */ +/*#define USB_START_IRQ_HOOK customTriggerHook*/ + + /* Reinstall edge level interrupt triggering (after sleep) */ #ifdef __ASSEMBLER__ -macro customTriggerHook
- in YH, USB_INTR_CFG
+macro customTriggerHook + in YH, USB_INTR_CFG ori YH, USB_INTR_CFG_SET out USB_INTR_CFG, YH -endm
+endm #endif -
+ #endif /* __usbconfig_h_included__ */ |