[gnoduino] arduino: unix line ends for hardware
- From: Lucian Langa <lucilanga src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnoduino] arduino: unix line ends for hardware
- Date: Wed, 24 Sep 2014 19:56:51 +0000 (UTC)
commit a20c57444164356f2a1fd85512de11305297ab52
Author: Pascal de Bruijn <pmjdebruijn pcode nl>
Date: Thu Jul 17 18:47:25 2014 +0200
arduino: unix line ends for hardware
.../arduino/bootloaders/atmega/ATmegaBOOT_168.c | 2088 ++++++++++----------
.../bootloaders/caterina-Arduino_Robot/Caterina.c | 1559 ++++++++--------
.../bootloaders/caterina-Arduino_Robot/Caterina.h | 211 +-
.../caterina-Arduino_Robot/Descriptors.c | 539 +++---
.../caterina-Arduino_Robot/Descriptors.h | 277 ++--
.../bootloaders/caterina-LilyPadUSB/Caterina.c | 1559 ++++++++--------
.../bootloaders/caterina-LilyPadUSB/Caterina.h | 197 +-
.../bootloaders/caterina-LilyPadUSB/Descriptors.c | 519 +++---
.../bootloaders/caterina-LilyPadUSB/Descriptors.h | 277 ++--
.../bootloaders/caterina-LilyPadUSB/Readme.txt | 20 +-
hardware/arduino/bootloaders/caterina/Caterina.c | 1427 +++++++-------
hardware/arduino/bootloaders/caterina/Caterina.h | 211 +-
.../arduino/bootloaders/caterina/Descriptors.c | 531 +++---
.../arduino/bootloaders/caterina/Descriptors.h | 277 ++--
hardware/arduino/bootloaders/stk500v2/License.txt | 560 +++---
.../atmegaxxu2/arduino-usbdfu/Arduino-usbdfu.c | 1456 +++++++-------
.../atmegaxxu2/arduino-usbdfu/Arduino-usbdfu.h | 440 ++--
.../atmegaxxu2/arduino-usbdfu/Board/LEDs.h | 220 +-
.../atmegaxxu2/arduino-usbdfu/Descriptors.c | 378 ++--
.../atmegaxxu2/arduino-usbdfu/Descriptors.h | 354 ++--
.../arduino-usbserial/Arduino-usbserial.c | 484 +++---
.../arduino-usbserial/Arduino-usbserial.h | 158 +-
.../atmegaxxu2/arduino-usbserial/Board/LEDs.h | 220 +-
.../atmegaxxu2/arduino-usbserial/Descriptors.c | 554 +++---
.../atmegaxxu2/arduino-usbserial/Descriptors.h | 176 +-
.../arduino-usbserial/Lib/LightweightRingBuff.h | 394 ++--
26 files changed, 7537 insertions(+), 7549 deletions(-)
---
diff --git a/hardware/arduino/bootloaders/atmega/ATmegaBOOT_168.c
b/hardware/arduino/bootloaders/atmega/ATmegaBOOT_168.c
index 721f8ea..adfacda 100644
--- a/hardware/arduino/bootloaders/atmega/ATmegaBOOT_168.c
+++ b/hardware/arduino/bootloaders/atmega/ATmegaBOOT_168.c
@@ -1,952 +1,952 @@
-/**********************************************************/
-/* Serial Bootloader for Atmel megaAVR Controllers */
-/* */
-/* tested with ATmega8, ATmega128 and ATmega168 */
-/* should work with other mega's, see code for details */
-/* */
-/* ATmegaBOOT.c */
-/* */
-/* */
-/* 20090308: integrated Mega changes into main bootloader */
-/* source by D. Mellis */
-/* 20080930: hacked for Arduino Mega (with the 1280 */
-/* processor, backwards compatible) */
-/* by D. Cuartielles */
-/* 20070626: hacked for Arduino Diecimila (which auto- */
-/* resets when a USB connection is made to it) */
-/* by D. Mellis */
-/* 20060802: hacked for Arduino by D. Cuartielles */
-/* based on a previous hack by D. Mellis */
-/* and D. Cuartielles */
-/* */
-/* Monitor and debug functions were added to the original */
-/* code by Dr. Erik Lins, chip45.com. (See below) */
-/* */
-/* Thanks to Karl Pitrich for fixing a bootloader pin */
-/* problem and more informative LED blinking! */
-/* */
-/* For the latest version see: */
-/* http://www.chip45.com/ */
-/* */
-/* ------------------------------------------------------ */
-/* */
-/* based on stk500boot.c */
-/* Copyright (c) 2003, Jason P. Kyle */
-/* All rights reserved. */
-/* see avr1.org for original file and information */
-/* */
-/* This program 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. */
-/* */
-/* This program 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., */
-/* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-/* */
-/* Licence can be viewed at */
-/* http://www.fsf.org/licenses/gpl.txt */
-/* */
-/* Target = Atmel AVR m128,m64,m32,m16,m8,m162,m163,m169, */
-/* m8515,m8535. ATmega161 has a very small boot block so */
-/* isn't supported. */
-/* */
-/* Tested with m168 */
-/**********************************************************/
-
-/* $Id$ */
-
-
-/* some includes */
-#include <inttypes.h>
-#include <avr/io.h>
-#include <avr/pgmspace.h>
-#include <avr/interrupt.h>
-#include <avr/wdt.h>
-#include <util/delay.h>
-
-/* the current avr-libc eeprom functions do not support the ATmega168 */
-/* own eeprom write/read functions are used instead */
-#if !defined(__AVR_ATmega168__) || !defined(__AVR_ATmega328P__)
-#include <avr/eeprom.h>
-#endif
-
-/* Use the F_CPU defined in Makefile */
-
-/* 20060803: hacked by DojoCorp */
-/* 20070626: hacked by David A. Mellis to decrease waiting time for auto-reset */
-/* set the waiting time for the bootloader */
-/* get this from the Makefile instead */
-/* #define MAX_TIME_COUNT (F_CPU>>4) */
-
-/* 20070707: hacked by David A. Mellis - after this many errors give up and launch application */
-#define MAX_ERROR_COUNT 5
-
-/* set the UART baud rate */
-/* 20060803: hacked by DojoCorp */
-//#define BAUD_RATE 115200
-#ifndef BAUD_RATE
-#define BAUD_RATE 19200
-#endif
-
-
-/* SW_MAJOR and MINOR needs to be updated from time to time to avoid warning message from AVR Studio */
-/* never allow AVR Studio to do an update !!!! */
-#define HW_VER 0x02
-#define SW_MAJOR 0x01
-#define SW_MINOR 0x10
-
-
-/* Adjust to suit whatever pin your hardware uses to enter the bootloader */
-/* ATmega128 has two UARTS so two pins are used to enter bootloader and select UART */
-/* ATmega1280 has four UARTS, but for Arduino Mega, we will only use RXD0 to get code */
-/* BL0... means UART0, BL1... means UART1 */
-#ifdef __AVR_ATmega128__
-#define BL_DDR DDRF
-#define BL_PORT PORTF
-#define BL_PIN PINF
-#define BL0 PINF7
-#define BL1 PINF6
-#elif defined __AVR_ATmega1280__
-/* we just don't do anything for the MEGA and enter bootloader on reset anyway*/
-#else
-/* other ATmegas have only one UART, so only one pin is defined to enter bootloader */
-#define BL_DDR DDRD
-#define BL_PORT PORTD
-#define BL_PIN PIND
-#define BL PIND6
-#endif
-
-
-/* onboard LED is used to indicate, that the bootloader was entered (3x flashing) */
-/* if monitor functions are included, LED goes on after monitor was entered */
-#if defined __AVR_ATmega128__ || defined __AVR_ATmega1280__
-/* Onboard LED is connected to pin PB7 (e.g. Crumb128, PROBOmega128, Savvy128, Arduino Mega) */
-#define LED_DDR DDRB
-#define LED_PORT PORTB
-#define LED_PIN PINB
-#define LED PINB7
-#else
-/* Onboard LED is connected to pin PB5 in Arduino NG, Diecimila, and Duomilanuove */
-/* other boards like e.g. Crumb8, Crumb168 are using PB2 */
-#define LED_DDR DDRB
-#define LED_PORT PORTB
-#define LED_PIN PINB
-#define LED PINB5
-#endif
-
-
-/* monitor functions will only be compiled when using ATmega128, due to bootblock size constraints */
-#if defined(__AVR_ATmega128__) || defined(__AVR_ATmega1280__)
-#define MONITOR 1
-#endif
-
-
-/* define various device id's */
-/* manufacturer byte is always the same */
-#define SIG1 0x1E // Yep, Atmel is the only manufacturer of AVR micros. Single source :(
-
-#if defined __AVR_ATmega1280__
-#define SIG2 0x97
-#define SIG3 0x03
-#define PAGE_SIZE 0x80U //128 words
-
-#elif defined __AVR_ATmega1281__
-#define SIG2 0x97
-#define SIG3 0x04
-#define PAGE_SIZE 0x80U //128 words
-
-#elif defined __AVR_ATmega128__
-#define SIG2 0x97
-#define SIG3 0x02
-#define PAGE_SIZE 0x80U //128 words
-
-#elif defined __AVR_ATmega64__
-#define SIG2 0x96
-#define SIG3 0x02
-#define PAGE_SIZE 0x80U //128 words
-
-#elif defined __AVR_ATmega32__
-#define SIG2 0x95
-#define SIG3 0x02
-#define PAGE_SIZE 0x40U //64 words
-
-#elif defined __AVR_ATmega16__
-#define SIG2 0x94
-#define SIG3 0x03
-#define PAGE_SIZE 0x40U //64 words
-
-#elif defined __AVR_ATmega8__
-#define SIG2 0x93
-#define SIG3 0x07
-#define PAGE_SIZE 0x20U //32 words
-
-#elif defined __AVR_ATmega88__
-#define SIG2 0x93
-#define SIG3 0x0a
-#define PAGE_SIZE 0x20U //32 words
-
-#elif defined __AVR_ATmega168__
-#define SIG2 0x94
-#define SIG3 0x06
-#define PAGE_SIZE 0x40U //64 words
-
-#elif defined __AVR_ATmega328P__
-#define SIG2 0x95
-#define SIG3 0x0F
-#define PAGE_SIZE 0x40U //64 words
-
-#elif defined __AVR_ATmega162__
-#define SIG2 0x94
-#define SIG3 0x04
-#define PAGE_SIZE 0x40U //64 words
-
-#elif defined __AVR_ATmega163__
-#define SIG2 0x94
-#define SIG3 0x02
-#define PAGE_SIZE 0x40U //64 words
-
-#elif defined __AVR_ATmega169__
-#define SIG2 0x94
-#define SIG3 0x05
-#define PAGE_SIZE 0x40U //64 words
-
-#elif defined __AVR_ATmega8515__
-#define SIG2 0x93
-#define SIG3 0x06
-#define PAGE_SIZE 0x20U //32 words
-
-#elif defined __AVR_ATmega8535__
-#define SIG2 0x93
-#define SIG3 0x08
-#define PAGE_SIZE 0x20U //32 words
-#endif
-
-
-/* function prototypes */
-void putch(char);
-char getch(void);
-void getNch(uint8_t);
-void byte_response(uint8_t);
-void nothing_response(void);
-char gethex(void);
-void puthex(char);
-void flash_led(uint8_t);
-
-/* some variables */
-union address_union {
- uint16_t word;
- uint8_t byte[2];
-} address;
-
-union length_union {
- uint16_t word;
- uint8_t byte[2];
-} length;
-
-struct flags_struct {
- unsigned eeprom : 1;
- unsigned rampz : 1;
-} flags;
-
-uint8_t buff[256];
-uint8_t address_high;
-
-uint8_t pagesz=0x80;
-
-uint8_t i;
-uint8_t bootuart = 0;
-
-uint8_t error_count = 0;
-
-void (*app_start)(void) = 0x0000;
-
-
-/* main program starts here */
-int main(void)
-{
- uint8_t ch,ch2;
- uint16_t w;
-
-#ifdef WATCHDOG_MODS
- ch = MCUSR;
- MCUSR = 0;
-
- WDTCSR |= _BV(WDCE) | _BV(WDE);
- WDTCSR = 0;
-
- // Check if the WDT was used to reset, in which case we dont bootload and skip straight to the code.
woot.
- if (! (ch & _BV(EXTRF))) // if its a not an external reset...
- app_start(); // skip bootloader
-#else
- asm volatile("nop\n\t");
-#endif
-
- /* set pin direction for bootloader pin and enable pullup */
- /* for ATmega128, two pins need to be initialized */
-#ifdef __AVR_ATmega128__
- BL_DDR &= ~_BV(BL0);
- BL_DDR &= ~_BV(BL1);
- BL_PORT |= _BV(BL0);
- BL_PORT |= _BV(BL1);
-#else
- /* We run the bootloader regardless of the state of this pin. Thus, don't
- put it in a different state than the other pins. --DAM, 070709
- This also applies to Arduino Mega -- DC, 080930
- BL_DDR &= ~_BV(BL);
- BL_PORT |= _BV(BL);
- */
-#endif
-
-
-#ifdef __AVR_ATmega128__
- /* check which UART should be used for booting */
- if(bit_is_clear(BL_PIN, BL0)) {
- bootuart = 1;
- }
- else if(bit_is_clear(BL_PIN, BL1)) {
- bootuart = 2;
- }
-#endif
-
-#if defined __AVR_ATmega1280__
- /* the mega1280 chip has four serial ports ... we could eventually use any of them, or not? */
- /* however, we don't wanna confuse people, to avoid making a mess, we will stick to RXD0, TXD0 */
- bootuart = 1;
-#endif
-
- /* check if flash is programmed already, if not start bootloader anyway */
- if(pgm_read_byte_near(0x0000) != 0xFF) {
-
-#ifdef __AVR_ATmega128__
- /* no UART was selected, start application */
- if(!bootuart) {
- app_start();
- }
-#else
- /* check if bootloader pin is set low */
- /* we don't start this part neither for the m8, nor m168 */
- //if(bit_is_set(BL_PIN, BL)) {
- // app_start();
- // }
-#endif
- }
-
-#ifdef __AVR_ATmega128__
- /* no bootuart was selected, default to uart 0 */
- if(!bootuart) {
- bootuart = 1;
- }
-#endif
-
-
- /* initialize UART(s) depending on CPU defined */
-#if defined(__AVR_ATmega128__) || defined(__AVR_ATmega1280__)
- if(bootuart == 1) {
- UBRR0L = (uint8_t)(F_CPU/(BAUD_RATE*16L)-1);
- UBRR0H = (F_CPU/(BAUD_RATE*16L)-1) >> 8;
- UCSR0A = 0x00;
- UCSR0C = 0x06;
- UCSR0B = _BV(TXEN0)|_BV(RXEN0);
- }
- if(bootuart == 2) {
- UBRR1L = (uint8_t)(F_CPU/(BAUD_RATE*16L)-1);
- UBRR1H = (F_CPU/(BAUD_RATE*16L)-1) >> 8;
- UCSR1A = 0x00;
- UCSR1C = 0x06;
- UCSR1B = _BV(TXEN1)|_BV(RXEN1);
- }
-#elif defined __AVR_ATmega163__
- UBRR = (uint8_t)(F_CPU/(BAUD_RATE*16L)-1);
- UBRRHI = (F_CPU/(BAUD_RATE*16L)-1) >> 8;
- UCSRA = 0x00;
- UCSRB = _BV(TXEN)|_BV(RXEN);
-#elif defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__)
-
-#ifdef DOUBLE_SPEED
- UCSR0A = (1<<U2X0); //Double speed mode USART0
- UBRR0L = (uint8_t)(F_CPU/(BAUD_RATE*8L)-1);
- UBRR0H = (F_CPU/(BAUD_RATE*8L)-1) >> 8;
-#else
- UBRR0L = (uint8_t)(F_CPU/(BAUD_RATE*16L)-1);
- UBRR0H = (F_CPU/(BAUD_RATE*16L)-1) >> 8;
-#endif
-
- UCSR0B = (1<<RXEN0) | (1<<TXEN0);
- UCSR0C = (1<<UCSZ00) | (1<<UCSZ01);
-
- /* Enable internal pull-up resistor on pin D0 (RX), in order
- to supress line noise that prevents the bootloader from
- timing out (DAM: 20070509) */
- DDRD &= ~_BV(PIND0);
- PORTD |= _BV(PIND0);
-#elif defined __AVR_ATmega8__
- /* m8 */
- UBRRH = (((F_CPU/BAUD_RATE)/16)-1)>>8; // set baud rate
- UBRRL = (((F_CPU/BAUD_RATE)/16)-1);
- UCSRB = (1<<RXEN)|(1<<TXEN); // enable Rx & Tx
- UCSRC = (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0); // config USART; 8N1
-#else
- /* m16,m32,m169,m8515,m8535 */
- UBRRL = (uint8_t)(F_CPU/(BAUD_RATE*16L)-1);
- UBRRH = (F_CPU/(BAUD_RATE*16L)-1) >> 8;
- UCSRA = 0x00;
- UCSRC = 0x06;
- UCSRB = _BV(TXEN)|_BV(RXEN);
-#endif
-
-#if defined __AVR_ATmega1280__
- /* Enable internal pull-up resistor on pin D0 (RX), in order
- to supress line noise that prevents the bootloader from
- timing out (DAM: 20070509) */
- /* feature added to the Arduino Mega --DC: 080930 */
- DDRE &= ~_BV(PINE0);
- PORTE |= _BV(PINE0);
-#endif
-
-
- /* set LED pin as output */
- LED_DDR |= _BV(LED);
-
-
- /* flash onboard LED to signal entering of bootloader */
-#if defined(__AVR_ATmega128__) || defined(__AVR_ATmega1280__)
- // 4x for UART0, 5x for UART1
- flash_led(NUM_LED_FLASHES + bootuart);
-#else
- flash_led(NUM_LED_FLASHES);
-#endif
-
- /* 20050803: by DojoCorp, this is one of the parts provoking the
- system to stop listening, cancelled from the original */
- //putch('\0');
-
- /* forever loop */
- for (;;) {
-
- /* get character from UART */
- ch = getch();
-
- /* A bunch of if...else if... gives smaller code than switch...case ! */
-
- /* Hello is anyone home ? */
- if(ch=='0') {
- nothing_response();
- }
-
-
- /* Request programmer ID */
- /* Not using PROGMEM string due to boot block in m128 being beyond 64kB boundry */
- /* Would need to selectively manipulate RAMPZ, and it's only 9 characters anyway so who cares. */
- else if(ch=='1') {
- if (getch() == ' ') {
- putch(0x14);
- putch('A');
- putch('V');
- putch('R');
- putch(' ');
- putch('I');
- putch('S');
- putch('P');
- putch(0x10);
- } else {
- if (++error_count == MAX_ERROR_COUNT)
- app_start();
- }
- }
-
-
- /* AVR ISP/STK500 board commands DON'T CARE so default nothing_response */
- else if(ch=='@') {
- ch2 = getch();
- if (ch2>0x85) getch();
- nothing_response();
- }
-
-
- /* AVR ISP/STK500 board requests */
- else if(ch=='A') {
- ch2 = getch();
- if(ch2==0x80) byte_response(HW_VER); // Hardware version
- else if(ch2==0x81) byte_response(SW_MAJOR); // Software major version
- else if(ch2==0x82) byte_response(SW_MINOR); // Software minor version
- else if(ch2==0x98) byte_response(0x03); // Unknown but seems to be required by avr
studio 3.56
- else byte_response(0x00); // Covers various unnecessary
responses we don't care about
- }
-
-
- /* Device Parameters DON'T CARE, DEVICE IS FIXED */
- else if(ch=='B') {
- getNch(20);
- nothing_response();
- }
-
-
- /* Parallel programming stuff DON'T CARE */
- else if(ch=='E') {
- getNch(5);
- nothing_response();
- }
-
-
- /* P: Enter programming mode */
- /* R: Erase device, don't care as we will erase one page at a time anyway. */
- else if(ch=='P' || ch=='R') {
- nothing_response();
- }
-
-
- /* Leave programming mode */
- else if(ch=='Q') {
- nothing_response();
-#ifdef WATCHDOG_MODS
- // autoreset via watchdog (sneaky!)
- WDTCSR = _BV(WDE);
- while (1); // 16 ms
-#endif
- }
-
-
- /* Set address, little endian. EEPROM in bytes, FLASH in words */
- /* Perhaps extra address bytes may be added in future to support > 128kB FLASH. */
- /* This might explain why little endian was used here, big endian used everywhere else. */
- else if(ch=='U') {
- address.byte[0] = getch();
- address.byte[1] = getch();
- nothing_response();
- }
-
-
- /* Universal SPI programming command, disabled. Would be used for fuses and lock bits. */
- else if(ch=='V') {
- if (getch() == 0x30) {
- getch();
- ch = getch();
- getch();
- if (ch == 0) {
- byte_response(SIG1);
- } else if (ch == 1) {
- byte_response(SIG2);
- } else {
- byte_response(SIG3);
- }
- } else {
- getNch(3);
- byte_response(0x00);
- }
- }
-
-
- /* Write memory, length is big endian and is in bytes */
- else if(ch=='d') {
- length.byte[1] = getch();
- length.byte[0] = getch();
- flags.eeprom = 0;
- if (getch() == 'E') flags.eeprom = 1;
- for (w=0;w<length.word;w++) {
- buff[w] = getch(); // Store data in buffer, can't keep
up with serial data stream whilst programming pages
- }
- if (getch() == ' ') {
- if (flags.eeprom) { //Write to EEPROM one byte at a time
- address.word <<= 1;
- for(w=0;w<length.word;w++) {
-#if defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__)
- while(EECR & (1<<EEPE));
- EEAR = (uint16_t)(void *)address.word;
- EEDR = buff[w];
- EECR |= (1<<EEMPE);
- EECR |= (1<<EEPE);
-#else
- eeprom_write_byte((void *)address.word,buff[w]);
-#endif
- address.word++;
- }
- }
- else { //Write to FLASH one page at a time
- if (address.byte[1]>127) address_high = 0x01; //Only possible with m128,
m256 will need 3rd address byte. FIXME
- else address_high = 0x00;
-#if defined(__AVR_ATmega128__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega1281__)
- RAMPZ = address_high;
-#endif
- address.word = address.word << 1; //address * 2 -> byte location
- /* if ((length.byte[0] & 0x01) == 0x01) length.word++; //Even up an odd
number of bytes */
- if ((length.byte[0] & 0x01)) length.word++; //Even up an odd number of
bytes
- cli(); //Disable interrupts, just to be sure
-#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega1281__)
- while(bit_is_set(EECR,EEPE)); //Wait for previous EEPROM
writes to complete
-#else
- while(bit_is_set(EECR,EEWE)); //Wait for previous EEPROM
writes to complete
-#endif
- asm volatile(
- "clr r17 \n\t" //page_word_count
- "lds r30,address \n\t" //Address of FLASH location (in bytes)
- "lds r31,address+1 \n\t"
- "ldi r28,lo8(buff) \n\t" //Start of buffer array in RAM
- "ldi r29,hi8(buff) \n\t"
- "lds r24,length \n\t" //Length of data to be written (in
bytes)
- "lds r25,length+1 \n\t"
- "length_loop: \n\t" //Main loop, repeat for number of
words in block
- "cpi r17,0x00 \n\t" //If page_word_count=0 then erase page
- "brne no_page_erase \n\t"
- "wait_spm1: \n\t"
- "lds r16,%0 \n\t" //Wait for previous spm to complete
- "andi r16,1 \n\t"
- "cpi r16,1 \n\t"
- "breq wait_spm1 \n\t"
- "ldi r16,0x03 \n\t" //Erase page pointed to by Z
- "sts %0,r16 \n\t"
- "spm \n\t"
-#ifdef __AVR_ATmega163__
- ".word 0xFFFF \n\t"
- "nop \n\t"
-#endif
- "wait_spm2: \n\t"
- "lds r16,%0 \n\t" //Wait for previous spm to complete
- "andi r16,1 \n\t"
- "cpi r16,1 \n\t"
- "breq wait_spm2 \n\t"
-
- "ldi r16,0x11 \n\t" //Re-enable RWW section
- "sts %0,r16 \n\t"
- "spm \n\t"
-#ifdef __AVR_ATmega163__
- ".word 0xFFFF \n\t"
- "nop \n\t"
-#endif
- "no_page_erase: \n\t"
- "ld r0,Y+ \n\t" //Write 2 bytes into page buffer
- "ld r1,Y+ \n\t"
-
- "wait_spm3: \n\t"
- "lds r16,%0 \n\t" //Wait for previous spm to complete
- "andi r16,1 \n\t"
- "cpi r16,1 \n\t"
- "breq wait_spm3 \n\t"
- "ldi r16,0x01 \n\t" //Load r0,r1 into FLASH page buffer
- "sts %0,r16 \n\t"
- "spm \n\t"
-
- "inc r17 \n\t" //page_word_count++
- "cpi r17,%1 \n\t"
- "brlo same_page \n\t" //Still same page in FLASH
- "write_page: \n\t"
- "clr r17 \n\t" //New page, write current one first
- "wait_spm4: \n\t"
- "lds r16,%0 \n\t" //Wait for previous spm to complete
- "andi r16,1 \n\t"
- "cpi r16,1 \n\t"
- "breq wait_spm4 \n\t"
-#ifdef __AVR_ATmega163__
- "andi r30,0x80 \n\t" // m163 requires Z6:Z1 to be zero
during page write
-#endif
- "ldi r16,0x05 \n\t" //Write page pointed to by Z
- "sts %0,r16 \n\t"
- "spm \n\t"
-#ifdef __AVR_ATmega163__
- ".word 0xFFFF \n\t"
- "nop \n\t"
- "ori r30,0x7E \n\t" // recover Z6:Z1 state after page
write (had to be zero during write)
-#endif
- "wait_spm5: \n\t"
- "lds r16,%0 \n\t" //Wait for previous spm to complete
- "andi r16,1 \n\t"
- "cpi r16,1 \n\t"
- "breq wait_spm5 \n\t"
- "ldi r16,0x11 \n\t" //Re-enable RWW section
- "sts %0,r16 \n\t"
- "spm \n\t"
-#ifdef __AVR_ATmega163__
- ".word 0xFFFF \n\t"
- "nop \n\t"
-#endif
- "same_page: \n\t"
- "adiw r30,2 \n\t" //Next word in FLASH
- "sbiw r24,2 \n\t" //length-2
- "breq final_write \n\t" //Finished
- "rjmp length_loop \n\t"
- "final_write: \n\t"
- "cpi r17,0 \n\t"
- "breq block_done \n\t"
- "adiw r24,2 \n\t" //length+2, fool above check on
length after short page write
- "rjmp write_page \n\t"
- "block_done: \n\t"
- "clr __zero_reg__ \n\t" //restore zero register
-#if defined __AVR_ATmega168__ || __AVR_ATmega328P__ || __AVR_ATmega128__ || __AVR_ATmega1280__ ||
__AVR_ATmega1281__
- : "=m" (SPMCSR) : "M" (PAGE_SIZE) :
"r0","r16","r17","r24","r25","r28","r29","r30","r31"
-#else
- : "=m" (SPMCR) : "M" (PAGE_SIZE) :
"r0","r16","r17","r24","r25","r28","r29","r30","r31"
-#endif
- );
- /* Should really add a wait for RWW section to be enabled, don't actually
need it since we never */
- /* exit the bootloader without a power cycle anyhow */
- }
- putch(0x14);
- putch(0x10);
- } else {
- if (++error_count == MAX_ERROR_COUNT)
- app_start();
- }
- }
-
-
- /* Read memory block mode, length is big endian. */
- else if(ch=='t') {
- length.byte[1] = getch();
- length.byte[0] = getch();
-#if defined(__AVR_ATmega128__) || defined(__AVR_ATmega1280__)
- if (address.word>0x7FFF) flags.rampz = 1; // No go with m256, FIXME
- else flags.rampz = 0;
-#endif
- address.word = address.word << 1; // address * 2 -> byte location
- if (getch() == 'E') flags.eeprom = 1;
- else flags.eeprom = 0;
- if (getch() == ' ') { // Command terminator
- putch(0x14);
- for (w=0;w < length.word;w++) { // Can handle odd and even lengths
okay
- if (flags.eeprom) { // Byte access EEPROM read
-#if defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__)
- while(EECR & (1<<EEPE));
- EEAR = (uint16_t)(void *)address.word;
- EECR |= (1<<EERE);
- putch(EEDR);
-#else
- putch(eeprom_read_byte((void *)address.word));
-#endif
- address.word++;
- }
- else {
-
- if (!flags.rampz) putch(pgm_read_byte_near(address.word));
-#if defined(__AVR_ATmega128__) || defined(__AVR_ATmega1280__)
- else putch(pgm_read_byte_far(address.word + 0x10000));
- // Hmmmm, yuck FIXME when m256 arrvies
-#endif
- address.word++;
- }
- }
- putch(0x10);
- }
- }
-
-
- /* Get device signature bytes */
- else if(ch=='u') {
- if (getch() == ' ') {
- putch(0x14);
- putch(SIG1);
- putch(SIG2);
- putch(SIG3);
- putch(0x10);
- } else {
- if (++error_count == MAX_ERROR_COUNT)
- app_start();
- }
- }
-
-
- /* Read oscillator calibration byte */
- else if(ch=='v') {
- byte_response(0x00);
- }
-
-
-#if defined MONITOR
-
- /* here come the extended monitor commands by Erik Lins */
-
- /* check for three times exclamation mark pressed */
- else if(ch=='!') {
- ch = getch();
- if(ch=='!') {
- ch = getch();
- if(ch=='!') {
- PGM_P welcome = "";
-#if defined(__AVR_ATmega128__) || defined(__AVR_ATmega1280__)
- uint16_t extaddr;
-#endif
- uint8_t addrl, addrh;
-
-#ifdef CRUMB128
- welcome = "ATmegaBOOT / Crumb128 - (C) J.P.Kyle, E.Lins - 050815\n\r";
-#elif defined PROBOMEGA128
- welcome = "ATmegaBOOT / PROBOmega128 - (C) J.P.Kyle, E.Lins - 050815\n\r";
-#elif defined SAVVY128
- welcome = "ATmegaBOOT / Savvy128 - (C) J.P.Kyle, E.Lins - 050815\n\r";
-#elif defined __AVR_ATmega1280__
- welcome = "ATmegaBOOT / Arduino Mega - (C) Arduino LLC - 090930\n\r";
-#endif
-
- /* turn on LED */
- LED_DDR |= _BV(LED);
- LED_PORT &= ~_BV(LED);
-
- /* print a welcome message and command overview */
- for(i=0; welcome[i] != '\0'; ++i) {
- putch(welcome[i]);
- }
-
- /* test for valid commands */
- for(;;) {
- putch('\n');
- putch('\r');
- putch(':');
- putch(' ');
-
- ch = getch();
- putch(ch);
-
- /* toggle LED */
- if(ch == 't') {
- if(bit_is_set(LED_PIN,LED)) {
- LED_PORT &= ~_BV(LED);
- putch('1');
- } else {
- LED_PORT |= _BV(LED);
- putch('0');
- }
- }
-
- /* read byte from address */
- else if(ch == 'r') {
- ch = getch(); putch(ch);
- addrh = gethex();
- addrl = gethex();
- putch('=');
- ch = *(uint8_t *)((addrh << 8) + addrl);
- puthex(ch);
- }
-
- /* write a byte to address */
- else if(ch == 'w') {
- ch = getch(); putch(ch);
- addrh = gethex();
- addrl = gethex();
- ch = getch(); putch(ch);
- ch = gethex();
- *(uint8_t *)((addrh << 8) + addrl) = ch;
- }
-
- /* read from uart and echo back */
- else if(ch == 'u') {
- for(;;) {
- putch(getch());
- }
- }
-#if defined(__AVR_ATmega128__) || defined(__AVR_ATmega1280__)
- /* external bus loop */
- else if(ch == 'b') {
- putch('b');
- putch('u');
- putch('s');
- MCUCR = 0x80;
- XMCRA = 0;
- XMCRB = 0;
- extaddr = 0x1100;
- for(;;) {
- ch = *(volatile uint8_t *)extaddr;
- if(++extaddr == 0) {
- extaddr = 0x1100;
- }
- }
- }
-#endif
-
- else if(ch == 'j') {
- app_start();
- }
-
- } /* end of monitor functions */
-
- }
- }
- }
- /* end of monitor */
-#endif
- else if (++error_count == MAX_ERROR_COUNT) {
- app_start();
- }
- } /* end of forever loop */
-
-}
-
-
-char gethexnib(void) {
- char a;
- a = getch(); putch(a);
- if(a >= 'a') {
- return (a - 'a' + 0x0a);
- } else if(a >= '0') {
- return(a - '0');
- }
- return a;
-}
-
-
-char gethex(void) {
- return (gethexnib() << 4) + gethexnib();
-}
-
-
-void puthex(char ch) {
- char ah;
-
- ah = ch >> 4;
- if(ah >= 0x0a) {
- ah = ah - 0x0a + 'a';
- } else {
- ah += '0';
- }
-
- ch &= 0x0f;
- if(ch >= 0x0a) {
- ch = ch - 0x0a + 'a';
- } else {
- ch += '0';
- }
-
- putch(ah);
- putch(ch);
-}
-
-
-void putch(char ch)
-{
-#if defined(__AVR_ATmega128__) || defined(__AVR_ATmega1280__)
- if(bootuart == 1) {
- while (!(UCSR0A & _BV(UDRE0)));
- UDR0 = ch;
- }
- else if (bootuart == 2) {
- while (!(UCSR1A & _BV(UDRE1)));
- UDR1 = ch;
- }
-#elif defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__)
- while (!(UCSR0A & _BV(UDRE0)));
- UDR0 = ch;
-#else
- /* m8,16,32,169,8515,8535,163 */
- while (!(UCSRA & _BV(UDRE)));
- UDR = ch;
-#endif
-}
-
-
-char getch(void)
-{
-#if defined(__AVR_ATmega128__) || defined(__AVR_ATmega1280__)
- uint32_t count = 0;
- if(bootuart == 1) {
- while(!(UCSR0A & _BV(RXC0))) {
- /* 20060803 DojoCorp:: Addon coming from the previous Bootloader*/
- /* HACKME:: here is a good place to count times*/
+/**********************************************************/
+/* Serial Bootloader for Atmel megaAVR Controllers */
+/* */
+/* tested with ATmega8, ATmega128 and ATmega168 */
+/* should work with other mega's, see code for details */
+/* */
+/* ATmegaBOOT.c */
+/* */
+/* */
+/* 20090308: integrated Mega changes into main bootloader */
+/* source by D. Mellis */
+/* 20080930: hacked for Arduino Mega (with the 1280 */
+/* processor, backwards compatible) */
+/* by D. Cuartielles */
+/* 20070626: hacked for Arduino Diecimila (which auto- */
+/* resets when a USB connection is made to it) */
+/* by D. Mellis */
+/* 20060802: hacked for Arduino by D. Cuartielles */
+/* based on a previous hack by D. Mellis */
+/* and D. Cuartielles */
+/* */
+/* Monitor and debug functions were added to the original */
+/* code by Dr. Erik Lins, chip45.com. (See below) */
+/* */
+/* Thanks to Karl Pitrich for fixing a bootloader pin */
+/* problem and more informative LED blinking! */
+/* */
+/* For the latest version see: */
+/* http://www.chip45.com/ */
+/* */
+/* ------------------------------------------------------ */
+/* */
+/* based on stk500boot.c */
+/* Copyright (c) 2003, Jason P. Kyle */
+/* All rights reserved. */
+/* see avr1.org for original file and information */
+/* */
+/* This program 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. */
+/* */
+/* This program 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., */
+/* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+/* */
+/* Licence can be viewed at */
+/* http://www.fsf.org/licenses/gpl.txt */
+/* */
+/* Target = Atmel AVR m128,m64,m32,m16,m8,m162,m163,m169, */
+/* m8515,m8535. ATmega161 has a very small boot block so */
+/* isn't supported. */
+/* */
+/* Tested with m168 */
+/**********************************************************/
+
+/* $Id$ */
+
+
+/* some includes */
+#include <inttypes.h>
+#include <avr/io.h>
+#include <avr/pgmspace.h>
+#include <avr/interrupt.h>
+#include <avr/wdt.h>
+#include <util/delay.h>
+
+/* the current avr-libc eeprom functions do not support the ATmega168 */
+/* own eeprom write/read functions are used instead */
+#if !defined(__AVR_ATmega168__) || !defined(__AVR_ATmega328P__)
+#include <avr/eeprom.h>
+#endif
+
+/* Use the F_CPU defined in Makefile */
+
+/* 20060803: hacked by DojoCorp */
+/* 20070626: hacked by David A. Mellis to decrease waiting time for auto-reset */
+/* set the waiting time for the bootloader */
+/* get this from the Makefile instead */
+/* #define MAX_TIME_COUNT (F_CPU>>4) */
+
+/* 20070707: hacked by David A. Mellis - after this many errors give up and launch application */
+#define MAX_ERROR_COUNT 5
+
+/* set the UART baud rate */
+/* 20060803: hacked by DojoCorp */
+//#define BAUD_RATE 115200
+#ifndef BAUD_RATE
+#define BAUD_RATE 19200
+#endif
+
+
+/* SW_MAJOR and MINOR needs to be updated from time to time to avoid warning message from AVR Studio */
+/* never allow AVR Studio to do an update !!!! */
+#define HW_VER 0x02
+#define SW_MAJOR 0x01
+#define SW_MINOR 0x10
+
+
+/* Adjust to suit whatever pin your hardware uses to enter the bootloader */
+/* ATmega128 has two UARTS so two pins are used to enter bootloader and select UART */
+/* ATmega1280 has four UARTS, but for Arduino Mega, we will only use RXD0 to get code */
+/* BL0... means UART0, BL1... means UART1 */
+#ifdef __AVR_ATmega128__
+#define BL_DDR DDRF
+#define BL_PORT PORTF
+#define BL_PIN PINF
+#define BL0 PINF7
+#define BL1 PINF6
+#elif defined __AVR_ATmega1280__
+/* we just don't do anything for the MEGA and enter bootloader on reset anyway*/
+#else
+/* other ATmegas have only one UART, so only one pin is defined to enter bootloader */
+#define BL_DDR DDRD
+#define BL_PORT PORTD
+#define BL_PIN PIND
+#define BL PIND6
+#endif
+
+
+/* onboard LED is used to indicate, that the bootloader was entered (3x flashing) */
+/* if monitor functions are included, LED goes on after monitor was entered */
+#if defined __AVR_ATmega128__ || defined __AVR_ATmega1280__
+/* Onboard LED is connected to pin PB7 (e.g. Crumb128, PROBOmega128, Savvy128, Arduino Mega) */
+#define LED_DDR DDRB
+#define LED_PORT PORTB
+#define LED_PIN PINB
+#define LED PINB7
+#else
+/* Onboard LED is connected to pin PB5 in Arduino NG, Diecimila, and Duomilanuove */
+/* other boards like e.g. Crumb8, Crumb168 are using PB2 */
+#define LED_DDR DDRB
+#define LED_PORT PORTB
+#define LED_PIN PINB
+#define LED PINB5
+#endif
+
+
+/* monitor functions will only be compiled when using ATmega128, due to bootblock size constraints */
+#if defined(__AVR_ATmega128__) || defined(__AVR_ATmega1280__)
+#define MONITOR 1
+#endif
+
+
+/* define various device id's */
+/* manufacturer byte is always the same */
+#define SIG1 0x1E // Yep, Atmel is the only manufacturer of AVR micros. Single source :(
+
+#if defined __AVR_ATmega1280__
+#define SIG2 0x97
+#define SIG3 0x03
+#define PAGE_SIZE 0x80U //128 words
+
+#elif defined __AVR_ATmega1281__
+#define SIG2 0x97
+#define SIG3 0x04
+#define PAGE_SIZE 0x80U //128 words
+
+#elif defined __AVR_ATmega128__
+#define SIG2 0x97
+#define SIG3 0x02
+#define PAGE_SIZE 0x80U //128 words
+
+#elif defined __AVR_ATmega64__
+#define SIG2 0x96
+#define SIG3 0x02
+#define PAGE_SIZE 0x80U //128 words
+
+#elif defined __AVR_ATmega32__
+#define SIG2 0x95
+#define SIG3 0x02
+#define PAGE_SIZE 0x40U //64 words
+
+#elif defined __AVR_ATmega16__
+#define SIG2 0x94
+#define SIG3 0x03
+#define PAGE_SIZE 0x40U //64 words
+
+#elif defined __AVR_ATmega8__
+#define SIG2 0x93
+#define SIG3 0x07
+#define PAGE_SIZE 0x20U //32 words
+
+#elif defined __AVR_ATmega88__
+#define SIG2 0x93
+#define SIG3 0x0a
+#define PAGE_SIZE 0x20U //32 words
+
+#elif defined __AVR_ATmega168__
+#define SIG2 0x94
+#define SIG3 0x06
+#define PAGE_SIZE 0x40U //64 words
+
+#elif defined __AVR_ATmega328P__
+#define SIG2 0x95
+#define SIG3 0x0F
+#define PAGE_SIZE 0x40U //64 words
+
+#elif defined __AVR_ATmega162__
+#define SIG2 0x94
+#define SIG3 0x04
+#define PAGE_SIZE 0x40U //64 words
+
+#elif defined __AVR_ATmega163__
+#define SIG2 0x94
+#define SIG3 0x02
+#define PAGE_SIZE 0x40U //64 words
+
+#elif defined __AVR_ATmega169__
+#define SIG2 0x94
+#define SIG3 0x05
+#define PAGE_SIZE 0x40U //64 words
+
+#elif defined __AVR_ATmega8515__
+#define SIG2 0x93
+#define SIG3 0x06
+#define PAGE_SIZE 0x20U //32 words
+
+#elif defined __AVR_ATmega8535__
+#define SIG2 0x93
+#define SIG3 0x08
+#define PAGE_SIZE 0x20U //32 words
+#endif
+
+
+/* function prototypes */
+void putch(char);
+char getch(void);
+void getNch(uint8_t);
+void byte_response(uint8_t);
+void nothing_response(void);
+char gethex(void);
+void puthex(char);
+void flash_led(uint8_t);
+
+/* some variables */
+union address_union {
+ uint16_t word;
+ uint8_t byte[2];
+} address;
+
+union length_union {
+ uint16_t word;
+ uint8_t byte[2];
+} length;
+
+struct flags_struct {
+ unsigned eeprom : 1;
+ unsigned rampz : 1;
+} flags;
+
+uint8_t buff[256];
+uint8_t address_high;
+
+uint8_t pagesz=0x80;
+
+uint8_t i;
+uint8_t bootuart = 0;
+
+uint8_t error_count = 0;
+
+void (*app_start)(void) = 0x0000;
+
+
+/* main program starts here */
+int main(void)
+{
+ uint8_t ch,ch2;
+ uint16_t w;
+
+#ifdef WATCHDOG_MODS
+ ch = MCUSR;
+ MCUSR = 0;
+
+ WDTCSR |= _BV(WDCE) | _BV(WDE);
+ WDTCSR = 0;
+
+ // Check if the WDT was used to reset, in which case we dont bootload and skip straight to the code.
woot.
+ if (! (ch & _BV(EXTRF))) // if its a not an external reset...
+ app_start(); // skip bootloader
+#else
+ asm volatile("nop\n\t");
+#endif
+
+ /* set pin direction for bootloader pin and enable pullup */
+ /* for ATmega128, two pins need to be initialized */
+#ifdef __AVR_ATmega128__
+ BL_DDR &= ~_BV(BL0);
+ BL_DDR &= ~_BV(BL1);
+ BL_PORT |= _BV(BL0);
+ BL_PORT |= _BV(BL1);
+#else
+ /* We run the bootloader regardless of the state of this pin. Thus, don't
+ put it in a different state than the other pins. --DAM, 070709
+ This also applies to Arduino Mega -- DC, 080930
+ BL_DDR &= ~_BV(BL);
+ BL_PORT |= _BV(BL);
+ */
+#endif
+
+
+#ifdef __AVR_ATmega128__
+ /* check which UART should be used for booting */
+ if(bit_is_clear(BL_PIN, BL0)) {
+ bootuart = 1;
+ }
+ else if(bit_is_clear(BL_PIN, BL1)) {
+ bootuart = 2;
+ }
+#endif
+
+#if defined __AVR_ATmega1280__
+ /* the mega1280 chip has four serial ports ... we could eventually use any of them, or not? */
+ /* however, we don't wanna confuse people, to avoid making a mess, we will stick to RXD0, TXD0 */
+ bootuart = 1;
+#endif
+
+ /* check if flash is programmed already, if not start bootloader anyway */
+ if(pgm_read_byte_near(0x0000) != 0xFF) {
+
+#ifdef __AVR_ATmega128__
+ /* no UART was selected, start application */
+ if(!bootuart) {
+ app_start();
+ }
+#else
+ /* check if bootloader pin is set low */
+ /* we don't start this part neither for the m8, nor m168 */
+ //if(bit_is_set(BL_PIN, BL)) {
+ // app_start();
+ // }
+#endif
+ }
+
+#ifdef __AVR_ATmega128__
+ /* no bootuart was selected, default to uart 0 */
+ if(!bootuart) {
+ bootuart = 1;
+ }
+#endif
+
+
+ /* initialize UART(s) depending on CPU defined */
+#if defined(__AVR_ATmega128__) || defined(__AVR_ATmega1280__)
+ if(bootuart == 1) {
+ UBRR0L = (uint8_t)(F_CPU/(BAUD_RATE*16L)-1);
+ UBRR0H = (F_CPU/(BAUD_RATE*16L)-1) >> 8;
+ UCSR0A = 0x00;
+ UCSR0C = 0x06;
+ UCSR0B = _BV(TXEN0)|_BV(RXEN0);
+ }
+ if(bootuart == 2) {
+ UBRR1L = (uint8_t)(F_CPU/(BAUD_RATE*16L)-1);
+ UBRR1H = (F_CPU/(BAUD_RATE*16L)-1) >> 8;
+ UCSR1A = 0x00;
+ UCSR1C = 0x06;
+ UCSR1B = _BV(TXEN1)|_BV(RXEN1);
+ }
+#elif defined __AVR_ATmega163__
+ UBRR = (uint8_t)(F_CPU/(BAUD_RATE*16L)-1);
+ UBRRHI = (F_CPU/(BAUD_RATE*16L)-1) >> 8;
+ UCSRA = 0x00;
+ UCSRB = _BV(TXEN)|_BV(RXEN);
+#elif defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__)
+
+#ifdef DOUBLE_SPEED
+ UCSR0A = (1<<U2X0); //Double speed mode USART0
+ UBRR0L = (uint8_t)(F_CPU/(BAUD_RATE*8L)-1);
+ UBRR0H = (F_CPU/(BAUD_RATE*8L)-1) >> 8;
+#else
+ UBRR0L = (uint8_t)(F_CPU/(BAUD_RATE*16L)-1);
+ UBRR0H = (F_CPU/(BAUD_RATE*16L)-1) >> 8;
+#endif
+
+ UCSR0B = (1<<RXEN0) | (1<<TXEN0);
+ UCSR0C = (1<<UCSZ00) | (1<<UCSZ01);
+
+ /* Enable internal pull-up resistor on pin D0 (RX), in order
+ to supress line noise that prevents the bootloader from
+ timing out (DAM: 20070509) */
+ DDRD &= ~_BV(PIND0);
+ PORTD |= _BV(PIND0);
+#elif defined __AVR_ATmega8__
+ /* m8 */
+ UBRRH = (((F_CPU/BAUD_RATE)/16)-1)>>8; // set baud rate
+ UBRRL = (((F_CPU/BAUD_RATE)/16)-1);
+ UCSRB = (1<<RXEN)|(1<<TXEN); // enable Rx & Tx
+ UCSRC = (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0); // config USART; 8N1
+#else
+ /* m16,m32,m169,m8515,m8535 */
+ UBRRL = (uint8_t)(F_CPU/(BAUD_RATE*16L)-1);
+ UBRRH = (F_CPU/(BAUD_RATE*16L)-1) >> 8;
+ UCSRA = 0x00;
+ UCSRC = 0x06;
+ UCSRB = _BV(TXEN)|_BV(RXEN);
+#endif
+
+#if defined __AVR_ATmega1280__
+ /* Enable internal pull-up resistor on pin D0 (RX), in order
+ to supress line noise that prevents the bootloader from
+ timing out (DAM: 20070509) */
+ /* feature added to the Arduino Mega --DC: 080930 */
+ DDRE &= ~_BV(PINE0);
+ PORTE |= _BV(PINE0);
+#endif
+
+
+ /* set LED pin as output */
+ LED_DDR |= _BV(LED);
+
+
+ /* flash onboard LED to signal entering of bootloader */
+#if defined(__AVR_ATmega128__) || defined(__AVR_ATmega1280__)
+ // 4x for UART0, 5x for UART1
+ flash_led(NUM_LED_FLASHES + bootuart);
+#else
+ flash_led(NUM_LED_FLASHES);
+#endif
+
+ /* 20050803: by DojoCorp, this is one of the parts provoking the
+ system to stop listening, cancelled from the original */
+ //putch('\0');
+
+ /* forever loop */
+ for (;;) {
+
+ /* get character from UART */
+ ch = getch();
+
+ /* A bunch of if...else if... gives smaller code than switch...case ! */
+
+ /* Hello is anyone home ? */
+ if(ch=='0') {
+ nothing_response();
+ }
+
+
+ /* Request programmer ID */
+ /* Not using PROGMEM string due to boot block in m128 being beyond 64kB boundry */
+ /* Would need to selectively manipulate RAMPZ, and it's only 9 characters anyway so who cares. */
+ else if(ch=='1') {
+ if (getch() == ' ') {
+ putch(0x14);
+ putch('A');
+ putch('V');
+ putch('R');
+ putch(' ');
+ putch('I');
+ putch('S');
+ putch('P');
+ putch(0x10);
+ } else {
+ if (++error_count == MAX_ERROR_COUNT)
+ app_start();
+ }
+ }
+
+
+ /* AVR ISP/STK500 board commands DON'T CARE so default nothing_response */
+ else if(ch=='@') {
+ ch2 = getch();
+ if (ch2>0x85) getch();
+ nothing_response();
+ }
+
+
+ /* AVR ISP/STK500 board requests */
+ else if(ch=='A') {
+ ch2 = getch();
+ if(ch2==0x80) byte_response(HW_VER); // Hardware version
+ else if(ch2==0x81) byte_response(SW_MAJOR); // Software major version
+ else if(ch2==0x82) byte_response(SW_MINOR); // Software minor version
+ else if(ch2==0x98) byte_response(0x03); // Unknown but seems to be required by avr
studio 3.56
+ else byte_response(0x00); // Covers various unnecessary
responses we don't care about
+ }
+
+
+ /* Device Parameters DON'T CARE, DEVICE IS FIXED */
+ else if(ch=='B') {
+ getNch(20);
+ nothing_response();
+ }
+
+
+ /* Parallel programming stuff DON'T CARE */
+ else if(ch=='E') {
+ getNch(5);
+ nothing_response();
+ }
+
+
+ /* P: Enter programming mode */
+ /* R: Erase device, don't care as we will erase one page at a time anyway. */
+ else if(ch=='P' || ch=='R') {
+ nothing_response();
+ }
+
+
+ /* Leave programming mode */
+ else if(ch=='Q') {
+ nothing_response();
+#ifdef WATCHDOG_MODS
+ // autoreset via watchdog (sneaky!)
+ WDTCSR = _BV(WDE);
+ while (1); // 16 ms
+#endif
+ }
+
+
+ /* Set address, little endian. EEPROM in bytes, FLASH in words */
+ /* Perhaps extra address bytes may be added in future to support > 128kB FLASH. */
+ /* This might explain why little endian was used here, big endian used everywhere else. */
+ else if(ch=='U') {
+ address.byte[0] = getch();
+ address.byte[1] = getch();
+ nothing_response();
+ }
+
+
+ /* Universal SPI programming command, disabled. Would be used for fuses and lock bits. */
+ else if(ch=='V') {
+ if (getch() == 0x30) {
+ getch();
+ ch = getch();
+ getch();
+ if (ch == 0) {
+ byte_response(SIG1);
+ } else if (ch == 1) {
+ byte_response(SIG2);
+ } else {
+ byte_response(SIG3);
+ }
+ } else {
+ getNch(3);
+ byte_response(0x00);
+ }
+ }
+
+
+ /* Write memory, length is big endian and is in bytes */
+ else if(ch=='d') {
+ length.byte[1] = getch();
+ length.byte[0] = getch();
+ flags.eeprom = 0;
+ if (getch() == 'E') flags.eeprom = 1;
+ for (w=0;w<length.word;w++) {
+ buff[w] = getch(); // Store data in buffer, can't keep
up with serial data stream whilst programming pages
+ }
+ if (getch() == ' ') {
+ if (flags.eeprom) { //Write to EEPROM one byte at a time
+ address.word <<= 1;
+ for(w=0;w<length.word;w++) {
+#if defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__)
+ while(EECR & (1<<EEPE));
+ EEAR = (uint16_t)(void *)address.word;
+ EEDR = buff[w];
+ EECR |= (1<<EEMPE);
+ EECR |= (1<<EEPE);
+#else
+ eeprom_write_byte((void *)address.word,buff[w]);
+#endif
+ address.word++;
+ }
+ }
+ else { //Write to FLASH one page at a time
+ if (address.byte[1]>127) address_high = 0x01; //Only possible with m128,
m256 will need 3rd address byte. FIXME
+ else address_high = 0x00;
+#if defined(__AVR_ATmega128__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega1281__)
+ RAMPZ = address_high;
+#endif
+ address.word = address.word << 1; //address * 2 -> byte location
+ /* if ((length.byte[0] & 0x01) == 0x01) length.word++; //Even up an odd
number of bytes */
+ if ((length.byte[0] & 0x01)) length.word++; //Even up an odd number of
bytes
+ cli(); //Disable interrupts, just to be sure
+#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega1281__)
+ while(bit_is_set(EECR,EEPE)); //Wait for previous EEPROM
writes to complete
+#else
+ while(bit_is_set(EECR,EEWE)); //Wait for previous EEPROM
writes to complete
+#endif
+ asm volatile(
+ "clr r17 \n\t" //page_word_count
+ "lds r30,address \n\t" //Address of FLASH location (in bytes)
+ "lds r31,address+1 \n\t"
+ "ldi r28,lo8(buff) \n\t" //Start of buffer array in RAM
+ "ldi r29,hi8(buff) \n\t"
+ "lds r24,length \n\t" //Length of data to be written (in
bytes)
+ "lds r25,length+1 \n\t"
+ "length_loop: \n\t" //Main loop, repeat for number of
words in block
+ "cpi r17,0x00 \n\t" //If page_word_count=0 then erase page
+ "brne no_page_erase \n\t"
+ "wait_spm1: \n\t"
+ "lds r16,%0 \n\t" //Wait for previous spm to complete
+ "andi r16,1 \n\t"
+ "cpi r16,1 \n\t"
+ "breq wait_spm1 \n\t"
+ "ldi r16,0x03 \n\t" //Erase page pointed to by Z
+ "sts %0,r16 \n\t"
+ "spm \n\t"
+#ifdef __AVR_ATmega163__
+ ".word 0xFFFF \n\t"
+ "nop \n\t"
+#endif
+ "wait_spm2: \n\t"
+ "lds r16,%0 \n\t" //Wait for previous spm to complete
+ "andi r16,1 \n\t"
+ "cpi r16,1 \n\t"
+ "breq wait_spm2 \n\t"
+
+ "ldi r16,0x11 \n\t" //Re-enable RWW section
+ "sts %0,r16 \n\t"
+ "spm \n\t"
+#ifdef __AVR_ATmega163__
+ ".word 0xFFFF \n\t"
+ "nop \n\t"
+#endif
+ "no_page_erase: \n\t"
+ "ld r0,Y+ \n\t" //Write 2 bytes into page buffer
+ "ld r1,Y+ \n\t"
+
+ "wait_spm3: \n\t"
+ "lds r16,%0 \n\t" //Wait for previous spm to complete
+ "andi r16,1 \n\t"
+ "cpi r16,1 \n\t"
+ "breq wait_spm3 \n\t"
+ "ldi r16,0x01 \n\t" //Load r0,r1 into FLASH page buffer
+ "sts %0,r16 \n\t"
+ "spm \n\t"
+
+ "inc r17 \n\t" //page_word_count++
+ "cpi r17,%1 \n\t"
+ "brlo same_page \n\t" //Still same page in FLASH
+ "write_page: \n\t"
+ "clr r17 \n\t" //New page, write current one first
+ "wait_spm4: \n\t"
+ "lds r16,%0 \n\t" //Wait for previous spm to complete
+ "andi r16,1 \n\t"
+ "cpi r16,1 \n\t"
+ "breq wait_spm4 \n\t"
+#ifdef __AVR_ATmega163__
+ "andi r30,0x80 \n\t" // m163 requires Z6:Z1 to be zero
during page write
+#endif
+ "ldi r16,0x05 \n\t" //Write page pointed to by Z
+ "sts %0,r16 \n\t"
+ "spm \n\t"
+#ifdef __AVR_ATmega163__
+ ".word 0xFFFF \n\t"
+ "nop \n\t"
+ "ori r30,0x7E \n\t" // recover Z6:Z1 state after page
write (had to be zero during write)
+#endif
+ "wait_spm5: \n\t"
+ "lds r16,%0 \n\t" //Wait for previous spm to complete
+ "andi r16,1 \n\t"
+ "cpi r16,1 \n\t"
+ "breq wait_spm5 \n\t"
+ "ldi r16,0x11 \n\t" //Re-enable RWW section
+ "sts %0,r16 \n\t"
+ "spm \n\t"
+#ifdef __AVR_ATmega163__
+ ".word 0xFFFF \n\t"
+ "nop \n\t"
+#endif
+ "same_page: \n\t"
+ "adiw r30,2 \n\t" //Next word in FLASH
+ "sbiw r24,2 \n\t" //length-2
+ "breq final_write \n\t" //Finished
+ "rjmp length_loop \n\t"
+ "final_write: \n\t"
+ "cpi r17,0 \n\t"
+ "breq block_done \n\t"
+ "adiw r24,2 \n\t" //length+2, fool above check on
length after short page write
+ "rjmp write_page \n\t"
+ "block_done: \n\t"
+ "clr __zero_reg__ \n\t" //restore zero register
+#if defined __AVR_ATmega168__ || __AVR_ATmega328P__ || __AVR_ATmega128__ || __AVR_ATmega1280__ ||
__AVR_ATmega1281__
+ : "=m" (SPMCSR) : "M" (PAGE_SIZE) :
"r0","r16","r17","r24","r25","r28","r29","r30","r31"
+#else
+ : "=m" (SPMCR) : "M" (PAGE_SIZE) :
"r0","r16","r17","r24","r25","r28","r29","r30","r31"
+#endif
+ );
+ /* Should really add a wait for RWW section to be enabled, don't actually
need it since we never */
+ /* exit the bootloader without a power cycle anyhow */
+ }
+ putch(0x14);
+ putch(0x10);
+ } else {
+ if (++error_count == MAX_ERROR_COUNT)
+ app_start();
+ }
+ }
+
+
+ /* Read memory block mode, length is big endian. */
+ else if(ch=='t') {
+ length.byte[1] = getch();
+ length.byte[0] = getch();
+#if defined(__AVR_ATmega128__) || defined(__AVR_ATmega1280__)
+ if (address.word>0x7FFF) flags.rampz = 1; // No go with m256, FIXME
+ else flags.rampz = 0;
+#endif
+ address.word = address.word << 1; // address * 2 -> byte location
+ if (getch() == 'E') flags.eeprom = 1;
+ else flags.eeprom = 0;
+ if (getch() == ' ') { // Command terminator
+ putch(0x14);
+ for (w=0;w < length.word;w++) { // Can handle odd and even lengths
okay
+ if (flags.eeprom) { // Byte access EEPROM read
+#if defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__)
+ while(EECR & (1<<EEPE));
+ EEAR = (uint16_t)(void *)address.word;
+ EECR |= (1<<EERE);
+ putch(EEDR);
+#else
+ putch(eeprom_read_byte((void *)address.word));
+#endif
+ address.word++;
+ }
+ else {
+
+ if (!flags.rampz) putch(pgm_read_byte_near(address.word));
+#if defined(__AVR_ATmega128__) || defined(__AVR_ATmega1280__)
+ else putch(pgm_read_byte_far(address.word + 0x10000));
+ // Hmmmm, yuck FIXME when m256 arrvies
+#endif
+ address.word++;
+ }
+ }
+ putch(0x10);
+ }
+ }
+
+
+ /* Get device signature bytes */
+ else if(ch=='u') {
+ if (getch() == ' ') {
+ putch(0x14);
+ putch(SIG1);
+ putch(SIG2);
+ putch(SIG3);
+ putch(0x10);
+ } else {
+ if (++error_count == MAX_ERROR_COUNT)
+ app_start();
+ }
+ }
+
+
+ /* Read oscillator calibration byte */
+ else if(ch=='v') {
+ byte_response(0x00);
+ }
+
+
+#if defined MONITOR
+
+ /* here come the extended monitor commands by Erik Lins */
+
+ /* check for three times exclamation mark pressed */
+ else if(ch=='!') {
+ ch = getch();
+ if(ch=='!') {
+ ch = getch();
+ if(ch=='!') {
+ PGM_P welcome = "";
+#if defined(__AVR_ATmega128__) || defined(__AVR_ATmega1280__)
+ uint16_t extaddr;
+#endif
+ uint8_t addrl, addrh;
+
+#ifdef CRUMB128
+ welcome = "ATmegaBOOT / Crumb128 - (C) J.P.Kyle, E.Lins - 050815\n\r";
+#elif defined PROBOMEGA128
+ welcome = "ATmegaBOOT / PROBOmega128 - (C) J.P.Kyle, E.Lins - 050815\n\r";
+#elif defined SAVVY128
+ welcome = "ATmegaBOOT / Savvy128 - (C) J.P.Kyle, E.Lins - 050815\n\r";
+#elif defined __AVR_ATmega1280__
+ welcome = "ATmegaBOOT / Arduino Mega - (C) Arduino LLC - 090930\n\r";
+#endif
+
+ /* turn on LED */
+ LED_DDR |= _BV(LED);
+ LED_PORT &= ~_BV(LED);
+
+ /* print a welcome message and command overview */
+ for(i=0; welcome[i] != '\0'; ++i) {
+ putch(welcome[i]);
+ }
+
+ /* test for valid commands */
+ for(;;) {
+ putch('\n');
+ putch('\r');
+ putch(':');
+ putch(' ');
+
+ ch = getch();
+ putch(ch);
+
+ /* toggle LED */
+ if(ch == 't') {
+ if(bit_is_set(LED_PIN,LED)) {
+ LED_PORT &= ~_BV(LED);
+ putch('1');
+ } else {
+ LED_PORT |= _BV(LED);
+ putch('0');
+ }
+ }
+
+ /* read byte from address */
+ else if(ch == 'r') {
+ ch = getch(); putch(ch);
+ addrh = gethex();
+ addrl = gethex();
+ putch('=');
+ ch = *(uint8_t *)((addrh << 8) + addrl);
+ puthex(ch);
+ }
+
+ /* write a byte to address */
+ else if(ch == 'w') {
+ ch = getch(); putch(ch);
+ addrh = gethex();
+ addrl = gethex();
+ ch = getch(); putch(ch);
+ ch = gethex();
+ *(uint8_t *)((addrh << 8) + addrl) = ch;
+ }
+
+ /* read from uart and echo back */
+ else if(ch == 'u') {
+ for(;;) {
+ putch(getch());
+ }
+ }
+#if defined(__AVR_ATmega128__) || defined(__AVR_ATmega1280__)
+ /* external bus loop */
+ else if(ch == 'b') {
+ putch('b');
+ putch('u');
+ putch('s');
+ MCUCR = 0x80;
+ XMCRA = 0;
+ XMCRB = 0;
+ extaddr = 0x1100;
+ for(;;) {
+ ch = *(volatile uint8_t *)extaddr;
+ if(++extaddr == 0) {
+ extaddr = 0x1100;
+ }
+ }
+ }
+#endif
+
+ else if(ch == 'j') {
+ app_start();
+ }
+
+ } /* end of monitor functions */
+
+ }
+ }
+ }
+ /* end of monitor */
+#endif
+ else if (++error_count == MAX_ERROR_COUNT) {
+ app_start();
+ }
+ } /* end of forever loop */
+
+}
+
+
+char gethexnib(void) {
+ char a;
+ a = getch(); putch(a);
+ if(a >= 'a') {
+ return (a - 'a' + 0x0a);
+ } else if(a >= '0') {
+ return(a - '0');
+ }
+ return a;
+}
+
+
+char gethex(void) {
+ return (gethexnib() << 4) + gethexnib();
+}
+
+
+void puthex(char ch) {
+ char ah;
+
+ ah = ch >> 4;
+ if(ah >= 0x0a) {
+ ah = ah - 0x0a + 'a';
+ } else {
+ ah += '0';
+ }
+
+ ch &= 0x0f;
+ if(ch >= 0x0a) {
+ ch = ch - 0x0a + 'a';
+ } else {
+ ch += '0';
+ }
+
+ putch(ah);
+ putch(ch);
+}
+
+
+void putch(char ch)
+{
+#if defined(__AVR_ATmega128__) || defined(__AVR_ATmega1280__)
+ if(bootuart == 1) {
+ while (!(UCSR0A & _BV(UDRE0)));
+ UDR0 = ch;
+ }
+ else if (bootuart == 2) {
+ while (!(UCSR1A & _BV(UDRE1)));
+ UDR1 = ch;
+ }
+#elif defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__)
+ while (!(UCSR0A & _BV(UDRE0)));
+ UDR0 = ch;
+#else
+ /* m8,16,32,169,8515,8535,163 */
+ while (!(UCSRA & _BV(UDRE)));
+ UDR = ch;
+#endif
+}
+
+
+char getch(void)
+{
+#if defined(__AVR_ATmega128__) || defined(__AVR_ATmega1280__)
+ uint32_t count = 0;
+ if(bootuart == 1) {
+ while(!(UCSR0A & _BV(RXC0))) {
+ /* 20060803 DojoCorp:: Addon coming from the previous Bootloader*/
+ /* HACKME:: here is a good place to count times*/
count++;
if (count > MAX_TIME_COUNT)
app_start();
@@ -957,98 +957,98 @@ char getch(void)
else if(bootuart == 2) {
while(!(UCSR1A & _BV(RXC1))) {
/* 20060803 DojoCorp:: Addon coming from the previous Bootloader*/
- /* HACKME:: here is a good place to count times*/
- count++;
- if (count > MAX_TIME_COUNT)
- app_start();
- }
-
- return UDR1;
- }
- return 0;
-#elif defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__)
- uint32_t count = 0;
- while(!(UCSR0A & _BV(RXC0))){
- /* 20060803 DojoCorp:: Addon coming from the previous Bootloader*/
- /* HACKME:: here is a good place to count times*/
- count++;
- if (count > MAX_TIME_COUNT)
- app_start();
- }
- return UDR0;
-#else
- /* m8,16,32,169,8515,8535,163 */
- uint32_t count = 0;
- while(!(UCSRA & _BV(RXC))){
- /* 20060803 DojoCorp:: Addon coming from the previous Bootloader*/
- /* HACKME:: here is a good place to count times*/
- count++;
- if (count > MAX_TIME_COUNT)
- app_start();
- }
- return UDR;
-#endif
-}
-
-
-void getNch(uint8_t count)
-{
- while(count--) {
-#if defined(__AVR_ATmega128__) || defined(__AVR_ATmega1280__)
- if(bootuart == 1) {
- while(!(UCSR0A & _BV(RXC0)));
- UDR0;
- }
- else if(bootuart == 2) {
- while(!(UCSR1A & _BV(RXC1)));
- UDR1;
- }
-#elif defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__)
- getch();
-#else
- /* m8,16,32,169,8515,8535,163 */
- /* 20060803 DojoCorp:: Addon coming from the previous Bootloader*/
- //while(!(UCSRA & _BV(RXC)));
- //UDR;
- getch(); // need to handle time out
-#endif
- }
-}
-
-
-void byte_response(uint8_t val)
-{
- if (getch() == ' ') {
- putch(0x14);
- putch(val);
- putch(0x10);
- } else {
- if (++error_count == MAX_ERROR_COUNT)
- app_start();
- }
-}
-
-
-void nothing_response(void)
-{
- if (getch() == ' ') {
- putch(0x14);
- putch(0x10);
- } else {
- if (++error_count == MAX_ERROR_COUNT)
- app_start();
- }
-}
-
-void flash_led(uint8_t count)
-{
- while (count--) {
- LED_PORT |= _BV(LED);
- _delay_ms(100);
- LED_PORT &= ~_BV(LED);
- _delay_ms(100);
- }
-}
-
-
-/* end of file ATmegaBOOT.c */
+ /* HACKME:: here is a good place to count times*/
+ count++;
+ if (count > MAX_TIME_COUNT)
+ app_start();
+ }
+
+ return UDR1;
+ }
+ return 0;
+#elif defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__)
+ uint32_t count = 0;
+ while(!(UCSR0A & _BV(RXC0))){
+ /* 20060803 DojoCorp:: Addon coming from the previous Bootloader*/
+ /* HACKME:: here is a good place to count times*/
+ count++;
+ if (count > MAX_TIME_COUNT)
+ app_start();
+ }
+ return UDR0;
+#else
+ /* m8,16,32,169,8515,8535,163 */
+ uint32_t count = 0;
+ while(!(UCSRA & _BV(RXC))){
+ /* 20060803 DojoCorp:: Addon coming from the previous Bootloader*/
+ /* HACKME:: here is a good place to count times*/
+ count++;
+ if (count > MAX_TIME_COUNT)
+ app_start();
+ }
+ return UDR;
+#endif
+}
+
+
+void getNch(uint8_t count)
+{
+ while(count--) {
+#if defined(__AVR_ATmega128__) || defined(__AVR_ATmega1280__)
+ if(bootuart == 1) {
+ while(!(UCSR0A & _BV(RXC0)));
+ UDR0;
+ }
+ else if(bootuart == 2) {
+ while(!(UCSR1A & _BV(RXC1)));
+ UDR1;
+ }
+#elif defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__)
+ getch();
+#else
+ /* m8,16,32,169,8515,8535,163 */
+ /* 20060803 DojoCorp:: Addon coming from the previous Bootloader*/
+ //while(!(UCSRA & _BV(RXC)));
+ //UDR;
+ getch(); // need to handle time out
+#endif
+ }
+}
+
+
+void byte_response(uint8_t val)
+{
+ if (getch() == ' ') {
+ putch(0x14);
+ putch(val);
+ putch(0x10);
+ } else {
+ if (++error_count == MAX_ERROR_COUNT)
+ app_start();
+ }
+}
+
+
+void nothing_response(void)
+{
+ if (getch() == ' ') {
+ putch(0x14);
+ putch(0x10);
+ } else {
+ if (++error_count == MAX_ERROR_COUNT)
+ app_start();
+ }
+}
+
+void flash_led(uint8_t count)
+{
+ while (count--) {
+ LED_PORT |= _BV(LED);
+ _delay_ms(100);
+ LED_PORT &= ~_BV(LED);
+ _delay_ms(100);
+ }
+}
+
+
+/* end of file ATmegaBOOT.c */
diff --git a/hardware/arduino/bootloaders/caterina-Arduino_Robot/Caterina.c
b/hardware/arduino/bootloaders/caterina-Arduino_Robot/Caterina.c
index c462420..0c4bcbc 100644
--- a/hardware/arduino/bootloaders/caterina-Arduino_Robot/Caterina.c
+++ b/hardware/arduino/bootloaders/caterina-Arduino_Robot/Caterina.c
@@ -1,780 +1,779 @@
-/*
- LUFA Library
- Copyright (C) Dean Camera, 2011.
-
- dean [at] fourwalledcubicle [dot] com
- www.lufa-lib.org
-*/
-
-/*
- Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com)
-
- Permission to use, copy, modify, distribute, and sell this
- software and its documentation for any purpose is hereby granted
- without fee, provided that the above copyright notice appear in
- all copies and that both that the copyright notice and this
- permission notice and warranty disclaimer appear in supporting
- documentation, and that the name of the author not be used in
- advertising or publicity pertaining to distribution of the
- software without specific, written prior permission.
-
- The author disclaim all warranties with regard to this
- software, including all implied warranties of merchantability
- and fitness. In no event shall the author be liable for any
- special, indirect or consequential damages or any damages
- whatsoever resulting from loss of use, data or profits, whether
- in an action of contract, negligence or other tortious action,
- arising out of or in connection with the use or performance of
- this software.
-*/
-
-/** \file
- *
- * Main source file for the CDC class bootloader. This file contains the complete bootloader logic.
- */
-
-#define INCLUDE_FROM_CATERINA_C
-#include "Caterina.h"
-
-/** Contains the current baud rate and other settings of the first virtual serial port. This must be
retained as some
- * operating systems will not open the port unless the settings can be set successfully.
- */
-static CDC_LineEncoding_t LineEncoding = { .BaudRateBPS = 0,
- .CharFormat = CDC_LINEENCODING_OneStopBit,
- .ParityType = CDC_PARITY_None,
- .DataBits = 8 };
-
-/** Current address counter. This stores the current address of the FLASH or EEPROM as set by the host,
- * and is used when reading or writing to the AVRs memory (either FLASH or EEPROM depending on the issued
- * command.)
- */
-static uint32_t CurrAddress;
-
-/** Flag to indicate if the bootloader should be running, or should exit and allow the application code to
run
- * via a watchdog reset. When cleared the bootloader will exit, starting the watchdog and entering an
infinite
- * loop until the AVR restarts and the application runs.
- */
-static bool RunBootloader = true;
-
-/* Pulse generation counters to keep track of the time remaining for each pulse type */
-#define TX_RX_LED_PULSE_PERIOD 100
-uint16_t TxLEDPulse = 0; // time remaining for Tx LED pulse
-uint16_t RxLEDPulse = 0; // time remaining for Rx LED pulse
-
-/* Bootloader timeout timer */
-// MAH 8/15/12- change so timeouts work properly when the chip is running at 8MHz instead of 16.
-#define TIMEOUT_PERIOD 8000
-#define EXT_RESET_TIMEOUT_PERIOD 750
-
-
-/*********************************************************************************************************
-LilyPadUSB bootloader code
-The LilyPadUSB bootloader has been changed to remove the 8-second delay after external reset which is in
-the Leonardo. To enter the bootloader, the user should execute TWO external resets within 750 ms; that is,
-press the reset button twice, quickly.\
-
-Some other changes were made to allow this code to compile tightly enough to fit in the alloted 4k of
-bootloader space.
-*/
-// MAH 8/15/12- added this flag to replace the bulky program memory reads to check for the presence of a
sketch
-// at the top of the memory space.
-static bool sketchPresent = false;
-
-// MAH 8/15/12- make this volatile, since we modify it in one place and read it in another, we want to make
-// sure we're always working on the copy in memory and not an erroneous value stored in a cache somewhere.
-// This variable stores the length of time we've been in the bootloader when waiting for the 8 second delay.
-volatile uint16_t Timeout = 0;
-// MAH 8/15/12- added this for delay during startup. Did not use existing Timeout value b/c it only
increments
-// when there's a sketch at the top of the memory.
-volatile uint16_t resetTimeout = 0;
-
-// MAH 8/15/12- let's make this an 8-bit value instead of 16- that saves on memory because 16-bit addition
and
-// comparison compiles to bulkier code. Note that this does *not* require a change to the Arduino core-
we're
-// just sort of ignoring the extra byte that the Arduino core puts at the next location.
-uint8_t bootKey = 0x77;
-volatile uint8_t *const bootKeyPtr = (volatile uint8_t *)0x0800;
-
-// StartSketch() is called to clean up our mess before passing execution to the sketch.
-void StartSketch(void)
-{
- cli();
-
- /* Undo TIMER1 setup and clear the count before running the sketch */
- TIMSK1 = 0;
- TCCR1B = 0;
-
- /* Relocate the interrupt vector table to the application section */
- MCUCR = (1 << IVCE);
- MCUCR = 0;
-
- L_LED_OFF();
- TX_LED_OFF();
- RX_LED_OFF();
-
- /* jump to beginning of application space */
- __asm__ volatile("jmp 0x0000");
-
-}
-
-uint16_t LLEDPulse;
-
-/** Main program entry point. This routine configures the hardware required by the bootloader, then
continuously
- * runs the bootloader processing routine until it times out or is instructed to exit.
- */
-int main(void)
-{
- /* Save the value of the boot key memory before it is overwritten */
- uint8_t bootKeyPtrVal = *bootKeyPtr;
- *bootKeyPtr = 0;
-
- /* Check the reason for the reset so we can act accordingly */
- uint8_t mcusr_state = MCUSR; // store the initial state of the Status register
- MCUSR = 0; // clear all reset flags
-
- /* Watchdog may be configured with a 15 ms period so must disable it before going any further */
- // MAH 8/15/12- I removed this because wdt_disable() is the first thing SetupHardware() does- why
- // do it twice right in a row?
- //wdt_disable();
-
- /* Setup hardware required for the bootloader */
- // MAH 8/15/12- Moved this up to before the bootloader go/no-go decision tree so I could use the
- // timer in that decision tree. Removed the USBInit() call from it; if I'm not going to stay in
- // the bootloader, there's no point spending the time initializing the USB.
- // SetupHardware();
- wdt_disable();
-
- // Disable clock division
- clock_prescale_set(clock_div_1);
-
- // Relocate the interrupt vector table to the bootloader section
- MCUCR = (1 << IVCE);
- MCUCR = (1 << IVSEL);
-
- LED_SETUP();
- CPU_PRESCALE(0);
- L_LED_OFF();
- TX_LED_OFF();
- RX_LED_OFF();
-
- // Initialize TIMER1 to handle bootloader timeout and LED tasks.
- // With 16 MHz clock and 1/64 prescaler, timer 1 is clocked at 250 kHz
- // Our chosen compare match generates an interrupt every 1 ms.
- // This interrupt is disabled selectively when doing memory reading, erasing,
- // or writing since SPM has tight timing requirements.
-
- OCR1AH = 0;
- OCR1AL = 250;
- TIMSK1 = (1 << OCIE1A); // enable timer 1 output compare A match
interrupt
- TCCR1B = ((1 << CS11) | (1 << CS10)); // 1/64 prescaler on timer 1 input
-
-
- // MAH 8/15/12- this replaces bulky pgm_read_word(0) calls later on, to save memory.
- if (pgm_read_word(0) != 0xFFFF) sketchPresent = true;
-
-// MAH 26 Oct 2012- The "bootload or not?" section has been modified since the code released
-// with Arduino 1.0.1. The simplest modification is the replacement of equivalence checks on
-// the reset bits with masked checks, so if more than one reset occurs before the register is
-// checked, the check doesn't fail and fall through to the bootloader unnecessarily.
-
-// The second, more in depth modification addresses behavior after an external reset (i.e.,
-// user pushes the reset button). The Leonardo treats all external resets as requests to
-// re-enter the bootloader and wait for code to be loaded. It remains in bootloader mode for
-// 8 seconds before continuing on to the sketch (if one is present). By defining RESET_DELAY
-// equal to 1, this behavior will persist.
-
-// However, if RESET_DELAY is defined to 0, the reset timeout before loading the sketch drops
-// to 750ms. If, during that 750ms, another external reset occurs, THEN an 8-second delay
-// in the bootloader will occur.
-
- // This is the "no-8-second-delay" code. If this is the first time through the loop, we
- // don't expect to see the bootKey in memory.
- if ( (mcusr_state & (1<<EXTRF)) && (bootKeyPtrVal != bootKey) ) {
- *bootKeyPtr = bootKey; // Put the bootKey in memory so if we get back to this
- // point again, we know to jump into the bootloader
- sei(); // Enable interrupts, so we can use timer1 to track our time in the bootloader
- while (RunBootloader)
- {
- if (resetTimeout > EXT_RESET_TIMEOUT_PERIOD) // resetTimeout is getting incremeted
- RunBootloader = false; // in the timer1 ISR.
- }
- // If we make it past that while loop, it's sketch loading time!
- *bootKeyPtr = 0; // clear out the bootKey; from now on, we want to treat a reset like
- // a normal reset.
- cli(); // Disable interrupts, in case no sketch is present.
- RunBootloader = true; // We want to hang out in the bootloader if no sketch is present.
- if (sketchPresent) StartSketch(); // If a sketch is present, go! Otherwise, wait around
- // in the bootloader until
one is uploaded.
- }
- // On a power-on reset, we ALWAYS want to go to the sketch. If there is one.
- // This is a place where the old code had an equivalence and now there is a mask.
- else if ( (mcusr_state & (1<<PORF)) && sketchPresent) {
- StartSketch();
- }
- // On a watchdog reset, if the bootKey isn't set, and there's a sketch, we should just
- // go straight to the sketch.
- // This is a place where the old code had an equivalence and now there is a mask.
- else if ( (mcusr_state & (1<<WDRF) ) && (bootKeyPtrVal != bootKey) && sketchPresent) {
- // If it looks like an "accidental" watchdog reset then start the sketch.
- StartSketch();
- }
-
- /* Initialize USB Subsystem */
- USB_Init();
-
- /* Enable global interrupts so that the USB stack can function */
- sei();
-
- Timeout = 0;
-
- while (RunBootloader)
- {
- CDC_Task();
- USB_USBTask();
- /* Time out and start the sketch if one is present */
- if (Timeout > TIMEOUT_PERIOD)
- RunBootloader = false;
-
- // MAH 8/15/12- This used to be a function call- inlining it saves a few bytes.
- LLEDPulse++;
- uint8_t p = LLEDPulse >> 8;
- if (p > 127)
- p = 254-p;
- p += p;
- if (((uint8_t)LLEDPulse) > p)
- L_LED_OFF();
- else
- L_LED_ON();
- }
-
- /* Disconnect from the host - USB interface will be reset later along with the AVR */
- USB_Detach();
-
- /* Jump to beginning of application space to run the sketch - do not reset */
- StartSketch();
-}
-
-// Timer1 is set up to provide periodic interrupts. This is used to flicker the LEDs during
-// programming as well as to generate the clock counts which determine how long the board should
-// remain in bootloading mode.
-
-ISR(TIMER1_COMPA_vect, ISR_BLOCK)
-{
- /* Reset counter */
- TCNT1H = 0;
- TCNT1L = 0;
-
- /* Check whether the TX or RX LED one-shot period has elapsed. if so, turn off the LED */
- if (TxLEDPulse && !(--TxLEDPulse))
- TX_LED_OFF();
- if (RxLEDPulse && !(--RxLEDPulse))
- RX_LED_OFF();
- resetTimeout++; // Needed for the "short reset delay" mode- governs the time the board waits
- // for a second reset before loading the sketch.
- if (pgm_read_word(0) != 0xFFFF)
- Timeout++;
-}
-
-// MAH 29 Oct 2012 Nothing below this point has to change for the LilyPadUSB support
-
-/** Event handler for the USB_ConfigurationChanged event. This configures the device's endpoints ready
- * to relay data to and from the attached USB host.
- */
-void EVENT_USB_Device_ConfigurationChanged(void)
-{
- /* Setup CDC Notification, Rx and Tx Endpoints */
- Endpoint_ConfigureEndpoint(CDC_NOTIFICATION_EPNUM, EP_TYPE_INTERRUPT,
- ENDPOINT_DIR_IN, CDC_NOTIFICATION_EPSIZE,
- ENDPOINT_BANK_SINGLE);
-
- Endpoint_ConfigureEndpoint(CDC_TX_EPNUM, EP_TYPE_BULK,
- ENDPOINT_DIR_IN, CDC_TXRX_EPSIZE,
- ENDPOINT_BANK_SINGLE);
-
- Endpoint_ConfigureEndpoint(CDC_RX_EPNUM, EP_TYPE_BULK,
- ENDPOINT_DIR_OUT, CDC_TXRX_EPSIZE,
- ENDPOINT_BANK_SINGLE);
-}
-
-/** Event handler for the USB_ControlRequest event. This is used to catch and process control requests sent
to
- * the device from the USB host before passing along unhandled control requests to the library for
processing
- * internally.
- */
-void EVENT_USB_Device_ControlRequest(void)
-{
- /* Ignore any requests that aren't directed to the CDC interface */
- if ((USB_ControlRequest.bmRequestType & (CONTROL_REQTYPE_TYPE | CONTROL_REQTYPE_RECIPIENT)) !=
- (REQTYPE_CLASS | REQREC_INTERFACE))
- {
- return;
- }
-
- /* Process CDC specific control requests */
- switch (USB_ControlRequest.bRequest)
- {
- case CDC_REQ_GetLineEncoding:
- if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS |
REQREC_INTERFACE))
- {
- Endpoint_ClearSETUP();
-
- /* Write the line coding data to the control endpoint */
- Endpoint_Write_Control_Stream_LE(&LineEncoding, sizeof(CDC_LineEncoding_t));
- Endpoint_ClearOUT();
- }
-
- break;
- case CDC_REQ_SetLineEncoding:
- if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS |
REQREC_INTERFACE))
- {
- Endpoint_ClearSETUP();
-
- /* Read the line coding data in from the host into the global struct */
- Endpoint_Read_Control_Stream_LE(&LineEncoding, sizeof(CDC_LineEncoding_t));
- Endpoint_ClearIN();
- }
-
- break;
- }
-}
-
-#if !defined(NO_BLOCK_SUPPORT)
-/** Reads or writes a block of EEPROM or FLASH memory to or from the appropriate CDC data endpoint, depending
- * on the AVR910 protocol command issued.
- *
- * \param[in] Command Single character AVR910 protocol command indicating what memory operation to perform
- */
-static void ReadWriteMemoryBlock(const uint8_t Command)
-{
- uint16_t BlockSize;
- char MemoryType;
-
- bool HighByte = false;
- uint8_t LowByte = 0;
-
- BlockSize = (FetchNextCommandByte() << 8);
- BlockSize |= FetchNextCommandByte();
-
- MemoryType = FetchNextCommandByte();
-
- if ((MemoryType != 'E') && (MemoryType != 'F'))
- {
- /* Send error byte back to the host */
- WriteNextResponseByte('?');
-
- return;
- }
-
- /* Disable timer 1 interrupt - can't afford to process nonessential interrupts
- * while doing SPM tasks */
- TIMSK1 = 0;
-
- /* Check if command is to read memory */
- if (Command == 'g')
- {
- /* Re-enable RWW section */
- boot_rww_enable();
-
- while (BlockSize--)
- {
- if (MemoryType == 'F')
- {
- /* Read the next FLASH byte from the current FLASH page */
- #if (FLASHEND > 0xFFFF)
- WriteNextResponseByte(pgm_read_byte_far(CurrAddress | HighByte));
- #else
- WriteNextResponseByte(pgm_read_byte(CurrAddress | HighByte));
- #endif
-
- /* If both bytes in current word have been read, increment the address
counter */
- if (HighByte)
- CurrAddress += 2;
-
- HighByte = !HighByte;
- }
- else
- {
- /* Read the next EEPROM byte into the endpoint */
- WriteNextResponseByte(eeprom_read_byte((uint8_t*)(intptr_t)(CurrAddress >>
1)));
-
- /* Increment the address counter after use */
- CurrAddress += 2;
- }
- }
- }
- else
- {
- uint32_t PageStartAddress = CurrAddress;
-
- if (MemoryType == 'F')
- {
- boot_page_erase(PageStartAddress);
- boot_spm_busy_wait();
- }
-
- while (BlockSize--)
- {
- if (MemoryType == 'F')
- {
- /* If both bytes in current word have been written, increment the address
counter */
- if (HighByte)
- {
- /* Write the next FLASH word to the current FLASH page */
- boot_page_fill(CurrAddress, ((FetchNextCommandByte() << 8) |
LowByte));
-
- /* Increment the address counter after use */
- CurrAddress += 2;
- }
- else
- {
- LowByte = FetchNextCommandByte();
- }
-
- HighByte = !HighByte;
- }
- else
- {
- /* Write the next EEPROM byte from the endpoint */
- eeprom_write_byte((uint8_t*)((intptr_t)(CurrAddress >> 1)),
FetchNextCommandByte());
-
- /* Increment the address counter after use */
- CurrAddress += 2;
- }
- }
-
- /* If in FLASH programming mode, commit the page after writing */
- if (MemoryType == 'F')
- {
- /* Commit the flash page to memory */
- boot_page_write(PageStartAddress);
-
- /* Wait until write operation has completed */
- boot_spm_busy_wait();
- }
-
- /* Send response byte back to the host */
- WriteNextResponseByte('\r');
- }
-
- /* Re-enable timer 1 interrupt disabled earlier in this routine */
- TIMSK1 = (1 << OCIE1A);
-}
-#endif
-
-/** Retrieves the next byte from the host in the CDC data OUT endpoint, and clears the endpoint bank if
needed
- * to allow reception of the next data packet from the host.
- *
- * \return Next received byte from the host in the CDC data OUT endpoint
- */
-static uint8_t FetchNextCommandByte(void)
-{
- /* Select the OUT endpoint so that the next data byte can be read */
- Endpoint_SelectEndpoint(CDC_RX_EPNUM);
-
- /* If OUT endpoint empty, clear it and wait for the next packet from the host */
- while (!(Endpoint_IsReadWriteAllowed()))
- {
- Endpoint_ClearOUT();
-
- while (!(Endpoint_IsOUTReceived()))
- {
- if (USB_DeviceState == DEVICE_STATE_Unattached)
- return 0;
- }
- }
-
- /* Fetch the next byte from the OUT endpoint */
- return Endpoint_Read_8();
-}
-
-/** Writes the next response byte to the CDC data IN endpoint, and sends the endpoint back if needed to free
up the
- * bank when full ready for the next byte in the packet to the host.
- *
- * \param[in] Response Next response byte to send to the host
- */
-static void WriteNextResponseByte(const uint8_t Response)
-{
- /* Select the IN endpoint so that the next data byte can be written */
- Endpoint_SelectEndpoint(CDC_TX_EPNUM);
-
- /* If IN endpoint full, clear it and wait until ready for the next packet to the host */
- if (!(Endpoint_IsReadWriteAllowed()))
- {
- Endpoint_ClearIN();
-
- while (!(Endpoint_IsINReady()))
- {
- if (USB_DeviceState == DEVICE_STATE_Unattached)
- return;
- }
- }
-
- /* Write the next byte to the IN endpoint */
- Endpoint_Write_8(Response);
-
- TX_LED_ON();
- TxLEDPulse = TX_RX_LED_PULSE_PERIOD;
-}
-
-#define STK_OK 0x10
-#define STK_INSYNC 0x14 // ' '
-#define CRC_EOP 0x20 // 'SPACE'
-#define STK_GET_SYNC 0x30 // '0'
-
-#define STK_GET_PARAMETER 0x41 // 'A'
-#define STK_SET_DEVICE 0x42 // 'B'
-#define STK_SET_DEVICE_EXT 0x45 // 'E'
-#define STK_LOAD_ADDRESS 0x55 // 'U'
-#define STK_UNIVERSAL 0x56 // 'V'
-#define STK_PROG_PAGE 0x64 // 'd'
-#define STK_READ_PAGE 0x74 // 't'
-#define STK_READ_SIGN 0x75 // 'u'
-
-/** Task to read in AVR910 commands from the CDC data OUT endpoint, process them, perform the required
actions
- * and send the appropriate response back to the host.
- */
-void CDC_Task(void)
-{
- /* Select the OUT endpoint */
- Endpoint_SelectEndpoint(CDC_RX_EPNUM);
-
- /* Check if endpoint has a command in it sent from the host */
- if (!(Endpoint_IsOUTReceived()))
- return;
-
- RX_LED_ON();
- RxLEDPulse = TX_RX_LED_PULSE_PERIOD;
-
- /* Read in the bootloader command (first byte sent from host) */
- uint8_t Command = FetchNextCommandByte();
-
- if (Command == 'E')
- {
- /* We nearly run out the bootloader timeout clock,
- * leaving just a few hundred milliseconds so the
- * bootloder has time to respond and service any
- * subsequent requests */
- Timeout = TIMEOUT_PERIOD - 500;
-
- /* Re-enable RWW section - must be done here in case
- * user has disabled verification on upload. */
- boot_rww_enable_safe();
-
- // Send confirmation byte back to the host
- WriteNextResponseByte('\r');
- }
- else if (Command == 'T')
- {
- FetchNextCommandByte();
-
- // Send confirmation byte back to the host
- WriteNextResponseByte('\r');
- }
- else if ((Command == 'L') || (Command == 'P'))
- {
- // Send confirmation byte back to the host
- WriteNextResponseByte('\r');
- }
- else if (Command == 't')
- {
- // Return ATMEGA128 part code - this is only to allow AVRProg to use the bootloader
- WriteNextResponseByte(0x44);
- WriteNextResponseByte(0x00);
- }
- else if (Command == 'a')
- {
- // Indicate auto-address increment is supported
- WriteNextResponseByte('Y');
- }
- else if (Command == 'A')
- {
- // Set the current address to that given by the host
- CurrAddress = (FetchNextCommandByte() << 9);
- CurrAddress |= (FetchNextCommandByte() << 1);
-
- // Send confirmation byte back to the host
- WriteNextResponseByte('\r');
- }
- else if (Command == 'p')
- {
- // Indicate serial programmer back to the host
- WriteNextResponseByte('S');
- }
- else if (Command == 'S')
- {
- // Write the 7-byte software identifier to the endpoint
- for (uint8_t CurrByte = 0; CurrByte < 7; CurrByte++)
- WriteNextResponseByte(SOFTWARE_IDENTIFIER[CurrByte]);
- }
- else if (Command == 'V')
- {
- WriteNextResponseByte('0' + BOOTLOADER_VERSION_MAJOR);
- WriteNextResponseByte('0' + BOOTLOADER_VERSION_MINOR);
- }
- else if (Command == 's')
- {
- WriteNextResponseByte(AVR_SIGNATURE_3);
- WriteNextResponseByte(AVR_SIGNATURE_2);
- WriteNextResponseByte(AVR_SIGNATURE_1);
- }
- else if (Command == 'e')
- {
- // Clear the application section of flash
- for (uint32_t CurrFlashAddress = 0; CurrFlashAddress < BOOT_START_ADDR; CurrFlashAddress +=
SPM_PAGESIZE)
- {
- boot_page_erase(CurrFlashAddress);
- boot_spm_busy_wait();
- boot_page_write(CurrFlashAddress);
- boot_spm_busy_wait();
- }
-
- // Send confirmation byte back to the host
- WriteNextResponseByte('\r');
- }
- #if !defined(NO_LOCK_BYTE_WRITE_SUPPORT)
- else if (Command == 'l')
- {
- // Set the lock bits to those given by the host
- boot_lock_bits_set(FetchNextCommandByte());
-
- // Send confirmation byte back to the host
- WriteNextResponseByte('\r');
- }
- #endif
- else if (Command == 'r')
- {
- WriteNextResponseByte(boot_lock_fuse_bits_get(GET_LOCK_BITS));
- }
- else if (Command == 'F')
- {
- WriteNextResponseByte(boot_lock_fuse_bits_get(GET_LOW_FUSE_BITS));
- }
- else if (Command == 'N')
- {
- WriteNextResponseByte(boot_lock_fuse_bits_get(GET_HIGH_FUSE_BITS));
- }
- else if (Command == 'Q')
- {
- WriteNextResponseByte(boot_lock_fuse_bits_get(GET_EXTENDED_FUSE_BITS));
- }
- #if !defined(NO_BLOCK_SUPPORT)
- else if (Command == 'b')
- {
- WriteNextResponseByte('Y');
-
- // Send block size to the host
- WriteNextResponseByte(SPM_PAGESIZE >> 8);
- WriteNextResponseByte(SPM_PAGESIZE & 0xFF);
- }
- else if ((Command == 'B') || (Command == 'g'))
- {
- // Keep resetting the timeout counter if we're receiving self-programming instructions
- Timeout = 0;
- // Delegate the block write/read to a separate function for clarity
- ReadWriteMemoryBlock(Command);
- }
- #endif
- #if !defined(NO_FLASH_BYTE_SUPPORT)
- else if (Command == 'C')
- {
- // Write the high byte to the current flash page
- boot_page_fill(CurrAddress, FetchNextCommandByte());
-
- // Send confirmation byte back to the host
- WriteNextResponseByte('\r');
- }
- else if (Command == 'c')
- {
- // Write the low byte to the current flash page
- boot_page_fill(CurrAddress | 0x01, FetchNextCommandByte());
-
- // Increment the address
- CurrAddress += 2;
-
- // Send confirmation byte back to the host
- WriteNextResponseByte('\r');
- }
- else if (Command == 'm')
- {
- // Commit the flash page to memory
- boot_page_write(CurrAddress);
-
- // Wait until write operation has completed
- boot_spm_busy_wait();
-
- // Send confirmation byte back to the host
- WriteNextResponseByte('\r');
- }
- else if (Command == 'R')
- {
- #if (FLASHEND > 0xFFFF)
- uint16_t ProgramWord = pgm_read_word_far(CurrAddress);
- #else
- uint16_t ProgramWord = pgm_read_word(CurrAddress);
- #endif
-
- WriteNextResponseByte(ProgramWord >> 8);
- WriteNextResponseByte(ProgramWord & 0xFF);
- }
- #endif
- #if !defined(NO_EEPROM_BYTE_SUPPORT)
- else if (Command == 'D')
- {
- // Read the byte from the endpoint and write it to the EEPROM
- eeprom_write_byte((uint8_t*)((intptr_t)(CurrAddress >> 1)), FetchNextCommandByte());
-
- // Increment the address after use
- CurrAddress += 2;
-
- // Send confirmation byte back to the host
- WriteNextResponseByte('\r');
- }
- else if (Command == 'd')
- {
- // Read the EEPROM byte and write it to the endpoint
- WriteNextResponseByte(eeprom_read_byte((uint8_t*)((intptr_t)(CurrAddress >> 1))));
-
- // Increment the address after use
- CurrAddress += 2;
- }
- #endif
- else if (Command != 27)
- {
- // Unknown (non-sync) command, return fail code
- WriteNextResponseByte('?');
- }
-
-
- /* Select the IN endpoint */
- Endpoint_SelectEndpoint(CDC_TX_EPNUM);
-
- /* Remember if the endpoint is completely full before clearing it */
- bool IsEndpointFull = !(Endpoint_IsReadWriteAllowed());
-
- /* Send the endpoint data to the host */
- Endpoint_ClearIN();
-
- /* If a full endpoint's worth of data was sent, we need to send an empty packet afterwards to signal
end of transfer */
- if (IsEndpointFull)
- {
- while (!(Endpoint_IsINReady()))
- {
- if (USB_DeviceState == DEVICE_STATE_Unattached)
- return;
- }
-
- Endpoint_ClearIN();
- }
-
- /* Wait until the data has been sent to the host */
- while (!(Endpoint_IsINReady()))
- {
- if (USB_DeviceState == DEVICE_STATE_Unattached)
- return;
- }
-
- /* Select the OUT endpoint */
- Endpoint_SelectEndpoint(CDC_RX_EPNUM);
-
- /* Acknowledge the command from the host */
- Endpoint_ClearOUT();
-}
-
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2011.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaim all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ *
+ * Main source file for the CDC class bootloader. This file contains the complete bootloader logic.
+ */
+
+#define INCLUDE_FROM_CATERINA_C
+#include "Caterina.h"
+
+/** Contains the current baud rate and other settings of the first virtual serial port. This must be
retained as some
+ * operating systems will not open the port unless the settings can be set successfully.
+ */
+static CDC_LineEncoding_t LineEncoding = { .BaudRateBPS = 0,
+ .CharFormat = CDC_LINEENCODING_OneStopBit,
+ .ParityType = CDC_PARITY_None,
+ .DataBits = 8 };
+
+/** Current address counter. This stores the current address of the FLASH or EEPROM as set by the host,
+ * and is used when reading or writing to the AVRs memory (either FLASH or EEPROM depending on the issued
+ * command.)
+ */
+static uint32_t CurrAddress;
+
+/** Flag to indicate if the bootloader should be running, or should exit and allow the application code to
run
+ * via a watchdog reset. When cleared the bootloader will exit, starting the watchdog and entering an
infinite
+ * loop until the AVR restarts and the application runs.
+ */
+static bool RunBootloader = true;
+
+/* Pulse generation counters to keep track of the time remaining for each pulse type */
+#define TX_RX_LED_PULSE_PERIOD 100
+uint16_t TxLEDPulse = 0; // time remaining for Tx LED pulse
+uint16_t RxLEDPulse = 0; // time remaining for Rx LED pulse
+
+/* Bootloader timeout timer */
+// MAH 8/15/12- change so timeouts work properly when the chip is running at 8MHz instead of 16.
+#define TIMEOUT_PERIOD 8000
+#define EXT_RESET_TIMEOUT_PERIOD 750
+
+
+/*********************************************************************************************************
+LilyPadUSB bootloader code
+The LilyPadUSB bootloader has been changed to remove the 8-second delay after external reset which is in
+the Leonardo. To enter the bootloader, the user should execute TWO external resets within 750 ms; that is,
+press the reset button twice, quickly.\
+
+Some other changes were made to allow this code to compile tightly enough to fit in the alloted 4k of
+bootloader space.
+*/
+// MAH 8/15/12- added this flag to replace the bulky program memory reads to check for the presence of a
sketch
+// at the top of the memory space.
+static bool sketchPresent = false;
+
+// MAH 8/15/12- make this volatile, since we modify it in one place and read it in another, we want to make
+// sure we're always working on the copy in memory and not an erroneous value stored in a cache somewhere.
+// This variable stores the length of time we've been in the bootloader when waiting for the 8 second delay.
+volatile uint16_t Timeout = 0;
+// MAH 8/15/12- added this for delay during startup. Did not use existing Timeout value b/c it only
increments
+// when there's a sketch at the top of the memory.
+volatile uint16_t resetTimeout = 0;
+
+// MAH 8/15/12- let's make this an 8-bit value instead of 16- that saves on memory because 16-bit addition
and
+// comparison compiles to bulkier code. Note that this does *not* require a change to the Arduino core-
we're
+// just sort of ignoring the extra byte that the Arduino core puts at the next location.
+uint8_t bootKey = 0x77;
+volatile uint8_t *const bootKeyPtr = (volatile uint8_t *)0x0800;
+
+// StartSketch() is called to clean up our mess before passing execution to the sketch.
+void StartSketch(void)
+{
+ cli();
+
+ /* Undo TIMER1 setup and clear the count before running the sketch */
+ TIMSK1 = 0;
+ TCCR1B = 0;
+
+ /* Relocate the interrupt vector table to the application section */
+ MCUCR = (1 << IVCE);
+ MCUCR = 0;
+
+ L_LED_OFF();
+ TX_LED_OFF();
+ RX_LED_OFF();
+
+ /* jump to beginning of application space */
+ __asm__ volatile("jmp 0x0000");
+
+}
+
+uint16_t LLEDPulse;
+
+/** Main program entry point. This routine configures the hardware required by the bootloader, then
continuously
+ * runs the bootloader processing routine until it times out or is instructed to exit.
+ */
+int main(void)
+{
+ /* Save the value of the boot key memory before it is overwritten */
+ uint8_t bootKeyPtrVal = *bootKeyPtr;
+ *bootKeyPtr = 0;
+
+ /* Check the reason for the reset so we can act accordingly */
+ uint8_t mcusr_state = MCUSR; // store the initial state of the Status register
+ MCUSR = 0; // clear all reset flags
+
+ /* Watchdog may be configured with a 15 ms period so must disable it before going any further */
+ // MAH 8/15/12- I removed this because wdt_disable() is the first thing SetupHardware() does- why
+ // do it twice right in a row?
+ //wdt_disable();
+
+ /* Setup hardware required for the bootloader */
+ // MAH 8/15/12- Moved this up to before the bootloader go/no-go decision tree so I could use the
+ // timer in that decision tree. Removed the USBInit() call from it; if I'm not going to stay in
+ // the bootloader, there's no point spending the time initializing the USB.
+ // SetupHardware();
+ wdt_disable();
+
+ // Disable clock division
+ clock_prescale_set(clock_div_1);
+
+ // Relocate the interrupt vector table to the bootloader section
+ MCUCR = (1 << IVCE);
+ MCUCR = (1 << IVSEL);
+
+ LED_SETUP();
+ CPU_PRESCALE(0);
+ L_LED_OFF();
+ TX_LED_OFF();
+ RX_LED_OFF();
+
+ // Initialize TIMER1 to handle bootloader timeout and LED tasks.
+ // With 16 MHz clock and 1/64 prescaler, timer 1 is clocked at 250 kHz
+ // Our chosen compare match generates an interrupt every 1 ms.
+ // This interrupt is disabled selectively when doing memory reading, erasing,
+ // or writing since SPM has tight timing requirements.
+
+ OCR1AH = 0;
+ OCR1AL = 250;
+ TIMSK1 = (1 << OCIE1A); // enable timer 1 output compare A match
interrupt
+ TCCR1B = ((1 << CS11) | (1 << CS10)); // 1/64 prescaler on timer 1 input
+
+
+ // MAH 8/15/12- this replaces bulky pgm_read_word(0) calls later on, to save memory.
+ if (pgm_read_word(0) != 0xFFFF) sketchPresent = true;
+
+// MAH 26 Oct 2012- The "bootload or not?" section has been modified since the code released
+// with Arduino 1.0.1. The simplest modification is the replacement of equivalence checks on
+// the reset bits with masked checks, so if more than one reset occurs before the register is
+// checked, the check doesn't fail and fall through to the bootloader unnecessarily.
+
+// The second, more in depth modification addresses behavior after an external reset (i.e.,
+// user pushes the reset button). The Leonardo treats all external resets as requests to
+// re-enter the bootloader and wait for code to be loaded. It remains in bootloader mode for
+// 8 seconds before continuing on to the sketch (if one is present). By defining RESET_DELAY
+// equal to 1, this behavior will persist.
+
+// However, if RESET_DELAY is defined to 0, the reset timeout before loading the sketch drops
+// to 750ms. If, during that 750ms, another external reset occurs, THEN an 8-second delay
+// in the bootloader will occur.
+
+ // This is the "no-8-second-delay" code. If this is the first time through the loop, we
+ // don't expect to see the bootKey in memory.
+ if ( (mcusr_state & (1<<EXTRF)) && (bootKeyPtrVal != bootKey) ) {
+ *bootKeyPtr = bootKey; // Put the bootKey in memory so if we get back to this
+ // point again, we know to jump into the bootloader
+ sei(); // Enable interrupts, so we can use timer1 to track our time in the bootloader
+ while (RunBootloader)
+ {
+ if (resetTimeout > EXT_RESET_TIMEOUT_PERIOD) // resetTimeout is getting incremeted
+ RunBootloader = false; // in the timer1 ISR.
+ }
+ // If we make it past that while loop, it's sketch loading time!
+ *bootKeyPtr = 0; // clear out the bootKey; from now on, we want to treat a reset like
+ // a normal reset.
+ cli(); // Disable interrupts, in case no sketch is present.
+ RunBootloader = true; // We want to hang out in the bootloader if no sketch is present.
+ if (sketchPresent) StartSketch(); // If a sketch is present, go! Otherwise, wait around
+ // in the bootloader until
one is uploaded.
+ }
+ // On a power-on reset, we ALWAYS want to go to the sketch. If there is one.
+ // This is a place where the old code had an equivalence and now there is a mask.
+ else if ( (mcusr_state & (1<<PORF)) && sketchPresent) {
+ StartSketch();
+ }
+ // On a watchdog reset, if the bootKey isn't set, and there's a sketch, we should just
+ // go straight to the sketch.
+ // This is a place where the old code had an equivalence and now there is a mask.
+ else if ( (mcusr_state & (1<<WDRF) ) && (bootKeyPtrVal != bootKey) && sketchPresent) {
+ // If it looks like an "accidental" watchdog reset then start the sketch.
+ StartSketch();
+ }
+
+ /* Initialize USB Subsystem */
+ USB_Init();
+
+ /* Enable global interrupts so that the USB stack can function */
+ sei();
+
+ Timeout = 0;
+
+ while (RunBootloader)
+ {
+ CDC_Task();
+ USB_USBTask();
+ /* Time out and start the sketch if one is present */
+ if (Timeout > TIMEOUT_PERIOD)
+ RunBootloader = false;
+
+ // MAH 8/15/12- This used to be a function call- inlining it saves a few bytes.
+ LLEDPulse++;
+ uint8_t p = LLEDPulse >> 8;
+ if (p > 127)
+ p = 254-p;
+ p += p;
+ if (((uint8_t)LLEDPulse) > p)
+ L_LED_OFF();
+ else
+ L_LED_ON();
+ }
+
+ /* Disconnect from the host - USB interface will be reset later along with the AVR */
+ USB_Detach();
+
+ /* Jump to beginning of application space to run the sketch - do not reset */
+ StartSketch();
+}
+
+// Timer1 is set up to provide periodic interrupts. This is used to flicker the LEDs during
+// programming as well as to generate the clock counts which determine how long the board should
+// remain in bootloading mode.
+
+ISR(TIMER1_COMPA_vect, ISR_BLOCK)
+{
+ /* Reset counter */
+ TCNT1H = 0;
+ TCNT1L = 0;
+
+ /* Check whether the TX or RX LED one-shot period has elapsed. if so, turn off the LED */
+ if (TxLEDPulse && !(--TxLEDPulse))
+ TX_LED_OFF();
+ if (RxLEDPulse && !(--RxLEDPulse))
+ RX_LED_OFF();
+ resetTimeout++; // Needed for the "short reset delay" mode- governs the time the board waits
+ // for a second reset before loading the sketch.
+ if (pgm_read_word(0) != 0xFFFF)
+ Timeout++;
+}
+
+// MAH 29 Oct 2012 Nothing below this point has to change for the LilyPadUSB support
+
+/** Event handler for the USB_ConfigurationChanged event. This configures the device's endpoints ready
+ * to relay data to and from the attached USB host.
+ */
+void EVENT_USB_Device_ConfigurationChanged(void)
+{
+ /* Setup CDC Notification, Rx and Tx Endpoints */
+ Endpoint_ConfigureEndpoint(CDC_NOTIFICATION_EPNUM, EP_TYPE_INTERRUPT,
+ ENDPOINT_DIR_IN, CDC_NOTIFICATION_EPSIZE,
+ ENDPOINT_BANK_SINGLE);
+
+ Endpoint_ConfigureEndpoint(CDC_TX_EPNUM, EP_TYPE_BULK,
+ ENDPOINT_DIR_IN, CDC_TXRX_EPSIZE,
+ ENDPOINT_BANK_SINGLE);
+
+ Endpoint_ConfigureEndpoint(CDC_RX_EPNUM, EP_TYPE_BULK,
+ ENDPOINT_DIR_OUT, CDC_TXRX_EPSIZE,
+ ENDPOINT_BANK_SINGLE);
+}
+
+/** Event handler for the USB_ControlRequest event. This is used to catch and process control requests sent
to
+ * the device from the USB host before passing along unhandled control requests to the library for
processing
+ * internally.
+ */
+void EVENT_USB_Device_ControlRequest(void)
+{
+ /* Ignore any requests that aren't directed to the CDC interface */
+ if ((USB_ControlRequest.bmRequestType & (CONTROL_REQTYPE_TYPE | CONTROL_REQTYPE_RECIPIENT)) !=
+ (REQTYPE_CLASS | REQREC_INTERFACE))
+ {
+ return;
+ }
+
+ /* Process CDC specific control requests */
+ switch (USB_ControlRequest.bRequest)
+ {
+ case CDC_REQ_GetLineEncoding:
+ if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS |
REQREC_INTERFACE))
+ {
+ Endpoint_ClearSETUP();
+
+ /* Write the line coding data to the control endpoint */
+ Endpoint_Write_Control_Stream_LE(&LineEncoding, sizeof(CDC_LineEncoding_t));
+ Endpoint_ClearOUT();
+ }
+
+ break;
+ case CDC_REQ_SetLineEncoding:
+ if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS |
REQREC_INTERFACE))
+ {
+ Endpoint_ClearSETUP();
+
+ /* Read the line coding data in from the host into the global struct */
+ Endpoint_Read_Control_Stream_LE(&LineEncoding, sizeof(CDC_LineEncoding_t));
+ Endpoint_ClearIN();
+ }
+
+ break;
+ }
+}
+
+#if !defined(NO_BLOCK_SUPPORT)
+/** Reads or writes a block of EEPROM or FLASH memory to or from the appropriate CDC data endpoint, depending
+ * on the AVR910 protocol command issued.
+ *
+ * \param[in] Command Single character AVR910 protocol command indicating what memory operation to perform
+ */
+static void ReadWriteMemoryBlock(const uint8_t Command)
+{
+ uint16_t BlockSize;
+ char MemoryType;
+
+ bool HighByte = false;
+ uint8_t LowByte = 0;
+
+ BlockSize = (FetchNextCommandByte() << 8);
+ BlockSize |= FetchNextCommandByte();
+
+ MemoryType = FetchNextCommandByte();
+
+ if ((MemoryType != 'E') && (MemoryType != 'F'))
+ {
+ /* Send error byte back to the host */
+ WriteNextResponseByte('?');
+
+ return;
+ }
+
+ /* Disable timer 1 interrupt - can't afford to process nonessential interrupts
+ * while doing SPM tasks */
+ TIMSK1 = 0;
+
+ /* Check if command is to read memory */
+ if (Command == 'g')
+ {
+ /* Re-enable RWW section */
+ boot_rww_enable();
+
+ while (BlockSize--)
+ {
+ if (MemoryType == 'F')
+ {
+ /* Read the next FLASH byte from the current FLASH page */
+ #if (FLASHEND > 0xFFFF)
+ WriteNextResponseByte(pgm_read_byte_far(CurrAddress | HighByte));
+ #else
+ WriteNextResponseByte(pgm_read_byte(CurrAddress | HighByte));
+ #endif
+
+ /* If both bytes in current word have been read, increment the address
counter */
+ if (HighByte)
+ CurrAddress += 2;
+
+ HighByte = !HighByte;
+ }
+ else
+ {
+ /* Read the next EEPROM byte into the endpoint */
+ WriteNextResponseByte(eeprom_read_byte((uint8_t*)(intptr_t)(CurrAddress >>
1)));
+
+ /* Increment the address counter after use */
+ CurrAddress += 2;
+ }
+ }
+ }
+ else
+ {
+ uint32_t PageStartAddress = CurrAddress;
+
+ if (MemoryType == 'F')
+ {
+ boot_page_erase(PageStartAddress);
+ boot_spm_busy_wait();
+ }
+
+ while (BlockSize--)
+ {
+ if (MemoryType == 'F')
+ {
+ /* If both bytes in current word have been written, increment the address
counter */
+ if (HighByte)
+ {
+ /* Write the next FLASH word to the current FLASH page */
+ boot_page_fill(CurrAddress, ((FetchNextCommandByte() << 8) |
LowByte));
+
+ /* Increment the address counter after use */
+ CurrAddress += 2;
+ }
+ else
+ {
+ LowByte = FetchNextCommandByte();
+ }
+
+ HighByte = !HighByte;
+ }
+ else
+ {
+ /* Write the next EEPROM byte from the endpoint */
+ eeprom_write_byte((uint8_t*)((intptr_t)(CurrAddress >> 1)),
FetchNextCommandByte());
+
+ /* Increment the address counter after use */
+ CurrAddress += 2;
+ }
+ }
+
+ /* If in FLASH programming mode, commit the page after writing */
+ if (MemoryType == 'F')
+ {
+ /* Commit the flash page to memory */
+ boot_page_write(PageStartAddress);
+
+ /* Wait until write operation has completed */
+ boot_spm_busy_wait();
+ }
+
+ /* Send response byte back to the host */
+ WriteNextResponseByte('\r');
+ }
+
+ /* Re-enable timer 1 interrupt disabled earlier in this routine */
+ TIMSK1 = (1 << OCIE1A);
+}
+#endif
+
+/** Retrieves the next byte from the host in the CDC data OUT endpoint, and clears the endpoint bank if
needed
+ * to allow reception of the next data packet from the host.
+ *
+ * \return Next received byte from the host in the CDC data OUT endpoint
+ */
+static uint8_t FetchNextCommandByte(void)
+{
+ /* Select the OUT endpoint so that the next data byte can be read */
+ Endpoint_SelectEndpoint(CDC_RX_EPNUM);
+
+ /* If OUT endpoint empty, clear it and wait for the next packet from the host */
+ while (!(Endpoint_IsReadWriteAllowed()))
+ {
+ Endpoint_ClearOUT();
+
+ while (!(Endpoint_IsOUTReceived()))
+ {
+ if (USB_DeviceState == DEVICE_STATE_Unattached)
+ return 0;
+ }
+ }
+
+ /* Fetch the next byte from the OUT endpoint */
+ return Endpoint_Read_8();
+}
+
+/** Writes the next response byte to the CDC data IN endpoint, and sends the endpoint back if needed to free
up the
+ * bank when full ready for the next byte in the packet to the host.
+ *
+ * \param[in] Response Next response byte to send to the host
+ */
+static void WriteNextResponseByte(const uint8_t Response)
+{
+ /* Select the IN endpoint so that the next data byte can be written */
+ Endpoint_SelectEndpoint(CDC_TX_EPNUM);
+
+ /* If IN endpoint full, clear it and wait until ready for the next packet to the host */
+ if (!(Endpoint_IsReadWriteAllowed()))
+ {
+ Endpoint_ClearIN();
+
+ while (!(Endpoint_IsINReady()))
+ {
+ if (USB_DeviceState == DEVICE_STATE_Unattached)
+ return;
+ }
+ }
+
+ /* Write the next byte to the IN endpoint */
+ Endpoint_Write_8(Response);
+
+ TX_LED_ON();
+ TxLEDPulse = TX_RX_LED_PULSE_PERIOD;
+}
+
+#define STK_OK 0x10
+#define STK_INSYNC 0x14 // ' '
+#define CRC_EOP 0x20 // 'SPACE'
+#define STK_GET_SYNC 0x30 // '0'
+
+#define STK_GET_PARAMETER 0x41 // 'A'
+#define STK_SET_DEVICE 0x42 // 'B'
+#define STK_SET_DEVICE_EXT 0x45 // 'E'
+#define STK_LOAD_ADDRESS 0x55 // 'U'
+#define STK_UNIVERSAL 0x56 // 'V'
+#define STK_PROG_PAGE 0x64 // 'd'
+#define STK_READ_PAGE 0x74 // 't'
+#define STK_READ_SIGN 0x75 // 'u'
+
+/** Task to read in AVR910 commands from the CDC data OUT endpoint, process them, perform the required
actions
+ * and send the appropriate response back to the host.
+ */
+void CDC_Task(void)
+{
+ /* Select the OUT endpoint */
+ Endpoint_SelectEndpoint(CDC_RX_EPNUM);
+
+ /* Check if endpoint has a command in it sent from the host */
+ if (!(Endpoint_IsOUTReceived()))
+ return;
+
+ RX_LED_ON();
+ RxLEDPulse = TX_RX_LED_PULSE_PERIOD;
+
+ /* Read in the bootloader command (first byte sent from host) */
+ uint8_t Command = FetchNextCommandByte();
+
+ if (Command == 'E')
+ {
+ /* We nearly run out the bootloader timeout clock,
+ * leaving just a few hundred milliseconds so the
+ * bootloder has time to respond and service any
+ * subsequent requests */
+ Timeout = TIMEOUT_PERIOD - 500;
+
+ /* Re-enable RWW section - must be done here in case
+ * user has disabled verification on upload. */
+ boot_rww_enable_safe();
+
+ // Send confirmation byte back to the host
+ WriteNextResponseByte('\r');
+ }
+ else if (Command == 'T')
+ {
+ FetchNextCommandByte();
+
+ // Send confirmation byte back to the host
+ WriteNextResponseByte('\r');
+ }
+ else if ((Command == 'L') || (Command == 'P'))
+ {
+ // Send confirmation byte back to the host
+ WriteNextResponseByte('\r');
+ }
+ else if (Command == 't')
+ {
+ // Return ATMEGA128 part code - this is only to allow AVRProg to use the bootloader
+ WriteNextResponseByte(0x44);
+ WriteNextResponseByte(0x00);
+ }
+ else if (Command == 'a')
+ {
+ // Indicate auto-address increment is supported
+ WriteNextResponseByte('Y');
+ }
+ else if (Command == 'A')
+ {
+ // Set the current address to that given by the host
+ CurrAddress = (FetchNextCommandByte() << 9);
+ CurrAddress |= (FetchNextCommandByte() << 1);
+
+ // Send confirmation byte back to the host
+ WriteNextResponseByte('\r');
+ }
+ else if (Command == 'p')
+ {
+ // Indicate serial programmer back to the host
+ WriteNextResponseByte('S');
+ }
+ else if (Command == 'S')
+ {
+ // Write the 7-byte software identifier to the endpoint
+ for (uint8_t CurrByte = 0; CurrByte < 7; CurrByte++)
+ WriteNextResponseByte(SOFTWARE_IDENTIFIER[CurrByte]);
+ }
+ else if (Command == 'V')
+ {
+ WriteNextResponseByte('0' + BOOTLOADER_VERSION_MAJOR);
+ WriteNextResponseByte('0' + BOOTLOADER_VERSION_MINOR);
+ }
+ else if (Command == 's')
+ {
+ WriteNextResponseByte(AVR_SIGNATURE_3);
+ WriteNextResponseByte(AVR_SIGNATURE_2);
+ WriteNextResponseByte(AVR_SIGNATURE_1);
+ }
+ else if (Command == 'e')
+ {
+ // Clear the application section of flash
+ for (uint32_t CurrFlashAddress = 0; CurrFlashAddress < BOOT_START_ADDR; CurrFlashAddress +=
SPM_PAGESIZE)
+ {
+ boot_page_erase(CurrFlashAddress);
+ boot_spm_busy_wait();
+ boot_page_write(CurrFlashAddress);
+ boot_spm_busy_wait();
+ }
+
+ // Send confirmation byte back to the host
+ WriteNextResponseByte('\r');
+ }
+ #if !defined(NO_LOCK_BYTE_WRITE_SUPPORT)
+ else if (Command == 'l')
+ {
+ // Set the lock bits to those given by the host
+ boot_lock_bits_set(FetchNextCommandByte());
+
+ // Send confirmation byte back to the host
+ WriteNextResponseByte('\r');
+ }
+ #endif
+ else if (Command == 'r')
+ {
+ WriteNextResponseByte(boot_lock_fuse_bits_get(GET_LOCK_BITS));
+ }
+ else if (Command == 'F')
+ {
+ WriteNextResponseByte(boot_lock_fuse_bits_get(GET_LOW_FUSE_BITS));
+ }
+ else if (Command == 'N')
+ {
+ WriteNextResponseByte(boot_lock_fuse_bits_get(GET_HIGH_FUSE_BITS));
+ }
+ else if (Command == 'Q')
+ {
+ WriteNextResponseByte(boot_lock_fuse_bits_get(GET_EXTENDED_FUSE_BITS));
+ }
+ #if !defined(NO_BLOCK_SUPPORT)
+ else if (Command == 'b')
+ {
+ WriteNextResponseByte('Y');
+
+ // Send block size to the host
+ WriteNextResponseByte(SPM_PAGESIZE >> 8);
+ WriteNextResponseByte(SPM_PAGESIZE & 0xFF);
+ }
+ else if ((Command == 'B') || (Command == 'g'))
+ {
+ // Keep resetting the timeout counter if we're receiving self-programming instructions
+ Timeout = 0;
+ // Delegate the block write/read to a separate function for clarity
+ ReadWriteMemoryBlock(Command);
+ }
+ #endif
+ #if !defined(NO_FLASH_BYTE_SUPPORT)
+ else if (Command == 'C')
+ {
+ // Write the high byte to the current flash page
+ boot_page_fill(CurrAddress, FetchNextCommandByte());
+
+ // Send confirmation byte back to the host
+ WriteNextResponseByte('\r');
+ }
+ else if (Command == 'c')
+ {
+ // Write the low byte to the current flash page
+ boot_page_fill(CurrAddress | 0x01, FetchNextCommandByte());
+
+ // Increment the address
+ CurrAddress += 2;
+
+ // Send confirmation byte back to the host
+ WriteNextResponseByte('\r');
+ }
+ else if (Command == 'm')
+ {
+ // Commit the flash page to memory
+ boot_page_write(CurrAddress);
+
+ // Wait until write operation has completed
+ boot_spm_busy_wait();
+
+ // Send confirmation byte back to the host
+ WriteNextResponseByte('\r');
+ }
+ else if (Command == 'R')
+ {
+ #if (FLASHEND > 0xFFFF)
+ uint16_t ProgramWord = pgm_read_word_far(CurrAddress);
+ #else
+ uint16_t ProgramWord = pgm_read_word(CurrAddress);
+ #endif
+
+ WriteNextResponseByte(ProgramWord >> 8);
+ WriteNextResponseByte(ProgramWord & 0xFF);
+ }
+ #endif
+ #if !defined(NO_EEPROM_BYTE_SUPPORT)
+ else if (Command == 'D')
+ {
+ // Read the byte from the endpoint and write it to the EEPROM
+ eeprom_write_byte((uint8_t*)((intptr_t)(CurrAddress >> 1)), FetchNextCommandByte());
+
+ // Increment the address after use
+ CurrAddress += 2;
+
+ // Send confirmation byte back to the host
+ WriteNextResponseByte('\r');
+ }
+ else if (Command == 'd')
+ {
+ // Read the EEPROM byte and write it to the endpoint
+ WriteNextResponseByte(eeprom_read_byte((uint8_t*)((intptr_t)(CurrAddress >> 1))));
+
+ // Increment the address after use
+ CurrAddress += 2;
+ }
+ #endif
+ else if (Command != 27)
+ {
+ // Unknown (non-sync) command, return fail code
+ WriteNextResponseByte('?');
+ }
+
+
+ /* Select the IN endpoint */
+ Endpoint_SelectEndpoint(CDC_TX_EPNUM);
+
+ /* Remember if the endpoint is completely full before clearing it */
+ bool IsEndpointFull = !(Endpoint_IsReadWriteAllowed());
+
+ /* Send the endpoint data to the host */
+ Endpoint_ClearIN();
+
+ /* If a full endpoint's worth of data was sent, we need to send an empty packet afterwards to signal
end of transfer */
+ if (IsEndpointFull)
+ {
+ while (!(Endpoint_IsINReady()))
+ {
+ if (USB_DeviceState == DEVICE_STATE_Unattached)
+ return;
+ }
+
+ Endpoint_ClearIN();
+ }
+
+ /* Wait until the data has been sent to the host */
+ while (!(Endpoint_IsINReady()))
+ {
+ if (USB_DeviceState == DEVICE_STATE_Unattached)
+ return;
+ }
+
+ /* Select the OUT endpoint */
+ Endpoint_SelectEndpoint(CDC_RX_EPNUM);
+
+ /* Acknowledge the command from the host */
+ Endpoint_ClearOUT();
+}
diff --git a/hardware/arduino/bootloaders/caterina-Arduino_Robot/Caterina.h
b/hardware/arduino/bootloaders/caterina-Arduino_Robot/Caterina.h
index 5ce80fa..1668ef9 100644
--- a/hardware/arduino/bootloaders/caterina-Arduino_Robot/Caterina.h
+++ b/hardware/arduino/bootloaders/caterina-Arduino_Robot/Caterina.h
@@ -1,106 +1,105 @@
-/*
- LUFA Library
- Copyright (C) Dean Camera, 2011.
-
- dean [at] fourwalledcubicle [dot] com
- www.lufa-lib.org
-*/
-
-/*
- Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com)
-
- Permission to use, copy, modify, distribute, and sell this
- software and its documentation for any purpose is hereby granted
- without fee, provided that the above copyright notice appear in
- all copies and that both that the copyright notice and this
- permission notice and warranty disclaimer appear in supporting
- documentation, and that the name of the author not be used in
- advertising or publicity pertaining to distribution of the
- software without specific, written prior permission.
-
- The author disclaim all warranties with regard to this
- software, including all implied warranties of merchantability
- and fitness. In no event shall the author be liable for any
- special, indirect or consequential damages or any damages
- whatsoever resulting from loss of use, data or profits, whether
- in an action of contract, negligence or other tortious action,
- arising out of or in connection with the use or performance of
- this software.
-*/
-
-/** \file
- *
- * Header file for BootloaderCDC.c.
- */
-
-#ifndef _CDC_H_
-#define _CDC_H_
-
- /* Includes: */
- #include <avr/io.h>
- #include <avr/wdt.h>
- #include <avr/boot.h>
- #include <avr/eeprom.h>
- #include <avr/power.h>
- #include <avr/interrupt.h>
- #include <stdbool.h>
-
- #include "Descriptors.h"
-
- #include <LUFA/Drivers/USB/USB.h>
- /* Macros: */
- /** Version major of the CDC bootloader. */
- #define BOOTLOADER_VERSION_MAJOR 0x01
-
- /** Version minor of the CDC bootloader. */
- #define BOOTLOADER_VERSION_MINOR 0x00
-
- /** Hardware version major of the CDC bootloader. */
- #define BOOTLOADER_HWVERSION_MAJOR 0x01
-
- /** Hardware version minor of the CDC bootloader. */
- #define BOOTLOADER_HWVERSION_MINOR 0x00
-
- /** Eight character bootloader firmware identifier reported to the host when requested */
- #define SOFTWARE_IDENTIFIER "CATERINA"
-
- #define CPU_PRESCALE(n) (CLKPR = 0x80, CLKPR = (n))
- #define LED_SETUP() DDRC |= (1<<7); DDRB |= (1<<0); DDRD |= (1<<5);
- #define L_LED_OFF() PORTC &= ~(1<<7)
- #define L_LED_ON() PORTC |= (1<<7)
- #define L_LED_TOGGLE() PORTC ^= (1<<7)
- #if DEVICE_PID == 0x0037 // polarity of the RX and TX LEDs is reversed on the Micro
- #define TX_LED_OFF() PORTD &= ~(1<<5)
- #define TX_LED_ON() PORTD |= (1<<5)
- #define RX_LED_OFF() PORTB &= ~(1<<0)
- #define RX_LED_ON() PORTB |= (1<<0)
- #else
- #define TX_LED_OFF() PORTD |= (1<<5)
- #define TX_LED_ON() PORTD &= ~(1<<5)
- #define RX_LED_OFF() PORTB |= (1<<0)
- #define RX_LED_ON() PORTB &= ~(1<<0)
- #endif
-
- /* Type Defines: */
- /** Type define for a non-returning pointer to the start of the loaded application in flash
memory. */
- typedef void (*AppPtr_t)(void) ATTR_NO_RETURN;
-
- /* Function Prototypes: */
- void StartSketch(void);
- void LEDPulse(void);
-
- void CDC_Task(void);
- void SetupHardware(void);
-
- void EVENT_USB_Device_ConfigurationChanged(void);
-
- #if defined(INCLUDE_FROM_CATERINA_C) || defined(__DOXYGEN__)
- #if !defined(NO_BLOCK_SUPPORT)
- static void ReadWriteMemoryBlock(const uint8_t Command);
- #endif
- static uint8_t FetchNextCommandByte(void);
- static void WriteNextResponseByte(const uint8_t Response);
- #endif
-
-#endif
-
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2011.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaim all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ *
+ * Header file for BootloaderCDC.c.
+ */
+
+#ifndef _CDC_H_
+#define _CDC_H_
+
+ /* Includes: */
+ #include <avr/io.h>
+ #include <avr/wdt.h>
+ #include <avr/boot.h>
+ #include <avr/eeprom.h>
+ #include <avr/power.h>
+ #include <avr/interrupt.h>
+ #include <stdbool.h>
+
+ #include "Descriptors.h"
+
+ #include <LUFA/Drivers/USB/USB.h>
+ /* Macros: */
+ /** Version major of the CDC bootloader. */
+ #define BOOTLOADER_VERSION_MAJOR 0x01
+
+ /** Version minor of the CDC bootloader. */
+ #define BOOTLOADER_VERSION_MINOR 0x00
+
+ /** Hardware version major of the CDC bootloader. */
+ #define BOOTLOADER_HWVERSION_MAJOR 0x01
+
+ /** Hardware version minor of the CDC bootloader. */
+ #define BOOTLOADER_HWVERSION_MINOR 0x00
+
+ /** Eight character bootloader firmware identifier reported to the host when requested */
+ #define SOFTWARE_IDENTIFIER "CATERINA"
+
+ #define CPU_PRESCALE(n) (CLKPR = 0x80, CLKPR = (n))
+ #define LED_SETUP() DDRC |= (1<<7); DDRB |= (1<<0); DDRD |= (1<<5);
+ #define L_LED_OFF() PORTC &= ~(1<<7)
+ #define L_LED_ON() PORTC |= (1<<7)
+ #define L_LED_TOGGLE() PORTC ^= (1<<7)
+ #if DEVICE_PID == 0x0037 // polarity of the RX and TX LEDs is reversed on the Micro
+ #define TX_LED_OFF() PORTD &= ~(1<<5)
+ #define TX_LED_ON() PORTD |= (1<<5)
+ #define RX_LED_OFF() PORTB &= ~(1<<0)
+ #define RX_LED_ON() PORTB |= (1<<0)
+ #else
+ #define TX_LED_OFF() PORTD |= (1<<5)
+ #define TX_LED_ON() PORTD &= ~(1<<5)
+ #define RX_LED_OFF() PORTB |= (1<<0)
+ #define RX_LED_ON() PORTB &= ~(1<<0)
+ #endif
+
+ /* Type Defines: */
+ /** Type define for a non-returning pointer to the start of the loaded application in flash
memory. */
+ typedef void (*AppPtr_t)(void) ATTR_NO_RETURN;
+
+ /* Function Prototypes: */
+ void StartSketch(void);
+ void LEDPulse(void);
+
+ void CDC_Task(void);
+ void SetupHardware(void);
+
+ void EVENT_USB_Device_ConfigurationChanged(void);
+
+ #if defined(INCLUDE_FROM_CATERINA_C) || defined(__DOXYGEN__)
+ #if !defined(NO_BLOCK_SUPPORT)
+ static void ReadWriteMemoryBlock(const uint8_t Command);
+ #endif
+ static uint8_t FetchNextCommandByte(void);
+ static void WriteNextResponseByte(const uint8_t Response);
+ #endif
+
+#endif
diff --git a/hardware/arduino/bootloaders/caterina-Arduino_Robot/Descriptors.c
b/hardware/arduino/bootloaders/caterina-Arduino_Robot/Descriptors.c
index 57f39d9..c74c2a3 100644
--- a/hardware/arduino/bootloaders/caterina-Arduino_Robot/Descriptors.c
+++ b/hardware/arduino/bootloaders/caterina-Arduino_Robot/Descriptors.c
@@ -1,270 +1,269 @@
-/*
- LUFA Library
- Copyright (C) Dean Camera, 2011.
-
- dean [at] fourwalledcubicle [dot] com
- www.lufa-lib.org
-*/
-
-/*
- Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com)
-
- Permission to use, copy, modify, distribute, and sell this
- software and its documentation for any purpose is hereby granted
- without fee, provided that the above copyright notice appear in
- all copies and that both that the copyright notice and this
- permission notice and warranty disclaimer appear in supporting
- documentation, and that the name of the author not be used in
- advertising or publicity pertaining to distribution of the
- software without specific, written prior permission.
-
- The author disclaim all warranties with regard to this
- software, including all implied warranties of merchantability
- and fitness. In no event shall the author be liable for any
- special, indirect or consequential damages or any damages
- whatsoever resulting from loss of use, data or profits, whether
- in an action of contract, negligence or other tortious action,
- arising out of or in connection with the use or performance of
- this software.
-*/
-
-/** \file
- *
- * USB Device Descriptors, for library use when in USB device mode. Descriptors are special
- * computer-readable structures which the host requests upon device enumeration, to determine
- * the device's capabilities and functions.
- */
-
-#include "Descriptors.h"
-
-/** Device descriptor structure. This descriptor, located in SRAM memory, describes the overall
- * device characteristics, including the supported USB version, control endpoint size and the
- * number of device configurations. The descriptor is read out by the USB host when the enumeration
- * process begins.
- */
-const USB_Descriptor_Device_t DeviceDescriptor =
-{
- .Header = {.Size = sizeof(USB_Descriptor_Device_t), .Type = DTYPE_Device},
-
- .USBSpecification = VERSION_BCD(01.10),
- .Class = CDC_CSCP_CDCClass,
- .SubClass = CDC_CSCP_NoSpecificSubclass,
- .Protocol = CDC_CSCP_NoSpecificProtocol,
-
- .Endpoint0Size = FIXED_CONTROL_ENDPOINT_SIZE,
-
- .VendorID = DEVICE_VID,
- .ProductID = DEVICE_PID,
- .ReleaseNumber = VERSION_BCD(00.01),
-
- .ManufacturerStrIndex = 0x02,
- .ProductStrIndex = 0x01,
- .SerialNumStrIndex = NO_DESCRIPTOR,
-
- .NumberOfConfigurations = FIXED_NUM_CONFIGURATIONS
-};
-
-/** Configuration descriptor structure. This descriptor, located in SRAM memory, describes the usage
- * of the device in one of its supported configurations, including information about any device interfaces
- * and endpoints. The descriptor is read out by the USB host during the enumeration process when selecting
- * a configuration so that the host may correctly communicate with the USB device.
- */
-const USB_Descriptor_Configuration_t ConfigurationDescriptor =
-{
- .Config =
- {
- .Header = {.Size = sizeof(USB_Descriptor_Configuration_Header_t),
.Type = DTYPE_Configuration},
-
- .TotalConfigurationSize = sizeof(USB_Descriptor_Configuration_t),
- .TotalInterfaces = 2,
-
- .ConfigurationNumber = 1,
- .ConfigurationStrIndex = NO_DESCRIPTOR,
-
- .ConfigAttributes = USB_CONFIG_ATTR_BUSPOWERED,
-
- .MaxPowerConsumption = USB_CONFIG_POWER_MA(100)
- },
-
- .CDC_CCI_Interface =
- {
- .Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type =
DTYPE_Interface},
-
- .InterfaceNumber = 0,
- .AlternateSetting = 0,
-
- .TotalEndpoints = 1,
-
- .Class = CDC_CSCP_CDCClass,
- .SubClass = CDC_CSCP_ACMSubclass,
- .Protocol = CDC_CSCP_ATCommandProtocol,
-
- .InterfaceStrIndex = NO_DESCRIPTOR
- },
-
- .CDC_Functional_Header =
- {
- .Header = {.Size = sizeof(USB_CDC_Descriptor_FunctionalHeader_t),
.Type = DTYPE_CSInterface},
- .Subtype = 0x00,
-
- .CDCSpecification = VERSION_BCD(01.10),
- },
-
- .CDC_Functional_ACM =
- {
- .Header = {.Size = sizeof(USB_CDC_Descriptor_FunctionalACM_t), .Type
= DTYPE_CSInterface},
- .Subtype = 0x02,
-
- .Capabilities = 0x04,
- },
-
- .CDC_Functional_Union =
- {
- .Header = {.Size = sizeof(USB_CDC_Descriptor_FunctionalUnion_t),
.Type = DTYPE_CSInterface},
- .Subtype = 0x06,
-
- .MasterInterfaceNumber = 0,
- .SlaveInterfaceNumber = 1,
- },
-
- .CDC_NotificationEndpoint =
- {
- .Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type =
DTYPE_Endpoint},
-
- .EndpointAddress = (ENDPOINT_DIR_IN | CDC_NOTIFICATION_EPNUM),
- .Attributes = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC |
ENDPOINT_USAGE_DATA),
- .EndpointSize = CDC_NOTIFICATION_EPSIZE,
- .PollingIntervalMS = 0xFF
- },
-
- .CDC_DCI_Interface =
- {
- .Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type =
DTYPE_Interface},
-
- .InterfaceNumber = 1,
- .AlternateSetting = 0,
-
- .TotalEndpoints = 2,
-
- .Class = CDC_CSCP_CDCDataClass,
- .SubClass = CDC_CSCP_NoDataSubclass,
- .Protocol = CDC_CSCP_NoDataProtocol,
-
- .InterfaceStrIndex = NO_DESCRIPTOR
- },
-
- .CDC_DataOutEndpoint =
- {
- .Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type =
DTYPE_Endpoint},
-
- .EndpointAddress = (ENDPOINT_DIR_OUT | CDC_RX_EPNUM),
- .Attributes = (EP_TYPE_BULK | ENDPOINT_ATTR_NO_SYNC |
ENDPOINT_USAGE_DATA),
- .EndpointSize = CDC_TXRX_EPSIZE,
- .PollingIntervalMS = 0x01
- },
-
- .CDC_DataInEndpoint =
- {
- .Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type =
DTYPE_Endpoint},
-
- .EndpointAddress = (ENDPOINT_DIR_IN | CDC_TX_EPNUM),
- .Attributes = (EP_TYPE_BULK | ENDPOINT_ATTR_NO_SYNC |
ENDPOINT_USAGE_DATA),
- .EndpointSize = CDC_TXRX_EPSIZE,
- .PollingIntervalMS = 0x01
- }
-};
-
-/** Language descriptor structure. This descriptor, located in SRAM memory, is returned when the host
requests
- * the string descriptor with index 0 (the first index). It is actually an array of 16-bit integers, which
indicate
- * via the language ID table available at USB.org what languages the device supports for its string
descriptors.
- */
-const USB_Descriptor_String_t LanguageString =
-{
- .Header = {.Size = USB_STRING_LEN(1), .Type = DTYPE_String},
-
- .UnicodeString = {LANGUAGE_ID_ENG}
-};
-
-/** Product descriptor string. This is a Unicode string containing the product's details in human readable
form,
- * and is read out upon request by the host when the appropriate string ID is requested, listed in the
Device
- * Descriptor.
- */
-const USB_Descriptor_String_t ProductString =
-{
- .Header = {.Size = USB_STRING_LEN(19), .Type = DTYPE_String},
-
- #if DEVICE_PID == 0x0036
- .UnicodeString = L"Arduino Leonardo"
- #elif DEVICE_PID == 0x0037
- .UnicodeString = L"Arduino Micro "
- #elif DEVICE_PID == 0x0038
- .UnicodeString = L"Robot Control Board"
- #elif DEVICE_PID == 0x0039
- .UnicodeString = L"Robot Motor Board "
- #elif DEVICE_PID == 0x003C
- .UnicodeString = L"Arduino Esplora "
- #else
- .UnicodeString = L"USB IO board "
- #endif
-};
-
-const USB_Descriptor_String_t ManufacturerString =
-{
- .Header = {.Size = USB_STRING_LEN(11), .Type = DTYPE_String},
-
- #if DEVICE_VID == 0x2341
- .UnicodeString = L"Arduino LLC"
- #else
- .UnicodeString = L"Unknown "
- #endif
-};
-
-/** This function is called by the library when in device mode, and must be overridden (see LUFA library
"USB Descriptors"
- * documentation) by the application code so that the address and size of a requested descriptor can be
given
- * to the USB library. When the device receives a Get Descriptor request on the control endpoint, this
function
- * is called so that the descriptor details can be passed back and the appropriate descriptor sent back to
the
- * USB host.
- */
-uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue,
- const uint8_t wIndex,
- const void** const DescriptorAddress)
-{
- const uint8_t DescriptorType = (wValue >> 8);
- const uint8_t DescriptorNumber = (wValue & 0xFF);
-
- const void* Address = NULL;
- uint16_t Size = NO_DESCRIPTOR;
-
- switch (DescriptorType)
- {
- case DTYPE_Device:
- Address = &DeviceDescriptor;
- Size = sizeof(USB_Descriptor_Device_t);
- break;
- case DTYPE_Configuration:
- Address = &ConfigurationDescriptor;
- Size = sizeof(USB_Descriptor_Configuration_t);
- break;
- case DTYPE_String:
- if (!(DescriptorNumber))
- {
- Address = &LanguageString;
- Size = LanguageString.Header.Size;
- }
- else if (DescriptorNumber == DeviceDescriptor.ProductStrIndex)
- {
- Address = &ProductString;
- Size = ProductString.Header.Size;
- } else if (DescriptorNumber == DeviceDescriptor.ManufacturerStrIndex)
- {
- Address = &ManufacturerString;
- Size = ManufacturerString.Header.Size;
- }
-
- break;
- }
-
- *DescriptorAddress = Address;
- return Size;
-}
-
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2011.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaim all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ *
+ * USB Device Descriptors, for library use when in USB device mode. Descriptors are special
+ * computer-readable structures which the host requests upon device enumeration, to determine
+ * the device's capabilities and functions.
+ */
+
+#include "Descriptors.h"
+
+/** Device descriptor structure. This descriptor, located in SRAM memory, describes the overall
+ * device characteristics, including the supported USB version, control endpoint size and the
+ * number of device configurations. The descriptor is read out by the USB host when the enumeration
+ * process begins.
+ */
+const USB_Descriptor_Device_t DeviceDescriptor =
+{
+ .Header = {.Size = sizeof(USB_Descriptor_Device_t), .Type = DTYPE_Device},
+
+ .USBSpecification = VERSION_BCD(01.10),
+ .Class = CDC_CSCP_CDCClass,
+ .SubClass = CDC_CSCP_NoSpecificSubclass,
+ .Protocol = CDC_CSCP_NoSpecificProtocol,
+
+ .Endpoint0Size = FIXED_CONTROL_ENDPOINT_SIZE,
+
+ .VendorID = DEVICE_VID,
+ .ProductID = DEVICE_PID,
+ .ReleaseNumber = VERSION_BCD(00.01),
+
+ .ManufacturerStrIndex = 0x02,
+ .ProductStrIndex = 0x01,
+ .SerialNumStrIndex = NO_DESCRIPTOR,
+
+ .NumberOfConfigurations = FIXED_NUM_CONFIGURATIONS
+};
+
+/** Configuration descriptor structure. This descriptor, located in SRAM memory, describes the usage
+ * of the device in one of its supported configurations, including information about any device interfaces
+ * and endpoints. The descriptor is read out by the USB host during the enumeration process when selecting
+ * a configuration so that the host may correctly communicate with the USB device.
+ */
+const USB_Descriptor_Configuration_t ConfigurationDescriptor =
+{
+ .Config =
+ {
+ .Header = {.Size = sizeof(USB_Descriptor_Configuration_Header_t),
.Type = DTYPE_Configuration},
+
+ .TotalConfigurationSize = sizeof(USB_Descriptor_Configuration_t),
+ .TotalInterfaces = 2,
+
+ .ConfigurationNumber = 1,
+ .ConfigurationStrIndex = NO_DESCRIPTOR,
+
+ .ConfigAttributes = USB_CONFIG_ATTR_BUSPOWERED,
+
+ .MaxPowerConsumption = USB_CONFIG_POWER_MA(100)
+ },
+
+ .CDC_CCI_Interface =
+ {
+ .Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type =
DTYPE_Interface},
+
+ .InterfaceNumber = 0,
+ .AlternateSetting = 0,
+
+ .TotalEndpoints = 1,
+
+ .Class = CDC_CSCP_CDCClass,
+ .SubClass = CDC_CSCP_ACMSubclass,
+ .Protocol = CDC_CSCP_ATCommandProtocol,
+
+ .InterfaceStrIndex = NO_DESCRIPTOR
+ },
+
+ .CDC_Functional_Header =
+ {
+ .Header = {.Size = sizeof(USB_CDC_Descriptor_FunctionalHeader_t),
.Type = DTYPE_CSInterface},
+ .Subtype = 0x00,
+
+ .CDCSpecification = VERSION_BCD(01.10),
+ },
+
+ .CDC_Functional_ACM =
+ {
+ .Header = {.Size = sizeof(USB_CDC_Descriptor_FunctionalACM_t), .Type
= DTYPE_CSInterface},
+ .Subtype = 0x02,
+
+ .Capabilities = 0x04,
+ },
+
+ .CDC_Functional_Union =
+ {
+ .Header = {.Size = sizeof(USB_CDC_Descriptor_FunctionalUnion_t),
.Type = DTYPE_CSInterface},
+ .Subtype = 0x06,
+
+ .MasterInterfaceNumber = 0,
+ .SlaveInterfaceNumber = 1,
+ },
+
+ .CDC_NotificationEndpoint =
+ {
+ .Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type =
DTYPE_Endpoint},
+
+ .EndpointAddress = (ENDPOINT_DIR_IN | CDC_NOTIFICATION_EPNUM),
+ .Attributes = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC |
ENDPOINT_USAGE_DATA),
+ .EndpointSize = CDC_NOTIFICATION_EPSIZE,
+ .PollingIntervalMS = 0xFF
+ },
+
+ .CDC_DCI_Interface =
+ {
+ .Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type =
DTYPE_Interface},
+
+ .InterfaceNumber = 1,
+ .AlternateSetting = 0,
+
+ .TotalEndpoints = 2,
+
+ .Class = CDC_CSCP_CDCDataClass,
+ .SubClass = CDC_CSCP_NoDataSubclass,
+ .Protocol = CDC_CSCP_NoDataProtocol,
+
+ .InterfaceStrIndex = NO_DESCRIPTOR
+ },
+
+ .CDC_DataOutEndpoint =
+ {
+ .Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type =
DTYPE_Endpoint},
+
+ .EndpointAddress = (ENDPOINT_DIR_OUT | CDC_RX_EPNUM),
+ .Attributes = (EP_TYPE_BULK | ENDPOINT_ATTR_NO_SYNC |
ENDPOINT_USAGE_DATA),
+ .EndpointSize = CDC_TXRX_EPSIZE,
+ .PollingIntervalMS = 0x01
+ },
+
+ .CDC_DataInEndpoint =
+ {
+ .Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type =
DTYPE_Endpoint},
+
+ .EndpointAddress = (ENDPOINT_DIR_IN | CDC_TX_EPNUM),
+ .Attributes = (EP_TYPE_BULK | ENDPOINT_ATTR_NO_SYNC |
ENDPOINT_USAGE_DATA),
+ .EndpointSize = CDC_TXRX_EPSIZE,
+ .PollingIntervalMS = 0x01
+ }
+};
+
+/** Language descriptor structure. This descriptor, located in SRAM memory, is returned when the host
requests
+ * the string descriptor with index 0 (the first index). It is actually an array of 16-bit integers, which
indicate
+ * via the language ID table available at USB.org what languages the device supports for its string
descriptors.
+ */
+const USB_Descriptor_String_t LanguageString =
+{
+ .Header = {.Size = USB_STRING_LEN(1), .Type = DTYPE_String},
+
+ .UnicodeString = {LANGUAGE_ID_ENG}
+};
+
+/** Product descriptor string. This is a Unicode string containing the product's details in human readable
form,
+ * and is read out upon request by the host when the appropriate string ID is requested, listed in the
Device
+ * Descriptor.
+ */
+const USB_Descriptor_String_t ProductString =
+{
+ .Header = {.Size = USB_STRING_LEN(19), .Type = DTYPE_String},
+
+ #if DEVICE_PID == 0x0036
+ .UnicodeString = L"Arduino Leonardo"
+ #elif DEVICE_PID == 0x0037
+ .UnicodeString = L"Arduino Micro "
+ #elif DEVICE_PID == 0x0038
+ .UnicodeString = L"Robot Control Board"
+ #elif DEVICE_PID == 0x0039
+ .UnicodeString = L"Robot Motor Board "
+ #elif DEVICE_PID == 0x003C
+ .UnicodeString = L"Arduino Esplora "
+ #else
+ .UnicodeString = L"USB IO board "
+ #endif
+};
+
+const USB_Descriptor_String_t ManufacturerString =
+{
+ .Header = {.Size = USB_STRING_LEN(11), .Type = DTYPE_String},
+
+ #if DEVICE_VID == 0x2341
+ .UnicodeString = L"Arduino LLC"
+ #else
+ .UnicodeString = L"Unknown "
+ #endif
+};
+
+/** This function is called by the library when in device mode, and must be overridden (see LUFA library
"USB Descriptors"
+ * documentation) by the application code so that the address and size of a requested descriptor can be
given
+ * to the USB library. When the device receives a Get Descriptor request on the control endpoint, this
function
+ * is called so that the descriptor details can be passed back and the appropriate descriptor sent back to
the
+ * USB host.
+ */
+uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue,
+ const uint8_t wIndex,
+ const void** const DescriptorAddress)
+{
+ const uint8_t DescriptorType = (wValue >> 8);
+ const uint8_t DescriptorNumber = (wValue & 0xFF);
+
+ const void* Address = NULL;
+ uint16_t Size = NO_DESCRIPTOR;
+
+ switch (DescriptorType)
+ {
+ case DTYPE_Device:
+ Address = &DeviceDescriptor;
+ Size = sizeof(USB_Descriptor_Device_t);
+ break;
+ case DTYPE_Configuration:
+ Address = &ConfigurationDescriptor;
+ Size = sizeof(USB_Descriptor_Configuration_t);
+ break;
+ case DTYPE_String:
+ if (!(DescriptorNumber))
+ {
+ Address = &LanguageString;
+ Size = LanguageString.Header.Size;
+ }
+ else if (DescriptorNumber == DeviceDescriptor.ProductStrIndex)
+ {
+ Address = &ProductString;
+ Size = ProductString.Header.Size;
+ } else if (DescriptorNumber == DeviceDescriptor.ManufacturerStrIndex)
+ {
+ Address = &ManufacturerString;
+ Size = ManufacturerString.Header.Size;
+ }
+
+ break;
+ }
+
+ *DescriptorAddress = Address;
+ return Size;
+}
diff --git a/hardware/arduino/bootloaders/caterina-Arduino_Robot/Descriptors.h
b/hardware/arduino/bootloaders/caterina-Arduino_Robot/Descriptors.h
index 94091ae..f08104b 100644
--- a/hardware/arduino/bootloaders/caterina-Arduino_Robot/Descriptors.h
+++ b/hardware/arduino/bootloaders/caterina-Arduino_Robot/Descriptors.h
@@ -1,139 +1,138 @@
-/*
- LUFA Library
- Copyright (C) Dean Camera, 2011.
-
- dean [at] fourwalledcubicle [dot] com
- www.lufa-lib.org
-*/
-
-/*
- Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com)
-
- Permission to use, copy, modify, distribute, and sell this
- software and its documentation for any purpose is hereby granted
- without fee, provided that the above copyright notice appear in
- all copies and that both that the copyright notice and this
- permission notice and warranty disclaimer appear in supporting
- documentation, and that the name of the author not be used in
- advertising or publicity pertaining to distribution of the
- software without specific, written prior permission.
-
- The author disclaim all warranties with regard to this
- software, including all implied warranties of merchantability
- and fitness. In no event shall the author be liable for any
- special, indirect or consequential damages or any damages
- whatsoever resulting from loss of use, data or profits, whether
- in an action of contract, negligence or other tortious action,
- arising out of or in connection with the use or performance of
- this software.
-*/
-
-/** \file
- *
- * Header file for Descriptors.c.
- */
-
-#ifndef _DESCRIPTORS_H_
-#define _DESCRIPTORS_H_
-
- /* Includes: */
- #include <LUFA/Drivers/USB/USB.h>
-
- /* Macros: */
- #if defined(__AVR_AT90USB1287__)
- #define AVR_SIGNATURE_1 0x1E
- #define AVR_SIGNATURE_2 0x97
- #define AVR_SIGNATURE_3 0x82
- #elif defined(__AVR_AT90USB647__)
- #define AVR_SIGNATURE_1 0x1E
- #define AVR_SIGNATURE_2 0x96
- #define AVR_SIGNATURE_3 0x82
- #elif defined(__AVR_AT90USB1286__)
- #define AVR_SIGNATURE_1 0x1E
- #define AVR_SIGNATURE_2 0x97
- #define AVR_SIGNATURE_3 0x82
- #elif defined(__AVR_AT90USB646__)
- #define AVR_SIGNATURE_1 0x1E
- #define AVR_SIGNATURE_2 0x96
- #define AVR_SIGNATURE_3 0x82
- #elif defined(__AVR_ATmega32U6__)
- #define AVR_SIGNATURE_1 0x1E
- #define AVR_SIGNATURE_2 0x95
- #define AVR_SIGNATURE_3 0x88
- #elif defined(__AVR_ATmega32U4__)
- #define AVR_SIGNATURE_1 0x1E
- #define AVR_SIGNATURE_2 0x95
- #define AVR_SIGNATURE_3 0x87
- #elif defined(__AVR_ATmega16U4__)
- #define AVR_SIGNATURE_1 0x1E
- #define AVR_SIGNATURE_2 0x94
- #define AVR_SIGNATURE_3 0x88
- #elif defined(__AVR_ATmega32U2__)
- #define AVR_SIGNATURE_1 0x1E
- #define AVR_SIGNATURE_2 0x95
- #define AVR_SIGNATURE_3 0x8A
- #elif defined(__AVR_ATmega16U2__)
- #define AVR_SIGNATURE_1 0x1E
- #define AVR_SIGNATURE_2 0x94
- #define AVR_SIGNATURE_3 0x89
- #elif defined(__AVR_AT90USB162__)
- #define AVR_SIGNATURE_1 0x1E
- #define AVR_SIGNATURE_2 0x94
- #define AVR_SIGNATURE_3 0x82
- #elif defined(__AVR_ATmega8U2__)
- #define AVR_SIGNATURE_1 0x1E
- #define AVR_SIGNATURE_2 0x93
- #define AVR_SIGNATURE_3 0x89
- #elif defined(__AVR_AT90USB82__)
- #define AVR_SIGNATURE_1 0x1E
- #define AVR_SIGNATURE_2 0x94
- #define AVR_SIGNATURE_3 0x82
- #else
- #error The selected AVR part is not currently supported by this bootloader.
- #endif
-
- /** Endpoint number for the CDC control interface event notification endpoint. */
- #define CDC_NOTIFICATION_EPNUM 2
-
- /** Endpoint number for the CDC data interface TX (data IN) endpoint. */
- #define CDC_TX_EPNUM 3
-
- /** Endpoint number for the CDC data interface RX (data OUT) endpoint. */
- #define CDC_RX_EPNUM 4
-
- /** Size of the CDC data interface TX and RX data endpoint banks, in bytes. */
- #define CDC_TXRX_EPSIZE 16
-
- /** Size of the CDC control interface notification endpoint bank, in bytes. */
- #define CDC_NOTIFICATION_EPSIZE 8
-
- /* Type Defines: */
- /** Type define for the device configuration descriptor structure. This must be defined in the
- * application code, as the configuration descriptor contains several sub-descriptors which
- * vary between devices, and which describe the device's usage to the host.
- */
- typedef struct
- {
- USB_Descriptor_Configuration_Header_t Config;
-
- // CDC Control Interface
- USB_Descriptor_Interface_t CDC_CCI_Interface;
- USB_CDC_Descriptor_FunctionalHeader_t CDC_Functional_Header;
- USB_CDC_Descriptor_FunctionalACM_t CDC_Functional_ACM;
- USB_CDC_Descriptor_FunctionalUnion_t CDC_Functional_Union;
- USB_Descriptor_Endpoint_t CDC_NotificationEndpoint;
-
- // CDC Data Interface
- USB_Descriptor_Interface_t CDC_DCI_Interface;
- USB_Descriptor_Endpoint_t CDC_DataOutEndpoint;
- USB_Descriptor_Endpoint_t CDC_DataInEndpoint;
- } USB_Descriptor_Configuration_t;
-
- /* Function Prototypes: */
- uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue,
- const uint8_t wIndex,
- const void** const DescriptorAddress)
- ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(3);
-
-#endif
-
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2011.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaim all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ *
+ * Header file for Descriptors.c.
+ */
+
+#ifndef _DESCRIPTORS_H_
+#define _DESCRIPTORS_H_
+
+ /* Includes: */
+ #include <LUFA/Drivers/USB/USB.h>
+
+ /* Macros: */
+ #if defined(__AVR_AT90USB1287__)
+ #define AVR_SIGNATURE_1 0x1E
+ #define AVR_SIGNATURE_2 0x97
+ #define AVR_SIGNATURE_3 0x82
+ #elif defined(__AVR_AT90USB647__)
+ #define AVR_SIGNATURE_1 0x1E
+ #define AVR_SIGNATURE_2 0x96
+ #define AVR_SIGNATURE_3 0x82
+ #elif defined(__AVR_AT90USB1286__)
+ #define AVR_SIGNATURE_1 0x1E
+ #define AVR_SIGNATURE_2 0x97
+ #define AVR_SIGNATURE_3 0x82
+ #elif defined(__AVR_AT90USB646__)
+ #define AVR_SIGNATURE_1 0x1E
+ #define AVR_SIGNATURE_2 0x96
+ #define AVR_SIGNATURE_3 0x82
+ #elif defined(__AVR_ATmega32U6__)
+ #define AVR_SIGNATURE_1 0x1E
+ #define AVR_SIGNATURE_2 0x95
+ #define AVR_SIGNATURE_3 0x88
+ #elif defined(__AVR_ATmega32U4__)
+ #define AVR_SIGNATURE_1 0x1E
+ #define AVR_SIGNATURE_2 0x95
+ #define AVR_SIGNATURE_3 0x87
+ #elif defined(__AVR_ATmega16U4__)
+ #define AVR_SIGNATURE_1 0x1E
+ #define AVR_SIGNATURE_2 0x94
+ #define AVR_SIGNATURE_3 0x88
+ #elif defined(__AVR_ATmega32U2__)
+ #define AVR_SIGNATURE_1 0x1E
+ #define AVR_SIGNATURE_2 0x95
+ #define AVR_SIGNATURE_3 0x8A
+ #elif defined(__AVR_ATmega16U2__)
+ #define AVR_SIGNATURE_1 0x1E
+ #define AVR_SIGNATURE_2 0x94
+ #define AVR_SIGNATURE_3 0x89
+ #elif defined(__AVR_AT90USB162__)
+ #define AVR_SIGNATURE_1 0x1E
+ #define AVR_SIGNATURE_2 0x94
+ #define AVR_SIGNATURE_3 0x82
+ #elif defined(__AVR_ATmega8U2__)
+ #define AVR_SIGNATURE_1 0x1E
+ #define AVR_SIGNATURE_2 0x93
+ #define AVR_SIGNATURE_3 0x89
+ #elif defined(__AVR_AT90USB82__)
+ #define AVR_SIGNATURE_1 0x1E
+ #define AVR_SIGNATURE_2 0x94
+ #define AVR_SIGNATURE_3 0x82
+ #else
+ #error The selected AVR part is not currently supported by this bootloader.
+ #endif
+
+ /** Endpoint number for the CDC control interface event notification endpoint. */
+ #define CDC_NOTIFICATION_EPNUM 2
+
+ /** Endpoint number for the CDC data interface TX (data IN) endpoint. */
+ #define CDC_TX_EPNUM 3
+
+ /** Endpoint number for the CDC data interface RX (data OUT) endpoint. */
+ #define CDC_RX_EPNUM 4
+
+ /** Size of the CDC data interface TX and RX data endpoint banks, in bytes. */
+ #define CDC_TXRX_EPSIZE 16
+
+ /** Size of the CDC control interface notification endpoint bank, in bytes. */
+ #define CDC_NOTIFICATION_EPSIZE 8
+
+ /* Type Defines: */
+ /** Type define for the device configuration descriptor structure. This must be defined in the
+ * application code, as the configuration descriptor contains several sub-descriptors which
+ * vary between devices, and which describe the device's usage to the host.
+ */
+ typedef struct
+ {
+ USB_Descriptor_Configuration_Header_t Config;
+
+ // CDC Control Interface
+ USB_Descriptor_Interface_t CDC_CCI_Interface;
+ USB_CDC_Descriptor_FunctionalHeader_t CDC_Functional_Header;
+ USB_CDC_Descriptor_FunctionalACM_t CDC_Functional_ACM;
+ USB_CDC_Descriptor_FunctionalUnion_t CDC_Functional_Union;
+ USB_Descriptor_Endpoint_t CDC_NotificationEndpoint;
+
+ // CDC Data Interface
+ USB_Descriptor_Interface_t CDC_DCI_Interface;
+ USB_Descriptor_Endpoint_t CDC_DataOutEndpoint;
+ USB_Descriptor_Endpoint_t CDC_DataInEndpoint;
+ } USB_Descriptor_Configuration_t;
+
+ /* Function Prototypes: */
+ uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue,
+ const uint8_t wIndex,
+ const void** const DescriptorAddress)
+ ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(3);
+
+#endif
diff --git a/hardware/arduino/bootloaders/caterina-LilyPadUSB/Caterina.c
b/hardware/arduino/bootloaders/caterina-LilyPadUSB/Caterina.c
index 9a59081..34d9087 100644
--- a/hardware/arduino/bootloaders/caterina-LilyPadUSB/Caterina.c
+++ b/hardware/arduino/bootloaders/caterina-LilyPadUSB/Caterina.c
@@ -1,780 +1,779 @@
-/*
- LUFA Library
- Copyright (C) Dean Camera, 2011.
-
- dean [at] fourwalledcubicle [dot] com
- www.lufa-lib.org
-*/
-
-/*
- Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com)
-
- Permission to use, copy, modify, distribute, and sell this
- software and its documentation for any purpose is hereby granted
- without fee, provided that the above copyright notice appear in
- all copies and that both that the copyright notice and this
- permission notice and warranty disclaimer appear in supporting
- documentation, and that the name of the author not be used in
- advertising or publicity pertaining to distribution of the
- software without specific, written prior permission.
-
- The author disclaim all warranties with regard to this
- software, including all implied warranties of merchantability
- and fitness. In no event shall the author be liable for any
- special, indirect or consequential damages or any damages
- whatsoever resulting from loss of use, data or profits, whether
- in an action of contract, negligence or other tortious action,
- arising out of or in connection with the use or performance of
- this software.
-*/
-
-/** \file
- *
- * Main source file for the CDC class bootloader. This file contains the complete bootloader logic.
- */
-
-#define INCLUDE_FROM_CATERINA_C
-#include "Caterina.h"
-
-/** Contains the current baud rate and other settings of the first virtual serial port. This must be
retained as some
- * operating systems will not open the port unless the settings can be set successfully.
- */
-static CDC_LineEncoding_t LineEncoding = { .BaudRateBPS = 0,
- .CharFormat = CDC_LINEENCODING_OneStopBit,
- .ParityType = CDC_PARITY_None,
- .DataBits = 8 };
-
-/** Current address counter. This stores the current address of the FLASH or EEPROM as set by the host,
- * and is used when reading or writing to the AVRs memory (either FLASH or EEPROM depending on the issued
- * command.)
- */
-static uint32_t CurrAddress;
-
-/** Flag to indicate if the bootloader should be running, or should exit and allow the application code to
run
- * via a watchdog reset. When cleared the bootloader will exit, starting the watchdog and entering an
infinite
- * loop until the AVR restarts and the application runs.
- */
-static bool RunBootloader = true;
-
-/* Pulse generation counters to keep track of the time remaining for each pulse type */
-#define TX_RX_LED_PULSE_PERIOD 100
-uint16_t TxLEDPulse = 0; // time remaining for Tx LED pulse
-uint16_t RxLEDPulse = 0; // time remaining for Rx LED pulse
-
-/* Bootloader timeout timer */
-// MAH 8/15/12- change so timeouts work properly when the chip is running at 8MHz instead of 16.
-#define TIMEOUT_PERIOD 4000
-#define EXT_RESET_TIMEOUT_PERIOD 375
-
-
-/*********************************************************************************************************
-LilyPadUSB bootloader code
-The LilyPadUSB bootloader has been changed to remove the 8-second delay after external reset which is in
-the Leonardo. To enter the bootloader, the user should execute TWO external resets within 750 ms; that is,
-press the reset button twice, quickly.\
-
-Some other changes were made to allow this code to compile tightly enough to fit in the alloted 4k of
-bootloader space.
-*/
-// MAH 8/15/12- added this flag to replace the bulky program memory reads to check for the presence of a
sketch
-// at the top of the memory space.
-static bool sketchPresent = false;
-
-// MAH 8/15/12- make this volatile, since we modify it in one place and read it in another, we want to make
-// sure we're always working on the copy in memory and not an erroneous value stored in a cache somewhere.
-// This variable stores the length of time we've been in the bootloader when waiting for the 8 second delay.
-volatile uint16_t Timeout = 0;
-// MAH 8/15/12- added this for delay during startup. Did not use existing Timeout value b/c it only
increments
-// when there's a sketch at the top of the memory.
-volatile uint16_t resetTimeout = 0;
-
-// MAH 8/15/12- let's make this an 8-bit value instead of 16- that saves on memory because 16-bit addition
and
-// comparison compiles to bulkier code. Note that this does *not* require a change to the Arduino core-
we're
-// just sort of ignoring the extra byte that the Arduino core puts at the next location.
-uint8_t bootKey = 0x77;
-volatile uint8_t *const bootKeyPtr = (volatile uint8_t *)0x0800;
-
-// StartSketch() is called to clean up our mess before passing execution to the sketch.
-void StartSketch(void)
-{
- cli();
-
- /* Undo TIMER1 setup and clear the count before running the sketch */
- TIMSK1 = 0;
- TCCR1B = 0;
-
- /* Relocate the interrupt vector table to the application section */
- MCUCR = (1 << IVCE);
- MCUCR = 0;
-
- L_LED_OFF();
- TX_LED_OFF();
- RX_LED_OFF();
-
- /* jump to beginning of application space */
- __asm__ volatile("jmp 0x0000");
-
-}
-
-uint16_t LLEDPulse;
-
-/** Main program entry point. This routine configures the hardware required by the bootloader, then
continuously
- * runs the bootloader processing routine until it times out or is instructed to exit.
- */
-int main(void)
-{
- /* Save the value of the boot key memory before it is overwritten */
- uint8_t bootKeyPtrVal = *bootKeyPtr;
- *bootKeyPtr = 0;
-
- /* Check the reason for the reset so we can act accordingly */
- uint8_t mcusr_state = MCUSR; // store the initial state of the Status register
- MCUSR = 0; // clear all reset flags
-
- /* Watchdog may be configured with a 15 ms period so must disable it before going any further */
- // MAH 8/15/12- I removed this because wdt_disable() is the first thing SetupHardware() does- why
- // do it twice right in a row?
- //wdt_disable();
-
- /* Setup hardware required for the bootloader */
- // MAH 8/15/12- Moved this up to before the bootloader go/no-go decision tree so I could use the
- // timer in that decision tree. Removed the USBInit() call from it; if I'm not going to stay in
- // the bootloader, there's no point spending the time initializing the USB.
- // SetupHardware();
- wdt_disable();
-
- // Disable clock division
- clock_prescale_set(clock_div_1);
-
- // Relocate the interrupt vector table to the bootloader section
- MCUCR = (1 << IVCE);
- MCUCR = (1 << IVSEL);
-
- LED_SETUP();
- CPU_PRESCALE(0);
- L_LED_OFF();
- TX_LED_OFF();
- RX_LED_OFF();
-
- // Initialize TIMER1 to handle bootloader timeout and LED tasks.
- // With 16 MHz clock and 1/64 prescaler, timer 1 is clocked at 250 kHz
- // Our chosen compare match generates an interrupt every 1 ms.
- // This interrupt is disabled selectively when doing memory reading, erasing,
- // or writing since SPM has tight timing requirements.
-
- OCR1AH = 0;
- OCR1AL = 250;
- TIMSK1 = (1 << OCIE1A); // enable timer 1 output compare A match
interrupt
- TCCR1B = ((1 << CS11) | (1 << CS10)); // 1/64 prescaler on timer 1 input
-
-
- // MAH 8/15/12- this replaces bulky pgm_read_word(0) calls later on, to save memory.
- if (pgm_read_word(0) != 0xFFFF) sketchPresent = true;
-
-// MAH 26 Oct 2012- The "bootload or not?" section has been modified since the code released
-// with Arduino 1.0.1. The simplest modification is the replacement of equivalence checks on
-// the reset bits with masked checks, so if more than one reset occurs before the register is
-// checked, the check doesn't fail and fall through to the bootloader unnecessarily.
-
-// The second, more in depth modification addresses behavior after an external reset (i.e.,
-// user pushes the reset button). The Leonardo treats all external resets as requests to
-// re-enter the bootloader and wait for code to be loaded. It remains in bootloader mode for
-// 8 seconds before continuing on to the sketch (if one is present). By defining RESET_DELAY
-// equal to 1, this behavior will persist.
-
-// However, if RESET_DELAY is defined to 0, the reset timeout before loading the sketch drops
-// to 750ms. If, during that 750ms, another external reset occurs, THEN an 8-second delay
-// in the bootloader will occur.
-
- // This is the "no-8-second-delay" code. If this is the first time through the loop, we
- // don't expect to see the bootKey in memory.
- if ( (mcusr_state & (1<<EXTRF)) && (bootKeyPtrVal != bootKey) ) {
- *bootKeyPtr = bootKey; // Put the bootKey in memory so if we get back to this
- // point again, we know to jump into the bootloader
- sei(); // Enable interrupts, so we can use timer1 to track our time in the bootloader
- while (RunBootloader)
- {
- if (resetTimeout > EXT_RESET_TIMEOUT_PERIOD) // resetTimeout is getting incremeted
- RunBootloader = false; // in the timer1 ISR.
- }
- // If we make it past that while loop, it's sketch loading time!
- *bootKeyPtr = 0; // clear out the bootKey; from now on, we want to treat a reset like
- // a normal reset.
- cli(); // Disable interrupts, in case no sketch is present.
- RunBootloader = true; // We want to hang out in the bootloader if no sketch is present.
- if (sketchPresent) StartSketch(); // If a sketch is present, go! Otherwise, wait around
- // in the bootloader until
one is uploaded.
- }
- // On a power-on reset, we ALWAYS want to go to the sketch. If there is one.
- // This is a place where the old code had an equivalence and now there is a mask.
- else if ( (mcusr_state & (1<<PORF)) && sketchPresent) {
- StartSketch();
- }
- // On a watchdog reset, if the bootKey isn't set, and there's a sketch, we should just
- // go straight to the sketch.
- // This is a place where the old code had an equivalence and now there is a mask.
- else if ( (mcusr_state & (1<<WDRF) ) && (bootKeyPtrVal != bootKey) && sketchPresent) {
- // If it looks like an "accidental" watchdog reset then start the sketch.
- StartSketch();
- }
-
- /* Initialize USB Subsystem */
- USB_Init();
-
- /* Enable global interrupts so that the USB stack can function */
- sei();
-
- Timeout = 0;
-
- while (RunBootloader)
- {
- CDC_Task();
- USB_USBTask();
- /* Time out and start the sketch if one is present */
- if (Timeout > TIMEOUT_PERIOD)
- RunBootloader = false;
-
- // MAH 8/15/12- This used to be a function call- inlining it saves a few bytes.
- LLEDPulse++;
- uint8_t p = LLEDPulse >> 8;
- if (p > 127)
- p = 254-p;
- p += p;
- if (((uint8_t)LLEDPulse) > p)
- L_LED_OFF();
- else
- L_LED_ON();
- }
-
- /* Disconnect from the host - USB interface will be reset later along with the AVR */
- USB_Detach();
-
- /* Jump to beginning of application space to run the sketch - do not reset */
- StartSketch();
-}
-
-// Timer1 is set up to provide periodic interrupts. This is used to flicker the LEDs during
-// programming as well as to generate the clock counts which determine how long the board should
-// remain in bootloading mode.
-
-ISR(TIMER1_COMPA_vect, ISR_BLOCK)
-{
- /* Reset counter */
- TCNT1H = 0;
- TCNT1L = 0;
-
- /* Check whether the TX or RX LED one-shot period has elapsed. if so, turn off the LED */
- if (TxLEDPulse && !(--TxLEDPulse))
- TX_LED_OFF();
- if (RxLEDPulse && !(--RxLEDPulse))
- RX_LED_OFF();
- resetTimeout++; // Needed for the "short reset delay" mode- governs the time the board waits
- // for a second reset before loading the sketch.
- if (pgm_read_word(0) != 0xFFFF)
- Timeout++;
-}
-
-// MAH 29 Oct 2012 Nothing below this point has to change for the LilyPadUSB support
-
-/** Event handler for the USB_ConfigurationChanged event. This configures the device's endpoints ready
- * to relay data to and from the attached USB host.
- */
-void EVENT_USB_Device_ConfigurationChanged(void)
-{
- /* Setup CDC Notification, Rx and Tx Endpoints */
- Endpoint_ConfigureEndpoint(CDC_NOTIFICATION_EPNUM, EP_TYPE_INTERRUPT,
- ENDPOINT_DIR_IN, CDC_NOTIFICATION_EPSIZE,
- ENDPOINT_BANK_SINGLE);
-
- Endpoint_ConfigureEndpoint(CDC_TX_EPNUM, EP_TYPE_BULK,
- ENDPOINT_DIR_IN, CDC_TXRX_EPSIZE,
- ENDPOINT_BANK_SINGLE);
-
- Endpoint_ConfigureEndpoint(CDC_RX_EPNUM, EP_TYPE_BULK,
- ENDPOINT_DIR_OUT, CDC_TXRX_EPSIZE,
- ENDPOINT_BANK_SINGLE);
-}
-
-/** Event handler for the USB_ControlRequest event. This is used to catch and process control requests sent
to
- * the device from the USB host before passing along unhandled control requests to the library for
processing
- * internally.
- */
-void EVENT_USB_Device_ControlRequest(void)
-{
- /* Ignore any requests that aren't directed to the CDC interface */
- if ((USB_ControlRequest.bmRequestType & (CONTROL_REQTYPE_TYPE | CONTROL_REQTYPE_RECIPIENT)) !=
- (REQTYPE_CLASS | REQREC_INTERFACE))
- {
- return;
- }
-
- /* Process CDC specific control requests */
- switch (USB_ControlRequest.bRequest)
- {
- case CDC_REQ_GetLineEncoding:
- if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS |
REQREC_INTERFACE))
- {
- Endpoint_ClearSETUP();
-
- /* Write the line coding data to the control endpoint */
- Endpoint_Write_Control_Stream_LE(&LineEncoding, sizeof(CDC_LineEncoding_t));
- Endpoint_ClearOUT();
- }
-
- break;
- case CDC_REQ_SetLineEncoding:
- if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS |
REQREC_INTERFACE))
- {
- Endpoint_ClearSETUP();
-
- /* Read the line coding data in from the host into the global struct */
- Endpoint_Read_Control_Stream_LE(&LineEncoding, sizeof(CDC_LineEncoding_t));
- Endpoint_ClearIN();
- }
-
- break;
- }
-}
-
-#if !defined(NO_BLOCK_SUPPORT)
-/** Reads or writes a block of EEPROM or FLASH memory to or from the appropriate CDC data endpoint, depending
- * on the AVR910 protocol command issued.
- *
- * \param[in] Command Single character AVR910 protocol command indicating what memory operation to perform
- */
-static void ReadWriteMemoryBlock(const uint8_t Command)
-{
- uint16_t BlockSize;
- char MemoryType;
-
- bool HighByte = false;
- uint8_t LowByte = 0;
-
- BlockSize = (FetchNextCommandByte() << 8);
- BlockSize |= FetchNextCommandByte();
-
- MemoryType = FetchNextCommandByte();
-
- if ((MemoryType != 'E') && (MemoryType != 'F'))
- {
- /* Send error byte back to the host */
- WriteNextResponseByte('?');
-
- return;
- }
-
- /* Disable timer 1 interrupt - can't afford to process nonessential interrupts
- * while doing SPM tasks */
- TIMSK1 = 0;
-
- /* Check if command is to read memory */
- if (Command == 'g')
- {
- /* Re-enable RWW section */
- boot_rww_enable();
-
- while (BlockSize--)
- {
- if (MemoryType == 'F')
- {
- /* Read the next FLASH byte from the current FLASH page */
- #if (FLASHEND > 0xFFFF)
- WriteNextResponseByte(pgm_read_byte_far(CurrAddress | HighByte));
- #else
- WriteNextResponseByte(pgm_read_byte(CurrAddress | HighByte));
- #endif
-
- /* If both bytes in current word have been read, increment the address
counter */
- if (HighByte)
- CurrAddress += 2;
-
- HighByte = !HighByte;
- }
- else
- {
- /* Read the next EEPROM byte into the endpoint */
- WriteNextResponseByte(eeprom_read_byte((uint8_t*)(intptr_t)(CurrAddress >>
1)));
-
- /* Increment the address counter after use */
- CurrAddress += 2;
- }
- }
- }
- else
- {
- uint32_t PageStartAddress = CurrAddress;
-
- if (MemoryType == 'F')
- {
- boot_page_erase(PageStartAddress);
- boot_spm_busy_wait();
- }
-
- while (BlockSize--)
- {
- if (MemoryType == 'F')
- {
- /* If both bytes in current word have been written, increment the address
counter */
- if (HighByte)
- {
- /* Write the next FLASH word to the current FLASH page */
- boot_page_fill(CurrAddress, ((FetchNextCommandByte() << 8) |
LowByte));
-
- /* Increment the address counter after use */
- CurrAddress += 2;
- }
- else
- {
- LowByte = FetchNextCommandByte();
- }
-
- HighByte = !HighByte;
- }
- else
- {
- /* Write the next EEPROM byte from the endpoint */
- eeprom_write_byte((uint8_t*)((intptr_t)(CurrAddress >> 1)),
FetchNextCommandByte());
-
- /* Increment the address counter after use */
- CurrAddress += 2;
- }
- }
-
- /* If in FLASH programming mode, commit the page after writing */
- if (MemoryType == 'F')
- {
- /* Commit the flash page to memory */
- boot_page_write(PageStartAddress);
-
- /* Wait until write operation has completed */
- boot_spm_busy_wait();
- }
-
- /* Send response byte back to the host */
- WriteNextResponseByte('\r');
- }
-
- /* Re-enable timer 1 interrupt disabled earlier in this routine */
- TIMSK1 = (1 << OCIE1A);
-}
-#endif
-
-/** Retrieves the next byte from the host in the CDC data OUT endpoint, and clears the endpoint bank if
needed
- * to allow reception of the next data packet from the host.
- *
- * \return Next received byte from the host in the CDC data OUT endpoint
- */
-static uint8_t FetchNextCommandByte(void)
-{
- /* Select the OUT endpoint so that the next data byte can be read */
- Endpoint_SelectEndpoint(CDC_RX_EPNUM);
-
- /* If OUT endpoint empty, clear it and wait for the next packet from the host */
- while (!(Endpoint_IsReadWriteAllowed()))
- {
- Endpoint_ClearOUT();
-
- while (!(Endpoint_IsOUTReceived()))
- {
- if (USB_DeviceState == DEVICE_STATE_Unattached)
- return 0;
- }
- }
-
- /* Fetch the next byte from the OUT endpoint */
- return Endpoint_Read_8();
-}
-
-/** Writes the next response byte to the CDC data IN endpoint, and sends the endpoint back if needed to free
up the
- * bank when full ready for the next byte in the packet to the host.
- *
- * \param[in] Response Next response byte to send to the host
- */
-static void WriteNextResponseByte(const uint8_t Response)
-{
- /* Select the IN endpoint so that the next data byte can be written */
- Endpoint_SelectEndpoint(CDC_TX_EPNUM);
-
- /* If IN endpoint full, clear it and wait until ready for the next packet to the host */
- if (!(Endpoint_IsReadWriteAllowed()))
- {
- Endpoint_ClearIN();
-
- while (!(Endpoint_IsINReady()))
- {
- if (USB_DeviceState == DEVICE_STATE_Unattached)
- return;
- }
- }
-
- /* Write the next byte to the IN endpoint */
- Endpoint_Write_8(Response);
-
- TX_LED_ON();
- TxLEDPulse = TX_RX_LED_PULSE_PERIOD;
-}
-
-#define STK_OK 0x10
-#define STK_INSYNC 0x14 // ' '
-#define CRC_EOP 0x20 // 'SPACE'
-#define STK_GET_SYNC 0x30 // '0'
-
-#define STK_GET_PARAMETER 0x41 // 'A'
-#define STK_SET_DEVICE 0x42 // 'B'
-#define STK_SET_DEVICE_EXT 0x45 // 'E'
-#define STK_LOAD_ADDRESS 0x55 // 'U'
-#define STK_UNIVERSAL 0x56 // 'V'
-#define STK_PROG_PAGE 0x64 // 'd'
-#define STK_READ_PAGE 0x74 // 't'
-#define STK_READ_SIGN 0x75 // 'u'
-
-/** Task to read in AVR910 commands from the CDC data OUT endpoint, process them, perform the required
actions
- * and send the appropriate response back to the host.
- */
-void CDC_Task(void)
-{
- /* Select the OUT endpoint */
- Endpoint_SelectEndpoint(CDC_RX_EPNUM);
-
- /* Check if endpoint has a command in it sent from the host */
- if (!(Endpoint_IsOUTReceived()))
- return;
-
- RX_LED_ON();
- RxLEDPulse = TX_RX_LED_PULSE_PERIOD;
-
- /* Read in the bootloader command (first byte sent from host) */
- uint8_t Command = FetchNextCommandByte();
-
- if (Command == 'E')
- {
- /* We nearly run out the bootloader timeout clock,
- * leaving just a few hundred milliseconds so the
- * bootloder has time to respond and service any
- * subsequent requests */
- Timeout = TIMEOUT_PERIOD - 500;
-
- /* Re-enable RWW section - must be done here in case
- * user has disabled verification on upload. */
- boot_rww_enable_safe();
-
- // Send confirmation byte back to the host
- WriteNextResponseByte('\r');
- }
- else if (Command == 'T')
- {
- FetchNextCommandByte();
-
- // Send confirmation byte back to the host
- WriteNextResponseByte('\r');
- }
- else if ((Command == 'L') || (Command == 'P'))
- {
- // Send confirmation byte back to the host
- WriteNextResponseByte('\r');
- }
- else if (Command == 't')
- {
- // Return ATMEGA128 part code - this is only to allow AVRProg to use the bootloader
- WriteNextResponseByte(0x44);
- WriteNextResponseByte(0x00);
- }
- else if (Command == 'a')
- {
- // Indicate auto-address increment is supported
- WriteNextResponseByte('Y');
- }
- else if (Command == 'A')
- {
- // Set the current address to that given by the host
- CurrAddress = (FetchNextCommandByte() << 9);
- CurrAddress |= (FetchNextCommandByte() << 1);
-
- // Send confirmation byte back to the host
- WriteNextResponseByte('\r');
- }
- else if (Command == 'p')
- {
- // Indicate serial programmer back to the host
- WriteNextResponseByte('S');
- }
- else if (Command == 'S')
- {
- // Write the 7-byte software identifier to the endpoint
- for (uint8_t CurrByte = 0; CurrByte < 7; CurrByte++)
- WriteNextResponseByte(SOFTWARE_IDENTIFIER[CurrByte]);
- }
- else if (Command == 'V')
- {
- WriteNextResponseByte('0' + BOOTLOADER_VERSION_MAJOR);
- WriteNextResponseByte('0' + BOOTLOADER_VERSION_MINOR);
- }
- else if (Command == 's')
- {
- WriteNextResponseByte(AVR_SIGNATURE_3);
- WriteNextResponseByte(AVR_SIGNATURE_2);
- WriteNextResponseByte(AVR_SIGNATURE_1);
- }
- else if (Command == 'e')
- {
- // Clear the application section of flash
- for (uint32_t CurrFlashAddress = 0; CurrFlashAddress < BOOT_START_ADDR; CurrFlashAddress +=
SPM_PAGESIZE)
- {
- boot_page_erase(CurrFlashAddress);
- boot_spm_busy_wait();
- boot_page_write(CurrFlashAddress);
- boot_spm_busy_wait();
- }
-
- // Send confirmation byte back to the host
- WriteNextResponseByte('\r');
- }
- #if !defined(NO_LOCK_BYTE_WRITE_SUPPORT)
- else if (Command == 'l')
- {
- // Set the lock bits to those given by the host
- boot_lock_bits_set(FetchNextCommandByte());
-
- // Send confirmation byte back to the host
- WriteNextResponseByte('\r');
- }
- #endif
- else if (Command == 'r')
- {
- WriteNextResponseByte(boot_lock_fuse_bits_get(GET_LOCK_BITS));
- }
- else if (Command == 'F')
- {
- WriteNextResponseByte(boot_lock_fuse_bits_get(GET_LOW_FUSE_BITS));
- }
- else if (Command == 'N')
- {
- WriteNextResponseByte(boot_lock_fuse_bits_get(GET_HIGH_FUSE_BITS));
- }
- else if (Command == 'Q')
- {
- WriteNextResponseByte(boot_lock_fuse_bits_get(GET_EXTENDED_FUSE_BITS));
- }
- #if !defined(NO_BLOCK_SUPPORT)
- else if (Command == 'b')
- {
- WriteNextResponseByte('Y');
-
- // Send block size to the host
- WriteNextResponseByte(SPM_PAGESIZE >> 8);
- WriteNextResponseByte(SPM_PAGESIZE & 0xFF);
- }
- else if ((Command == 'B') || (Command == 'g'))
- {
- // Keep resetting the timeout counter if we're receiving self-programming instructions
- Timeout = 0;
- // Delegate the block write/read to a separate function for clarity
- ReadWriteMemoryBlock(Command);
- }
- #endif
- #if !defined(NO_FLASH_BYTE_SUPPORT)
- else if (Command == 'C')
- {
- // Write the high byte to the current flash page
- boot_page_fill(CurrAddress, FetchNextCommandByte());
-
- // Send confirmation byte back to the host
- WriteNextResponseByte('\r');
- }
- else if (Command == 'c')
- {
- // Write the low byte to the current flash page
- boot_page_fill(CurrAddress | 0x01, FetchNextCommandByte());
-
- // Increment the address
- CurrAddress += 2;
-
- // Send confirmation byte back to the host
- WriteNextResponseByte('\r');
- }
- else if (Command == 'm')
- {
- // Commit the flash page to memory
- boot_page_write(CurrAddress);
-
- // Wait until write operation has completed
- boot_spm_busy_wait();
-
- // Send confirmation byte back to the host
- WriteNextResponseByte('\r');
- }
- else if (Command == 'R')
- {
- #if (FLASHEND > 0xFFFF)
- uint16_t ProgramWord = pgm_read_word_far(CurrAddress);
- #else
- uint16_t ProgramWord = pgm_read_word(CurrAddress);
- #endif
-
- WriteNextResponseByte(ProgramWord >> 8);
- WriteNextResponseByte(ProgramWord & 0xFF);
- }
- #endif
- #if !defined(NO_EEPROM_BYTE_SUPPORT)
- else if (Command == 'D')
- {
- // Read the byte from the endpoint and write it to the EEPROM
- eeprom_write_byte((uint8_t*)((intptr_t)(CurrAddress >> 1)), FetchNextCommandByte());
-
- // Increment the address after use
- CurrAddress += 2;
-
- // Send confirmation byte back to the host
- WriteNextResponseByte('\r');
- }
- else if (Command == 'd')
- {
- // Read the EEPROM byte and write it to the endpoint
- WriteNextResponseByte(eeprom_read_byte((uint8_t*)((intptr_t)(CurrAddress >> 1))));
-
- // Increment the address after use
- CurrAddress += 2;
- }
- #endif
- else if (Command != 27)
- {
- // Unknown (non-sync) command, return fail code
- WriteNextResponseByte('?');
- }
-
-
- /* Select the IN endpoint */
- Endpoint_SelectEndpoint(CDC_TX_EPNUM);
-
- /* Remember if the endpoint is completely full before clearing it */
- bool IsEndpointFull = !(Endpoint_IsReadWriteAllowed());
-
- /* Send the endpoint data to the host */
- Endpoint_ClearIN();
-
- /* If a full endpoint's worth of data was sent, we need to send an empty packet afterwards to signal
end of transfer */
- if (IsEndpointFull)
- {
- while (!(Endpoint_IsINReady()))
- {
- if (USB_DeviceState == DEVICE_STATE_Unattached)
- return;
- }
-
- Endpoint_ClearIN();
- }
-
- /* Wait until the data has been sent to the host */
- while (!(Endpoint_IsINReady()))
- {
- if (USB_DeviceState == DEVICE_STATE_Unattached)
- return;
- }
-
- /* Select the OUT endpoint */
- Endpoint_SelectEndpoint(CDC_RX_EPNUM);
-
- /* Acknowledge the command from the host */
- Endpoint_ClearOUT();
-}
-
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2011.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaim all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ *
+ * Main source file for the CDC class bootloader. This file contains the complete bootloader logic.
+ */
+
+#define INCLUDE_FROM_CATERINA_C
+#include "Caterina.h"
+
+/** Contains the current baud rate and other settings of the first virtual serial port. This must be
retained as some
+ * operating systems will not open the port unless the settings can be set successfully.
+ */
+static CDC_LineEncoding_t LineEncoding = { .BaudRateBPS = 0,
+ .CharFormat = CDC_LINEENCODING_OneStopBit,
+ .ParityType = CDC_PARITY_None,
+ .DataBits = 8 };
+
+/** Current address counter. This stores the current address of the FLASH or EEPROM as set by the host,
+ * and is used when reading or writing to the AVRs memory (either FLASH or EEPROM depending on the issued
+ * command.)
+ */
+static uint32_t CurrAddress;
+
+/** Flag to indicate if the bootloader should be running, or should exit and allow the application code to
run
+ * via a watchdog reset. When cleared the bootloader will exit, starting the watchdog and entering an
infinite
+ * loop until the AVR restarts and the application runs.
+ */
+static bool RunBootloader = true;
+
+/* Pulse generation counters to keep track of the time remaining for each pulse type */
+#define TX_RX_LED_PULSE_PERIOD 100
+uint16_t TxLEDPulse = 0; // time remaining for Tx LED pulse
+uint16_t RxLEDPulse = 0; // time remaining for Rx LED pulse
+
+/* Bootloader timeout timer */
+// MAH 8/15/12- change so timeouts work properly when the chip is running at 8MHz instead of 16.
+#define TIMEOUT_PERIOD 4000
+#define EXT_RESET_TIMEOUT_PERIOD 375
+
+
+/*********************************************************************************************************
+LilyPadUSB bootloader code
+The LilyPadUSB bootloader has been changed to remove the 8-second delay after external reset which is in
+the Leonardo. To enter the bootloader, the user should execute TWO external resets within 750 ms; that is,
+press the reset button twice, quickly.\
+
+Some other changes were made to allow this code to compile tightly enough to fit in the alloted 4k of
+bootloader space.
+*/
+// MAH 8/15/12- added this flag to replace the bulky program memory reads to check for the presence of a
sketch
+// at the top of the memory space.
+static bool sketchPresent = false;
+
+// MAH 8/15/12- make this volatile, since we modify it in one place and read it in another, we want to make
+// sure we're always working on the copy in memory and not an erroneous value stored in a cache somewhere.
+// This variable stores the length of time we've been in the bootloader when waiting for the 8 second delay.
+volatile uint16_t Timeout = 0;
+// MAH 8/15/12- added this for delay during startup. Did not use existing Timeout value b/c it only
increments
+// when there's a sketch at the top of the memory.
+volatile uint16_t resetTimeout = 0;
+
+// MAH 8/15/12- let's make this an 8-bit value instead of 16- that saves on memory because 16-bit addition
and
+// comparison compiles to bulkier code. Note that this does *not* require a change to the Arduino core-
we're
+// just sort of ignoring the extra byte that the Arduino core puts at the next location.
+uint8_t bootKey = 0x77;
+volatile uint8_t *const bootKeyPtr = (volatile uint8_t *)0x0800;
+
+// StartSketch() is called to clean up our mess before passing execution to the sketch.
+void StartSketch(void)
+{
+ cli();
+
+ /* Undo TIMER1 setup and clear the count before running the sketch */
+ TIMSK1 = 0;
+ TCCR1B = 0;
+
+ /* Relocate the interrupt vector table to the application section */
+ MCUCR = (1 << IVCE);
+ MCUCR = 0;
+
+ L_LED_OFF();
+ TX_LED_OFF();
+ RX_LED_OFF();
+
+ /* jump to beginning of application space */
+ __asm__ volatile("jmp 0x0000");
+
+}
+
+uint16_t LLEDPulse;
+
+/** Main program entry point. This routine configures the hardware required by the bootloader, then
continuously
+ * runs the bootloader processing routine until it times out or is instructed to exit.
+ */
+int main(void)
+{
+ /* Save the value of the boot key memory before it is overwritten */
+ uint8_t bootKeyPtrVal = *bootKeyPtr;
+ *bootKeyPtr = 0;
+
+ /* Check the reason for the reset so we can act accordingly */
+ uint8_t mcusr_state = MCUSR; // store the initial state of the Status register
+ MCUSR = 0; // clear all reset flags
+
+ /* Watchdog may be configured with a 15 ms period so must disable it before going any further */
+ // MAH 8/15/12- I removed this because wdt_disable() is the first thing SetupHardware() does- why
+ // do it twice right in a row?
+ //wdt_disable();
+
+ /* Setup hardware required for the bootloader */
+ // MAH 8/15/12- Moved this up to before the bootloader go/no-go decision tree so I could use the
+ // timer in that decision tree. Removed the USBInit() call from it; if I'm not going to stay in
+ // the bootloader, there's no point spending the time initializing the USB.
+ // SetupHardware();
+ wdt_disable();
+
+ // Disable clock division
+ clock_prescale_set(clock_div_1);
+
+ // Relocate the interrupt vector table to the bootloader section
+ MCUCR = (1 << IVCE);
+ MCUCR = (1 << IVSEL);
+
+ LED_SETUP();
+ CPU_PRESCALE(0);
+ L_LED_OFF();
+ TX_LED_OFF();
+ RX_LED_OFF();
+
+ // Initialize TIMER1 to handle bootloader timeout and LED tasks.
+ // With 16 MHz clock and 1/64 prescaler, timer 1 is clocked at 250 kHz
+ // Our chosen compare match generates an interrupt every 1 ms.
+ // This interrupt is disabled selectively when doing memory reading, erasing,
+ // or writing since SPM has tight timing requirements.
+
+ OCR1AH = 0;
+ OCR1AL = 250;
+ TIMSK1 = (1 << OCIE1A); // enable timer 1 output compare A match
interrupt
+ TCCR1B = ((1 << CS11) | (1 << CS10)); // 1/64 prescaler on timer 1 input
+
+
+ // MAH 8/15/12- this replaces bulky pgm_read_word(0) calls later on, to save memory.
+ if (pgm_read_word(0) != 0xFFFF) sketchPresent = true;
+
+// MAH 26 Oct 2012- The "bootload or not?" section has been modified since the code released
+// with Arduino 1.0.1. The simplest modification is the replacement of equivalence checks on
+// the reset bits with masked checks, so if more than one reset occurs before the register is
+// checked, the check doesn't fail and fall through to the bootloader unnecessarily.
+
+// The second, more in depth modification addresses behavior after an external reset (i.e.,
+// user pushes the reset button). The Leonardo treats all external resets as requests to
+// re-enter the bootloader and wait for code to be loaded. It remains in bootloader mode for
+// 8 seconds before continuing on to the sketch (if one is present). By defining RESET_DELAY
+// equal to 1, this behavior will persist.
+
+// However, if RESET_DELAY is defined to 0, the reset timeout before loading the sketch drops
+// to 750ms. If, during that 750ms, another external reset occurs, THEN an 8-second delay
+// in the bootloader will occur.
+
+ // This is the "no-8-second-delay" code. If this is the first time through the loop, we
+ // don't expect to see the bootKey in memory.
+ if ( (mcusr_state & (1<<EXTRF)) && (bootKeyPtrVal != bootKey) ) {
+ *bootKeyPtr = bootKey; // Put the bootKey in memory so if we get back to this
+ // point again, we know to jump into the bootloader
+ sei(); // Enable interrupts, so we can use timer1 to track our time in the bootloader
+ while (RunBootloader)
+ {
+ if (resetTimeout > EXT_RESET_TIMEOUT_PERIOD) // resetTimeout is getting incremeted
+ RunBootloader = false; // in the timer1 ISR.
+ }
+ // If we make it past that while loop, it's sketch loading time!
+ *bootKeyPtr = 0; // clear out the bootKey; from now on, we want to treat a reset like
+ // a normal reset.
+ cli(); // Disable interrupts, in case no sketch is present.
+ RunBootloader = true; // We want to hang out in the bootloader if no sketch is present.
+ if (sketchPresent) StartSketch(); // If a sketch is present, go! Otherwise, wait around
+ // in the bootloader until
one is uploaded.
+ }
+ // On a power-on reset, we ALWAYS want to go to the sketch. If there is one.
+ // This is a place where the old code had an equivalence and now there is a mask.
+ else if ( (mcusr_state & (1<<PORF)) && sketchPresent) {
+ StartSketch();
+ }
+ // On a watchdog reset, if the bootKey isn't set, and there's a sketch, we should just
+ // go straight to the sketch.
+ // This is a place where the old code had an equivalence and now there is a mask.
+ else if ( (mcusr_state & (1<<WDRF) ) && (bootKeyPtrVal != bootKey) && sketchPresent) {
+ // If it looks like an "accidental" watchdog reset then start the sketch.
+ StartSketch();
+ }
+
+ /* Initialize USB Subsystem */
+ USB_Init();
+
+ /* Enable global interrupts so that the USB stack can function */
+ sei();
+
+ Timeout = 0;
+
+ while (RunBootloader)
+ {
+ CDC_Task();
+ USB_USBTask();
+ /* Time out and start the sketch if one is present */
+ if (Timeout > TIMEOUT_PERIOD)
+ RunBootloader = false;
+
+ // MAH 8/15/12- This used to be a function call- inlining it saves a few bytes.
+ LLEDPulse++;
+ uint8_t p = LLEDPulse >> 8;
+ if (p > 127)
+ p = 254-p;
+ p += p;
+ if (((uint8_t)LLEDPulse) > p)
+ L_LED_OFF();
+ else
+ L_LED_ON();
+ }
+
+ /* Disconnect from the host - USB interface will be reset later along with the AVR */
+ USB_Detach();
+
+ /* Jump to beginning of application space to run the sketch - do not reset */
+ StartSketch();
+}
+
+// Timer1 is set up to provide periodic interrupts. This is used to flicker the LEDs during
+// programming as well as to generate the clock counts which determine how long the board should
+// remain in bootloading mode.
+
+ISR(TIMER1_COMPA_vect, ISR_BLOCK)
+{
+ /* Reset counter */
+ TCNT1H = 0;
+ TCNT1L = 0;
+
+ /* Check whether the TX or RX LED one-shot period has elapsed. if so, turn off the LED */
+ if (TxLEDPulse && !(--TxLEDPulse))
+ TX_LED_OFF();
+ if (RxLEDPulse && !(--RxLEDPulse))
+ RX_LED_OFF();
+ resetTimeout++; // Needed for the "short reset delay" mode- governs the time the board waits
+ // for a second reset before loading the sketch.
+ if (pgm_read_word(0) != 0xFFFF)
+ Timeout++;
+}
+
+// MAH 29 Oct 2012 Nothing below this point has to change for the LilyPadUSB support
+
+/** Event handler for the USB_ConfigurationChanged event. This configures the device's endpoints ready
+ * to relay data to and from the attached USB host.
+ */
+void EVENT_USB_Device_ConfigurationChanged(void)
+{
+ /* Setup CDC Notification, Rx and Tx Endpoints */
+ Endpoint_ConfigureEndpoint(CDC_NOTIFICATION_EPNUM, EP_TYPE_INTERRUPT,
+ ENDPOINT_DIR_IN, CDC_NOTIFICATION_EPSIZE,
+ ENDPOINT_BANK_SINGLE);
+
+ Endpoint_ConfigureEndpoint(CDC_TX_EPNUM, EP_TYPE_BULK,
+ ENDPOINT_DIR_IN, CDC_TXRX_EPSIZE,
+ ENDPOINT_BANK_SINGLE);
+
+ Endpoint_ConfigureEndpoint(CDC_RX_EPNUM, EP_TYPE_BULK,
+ ENDPOINT_DIR_OUT, CDC_TXRX_EPSIZE,
+ ENDPOINT_BANK_SINGLE);
+}
+
+/** Event handler for the USB_ControlRequest event. This is used to catch and process control requests sent
to
+ * the device from the USB host before passing along unhandled control requests to the library for
processing
+ * internally.
+ */
+void EVENT_USB_Device_ControlRequest(void)
+{
+ /* Ignore any requests that aren't directed to the CDC interface */
+ if ((USB_ControlRequest.bmRequestType & (CONTROL_REQTYPE_TYPE | CONTROL_REQTYPE_RECIPIENT)) !=
+ (REQTYPE_CLASS | REQREC_INTERFACE))
+ {
+ return;
+ }
+
+ /* Process CDC specific control requests */
+ switch (USB_ControlRequest.bRequest)
+ {
+ case CDC_REQ_GetLineEncoding:
+ if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS |
REQREC_INTERFACE))
+ {
+ Endpoint_ClearSETUP();
+
+ /* Write the line coding data to the control endpoint */
+ Endpoint_Write_Control_Stream_LE(&LineEncoding, sizeof(CDC_LineEncoding_t));
+ Endpoint_ClearOUT();
+ }
+
+ break;
+ case CDC_REQ_SetLineEncoding:
+ if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS |
REQREC_INTERFACE))
+ {
+ Endpoint_ClearSETUP();
+
+ /* Read the line coding data in from the host into the global struct */
+ Endpoint_Read_Control_Stream_LE(&LineEncoding, sizeof(CDC_LineEncoding_t));
+ Endpoint_ClearIN();
+ }
+
+ break;
+ }
+}
+
+#if !defined(NO_BLOCK_SUPPORT)
+/** Reads or writes a block of EEPROM or FLASH memory to or from the appropriate CDC data endpoint, depending
+ * on the AVR910 protocol command issued.
+ *
+ * \param[in] Command Single character AVR910 protocol command indicating what memory operation to perform
+ */
+static void ReadWriteMemoryBlock(const uint8_t Command)
+{
+ uint16_t BlockSize;
+ char MemoryType;
+
+ bool HighByte = false;
+ uint8_t LowByte = 0;
+
+ BlockSize = (FetchNextCommandByte() << 8);
+ BlockSize |= FetchNextCommandByte();
+
+ MemoryType = FetchNextCommandByte();
+
+ if ((MemoryType != 'E') && (MemoryType != 'F'))
+ {
+ /* Send error byte back to the host */
+ WriteNextResponseByte('?');
+
+ return;
+ }
+
+ /* Disable timer 1 interrupt - can't afford to process nonessential interrupts
+ * while doing SPM tasks */
+ TIMSK1 = 0;
+
+ /* Check if command is to read memory */
+ if (Command == 'g')
+ {
+ /* Re-enable RWW section */
+ boot_rww_enable();
+
+ while (BlockSize--)
+ {
+ if (MemoryType == 'F')
+ {
+ /* Read the next FLASH byte from the current FLASH page */
+ #if (FLASHEND > 0xFFFF)
+ WriteNextResponseByte(pgm_read_byte_far(CurrAddress | HighByte));
+ #else
+ WriteNextResponseByte(pgm_read_byte(CurrAddress | HighByte));
+ #endif
+
+ /* If both bytes in current word have been read, increment the address
counter */
+ if (HighByte)
+ CurrAddress += 2;
+
+ HighByte = !HighByte;
+ }
+ else
+ {
+ /* Read the next EEPROM byte into the endpoint */
+ WriteNextResponseByte(eeprom_read_byte((uint8_t*)(intptr_t)(CurrAddress >>
1)));
+
+ /* Increment the address counter after use */
+ CurrAddress += 2;
+ }
+ }
+ }
+ else
+ {
+ uint32_t PageStartAddress = CurrAddress;
+
+ if (MemoryType == 'F')
+ {
+ boot_page_erase(PageStartAddress);
+ boot_spm_busy_wait();
+ }
+
+ while (BlockSize--)
+ {
+ if (MemoryType == 'F')
+ {
+ /* If both bytes in current word have been written, increment the address
counter */
+ if (HighByte)
+ {
+ /* Write the next FLASH word to the current FLASH page */
+ boot_page_fill(CurrAddress, ((FetchNextCommandByte() << 8) |
LowByte));
+
+ /* Increment the address counter after use */
+ CurrAddress += 2;
+ }
+ else
+ {
+ LowByte = FetchNextCommandByte();
+ }
+
+ HighByte = !HighByte;
+ }
+ else
+ {
+ /* Write the next EEPROM byte from the endpoint */
+ eeprom_write_byte((uint8_t*)((intptr_t)(CurrAddress >> 1)),
FetchNextCommandByte());
+
+ /* Increment the address counter after use */
+ CurrAddress += 2;
+ }
+ }
+
+ /* If in FLASH programming mode, commit the page after writing */
+ if (MemoryType == 'F')
+ {
+ /* Commit the flash page to memory */
+ boot_page_write(PageStartAddress);
+
+ /* Wait until write operation has completed */
+ boot_spm_busy_wait();
+ }
+
+ /* Send response byte back to the host */
+ WriteNextResponseByte('\r');
+ }
+
+ /* Re-enable timer 1 interrupt disabled earlier in this routine */
+ TIMSK1 = (1 << OCIE1A);
+}
+#endif
+
+/** Retrieves the next byte from the host in the CDC data OUT endpoint, and clears the endpoint bank if
needed
+ * to allow reception of the next data packet from the host.
+ *
+ * \return Next received byte from the host in the CDC data OUT endpoint
+ */
+static uint8_t FetchNextCommandByte(void)
+{
+ /* Select the OUT endpoint so that the next data byte can be read */
+ Endpoint_SelectEndpoint(CDC_RX_EPNUM);
+
+ /* If OUT endpoint empty, clear it and wait for the next packet from the host */
+ while (!(Endpoint_IsReadWriteAllowed()))
+ {
+ Endpoint_ClearOUT();
+
+ while (!(Endpoint_IsOUTReceived()))
+ {
+ if (USB_DeviceState == DEVICE_STATE_Unattached)
+ return 0;
+ }
+ }
+
+ /* Fetch the next byte from the OUT endpoint */
+ return Endpoint_Read_8();
+}
+
+/** Writes the next response byte to the CDC data IN endpoint, and sends the endpoint back if needed to free
up the
+ * bank when full ready for the next byte in the packet to the host.
+ *
+ * \param[in] Response Next response byte to send to the host
+ */
+static void WriteNextResponseByte(const uint8_t Response)
+{
+ /* Select the IN endpoint so that the next data byte can be written */
+ Endpoint_SelectEndpoint(CDC_TX_EPNUM);
+
+ /* If IN endpoint full, clear it and wait until ready for the next packet to the host */
+ if (!(Endpoint_IsReadWriteAllowed()))
+ {
+ Endpoint_ClearIN();
+
+ while (!(Endpoint_IsINReady()))
+ {
+ if (USB_DeviceState == DEVICE_STATE_Unattached)
+ return;
+ }
+ }
+
+ /* Write the next byte to the IN endpoint */
+ Endpoint_Write_8(Response);
+
+ TX_LED_ON();
+ TxLEDPulse = TX_RX_LED_PULSE_PERIOD;
+}
+
+#define STK_OK 0x10
+#define STK_INSYNC 0x14 // ' '
+#define CRC_EOP 0x20 // 'SPACE'
+#define STK_GET_SYNC 0x30 // '0'
+
+#define STK_GET_PARAMETER 0x41 // 'A'
+#define STK_SET_DEVICE 0x42 // 'B'
+#define STK_SET_DEVICE_EXT 0x45 // 'E'
+#define STK_LOAD_ADDRESS 0x55 // 'U'
+#define STK_UNIVERSAL 0x56 // 'V'
+#define STK_PROG_PAGE 0x64 // 'd'
+#define STK_READ_PAGE 0x74 // 't'
+#define STK_READ_SIGN 0x75 // 'u'
+
+/** Task to read in AVR910 commands from the CDC data OUT endpoint, process them, perform the required
actions
+ * and send the appropriate response back to the host.
+ */
+void CDC_Task(void)
+{
+ /* Select the OUT endpoint */
+ Endpoint_SelectEndpoint(CDC_RX_EPNUM);
+
+ /* Check if endpoint has a command in it sent from the host */
+ if (!(Endpoint_IsOUTReceived()))
+ return;
+
+ RX_LED_ON();
+ RxLEDPulse = TX_RX_LED_PULSE_PERIOD;
+
+ /* Read in the bootloader command (first byte sent from host) */
+ uint8_t Command = FetchNextCommandByte();
+
+ if (Command == 'E')
+ {
+ /* We nearly run out the bootloader timeout clock,
+ * leaving just a few hundred milliseconds so the
+ * bootloder has time to respond and service any
+ * subsequent requests */
+ Timeout = TIMEOUT_PERIOD - 500;
+
+ /* Re-enable RWW section - must be done here in case
+ * user has disabled verification on upload. */
+ boot_rww_enable_safe();
+
+ // Send confirmation byte back to the host
+ WriteNextResponseByte('\r');
+ }
+ else if (Command == 'T')
+ {
+ FetchNextCommandByte();
+
+ // Send confirmation byte back to the host
+ WriteNextResponseByte('\r');
+ }
+ else if ((Command == 'L') || (Command == 'P'))
+ {
+ // Send confirmation byte back to the host
+ WriteNextResponseByte('\r');
+ }
+ else if (Command == 't')
+ {
+ // Return ATMEGA128 part code - this is only to allow AVRProg to use the bootloader
+ WriteNextResponseByte(0x44);
+ WriteNextResponseByte(0x00);
+ }
+ else if (Command == 'a')
+ {
+ // Indicate auto-address increment is supported
+ WriteNextResponseByte('Y');
+ }
+ else if (Command == 'A')
+ {
+ // Set the current address to that given by the host
+ CurrAddress = (FetchNextCommandByte() << 9);
+ CurrAddress |= (FetchNextCommandByte() << 1);
+
+ // Send confirmation byte back to the host
+ WriteNextResponseByte('\r');
+ }
+ else if (Command == 'p')
+ {
+ // Indicate serial programmer back to the host
+ WriteNextResponseByte('S');
+ }
+ else if (Command == 'S')
+ {
+ // Write the 7-byte software identifier to the endpoint
+ for (uint8_t CurrByte = 0; CurrByte < 7; CurrByte++)
+ WriteNextResponseByte(SOFTWARE_IDENTIFIER[CurrByte]);
+ }
+ else if (Command == 'V')
+ {
+ WriteNextResponseByte('0' + BOOTLOADER_VERSION_MAJOR);
+ WriteNextResponseByte('0' + BOOTLOADER_VERSION_MINOR);
+ }
+ else if (Command == 's')
+ {
+ WriteNextResponseByte(AVR_SIGNATURE_3);
+ WriteNextResponseByte(AVR_SIGNATURE_2);
+ WriteNextResponseByte(AVR_SIGNATURE_1);
+ }
+ else if (Command == 'e')
+ {
+ // Clear the application section of flash
+ for (uint32_t CurrFlashAddress = 0; CurrFlashAddress < BOOT_START_ADDR; CurrFlashAddress +=
SPM_PAGESIZE)
+ {
+ boot_page_erase(CurrFlashAddress);
+ boot_spm_busy_wait();
+ boot_page_write(CurrFlashAddress);
+ boot_spm_busy_wait();
+ }
+
+ // Send confirmation byte back to the host
+ WriteNextResponseByte('\r');
+ }
+ #if !defined(NO_LOCK_BYTE_WRITE_SUPPORT)
+ else if (Command == 'l')
+ {
+ // Set the lock bits to those given by the host
+ boot_lock_bits_set(FetchNextCommandByte());
+
+ // Send confirmation byte back to the host
+ WriteNextResponseByte('\r');
+ }
+ #endif
+ else if (Command == 'r')
+ {
+ WriteNextResponseByte(boot_lock_fuse_bits_get(GET_LOCK_BITS));
+ }
+ else if (Command == 'F')
+ {
+ WriteNextResponseByte(boot_lock_fuse_bits_get(GET_LOW_FUSE_BITS));
+ }
+ else if (Command == 'N')
+ {
+ WriteNextResponseByte(boot_lock_fuse_bits_get(GET_HIGH_FUSE_BITS));
+ }
+ else if (Command == 'Q')
+ {
+ WriteNextResponseByte(boot_lock_fuse_bits_get(GET_EXTENDED_FUSE_BITS));
+ }
+ #if !defined(NO_BLOCK_SUPPORT)
+ else if (Command == 'b')
+ {
+ WriteNextResponseByte('Y');
+
+ // Send block size to the host
+ WriteNextResponseByte(SPM_PAGESIZE >> 8);
+ WriteNextResponseByte(SPM_PAGESIZE & 0xFF);
+ }
+ else if ((Command == 'B') || (Command == 'g'))
+ {
+ // Keep resetting the timeout counter if we're receiving self-programming instructions
+ Timeout = 0;
+ // Delegate the block write/read to a separate function for clarity
+ ReadWriteMemoryBlock(Command);
+ }
+ #endif
+ #if !defined(NO_FLASH_BYTE_SUPPORT)
+ else if (Command == 'C')
+ {
+ // Write the high byte to the current flash page
+ boot_page_fill(CurrAddress, FetchNextCommandByte());
+
+ // Send confirmation byte back to the host
+ WriteNextResponseByte('\r');
+ }
+ else if (Command == 'c')
+ {
+ // Write the low byte to the current flash page
+ boot_page_fill(CurrAddress | 0x01, FetchNextCommandByte());
+
+ // Increment the address
+ CurrAddress += 2;
+
+ // Send confirmation byte back to the host
+ WriteNextResponseByte('\r');
+ }
+ else if (Command == 'm')
+ {
+ // Commit the flash page to memory
+ boot_page_write(CurrAddress);
+
+ // Wait until write operation has completed
+ boot_spm_busy_wait();
+
+ // Send confirmation byte back to the host
+ WriteNextResponseByte('\r');
+ }
+ else if (Command == 'R')
+ {
+ #if (FLASHEND > 0xFFFF)
+ uint16_t ProgramWord = pgm_read_word_far(CurrAddress);
+ #else
+ uint16_t ProgramWord = pgm_read_word(CurrAddress);
+ #endif
+
+ WriteNextResponseByte(ProgramWord >> 8);
+ WriteNextResponseByte(ProgramWord & 0xFF);
+ }
+ #endif
+ #if !defined(NO_EEPROM_BYTE_SUPPORT)
+ else if (Command == 'D')
+ {
+ // Read the byte from the endpoint and write it to the EEPROM
+ eeprom_write_byte((uint8_t*)((intptr_t)(CurrAddress >> 1)), FetchNextCommandByte());
+
+ // Increment the address after use
+ CurrAddress += 2;
+
+ // Send confirmation byte back to the host
+ WriteNextResponseByte('\r');
+ }
+ else if (Command == 'd')
+ {
+ // Read the EEPROM byte and write it to the endpoint
+ WriteNextResponseByte(eeprom_read_byte((uint8_t*)((intptr_t)(CurrAddress >> 1))));
+
+ // Increment the address after use
+ CurrAddress += 2;
+ }
+ #endif
+ else if (Command != 27)
+ {
+ // Unknown (non-sync) command, return fail code
+ WriteNextResponseByte('?');
+ }
+
+
+ /* Select the IN endpoint */
+ Endpoint_SelectEndpoint(CDC_TX_EPNUM);
+
+ /* Remember if the endpoint is completely full before clearing it */
+ bool IsEndpointFull = !(Endpoint_IsReadWriteAllowed());
+
+ /* Send the endpoint data to the host */
+ Endpoint_ClearIN();
+
+ /* If a full endpoint's worth of data was sent, we need to send an empty packet afterwards to signal
end of transfer */
+ if (IsEndpointFull)
+ {
+ while (!(Endpoint_IsINReady()))
+ {
+ if (USB_DeviceState == DEVICE_STATE_Unattached)
+ return;
+ }
+
+ Endpoint_ClearIN();
+ }
+
+ /* Wait until the data has been sent to the host */
+ while (!(Endpoint_IsINReady()))
+ {
+ if (USB_DeviceState == DEVICE_STATE_Unattached)
+ return;
+ }
+
+ /* Select the OUT endpoint */
+ Endpoint_SelectEndpoint(CDC_RX_EPNUM);
+
+ /* Acknowledge the command from the host */
+ Endpoint_ClearOUT();
+}
diff --git a/hardware/arduino/bootloaders/caterina-LilyPadUSB/Caterina.h
b/hardware/arduino/bootloaders/caterina-LilyPadUSB/Caterina.h
index f8251d4..1281515 100644
--- a/hardware/arduino/bootloaders/caterina-LilyPadUSB/Caterina.h
+++ b/hardware/arduino/bootloaders/caterina-LilyPadUSB/Caterina.h
@@ -1,99 +1,98 @@
-/*
- LUFA Library
- Copyright (C) Dean Camera, 2011.
-
- dean [at] fourwalledcubicle [dot] com
- www.lufa-lib.org
-*/
-
-/*
- Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com)
-
- Permission to use, copy, modify, distribute, and sell this
- software and its documentation for any purpose is hereby granted
- without fee, provided that the above copyright notice appear in
- all copies and that both that the copyright notice and this
- permission notice and warranty disclaimer appear in supporting
- documentation, and that the name of the author not be used in
- advertising or publicity pertaining to distribution of the
- software without specific, written prior permission.
-
- The author disclaim all warranties with regard to this
- software, including all implied warranties of merchantability
- and fitness. In no event shall the author be liable for any
- special, indirect or consequential damages or any damages
- whatsoever resulting from loss of use, data or profits, whether
- in an action of contract, negligence or other tortious action,
- arising out of or in connection with the use or performance of
- this software.
-*/
-
-/** \file
- *
- * Header file for BootloaderCDC.c.
- */
-
-#ifndef _CDC_H_
-#define _CDC_H_
-
- /* Includes: */
- #include <avr/io.h>
- #include <avr/wdt.h>
- #include <avr/boot.h>
- #include <avr/eeprom.h>
- #include <avr/power.h>
- #include <avr/interrupt.h>
- #include <stdbool.h>
-
- #include "Descriptors.h"
-
- #include <LUFA/Drivers/USB/USB.h>
- /* Macros: */
- /** Version major of the CDC bootloader. */
- #define BOOTLOADER_VERSION_MAJOR 0x01
-
- /** Version minor of the CDC bootloader. */
- #define BOOTLOADER_VERSION_MINOR 0x00
-
- /** Hardware version major of the CDC bootloader. */
- #define BOOTLOADER_HWVERSION_MAJOR 0x01
-
- /** Hardware version minor of the CDC bootloader. */
- #define BOOTLOADER_HWVERSION_MINOR 0x00
-
- /** Eight character bootloader firmware identifier reported to the host when requested */
- #define SOFTWARE_IDENTIFIER "CATERINA"
-
- #define CPU_PRESCALE(n) (CLKPR = 0x80, CLKPR = (n))
- #define LED_SETUP() DDRC |= (1<<7); DDRB |= (1<<0); DDRD |= (1<<5);
- #define L_LED_OFF() PORTC &= ~(1<<7)
- #define L_LED_ON() PORTC |= (1<<7)
- #define L_LED_TOGGLE() PORTC ^= (1<<7)
- #define TX_LED_OFF() PORTD |= (1<<5)
- #define TX_LED_ON() PORTD &= ~(1<<5)
- #define RX_LED_OFF() PORTB |= (1<<0)
- #define RX_LED_ON() PORTB &= ~(1<<0)
-
- /* Type Defines: */
- /** Type define for a non-returning pointer to the start of the loaded application in flash
memory. */
- typedef void (*AppPtr_t)(void) ATTR_NO_RETURN;
-
- /* Function Prototypes: */
- void StartSketch(void);
- void LEDPulse(void);
-
- void CDC_Task(void);
- void SetupHardware(void);
-
- void EVENT_USB_Device_ConfigurationChanged(void);
-
- #if defined(INCLUDE_FROM_CATERINA_C) || defined(__DOXYGEN__)
- #if !defined(NO_BLOCK_SUPPORT)
- static void ReadWriteMemoryBlock(const uint8_t Command);
- #endif
- static uint8_t FetchNextCommandByte(void);
- static void WriteNextResponseByte(const uint8_t Response);
- #endif
-
-#endif
-
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2011.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaim all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ *
+ * Header file for BootloaderCDC.c.
+ */
+
+#ifndef _CDC_H_
+#define _CDC_H_
+
+ /* Includes: */
+ #include <avr/io.h>
+ #include <avr/wdt.h>
+ #include <avr/boot.h>
+ #include <avr/eeprom.h>
+ #include <avr/power.h>
+ #include <avr/interrupt.h>
+ #include <stdbool.h>
+
+ #include "Descriptors.h"
+
+ #include <LUFA/Drivers/USB/USB.h>
+ /* Macros: */
+ /** Version major of the CDC bootloader. */
+ #define BOOTLOADER_VERSION_MAJOR 0x01
+
+ /** Version minor of the CDC bootloader. */
+ #define BOOTLOADER_VERSION_MINOR 0x00
+
+ /** Hardware version major of the CDC bootloader. */
+ #define BOOTLOADER_HWVERSION_MAJOR 0x01
+
+ /** Hardware version minor of the CDC bootloader. */
+ #define BOOTLOADER_HWVERSION_MINOR 0x00
+
+ /** Eight character bootloader firmware identifier reported to the host when requested */
+ #define SOFTWARE_IDENTIFIER "CATERINA"
+
+ #define CPU_PRESCALE(n) (CLKPR = 0x80, CLKPR = (n))
+ #define LED_SETUP() DDRC |= (1<<7); DDRB |= (1<<0); DDRD |= (1<<5);
+ #define L_LED_OFF() PORTC &= ~(1<<7)
+ #define L_LED_ON() PORTC |= (1<<7)
+ #define L_LED_TOGGLE() PORTC ^= (1<<7)
+ #define TX_LED_OFF() PORTD |= (1<<5)
+ #define TX_LED_ON() PORTD &= ~(1<<5)
+ #define RX_LED_OFF() PORTB |= (1<<0)
+ #define RX_LED_ON() PORTB &= ~(1<<0)
+
+ /* Type Defines: */
+ /** Type define for a non-returning pointer to the start of the loaded application in flash
memory. */
+ typedef void (*AppPtr_t)(void) ATTR_NO_RETURN;
+
+ /* Function Prototypes: */
+ void StartSketch(void);
+ void LEDPulse(void);
+
+ void CDC_Task(void);
+ void SetupHardware(void);
+
+ void EVENT_USB_Device_ConfigurationChanged(void);
+
+ #if defined(INCLUDE_FROM_CATERINA_C) || defined(__DOXYGEN__)
+ #if !defined(NO_BLOCK_SUPPORT)
+ static void ReadWriteMemoryBlock(const uint8_t Command);
+ #endif
+ static uint8_t FetchNextCommandByte(void);
+ static void WriteNextResponseByte(const uint8_t Response);
+ #endif
+
+#endif
diff --git a/hardware/arduino/bootloaders/caterina-LilyPadUSB/Descriptors.c
b/hardware/arduino/bootloaders/caterina-LilyPadUSB/Descriptors.c
index f58519f..5380b8d 100644
--- a/hardware/arduino/bootloaders/caterina-LilyPadUSB/Descriptors.c
+++ b/hardware/arduino/bootloaders/caterina-LilyPadUSB/Descriptors.c
@@ -1,260 +1,259 @@
-/*
- LUFA Library
- Copyright (C) Dean Camera, 2011.
-
- dean [at] fourwalledcubicle [dot] com
- www.lufa-lib.org
-*/
-
-/*
- Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com)
-
- Permission to use, copy, modify, distribute, and sell this
- software and its documentation for any purpose is hereby granted
- without fee, provided that the above copyright notice appear in
- all copies and that both that the copyright notice and this
- permission notice and warranty disclaimer appear in supporting
- documentation, and that the name of the author not be used in
- advertising or publicity pertaining to distribution of the
- software without specific, written prior permission.
-
- The author disclaim all warranties with regard to this
- software, including all implied warranties of merchantability
- and fitness. In no event shall the author be liable for any
- special, indirect or consequential damages or any damages
- whatsoever resulting from loss of use, data or profits, whether
- in an action of contract, negligence or other tortious action,
- arising out of or in connection with the use or performance of
- this software.
-*/
-
-/** \file
- *
- * USB Device Descriptors, for library use when in USB device mode. Descriptors are special
- * computer-readable structures which the host requests upon device enumeration, to determine
- * the device's capabilities and functions.
- */
-
-#include "Descriptors.h"
-
-/** Device descriptor structure. This descriptor, located in SRAM memory, describes the overall
- * device characteristics, including the supported USB version, control endpoint size and the
- * number of device configurations. The descriptor is read out by the USB host when the enumeration
- * process begins.
- */
-const USB_Descriptor_Device_t DeviceDescriptor =
-{
- .Header = {.Size = sizeof(USB_Descriptor_Device_t), .Type = DTYPE_Device},
-
- .USBSpecification = VERSION_BCD(01.10),
- .Class = CDC_CSCP_CDCClass,
- .SubClass = CDC_CSCP_NoSpecificSubclass,
- .Protocol = CDC_CSCP_NoSpecificProtocol,
-
- .Endpoint0Size = FIXED_CONTROL_ENDPOINT_SIZE,
-
- .VendorID = DEVICE_VID,
- .ProductID = DEVICE_PID,
- .ReleaseNumber = VERSION_BCD(00.01),
-
- .ManufacturerStrIndex = 0x02,
- .ProductStrIndex = 0x01,
- .SerialNumStrIndex = NO_DESCRIPTOR,
-
- .NumberOfConfigurations = FIXED_NUM_CONFIGURATIONS
-};
-
-/** Configuration descriptor structure. This descriptor, located in SRAM memory, describes the usage
- * of the device in one of its supported configurations, including information about any device interfaces
- * and endpoints. The descriptor is read out by the USB host during the enumeration process when selecting
- * a configuration so that the host may correctly communicate with the USB device.
- */
-const USB_Descriptor_Configuration_t ConfigurationDescriptor =
-{
- .Config =
- {
- .Header = {.Size = sizeof(USB_Descriptor_Configuration_Header_t),
.Type = DTYPE_Configuration},
-
- .TotalConfigurationSize = sizeof(USB_Descriptor_Configuration_t),
- .TotalInterfaces = 2,
-
- .ConfigurationNumber = 1,
- .ConfigurationStrIndex = NO_DESCRIPTOR,
-
- .ConfigAttributes = USB_CONFIG_ATTR_BUSPOWERED,
-
- .MaxPowerConsumption = USB_CONFIG_POWER_MA(100)
- },
-
- .CDC_CCI_Interface =
- {
- .Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type =
DTYPE_Interface},
-
- .InterfaceNumber = 0,
- .AlternateSetting = 0,
-
- .TotalEndpoints = 1,
-
- .Class = CDC_CSCP_CDCClass,
- .SubClass = CDC_CSCP_ACMSubclass,
- .Protocol = CDC_CSCP_ATCommandProtocol,
-
- .InterfaceStrIndex = NO_DESCRIPTOR
- },
-
- .CDC_Functional_Header =
- {
- .Header = {.Size = sizeof(USB_CDC_Descriptor_FunctionalHeader_t),
.Type = DTYPE_CSInterface},
- .Subtype = 0x00,
-
- .CDCSpecification = VERSION_BCD(01.10),
- },
-
- .CDC_Functional_ACM =
- {
- .Header = {.Size = sizeof(USB_CDC_Descriptor_FunctionalACM_t), .Type
= DTYPE_CSInterface},
- .Subtype = 0x02,
-
- .Capabilities = 0x04,
- },
-
- .CDC_Functional_Union =
- {
- .Header = {.Size = sizeof(USB_CDC_Descriptor_FunctionalUnion_t),
.Type = DTYPE_CSInterface},
- .Subtype = 0x06,
-
- .MasterInterfaceNumber = 0,
- .SlaveInterfaceNumber = 1,
- },
-
- .CDC_NotificationEndpoint =
- {
- .Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type =
DTYPE_Endpoint},
-
- .EndpointAddress = (ENDPOINT_DIR_IN | CDC_NOTIFICATION_EPNUM),
- .Attributes = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC |
ENDPOINT_USAGE_DATA),
- .EndpointSize = CDC_NOTIFICATION_EPSIZE,
- .PollingIntervalMS = 0xFF
- },
-
- .CDC_DCI_Interface =
- {
- .Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type =
DTYPE_Interface},
-
- .InterfaceNumber = 1,
- .AlternateSetting = 0,
-
- .TotalEndpoints = 2,
-
- .Class = CDC_CSCP_CDCDataClass,
- .SubClass = CDC_CSCP_NoDataSubclass,
- .Protocol = CDC_CSCP_NoDataProtocol,
-
- .InterfaceStrIndex = NO_DESCRIPTOR
- },
-
- .CDC_DataOutEndpoint =
- {
- .Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type =
DTYPE_Endpoint},
-
- .EndpointAddress = (ENDPOINT_DIR_OUT | CDC_RX_EPNUM),
- .Attributes = (EP_TYPE_BULK | ENDPOINT_ATTR_NO_SYNC |
ENDPOINT_USAGE_DATA),
- .EndpointSize = CDC_TXRX_EPSIZE,
- .PollingIntervalMS = 0x01
- },
-
- .CDC_DataInEndpoint =
- {
- .Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type =
DTYPE_Endpoint},
-
- .EndpointAddress = (ENDPOINT_DIR_IN | CDC_TX_EPNUM),
- .Attributes = (EP_TYPE_BULK | ENDPOINT_ATTR_NO_SYNC |
ENDPOINT_USAGE_DATA),
- .EndpointSize = CDC_TXRX_EPSIZE,
- .PollingIntervalMS = 0x01
- }
-};
-
-/** Language descriptor structure. This descriptor, located in SRAM memory, is returned when the host
requests
- * the string descriptor with index 0 (the first index). It is actually an array of 16-bit integers, which
indicate
- * via the language ID table available at USB.org what languages the device supports for its string
descriptors.
- */
-const USB_Descriptor_String_t LanguageString =
-{
- .Header = {.Size = USB_STRING_LEN(1), .Type = DTYPE_String},
-
- .UnicodeString = {LANGUAGE_ID_ENG}
-};
-
-/** Product descriptor string. This is a Unicode string containing the product's details in human readable
form,
- * and is read out upon request by the host when the appropriate string ID is requested, listed in the
Device
- * Descriptor.
- */
-const USB_Descriptor_String_t ProductString =
-{
- .Header = {.Size = USB_STRING_LEN(16), .Type = DTYPE_String},
- #if DEVICE_PID == 0x9207
- .UnicodeString = L"LilyPadUSB "
- #else
- .UnicodeString = L"USB IO board "
- #endif
-};
-
-const USB_Descriptor_String_t ManufNameString =
-{
- .Header = {.Size = USB_STRING_LEN(20), .Type = DTYPE_String},
- #if DEVICE_VID == 0x1B4F
- .UnicodeString = L"SparkFun Electronics"
- #else
- .UnicodeString = L"Unknown "
- #endif
-};
-
-/** This function is called by the library when in device mode, and must be overridden (see LUFA library
"USB Descriptors"
- * documentation) by the application code so that the address and size of a requested descriptor can be
given
- * to the USB library. When the device receives a Get Descriptor request on the control endpoint, this
function
- * is called so that the descriptor details can be passed back and the appropriate descriptor sent back to
the
- * USB host.
- */
-uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue,
- const uint8_t wIndex,
- const void** const DescriptorAddress)
-{
- const uint8_t DescriptorType = (wValue >> 8);
- const uint8_t DescriptorNumber = (wValue & 0xFF);
-
- const void* Address = NULL;
- uint16_t Size = NO_DESCRIPTOR;
-
- switch (DescriptorType)
- {
- case DTYPE_Device:
- Address = &DeviceDescriptor;
- Size = sizeof(USB_Descriptor_Device_t);
- break;
- case DTYPE_Configuration:
- Address = &ConfigurationDescriptor;
- Size = sizeof(USB_Descriptor_Configuration_t);
- break;
- case DTYPE_String:
- if (!(DescriptorNumber))
- {
- Address = &LanguageString;
- Size = LanguageString.Header.Size;
- }
- else if (DescriptorNumber == DeviceDescriptor.ProductStrIndex)
- {
- Address = &ProductString;
- Size = ProductString.Header.Size;
- } else if (DescriptorNumber == DeviceDescriptor.ManufacturerStrIndex)
- {
- Address = &ManufNameString;
- Size = ManufNameString.Header.Size;
- }
-
- break;
- }
-
- *DescriptorAddress = Address;
- return Size;
-}
-
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2011.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaim all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ *
+ * USB Device Descriptors, for library use when in USB device mode. Descriptors are special
+ * computer-readable structures which the host requests upon device enumeration, to determine
+ * the device's capabilities and functions.
+ */
+
+#include "Descriptors.h"
+
+/** Device descriptor structure. This descriptor, located in SRAM memory, describes the overall
+ * device characteristics, including the supported USB version, control endpoint size and the
+ * number of device configurations. The descriptor is read out by the USB host when the enumeration
+ * process begins.
+ */
+const USB_Descriptor_Device_t DeviceDescriptor =
+{
+ .Header = {.Size = sizeof(USB_Descriptor_Device_t), .Type = DTYPE_Device},
+
+ .USBSpecification = VERSION_BCD(01.10),
+ .Class = CDC_CSCP_CDCClass,
+ .SubClass = CDC_CSCP_NoSpecificSubclass,
+ .Protocol = CDC_CSCP_NoSpecificProtocol,
+
+ .Endpoint0Size = FIXED_CONTROL_ENDPOINT_SIZE,
+
+ .VendorID = DEVICE_VID,
+ .ProductID = DEVICE_PID,
+ .ReleaseNumber = VERSION_BCD(00.01),
+
+ .ManufacturerStrIndex = 0x02,
+ .ProductStrIndex = 0x01,
+ .SerialNumStrIndex = NO_DESCRIPTOR,
+
+ .NumberOfConfigurations = FIXED_NUM_CONFIGURATIONS
+};
+
+/** Configuration descriptor structure. This descriptor, located in SRAM memory, describes the usage
+ * of the device in one of its supported configurations, including information about any device interfaces
+ * and endpoints. The descriptor is read out by the USB host during the enumeration process when selecting
+ * a configuration so that the host may correctly communicate with the USB device.
+ */
+const USB_Descriptor_Configuration_t ConfigurationDescriptor =
+{
+ .Config =
+ {
+ .Header = {.Size = sizeof(USB_Descriptor_Configuration_Header_t),
.Type = DTYPE_Configuration},
+
+ .TotalConfigurationSize = sizeof(USB_Descriptor_Configuration_t),
+ .TotalInterfaces = 2,
+
+ .ConfigurationNumber = 1,
+ .ConfigurationStrIndex = NO_DESCRIPTOR,
+
+ .ConfigAttributes = USB_CONFIG_ATTR_BUSPOWERED,
+
+ .MaxPowerConsumption = USB_CONFIG_POWER_MA(100)
+ },
+
+ .CDC_CCI_Interface =
+ {
+ .Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type =
DTYPE_Interface},
+
+ .InterfaceNumber = 0,
+ .AlternateSetting = 0,
+
+ .TotalEndpoints = 1,
+
+ .Class = CDC_CSCP_CDCClass,
+ .SubClass = CDC_CSCP_ACMSubclass,
+ .Protocol = CDC_CSCP_ATCommandProtocol,
+
+ .InterfaceStrIndex = NO_DESCRIPTOR
+ },
+
+ .CDC_Functional_Header =
+ {
+ .Header = {.Size = sizeof(USB_CDC_Descriptor_FunctionalHeader_t),
.Type = DTYPE_CSInterface},
+ .Subtype = 0x00,
+
+ .CDCSpecification = VERSION_BCD(01.10),
+ },
+
+ .CDC_Functional_ACM =
+ {
+ .Header = {.Size = sizeof(USB_CDC_Descriptor_FunctionalACM_t), .Type
= DTYPE_CSInterface},
+ .Subtype = 0x02,
+
+ .Capabilities = 0x04,
+ },
+
+ .CDC_Functional_Union =
+ {
+ .Header = {.Size = sizeof(USB_CDC_Descriptor_FunctionalUnion_t),
.Type = DTYPE_CSInterface},
+ .Subtype = 0x06,
+
+ .MasterInterfaceNumber = 0,
+ .SlaveInterfaceNumber = 1,
+ },
+
+ .CDC_NotificationEndpoint =
+ {
+ .Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type =
DTYPE_Endpoint},
+
+ .EndpointAddress = (ENDPOINT_DIR_IN | CDC_NOTIFICATION_EPNUM),
+ .Attributes = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC |
ENDPOINT_USAGE_DATA),
+ .EndpointSize = CDC_NOTIFICATION_EPSIZE,
+ .PollingIntervalMS = 0xFF
+ },
+
+ .CDC_DCI_Interface =
+ {
+ .Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type =
DTYPE_Interface},
+
+ .InterfaceNumber = 1,
+ .AlternateSetting = 0,
+
+ .TotalEndpoints = 2,
+
+ .Class = CDC_CSCP_CDCDataClass,
+ .SubClass = CDC_CSCP_NoDataSubclass,
+ .Protocol = CDC_CSCP_NoDataProtocol,
+
+ .InterfaceStrIndex = NO_DESCRIPTOR
+ },
+
+ .CDC_DataOutEndpoint =
+ {
+ .Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type =
DTYPE_Endpoint},
+
+ .EndpointAddress = (ENDPOINT_DIR_OUT | CDC_RX_EPNUM),
+ .Attributes = (EP_TYPE_BULK | ENDPOINT_ATTR_NO_SYNC |
ENDPOINT_USAGE_DATA),
+ .EndpointSize = CDC_TXRX_EPSIZE,
+ .PollingIntervalMS = 0x01
+ },
+
+ .CDC_DataInEndpoint =
+ {
+ .Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type =
DTYPE_Endpoint},
+
+ .EndpointAddress = (ENDPOINT_DIR_IN | CDC_TX_EPNUM),
+ .Attributes = (EP_TYPE_BULK | ENDPOINT_ATTR_NO_SYNC |
ENDPOINT_USAGE_DATA),
+ .EndpointSize = CDC_TXRX_EPSIZE,
+ .PollingIntervalMS = 0x01
+ }
+};
+
+/** Language descriptor structure. This descriptor, located in SRAM memory, is returned when the host
requests
+ * the string descriptor with index 0 (the first index). It is actually an array of 16-bit integers, which
indicate
+ * via the language ID table available at USB.org what languages the device supports for its string
descriptors.
+ */
+const USB_Descriptor_String_t LanguageString =
+{
+ .Header = {.Size = USB_STRING_LEN(1), .Type = DTYPE_String},
+
+ .UnicodeString = {LANGUAGE_ID_ENG}
+};
+
+/** Product descriptor string. This is a Unicode string containing the product's details in human readable
form,
+ * and is read out upon request by the host when the appropriate string ID is requested, listed in the
Device
+ * Descriptor.
+ */
+const USB_Descriptor_String_t ProductString =
+{
+ .Header = {.Size = USB_STRING_LEN(16), .Type = DTYPE_String},
+ #if DEVICE_PID == 0x9207
+ .UnicodeString = L"LilyPadUSB "
+ #else
+ .UnicodeString = L"USB IO board "
+ #endif
+};
+
+const USB_Descriptor_String_t ManufNameString =
+{
+ .Header = {.Size = USB_STRING_LEN(20), .Type = DTYPE_String},
+ #if DEVICE_VID == 0x1B4F
+ .UnicodeString = L"SparkFun Electronics"
+ #else
+ .UnicodeString = L"Unknown "
+ #endif
+};
+
+/** This function is called by the library when in device mode, and must be overridden (see LUFA library
"USB Descriptors"
+ * documentation) by the application code so that the address and size of a requested descriptor can be
given
+ * to the USB library. When the device receives a Get Descriptor request on the control endpoint, this
function
+ * is called so that the descriptor details can be passed back and the appropriate descriptor sent back to
the
+ * USB host.
+ */
+uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue,
+ const uint8_t wIndex,
+ const void** const DescriptorAddress)
+{
+ const uint8_t DescriptorType = (wValue >> 8);
+ const uint8_t DescriptorNumber = (wValue & 0xFF);
+
+ const void* Address = NULL;
+ uint16_t Size = NO_DESCRIPTOR;
+
+ switch (DescriptorType)
+ {
+ case DTYPE_Device:
+ Address = &DeviceDescriptor;
+ Size = sizeof(USB_Descriptor_Device_t);
+ break;
+ case DTYPE_Configuration:
+ Address = &ConfigurationDescriptor;
+ Size = sizeof(USB_Descriptor_Configuration_t);
+ break;
+ case DTYPE_String:
+ if (!(DescriptorNumber))
+ {
+ Address = &LanguageString;
+ Size = LanguageString.Header.Size;
+ }
+ else if (DescriptorNumber == DeviceDescriptor.ProductStrIndex)
+ {
+ Address = &ProductString;
+ Size = ProductString.Header.Size;
+ } else if (DescriptorNumber == DeviceDescriptor.ManufacturerStrIndex)
+ {
+ Address = &ManufNameString;
+ Size = ManufNameString.Header.Size;
+ }
+
+ break;
+ }
+
+ *DescriptorAddress = Address;
+ return Size;
+}
diff --git a/hardware/arduino/bootloaders/caterina-LilyPadUSB/Descriptors.h
b/hardware/arduino/bootloaders/caterina-LilyPadUSB/Descriptors.h
index 94091ae..f08104b 100644
--- a/hardware/arduino/bootloaders/caterina-LilyPadUSB/Descriptors.h
+++ b/hardware/arduino/bootloaders/caterina-LilyPadUSB/Descriptors.h
@@ -1,139 +1,138 @@
-/*
- LUFA Library
- Copyright (C) Dean Camera, 2011.
-
- dean [at] fourwalledcubicle [dot] com
- www.lufa-lib.org
-*/
-
-/*
- Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com)
-
- Permission to use, copy, modify, distribute, and sell this
- software and its documentation for any purpose is hereby granted
- without fee, provided that the above copyright notice appear in
- all copies and that both that the copyright notice and this
- permission notice and warranty disclaimer appear in supporting
- documentation, and that the name of the author not be used in
- advertising or publicity pertaining to distribution of the
- software without specific, written prior permission.
-
- The author disclaim all warranties with regard to this
- software, including all implied warranties of merchantability
- and fitness. In no event shall the author be liable for any
- special, indirect or consequential damages or any damages
- whatsoever resulting from loss of use, data or profits, whether
- in an action of contract, negligence or other tortious action,
- arising out of or in connection with the use or performance of
- this software.
-*/
-
-/** \file
- *
- * Header file for Descriptors.c.
- */
-
-#ifndef _DESCRIPTORS_H_
-#define _DESCRIPTORS_H_
-
- /* Includes: */
- #include <LUFA/Drivers/USB/USB.h>
-
- /* Macros: */
- #if defined(__AVR_AT90USB1287__)
- #define AVR_SIGNATURE_1 0x1E
- #define AVR_SIGNATURE_2 0x97
- #define AVR_SIGNATURE_3 0x82
- #elif defined(__AVR_AT90USB647__)
- #define AVR_SIGNATURE_1 0x1E
- #define AVR_SIGNATURE_2 0x96
- #define AVR_SIGNATURE_3 0x82
- #elif defined(__AVR_AT90USB1286__)
- #define AVR_SIGNATURE_1 0x1E
- #define AVR_SIGNATURE_2 0x97
- #define AVR_SIGNATURE_3 0x82
- #elif defined(__AVR_AT90USB646__)
- #define AVR_SIGNATURE_1 0x1E
- #define AVR_SIGNATURE_2 0x96
- #define AVR_SIGNATURE_3 0x82
- #elif defined(__AVR_ATmega32U6__)
- #define AVR_SIGNATURE_1 0x1E
- #define AVR_SIGNATURE_2 0x95
- #define AVR_SIGNATURE_3 0x88
- #elif defined(__AVR_ATmega32U4__)
- #define AVR_SIGNATURE_1 0x1E
- #define AVR_SIGNATURE_2 0x95
- #define AVR_SIGNATURE_3 0x87
- #elif defined(__AVR_ATmega16U4__)
- #define AVR_SIGNATURE_1 0x1E
- #define AVR_SIGNATURE_2 0x94
- #define AVR_SIGNATURE_3 0x88
- #elif defined(__AVR_ATmega32U2__)
- #define AVR_SIGNATURE_1 0x1E
- #define AVR_SIGNATURE_2 0x95
- #define AVR_SIGNATURE_3 0x8A
- #elif defined(__AVR_ATmega16U2__)
- #define AVR_SIGNATURE_1 0x1E
- #define AVR_SIGNATURE_2 0x94
- #define AVR_SIGNATURE_3 0x89
- #elif defined(__AVR_AT90USB162__)
- #define AVR_SIGNATURE_1 0x1E
- #define AVR_SIGNATURE_2 0x94
- #define AVR_SIGNATURE_3 0x82
- #elif defined(__AVR_ATmega8U2__)
- #define AVR_SIGNATURE_1 0x1E
- #define AVR_SIGNATURE_2 0x93
- #define AVR_SIGNATURE_3 0x89
- #elif defined(__AVR_AT90USB82__)
- #define AVR_SIGNATURE_1 0x1E
- #define AVR_SIGNATURE_2 0x94
- #define AVR_SIGNATURE_3 0x82
- #else
- #error The selected AVR part is not currently supported by this bootloader.
- #endif
-
- /** Endpoint number for the CDC control interface event notification endpoint. */
- #define CDC_NOTIFICATION_EPNUM 2
-
- /** Endpoint number for the CDC data interface TX (data IN) endpoint. */
- #define CDC_TX_EPNUM 3
-
- /** Endpoint number for the CDC data interface RX (data OUT) endpoint. */
- #define CDC_RX_EPNUM 4
-
- /** Size of the CDC data interface TX and RX data endpoint banks, in bytes. */
- #define CDC_TXRX_EPSIZE 16
-
- /** Size of the CDC control interface notification endpoint bank, in bytes. */
- #define CDC_NOTIFICATION_EPSIZE 8
-
- /* Type Defines: */
- /** Type define for the device configuration descriptor structure. This must be defined in the
- * application code, as the configuration descriptor contains several sub-descriptors which
- * vary between devices, and which describe the device's usage to the host.
- */
- typedef struct
- {
- USB_Descriptor_Configuration_Header_t Config;
-
- // CDC Control Interface
- USB_Descriptor_Interface_t CDC_CCI_Interface;
- USB_CDC_Descriptor_FunctionalHeader_t CDC_Functional_Header;
- USB_CDC_Descriptor_FunctionalACM_t CDC_Functional_ACM;
- USB_CDC_Descriptor_FunctionalUnion_t CDC_Functional_Union;
- USB_Descriptor_Endpoint_t CDC_NotificationEndpoint;
-
- // CDC Data Interface
- USB_Descriptor_Interface_t CDC_DCI_Interface;
- USB_Descriptor_Endpoint_t CDC_DataOutEndpoint;
- USB_Descriptor_Endpoint_t CDC_DataInEndpoint;
- } USB_Descriptor_Configuration_t;
-
- /* Function Prototypes: */
- uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue,
- const uint8_t wIndex,
- const void** const DescriptorAddress)
- ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(3);
-
-#endif
-
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2011.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaim all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ *
+ * Header file for Descriptors.c.
+ */
+
+#ifndef _DESCRIPTORS_H_
+#define _DESCRIPTORS_H_
+
+ /* Includes: */
+ #include <LUFA/Drivers/USB/USB.h>
+
+ /* Macros: */
+ #if defined(__AVR_AT90USB1287__)
+ #define AVR_SIGNATURE_1 0x1E
+ #define AVR_SIGNATURE_2 0x97
+ #define AVR_SIGNATURE_3 0x82
+ #elif defined(__AVR_AT90USB647__)
+ #define AVR_SIGNATURE_1 0x1E
+ #define AVR_SIGNATURE_2 0x96
+ #define AVR_SIGNATURE_3 0x82
+ #elif defined(__AVR_AT90USB1286__)
+ #define AVR_SIGNATURE_1 0x1E
+ #define AVR_SIGNATURE_2 0x97
+ #define AVR_SIGNATURE_3 0x82
+ #elif defined(__AVR_AT90USB646__)
+ #define AVR_SIGNATURE_1 0x1E
+ #define AVR_SIGNATURE_2 0x96
+ #define AVR_SIGNATURE_3 0x82
+ #elif defined(__AVR_ATmega32U6__)
+ #define AVR_SIGNATURE_1 0x1E
+ #define AVR_SIGNATURE_2 0x95
+ #define AVR_SIGNATURE_3 0x88
+ #elif defined(__AVR_ATmega32U4__)
+ #define AVR_SIGNATURE_1 0x1E
+ #define AVR_SIGNATURE_2 0x95
+ #define AVR_SIGNATURE_3 0x87
+ #elif defined(__AVR_ATmega16U4__)
+ #define AVR_SIGNATURE_1 0x1E
+ #define AVR_SIGNATURE_2 0x94
+ #define AVR_SIGNATURE_3 0x88
+ #elif defined(__AVR_ATmega32U2__)
+ #define AVR_SIGNATURE_1 0x1E
+ #define AVR_SIGNATURE_2 0x95
+ #define AVR_SIGNATURE_3 0x8A
+ #elif defined(__AVR_ATmega16U2__)
+ #define AVR_SIGNATURE_1 0x1E
+ #define AVR_SIGNATURE_2 0x94
+ #define AVR_SIGNATURE_3 0x89
+ #elif defined(__AVR_AT90USB162__)
+ #define AVR_SIGNATURE_1 0x1E
+ #define AVR_SIGNATURE_2 0x94
+ #define AVR_SIGNATURE_3 0x82
+ #elif defined(__AVR_ATmega8U2__)
+ #define AVR_SIGNATURE_1 0x1E
+ #define AVR_SIGNATURE_2 0x93
+ #define AVR_SIGNATURE_3 0x89
+ #elif defined(__AVR_AT90USB82__)
+ #define AVR_SIGNATURE_1 0x1E
+ #define AVR_SIGNATURE_2 0x94
+ #define AVR_SIGNATURE_3 0x82
+ #else
+ #error The selected AVR part is not currently supported by this bootloader.
+ #endif
+
+ /** Endpoint number for the CDC control interface event notification endpoint. */
+ #define CDC_NOTIFICATION_EPNUM 2
+
+ /** Endpoint number for the CDC data interface TX (data IN) endpoint. */
+ #define CDC_TX_EPNUM 3
+
+ /** Endpoint number for the CDC data interface RX (data OUT) endpoint. */
+ #define CDC_RX_EPNUM 4
+
+ /** Size of the CDC data interface TX and RX data endpoint banks, in bytes. */
+ #define CDC_TXRX_EPSIZE 16
+
+ /** Size of the CDC control interface notification endpoint bank, in bytes. */
+ #define CDC_NOTIFICATION_EPSIZE 8
+
+ /* Type Defines: */
+ /** Type define for the device configuration descriptor structure. This must be defined in the
+ * application code, as the configuration descriptor contains several sub-descriptors which
+ * vary between devices, and which describe the device's usage to the host.
+ */
+ typedef struct
+ {
+ USB_Descriptor_Configuration_Header_t Config;
+
+ // CDC Control Interface
+ USB_Descriptor_Interface_t CDC_CCI_Interface;
+ USB_CDC_Descriptor_FunctionalHeader_t CDC_Functional_Header;
+ USB_CDC_Descriptor_FunctionalACM_t CDC_Functional_ACM;
+ USB_CDC_Descriptor_FunctionalUnion_t CDC_Functional_Union;
+ USB_Descriptor_Endpoint_t CDC_NotificationEndpoint;
+
+ // CDC Data Interface
+ USB_Descriptor_Interface_t CDC_DCI_Interface;
+ USB_Descriptor_Endpoint_t CDC_DataOutEndpoint;
+ USB_Descriptor_Endpoint_t CDC_DataInEndpoint;
+ } USB_Descriptor_Configuration_t;
+
+ /* Function Prototypes: */
+ uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue,
+ const uint8_t wIndex,
+ const void** const DescriptorAddress)
+ ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(3);
+
+#endif
diff --git a/hardware/arduino/bootloaders/caterina-LilyPadUSB/Readme.txt
b/hardware/arduino/bootloaders/caterina-LilyPadUSB/Readme.txt
index 9656a6e..d066611 100644
--- a/hardware/arduino/bootloaders/caterina-LilyPadUSB/Readme.txt
+++ b/hardware/arduino/bootloaders/caterina-LilyPadUSB/Readme.txt
@@ -1,11 +1,11 @@
-Building the bootloader for the LilyPadUSB
-1. Download the LUFA-111009 file (http://fourwalledcubicle.com/blog/2011/10/lufa-111009-released/).
-2. Extract that file directly to the Caterina-LilyPadUSB bootloader directory.
-3. Open a command prompt in the Caterina-LilyPadUSB bootloader directory.
-4. Type 'make'.
-5. Enjoy!
-
-Programming the bootloader for the LilyPadUSB
-1. Open a command prompt in the Caterina-LilyPadUSB folder.
-2. Connect your programmer- use a 2x3 .1" header, pressed against the programming vias.
+Building the bootloader for the LilyPadUSB
+1. Download the LUFA-111009 file (http://fourwalledcubicle.com/blog/2011/10/lufa-111009-released/).
+2. Extract that file directly to the Caterina-LilyPadUSB bootloader directory.
+3. Open a command prompt in the Caterina-LilyPadUSB bootloader directory.
+4. Type 'make'.
+5. Enjoy!
+
+Programming the bootloader for the LilyPadUSB
+1. Open a command prompt in the Caterina-LilyPadUSB folder.
+2. Connect your programmer- use a 2x3 .1" header, pressed against the programming vias.
3. Type 'make program' into the command prompt.
\ No newline at end of file
diff --git a/hardware/arduino/bootloaders/caterina/Caterina.c
b/hardware/arduino/bootloaders/caterina/Caterina.c
index 9860b3a..8cd7914 100644
--- a/hardware/arduino/bootloaders/caterina/Caterina.c
+++ b/hardware/arduino/bootloaders/caterina/Caterina.c
@@ -1,714 +1,713 @@
-/*
- LUFA Library
- Copyright (C) Dean Camera, 2011.
-
- dean [at] fourwalledcubicle [dot] com
- www.lufa-lib.org
-*/
-
-/*
- Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com)
-
- Permission to use, copy, modify, distribute, and sell this
- software and its documentation for any purpose is hereby granted
- without fee, provided that the above copyright notice appear in
- all copies and that both that the copyright notice and this
- permission notice and warranty disclaimer appear in supporting
- documentation, and that the name of the author not be used in
- advertising or publicity pertaining to distribution of the
- software without specific, written prior permission.
-
- The author disclaim all warranties with regard to this
- software, including all implied warranties of merchantability
- and fitness. In no event shall the author be liable for any
- special, indirect or consequential damages or any damages
- whatsoever resulting from loss of use, data or profits, whether
- in an action of contract, negligence or other tortious action,
- arising out of or in connection with the use or performance of
- this software.
-*/
-
-/** \file
- *
- * Main source file for the CDC class bootloader. This file contains the complete bootloader logic.
- */
-
-#define INCLUDE_FROM_CATERINA_C
-#include "Caterina.h"
-
-/** Contains the current baud rate and other settings of the first virtual serial port. This must be
retained as some
- * operating systems will not open the port unless the settings can be set successfully.
- */
-static CDC_LineEncoding_t LineEncoding = { .BaudRateBPS = 0,
- .CharFormat = CDC_LINEENCODING_OneStopBit,
- .ParityType = CDC_PARITY_None,
- .DataBits = 8 };
-
-/** Current address counter. This stores the current address of the FLASH or EEPROM as set by the host,
- * and is used when reading or writing to the AVRs memory (either FLASH or EEPROM depending on the issued
- * command.)
- */
-static uint32_t CurrAddress;
-
-/** Flag to indicate if the bootloader should be running, or should exit and allow the application code to
run
- * via a watchdog reset. When cleared the bootloader will exit, starting the watchdog and entering an
infinite
- * loop until the AVR restarts and the application runs.
- */
-static bool RunBootloader = true;
-
-/* Pulse generation counters to keep track of the time remaining for each pulse type */
-#define TX_RX_LED_PULSE_PERIOD 100
-uint16_t TxLEDPulse = 0; // time remaining for Tx LED pulse
-uint16_t RxLEDPulse = 0; // time remaining for Rx LED pulse
-
-/* Bootloader timeout timer */
-#define TIMEOUT_PERIOD 8000
-uint16_t Timeout = 0;
-
-uint16_t bootKey = 0x7777;
-volatile uint16_t *const bootKeyPtr = (volatile uint16_t *)0x0800;
-
-void StartSketch(void)
-{
- cli();
-
- /* Undo TIMER1 setup and clear the count before running the sketch */
- TIMSK1 = 0;
- TCCR1B = 0;
- TCNT1H = 0; // 16-bit write to TCNT1 requires high byte be written first
- TCNT1L = 0;
-
- /* Relocate the interrupt vector table to the application section */
- MCUCR = (1 << IVCE);
- MCUCR = 0;
-
- L_LED_OFF();
- TX_LED_OFF();
- RX_LED_OFF();
-
- /* jump to beginning of application space */
- __asm__ volatile("jmp 0x0000");
-}
-
-/* Breathing animation on L LED indicates bootloader is running */
-uint16_t LLEDPulse;
-void LEDPulse(void)
-{
- LLEDPulse++;
- uint8_t p = LLEDPulse >> 8;
- if (p > 127)
- p = 254-p;
- p += p;
- if (((uint8_t)LLEDPulse) > p)
- L_LED_OFF();
- else
- L_LED_ON();
-}
-
-/** Main program entry point. This routine configures the hardware required by the bootloader, then
continuously
- * runs the bootloader processing routine until it times out or is instructed to exit.
- */
-int main(void)
-{
- /* Save the value of the boot key memory before it is overwritten */
- uint16_t bootKeyPtrVal = *bootKeyPtr;
- *bootKeyPtr = 0;
-
- /* Check the reason for the reset so we can act accordingly */
- uint8_t mcusr_state = MCUSR; // store the initial state of the Status register
- MCUSR = 0; // clear all reset flags
-
- /* Watchdog may be configured with a 15 ms period so must disable it before going any further */
- wdt_disable();
-
- if (mcusr_state & (1<<EXTRF)) {
- // External reset - we should continue to self-programming mode.
- } else if ((mcusr_state & (1<<PORF)) && (pgm_read_word(0) != 0xFFFF)) {
- // After a power-on reset skip the bootloader and jump straight to sketch
- // if one exists.
- StartSketch();
- } else if ((mcusr_state & (1<<WDRF)) && (bootKeyPtrVal != bootKey) && (pgm_read_word(0) != 0xFFFF)) {
- // If it looks like an "accidental" watchdog reset then start the sketch.
- StartSketch();
- }
-
- /* Setup hardware required for the bootloader */
- SetupHardware();
-
- /* Enable global interrupts so that the USB stack can function */
- sei();
-
- Timeout = 0;
-
- while (RunBootloader)
- {
- CDC_Task();
- USB_USBTask();
- /* Time out and start the sketch if one is present */
- if (Timeout > TIMEOUT_PERIOD)
- RunBootloader = false;
-
- LEDPulse();
- }
-
- /* Disconnect from the host - USB interface will be reset later along with the AVR */
- USB_Detach();
-
- /* Jump to beginning of application space to run the sketch - do not reset */
- StartSketch();
-}
-
-/** Configures all hardware required for the bootloader. */
-void SetupHardware(void)
-{
- /* Disable watchdog if enabled by bootloader/fuses */
- MCUSR &= ~(1 << WDRF);
- wdt_disable();
-
- /* Disable clock division */
- clock_prescale_set(clock_div_1);
-
- /* Relocate the interrupt vector table to the bootloader section */
- MCUCR = (1 << IVCE);
- MCUCR = (1 << IVSEL);
-
- LED_SETUP();
- CPU_PRESCALE(0);
- L_LED_OFF();
- TX_LED_OFF();
- RX_LED_OFF();
-
- /* Initialize TIMER1 to handle bootloader timeout and LED tasks.
- * With 16 MHz clock and 1/64 prescaler, timer 1 is clocked at 250 kHz
- * Our chosen compare match generates an interrupt every 1 ms.
- * This interrupt is disabled selectively when doing memory reading, erasing,
- * or writing since SPM has tight timing requirements.
- */
- OCR1AH = 0;
- OCR1AL = 250;
- TIMSK1 = (1 << OCIE1A); // enable timer 1 output compare A match
interrupt
- TCCR1B = ((1 << CS11) | (1 << CS10)); // 1/64 prescaler on timer 1 input
-
- /* Initialize USB Subsystem */
- USB_Init();
-}
-
-//uint16_t ctr = 0;
-ISR(TIMER1_COMPA_vect, ISR_BLOCK)
-{
- /* Reset counter */
- TCNT1H = 0;
- TCNT1L = 0;
-
- /* Check whether the TX or RX LED one-shot period has elapsed. if so, turn off the LED */
- if (TxLEDPulse && !(--TxLEDPulse))
- TX_LED_OFF();
- if (RxLEDPulse && !(--RxLEDPulse))
- RX_LED_OFF();
-
- if (pgm_read_word(0) != 0xFFFF)
- Timeout++;
-}
-
-/** Event handler for the USB_ConfigurationChanged event. This configures the device's endpoints ready
- * to relay data to and from the attached USB host.
- */
-void EVENT_USB_Device_ConfigurationChanged(void)
-{
- /* Setup CDC Notification, Rx and Tx Endpoints */
- Endpoint_ConfigureEndpoint(CDC_NOTIFICATION_EPNUM, EP_TYPE_INTERRUPT,
- ENDPOINT_DIR_IN, CDC_NOTIFICATION_EPSIZE,
- ENDPOINT_BANK_SINGLE);
-
- Endpoint_ConfigureEndpoint(CDC_TX_EPNUM, EP_TYPE_BULK,
- ENDPOINT_DIR_IN, CDC_TXRX_EPSIZE,
- ENDPOINT_BANK_SINGLE);
-
- Endpoint_ConfigureEndpoint(CDC_RX_EPNUM, EP_TYPE_BULK,
- ENDPOINT_DIR_OUT, CDC_TXRX_EPSIZE,
- ENDPOINT_BANK_SINGLE);
-}
-
-/** Event handler for the USB_ControlRequest event. This is used to catch and process control requests sent
to
- * the device from the USB host before passing along unhandled control requests to the library for
processing
- * internally.
- */
-void EVENT_USB_Device_ControlRequest(void)
-{
- /* Ignore any requests that aren't directed to the CDC interface */
- if ((USB_ControlRequest.bmRequestType & (CONTROL_REQTYPE_TYPE | CONTROL_REQTYPE_RECIPIENT)) !=
- (REQTYPE_CLASS | REQREC_INTERFACE))
- {
- return;
- }
-
- /* Process CDC specific control requests */
- switch (USB_ControlRequest.bRequest)
- {
- case CDC_REQ_GetLineEncoding:
- if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS |
REQREC_INTERFACE))
- {
- Endpoint_ClearSETUP();
-
- /* Write the line coding data to the control endpoint */
- Endpoint_Write_Control_Stream_LE(&LineEncoding, sizeof(CDC_LineEncoding_t));
- Endpoint_ClearOUT();
- }
-
- break;
- case CDC_REQ_SetLineEncoding:
- if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS |
REQREC_INTERFACE))
- {
- Endpoint_ClearSETUP();
-
- /* Read the line coding data in from the host into the global struct */
- Endpoint_Read_Control_Stream_LE(&LineEncoding, sizeof(CDC_LineEncoding_t));
- Endpoint_ClearIN();
- }
-
- break;
- }
-}
-
-#if !defined(NO_BLOCK_SUPPORT)
-/** Reads or writes a block of EEPROM or FLASH memory to or from the appropriate CDC data endpoint, depending
- * on the AVR910 protocol command issued.
- *
- * \param[in] Command Single character AVR910 protocol command indicating what memory operation to perform
- */
-static void ReadWriteMemoryBlock(const uint8_t Command)
-{
- uint16_t BlockSize;
- char MemoryType;
-
- bool HighByte = false;
- uint8_t LowByte = 0;
-
- BlockSize = (FetchNextCommandByte() << 8);
- BlockSize |= FetchNextCommandByte();
-
- MemoryType = FetchNextCommandByte();
-
- if ((MemoryType != 'E') && (MemoryType != 'F'))
- {
- /* Send error byte back to the host */
- WriteNextResponseByte('?');
-
- return;
- }
-
- /* Disable timer 1 interrupt - can't afford to process nonessential interrupts
- * while doing SPM tasks */
- TIMSK1 = 0;
-
- /* Check if command is to read memory */
- if (Command == 'g')
- {
- /* Re-enable RWW section */
- boot_rww_enable();
-
- while (BlockSize--)
- {
- if (MemoryType == 'F')
- {
- /* Read the next FLASH byte from the current FLASH page */
- #if (FLASHEND > 0xFFFF)
- WriteNextResponseByte(pgm_read_byte_far(CurrAddress | HighByte));
- #else
- WriteNextResponseByte(pgm_read_byte(CurrAddress | HighByte));
- #endif
-
- /* If both bytes in current word have been read, increment the address
counter */
- if (HighByte)
- CurrAddress += 2;
-
- HighByte = !HighByte;
- }
- else
- {
- /* Read the next EEPROM byte into the endpoint */
- WriteNextResponseByte(eeprom_read_byte((uint8_t*)(intptr_t)(CurrAddress >>
1)));
-
- /* Increment the address counter after use */
- CurrAddress += 2;
- }
- }
- }
- else
- {
- uint32_t PageStartAddress = CurrAddress;
-
- if (MemoryType == 'F')
- {
- boot_page_erase(PageStartAddress);
- boot_spm_busy_wait();
- }
-
- while (BlockSize--)
- {
- if (MemoryType == 'F')
- {
- /* If both bytes in current word have been written, increment the address
counter */
- if (HighByte)
- {
- /* Write the next FLASH word to the current FLASH page */
- boot_page_fill(CurrAddress, ((FetchNextCommandByte() << 8) |
LowByte));
-
- /* Increment the address counter after use */
- CurrAddress += 2;
- }
- else
- {
- LowByte = FetchNextCommandByte();
- }
-
- HighByte = !HighByte;
- }
- else
- {
- /* Write the next EEPROM byte from the endpoint */
- eeprom_write_byte((uint8_t*)((intptr_t)(CurrAddress >> 1)),
FetchNextCommandByte());
-
- /* Increment the address counter after use */
- CurrAddress += 2;
- }
- }
-
- /* If in FLASH programming mode, commit the page after writing */
- if (MemoryType == 'F')
- {
- /* Commit the flash page to memory */
- boot_page_write(PageStartAddress);
-
- /* Wait until write operation has completed */
- boot_spm_busy_wait();
- }
-
- /* Send response byte back to the host */
- WriteNextResponseByte('\r');
- }
-
- /* Re-enable timer 1 interrupt disabled earlier in this routine */
- TIMSK1 = (1 << OCIE1A);
-}
-#endif
-
-/** Retrieves the next byte from the host in the CDC data OUT endpoint, and clears the endpoint bank if
needed
- * to allow reception of the next data packet from the host.
- *
- * \return Next received byte from the host in the CDC data OUT endpoint
- */
-static uint8_t FetchNextCommandByte(void)
-{
- /* Select the OUT endpoint so that the next data byte can be read */
- Endpoint_SelectEndpoint(CDC_RX_EPNUM);
-
- /* If OUT endpoint empty, clear it and wait for the next packet from the host */
- while (!(Endpoint_IsReadWriteAllowed()))
- {
- Endpoint_ClearOUT();
-
- while (!(Endpoint_IsOUTReceived()))
- {
- if (USB_DeviceState == DEVICE_STATE_Unattached)
- return 0;
- }
- }
-
- /* Fetch the next byte from the OUT endpoint */
- return Endpoint_Read_8();
-}
-
-/** Writes the next response byte to the CDC data IN endpoint, and sends the endpoint back if needed to free
up the
- * bank when full ready for the next byte in the packet to the host.
- *
- * \param[in] Response Next response byte to send to the host
- */
-static void WriteNextResponseByte(const uint8_t Response)
-{
- /* Select the IN endpoint so that the next data byte can be written */
- Endpoint_SelectEndpoint(CDC_TX_EPNUM);
-
- /* If IN endpoint full, clear it and wait until ready for the next packet to the host */
- if (!(Endpoint_IsReadWriteAllowed()))
- {
- Endpoint_ClearIN();
-
- while (!(Endpoint_IsINReady()))
- {
- if (USB_DeviceState == DEVICE_STATE_Unattached)
- return;
- }
- }
-
- /* Write the next byte to the IN endpoint */
- Endpoint_Write_8(Response);
-
- TX_LED_ON();
- TxLEDPulse = TX_RX_LED_PULSE_PERIOD;
-}
-
-#define STK_OK 0x10
-#define STK_INSYNC 0x14 // ' '
-#define CRC_EOP 0x20 // 'SPACE'
-#define STK_GET_SYNC 0x30 // '0'
-
-#define STK_GET_PARAMETER 0x41 // 'A'
-#define STK_SET_DEVICE 0x42 // 'B'
-#define STK_SET_DEVICE_EXT 0x45 // 'E'
-#define STK_LOAD_ADDRESS 0x55 // 'U'
-#define STK_UNIVERSAL 0x56 // 'V'
-#define STK_PROG_PAGE 0x64 // 'd'
-#define STK_READ_PAGE 0x74 // 't'
-#define STK_READ_SIGN 0x75 // 'u'
-
-/** Task to read in AVR910 commands from the CDC data OUT endpoint, process them, perform the required
actions
- * and send the appropriate response back to the host.
- */
-void CDC_Task(void)
-{
- /* Select the OUT endpoint */
- Endpoint_SelectEndpoint(CDC_RX_EPNUM);
-
- /* Check if endpoint has a command in it sent from the host */
- if (!(Endpoint_IsOUTReceived()))
- return;
-
- RX_LED_ON();
- RxLEDPulse = TX_RX_LED_PULSE_PERIOD;
-
- /* Read in the bootloader command (first byte sent from host) */
- uint8_t Command = FetchNextCommandByte();
-
- if (Command == 'E')
- {
- /* We nearly run out the bootloader timeout clock,
- * leaving just a few hundred milliseconds so the
- * bootloder has time to respond and service any
- * subsequent requests */
- Timeout = TIMEOUT_PERIOD - 500;
-
- /* Re-enable RWW section - must be done here in case
- * user has disabled verification on upload. */
- boot_rww_enable_safe();
-
- // Send confirmation byte back to the host
- WriteNextResponseByte('\r');
- }
- else if (Command == 'T')
- {
- FetchNextCommandByte();
-
- // Send confirmation byte back to the host
- WriteNextResponseByte('\r');
- }
- else if ((Command == 'L') || (Command == 'P'))
- {
- // Send confirmation byte back to the host
- WriteNextResponseByte('\r');
- }
- else if (Command == 't')
- {
- // Return ATMEGA128 part code - this is only to allow AVRProg to use the bootloader
- WriteNextResponseByte(0x44);
- WriteNextResponseByte(0x00);
- }
- else if (Command == 'a')
- {
- // Indicate auto-address increment is supported
- WriteNextResponseByte('Y');
- }
- else if (Command == 'A')
- {
- // Set the current address to that given by the host
- CurrAddress = (FetchNextCommandByte() << 9);
- CurrAddress |= (FetchNextCommandByte() << 1);
-
- // Send confirmation byte back to the host
- WriteNextResponseByte('\r');
- }
- else if (Command == 'p')
- {
- // Indicate serial programmer back to the host
- WriteNextResponseByte('S');
- }
- else if (Command == 'S')
- {
- // Write the 7-byte software identifier to the endpoint
- for (uint8_t CurrByte = 0; CurrByte < 7; CurrByte++)
- WriteNextResponseByte(SOFTWARE_IDENTIFIER[CurrByte]);
- }
- else if (Command == 'V')
- {
- WriteNextResponseByte('0' + BOOTLOADER_VERSION_MAJOR);
- WriteNextResponseByte('0' + BOOTLOADER_VERSION_MINOR);
- }
- else if (Command == 's')
- {
- WriteNextResponseByte(AVR_SIGNATURE_3);
- WriteNextResponseByte(AVR_SIGNATURE_2);
- WriteNextResponseByte(AVR_SIGNATURE_1);
- }
- else if (Command == 'e')
- {
- // Clear the application section of flash
- for (uint32_t CurrFlashAddress = 0; CurrFlashAddress < BOOT_START_ADDR; CurrFlashAddress +=
SPM_PAGESIZE)
- {
- boot_page_erase(CurrFlashAddress);
- boot_spm_busy_wait();
- boot_page_write(CurrFlashAddress);
- boot_spm_busy_wait();
- }
-
- // Send confirmation byte back to the host
- WriteNextResponseByte('\r');
- }
- #if !defined(NO_LOCK_BYTE_WRITE_SUPPORT)
- else if (Command == 'l')
- {
- // Set the lock bits to those given by the host
- boot_lock_bits_set(FetchNextCommandByte());
-
- // Send confirmation byte back to the host
- WriteNextResponseByte('\r');
- }
- #endif
- else if (Command == 'r')
- {
- WriteNextResponseByte(boot_lock_fuse_bits_get(GET_LOCK_BITS));
- }
- else if (Command == 'F')
- {
- WriteNextResponseByte(boot_lock_fuse_bits_get(GET_LOW_FUSE_BITS));
- }
- else if (Command == 'N')
- {
- WriteNextResponseByte(boot_lock_fuse_bits_get(GET_HIGH_FUSE_BITS));
- }
- else if (Command == 'Q')
- {
- WriteNextResponseByte(boot_lock_fuse_bits_get(GET_EXTENDED_FUSE_BITS));
- }
- #if !defined(NO_BLOCK_SUPPORT)
- else if (Command == 'b')
- {
- WriteNextResponseByte('Y');
-
- // Send block size to the host
- WriteNextResponseByte(SPM_PAGESIZE >> 8);
- WriteNextResponseByte(SPM_PAGESIZE & 0xFF);
- }
- else if ((Command == 'B') || (Command == 'g'))
- {
- // Keep resetting the timeout counter if we're receiving self-programming instructions
- Timeout = 0;
- // Delegate the block write/read to a separate function for clarity
- ReadWriteMemoryBlock(Command);
- }
- #endif
- #if !defined(NO_FLASH_BYTE_SUPPORT)
- else if (Command == 'C')
- {
- // Write the high byte to the current flash page
- boot_page_fill(CurrAddress, FetchNextCommandByte());
-
- // Send confirmation byte back to the host
- WriteNextResponseByte('\r');
- }
- else if (Command == 'c')
- {
- // Write the low byte to the current flash page
- boot_page_fill(CurrAddress | 0x01, FetchNextCommandByte());
-
- // Increment the address
- CurrAddress += 2;
-
- // Send confirmation byte back to the host
- WriteNextResponseByte('\r');
- }
- else if (Command == 'm')
- {
- // Commit the flash page to memory
- boot_page_write(CurrAddress);
-
- // Wait until write operation has completed
- boot_spm_busy_wait();
-
- // Send confirmation byte back to the host
- WriteNextResponseByte('\r');
- }
- else if (Command == 'R')
- {
- #if (FLASHEND > 0xFFFF)
- uint16_t ProgramWord = pgm_read_word_far(CurrAddress);
- #else
- uint16_t ProgramWord = pgm_read_word(CurrAddress);
- #endif
-
- WriteNextResponseByte(ProgramWord >> 8);
- WriteNextResponseByte(ProgramWord & 0xFF);
- }
- #endif
- #if !defined(NO_EEPROM_BYTE_SUPPORT)
- else if (Command == 'D')
- {
- // Read the byte from the endpoint and write it to the EEPROM
- eeprom_write_byte((uint8_t*)((intptr_t)(CurrAddress >> 1)), FetchNextCommandByte());
-
- // Increment the address after use
- CurrAddress += 2;
-
- // Send confirmation byte back to the host
- WriteNextResponseByte('\r');
- }
- else if (Command == 'd')
- {
- // Read the EEPROM byte and write it to the endpoint
- WriteNextResponseByte(eeprom_read_byte((uint8_t*)((intptr_t)(CurrAddress >> 1))));
-
- // Increment the address after use
- CurrAddress += 2;
- }
- #endif
- else if (Command != 27)
- {
- // Unknown (non-sync) command, return fail code
- WriteNextResponseByte('?');
- }
-
-
- /* Select the IN endpoint */
- Endpoint_SelectEndpoint(CDC_TX_EPNUM);
-
- /* Remember if the endpoint is completely full before clearing it */
- bool IsEndpointFull = !(Endpoint_IsReadWriteAllowed());
-
- /* Send the endpoint data to the host */
- Endpoint_ClearIN();
-
- /* If a full endpoint's worth of data was sent, we need to send an empty packet afterwards to signal
end of transfer */
- if (IsEndpointFull)
- {
- while (!(Endpoint_IsINReady()))
- {
- if (USB_DeviceState == DEVICE_STATE_Unattached)
- return;
- }
-
- Endpoint_ClearIN();
- }
-
- /* Wait until the data has been sent to the host */
- while (!(Endpoint_IsINReady()))
- {
- if (USB_DeviceState == DEVICE_STATE_Unattached)
- return;
- }
-
- /* Select the OUT endpoint */
- Endpoint_SelectEndpoint(CDC_RX_EPNUM);
-
- /* Acknowledge the command from the host */
- Endpoint_ClearOUT();
-}
-
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2011.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaim all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ *
+ * Main source file for the CDC class bootloader. This file contains the complete bootloader logic.
+ */
+
+#define INCLUDE_FROM_CATERINA_C
+#include "Caterina.h"
+
+/** Contains the current baud rate and other settings of the first virtual serial port. This must be
retained as some
+ * operating systems will not open the port unless the settings can be set successfully.
+ */
+static CDC_LineEncoding_t LineEncoding = { .BaudRateBPS = 0,
+ .CharFormat = CDC_LINEENCODING_OneStopBit,
+ .ParityType = CDC_PARITY_None,
+ .DataBits = 8 };
+
+/** Current address counter. This stores the current address of the FLASH or EEPROM as set by the host,
+ * and is used when reading or writing to the AVRs memory (either FLASH or EEPROM depending on the issued
+ * command.)
+ */
+static uint32_t CurrAddress;
+
+/** Flag to indicate if the bootloader should be running, or should exit and allow the application code to
run
+ * via a watchdog reset. When cleared the bootloader will exit, starting the watchdog and entering an
infinite
+ * loop until the AVR restarts and the application runs.
+ */
+static bool RunBootloader = true;
+
+/* Pulse generation counters to keep track of the time remaining for each pulse type */
+#define TX_RX_LED_PULSE_PERIOD 100
+uint16_t TxLEDPulse = 0; // time remaining for Tx LED pulse
+uint16_t RxLEDPulse = 0; // time remaining for Rx LED pulse
+
+/* Bootloader timeout timer */
+#define TIMEOUT_PERIOD 8000
+uint16_t Timeout = 0;
+
+uint16_t bootKey = 0x7777;
+volatile uint16_t *const bootKeyPtr = (volatile uint16_t *)0x0800;
+
+void StartSketch(void)
+{
+ cli();
+
+ /* Undo TIMER1 setup and clear the count before running the sketch */
+ TIMSK1 = 0;
+ TCCR1B = 0;
+ TCNT1H = 0; // 16-bit write to TCNT1 requires high byte be written first
+ TCNT1L = 0;
+
+ /* Relocate the interrupt vector table to the application section */
+ MCUCR = (1 << IVCE);
+ MCUCR = 0;
+
+ L_LED_OFF();
+ TX_LED_OFF();
+ RX_LED_OFF();
+
+ /* jump to beginning of application space */
+ __asm__ volatile("jmp 0x0000");
+}
+
+/* Breathing animation on L LED indicates bootloader is running */
+uint16_t LLEDPulse;
+void LEDPulse(void)
+{
+ LLEDPulse++;
+ uint8_t p = LLEDPulse >> 8;
+ if (p > 127)
+ p = 254-p;
+ p += p;
+ if (((uint8_t)LLEDPulse) > p)
+ L_LED_OFF();
+ else
+ L_LED_ON();
+}
+
+/** Main program entry point. This routine configures the hardware required by the bootloader, then
continuously
+ * runs the bootloader processing routine until it times out or is instructed to exit.
+ */
+int main(void)
+{
+ /* Save the value of the boot key memory before it is overwritten */
+ uint16_t bootKeyPtrVal = *bootKeyPtr;
+ *bootKeyPtr = 0;
+
+ /* Check the reason for the reset so we can act accordingly */
+ uint8_t mcusr_state = MCUSR; // store the initial state of the Status register
+ MCUSR = 0; // clear all reset flags
+
+ /* Watchdog may be configured with a 15 ms period so must disable it before going any further */
+ wdt_disable();
+
+ if (mcusr_state & (1<<EXTRF)) {
+ // External reset - we should continue to self-programming mode.
+ } else if ((mcusr_state & (1<<PORF)) && (pgm_read_word(0) != 0xFFFF)) {
+ // After a power-on reset skip the bootloader and jump straight to sketch
+ // if one exists.
+ StartSketch();
+ } else if ((mcusr_state & (1<<WDRF)) && (bootKeyPtrVal != bootKey) && (pgm_read_word(0) != 0xFFFF)) {
+ // If it looks like an "accidental" watchdog reset then start the sketch.
+ StartSketch();
+ }
+
+ /* Setup hardware required for the bootloader */
+ SetupHardware();
+
+ /* Enable global interrupts so that the USB stack can function */
+ sei();
+
+ Timeout = 0;
+
+ while (RunBootloader)
+ {
+ CDC_Task();
+ USB_USBTask();
+ /* Time out and start the sketch if one is present */
+ if (Timeout > TIMEOUT_PERIOD)
+ RunBootloader = false;
+
+ LEDPulse();
+ }
+
+ /* Disconnect from the host - USB interface will be reset later along with the AVR */
+ USB_Detach();
+
+ /* Jump to beginning of application space to run the sketch - do not reset */
+ StartSketch();
+}
+
+/** Configures all hardware required for the bootloader. */
+void SetupHardware(void)
+{
+ /* Disable watchdog if enabled by bootloader/fuses */
+ MCUSR &= ~(1 << WDRF);
+ wdt_disable();
+
+ /* Disable clock division */
+ clock_prescale_set(clock_div_1);
+
+ /* Relocate the interrupt vector table to the bootloader section */
+ MCUCR = (1 << IVCE);
+ MCUCR = (1 << IVSEL);
+
+ LED_SETUP();
+ CPU_PRESCALE(0);
+ L_LED_OFF();
+ TX_LED_OFF();
+ RX_LED_OFF();
+
+ /* Initialize TIMER1 to handle bootloader timeout and LED tasks.
+ * With 16 MHz clock and 1/64 prescaler, timer 1 is clocked at 250 kHz
+ * Our chosen compare match generates an interrupt every 1 ms.
+ * This interrupt is disabled selectively when doing memory reading, erasing,
+ * or writing since SPM has tight timing requirements.
+ */
+ OCR1AH = 0;
+ OCR1AL = 250;
+ TIMSK1 = (1 << OCIE1A); // enable timer 1 output compare A match
interrupt
+ TCCR1B = ((1 << CS11) | (1 << CS10)); // 1/64 prescaler on timer 1 input
+
+ /* Initialize USB Subsystem */
+ USB_Init();
+}
+
+//uint16_t ctr = 0;
+ISR(TIMER1_COMPA_vect, ISR_BLOCK)
+{
+ /* Reset counter */
+ TCNT1H = 0;
+ TCNT1L = 0;
+
+ /* Check whether the TX or RX LED one-shot period has elapsed. if so, turn off the LED */
+ if (TxLEDPulse && !(--TxLEDPulse))
+ TX_LED_OFF();
+ if (RxLEDPulse && !(--RxLEDPulse))
+ RX_LED_OFF();
+
+ if (pgm_read_word(0) != 0xFFFF)
+ Timeout++;
+}
+
+/** Event handler for the USB_ConfigurationChanged event. This configures the device's endpoints ready
+ * to relay data to and from the attached USB host.
+ */
+void EVENT_USB_Device_ConfigurationChanged(void)
+{
+ /* Setup CDC Notification, Rx and Tx Endpoints */
+ Endpoint_ConfigureEndpoint(CDC_NOTIFICATION_EPNUM, EP_TYPE_INTERRUPT,
+ ENDPOINT_DIR_IN, CDC_NOTIFICATION_EPSIZE,
+ ENDPOINT_BANK_SINGLE);
+
+ Endpoint_ConfigureEndpoint(CDC_TX_EPNUM, EP_TYPE_BULK,
+ ENDPOINT_DIR_IN, CDC_TXRX_EPSIZE,
+ ENDPOINT_BANK_SINGLE);
+
+ Endpoint_ConfigureEndpoint(CDC_RX_EPNUM, EP_TYPE_BULK,
+ ENDPOINT_DIR_OUT, CDC_TXRX_EPSIZE,
+ ENDPOINT_BANK_SINGLE);
+}
+
+/** Event handler for the USB_ControlRequest event. This is used to catch and process control requests sent
to
+ * the device from the USB host before passing along unhandled control requests to the library for
processing
+ * internally.
+ */
+void EVENT_USB_Device_ControlRequest(void)
+{
+ /* Ignore any requests that aren't directed to the CDC interface */
+ if ((USB_ControlRequest.bmRequestType & (CONTROL_REQTYPE_TYPE | CONTROL_REQTYPE_RECIPIENT)) !=
+ (REQTYPE_CLASS | REQREC_INTERFACE))
+ {
+ return;
+ }
+
+ /* Process CDC specific control requests */
+ switch (USB_ControlRequest.bRequest)
+ {
+ case CDC_REQ_GetLineEncoding:
+ if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS |
REQREC_INTERFACE))
+ {
+ Endpoint_ClearSETUP();
+
+ /* Write the line coding data to the control endpoint */
+ Endpoint_Write_Control_Stream_LE(&LineEncoding, sizeof(CDC_LineEncoding_t));
+ Endpoint_ClearOUT();
+ }
+
+ break;
+ case CDC_REQ_SetLineEncoding:
+ if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS |
REQREC_INTERFACE))
+ {
+ Endpoint_ClearSETUP();
+
+ /* Read the line coding data in from the host into the global struct */
+ Endpoint_Read_Control_Stream_LE(&LineEncoding, sizeof(CDC_LineEncoding_t));
+ Endpoint_ClearIN();
+ }
+
+ break;
+ }
+}
+
+#if !defined(NO_BLOCK_SUPPORT)
+/** Reads or writes a block of EEPROM or FLASH memory to or from the appropriate CDC data endpoint, depending
+ * on the AVR910 protocol command issued.
+ *
+ * \param[in] Command Single character AVR910 protocol command indicating what memory operation to perform
+ */
+static void ReadWriteMemoryBlock(const uint8_t Command)
+{
+ uint16_t BlockSize;
+ char MemoryType;
+
+ bool HighByte = false;
+ uint8_t LowByte = 0;
+
+ BlockSize = (FetchNextCommandByte() << 8);
+ BlockSize |= FetchNextCommandByte();
+
+ MemoryType = FetchNextCommandByte();
+
+ if ((MemoryType != 'E') && (MemoryType != 'F'))
+ {
+ /* Send error byte back to the host */
+ WriteNextResponseByte('?');
+
+ return;
+ }
+
+ /* Disable timer 1 interrupt - can't afford to process nonessential interrupts
+ * while doing SPM tasks */
+ TIMSK1 = 0;
+
+ /* Check if command is to read memory */
+ if (Command == 'g')
+ {
+ /* Re-enable RWW section */
+ boot_rww_enable();
+
+ while (BlockSize--)
+ {
+ if (MemoryType == 'F')
+ {
+ /* Read the next FLASH byte from the current FLASH page */
+ #if (FLASHEND > 0xFFFF)
+ WriteNextResponseByte(pgm_read_byte_far(CurrAddress | HighByte));
+ #else
+ WriteNextResponseByte(pgm_read_byte(CurrAddress | HighByte));
+ #endif
+
+ /* If both bytes in current word have been read, increment the address
counter */
+ if (HighByte)
+ CurrAddress += 2;
+
+ HighByte = !HighByte;
+ }
+ else
+ {
+ /* Read the next EEPROM byte into the endpoint */
+ WriteNextResponseByte(eeprom_read_byte((uint8_t*)(intptr_t)(CurrAddress >>
1)));
+
+ /* Increment the address counter after use */
+ CurrAddress += 2;
+ }
+ }
+ }
+ else
+ {
+ uint32_t PageStartAddress = CurrAddress;
+
+ if (MemoryType == 'F')
+ {
+ boot_page_erase(PageStartAddress);
+ boot_spm_busy_wait();
+ }
+
+ while (BlockSize--)
+ {
+ if (MemoryType == 'F')
+ {
+ /* If both bytes in current word have been written, increment the address
counter */
+ if (HighByte)
+ {
+ /* Write the next FLASH word to the current FLASH page */
+ boot_page_fill(CurrAddress, ((FetchNextCommandByte() << 8) |
LowByte));
+
+ /* Increment the address counter after use */
+ CurrAddress += 2;
+ }
+ else
+ {
+ LowByte = FetchNextCommandByte();
+ }
+
+ HighByte = !HighByte;
+ }
+ else
+ {
+ /* Write the next EEPROM byte from the endpoint */
+ eeprom_write_byte((uint8_t*)((intptr_t)(CurrAddress >> 1)),
FetchNextCommandByte());
+
+ /* Increment the address counter after use */
+ CurrAddress += 2;
+ }
+ }
+
+ /* If in FLASH programming mode, commit the page after writing */
+ if (MemoryType == 'F')
+ {
+ /* Commit the flash page to memory */
+ boot_page_write(PageStartAddress);
+
+ /* Wait until write operation has completed */
+ boot_spm_busy_wait();
+ }
+
+ /* Send response byte back to the host */
+ WriteNextResponseByte('\r');
+ }
+
+ /* Re-enable timer 1 interrupt disabled earlier in this routine */
+ TIMSK1 = (1 << OCIE1A);
+}
+#endif
+
+/** Retrieves the next byte from the host in the CDC data OUT endpoint, and clears the endpoint bank if
needed
+ * to allow reception of the next data packet from the host.
+ *
+ * \return Next received byte from the host in the CDC data OUT endpoint
+ */
+static uint8_t FetchNextCommandByte(void)
+{
+ /* Select the OUT endpoint so that the next data byte can be read */
+ Endpoint_SelectEndpoint(CDC_RX_EPNUM);
+
+ /* If OUT endpoint empty, clear it and wait for the next packet from the host */
+ while (!(Endpoint_IsReadWriteAllowed()))
+ {
+ Endpoint_ClearOUT();
+
+ while (!(Endpoint_IsOUTReceived()))
+ {
+ if (USB_DeviceState == DEVICE_STATE_Unattached)
+ return 0;
+ }
+ }
+
+ /* Fetch the next byte from the OUT endpoint */
+ return Endpoint_Read_8();
+}
+
+/** Writes the next response byte to the CDC data IN endpoint, and sends the endpoint back if needed to free
up the
+ * bank when full ready for the next byte in the packet to the host.
+ *
+ * \param[in] Response Next response byte to send to the host
+ */
+static void WriteNextResponseByte(const uint8_t Response)
+{
+ /* Select the IN endpoint so that the next data byte can be written */
+ Endpoint_SelectEndpoint(CDC_TX_EPNUM);
+
+ /* If IN endpoint full, clear it and wait until ready for the next packet to the host */
+ if (!(Endpoint_IsReadWriteAllowed()))
+ {
+ Endpoint_ClearIN();
+
+ while (!(Endpoint_IsINReady()))
+ {
+ if (USB_DeviceState == DEVICE_STATE_Unattached)
+ return;
+ }
+ }
+
+ /* Write the next byte to the IN endpoint */
+ Endpoint_Write_8(Response);
+
+ TX_LED_ON();
+ TxLEDPulse = TX_RX_LED_PULSE_PERIOD;
+}
+
+#define STK_OK 0x10
+#define STK_INSYNC 0x14 // ' '
+#define CRC_EOP 0x20 // 'SPACE'
+#define STK_GET_SYNC 0x30 // '0'
+
+#define STK_GET_PARAMETER 0x41 // 'A'
+#define STK_SET_DEVICE 0x42 // 'B'
+#define STK_SET_DEVICE_EXT 0x45 // 'E'
+#define STK_LOAD_ADDRESS 0x55 // 'U'
+#define STK_UNIVERSAL 0x56 // 'V'
+#define STK_PROG_PAGE 0x64 // 'd'
+#define STK_READ_PAGE 0x74 // 't'
+#define STK_READ_SIGN 0x75 // 'u'
+
+/** Task to read in AVR910 commands from the CDC data OUT endpoint, process them, perform the required
actions
+ * and send the appropriate response back to the host.
+ */
+void CDC_Task(void)
+{
+ /* Select the OUT endpoint */
+ Endpoint_SelectEndpoint(CDC_RX_EPNUM);
+
+ /* Check if endpoint has a command in it sent from the host */
+ if (!(Endpoint_IsOUTReceived()))
+ return;
+
+ RX_LED_ON();
+ RxLEDPulse = TX_RX_LED_PULSE_PERIOD;
+
+ /* Read in the bootloader command (first byte sent from host) */
+ uint8_t Command = FetchNextCommandByte();
+
+ if (Command == 'E')
+ {
+ /* We nearly run out the bootloader timeout clock,
+ * leaving just a few hundred milliseconds so the
+ * bootloder has time to respond and service any
+ * subsequent requests */
+ Timeout = TIMEOUT_PERIOD - 500;
+
+ /* Re-enable RWW section - must be done here in case
+ * user has disabled verification on upload. */
+ boot_rww_enable_safe();
+
+ // Send confirmation byte back to the host
+ WriteNextResponseByte('\r');
+ }
+ else if (Command == 'T')
+ {
+ FetchNextCommandByte();
+
+ // Send confirmation byte back to the host
+ WriteNextResponseByte('\r');
+ }
+ else if ((Command == 'L') || (Command == 'P'))
+ {
+ // Send confirmation byte back to the host
+ WriteNextResponseByte('\r');
+ }
+ else if (Command == 't')
+ {
+ // Return ATMEGA128 part code - this is only to allow AVRProg to use the bootloader
+ WriteNextResponseByte(0x44);
+ WriteNextResponseByte(0x00);
+ }
+ else if (Command == 'a')
+ {
+ // Indicate auto-address increment is supported
+ WriteNextResponseByte('Y');
+ }
+ else if (Command == 'A')
+ {
+ // Set the current address to that given by the host
+ CurrAddress = (FetchNextCommandByte() << 9);
+ CurrAddress |= (FetchNextCommandByte() << 1);
+
+ // Send confirmation byte back to the host
+ WriteNextResponseByte('\r');
+ }
+ else if (Command == 'p')
+ {
+ // Indicate serial programmer back to the host
+ WriteNextResponseByte('S');
+ }
+ else if (Command == 'S')
+ {
+ // Write the 7-byte software identifier to the endpoint
+ for (uint8_t CurrByte = 0; CurrByte < 7; CurrByte++)
+ WriteNextResponseByte(SOFTWARE_IDENTIFIER[CurrByte]);
+ }
+ else if (Command == 'V')
+ {
+ WriteNextResponseByte('0' + BOOTLOADER_VERSION_MAJOR);
+ WriteNextResponseByte('0' + BOOTLOADER_VERSION_MINOR);
+ }
+ else if (Command == 's')
+ {
+ WriteNextResponseByte(AVR_SIGNATURE_3);
+ WriteNextResponseByte(AVR_SIGNATURE_2);
+ WriteNextResponseByte(AVR_SIGNATURE_1);
+ }
+ else if (Command == 'e')
+ {
+ // Clear the application section of flash
+ for (uint32_t CurrFlashAddress = 0; CurrFlashAddress < BOOT_START_ADDR; CurrFlashAddress +=
SPM_PAGESIZE)
+ {
+ boot_page_erase(CurrFlashAddress);
+ boot_spm_busy_wait();
+ boot_page_write(CurrFlashAddress);
+ boot_spm_busy_wait();
+ }
+
+ // Send confirmation byte back to the host
+ WriteNextResponseByte('\r');
+ }
+ #if !defined(NO_LOCK_BYTE_WRITE_SUPPORT)
+ else if (Command == 'l')
+ {
+ // Set the lock bits to those given by the host
+ boot_lock_bits_set(FetchNextCommandByte());
+
+ // Send confirmation byte back to the host
+ WriteNextResponseByte('\r');
+ }
+ #endif
+ else if (Command == 'r')
+ {
+ WriteNextResponseByte(boot_lock_fuse_bits_get(GET_LOCK_BITS));
+ }
+ else if (Command == 'F')
+ {
+ WriteNextResponseByte(boot_lock_fuse_bits_get(GET_LOW_FUSE_BITS));
+ }
+ else if (Command == 'N')
+ {
+ WriteNextResponseByte(boot_lock_fuse_bits_get(GET_HIGH_FUSE_BITS));
+ }
+ else if (Command == 'Q')
+ {
+ WriteNextResponseByte(boot_lock_fuse_bits_get(GET_EXTENDED_FUSE_BITS));
+ }
+ #if !defined(NO_BLOCK_SUPPORT)
+ else if (Command == 'b')
+ {
+ WriteNextResponseByte('Y');
+
+ // Send block size to the host
+ WriteNextResponseByte(SPM_PAGESIZE >> 8);
+ WriteNextResponseByte(SPM_PAGESIZE & 0xFF);
+ }
+ else if ((Command == 'B') || (Command == 'g'))
+ {
+ // Keep resetting the timeout counter if we're receiving self-programming instructions
+ Timeout = 0;
+ // Delegate the block write/read to a separate function for clarity
+ ReadWriteMemoryBlock(Command);
+ }
+ #endif
+ #if !defined(NO_FLASH_BYTE_SUPPORT)
+ else if (Command == 'C')
+ {
+ // Write the high byte to the current flash page
+ boot_page_fill(CurrAddress, FetchNextCommandByte());
+
+ // Send confirmation byte back to the host
+ WriteNextResponseByte('\r');
+ }
+ else if (Command == 'c')
+ {
+ // Write the low byte to the current flash page
+ boot_page_fill(CurrAddress | 0x01, FetchNextCommandByte());
+
+ // Increment the address
+ CurrAddress += 2;
+
+ // Send confirmation byte back to the host
+ WriteNextResponseByte('\r');
+ }
+ else if (Command == 'm')
+ {
+ // Commit the flash page to memory
+ boot_page_write(CurrAddress);
+
+ // Wait until write operation has completed
+ boot_spm_busy_wait();
+
+ // Send confirmation byte back to the host
+ WriteNextResponseByte('\r');
+ }
+ else if (Command == 'R')
+ {
+ #if (FLASHEND > 0xFFFF)
+ uint16_t ProgramWord = pgm_read_word_far(CurrAddress);
+ #else
+ uint16_t ProgramWord = pgm_read_word(CurrAddress);
+ #endif
+
+ WriteNextResponseByte(ProgramWord >> 8);
+ WriteNextResponseByte(ProgramWord & 0xFF);
+ }
+ #endif
+ #if !defined(NO_EEPROM_BYTE_SUPPORT)
+ else if (Command == 'D')
+ {
+ // Read the byte from the endpoint and write it to the EEPROM
+ eeprom_write_byte((uint8_t*)((intptr_t)(CurrAddress >> 1)), FetchNextCommandByte());
+
+ // Increment the address after use
+ CurrAddress += 2;
+
+ // Send confirmation byte back to the host
+ WriteNextResponseByte('\r');
+ }
+ else if (Command == 'd')
+ {
+ // Read the EEPROM byte and write it to the endpoint
+ WriteNextResponseByte(eeprom_read_byte((uint8_t*)((intptr_t)(CurrAddress >> 1))));
+
+ // Increment the address after use
+ CurrAddress += 2;
+ }
+ #endif
+ else if (Command != 27)
+ {
+ // Unknown (non-sync) command, return fail code
+ WriteNextResponseByte('?');
+ }
+
+
+ /* Select the IN endpoint */
+ Endpoint_SelectEndpoint(CDC_TX_EPNUM);
+
+ /* Remember if the endpoint is completely full before clearing it */
+ bool IsEndpointFull = !(Endpoint_IsReadWriteAllowed());
+
+ /* Send the endpoint data to the host */
+ Endpoint_ClearIN();
+
+ /* If a full endpoint's worth of data was sent, we need to send an empty packet afterwards to signal
end of transfer */
+ if (IsEndpointFull)
+ {
+ while (!(Endpoint_IsINReady()))
+ {
+ if (USB_DeviceState == DEVICE_STATE_Unattached)
+ return;
+ }
+
+ Endpoint_ClearIN();
+ }
+
+ /* Wait until the data has been sent to the host */
+ while (!(Endpoint_IsINReady()))
+ {
+ if (USB_DeviceState == DEVICE_STATE_Unattached)
+ return;
+ }
+
+ /* Select the OUT endpoint */
+ Endpoint_SelectEndpoint(CDC_RX_EPNUM);
+
+ /* Acknowledge the command from the host */
+ Endpoint_ClearOUT();
+}
diff --git a/hardware/arduino/bootloaders/caterina/Caterina.h
b/hardware/arduino/bootloaders/caterina/Caterina.h
index 5ce80fa..1668ef9 100644
--- a/hardware/arduino/bootloaders/caterina/Caterina.h
+++ b/hardware/arduino/bootloaders/caterina/Caterina.h
@@ -1,106 +1,105 @@
-/*
- LUFA Library
- Copyright (C) Dean Camera, 2011.
-
- dean [at] fourwalledcubicle [dot] com
- www.lufa-lib.org
-*/
-
-/*
- Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com)
-
- Permission to use, copy, modify, distribute, and sell this
- software and its documentation for any purpose is hereby granted
- without fee, provided that the above copyright notice appear in
- all copies and that both that the copyright notice and this
- permission notice and warranty disclaimer appear in supporting
- documentation, and that the name of the author not be used in
- advertising or publicity pertaining to distribution of the
- software without specific, written prior permission.
-
- The author disclaim all warranties with regard to this
- software, including all implied warranties of merchantability
- and fitness. In no event shall the author be liable for any
- special, indirect or consequential damages or any damages
- whatsoever resulting from loss of use, data or profits, whether
- in an action of contract, negligence or other tortious action,
- arising out of or in connection with the use or performance of
- this software.
-*/
-
-/** \file
- *
- * Header file for BootloaderCDC.c.
- */
-
-#ifndef _CDC_H_
-#define _CDC_H_
-
- /* Includes: */
- #include <avr/io.h>
- #include <avr/wdt.h>
- #include <avr/boot.h>
- #include <avr/eeprom.h>
- #include <avr/power.h>
- #include <avr/interrupt.h>
- #include <stdbool.h>
-
- #include "Descriptors.h"
-
- #include <LUFA/Drivers/USB/USB.h>
- /* Macros: */
- /** Version major of the CDC bootloader. */
- #define BOOTLOADER_VERSION_MAJOR 0x01
-
- /** Version minor of the CDC bootloader. */
- #define BOOTLOADER_VERSION_MINOR 0x00
-
- /** Hardware version major of the CDC bootloader. */
- #define BOOTLOADER_HWVERSION_MAJOR 0x01
-
- /** Hardware version minor of the CDC bootloader. */
- #define BOOTLOADER_HWVERSION_MINOR 0x00
-
- /** Eight character bootloader firmware identifier reported to the host when requested */
- #define SOFTWARE_IDENTIFIER "CATERINA"
-
- #define CPU_PRESCALE(n) (CLKPR = 0x80, CLKPR = (n))
- #define LED_SETUP() DDRC |= (1<<7); DDRB |= (1<<0); DDRD |= (1<<5);
- #define L_LED_OFF() PORTC &= ~(1<<7)
- #define L_LED_ON() PORTC |= (1<<7)
- #define L_LED_TOGGLE() PORTC ^= (1<<7)
- #if DEVICE_PID == 0x0037 // polarity of the RX and TX LEDs is reversed on the Micro
- #define TX_LED_OFF() PORTD &= ~(1<<5)
- #define TX_LED_ON() PORTD |= (1<<5)
- #define RX_LED_OFF() PORTB &= ~(1<<0)
- #define RX_LED_ON() PORTB |= (1<<0)
- #else
- #define TX_LED_OFF() PORTD |= (1<<5)
- #define TX_LED_ON() PORTD &= ~(1<<5)
- #define RX_LED_OFF() PORTB |= (1<<0)
- #define RX_LED_ON() PORTB &= ~(1<<0)
- #endif
-
- /* Type Defines: */
- /** Type define for a non-returning pointer to the start of the loaded application in flash
memory. */
- typedef void (*AppPtr_t)(void) ATTR_NO_RETURN;
-
- /* Function Prototypes: */
- void StartSketch(void);
- void LEDPulse(void);
-
- void CDC_Task(void);
- void SetupHardware(void);
-
- void EVENT_USB_Device_ConfigurationChanged(void);
-
- #if defined(INCLUDE_FROM_CATERINA_C) || defined(__DOXYGEN__)
- #if !defined(NO_BLOCK_SUPPORT)
- static void ReadWriteMemoryBlock(const uint8_t Command);
- #endif
- static uint8_t FetchNextCommandByte(void);
- static void WriteNextResponseByte(const uint8_t Response);
- #endif
-
-#endif
-
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2011.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaim all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ *
+ * Header file for BootloaderCDC.c.
+ */
+
+#ifndef _CDC_H_
+#define _CDC_H_
+
+ /* Includes: */
+ #include <avr/io.h>
+ #include <avr/wdt.h>
+ #include <avr/boot.h>
+ #include <avr/eeprom.h>
+ #include <avr/power.h>
+ #include <avr/interrupt.h>
+ #include <stdbool.h>
+
+ #include "Descriptors.h"
+
+ #include <LUFA/Drivers/USB/USB.h>
+ /* Macros: */
+ /** Version major of the CDC bootloader. */
+ #define BOOTLOADER_VERSION_MAJOR 0x01
+
+ /** Version minor of the CDC bootloader. */
+ #define BOOTLOADER_VERSION_MINOR 0x00
+
+ /** Hardware version major of the CDC bootloader. */
+ #define BOOTLOADER_HWVERSION_MAJOR 0x01
+
+ /** Hardware version minor of the CDC bootloader. */
+ #define BOOTLOADER_HWVERSION_MINOR 0x00
+
+ /** Eight character bootloader firmware identifier reported to the host when requested */
+ #define SOFTWARE_IDENTIFIER "CATERINA"
+
+ #define CPU_PRESCALE(n) (CLKPR = 0x80, CLKPR = (n))
+ #define LED_SETUP() DDRC |= (1<<7); DDRB |= (1<<0); DDRD |= (1<<5);
+ #define L_LED_OFF() PORTC &= ~(1<<7)
+ #define L_LED_ON() PORTC |= (1<<7)
+ #define L_LED_TOGGLE() PORTC ^= (1<<7)
+ #if DEVICE_PID == 0x0037 // polarity of the RX and TX LEDs is reversed on the Micro
+ #define TX_LED_OFF() PORTD &= ~(1<<5)
+ #define TX_LED_ON() PORTD |= (1<<5)
+ #define RX_LED_OFF() PORTB &= ~(1<<0)
+ #define RX_LED_ON() PORTB |= (1<<0)
+ #else
+ #define TX_LED_OFF() PORTD |= (1<<5)
+ #define TX_LED_ON() PORTD &= ~(1<<5)
+ #define RX_LED_OFF() PORTB |= (1<<0)
+ #define RX_LED_ON() PORTB &= ~(1<<0)
+ #endif
+
+ /* Type Defines: */
+ /** Type define for a non-returning pointer to the start of the loaded application in flash
memory. */
+ typedef void (*AppPtr_t)(void) ATTR_NO_RETURN;
+
+ /* Function Prototypes: */
+ void StartSketch(void);
+ void LEDPulse(void);
+
+ void CDC_Task(void);
+ void SetupHardware(void);
+
+ void EVENT_USB_Device_ConfigurationChanged(void);
+
+ #if defined(INCLUDE_FROM_CATERINA_C) || defined(__DOXYGEN__)
+ #if !defined(NO_BLOCK_SUPPORT)
+ static void ReadWriteMemoryBlock(const uint8_t Command);
+ #endif
+ static uint8_t FetchNextCommandByte(void);
+ static void WriteNextResponseByte(const uint8_t Response);
+ #endif
+
+#endif
diff --git a/hardware/arduino/bootloaders/caterina/Descriptors.c
b/hardware/arduino/bootloaders/caterina/Descriptors.c
index b5e5150..2546b29 100644
--- a/hardware/arduino/bootloaders/caterina/Descriptors.c
+++ b/hardware/arduino/bootloaders/caterina/Descriptors.c
@@ -1,266 +1,265 @@
-/*
- LUFA Library
- Copyright (C) Dean Camera, 2011.
-
- dean [at] fourwalledcubicle [dot] com
- www.lufa-lib.org
-*/
-
-/*
- Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com)
-
- Permission to use, copy, modify, distribute, and sell this
- software and its documentation for any purpose is hereby granted
- without fee, provided that the above copyright notice appear in
- all copies and that both that the copyright notice and this
- permission notice and warranty disclaimer appear in supporting
- documentation, and that the name of the author not be used in
- advertising or publicity pertaining to distribution of the
- software without specific, written prior permission.
-
- The author disclaim all warranties with regard to this
- software, including all implied warranties of merchantability
- and fitness. In no event shall the author be liable for any
- special, indirect or consequential damages or any damages
- whatsoever resulting from loss of use, data or profits, whether
- in an action of contract, negligence or other tortious action,
- arising out of or in connection with the use or performance of
- this software.
-*/
-
-/** \file
- *
- * USB Device Descriptors, for library use when in USB device mode. Descriptors are special
- * computer-readable structures which the host requests upon device enumeration, to determine
- * the device's capabilities and functions.
- */
-
-#include "Descriptors.h"
-
-/** Device descriptor structure. This descriptor, located in SRAM memory, describes the overall
- * device characteristics, including the supported USB version, control endpoint size and the
- * number of device configurations. The descriptor is read out by the USB host when the enumeration
- * process begins.
- */
-const USB_Descriptor_Device_t DeviceDescriptor =
-{
- .Header = {.Size = sizeof(USB_Descriptor_Device_t), .Type = DTYPE_Device},
-
- .USBSpecification = VERSION_BCD(01.10),
- .Class = CDC_CSCP_CDCClass,
- .SubClass = CDC_CSCP_NoSpecificSubclass,
- .Protocol = CDC_CSCP_NoSpecificProtocol,
-
- .Endpoint0Size = FIXED_CONTROL_ENDPOINT_SIZE,
-
- .VendorID = DEVICE_VID,
- .ProductID = DEVICE_PID,
- .ReleaseNumber = VERSION_BCD(00.01),
-
- .ManufacturerStrIndex = 0x02,
- .ProductStrIndex = 0x01,
- .SerialNumStrIndex = NO_DESCRIPTOR,
-
- .NumberOfConfigurations = FIXED_NUM_CONFIGURATIONS
-};
-
-/** Configuration descriptor structure. This descriptor, located in SRAM memory, describes the usage
- * of the device in one of its supported configurations, including information about any device interfaces
- * and endpoints. The descriptor is read out by the USB host during the enumeration process when selecting
- * a configuration so that the host may correctly communicate with the USB device.
- */
-const USB_Descriptor_Configuration_t ConfigurationDescriptor =
-{
- .Config =
- {
- .Header = {.Size = sizeof(USB_Descriptor_Configuration_Header_t),
.Type = DTYPE_Configuration},
-
- .TotalConfigurationSize = sizeof(USB_Descriptor_Configuration_t),
- .TotalInterfaces = 2,
-
- .ConfigurationNumber = 1,
- .ConfigurationStrIndex = NO_DESCRIPTOR,
-
- .ConfigAttributes = USB_CONFIG_ATTR_BUSPOWERED,
-
- .MaxPowerConsumption = USB_CONFIG_POWER_MA(100)
- },
-
- .CDC_CCI_Interface =
- {
- .Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type =
DTYPE_Interface},
-
- .InterfaceNumber = 0,
- .AlternateSetting = 0,
-
- .TotalEndpoints = 1,
-
- .Class = CDC_CSCP_CDCClass,
- .SubClass = CDC_CSCP_ACMSubclass,
- .Protocol = CDC_CSCP_ATCommandProtocol,
-
- .InterfaceStrIndex = NO_DESCRIPTOR
- },
-
- .CDC_Functional_Header =
- {
- .Header = {.Size = sizeof(USB_CDC_Descriptor_FunctionalHeader_t),
.Type = DTYPE_CSInterface},
- .Subtype = 0x00,
-
- .CDCSpecification = VERSION_BCD(01.10),
- },
-
- .CDC_Functional_ACM =
- {
- .Header = {.Size = sizeof(USB_CDC_Descriptor_FunctionalACM_t), .Type
= DTYPE_CSInterface},
- .Subtype = 0x02,
-
- .Capabilities = 0x04,
- },
-
- .CDC_Functional_Union =
- {
- .Header = {.Size = sizeof(USB_CDC_Descriptor_FunctionalUnion_t),
.Type = DTYPE_CSInterface},
- .Subtype = 0x06,
-
- .MasterInterfaceNumber = 0,
- .SlaveInterfaceNumber = 1,
- },
-
- .CDC_NotificationEndpoint =
- {
- .Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type =
DTYPE_Endpoint},
-
- .EndpointAddress = (ENDPOINT_DIR_IN | CDC_NOTIFICATION_EPNUM),
- .Attributes = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC |
ENDPOINT_USAGE_DATA),
- .EndpointSize = CDC_NOTIFICATION_EPSIZE,
- .PollingIntervalMS = 0xFF
- },
-
- .CDC_DCI_Interface =
- {
- .Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type =
DTYPE_Interface},
-
- .InterfaceNumber = 1,
- .AlternateSetting = 0,
-
- .TotalEndpoints = 2,
-
- .Class = CDC_CSCP_CDCDataClass,
- .SubClass = CDC_CSCP_NoDataSubclass,
- .Protocol = CDC_CSCP_NoDataProtocol,
-
- .InterfaceStrIndex = NO_DESCRIPTOR
- },
-
- .CDC_DataOutEndpoint =
- {
- .Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type =
DTYPE_Endpoint},
-
- .EndpointAddress = (ENDPOINT_DIR_OUT | CDC_RX_EPNUM),
- .Attributes = (EP_TYPE_BULK | ENDPOINT_ATTR_NO_SYNC |
ENDPOINT_USAGE_DATA),
- .EndpointSize = CDC_TXRX_EPSIZE,
- .PollingIntervalMS = 0x01
- },
-
- .CDC_DataInEndpoint =
- {
- .Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type =
DTYPE_Endpoint},
-
- .EndpointAddress = (ENDPOINT_DIR_IN | CDC_TX_EPNUM),
- .Attributes = (EP_TYPE_BULK | ENDPOINT_ATTR_NO_SYNC |
ENDPOINT_USAGE_DATA),
- .EndpointSize = CDC_TXRX_EPSIZE,
- .PollingIntervalMS = 0x01
- }
-};
-
-/** Language descriptor structure. This descriptor, located in SRAM memory, is returned when the host
requests
- * the string descriptor with index 0 (the first index). It is actually an array of 16-bit integers, which
indicate
- * via the language ID table available at USB.org what languages the device supports for its string
descriptors.
- */
-const USB_Descriptor_String_t LanguageString =
-{
- .Header = {.Size = USB_STRING_LEN(1), .Type = DTYPE_String},
-
- .UnicodeString = {LANGUAGE_ID_ENG}
-};
-
-/** Product descriptor string. This is a Unicode string containing the product's details in human readable
form,
- * and is read out upon request by the host when the appropriate string ID is requested, listed in the
Device
- * Descriptor.
- */
-const USB_Descriptor_String_t ProductString =
-{
- .Header = {.Size = USB_STRING_LEN(16), .Type = DTYPE_String},
-
- #if DEVICE_PID == 0x0036
- .UnicodeString = L"Arduino Leonardo"
- #elif DEVICE_PID == 0x0037
- .UnicodeString = L"Arduino Micro "
- #elif DEVICE_PID == 0x003C
- .UnicodeString = L"Arduino Esplora "
- #else
- .UnicodeString = L"USB IO board "
- #endif
-};
-
-const USB_Descriptor_String_t ManufNameString =
-{
- .Header = {.Size = USB_STRING_LEN(11), .Type = DTYPE_String},
-
- #if DEVICE_VID == 0x2341
- .UnicodeString = L"Arduino LLC"
- #else
- .UnicodeString = L"Unknown "
- #endif
-};
-
-/** This function is called by the library when in device mode, and must be overridden (see LUFA library
"USB Descriptors"
- * documentation) by the application code so that the address and size of a requested descriptor can be
given
- * to the USB library. When the device receives a Get Descriptor request on the control endpoint, this
function
- * is called so that the descriptor details can be passed back and the appropriate descriptor sent back to
the
- * USB host.
- */
-uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue,
- const uint8_t wIndex,
- const void** const DescriptorAddress)
-{
- const uint8_t DescriptorType = (wValue >> 8);
- const uint8_t DescriptorNumber = (wValue & 0xFF);
-
- const void* Address = NULL;
- uint16_t Size = NO_DESCRIPTOR;
-
- switch (DescriptorType)
- {
- case DTYPE_Device:
- Address = &DeviceDescriptor;
- Size = sizeof(USB_Descriptor_Device_t);
- break;
- case DTYPE_Configuration:
- Address = &ConfigurationDescriptor;
- Size = sizeof(USB_Descriptor_Configuration_t);
- break;
- case DTYPE_String:
- if (!(DescriptorNumber))
- {
- Address = &LanguageString;
- Size = LanguageString.Header.Size;
- }
- else if (DescriptorNumber == DeviceDescriptor.ProductStrIndex)
- {
- Address = &ProductString;
- Size = ProductString.Header.Size;
- } else if (DescriptorNumber == DeviceDescriptor.ManufacturerStrIndex)
- {
- Address = &ManufNameString;
- Size = ManufNameString.Header.Size;
- }
-
- break;
- }
-
- *DescriptorAddress = Address;
- return Size;
-}
-
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2011.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaim all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ *
+ * USB Device Descriptors, for library use when in USB device mode. Descriptors are special
+ * computer-readable structures which the host requests upon device enumeration, to determine
+ * the device's capabilities and functions.
+ */
+
+#include "Descriptors.h"
+
+/** Device descriptor structure. This descriptor, located in SRAM memory, describes the overall
+ * device characteristics, including the supported USB version, control endpoint size and the
+ * number of device configurations. The descriptor is read out by the USB host when the enumeration
+ * process begins.
+ */
+const USB_Descriptor_Device_t DeviceDescriptor =
+{
+ .Header = {.Size = sizeof(USB_Descriptor_Device_t), .Type = DTYPE_Device},
+
+ .USBSpecification = VERSION_BCD(01.10),
+ .Class = CDC_CSCP_CDCClass,
+ .SubClass = CDC_CSCP_NoSpecificSubclass,
+ .Protocol = CDC_CSCP_NoSpecificProtocol,
+
+ .Endpoint0Size = FIXED_CONTROL_ENDPOINT_SIZE,
+
+ .VendorID = DEVICE_VID,
+ .ProductID = DEVICE_PID,
+ .ReleaseNumber = VERSION_BCD(00.01),
+
+ .ManufacturerStrIndex = 0x02,
+ .ProductStrIndex = 0x01,
+ .SerialNumStrIndex = NO_DESCRIPTOR,
+
+ .NumberOfConfigurations = FIXED_NUM_CONFIGURATIONS
+};
+
+/** Configuration descriptor structure. This descriptor, located in SRAM memory, describes the usage
+ * of the device in one of its supported configurations, including information about any device interfaces
+ * and endpoints. The descriptor is read out by the USB host during the enumeration process when selecting
+ * a configuration so that the host may correctly communicate with the USB device.
+ */
+const USB_Descriptor_Configuration_t ConfigurationDescriptor =
+{
+ .Config =
+ {
+ .Header = {.Size = sizeof(USB_Descriptor_Configuration_Header_t),
.Type = DTYPE_Configuration},
+
+ .TotalConfigurationSize = sizeof(USB_Descriptor_Configuration_t),
+ .TotalInterfaces = 2,
+
+ .ConfigurationNumber = 1,
+ .ConfigurationStrIndex = NO_DESCRIPTOR,
+
+ .ConfigAttributes = USB_CONFIG_ATTR_BUSPOWERED,
+
+ .MaxPowerConsumption = USB_CONFIG_POWER_MA(100)
+ },
+
+ .CDC_CCI_Interface =
+ {
+ .Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type =
DTYPE_Interface},
+
+ .InterfaceNumber = 0,
+ .AlternateSetting = 0,
+
+ .TotalEndpoints = 1,
+
+ .Class = CDC_CSCP_CDCClass,
+ .SubClass = CDC_CSCP_ACMSubclass,
+ .Protocol = CDC_CSCP_ATCommandProtocol,
+
+ .InterfaceStrIndex = NO_DESCRIPTOR
+ },
+
+ .CDC_Functional_Header =
+ {
+ .Header = {.Size = sizeof(USB_CDC_Descriptor_FunctionalHeader_t),
.Type = DTYPE_CSInterface},
+ .Subtype = 0x00,
+
+ .CDCSpecification = VERSION_BCD(01.10),
+ },
+
+ .CDC_Functional_ACM =
+ {
+ .Header = {.Size = sizeof(USB_CDC_Descriptor_FunctionalACM_t), .Type
= DTYPE_CSInterface},
+ .Subtype = 0x02,
+
+ .Capabilities = 0x04,
+ },
+
+ .CDC_Functional_Union =
+ {
+ .Header = {.Size = sizeof(USB_CDC_Descriptor_FunctionalUnion_t),
.Type = DTYPE_CSInterface},
+ .Subtype = 0x06,
+
+ .MasterInterfaceNumber = 0,
+ .SlaveInterfaceNumber = 1,
+ },
+
+ .CDC_NotificationEndpoint =
+ {
+ .Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type =
DTYPE_Endpoint},
+
+ .EndpointAddress = (ENDPOINT_DIR_IN | CDC_NOTIFICATION_EPNUM),
+ .Attributes = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC |
ENDPOINT_USAGE_DATA),
+ .EndpointSize = CDC_NOTIFICATION_EPSIZE,
+ .PollingIntervalMS = 0xFF
+ },
+
+ .CDC_DCI_Interface =
+ {
+ .Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type =
DTYPE_Interface},
+
+ .InterfaceNumber = 1,
+ .AlternateSetting = 0,
+
+ .TotalEndpoints = 2,
+
+ .Class = CDC_CSCP_CDCDataClass,
+ .SubClass = CDC_CSCP_NoDataSubclass,
+ .Protocol = CDC_CSCP_NoDataProtocol,
+
+ .InterfaceStrIndex = NO_DESCRIPTOR
+ },
+
+ .CDC_DataOutEndpoint =
+ {
+ .Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type =
DTYPE_Endpoint},
+
+ .EndpointAddress = (ENDPOINT_DIR_OUT | CDC_RX_EPNUM),
+ .Attributes = (EP_TYPE_BULK | ENDPOINT_ATTR_NO_SYNC |
ENDPOINT_USAGE_DATA),
+ .EndpointSize = CDC_TXRX_EPSIZE,
+ .PollingIntervalMS = 0x01
+ },
+
+ .CDC_DataInEndpoint =
+ {
+ .Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type =
DTYPE_Endpoint},
+
+ .EndpointAddress = (ENDPOINT_DIR_IN | CDC_TX_EPNUM),
+ .Attributes = (EP_TYPE_BULK | ENDPOINT_ATTR_NO_SYNC |
ENDPOINT_USAGE_DATA),
+ .EndpointSize = CDC_TXRX_EPSIZE,
+ .PollingIntervalMS = 0x01
+ }
+};
+
+/** Language descriptor structure. This descriptor, located in SRAM memory, is returned when the host
requests
+ * the string descriptor with index 0 (the first index). It is actually an array of 16-bit integers, which
indicate
+ * via the language ID table available at USB.org what languages the device supports for its string
descriptors.
+ */
+const USB_Descriptor_String_t LanguageString =
+{
+ .Header = {.Size = USB_STRING_LEN(1), .Type = DTYPE_String},
+
+ .UnicodeString = {LANGUAGE_ID_ENG}
+};
+
+/** Product descriptor string. This is a Unicode string containing the product's details in human readable
form,
+ * and is read out upon request by the host when the appropriate string ID is requested, listed in the
Device
+ * Descriptor.
+ */
+const USB_Descriptor_String_t ProductString =
+{
+ .Header = {.Size = USB_STRING_LEN(16), .Type = DTYPE_String},
+
+ #if DEVICE_PID == 0x0036
+ .UnicodeString = L"Arduino Leonardo"
+ #elif DEVICE_PID == 0x0037
+ .UnicodeString = L"Arduino Micro "
+ #elif DEVICE_PID == 0x003C
+ .UnicodeString = L"Arduino Esplora "
+ #else
+ .UnicodeString = L"USB IO board "
+ #endif
+};
+
+const USB_Descriptor_String_t ManufNameString =
+{
+ .Header = {.Size = USB_STRING_LEN(11), .Type = DTYPE_String},
+
+ #if DEVICE_VID == 0x2341
+ .UnicodeString = L"Arduino LLC"
+ #else
+ .UnicodeString = L"Unknown "
+ #endif
+};
+
+/** This function is called by the library when in device mode, and must be overridden (see LUFA library
"USB Descriptors"
+ * documentation) by the application code so that the address and size of a requested descriptor can be
given
+ * to the USB library. When the device receives a Get Descriptor request on the control endpoint, this
function
+ * is called so that the descriptor details can be passed back and the appropriate descriptor sent back to
the
+ * USB host.
+ */
+uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue,
+ const uint8_t wIndex,
+ const void** const DescriptorAddress)
+{
+ const uint8_t DescriptorType = (wValue >> 8);
+ const uint8_t DescriptorNumber = (wValue & 0xFF);
+
+ const void* Address = NULL;
+ uint16_t Size = NO_DESCRIPTOR;
+
+ switch (DescriptorType)
+ {
+ case DTYPE_Device:
+ Address = &DeviceDescriptor;
+ Size = sizeof(USB_Descriptor_Device_t);
+ break;
+ case DTYPE_Configuration:
+ Address = &ConfigurationDescriptor;
+ Size = sizeof(USB_Descriptor_Configuration_t);
+ break;
+ case DTYPE_String:
+ if (!(DescriptorNumber))
+ {
+ Address = &LanguageString;
+ Size = LanguageString.Header.Size;
+ }
+ else if (DescriptorNumber == DeviceDescriptor.ProductStrIndex)
+ {
+ Address = &ProductString;
+ Size = ProductString.Header.Size;
+ } else if (DescriptorNumber == DeviceDescriptor.ManufacturerStrIndex)
+ {
+ Address = &ManufNameString;
+ Size = ManufNameString.Header.Size;
+ }
+
+ break;
+ }
+
+ *DescriptorAddress = Address;
+ return Size;
+}
diff --git a/hardware/arduino/bootloaders/caterina/Descriptors.h
b/hardware/arduino/bootloaders/caterina/Descriptors.h
index 94091ae..f08104b 100644
--- a/hardware/arduino/bootloaders/caterina/Descriptors.h
+++ b/hardware/arduino/bootloaders/caterina/Descriptors.h
@@ -1,139 +1,138 @@
-/*
- LUFA Library
- Copyright (C) Dean Camera, 2011.
-
- dean [at] fourwalledcubicle [dot] com
- www.lufa-lib.org
-*/
-
-/*
- Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com)
-
- Permission to use, copy, modify, distribute, and sell this
- software and its documentation for any purpose is hereby granted
- without fee, provided that the above copyright notice appear in
- all copies and that both that the copyright notice and this
- permission notice and warranty disclaimer appear in supporting
- documentation, and that the name of the author not be used in
- advertising or publicity pertaining to distribution of the
- software without specific, written prior permission.
-
- The author disclaim all warranties with regard to this
- software, including all implied warranties of merchantability
- and fitness. In no event shall the author be liable for any
- special, indirect or consequential damages or any damages
- whatsoever resulting from loss of use, data or profits, whether
- in an action of contract, negligence or other tortious action,
- arising out of or in connection with the use or performance of
- this software.
-*/
-
-/** \file
- *
- * Header file for Descriptors.c.
- */
-
-#ifndef _DESCRIPTORS_H_
-#define _DESCRIPTORS_H_
-
- /* Includes: */
- #include <LUFA/Drivers/USB/USB.h>
-
- /* Macros: */
- #if defined(__AVR_AT90USB1287__)
- #define AVR_SIGNATURE_1 0x1E
- #define AVR_SIGNATURE_2 0x97
- #define AVR_SIGNATURE_3 0x82
- #elif defined(__AVR_AT90USB647__)
- #define AVR_SIGNATURE_1 0x1E
- #define AVR_SIGNATURE_2 0x96
- #define AVR_SIGNATURE_3 0x82
- #elif defined(__AVR_AT90USB1286__)
- #define AVR_SIGNATURE_1 0x1E
- #define AVR_SIGNATURE_2 0x97
- #define AVR_SIGNATURE_3 0x82
- #elif defined(__AVR_AT90USB646__)
- #define AVR_SIGNATURE_1 0x1E
- #define AVR_SIGNATURE_2 0x96
- #define AVR_SIGNATURE_3 0x82
- #elif defined(__AVR_ATmega32U6__)
- #define AVR_SIGNATURE_1 0x1E
- #define AVR_SIGNATURE_2 0x95
- #define AVR_SIGNATURE_3 0x88
- #elif defined(__AVR_ATmega32U4__)
- #define AVR_SIGNATURE_1 0x1E
- #define AVR_SIGNATURE_2 0x95
- #define AVR_SIGNATURE_3 0x87
- #elif defined(__AVR_ATmega16U4__)
- #define AVR_SIGNATURE_1 0x1E
- #define AVR_SIGNATURE_2 0x94
- #define AVR_SIGNATURE_3 0x88
- #elif defined(__AVR_ATmega32U2__)
- #define AVR_SIGNATURE_1 0x1E
- #define AVR_SIGNATURE_2 0x95
- #define AVR_SIGNATURE_3 0x8A
- #elif defined(__AVR_ATmega16U2__)
- #define AVR_SIGNATURE_1 0x1E
- #define AVR_SIGNATURE_2 0x94
- #define AVR_SIGNATURE_3 0x89
- #elif defined(__AVR_AT90USB162__)
- #define AVR_SIGNATURE_1 0x1E
- #define AVR_SIGNATURE_2 0x94
- #define AVR_SIGNATURE_3 0x82
- #elif defined(__AVR_ATmega8U2__)
- #define AVR_SIGNATURE_1 0x1E
- #define AVR_SIGNATURE_2 0x93
- #define AVR_SIGNATURE_3 0x89
- #elif defined(__AVR_AT90USB82__)
- #define AVR_SIGNATURE_1 0x1E
- #define AVR_SIGNATURE_2 0x94
- #define AVR_SIGNATURE_3 0x82
- #else
- #error The selected AVR part is not currently supported by this bootloader.
- #endif
-
- /** Endpoint number for the CDC control interface event notification endpoint. */
- #define CDC_NOTIFICATION_EPNUM 2
-
- /** Endpoint number for the CDC data interface TX (data IN) endpoint. */
- #define CDC_TX_EPNUM 3
-
- /** Endpoint number for the CDC data interface RX (data OUT) endpoint. */
- #define CDC_RX_EPNUM 4
-
- /** Size of the CDC data interface TX and RX data endpoint banks, in bytes. */
- #define CDC_TXRX_EPSIZE 16
-
- /** Size of the CDC control interface notification endpoint bank, in bytes. */
- #define CDC_NOTIFICATION_EPSIZE 8
-
- /* Type Defines: */
- /** Type define for the device configuration descriptor structure. This must be defined in the
- * application code, as the configuration descriptor contains several sub-descriptors which
- * vary between devices, and which describe the device's usage to the host.
- */
- typedef struct
- {
- USB_Descriptor_Configuration_Header_t Config;
-
- // CDC Control Interface
- USB_Descriptor_Interface_t CDC_CCI_Interface;
- USB_CDC_Descriptor_FunctionalHeader_t CDC_Functional_Header;
- USB_CDC_Descriptor_FunctionalACM_t CDC_Functional_ACM;
- USB_CDC_Descriptor_FunctionalUnion_t CDC_Functional_Union;
- USB_Descriptor_Endpoint_t CDC_NotificationEndpoint;
-
- // CDC Data Interface
- USB_Descriptor_Interface_t CDC_DCI_Interface;
- USB_Descriptor_Endpoint_t CDC_DataOutEndpoint;
- USB_Descriptor_Endpoint_t CDC_DataInEndpoint;
- } USB_Descriptor_Configuration_t;
-
- /* Function Prototypes: */
- uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue,
- const uint8_t wIndex,
- const void** const DescriptorAddress)
- ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(3);
-
-#endif
-
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2011.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaim all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ *
+ * Header file for Descriptors.c.
+ */
+
+#ifndef _DESCRIPTORS_H_
+#define _DESCRIPTORS_H_
+
+ /* Includes: */
+ #include <LUFA/Drivers/USB/USB.h>
+
+ /* Macros: */
+ #if defined(__AVR_AT90USB1287__)
+ #define AVR_SIGNATURE_1 0x1E
+ #define AVR_SIGNATURE_2 0x97
+ #define AVR_SIGNATURE_3 0x82
+ #elif defined(__AVR_AT90USB647__)
+ #define AVR_SIGNATURE_1 0x1E
+ #define AVR_SIGNATURE_2 0x96
+ #define AVR_SIGNATURE_3 0x82
+ #elif defined(__AVR_AT90USB1286__)
+ #define AVR_SIGNATURE_1 0x1E
+ #define AVR_SIGNATURE_2 0x97
+ #define AVR_SIGNATURE_3 0x82
+ #elif defined(__AVR_AT90USB646__)
+ #define AVR_SIGNATURE_1 0x1E
+ #define AVR_SIGNATURE_2 0x96
+ #define AVR_SIGNATURE_3 0x82
+ #elif defined(__AVR_ATmega32U6__)
+ #define AVR_SIGNATURE_1 0x1E
+ #define AVR_SIGNATURE_2 0x95
+ #define AVR_SIGNATURE_3 0x88
+ #elif defined(__AVR_ATmega32U4__)
+ #define AVR_SIGNATURE_1 0x1E
+ #define AVR_SIGNATURE_2 0x95
+ #define AVR_SIGNATURE_3 0x87
+ #elif defined(__AVR_ATmega16U4__)
+ #define AVR_SIGNATURE_1 0x1E
+ #define AVR_SIGNATURE_2 0x94
+ #define AVR_SIGNATURE_3 0x88
+ #elif defined(__AVR_ATmega32U2__)
+ #define AVR_SIGNATURE_1 0x1E
+ #define AVR_SIGNATURE_2 0x95
+ #define AVR_SIGNATURE_3 0x8A
+ #elif defined(__AVR_ATmega16U2__)
+ #define AVR_SIGNATURE_1 0x1E
+ #define AVR_SIGNATURE_2 0x94
+ #define AVR_SIGNATURE_3 0x89
+ #elif defined(__AVR_AT90USB162__)
+ #define AVR_SIGNATURE_1 0x1E
+ #define AVR_SIGNATURE_2 0x94
+ #define AVR_SIGNATURE_3 0x82
+ #elif defined(__AVR_ATmega8U2__)
+ #define AVR_SIGNATURE_1 0x1E
+ #define AVR_SIGNATURE_2 0x93
+ #define AVR_SIGNATURE_3 0x89
+ #elif defined(__AVR_AT90USB82__)
+ #define AVR_SIGNATURE_1 0x1E
+ #define AVR_SIGNATURE_2 0x94
+ #define AVR_SIGNATURE_3 0x82
+ #else
+ #error The selected AVR part is not currently supported by this bootloader.
+ #endif
+
+ /** Endpoint number for the CDC control interface event notification endpoint. */
+ #define CDC_NOTIFICATION_EPNUM 2
+
+ /** Endpoint number for the CDC data interface TX (data IN) endpoint. */
+ #define CDC_TX_EPNUM 3
+
+ /** Endpoint number for the CDC data interface RX (data OUT) endpoint. */
+ #define CDC_RX_EPNUM 4
+
+ /** Size of the CDC data interface TX and RX data endpoint banks, in bytes. */
+ #define CDC_TXRX_EPSIZE 16
+
+ /** Size of the CDC control interface notification endpoint bank, in bytes. */
+ #define CDC_NOTIFICATION_EPSIZE 8
+
+ /* Type Defines: */
+ /** Type define for the device configuration descriptor structure. This must be defined in the
+ * application code, as the configuration descriptor contains several sub-descriptors which
+ * vary between devices, and which describe the device's usage to the host.
+ */
+ typedef struct
+ {
+ USB_Descriptor_Configuration_Header_t Config;
+
+ // CDC Control Interface
+ USB_Descriptor_Interface_t CDC_CCI_Interface;
+ USB_CDC_Descriptor_FunctionalHeader_t CDC_Functional_Header;
+ USB_CDC_Descriptor_FunctionalACM_t CDC_Functional_ACM;
+ USB_CDC_Descriptor_FunctionalUnion_t CDC_Functional_Union;
+ USB_Descriptor_Endpoint_t CDC_NotificationEndpoint;
+
+ // CDC Data Interface
+ USB_Descriptor_Interface_t CDC_DCI_Interface;
+ USB_Descriptor_Endpoint_t CDC_DataOutEndpoint;
+ USB_Descriptor_Endpoint_t CDC_DataInEndpoint;
+ } USB_Descriptor_Configuration_t;
+
+ /* Function Prototypes: */
+ uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue,
+ const uint8_t wIndex,
+ const void** const DescriptorAddress)
+ ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(3);
+
+#endif
diff --git a/hardware/arduino/bootloaders/stk500v2/License.txt
b/hardware/arduino/bootloaders/stk500v2/License.txt
index e7dcdd8..a66eb90 100644
--- a/hardware/arduino/bootloaders/stk500v2/License.txt
+++ b/hardware/arduino/bootloaders/stk500v2/License.txt
@@ -1,280 +1,280 @@
- GNU GENERAL PUBLIC LICENSE
- Version 2, June 1991
-
- Copyright (C) 1989, 1991 Free Software Foundation, Inc.
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
- Preamble
-
- The licenses for most software are designed to take away your
-freedom to share and change it. By contrast, the GNU General Public
-License is intended to guarantee your freedom to share and change free
-software--to make sure the software is free for all its users. This
-General Public License applies to most of the Free Software
-Foundation's software and to any other program whose authors commit to
-using it. (Some other Free Software Foundation software is covered by
-the GNU Library General Public License instead.) You can apply it to
-your programs, too.
-
- When we speak of free software, we are referring to freedom, not
-price. Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-this service if you wish), that you receive source code or can get it
-if you want it, that you can change the software or use pieces of it
-in new free programs; and that you know you can do these things.
-
- To protect your rights, we need to make restrictions that forbid
-anyone to deny you these rights or to ask you to surrender the rights.
-These restrictions translate to certain responsibilities for you if you
-distribute copies of the software, or if you modify it.
-
- For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must give the recipients all the rights that
-you have. You must make sure that they, too, receive or can get the
-source code. And you must show them these terms so they know their
-rights.
-
- We protect your rights with two steps: (1) copyright the software, and
-(2) offer you this license which gives you legal permission to copy,
-distribute and/or modify the software.
-
- Also, for each author's protection and ours, we want to make certain
-that everyone understands that there is no warranty for this free
-software. If the software is modified by someone else and passed on, we
-want its recipients to know that what they have is not the original, so
-that any problems introduced by others will not reflect on the original
-authors' reputations.
-
- Finally, any free program is threatened constantly by software
-patents. We wish to avoid the danger that redistributors of a free
-program will individually obtain patent licenses, in effect making the
-program proprietary. To prevent this, we have made it clear that any
-patent must be licensed for everyone's free use or not licensed at all.
-
- The precise terms and conditions for copying, distribution and
-modification follow.
-
- GNU GENERAL PUBLIC LICENSE
- TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
- 0. This License applies to any program or other work which contains
-a notice placed by the copyright holder saying it may be distributed
-under the terms of this General Public License. The "Program", below,
-refers to any such program or work, and a "work based on the Program"
-means either the Program or any derivative work under copyright law:
-that is to say, a work containing the Program or a portion of it,
-either verbatim or with modifications and/or translated into another
-language. (Hereinafter, translation is included without limitation in
-the term "modification".) Each licensee is addressed as "you".
-
-Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope. The act of
-running the Program is not restricted, and the output from the Program
-is covered only if its contents constitute a work based on the
-Program (independent of having been made by running the Program).
-Whether that is true depends on what the Program does.
-
- 1. You may copy and distribute verbatim copies of the Program's
-source code as you receive it, in any medium, provided that you
-conspicuously and appropriately publish on each copy an appropriate
-copyright notice and disclaimer of warranty; keep intact all the
-notices that refer to this License and to the absence of any warranty;
-and give any other recipients of the Program a copy of this License
-along with the Program.
-
-You may charge a fee for the physical act of transferring a copy, and
-you may at your option offer warranty protection in exchange for a fee.
-
- 2. You may modify your copy or copies of the Program or any portion
-of it, thus forming a work based on the Program, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
- a) You must cause the modified files to carry prominent notices
- stating that you changed the files and the date of any change.
-
- b) You must cause any work that you distribute or publish, that in
- whole or in part contains or is derived from the Program or any
- part thereof, to be licensed as a whole at no charge to all third
- parties under the terms of this License.
-
- c) If the modified program normally reads commands interactively
- when run, you must cause it, when started running for such
- interactive use in the most ordinary way, to print or display an
- announcement including an appropriate copyright notice and a
- notice that there is no warranty (or else, saying that you provide
- a warranty) and that users may redistribute the program under
- these conditions, and telling the user how to view a copy of this
- License. (Exception: if the Program itself is interactive but
- does not normally print such an announcement, your work based on
- the Program is not required to print an announcement.)
-
-These requirements apply to the modified work as a whole. If
-identifiable sections of that work are not derived from the Program,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works. But when you
-distribute the same sections as part of a whole which is a work based
-on the Program, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Program.
-
-In addition, mere aggregation of another work not based on the Program
-with the Program (or with a work based on the Program) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
- 3. You may copy and distribute the Program (or a work based on it,
-under Section 2) in object code or executable form under the terms of
-Sections 1 and 2 above provided that you also do one of the following:
-
- a) Accompany it with the complete corresponding machine-readable
- source code, which must be distributed under the terms of Sections
- 1 and 2 above on a medium customarily used for software interchange; or,
-
- b) Accompany it with a written offer, valid for at least three
- years, to give any third party, for a charge no more than your
- cost of physically performing source distribution, a complete
- machine-readable copy of the corresponding source code, to be
- distributed under the terms of Sections 1 and 2 above on a medium
- customarily used for software interchange; or,
-
- c) Accompany it with the information you received as to the offer
- to distribute corresponding source code. (This alternative is
- allowed only for noncommercial distribution and only if you
- received the program in object code or executable form with such
- an offer, in accord with Subsection b above.)
-
-The source code for a work means the preferred form of the work for
-making modifications to it. For an executable work, complete source
-code means all the source code for all modules it contains, plus any
-associated interface definition files, plus the scripts used to
-control compilation and installation of the executable. However, as a
-special exception, the source code distributed need not include
-anything that is normally distributed (in either source or binary
-form) with the major components (compiler, kernel, and so on) of the
-operating system on which the executable runs, unless that component
-itself accompanies the executable.
-
-If distribution of executable or object code is made by offering
-access to copy from a designated place, then offering equivalent
-access to copy the source code from the same place counts as
-distribution of the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
- 4. You may not copy, modify, sublicense, or distribute the Program
-except as expressly provided under this License. Any attempt
-otherwise to copy, modify, sublicense or distribute the Program is
-void, and will automatically terminate your rights under this License.
-However, parties who have received copies, or rights, from you under
-this License will not have their licenses terminated so long as such
-parties remain in full compliance.
-
- 5. You are not required to accept this License, since you have not
-signed it. However, nothing else grants you permission to modify or
-distribute the Program or its derivative works. These actions are
-prohibited by law if you do not accept this License. Therefore, by
-modifying or distributing the Program (or any work based on the
-Program), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Program or works based on it.
-
- 6. Each time you redistribute the Program (or any work based on the
-Program), the recipient automatically receives a license from the
-original licensor to copy, distribute or modify the Program subject to
-these terms and conditions. You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties to
-this License.
-
- 7. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License. If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Program at all. For example, if a patent
-license would not permit royalty-free redistribution of the Program by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Program.
-
-If any portion of this section is held invalid or unenforceable under
-any particular circumstance, the balance of the section is intended to
-apply and the section as a whole is intended to apply in other
-circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system, which is
-implemented by public license practices. Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
- 8. If the distribution and/or use of the Program is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Program under this License
-may add an explicit geographical distribution limitation excluding
-those countries, so that distribution is permitted only in or among
-countries not thus excluded. In such case, this License incorporates
-the limitation as if written in the body of this License.
-
- 9. The Free Software Foundation may publish revised and/or new versions
-of the General Public License from time to time. Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
-Each version is given a distinguishing version number. If the Program
-specifies a version number of this License which applies to it and "any
-later version", you have the option of following the terms and conditions
-either of that version or of any later version published by the Free
-Software Foundation. If the Program does not specify a version number of
-this License, you may choose any version ever published by the Free Software
-Foundation.
-
- 10. If you wish to incorporate parts of the Program into other free
-programs whose distribution conditions are different, write to the author
-to ask for permission. For software which is copyrighted by the Free
-Software Foundation, write to the Free Software Foundation; we sometimes
-make exceptions for this. Our decision will be guided by the two goals
-of preserving the free status of all derivatives of our free software and
-of promoting the sharing and reuse of software generally.
-
- NO WARRANTY
-
- 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
-FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
-OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
-PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
-OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
-TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
-PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
-REPAIR OR CORRECTION.
-
- 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
-REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
-INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
-OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
-TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
-YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
-PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGES.
-
- END OF TERMS AND CONDITIONS
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
diff --git a/hardware/arduino/firmwares/atmegaxxu2/arduino-usbdfu/Arduino-usbdfu.c
b/hardware/arduino/firmwares/atmegaxxu2/arduino-usbdfu/Arduino-usbdfu.c
index 7bed831..aa07293 100644
--- a/hardware/arduino/firmwares/atmegaxxu2/arduino-usbdfu/Arduino-usbdfu.c
+++ b/hardware/arduino/firmwares/atmegaxxu2/arduino-usbdfu/Arduino-usbdfu.c
@@ -1,728 +1,728 @@
-/*
- LUFA Library
- Copyright (C) Dean Camera, 2010.
-
- dean [at] fourwalledcubicle [dot] com
- www.fourwalledcubicle.com
-*/
-
-/*
- Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
-
- Permission to use, copy, modify, distribute, and sell this
- software and its documentation for any purpose is hereby granted
- without fee, provided that the above copyright notice appear in
- all copies and that both that the copyright notice and this
- permission notice and warranty disclaimer appear in supporting
- documentation, and that the name of the author not be used in
- advertising or publicity pertaining to distribution of the
- software without specific, written prior permission.
-
- The author disclaim all warranties with regard to this
- software, including all implied warranties of merchantability
- and fitness. In no event shall the author be liable for any
- special, indirect or consequential damages or any damages
- whatsoever resulting from loss of use, data or profits, whether
- in an action of contract, negligence or other tortious action,
- arising out of or in connection with the use or performance of
- this software.
-*/
-
-/** \file
- *
- * Main source file for the DFU class bootloader. This file contains the complete bootloader logic.
- */
-
-#define INCLUDE_FROM_BOOTLOADER_C
-#include "Arduino-usbdfu.h"
-
-/** Flag to indicate if the bootloader should be running, or should exit and allow the application code to
run
- * via a soft reset. When cleared, the bootloader will abort, the USB interface will shut down and the
application
- * jumped to via an indirect jump to location 0x0000 (or other location specified by the host).
- */
-bool RunBootloader = true;
-
-/** Flag to indicate if the bootloader is waiting to exit. When the host requests the bootloader to exit and
- * jump to the application address it specifies, it sends two sequential commands which must be properly
- * acknowledged. Upon reception of the first the RunBootloader flag is cleared and the WaitForExit flag is
set,
- * causing the bootloader to wait for the final exit command before shutting down.
- */
-bool WaitForExit = false;
-
-/** Current DFU state machine state, one of the values in the DFU_State_t enum. */
-uint8_t DFU_State = dfuIDLE;
-
-/** Status code of the last executed DFU command. This is set to one of the values in the DFU_Status_t enum
after
- * each operation, and returned to the host when a Get Status DFU request is issued.
- */
-uint8_t DFU_Status = OK;
-
-/** Data containing the DFU command sent from the host. */
-DFU_Command_t SentCommand;
-
-/** Response to the last issued Read Data DFU command. Unlike other DFU commands, the read command
- * requires a single byte response from the bootloader containing the read data when the next DFU_UPLOAD
command
- * is issued by the host.
- */
-uint8_t ResponseByte;
-
-/** Pointer to the start of the user application. By default this is 0x0000 (the reset vector), however the
host
- * may specify an alternate address when issuing the application soft-start command.
- */
-AppPtr_t AppStartPtr = (AppPtr_t)0x0000;
-
-/** 64-bit flash page number. This is concatenated with the current 16-bit address on USB AVRs containing
more than
- * 64KB of flash memory.
- */
-uint8_t Flash64KBPage = 0;
-
-/** Memory start address, indicating the current address in the memory being addressed (either FLASH or
EEPROM
- * depending on the issued command from the host).
- */
-uint16_t StartAddr = 0x0000;
-
-/** Memory end address, indicating the end address to read to/write from in the memory being addressed
(either FLASH
- * of EEPROM depending on the issued command from the host).
- */
-uint16_t EndAddr = 0x0000;
-
-
-/** Pulse generation counters to keep track of the number of milliseconds remaining for each pulse type */
-volatile struct
-{
- uint8_t TxLEDPulse; /**< Milliseconds remaining for data Tx LED pulse */
- uint8_t RxLEDPulse; /**< Milliseconds remaining for data Rx LED pulse */
- uint8_t PingPongLEDPulse; /**< Milliseconds remaining for enumeration Tx/Rx ping-pong LED pulse */
-} PulseMSRemaining;
-
-/** Main program entry point. This routine configures the hardware required by the bootloader, then
continuously
- * runs the bootloader processing routine until instructed to soft-exit, or hard-reset via the watchdog to
start
- * the loaded application code.
- */
-int main(void)
-{
- /* Configure hardware required by the bootloader */
- SetupHardware();
-
- /* Enable global interrupts so that the USB stack can function */
- sei();
-
- /* Run the USB management task while the bootloader is supposed to be running */
- while (RunBootloader || WaitForExit)
- USB_USBTask();
-
- /* Reset configured hardware back to their original states for the user application */
- ResetHardware();
-
- /* Start the user application */
- AppStartPtr();
-}
-
-/** Configures all hardware required for the bootloader. */
-void SetupHardware(void)
-{
- /* Disable watchdog if enabled by bootloader/fuses */
- MCUSR &= ~(1 << WDRF);
- wdt_disable();
-
- /* Disable clock division */
-// clock_prescale_set(clock_div_1);
-
- /* Relocate the interrupt vector table to the bootloader section */
- MCUCR = (1 << IVCE);
- MCUCR = (1 << IVSEL);
-
- LEDs_Init();
-
- /* Initialize the USB subsystem */
- USB_Init();
-}
-
-/** Resets all configured hardware required for the bootloader back to their original states. */
-void ResetHardware(void)
-{
- /* Shut down the USB subsystem */
- USB_ShutDown();
-
- /* Relocate the interrupt vector table back to the application section */
- MCUCR = (1 << IVCE);
- MCUCR = 0;
-}
-
-/** Event handler for the USB_UnhandledControlRequest event. This is used to catch standard and class
specific
- * control requests that are not handled internally by the USB library (including the DFU commands, which
are
- * all issued via the control endpoint), so that they can be handled appropriately for the application.
- */
-void EVENT_USB_Device_UnhandledControlRequest(void)
-{
- /* Get the size of the command and data from the wLength value */
- SentCommand.DataSize = USB_ControlRequest.wLength;
-
- /* Turn off TX LED(s) once the TX pulse period has elapsed */
- if (PulseMSRemaining.TxLEDPulse && !(--PulseMSRemaining.TxLEDPulse))
- LEDs_TurnOffLEDs(LEDMASK_TX);
-
- /* Turn off RX LED(s) once the RX pulse period has elapsed */
- if (PulseMSRemaining.RxLEDPulse && !(--PulseMSRemaining.RxLEDPulse))
- LEDs_TurnOffLEDs(LEDMASK_RX);
-
- switch (USB_ControlRequest.bRequest)
- {
- case DFU_DNLOAD:
- LEDs_TurnOnLEDs(LEDMASK_RX);
- PulseMSRemaining.RxLEDPulse = TX_RX_LED_PULSE_MS;
-
- Endpoint_ClearSETUP();
-
- /* Check if bootloader is waiting to terminate */
- if (WaitForExit)
- {
- /* Bootloader is terminating - process last received command */
- ProcessBootloaderCommand();
-
- /* Turn off TX/RX status LEDs so that they're not left on when application
starts */
- LEDs_TurnOffLEDs(LEDMASK_TX);
- LEDs_TurnOffLEDs(LEDMASK_RX);
-
- /* Indicate that the last command has now been processed - free to exit
bootloader */
- WaitForExit = false;
- }
-
- /* If the request has a data stage, load it into the command struct */
- if (SentCommand.DataSize)
- {
- while (!(Endpoint_IsOUTReceived()))
- {
- if (USB_DeviceState == DEVICE_STATE_Unattached)
- return;
- }
-
- /* First byte of the data stage is the DNLOAD request's command */
- SentCommand.Command = Endpoint_Read_Byte();
-
- /* One byte of the data stage is the command, so subtract it from the total
data bytes */
- SentCommand.DataSize--;
-
- /* Load in the rest of the data stage as command parameters */
- for (uint8_t DataByte = 0; (DataByte < sizeof(SentCommand.Data)) &&
- Endpoint_BytesInEndpoint(); DataByte++)
- {
- SentCommand.Data[DataByte] = Endpoint_Read_Byte();
- SentCommand.DataSize--;
- }
-
- /* Process the command */
- ProcessBootloaderCommand();
- }
-
- /* Check if currently downloading firmware */
- if (DFU_State == dfuDNLOAD_IDLE)
- {
- if (!(SentCommand.DataSize))
- {
- DFU_State = dfuIDLE;
- }
- else
- {
- /* Throw away the filler bytes before the start of the firmware */
- DiscardFillerBytes(DFU_FILLER_BYTES_SIZE);
-
- /* Throw away the packet alignment filler bytes before the start of
the firmware */
- DiscardFillerBytes(StartAddr % FIXED_CONTROL_ENDPOINT_SIZE);
-
- /* Calculate the number of bytes remaining to be written */
- uint16_t BytesRemaining = ((EndAddr - StartAddr) + 1);
-
- if (IS_ONEBYTE_COMMAND(SentCommand.Data, 0x00)) // Write flash
- {
- /* Calculate the number of words to be written from the
number of bytes to be written */
- uint16_t WordsRemaining = (BytesRemaining >> 1);
-
- union
- {
- uint16_t Words[2];
- uint32_t Long;
- } CurrFlashAddress = {.Words = {StartAddr,
Flash64KBPage}};
-
- uint32_t CurrFlashPageStartAddress = CurrFlashAddress.Long;
- uint8_t WordsInFlashPage = 0;
-
- while (WordsRemaining--)
- {
- /* Check if endpoint is empty - if so clear it and
wait until ready for next packet */
- if (!(Endpoint_BytesInEndpoint()))
- {
- Endpoint_ClearOUT();
-
- while (!(Endpoint_IsOUTReceived()))
- {
- if (USB_DeviceState ==
DEVICE_STATE_Unattached)
- return;
- }
- }
-
- /* Write the next word into the current flash page */
- boot_page_fill(CurrFlashAddress.Long,
Endpoint_Read_Word_LE());
-
- /* Adjust counters */
- WordsInFlashPage += 1;
- CurrFlashAddress.Long += 2;
-
- /* See if an entire page has been written to the
flash page buffer */
- if ((WordsInFlashPage == (SPM_PAGESIZE >> 1)) ||
!(WordsRemaining))
- {
- /* Commit the flash page to memory */
- boot_page_write(CurrFlashPageStartAddress);
- boot_spm_busy_wait();
-
- /* Check if programming incomplete */
- if (WordsRemaining)
- {
- CurrFlashPageStartAddress =
CurrFlashAddress.Long;
- WordsInFlashPage = 0;
-
- /* Erase next page's temp buffer */
-
boot_page_erase(CurrFlashAddress.Long);
- boot_spm_busy_wait();
- }
- }
- }
-
- /* Once programming complete, start address equals the end
address */
- StartAddr = EndAddr;
-
- /* Re-enable the RWW section of flash */
- boot_rww_enable();
- }
- else // Write EEPROM
- {
- while (BytesRemaining--)
- {
- /* Check if endpoint is empty - if so clear it and
wait until ready for next packet */
- if (!(Endpoint_BytesInEndpoint()))
- {
- Endpoint_ClearOUT();
-
- while (!(Endpoint_IsOUTReceived()))
- {
- if (USB_DeviceState ==
DEVICE_STATE_Unattached)
- return;
- }
- }
-
- /* Read the byte from the USB interface and write to
to the EEPROM */
- eeprom_write_byte((uint8_t*)StartAddr,
Endpoint_Read_Byte());
-
- /* Adjust counters */
- StartAddr++;
- }
- }
-
- /* Throw away the currently unused DFU file suffix */
- DiscardFillerBytes(DFU_FILE_SUFFIX_SIZE);
- }
- }
-
- Endpoint_ClearOUT();
-
- Endpoint_ClearStatusStage();
-
- break;
- case DFU_UPLOAD:
- Endpoint_ClearSETUP();
-
- LEDs_TurnOnLEDs(LEDMASK_TX);
- PulseMSRemaining.TxLEDPulse = TX_RX_LED_PULSE_MS;
-
- while (!(Endpoint_IsINReady()))
- {
- if (USB_DeviceState == DEVICE_STATE_Unattached)
- return;
- }
-
- if (DFU_State != dfuUPLOAD_IDLE)
- {
- if ((DFU_State == dfuERROR) && IS_ONEBYTE_COMMAND(SentCommand.Data, 0x01))
// Blank Check
- {
- /* Blank checking is performed in the DFU_DNLOAD request - if we get
here we've told the host
- that the memory isn't blank, and the host is requesting the first
non-blank address */
- Endpoint_Write_Word_LE(StartAddr);
- }
- else
- {
- /* Idle state upload - send response to last issued command */
- Endpoint_Write_Byte(ResponseByte);
- }
- }
- else
- {
- /* Determine the number of bytes remaining in the current block */
- uint16_t BytesRemaining = ((EndAddr - StartAddr) + 1);
-
- if (IS_ONEBYTE_COMMAND(SentCommand.Data, 0x00)) // Read FLASH
- {
- /* Calculate the number of words to be written from the number of
bytes to be written */
- uint16_t WordsRemaining = (BytesRemaining >> 1);
-
- union
- {
- uint16_t Words[2];
- uint32_t Long;
- } CurrFlashAddress = {.Words = {StartAddr, Flash64KBPage}};
-
- while (WordsRemaining--)
- {
- /* Check if endpoint is full - if so clear it and wait until
ready for next packet */
- if (Endpoint_BytesInEndpoint() == FIXED_CONTROL_ENDPOINT_SIZE)
- {
- Endpoint_ClearIN();
-
- while (!(Endpoint_IsINReady()))
- {
- if (USB_DeviceState ==
DEVICE_STATE_Unattached)
- return;
- }
- }
-
- /* Read the flash word and send it via USB to the host */
- #if (FLASHEND > 0xFFFF)
-
Endpoint_Write_Word_LE(pgm_read_word_far(CurrFlashAddress.Long));
- #else
-
Endpoint_Write_Word_LE(pgm_read_word(CurrFlashAddress.Long));
- #endif
-
- /* Adjust counters */
- CurrFlashAddress.Long += 2;
- }
-
- /* Once reading is complete, start address equals the end address */
- StartAddr = EndAddr;
- }
- else if (IS_ONEBYTE_COMMAND(SentCommand.Data, 0x02)) // Read EEPROM
- {
- while (BytesRemaining--)
- {
- /* Check if endpoint is full - if so clear it and wait until
ready for next packet */
- if (Endpoint_BytesInEndpoint() == FIXED_CONTROL_ENDPOINT_SIZE)
- {
- Endpoint_ClearIN();
-
- while (!(Endpoint_IsINReady()))
- {
- if (USB_DeviceState ==
DEVICE_STATE_Unattached)
- return;
- }
- }
-
- /* Read the EEPROM byte and send it via USB to the host */
- Endpoint_Write_Byte(eeprom_read_byte((uint8_t*)StartAddr));
-
- /* Adjust counters */
- StartAddr++;
- }
- }
-
- /* Return to idle state */
- DFU_State = dfuIDLE;
- }
-
- Endpoint_ClearIN();
-
- Endpoint_ClearStatusStage();
- break;
- case DFU_GETSTATUS:
- Endpoint_ClearSETUP();
-
- /* Write 8-bit status value */
- Endpoint_Write_Byte(DFU_Status);
-
- /* Write 24-bit poll timeout value */
- Endpoint_Write_Byte(0);
- Endpoint_Write_Word_LE(0);
-
- /* Write 8-bit state value */
- Endpoint_Write_Byte(DFU_State);
-
- /* Write 8-bit state string ID number */
- Endpoint_Write_Byte(0);
-
- Endpoint_ClearIN();
-
- Endpoint_ClearStatusStage();
- break;
- case DFU_CLRSTATUS:
- Endpoint_ClearSETUP();
-
- /* Reset the status value variable to the default OK status */
- DFU_Status = OK;
-
- Endpoint_ClearStatusStage();
- break;
- case DFU_GETSTATE:
- Endpoint_ClearSETUP();
-
- /* Write the current device state to the endpoint */
- Endpoint_Write_Byte(DFU_State);
-
- Endpoint_ClearIN();
-
- Endpoint_ClearStatusStage();
- break;
- case DFU_ABORT:
- Endpoint_ClearSETUP();
-
- /* Turn off TX/RX status LEDs so that they're not left on when application starts */
- LEDs_TurnOffLEDs(LEDMASK_TX);
- LEDs_TurnOffLEDs(LEDMASK_RX);
-
- /* Reset the current state variable to the default idle state */
- DFU_State = dfuIDLE;
-
- Endpoint_ClearStatusStage();
- break;
- }
-}
-
-/** Routine to discard the specified number of bytes from the control endpoint stream. This is used to
- * discard unused bytes in the stream from the host, including the memory program block suffix.
- *
- * \param[in] NumberOfBytes Number of bytes to discard from the host from the control endpoint
- */
-static void DiscardFillerBytes(uint8_t NumberOfBytes)
-{
- while (NumberOfBytes--)
- {
- if (!(Endpoint_BytesInEndpoint()))
- {
- Endpoint_ClearOUT();
-
- /* Wait until next data packet received */
- while (!(Endpoint_IsOUTReceived()))
- {
- if (USB_DeviceState == DEVICE_STATE_Unattached)
- return;
- }
- }
- else
- {
- Endpoint_Discard_Byte();
- }
- }
-}
-
-/** Routine to process an issued command from the host, via a DFU_DNLOAD request wrapper. This routine
ensures
- * that the command is allowed based on the current secure mode flag value, and passes the command off to
the
- * appropriate handler function.
- */
-static void ProcessBootloaderCommand(void)
-{
- /* Check if device is in secure mode */
-// if (IsSecure)
-// {
-// /* Don't process command unless it is a READ or chip erase command */
-// if (!(((SentCommand.Command == COMMAND_WRITE) &&
-// IS_TWOBYTE_COMMAND(SentCommand.Data, 0x00, 0xFF)) ||
-// (SentCommand.Command == COMMAND_READ)))
-// {
-// /* Set the state and status variables to indicate the error */
-// DFU_State = dfuERROR;
-// DFU_Status = errWRITE;
-//
-// /* Stall command */
-// Endpoint_StallTransaction();
-//
-// /* Don't process the command */
-// return;
-// }
-// }
-
- /* Dispatch the required command processing routine based on the command type */
- switch (SentCommand.Command)
- {
- case COMMAND_PROG_START:
- ProcessMemProgCommand();
- break;
- case COMMAND_DISP_DATA:
- ProcessMemReadCommand();
- break;
- case COMMAND_WRITE:
- ProcessWriteCommand();
- break;
- case COMMAND_READ:
- ProcessReadCommand();
- break;
- case COMMAND_CHANGE_BASE_ADDR:
- if (IS_TWOBYTE_COMMAND(SentCommand.Data, 0x03, 0x00)) // Set 64KB flash
page command
- Flash64KBPage = SentCommand.Data[2];
- break;
- }
-}
-
-/** Routine to concatenate the given pair of 16-bit memory start and end addresses from the host, and store
them
- * in the StartAddr and EndAddr global variables.
- */
-static void LoadStartEndAddresses(void)
-{
- union
- {
- uint8_t Bytes[2];
- uint16_t Word;
- } Address[2] = {{.Bytes = {SentCommand.Data[2], SentCommand.Data[1]}},
- {.Bytes = {SentCommand.Data[4], SentCommand.Data[3]}}};
-
- /* Load in the start and ending read addresses from the sent data packet */
- StartAddr = Address[0].Word;
- EndAddr = Address[1].Word;
-}
-
-/** Handler for a Memory Program command issued by the host. This routine handles the preparations needed
- * to write subsequent data from the host into the specified memory.
- */
-static void ProcessMemProgCommand(void)
-{
- if (IS_ONEBYTE_COMMAND(SentCommand.Data, 0x00) || // Write FLASH command
- IS_ONEBYTE_COMMAND(SentCommand.Data, 0x01)) // Write EEPROM command
- {
- /* Load in the start and ending read addresses */
- LoadStartEndAddresses();
-
- /* If FLASH is being written to, we need to pre-erase the first page to write to */
- if (IS_ONEBYTE_COMMAND(SentCommand.Data, 0x00))
- {
- union
- {
- uint16_t Words[2];
- uint32_t Long;
- } CurrFlashAddress = {.Words = {StartAddr, Flash64KBPage}};
-
- /* Erase the current page's temp buffer */
- boot_page_erase(CurrFlashAddress.Long);
- boot_spm_busy_wait();
- }
-
- /* Set the state so that the next DNLOAD requests reads in the firmware */
- DFU_State = dfuDNLOAD_IDLE;
- }
-}
-
-/** Handler for a Memory Read command issued by the host. This routine handles the preparations needed
- * to read subsequent data from the specified memory out to the host, as well as implementing the memory
- * blank check command.
- */
-static void ProcessMemReadCommand(void)
-{
- if (IS_ONEBYTE_COMMAND(SentCommand.Data, 0x00) || // Read FLASH command
- IS_ONEBYTE_COMMAND(SentCommand.Data, 0x02)) // Read EEPROM command
- {
- /* Load in the start and ending read addresses */
- LoadStartEndAddresses();
-
- /* Set the state so that the next UPLOAD requests read out the firmware */
- DFU_State = dfuUPLOAD_IDLE;
- }
- else if (IS_ONEBYTE_COMMAND(SentCommand.Data, 0x01)) // Blank check FLASH
command
- {
- uint32_t CurrFlashAddress = 0;
-
- while (CurrFlashAddress < BOOT_START_ADDR)
- {
- /* Check if the current byte is not blank */
- #if (FLASHEND > 0xFFFF)
- if (pgm_read_byte_far(CurrFlashAddress) != 0xFF)
- #else
- if (pgm_read_byte(CurrFlashAddress) != 0xFF)
- #endif
- {
- /* Save the location of the first non-blank byte for response back to the
host */
- Flash64KBPage = (CurrFlashAddress >> 16);
- StartAddr = CurrFlashAddress;
-
- /* Set state and status variables to the appropriate error values */
- DFU_State = dfuERROR;
- DFU_Status = errCHECK_ERASED;
-
- break;
- }
-
- CurrFlashAddress++;
- }
- }
-}
-
-/** Handler for a Data Write command issued by the host. This routine handles non-programming commands such
as
- * bootloader exit (both via software jumps and hardware watchdog resets) and flash memory erasure.
- */
-static void ProcessWriteCommand(void)
-{
- if (IS_ONEBYTE_COMMAND(SentCommand.Data, 0x03)) // Start application
- {
- /* Indicate that the bootloader is terminating */
- WaitForExit = true;
-
- /* Check if data supplied for the Start Program command - no data executes the program */
- if (SentCommand.DataSize)
- {
- if (SentCommand.Data[1] == 0x01) // Start via jump
- {
- union
- {
- uint8_t Bytes[2];
- AppPtr_t FuncPtr;
- } Address = {.Bytes = {SentCommand.Data[4], SentCommand.Data[3]}};
-
- /* Load in the jump address into the application start address pointer */
- AppStartPtr = Address.FuncPtr;
- }
- }
- else
- {
- if (SentCommand.Data[1] == 0x00) // Start via
watchdog
- {
- /* Start the watchdog to reset the AVR once the communications are finalized
*/
- wdt_enable(WDTO_250MS);
- }
- else // Start via jump
- {
- /* Set the flag to terminate the bootloader at next opportunity */
- RunBootloader = false;
- }
- }
- }
- else if (IS_TWOBYTE_COMMAND(SentCommand.Data, 0x00, 0xFF)) // Erase flash
- {
- uint32_t CurrFlashAddress = 0;
-
- /* Clear the application section of flash */
- while (CurrFlashAddress < BOOT_START_ADDR)
- {
- boot_page_erase(CurrFlashAddress);
- boot_spm_busy_wait();
- boot_page_write(CurrFlashAddress);
- boot_spm_busy_wait();
-
- CurrFlashAddress += SPM_PAGESIZE;
- }
-
- /* Re-enable the RWW section of flash as writing to the flash locks it out */
- boot_rww_enable();
-
- /* Memory has been erased, reset the security bit so that programming/reading is allowed */
-// IsSecure = false;
- }
-}
-
-/** Handler for a Data Read command issued by the host. This routine handles bootloader information retrieval
- * commands such as device signature and bootloader version retrieval.
- */
-static void ProcessReadCommand(void)
-{
- const uint8_t BootloaderInfo[3] = {BOOTLOADER_VERSION, BOOTLOADER_ID_BYTE1, BOOTLOADER_ID_BYTE2};
- const uint8_t SignatureInfo[3] = {AVR_SIGNATURE_1, AVR_SIGNATURE_2, AVR_SIGNATURE_3};
-
- uint8_t DataIndexToRead = SentCommand.Data[1];
-
- if (IS_ONEBYTE_COMMAND(SentCommand.Data, 0x00)) // Read bootloader info
- ResponseByte = BootloaderInfo[DataIndexToRead];
- else if (IS_ONEBYTE_COMMAND(SentCommand.Data, 0x01)) // Read signature byte
- ResponseByte = SignatureInfo[DataIndexToRead - 0x30];
-}
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2010.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.fourwalledcubicle.com
+*/
+
+/*
+ Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaim all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ *
+ * Main source file for the DFU class bootloader. This file contains the complete bootloader logic.
+ */
+
+#define INCLUDE_FROM_BOOTLOADER_C
+#include "Arduino-usbdfu.h"
+
+/** Flag to indicate if the bootloader should be running, or should exit and allow the application code to
run
+ * via a soft reset. When cleared, the bootloader will abort, the USB interface will shut down and the
application
+ * jumped to via an indirect jump to location 0x0000 (or other location specified by the host).
+ */
+bool RunBootloader = true;
+
+/** Flag to indicate if the bootloader is waiting to exit. When the host requests the bootloader to exit and
+ * jump to the application address it specifies, it sends two sequential commands which must be properly
+ * acknowledged. Upon reception of the first the RunBootloader flag is cleared and the WaitForExit flag is
set,
+ * causing the bootloader to wait for the final exit command before shutting down.
+ */
+bool WaitForExit = false;
+
+/** Current DFU state machine state, one of the values in the DFU_State_t enum. */
+uint8_t DFU_State = dfuIDLE;
+
+/** Status code of the last executed DFU command. This is set to one of the values in the DFU_Status_t enum
after
+ * each operation, and returned to the host when a Get Status DFU request is issued.
+ */
+uint8_t DFU_Status = OK;
+
+/** Data containing the DFU command sent from the host. */
+DFU_Command_t SentCommand;
+
+/** Response to the last issued Read Data DFU command. Unlike other DFU commands, the read command
+ * requires a single byte response from the bootloader containing the read data when the next DFU_UPLOAD
command
+ * is issued by the host.
+ */
+uint8_t ResponseByte;
+
+/** Pointer to the start of the user application. By default this is 0x0000 (the reset vector), however the
host
+ * may specify an alternate address when issuing the application soft-start command.
+ */
+AppPtr_t AppStartPtr = (AppPtr_t)0x0000;
+
+/** 64-bit flash page number. This is concatenated with the current 16-bit address on USB AVRs containing
more than
+ * 64KB of flash memory.
+ */
+uint8_t Flash64KBPage = 0;
+
+/** Memory start address, indicating the current address in the memory being addressed (either FLASH or
EEPROM
+ * depending on the issued command from the host).
+ */
+uint16_t StartAddr = 0x0000;
+
+/** Memory end address, indicating the end address to read to/write from in the memory being addressed
(either FLASH
+ * of EEPROM depending on the issued command from the host).
+ */
+uint16_t EndAddr = 0x0000;
+
+
+/** Pulse generation counters to keep track of the number of milliseconds remaining for each pulse type */
+volatile struct
+{
+ uint8_t TxLEDPulse; /**< Milliseconds remaining for data Tx LED pulse */
+ uint8_t RxLEDPulse; /**< Milliseconds remaining for data Rx LED pulse */
+ uint8_t PingPongLEDPulse; /**< Milliseconds remaining for enumeration Tx/Rx ping-pong LED pulse */
+} PulseMSRemaining;
+
+/** Main program entry point. This routine configures the hardware required by the bootloader, then
continuously
+ * runs the bootloader processing routine until instructed to soft-exit, or hard-reset via the watchdog to
start
+ * the loaded application code.
+ */
+int main(void)
+{
+ /* Configure hardware required by the bootloader */
+ SetupHardware();
+
+ /* Enable global interrupts so that the USB stack can function */
+ sei();
+
+ /* Run the USB management task while the bootloader is supposed to be running */
+ while (RunBootloader || WaitForExit)
+ USB_USBTask();
+
+ /* Reset configured hardware back to their original states for the user application */
+ ResetHardware();
+
+ /* Start the user application */
+ AppStartPtr();
+}
+
+/** Configures all hardware required for the bootloader. */
+void SetupHardware(void)
+{
+ /* Disable watchdog if enabled by bootloader/fuses */
+ MCUSR &= ~(1 << WDRF);
+ wdt_disable();
+
+ /* Disable clock division */
+// clock_prescale_set(clock_div_1);
+
+ /* Relocate the interrupt vector table to the bootloader section */
+ MCUCR = (1 << IVCE);
+ MCUCR = (1 << IVSEL);
+
+ LEDs_Init();
+
+ /* Initialize the USB subsystem */
+ USB_Init();
+}
+
+/** Resets all configured hardware required for the bootloader back to their original states. */
+void ResetHardware(void)
+{
+ /* Shut down the USB subsystem */
+ USB_ShutDown();
+
+ /* Relocate the interrupt vector table back to the application section */
+ MCUCR = (1 << IVCE);
+ MCUCR = 0;
+}
+
+/** Event handler for the USB_UnhandledControlRequest event. This is used to catch standard and class
specific
+ * control requests that are not handled internally by the USB library (including the DFU commands, which
are
+ * all issued via the control endpoint), so that they can be handled appropriately for the application.
+ */
+void EVENT_USB_Device_UnhandledControlRequest(void)
+{
+ /* Get the size of the command and data from the wLength value */
+ SentCommand.DataSize = USB_ControlRequest.wLength;
+
+ /* Turn off TX LED(s) once the TX pulse period has elapsed */
+ if (PulseMSRemaining.TxLEDPulse && !(--PulseMSRemaining.TxLEDPulse))
+ LEDs_TurnOffLEDs(LEDMASK_TX);
+
+ /* Turn off RX LED(s) once the RX pulse period has elapsed */
+ if (PulseMSRemaining.RxLEDPulse && !(--PulseMSRemaining.RxLEDPulse))
+ LEDs_TurnOffLEDs(LEDMASK_RX);
+
+ switch (USB_ControlRequest.bRequest)
+ {
+ case DFU_DNLOAD:
+ LEDs_TurnOnLEDs(LEDMASK_RX);
+ PulseMSRemaining.RxLEDPulse = TX_RX_LED_PULSE_MS;
+
+ Endpoint_ClearSETUP();
+
+ /* Check if bootloader is waiting to terminate */
+ if (WaitForExit)
+ {
+ /* Bootloader is terminating - process last received command */
+ ProcessBootloaderCommand();
+
+ /* Turn off TX/RX status LEDs so that they're not left on when application
starts */
+ LEDs_TurnOffLEDs(LEDMASK_TX);
+ LEDs_TurnOffLEDs(LEDMASK_RX);
+
+ /* Indicate that the last command has now been processed - free to exit
bootloader */
+ WaitForExit = false;
+ }
+
+ /* If the request has a data stage, load it into the command struct */
+ if (SentCommand.DataSize)
+ {
+ while (!(Endpoint_IsOUTReceived()))
+ {
+ if (USB_DeviceState == DEVICE_STATE_Unattached)
+ return;
+ }
+
+ /* First byte of the data stage is the DNLOAD request's command */
+ SentCommand.Command = Endpoint_Read_Byte();
+
+ /* One byte of the data stage is the command, so subtract it from the total
data bytes */
+ SentCommand.DataSize--;
+
+ /* Load in the rest of the data stage as command parameters */
+ for (uint8_t DataByte = 0; (DataByte < sizeof(SentCommand.Data)) &&
+ Endpoint_BytesInEndpoint(); DataByte++)
+ {
+ SentCommand.Data[DataByte] = Endpoint_Read_Byte();
+ SentCommand.DataSize--;
+ }
+
+ /* Process the command */
+ ProcessBootloaderCommand();
+ }
+
+ /* Check if currently downloading firmware */
+ if (DFU_State == dfuDNLOAD_IDLE)
+ {
+ if (!(SentCommand.DataSize))
+ {
+ DFU_State = dfuIDLE;
+ }
+ else
+ {
+ /* Throw away the filler bytes before the start of the firmware */
+ DiscardFillerBytes(DFU_FILLER_BYTES_SIZE);
+
+ /* Throw away the packet alignment filler bytes before the start of
the firmware */
+ DiscardFillerBytes(StartAddr % FIXED_CONTROL_ENDPOINT_SIZE);
+
+ /* Calculate the number of bytes remaining to be written */
+ uint16_t BytesRemaining = ((EndAddr - StartAddr) + 1);
+
+ if (IS_ONEBYTE_COMMAND(SentCommand.Data, 0x00)) // Write flash
+ {
+ /* Calculate the number of words to be written from the
number of bytes to be written */
+ uint16_t WordsRemaining = (BytesRemaining >> 1);
+
+ union
+ {
+ uint16_t Words[2];
+ uint32_t Long;
+ } CurrFlashAddress = {.Words = {StartAddr,
Flash64KBPage}};
+
+ uint32_t CurrFlashPageStartAddress = CurrFlashAddress.Long;
+ uint8_t WordsInFlashPage = 0;
+
+ while (WordsRemaining--)
+ {
+ /* Check if endpoint is empty - if so clear it and
wait until ready for next packet */
+ if (!(Endpoint_BytesInEndpoint()))
+ {
+ Endpoint_ClearOUT();
+
+ while (!(Endpoint_IsOUTReceived()))
+ {
+ if (USB_DeviceState ==
DEVICE_STATE_Unattached)
+ return;
+ }
+ }
+
+ /* Write the next word into the current flash page */
+ boot_page_fill(CurrFlashAddress.Long,
Endpoint_Read_Word_LE());
+
+ /* Adjust counters */
+ WordsInFlashPage += 1;
+ CurrFlashAddress.Long += 2;
+
+ /* See if an entire page has been written to the
flash page buffer */
+ if ((WordsInFlashPage == (SPM_PAGESIZE >> 1)) ||
!(WordsRemaining))
+ {
+ /* Commit the flash page to memory */
+ boot_page_write(CurrFlashPageStartAddress);
+ boot_spm_busy_wait();
+
+ /* Check if programming incomplete */
+ if (WordsRemaining)
+ {
+ CurrFlashPageStartAddress =
CurrFlashAddress.Long;
+ WordsInFlashPage = 0;
+
+ /* Erase next page's temp buffer */
+
boot_page_erase(CurrFlashAddress.Long);
+ boot_spm_busy_wait();
+ }
+ }
+ }
+
+ /* Once programming complete, start address equals the end
address */
+ StartAddr = EndAddr;
+
+ /* Re-enable the RWW section of flash */
+ boot_rww_enable();
+ }
+ else // Write EEPROM
+ {
+ while (BytesRemaining--)
+ {
+ /* Check if endpoint is empty - if so clear it and
wait until ready for next packet */
+ if (!(Endpoint_BytesInEndpoint()))
+ {
+ Endpoint_ClearOUT();
+
+ while (!(Endpoint_IsOUTReceived()))
+ {
+ if (USB_DeviceState ==
DEVICE_STATE_Unattached)
+ return;
+ }
+ }
+
+ /* Read the byte from the USB interface and write to
to the EEPROM */
+ eeprom_write_byte((uint8_t*)StartAddr,
Endpoint_Read_Byte());
+
+ /* Adjust counters */
+ StartAddr++;
+ }
+ }
+
+ /* Throw away the currently unused DFU file suffix */
+ DiscardFillerBytes(DFU_FILE_SUFFIX_SIZE);
+ }
+ }
+
+ Endpoint_ClearOUT();
+
+ Endpoint_ClearStatusStage();
+
+ break;
+ case DFU_UPLOAD:
+ Endpoint_ClearSETUP();
+
+ LEDs_TurnOnLEDs(LEDMASK_TX);
+ PulseMSRemaining.TxLEDPulse = TX_RX_LED_PULSE_MS;
+
+ while (!(Endpoint_IsINReady()))
+ {
+ if (USB_DeviceState == DEVICE_STATE_Unattached)
+ return;
+ }
+
+ if (DFU_State != dfuUPLOAD_IDLE)
+ {
+ if ((DFU_State == dfuERROR) && IS_ONEBYTE_COMMAND(SentCommand.Data, 0x01))
// Blank Check
+ {
+ /* Blank checking is performed in the DFU_DNLOAD request - if we get
here we've told the host
+ that the memory isn't blank, and the host is requesting the first
non-blank address */
+ Endpoint_Write_Word_LE(StartAddr);
+ }
+ else
+ {
+ /* Idle state upload - send response to last issued command */
+ Endpoint_Write_Byte(ResponseByte);
+ }
+ }
+ else
+ {
+ /* Determine the number of bytes remaining in the current block */
+ uint16_t BytesRemaining = ((EndAddr - StartAddr) + 1);
+
+ if (IS_ONEBYTE_COMMAND(SentCommand.Data, 0x00)) // Read FLASH
+ {
+ /* Calculate the number of words to be written from the number of
bytes to be written */
+ uint16_t WordsRemaining = (BytesRemaining >> 1);
+
+ union
+ {
+ uint16_t Words[2];
+ uint32_t Long;
+ } CurrFlashAddress = {.Words = {StartAddr, Flash64KBPage}};
+
+ while (WordsRemaining--)
+ {
+ /* Check if endpoint is full - if so clear it and wait until
ready for next packet */
+ if (Endpoint_BytesInEndpoint() == FIXED_CONTROL_ENDPOINT_SIZE)
+ {
+ Endpoint_ClearIN();
+
+ while (!(Endpoint_IsINReady()))
+ {
+ if (USB_DeviceState ==
DEVICE_STATE_Unattached)
+ return;
+ }
+ }
+
+ /* Read the flash word and send it via USB to the host */
+ #if (FLASHEND > 0xFFFF)
+
Endpoint_Write_Word_LE(pgm_read_word_far(CurrFlashAddress.Long));
+ #else
+
Endpoint_Write_Word_LE(pgm_read_word(CurrFlashAddress.Long));
+ #endif
+
+ /* Adjust counters */
+ CurrFlashAddress.Long += 2;
+ }
+
+ /* Once reading is complete, start address equals the end address */
+ StartAddr = EndAddr;
+ }
+ else if (IS_ONEBYTE_COMMAND(SentCommand.Data, 0x02)) // Read EEPROM
+ {
+ while (BytesRemaining--)
+ {
+ /* Check if endpoint is full - if so clear it and wait until
ready for next packet */
+ if (Endpoint_BytesInEndpoint() == FIXED_CONTROL_ENDPOINT_SIZE)
+ {
+ Endpoint_ClearIN();
+
+ while (!(Endpoint_IsINReady()))
+ {
+ if (USB_DeviceState ==
DEVICE_STATE_Unattached)
+ return;
+ }
+ }
+
+ /* Read the EEPROM byte and send it via USB to the host */
+ Endpoint_Write_Byte(eeprom_read_byte((uint8_t*)StartAddr));
+
+ /* Adjust counters */
+ StartAddr++;
+ }
+ }
+
+ /* Return to idle state */
+ DFU_State = dfuIDLE;
+ }
+
+ Endpoint_ClearIN();
+
+ Endpoint_ClearStatusStage();
+ break;
+ case DFU_GETSTATUS:
+ Endpoint_ClearSETUP();
+
+ /* Write 8-bit status value */
+ Endpoint_Write_Byte(DFU_Status);
+
+ /* Write 24-bit poll timeout value */
+ Endpoint_Write_Byte(0);
+ Endpoint_Write_Word_LE(0);
+
+ /* Write 8-bit state value */
+ Endpoint_Write_Byte(DFU_State);
+
+ /* Write 8-bit state string ID number */
+ Endpoint_Write_Byte(0);
+
+ Endpoint_ClearIN();
+
+ Endpoint_ClearStatusStage();
+ break;
+ case DFU_CLRSTATUS:
+ Endpoint_ClearSETUP();
+
+ /* Reset the status value variable to the default OK status */
+ DFU_Status = OK;
+
+ Endpoint_ClearStatusStage();
+ break;
+ case DFU_GETSTATE:
+ Endpoint_ClearSETUP();
+
+ /* Write the current device state to the endpoint */
+ Endpoint_Write_Byte(DFU_State);
+
+ Endpoint_ClearIN();
+
+ Endpoint_ClearStatusStage();
+ break;
+ case DFU_ABORT:
+ Endpoint_ClearSETUP();
+
+ /* Turn off TX/RX status LEDs so that they're not left on when application starts */
+ LEDs_TurnOffLEDs(LEDMASK_TX);
+ LEDs_TurnOffLEDs(LEDMASK_RX);
+
+ /* Reset the current state variable to the default idle state */
+ DFU_State = dfuIDLE;
+
+ Endpoint_ClearStatusStage();
+ break;
+ }
+}
+
+/** Routine to discard the specified number of bytes from the control endpoint stream. This is used to
+ * discard unused bytes in the stream from the host, including the memory program block suffix.
+ *
+ * \param[in] NumberOfBytes Number of bytes to discard from the host from the control endpoint
+ */
+static void DiscardFillerBytes(uint8_t NumberOfBytes)
+{
+ while (NumberOfBytes--)
+ {
+ if (!(Endpoint_BytesInEndpoint()))
+ {
+ Endpoint_ClearOUT();
+
+ /* Wait until next data packet received */
+ while (!(Endpoint_IsOUTReceived()))
+ {
+ if (USB_DeviceState == DEVICE_STATE_Unattached)
+ return;
+ }
+ }
+ else
+ {
+ Endpoint_Discard_Byte();
+ }
+ }
+}
+
+/** Routine to process an issued command from the host, via a DFU_DNLOAD request wrapper. This routine
ensures
+ * that the command is allowed based on the current secure mode flag value, and passes the command off to
the
+ * appropriate handler function.
+ */
+static void ProcessBootloaderCommand(void)
+{
+ /* Check if device is in secure mode */
+// if (IsSecure)
+// {
+// /* Don't process command unless it is a READ or chip erase command */
+// if (!(((SentCommand.Command == COMMAND_WRITE) &&
+// IS_TWOBYTE_COMMAND(SentCommand.Data, 0x00, 0xFF)) ||
+// (SentCommand.Command == COMMAND_READ)))
+// {
+// /* Set the state and status variables to indicate the error */
+// DFU_State = dfuERROR;
+// DFU_Status = errWRITE;
+//
+// /* Stall command */
+// Endpoint_StallTransaction();
+//
+// /* Don't process the command */
+// return;
+// }
+// }
+
+ /* Dispatch the required command processing routine based on the command type */
+ switch (SentCommand.Command)
+ {
+ case COMMAND_PROG_START:
+ ProcessMemProgCommand();
+ break;
+ case COMMAND_DISP_DATA:
+ ProcessMemReadCommand();
+ break;
+ case COMMAND_WRITE:
+ ProcessWriteCommand();
+ break;
+ case COMMAND_READ:
+ ProcessReadCommand();
+ break;
+ case COMMAND_CHANGE_BASE_ADDR:
+ if (IS_TWOBYTE_COMMAND(SentCommand.Data, 0x03, 0x00)) // Set 64KB flash
page command
+ Flash64KBPage = SentCommand.Data[2];
+ break;
+ }
+}
+
+/** Routine to concatenate the given pair of 16-bit memory start and end addresses from the host, and store
them
+ * in the StartAddr and EndAddr global variables.
+ */
+static void LoadStartEndAddresses(void)
+{
+ union
+ {
+ uint8_t Bytes[2];
+ uint16_t Word;
+ } Address[2] = {{.Bytes = {SentCommand.Data[2], SentCommand.Data[1]}},
+ {.Bytes = {SentCommand.Data[4], SentCommand.Data[3]}}};
+
+ /* Load in the start and ending read addresses from the sent data packet */
+ StartAddr = Address[0].Word;
+ EndAddr = Address[1].Word;
+}
+
+/** Handler for a Memory Program command issued by the host. This routine handles the preparations needed
+ * to write subsequent data from the host into the specified memory.
+ */
+static void ProcessMemProgCommand(void)
+{
+ if (IS_ONEBYTE_COMMAND(SentCommand.Data, 0x00) || // Write FLASH command
+ IS_ONEBYTE_COMMAND(SentCommand.Data, 0x01)) // Write EEPROM command
+ {
+ /* Load in the start and ending read addresses */
+ LoadStartEndAddresses();
+
+ /* If FLASH is being written to, we need to pre-erase the first page to write to */
+ if (IS_ONEBYTE_COMMAND(SentCommand.Data, 0x00))
+ {
+ union
+ {
+ uint16_t Words[2];
+ uint32_t Long;
+ } CurrFlashAddress = {.Words = {StartAddr, Flash64KBPage}};
+
+ /* Erase the current page's temp buffer */
+ boot_page_erase(CurrFlashAddress.Long);
+ boot_spm_busy_wait();
+ }
+
+ /* Set the state so that the next DNLOAD requests reads in the firmware */
+ DFU_State = dfuDNLOAD_IDLE;
+ }
+}
+
+/** Handler for a Memory Read command issued by the host. This routine handles the preparations needed
+ * to read subsequent data from the specified memory out to the host, as well as implementing the memory
+ * blank check command.
+ */
+static void ProcessMemReadCommand(void)
+{
+ if (IS_ONEBYTE_COMMAND(SentCommand.Data, 0x00) || // Read FLASH command
+ IS_ONEBYTE_COMMAND(SentCommand.Data, 0x02)) // Read EEPROM command
+ {
+ /* Load in the start and ending read addresses */
+ LoadStartEndAddresses();
+
+ /* Set the state so that the next UPLOAD requests read out the firmware */
+ DFU_State = dfuUPLOAD_IDLE;
+ }
+ else if (IS_ONEBYTE_COMMAND(SentCommand.Data, 0x01)) // Blank check FLASH
command
+ {
+ uint32_t CurrFlashAddress = 0;
+
+ while (CurrFlashAddress < BOOT_START_ADDR)
+ {
+ /* Check if the current byte is not blank */
+ #if (FLASHEND > 0xFFFF)
+ if (pgm_read_byte_far(CurrFlashAddress) != 0xFF)
+ #else
+ if (pgm_read_byte(CurrFlashAddress) != 0xFF)
+ #endif
+ {
+ /* Save the location of the first non-blank byte for response back to the
host */
+ Flash64KBPage = (CurrFlashAddress >> 16);
+ StartAddr = CurrFlashAddress;
+
+ /* Set state and status variables to the appropriate error values */
+ DFU_State = dfuERROR;
+ DFU_Status = errCHECK_ERASED;
+
+ break;
+ }
+
+ CurrFlashAddress++;
+ }
+ }
+}
+
+/** Handler for a Data Write command issued by the host. This routine handles non-programming commands such
as
+ * bootloader exit (both via software jumps and hardware watchdog resets) and flash memory erasure.
+ */
+static void ProcessWriteCommand(void)
+{
+ if (IS_ONEBYTE_COMMAND(SentCommand.Data, 0x03)) // Start application
+ {
+ /* Indicate that the bootloader is terminating */
+ WaitForExit = true;
+
+ /* Check if data supplied for the Start Program command - no data executes the program */
+ if (SentCommand.DataSize)
+ {
+ if (SentCommand.Data[1] == 0x01) // Start via jump
+ {
+ union
+ {
+ uint8_t Bytes[2];
+ AppPtr_t FuncPtr;
+ } Address = {.Bytes = {SentCommand.Data[4], SentCommand.Data[3]}};
+
+ /* Load in the jump address into the application start address pointer */
+ AppStartPtr = Address.FuncPtr;
+ }
+ }
+ else
+ {
+ if (SentCommand.Data[1] == 0x00) // Start via
watchdog
+ {
+ /* Start the watchdog to reset the AVR once the communications are finalized
*/
+ wdt_enable(WDTO_250MS);
+ }
+ else // Start via jump
+ {
+ /* Set the flag to terminate the bootloader at next opportunity */
+ RunBootloader = false;
+ }
+ }
+ }
+ else if (IS_TWOBYTE_COMMAND(SentCommand.Data, 0x00, 0xFF)) // Erase flash
+ {
+ uint32_t CurrFlashAddress = 0;
+
+ /* Clear the application section of flash */
+ while (CurrFlashAddress < BOOT_START_ADDR)
+ {
+ boot_page_erase(CurrFlashAddress);
+ boot_spm_busy_wait();
+ boot_page_write(CurrFlashAddress);
+ boot_spm_busy_wait();
+
+ CurrFlashAddress += SPM_PAGESIZE;
+ }
+
+ /* Re-enable the RWW section of flash as writing to the flash locks it out */
+ boot_rww_enable();
+
+ /* Memory has been erased, reset the security bit so that programming/reading is allowed */
+// IsSecure = false;
+ }
+}
+
+/** Handler for a Data Read command issued by the host. This routine handles bootloader information retrieval
+ * commands such as device signature and bootloader version retrieval.
+ */
+static void ProcessReadCommand(void)
+{
+ const uint8_t BootloaderInfo[3] = {BOOTLOADER_VERSION, BOOTLOADER_ID_BYTE1, BOOTLOADER_ID_BYTE2};
+ const uint8_t SignatureInfo[3] = {AVR_SIGNATURE_1, AVR_SIGNATURE_2, AVR_SIGNATURE_3};
+
+ uint8_t DataIndexToRead = SentCommand.Data[1];
+
+ if (IS_ONEBYTE_COMMAND(SentCommand.Data, 0x00)) // Read bootloader info
+ ResponseByte = BootloaderInfo[DataIndexToRead];
+ else if (IS_ONEBYTE_COMMAND(SentCommand.Data, 0x01)) // Read signature byte
+ ResponseByte = SignatureInfo[DataIndexToRead - 0x30];
+}
diff --git a/hardware/arduino/firmwares/atmegaxxu2/arduino-usbdfu/Arduino-usbdfu.h
b/hardware/arduino/firmwares/atmegaxxu2/arduino-usbdfu/Arduino-usbdfu.h
index 4fb236e..dc9e918 100644
--- a/hardware/arduino/firmwares/atmegaxxu2/arduino-usbdfu/Arduino-usbdfu.h
+++ b/hardware/arduino/firmwares/atmegaxxu2/arduino-usbdfu/Arduino-usbdfu.h
@@ -1,220 +1,220 @@
-/*
- LUFA Library
- Copyright (C) Dean Camera, 2010.
-
- dean [at] fourwalledcubicle [dot] com
- www.fourwalledcubicle.com
-*/
-
-/*
- Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
-
- Permission to use, copy, modify, distribute, and sell this
- software and its documentation for any purpose is hereby granted
- without fee, provided that the above copyright notice appear in
- all copies and that both that the copyright notice and this
- permission notice and warranty disclaimer appear in supporting
- documentation, and that the name of the author not be used in
- advertising or publicity pertaining to distribution of the
- software without specific, written prior permission.
-
- The author disclaim all warranties with regard to this
- software, including all implied warranties of merchantability
- and fitness. In no event shall the author be liable for any
- special, indirect or consequential damages or any damages
- whatsoever resulting from loss of use, data or profits, whether
- in an action of contract, negligence or other tortious action,
- arising out of or in connection with the use or performance of
- this software.
-*/
-
-/** \file
- *
- * Header file for Arduino-usbdfu.c.
- */
-
-#ifndef _ARDUINO_USB_DFU_BOOTLOADER_H_
-#define _ARDUINO_USB_DFU_BOOTLOADER_H_
-
- /* Includes: */
- #include <avr/io.h>
- #include <avr/wdt.h>
- #include <avr/boot.h>
- #include <avr/pgmspace.h>
- #include <avr/eeprom.h>
- #include <avr/power.h>
- #include <avr/interrupt.h>
- #include <stdbool.h>
-
- #include "Descriptors.h"
-
- #include <LUFA/Drivers/Board/LEDs.h>
- #include <LUFA/Drivers/USB/USB.h>
-
- /* Macros: */
- /** LED mask for the library LED driver, to indicate TX activity. */
- #define LEDMASK_TX LEDS_LED1
-
- /** LED mask for the library LED driver, to indicate RX activity. */
- #define LEDMASK_RX LEDS_LED2
-
- /** LED mask for the library LED driver, to indicate that an error has occurred in the USB
interface. */
- #define LEDMASK_ERROR (LEDS_LED1 | LEDS_LED2)
-
- /** LED mask for the library LED driver, to indicate that the USB interface is busy. */
- #define LEDMASK_BUSY (LEDS_LED1 | LEDS_LED2)
-
- /** Configuration define. Define this token to true to case the bootloader to reject all
memory commands
- * until a memory erase has been performed. When used in conjunction with the lockbits of
the AVR, this
- * can protect the AVR's firmware from being dumped from a secured AVR. When false, memory
operations are
- * allowed at any time.
- */
-// #define SECURE_MODE false
-
- /** Major bootloader version number. */
- #define BOOTLOADER_VERSION_MINOR 2
-
- /** Minor bootloader version number. */
- #define BOOTLOADER_VERSION_REV 0
-
- /** Complete bootloader version number expressed as a packed byte, constructed from the
- * two individual bootloader version macros.
- */
- #define BOOTLOADER_VERSION ((BOOTLOADER_VERSION_MINOR << 4) | BOOTLOADER_VERSION_REV)
-
- /** First byte of the bootloader identification bytes, used to identify a device's
bootloader. */
- #define BOOTLOADER_ID_BYTE1 0xDC
-
- /** Second byte of the bootloader identification bytes, used to identify a device's
bootloader. */
- #define BOOTLOADER_ID_BYTE2 0xFB
-
- /** Convenience macro, used to determine if the issued command is the given one-byte long
command.
- *
- * \param[in] dataarr Command byte array to check against
- * \param[in] cb1 First command byte to check
- */
- #define IS_ONEBYTE_COMMAND(dataarr, cb1) (dataarr[0] == (cb1))
-
- /** Convenience macro, used to determine if the issued command is the given two-byte long
command.
- *
- * \param[in] dataarr Command byte array to check against
- * \param[in] cb1 First command byte to check
- * \param[in] cb2 Second command byte to check
- */
- #define IS_TWOBYTE_COMMAND(dataarr, cb1, cb2) ((dataarr[0] == (cb1)) && (dataarr[1] == (cb2)))
-
- /** Length of the DFU file suffix block, appended to the end of each complete memory write
command.
- * The DFU file suffix is currently unused (but is designed to give extra file information,
such as
- * a CRC of the complete firmware for error checking) and so is discarded.
- */
- #define DFU_FILE_SUFFIX_SIZE 16
-
- /** Length of the DFU file filler block, appended to the start of each complete memory write
command.
- * Filler bytes are added to the start of each complete memory write command, and must be
discarded.
- */
- #define DFU_FILLER_BYTES_SIZE 26
-
- /** DFU class command request to detach from the host. */
- #define DFU_DETATCH 0x00
-
- /** DFU class command request to send data from the host to the bootloader. */
- #define DFU_DNLOAD 0x01
-
- /** DFU class command request to send data from the bootloader to the host. */
- #define DFU_UPLOAD 0x02
-
- /** DFU class command request to get the current DFU status and state from the bootloader. */
- #define DFU_GETSTATUS 0x03
-
- /** DFU class command request to reset the current DFU status and state variables to their
defaults. */
- #define DFU_CLRSTATUS 0x04
-
- /** DFU class command request to get the current DFU state of the bootloader. */
- #define DFU_GETSTATE 0x05
-
- /** DFU class command request to abort the current multi-request transfer and return to the
dfuIDLE state. */
- #define DFU_ABORT 0x06
-
- /** DFU command to begin programming the device's memory. */
- #define COMMAND_PROG_START 0x01
-
- /** DFU command to begin reading the device's memory. */
- #define COMMAND_DISP_DATA 0x03
-
- /** DFU command to issue a write command. */
- #define COMMAND_WRITE 0x04
-
- /** DFU command to issue a read command. */
- #define COMMAND_READ 0x05
-
- /** DFU command to issue a memory base address change command, to set the current 64KB flash
page
- * that subsequent flash operations should use. */
- #define COMMAND_CHANGE_BASE_ADDR 0x06
-
- /* Type Defines: */
- /** Type define for a non-returning function pointer to the loaded application. */
- typedef void (*AppPtr_t)(void) ATTR_NO_RETURN;
-
- /** Type define for a structure containing a complete DFU command issued by the host. */
- typedef struct
- {
- uint8_t Command; /**< Single byte command to perform, one of the COMMAND_* macro
values */
- uint8_t Data[5]; /**< Command parameters */
- uint16_t DataSize; /**< Size of the command parameters */
- } DFU_Command_t;
-
- /* Enums: */
- /** DFU bootloader states. Refer to the DFU class specification for information on each
state. */
- enum DFU_State_t
- {
- appIDLE = 0,
- appDETACH = 1,
- dfuIDLE = 2,
- dfuDNLOAD_SYNC = 3,
- dfuDNBUSY = 4,
- dfuDNLOAD_IDLE = 5,
- dfuMANIFEST_SYNC = 6,
- dfuMANIFEST = 7,
- dfuMANIFEST_WAIT_RESET = 8,
- dfuUPLOAD_IDLE = 9,
- dfuERROR = 10
- };
-
- /** DFU command status error codes. Refer to the DFU class specification for information on
each error code. */
- enum DFU_Status_t
- {
- OK = 0,
- errTARGET = 1,
- errFILE = 2,
- errWRITE = 3,
- errERASE = 4,
- errCHECK_ERASED = 5,
- errPROG = 6,
- errVERIFY = 7,
- errADDRESS = 8,
- errNOTDONE = 9,
- errFIRMWARE = 10,
- errVENDOR = 11,
- errUSBR = 12,
- errPOR = 13,
- errUNKNOWN = 14,
- errSTALLEDPKT = 15
- };
-
- /* Function Prototypes: */
- void SetupHardware(void);
- void ResetHardware(void);
-
- void EVENT_USB_Device_UnhandledControlRequest(void);
-
- #if defined(INCLUDE_FROM_BOOTLOADER_C)
- static void DiscardFillerBytes(uint8_t NumberOfBytes);
- static void ProcessBootloaderCommand(void);
- static void LoadStartEndAddresses(void);
- static void ProcessMemProgCommand(void);
- static void ProcessMemReadCommand(void);
- static void ProcessWriteCommand(void);
- static void ProcessReadCommand(void);
- #endif
-
-#endif /* _ARDUINO_USB_DFU_BOOTLOADER_H_ */
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2010.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.fourwalledcubicle.com
+*/
+
+/*
+ Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaim all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ *
+ * Header file for Arduino-usbdfu.c.
+ */
+
+#ifndef _ARDUINO_USB_DFU_BOOTLOADER_H_
+#define _ARDUINO_USB_DFU_BOOTLOADER_H_
+
+ /* Includes: */
+ #include <avr/io.h>
+ #include <avr/wdt.h>
+ #include <avr/boot.h>
+ #include <avr/pgmspace.h>
+ #include <avr/eeprom.h>
+ #include <avr/power.h>
+ #include <avr/interrupt.h>
+ #include <stdbool.h>
+
+ #include "Descriptors.h"
+
+ #include <LUFA/Drivers/Board/LEDs.h>
+ #include <LUFA/Drivers/USB/USB.h>
+
+ /* Macros: */
+ /** LED mask for the library LED driver, to indicate TX activity. */
+ #define LEDMASK_TX LEDS_LED1
+
+ /** LED mask for the library LED driver, to indicate RX activity. */
+ #define LEDMASK_RX LEDS_LED2
+
+ /** LED mask for the library LED driver, to indicate that an error has occurred in the USB
interface. */
+ #define LEDMASK_ERROR (LEDS_LED1 | LEDS_LED2)
+
+ /** LED mask for the library LED driver, to indicate that the USB interface is busy. */
+ #define LEDMASK_BUSY (LEDS_LED1 | LEDS_LED2)
+
+ /** Configuration define. Define this token to true to case the bootloader to reject all
memory commands
+ * until a memory erase has been performed. When used in conjunction with the lockbits of
the AVR, this
+ * can protect the AVR's firmware from being dumped from a secured AVR. When false, memory
operations are
+ * allowed at any time.
+ */
+// #define SECURE_MODE false
+
+ /** Major bootloader version number. */
+ #define BOOTLOADER_VERSION_MINOR 2
+
+ /** Minor bootloader version number. */
+ #define BOOTLOADER_VERSION_REV 0
+
+ /** Complete bootloader version number expressed as a packed byte, constructed from the
+ * two individual bootloader version macros.
+ */
+ #define BOOTLOADER_VERSION ((BOOTLOADER_VERSION_MINOR << 4) | BOOTLOADER_VERSION_REV)
+
+ /** First byte of the bootloader identification bytes, used to identify a device's
bootloader. */
+ #define BOOTLOADER_ID_BYTE1 0xDC
+
+ /** Second byte of the bootloader identification bytes, used to identify a device's
bootloader. */
+ #define BOOTLOADER_ID_BYTE2 0xFB
+
+ /** Convenience macro, used to determine if the issued command is the given one-byte long
command.
+ *
+ * \param[in] dataarr Command byte array to check against
+ * \param[in] cb1 First command byte to check
+ */
+ #define IS_ONEBYTE_COMMAND(dataarr, cb1) (dataarr[0] == (cb1))
+
+ /** Convenience macro, used to determine if the issued command is the given two-byte long
command.
+ *
+ * \param[in] dataarr Command byte array to check against
+ * \param[in] cb1 First command byte to check
+ * \param[in] cb2 Second command byte to check
+ */
+ #define IS_TWOBYTE_COMMAND(dataarr, cb1, cb2) ((dataarr[0] == (cb1)) && (dataarr[1] == (cb2)))
+
+ /** Length of the DFU file suffix block, appended to the end of each complete memory write
command.
+ * The DFU file suffix is currently unused (but is designed to give extra file information,
such as
+ * a CRC of the complete firmware for error checking) and so is discarded.
+ */
+ #define DFU_FILE_SUFFIX_SIZE 16
+
+ /** Length of the DFU file filler block, appended to the start of each complete memory write
command.
+ * Filler bytes are added to the start of each complete memory write command, and must be
discarded.
+ */
+ #define DFU_FILLER_BYTES_SIZE 26
+
+ /** DFU class command request to detach from the host. */
+ #define DFU_DETATCH 0x00
+
+ /** DFU class command request to send data from the host to the bootloader. */
+ #define DFU_DNLOAD 0x01
+
+ /** DFU class command request to send data from the bootloader to the host. */
+ #define DFU_UPLOAD 0x02
+
+ /** DFU class command request to get the current DFU status and state from the bootloader. */
+ #define DFU_GETSTATUS 0x03
+
+ /** DFU class command request to reset the current DFU status and state variables to their
defaults. */
+ #define DFU_CLRSTATUS 0x04
+
+ /** DFU class command request to get the current DFU state of the bootloader. */
+ #define DFU_GETSTATE 0x05
+
+ /** DFU class command request to abort the current multi-request transfer and return to the
dfuIDLE state. */
+ #define DFU_ABORT 0x06
+
+ /** DFU command to begin programming the device's memory. */
+ #define COMMAND_PROG_START 0x01
+
+ /** DFU command to begin reading the device's memory. */
+ #define COMMAND_DISP_DATA 0x03
+
+ /** DFU command to issue a write command. */
+ #define COMMAND_WRITE 0x04
+
+ /** DFU command to issue a read command. */
+ #define COMMAND_READ 0x05
+
+ /** DFU command to issue a memory base address change command, to set the current 64KB flash
page
+ * that subsequent flash operations should use. */
+ #define COMMAND_CHANGE_BASE_ADDR 0x06
+
+ /* Type Defines: */
+ /** Type define for a non-returning function pointer to the loaded application. */
+ typedef void (*AppPtr_t)(void) ATTR_NO_RETURN;
+
+ /** Type define for a structure containing a complete DFU command issued by the host. */
+ typedef struct
+ {
+ uint8_t Command; /**< Single byte command to perform, one of the COMMAND_* macro
values */
+ uint8_t Data[5]; /**< Command parameters */
+ uint16_t DataSize; /**< Size of the command parameters */
+ } DFU_Command_t;
+
+ /* Enums: */
+ /** DFU bootloader states. Refer to the DFU class specification for information on each
state. */
+ enum DFU_State_t
+ {
+ appIDLE = 0,
+ appDETACH = 1,
+ dfuIDLE = 2,
+ dfuDNLOAD_SYNC = 3,
+ dfuDNBUSY = 4,
+ dfuDNLOAD_IDLE = 5,
+ dfuMANIFEST_SYNC = 6,
+ dfuMANIFEST = 7,
+ dfuMANIFEST_WAIT_RESET = 8,
+ dfuUPLOAD_IDLE = 9,
+ dfuERROR = 10
+ };
+
+ /** DFU command status error codes. Refer to the DFU class specification for information on
each error code. */
+ enum DFU_Status_t
+ {
+ OK = 0,
+ errTARGET = 1,
+ errFILE = 2,
+ errWRITE = 3,
+ errERASE = 4,
+ errCHECK_ERASED = 5,
+ errPROG = 6,
+ errVERIFY = 7,
+ errADDRESS = 8,
+ errNOTDONE = 9,
+ errFIRMWARE = 10,
+ errVENDOR = 11,
+ errUSBR = 12,
+ errPOR = 13,
+ errUNKNOWN = 14,
+ errSTALLEDPKT = 15
+ };
+
+ /* Function Prototypes: */
+ void SetupHardware(void);
+ void ResetHardware(void);
+
+ void EVENT_USB_Device_UnhandledControlRequest(void);
+
+ #if defined(INCLUDE_FROM_BOOTLOADER_C)
+ static void DiscardFillerBytes(uint8_t NumberOfBytes);
+ static void ProcessBootloaderCommand(void);
+ static void LoadStartEndAddresses(void);
+ static void ProcessMemProgCommand(void);
+ static void ProcessMemReadCommand(void);
+ static void ProcessWriteCommand(void);
+ static void ProcessReadCommand(void);
+ #endif
+
+#endif /* _ARDUINO_USB_DFU_BOOTLOADER_H_ */
diff --git a/hardware/arduino/firmwares/atmegaxxu2/arduino-usbdfu/Board/LEDs.h
b/hardware/arduino/firmwares/atmegaxxu2/arduino-usbdfu/Board/LEDs.h
index 152e8f5..173cff7 100644
--- a/hardware/arduino/firmwares/atmegaxxu2/arduino-usbdfu/Board/LEDs.h
+++ b/hardware/arduino/firmwares/atmegaxxu2/arduino-usbdfu/Board/LEDs.h
@@ -1,110 +1,110 @@
-/*
- LUFA Library
- Copyright (C) Dean Camera, 2010.
-
- dean [at] fourwalledcubicle [dot] com
- www.fourwalledcubicle.com
-*/
-
-/*
- Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
-
- Permission to use, copy, modify, distribute, and sell this
- software and its documentation for any purpose is hereby granted
- without fee, provided that the above copyright notice appear in
- all copies and that both that the copyright notice and this
- permission notice and warranty disclaimer appear in supporting
- documentation, and that the name of the author not be used in
- advertising or publicity pertaining to distribution of the
- software without specific, written prior permission.
-
- The author disclaim all warranties with regard to this
- software, including all implied warranties of merchantability
- and fitness. In no event shall the author be liable for any
- special, indirect or consequential damages or any damages
- whatsoever resulting from loss of use, data or profits, whether
- in an action of contract, negligence or other tortious action,
- arising out of or in connection with the use or performance of
- this software.
-*/
-
-/*
- Board LEDs driver for the Benito board, from www.dorkbotpdx.org.
-*/
-
-#ifndef __LEDS_ARDUINOUNO_H__
-#define __LEDS_ARDUINOUNO_H__
-
- /* Includes: */
- #include <avr/io.h>
-
-/* Enable C linkage for C++ Compilers: */
- #if defined(__cplusplus)
- extern "C" {
- #endif
-
- /* Preprocessor Checks: */
- #if !defined(INCLUDE_FROM_LEDS_H)
- #error Do not include this file directly. Include LUFA/Drivers/Board/LEDS.h instead.
- #endif
-
- /* Public Interface - May be used in end-application: */
- /* Macros: */
- /** LED mask for the first LED on the board. */
- #define LEDS_LED1 (1 << 5)
-
- /** LED mask for the second LED on the board. */
- #define LEDS_LED2 (1 << 4)
-
- /** LED mask for all the LEDs on the board. */
- #define LEDS_ALL_LEDS (LEDS_LED1 | LEDS_LED2)
-
- /** LED mask for the none of the board LEDs */
- #define LEDS_NO_LEDS 0
-
- /* Inline Functions: */
- #if !defined(__DOXYGEN__)
- static inline void LEDs_Init(void)
- {
- DDRD |= LEDS_ALL_LEDS;
- PORTD |= LEDS_ALL_LEDS;
- }
-
- static inline void LEDs_TurnOnLEDs(const uint8_t LEDMask)
- {
- PORTD &= ~LEDMask;
- }
-
- static inline void LEDs_TurnOffLEDs(const uint8_t LEDMask)
- {
- PORTD |= LEDMask;
- }
-
- static inline void LEDs_SetAllLEDs(const uint8_t LEDMask)
- {
- PORTD = ((PORTD | LEDS_ALL_LEDS) & ~LEDMask);
- }
-
- static inline void LEDs_ChangeLEDs(const uint8_t LEDMask, const uint8_t ActiveMask)
- {
- PORTD = ((PORTD | ActiveMask) & ~LEDMask);
- }
-
- static inline void LEDs_ToggleLEDs(const uint8_t LEDMask)
- {
- PORTD ^= LEDMask;
- }
-
- static inline uint8_t LEDs_GetLEDs(void) ATTR_WARN_UNUSED_RESULT;
- static inline uint8_t LEDs_GetLEDs(void)
- {
- return (PORTD & LEDS_ALL_LEDS);
- }
- #endif
-
- /* Disable C linkage for C++ Compilers: */
- #if defined(__cplusplus)
- }
- #endif
-
-#endif
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2010.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.fourwalledcubicle.com
+*/
+
+/*
+ Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaim all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/*
+ Board LEDs driver for the Benito board, from www.dorkbotpdx.org.
+*/
+
+#ifndef __LEDS_ARDUINOUNO_H__
+#define __LEDS_ARDUINOUNO_H__
+
+ /* Includes: */
+ #include <avr/io.h>
+
+/* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(INCLUDE_FROM_LEDS_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/LEDS.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** LED mask for the first LED on the board. */
+ #define LEDS_LED1 (1 << 5)
+
+ /** LED mask for the second LED on the board. */
+ #define LEDS_LED2 (1 << 4)
+
+ /** LED mask for all the LEDs on the board. */
+ #define LEDS_ALL_LEDS (LEDS_LED1 | LEDS_LED2)
+
+ /** LED mask for the none of the board LEDs */
+ #define LEDS_NO_LEDS 0
+
+ /* Inline Functions: */
+ #if !defined(__DOXYGEN__)
+ static inline void LEDs_Init(void)
+ {
+ DDRD |= LEDS_ALL_LEDS;
+ PORTD |= LEDS_ALL_LEDS;
+ }
+
+ static inline void LEDs_TurnOnLEDs(const uint8_t LEDMask)
+ {
+ PORTD &= ~LEDMask;
+ }
+
+ static inline void LEDs_TurnOffLEDs(const uint8_t LEDMask)
+ {
+ PORTD |= LEDMask;
+ }
+
+ static inline void LEDs_SetAllLEDs(const uint8_t LEDMask)
+ {
+ PORTD = ((PORTD | LEDS_ALL_LEDS) & ~LEDMask);
+ }
+
+ static inline void LEDs_ChangeLEDs(const uint8_t LEDMask, const uint8_t ActiveMask)
+ {
+ PORTD = ((PORTD | ActiveMask) & ~LEDMask);
+ }
+
+ static inline void LEDs_ToggleLEDs(const uint8_t LEDMask)
+ {
+ PORTD ^= LEDMask;
+ }
+
+ static inline uint8_t LEDs_GetLEDs(void) ATTR_WARN_UNUSED_RESULT;
+ static inline uint8_t LEDs_GetLEDs(void)
+ {
+ return (PORTD & LEDS_ALL_LEDS);
+ }
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
diff --git a/hardware/arduino/firmwares/atmegaxxu2/arduino-usbdfu/Descriptors.c
b/hardware/arduino/firmwares/atmegaxxu2/arduino-usbdfu/Descriptors.c
index 4deaa06..df4a93a 100644
--- a/hardware/arduino/firmwares/atmegaxxu2/arduino-usbdfu/Descriptors.c
+++ b/hardware/arduino/firmwares/atmegaxxu2/arduino-usbdfu/Descriptors.c
@@ -1,189 +1,189 @@
-/*
- LUFA Library
- Copyright (C) Dean Camera, 2010.
-
- dean [at] fourwalledcubicle [dot] com
- www.fourwalledcubicle.com
-*/
-
-/*
- Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
-
- Permission to use, copy, modify, distribute, and sell this
- software and its documentation for any purpose is hereby granted
- without fee, provided that the above copyright notice appear in
- all copies and that both that the copyright notice and this
- permission notice and warranty disclaimer appear in supporting
- documentation, and that the name of the author not be used in
- advertising or publicity pertaining to distribution of the
- software without specific, written prior permission.
-
- The author disclaim all warranties with regard to this
- software, including all implied warranties of merchantability
- and fitness. In no event shall the author be liable for any
- special, indirect or consequential damages or any damages
- whatsoever resulting from loss of use, data or profits, whether
- in an action of contract, negligence or other tortious action,
- arising out of or in connection with the use or performance of
- this software.
-*/
-
-/** \file
- *
- * USB Device Descriptors, for library use when in USB device mode. Descriptors are special
- * computer-readable structures which the host requests upon device enumeration, to determine
- * the device's capabilities and functions.
- */
-
-#include "Descriptors.h"
-
-/** Device descriptor structure. This descriptor, located in FLASH memory, describes the overall
- * device characteristics, including the supported USB version, control endpoint size and the
- * number of device configurations. The descriptor is read out by the USB host when the enumeration
- * process begins.
- */
-USB_Descriptor_Device_t DeviceDescriptor =
-{
- .Header = {.Size = sizeof(USB_Descriptor_Device_t), .Type = DTYPE_Device},
-
- .USBSpecification = VERSION_BCD(01.10),
- .Class = 0x00,
- .SubClass = 0x00,
- .Protocol = 0x00,
-
- .Endpoint0Size = FIXED_CONTROL_ENDPOINT_SIZE,
-
- .VendorID = 0x03EB, // Atmel
- .ProductID = PRODUCT_ID_CODE, // MCU-dependent
- .ReleaseNumber = 0x0000,
-
- .ManufacturerStrIndex = NO_DESCRIPTOR,
- .ProductStrIndex = 0x01,
- .SerialNumStrIndex = NO_DESCRIPTOR,
-
- .NumberOfConfigurations = FIXED_NUM_CONFIGURATIONS
-};
-
-/** Configuration descriptor structure. This descriptor, located in FLASH memory, describes the usage
- * of the device in one of its supported configurations, including information about any device interfaces
- * and endpoints. The descriptor is read out by the USB host during the enumeration process when selecting
- * a configuration so that the host may correctly communicate with the USB device.
- */
-USB_Descriptor_Configuration_t ConfigurationDescriptor =
-{
- .Config =
- {
- .Header = {.Size = sizeof(USB_Descriptor_Configuration_Header_t),
.Type = DTYPE_Configuration},
-
- .TotalConfigurationSize = sizeof(USB_Descriptor_Configuration_t),
- .TotalInterfaces = 1,
-
- .ConfigurationNumber = 1,
- .ConfigurationStrIndex = NO_DESCRIPTOR,
-
- .ConfigAttributes = USB_CONFIG_ATTR_BUSPOWERED,
-
- .MaxPowerConsumption = USB_CONFIG_POWER_MA(100)
- },
-
- .DFU_Interface =
- {
- .Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type =
DTYPE_Interface},
-
- .InterfaceNumber = 0,
- .AlternateSetting = 0,
-
- .TotalEndpoints = 0,
-
- .Class = 0xFE,
- .SubClass = 0x01,
- .Protocol = 0x02,
-
- .InterfaceStrIndex = NO_DESCRIPTOR
- },
-
- .DFU_Functional =
- {
- .Header = {.Size = sizeof(USB_DFU_Functional_Descriptor_t), .Type =
DTYPE_DFUFunctional},
-
- .Attributes = (ATTR_CAN_UPLOAD | ATTR_CAN_DOWNLOAD),
-
- .DetachTimeout = 0x0000,
- .TransferSize = 0x0c00,
-
- .DFUSpecification = VERSION_BCD(01.01)
- }
-};
-
-/** Language descriptor structure. This descriptor, located in FLASH memory, is returned when the host
requests
- * the string descriptor with index 0 (the first index). It is actually an array of 16-bit integers, which
indicate
- * via the language ID table available at USB.org what languages the device supports for its string
descriptors.
- */
-USB_Descriptor_String_t LanguageString =
-{
- .Header = {.Size = USB_STRING_LEN(1), .Type = DTYPE_String},
-
- .UnicodeString = {LANGUAGE_ID_ENG}
-};
-
-/** Product descriptor string. This is a Unicode string containing the product's details in human readable
form,
- * and is read out upon request by the host when the appropriate string ID is requested, listed in the
Device
- * Descriptor.
- */
-USB_Descriptor_String_t ProductString =
-{
- #if (ARDUINO_MODEL_PID == ARDUINO_UNO_PID)
- .Header = {.Size = USB_STRING_LEN(15), .Type = DTYPE_String},
-
- .UnicodeString = L"Arduino Uno DFU"
- #elif (ARDUINO_MODEL_PID == ARDUINO_MEGA2560_PID)
- .Header = {.Size = USB_STRING_LEN(21), .Type = DTYPE_String},
-
- .UnicodeString = L"Arduino Mega 2560 DFU"
- #endif
-};
-
-/** This function is called by the library when in device mode, and must be overridden (see library "USB
Descriptors"
- * documentation) by the application code so that the address and size of a requested descriptor can be
given
- * to the USB library. When the device receives a Get Descriptor request on the control endpoint, this
function
- * is called so that the descriptor details can be passed back and the appropriate descriptor sent back to
the
- * USB host.
- */
-uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue,
- const uint8_t wIndex,
- void** const DescriptorAddress)
-{
- const uint8_t DescriptorType = (wValue >> 8);
- const uint8_t DescriptorNumber = (wValue & 0xFF);
-
- void* Address = NULL;
- uint16_t Size = NO_DESCRIPTOR;
-
- switch (DescriptorType)
- {
- case DTYPE_Device:
- Address = &DeviceDescriptor;
- Size = sizeof(USB_Descriptor_Device_t);
- break;
- case DTYPE_Configuration:
- Address = &ConfigurationDescriptor;
- Size = sizeof(USB_Descriptor_Configuration_t);
- break;
- case DTYPE_String:
- if (!(DescriptorNumber))
- {
- Address = &LanguageString;
- Size = LanguageString.Header.Size;
- }
- else
- {
- Address = &ProductString;
- Size = ProductString.Header.Size;
- }
-
- break;
- }
-
- *DescriptorAddress = Address;
- return Size;
-}
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2010.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.fourwalledcubicle.com
+*/
+
+/*
+ Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaim all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ *
+ * USB Device Descriptors, for library use when in USB device mode. Descriptors are special
+ * computer-readable structures which the host requests upon device enumeration, to determine
+ * the device's capabilities and functions.
+ */
+
+#include "Descriptors.h"
+
+/** Device descriptor structure. This descriptor, located in FLASH memory, describes the overall
+ * device characteristics, including the supported USB version, control endpoint size and the
+ * number of device configurations. The descriptor is read out by the USB host when the enumeration
+ * process begins.
+ */
+USB_Descriptor_Device_t DeviceDescriptor =
+{
+ .Header = {.Size = sizeof(USB_Descriptor_Device_t), .Type = DTYPE_Device},
+
+ .USBSpecification = VERSION_BCD(01.10),
+ .Class = 0x00,
+ .SubClass = 0x00,
+ .Protocol = 0x00,
+
+ .Endpoint0Size = FIXED_CONTROL_ENDPOINT_SIZE,
+
+ .VendorID = 0x03EB, // Atmel
+ .ProductID = PRODUCT_ID_CODE, // MCU-dependent
+ .ReleaseNumber = 0x0000,
+
+ .ManufacturerStrIndex = NO_DESCRIPTOR,
+ .ProductStrIndex = 0x01,
+ .SerialNumStrIndex = NO_DESCRIPTOR,
+
+ .NumberOfConfigurations = FIXED_NUM_CONFIGURATIONS
+};
+
+/** Configuration descriptor structure. This descriptor, located in FLASH memory, describes the usage
+ * of the device in one of its supported configurations, including information about any device interfaces
+ * and endpoints. The descriptor is read out by the USB host during the enumeration process when selecting
+ * a configuration so that the host may correctly communicate with the USB device.
+ */
+USB_Descriptor_Configuration_t ConfigurationDescriptor =
+{
+ .Config =
+ {
+ .Header = {.Size = sizeof(USB_Descriptor_Configuration_Header_t),
.Type = DTYPE_Configuration},
+
+ .TotalConfigurationSize = sizeof(USB_Descriptor_Configuration_t),
+ .TotalInterfaces = 1,
+
+ .ConfigurationNumber = 1,
+ .ConfigurationStrIndex = NO_DESCRIPTOR,
+
+ .ConfigAttributes = USB_CONFIG_ATTR_BUSPOWERED,
+
+ .MaxPowerConsumption = USB_CONFIG_POWER_MA(100)
+ },
+
+ .DFU_Interface =
+ {
+ .Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type =
DTYPE_Interface},
+
+ .InterfaceNumber = 0,
+ .AlternateSetting = 0,
+
+ .TotalEndpoints = 0,
+
+ .Class = 0xFE,
+ .SubClass = 0x01,
+ .Protocol = 0x02,
+
+ .InterfaceStrIndex = NO_DESCRIPTOR
+ },
+
+ .DFU_Functional =
+ {
+ .Header = {.Size = sizeof(USB_DFU_Functional_Descriptor_t), .Type =
DTYPE_DFUFunctional},
+
+ .Attributes = (ATTR_CAN_UPLOAD | ATTR_CAN_DOWNLOAD),
+
+ .DetachTimeout = 0x0000,
+ .TransferSize = 0x0c00,
+
+ .DFUSpecification = VERSION_BCD(01.01)
+ }
+};
+
+/** Language descriptor structure. This descriptor, located in FLASH memory, is returned when the host
requests
+ * the string descriptor with index 0 (the first index). It is actually an array of 16-bit integers, which
indicate
+ * via the language ID table available at USB.org what languages the device supports for its string
descriptors.
+ */
+USB_Descriptor_String_t LanguageString =
+{
+ .Header = {.Size = USB_STRING_LEN(1), .Type = DTYPE_String},
+
+ .UnicodeString = {LANGUAGE_ID_ENG}
+};
+
+/** Product descriptor string. This is a Unicode string containing the product's details in human readable
form,
+ * and is read out upon request by the host when the appropriate string ID is requested, listed in the
Device
+ * Descriptor.
+ */
+USB_Descriptor_String_t ProductString =
+{
+ #if (ARDUINO_MODEL_PID == ARDUINO_UNO_PID)
+ .Header = {.Size = USB_STRING_LEN(15), .Type = DTYPE_String},
+
+ .UnicodeString = L"Arduino Uno DFU"
+ #elif (ARDUINO_MODEL_PID == ARDUINO_MEGA2560_PID)
+ .Header = {.Size = USB_STRING_LEN(21), .Type = DTYPE_String},
+
+ .UnicodeString = L"Arduino Mega 2560 DFU"
+ #endif
+};
+
+/** This function is called by the library when in device mode, and must be overridden (see library "USB
Descriptors"
+ * documentation) by the application code so that the address and size of a requested descriptor can be
given
+ * to the USB library. When the device receives a Get Descriptor request on the control endpoint, this
function
+ * is called so that the descriptor details can be passed back and the appropriate descriptor sent back to
the
+ * USB host.
+ */
+uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue,
+ const uint8_t wIndex,
+ void** const DescriptorAddress)
+{
+ const uint8_t DescriptorType = (wValue >> 8);
+ const uint8_t DescriptorNumber = (wValue & 0xFF);
+
+ void* Address = NULL;
+ uint16_t Size = NO_DESCRIPTOR;
+
+ switch (DescriptorType)
+ {
+ case DTYPE_Device:
+ Address = &DeviceDescriptor;
+ Size = sizeof(USB_Descriptor_Device_t);
+ break;
+ case DTYPE_Configuration:
+ Address = &ConfigurationDescriptor;
+ Size = sizeof(USB_Descriptor_Configuration_t);
+ break;
+ case DTYPE_String:
+ if (!(DescriptorNumber))
+ {
+ Address = &LanguageString;
+ Size = LanguageString.Header.Size;
+ }
+ else
+ {
+ Address = &ProductString;
+ Size = ProductString.Header.Size;
+ }
+
+ break;
+ }
+
+ *DescriptorAddress = Address;
+ return Size;
+}
diff --git a/hardware/arduino/firmwares/atmegaxxu2/arduino-usbdfu/Descriptors.h
b/hardware/arduino/firmwares/atmegaxxu2/arduino-usbdfu/Descriptors.h
index 6c93f20..c451dd5 100644
--- a/hardware/arduino/firmwares/atmegaxxu2/arduino-usbdfu/Descriptors.h
+++ b/hardware/arduino/firmwares/atmegaxxu2/arduino-usbdfu/Descriptors.h
@@ -1,177 +1,177 @@
-/*
- LUFA Library
- Copyright (C) Dean Camera, 2010.
-
- dean [at] fourwalledcubicle [dot] com
- www.fourwalledcubicle.com
-*/
-
-/*
- Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
-
- Permission to use, copy, modify, distribute, and sell this
- software and its documentation for any purpose is hereby granted
- without fee, provided that the above copyright notice appear in
- all copies and that both that the copyright notice and this
- permission notice and warranty disclaimer appear in supporting
- documentation, and that the name of the author not be used in
- advertising or publicity pertaining to distribution of the
- software without specific, written prior permission.
-
- The author disclaim all warranties with regard to this
- software, including all implied warranties of merchantability
- and fitness. In no event shall the author be liable for any
- special, indirect or consequential damages or any damages
- whatsoever resulting from loss of use, data or profits, whether
- in an action of contract, negligence or other tortious action,
- arising out of or in connection with the use or performance of
- this software.
-*/
-
-/** \file
- *
- * Header file for Descriptors.c.
- */
-
-#ifndef _DESCRIPTORS_H_
-#define _DESCRIPTORS_H_
-
- /* Includes: */
- #include <LUFA/Drivers/USB/USB.h>
-
- /* Product-specific definitions: */
- #define ARDUINO_UNO_PID 0x0001
- #define ARDUINO_MEGA2560_PID 0x0010
-
- /* Macros: */
- /** Descriptor type value for a DFU class functional descriptor. */
- #define DTYPE_DFUFunctional 0x21
-
- /** DFU attribute mask, indicating that the DFU device will detach and re-attach when a
DFU_DETACH
- * command is issued, rather than the host issuing a USB Reset.
- */
- #define ATTR_WILL_DETATCH (1 << 3)
-
- /** DFU attribute mask, indicating that the DFU device can communicate during the
manifestation phase
- * (memory programming phase).
- */
- #define ATTR_MANEFESTATION_TOLLERANT (1 << 2)
-
- /** DFU attribute mask, indicating that the DFU device can accept DFU_UPLOAD requests to send
data from
- * the device to the host.
- */
- #define ATTR_CAN_UPLOAD (1 << 1)
-
- /** DFU attribute mask, indicating that the DFU device can accept DFU_DNLOAD requests to send
data from
- * the host to the device.
- */
- #define ATTR_CAN_DOWNLOAD (1 << 0)
-
- #if defined(__AVR_AT90USB1287__)
- #define PRODUCT_ID_CODE 0x2FFB
- #define AVR_SIGNATURE_1 0x1E
- #define AVR_SIGNATURE_2 0x97
- #define AVR_SIGNATURE_3 0x82
- #elif defined(__AVR_AT90USB1286__)
- #define PRODUCT_ID_CODE 0x2FFB
- #define AVR_SIGNATURE_1 0x1E
- #define AVR_SIGNATURE_2 0x97
- #define AVR_SIGNATURE_3 0x82
- #elif defined(__AVR_AT90USB647__)
- #define PRODUCT_ID_CODE 0x2FF9
- #define AVR_SIGNATURE_1 0x1E
- #define AVR_SIGNATURE_2 0x96
- #define AVR_SIGNATURE_3 0x82
- #elif defined(__AVR_AT90USB646__)
- #define PRODUCT_ID_CODE 0x2FF9
- #define AVR_SIGNATURE_1 0x1E
- #define AVR_SIGNATURE_2 0x96
- #define AVR_SIGNATURE_3 0x82
- #elif defined(__AVR_ATmega32U6__)
- #define PRODUCT_ID_CODE 0x2FFB
- #define AVR_SIGNATURE_1 0x1E
- #define AVR_SIGNATURE_2 0x95
- #define AVR_SIGNATURE_3 0x88
- #elif defined(__AVR_ATmega32U4__)
- #define PRODUCT_ID_CODE 0x2FF4
- #define AVR_SIGNATURE_1 0x1E
- #define AVR_SIGNATURE_2 0x95
- #define AVR_SIGNATURE_3 0x87
- #elif defined(__AVR_ATmega32U2__)
- #define PRODUCT_ID_CODE 0x2FF0
- #define AVR_SIGNATURE_1 0x1E
- #define AVR_SIGNATURE_2 0x95
- #define AVR_SIGNATURE_3 0x8A
- #elif defined(__AVR_ATmega16U4__)
- #define PRODUCT_ID_CODE 0x2FF3
- #define AVR_SIGNATURE_1 0x1E
- #define AVR_SIGNATURE_2 0x94
- #define AVR_SIGNATURE_3 0x88
- #elif defined(__AVR_ATmega16U2__)
- #define PRODUCT_ID_CODE 0x2FEF
- #define AVR_SIGNATURE_1 0x1E
- #define AVR_SIGNATURE_2 0x94
- #define AVR_SIGNATURE_3 0x89
- #elif defined(__AVR_AT90USB162__)
- #define PRODUCT_ID_CODE 0x2FFA
- #define AVR_SIGNATURE_1 0x1E
- #define AVR_SIGNATURE_2 0x94
- #define AVR_SIGNATURE_3 0x82
- #elif defined(__AVR_AT90USB82__)
- #define PRODUCT_ID_CODE 0x2FEE
- #define AVR_SIGNATURE_1 0x1E
- #define AVR_SIGNATURE_2 0x93
- #define AVR_SIGNATURE_3 0x89
- #elif defined(__AVR_ATmega8U2__)
- #define PRODUCT_ID_CODE 0x2FF7
- #define AVR_SIGNATURE_1 0x1E
- #define AVR_SIGNATURE_2 0x93
- #define AVR_SIGNATURE_3 0x82
- #else
- #error The selected AVR part is not currently supported by this bootloader.
- #endif
-
- #if !defined(PRODUCT_ID_CODE)
- #error Current AVR model is not supported by this bootloader.
- #endif
-
- /* Type Defines: */
- /** Type define for a DFU class function descriptor. This descriptor gives DFU class
information
- * to the host when read, indicating the DFU device's capabilities.
- */
- typedef struct
- {
- USB_Descriptor_Header_t Header; /**< Standard descriptor header
structure */
-
- uint8_t Attributes; /**< DFU device attributes, a mask
comprising of the
- * ATTR_* macros listed in this
source file
- */
- uint16_t DetachTimeout; /**< Timeout in milliseconds
between a USB_DETACH
- * command being issued and
the device detaching
- * from the USB bus
- */
- uint16_t TransferSize; /**< Maximum number of bytes the
DFU device can accept
- * from the host in a
transaction
- */
- uint16_t DFUSpecification; /**< BCD packed DFU
specification number this DFU
- * device complies with
- */
- } USB_DFU_Functional_Descriptor_t;
-
- /** Type define for the device configuration descriptor structure. This must be defined in the
- * application code, as the configuration descriptor contains several sub-descriptors which
- * vary between devices, and which describe the device's usage to the host.
- */
- typedef struct
- {
- USB_Descriptor_Configuration_Header_t Config;
- USB_Descriptor_Interface_t DFU_Interface;
- USB_DFU_Functional_Descriptor_t DFU_Functional;
- } USB_Descriptor_Configuration_t;
-
- /* Function Prototypes: */
- uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue,
- const uint8_t wIndex,
- void** const DescriptorAddress) ATTR_WARN_UNUSED_RESULT
ATTR_NON_NULL_PTR_ARG(3);
-
-#endif
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2010.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.fourwalledcubicle.com
+*/
+
+/*
+ Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaim all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ *
+ * Header file for Descriptors.c.
+ */
+
+#ifndef _DESCRIPTORS_H_
+#define _DESCRIPTORS_H_
+
+ /* Includes: */
+ #include <LUFA/Drivers/USB/USB.h>
+
+ /* Product-specific definitions: */
+ #define ARDUINO_UNO_PID 0x0001
+ #define ARDUINO_MEGA2560_PID 0x0010
+
+ /* Macros: */
+ /** Descriptor type value for a DFU class functional descriptor. */
+ #define DTYPE_DFUFunctional 0x21
+
+ /** DFU attribute mask, indicating that the DFU device will detach and re-attach when a
DFU_DETACH
+ * command is issued, rather than the host issuing a USB Reset.
+ */
+ #define ATTR_WILL_DETATCH (1 << 3)
+
+ /** DFU attribute mask, indicating that the DFU device can communicate during the
manifestation phase
+ * (memory programming phase).
+ */
+ #define ATTR_MANEFESTATION_TOLLERANT (1 << 2)
+
+ /** DFU attribute mask, indicating that the DFU device can accept DFU_UPLOAD requests to send
data from
+ * the device to the host.
+ */
+ #define ATTR_CAN_UPLOAD (1 << 1)
+
+ /** DFU attribute mask, indicating that the DFU device can accept DFU_DNLOAD requests to send
data from
+ * the host to the device.
+ */
+ #define ATTR_CAN_DOWNLOAD (1 << 0)
+
+ #if defined(__AVR_AT90USB1287__)
+ #define PRODUCT_ID_CODE 0x2FFB
+ #define AVR_SIGNATURE_1 0x1E
+ #define AVR_SIGNATURE_2 0x97
+ #define AVR_SIGNATURE_3 0x82
+ #elif defined(__AVR_AT90USB1286__)
+ #define PRODUCT_ID_CODE 0x2FFB
+ #define AVR_SIGNATURE_1 0x1E
+ #define AVR_SIGNATURE_2 0x97
+ #define AVR_SIGNATURE_3 0x82
+ #elif defined(__AVR_AT90USB647__)
+ #define PRODUCT_ID_CODE 0x2FF9
+ #define AVR_SIGNATURE_1 0x1E
+ #define AVR_SIGNATURE_2 0x96
+ #define AVR_SIGNATURE_3 0x82
+ #elif defined(__AVR_AT90USB646__)
+ #define PRODUCT_ID_CODE 0x2FF9
+ #define AVR_SIGNATURE_1 0x1E
+ #define AVR_SIGNATURE_2 0x96
+ #define AVR_SIGNATURE_3 0x82
+ #elif defined(__AVR_ATmega32U6__)
+ #define PRODUCT_ID_CODE 0x2FFB
+ #define AVR_SIGNATURE_1 0x1E
+ #define AVR_SIGNATURE_2 0x95
+ #define AVR_SIGNATURE_3 0x88
+ #elif defined(__AVR_ATmega32U4__)
+ #define PRODUCT_ID_CODE 0x2FF4
+ #define AVR_SIGNATURE_1 0x1E
+ #define AVR_SIGNATURE_2 0x95
+ #define AVR_SIGNATURE_3 0x87
+ #elif defined(__AVR_ATmega32U2__)
+ #define PRODUCT_ID_CODE 0x2FF0
+ #define AVR_SIGNATURE_1 0x1E
+ #define AVR_SIGNATURE_2 0x95
+ #define AVR_SIGNATURE_3 0x8A
+ #elif defined(__AVR_ATmega16U4__)
+ #define PRODUCT_ID_CODE 0x2FF3
+ #define AVR_SIGNATURE_1 0x1E
+ #define AVR_SIGNATURE_2 0x94
+ #define AVR_SIGNATURE_3 0x88
+ #elif defined(__AVR_ATmega16U2__)
+ #define PRODUCT_ID_CODE 0x2FEF
+ #define AVR_SIGNATURE_1 0x1E
+ #define AVR_SIGNATURE_2 0x94
+ #define AVR_SIGNATURE_3 0x89
+ #elif defined(__AVR_AT90USB162__)
+ #define PRODUCT_ID_CODE 0x2FFA
+ #define AVR_SIGNATURE_1 0x1E
+ #define AVR_SIGNATURE_2 0x94
+ #define AVR_SIGNATURE_3 0x82
+ #elif defined(__AVR_AT90USB82__)
+ #define PRODUCT_ID_CODE 0x2FEE
+ #define AVR_SIGNATURE_1 0x1E
+ #define AVR_SIGNATURE_2 0x93
+ #define AVR_SIGNATURE_3 0x89
+ #elif defined(__AVR_ATmega8U2__)
+ #define PRODUCT_ID_CODE 0x2FF7
+ #define AVR_SIGNATURE_1 0x1E
+ #define AVR_SIGNATURE_2 0x93
+ #define AVR_SIGNATURE_3 0x82
+ #else
+ #error The selected AVR part is not currently supported by this bootloader.
+ #endif
+
+ #if !defined(PRODUCT_ID_CODE)
+ #error Current AVR model is not supported by this bootloader.
+ #endif
+
+ /* Type Defines: */
+ /** Type define for a DFU class function descriptor. This descriptor gives DFU class
information
+ * to the host when read, indicating the DFU device's capabilities.
+ */
+ typedef struct
+ {
+ USB_Descriptor_Header_t Header; /**< Standard descriptor header
structure */
+
+ uint8_t Attributes; /**< DFU device attributes, a mask
comprising of the
+ * ATTR_* macros listed in this
source file
+ */
+ uint16_t DetachTimeout; /**< Timeout in milliseconds
between a USB_DETACH
+ * command being issued and
the device detaching
+ * from the USB bus
+ */
+ uint16_t TransferSize; /**< Maximum number of bytes the
DFU device can accept
+ * from the host in a
transaction
+ */
+ uint16_t DFUSpecification; /**< BCD packed DFU
specification number this DFU
+ * device complies with
+ */
+ } USB_DFU_Functional_Descriptor_t;
+
+ /** Type define for the device configuration descriptor structure. This must be defined in the
+ * application code, as the configuration descriptor contains several sub-descriptors which
+ * vary between devices, and which describe the device's usage to the host.
+ */
+ typedef struct
+ {
+ USB_Descriptor_Configuration_Header_t Config;
+ USB_Descriptor_Interface_t DFU_Interface;
+ USB_DFU_Functional_Descriptor_t DFU_Functional;
+ } USB_Descriptor_Configuration_t;
+
+ /* Function Prototypes: */
+ uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue,
+ const uint8_t wIndex,
+ void** const DescriptorAddress) ATTR_WARN_UNUSED_RESULT
ATTR_NON_NULL_PTR_ARG(3);
+
+#endif
diff --git a/hardware/arduino/firmwares/atmegaxxu2/arduino-usbserial/Arduino-usbserial.c
b/hardware/arduino/firmwares/atmegaxxu2/arduino-usbserial/Arduino-usbserial.c
index 4de73c8..d22f32c 100644
--- a/hardware/arduino/firmwares/atmegaxxu2/arduino-usbserial/Arduino-usbserial.c
+++ b/hardware/arduino/firmwares/atmegaxxu2/arduino-usbserial/Arduino-usbserial.c
@@ -1,242 +1,242 @@
-/*
- LUFA Library
- Copyright (C) Dean Camera, 2010.
-
- dean [at] fourwalledcubicle [dot] com
- www.fourwalledcubicle.com
-*/
-
-/*
- Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
-
- Permission to use, copy, modify, distribute, and sell this
- software and its documentation for any purpose is hereby granted
- without fee, provided that the above copyright notice appear in
- all copies and that both that the copyright notice and this
- permission notice and warranty disclaimer appear in supporting
- documentation, and that the name of the author not be used in
- advertising or publicity pertaining to distribution of the
- software without specific, written prior permission.
-
- The author disclaim all warranties with regard to this
- software, including all implied warranties of merchantability
- and fitness. In no event shall the author be liable for any
- special, indirect or consequential damages or any damages
- whatsoever resulting from loss of use, data or profits, whether
- in an action of contract, negligence or other tortious action,
- arising out of or in connection with the use or performance of
- this software.
-*/
-
-/** \file
- *
- * Main source file for the Arduino-usbserial project. This file contains the main tasks of
- * the project and is responsible for the initial application hardware configuration.
- */
-
-#include "Arduino-usbserial.h"
-
-/** Circular buffer to hold data from the host before it is sent to the device via the serial port. */
-RingBuff_t USBtoUSART_Buffer;
-
-/** Circular buffer to hold data from the serial port before it is sent to the host. */
-RingBuff_t USARTtoUSB_Buffer;
-
-/** Pulse generation counters to keep track of the number of milliseconds remaining for each pulse type */
-volatile struct
-{
- uint8_t TxLEDPulse; /**< Milliseconds remaining for data Tx LED pulse */
- uint8_t RxLEDPulse; /**< Milliseconds remaining for data Rx LED pulse */
- uint8_t PingPongLEDPulse; /**< Milliseconds remaining for enumeration Tx/Rx ping-pong LED pulse */
-} PulseMSRemaining;
-
-/** LUFA CDC Class driver interface configuration and state information. This structure is
- * passed to all CDC Class driver functions, so that multiple instances of the same class
- * within a device can be differentiated from one another.
- */
-USB_ClassInfo_CDC_Device_t VirtualSerial_CDC_Interface =
- {
- .Config =
- {
- .ControlInterfaceNumber = 0,
-
- .DataINEndpointNumber = CDC_TX_EPNUM,
- .DataINEndpointSize = CDC_TXRX_EPSIZE,
- .DataINEndpointDoubleBank = false,
-
- .DataOUTEndpointNumber = CDC_RX_EPNUM,
- .DataOUTEndpointSize = CDC_TXRX_EPSIZE,
- .DataOUTEndpointDoubleBank = false,
-
- .NotificationEndpointNumber = CDC_NOTIFICATION_EPNUM,
- .NotificationEndpointSize = CDC_NOTIFICATION_EPSIZE,
- .NotificationEndpointDoubleBank = false,
- },
- };
-
-/** Main program entry point. This routine contains the overall program flow, including initial
- * setup of all components and the main program loop.
- */
-int main(void)
-{
- SetupHardware();
-
- RingBuffer_InitBuffer(&USBtoUSART_Buffer);
- RingBuffer_InitBuffer(&USARTtoUSB_Buffer);
-
- sei();
-
- for (;;)
- {
- /* Only try to read in bytes from the CDC interface if the transmit buffer is not full */
- if (!(RingBuffer_IsFull(&USBtoUSART_Buffer)))
- {
- int16_t ReceivedByte = CDC_Device_ReceiveByte(&VirtualSerial_CDC_Interface);
-
- /* Read bytes from the USB OUT endpoint into the USART transmit buffer */
- if (!(ReceivedByte < 0))
- RingBuffer_Insert(&USBtoUSART_Buffer, ReceivedByte);
- }
-
- /* Check if the UART receive buffer flush timer has expired or the buffer is nearly full */
- RingBuff_Count_t BufferCount = RingBuffer_GetCount(&USARTtoUSB_Buffer);
- if ((TIFR0 & (1 << TOV0)) || (BufferCount > BUFFER_NEARLY_FULL))
- {
- TIFR0 |= (1 << TOV0);
-
- if (USARTtoUSB_Buffer.Count) {
- LEDs_TurnOnLEDs(LEDMASK_TX);
- PulseMSRemaining.TxLEDPulse = TX_RX_LED_PULSE_MS;
- }
-
- /* Read bytes from the USART receive buffer into the USB IN endpoint */
- while (BufferCount--)
- CDC_Device_SendByte(&VirtualSerial_CDC_Interface,
RingBuffer_Remove(&USARTtoUSB_Buffer));
-
- /* Turn off TX LED(s) once the TX pulse period has elapsed */
- if (PulseMSRemaining.TxLEDPulse && !(--PulseMSRemaining.TxLEDPulse))
- LEDs_TurnOffLEDs(LEDMASK_TX);
-
- /* Turn off RX LED(s) once the RX pulse period has elapsed */
- if (PulseMSRemaining.RxLEDPulse && !(--PulseMSRemaining.RxLEDPulse))
- LEDs_TurnOffLEDs(LEDMASK_RX);
- }
-
- /* Load the next byte from the USART transmit buffer into the USART */
- if (!(RingBuffer_IsEmpty(&USBtoUSART_Buffer))) {
- Serial_TxByte(RingBuffer_Remove(&USBtoUSART_Buffer));
-
- LEDs_TurnOnLEDs(LEDMASK_RX);
- PulseMSRemaining.RxLEDPulse = TX_RX_LED_PULSE_MS;
- }
-
- CDC_Device_USBTask(&VirtualSerial_CDC_Interface);
- USB_USBTask();
- }
-}
-
-/** Configures the board hardware and chip peripherals for the demo's functionality. */
-void SetupHardware(void)
-{
- /* Disable watchdog if enabled by bootloader/fuses */
- MCUSR &= ~(1 << WDRF);
- wdt_disable();
-
- /* Hardware Initialization */
- Serial_Init(9600, false);
- LEDs_Init();
- USB_Init();
-
- /* Start the flush timer so that overflows occur rapidly to push received bytes to the USB interface
*/
- TCCR0B = (1 << CS02);
-
- /* Pull target /RESET line high */
- AVR_RESET_LINE_PORT |= AVR_RESET_LINE_MASK;
- AVR_RESET_LINE_DDR |= AVR_RESET_LINE_MASK;
-}
-
-/** Event handler for the library USB Configuration Changed event. */
-void EVENT_USB_Device_ConfigurationChanged(void)
-{
- CDC_Device_ConfigureEndpoints(&VirtualSerial_CDC_Interface);
-}
-
-/** Event handler for the library USB Unhandled Control Request event. */
-void EVENT_USB_Device_UnhandledControlRequest(void)
-{
- CDC_Device_ProcessControlRequest(&VirtualSerial_CDC_Interface);
-}
-
-/** Event handler for the CDC Class driver Line Encoding Changed event.
- *
- * \param[in] CDCInterfaceInfo Pointer to the CDC class interface configuration structure being referenced
- */
-void EVENT_CDC_Device_LineEncodingChanged(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo)
-{
- uint8_t ConfigMask = 0;
-
- switch (CDCInterfaceInfo->State.LineEncoding.ParityType)
- {
- case CDC_PARITY_Odd:
- ConfigMask = ((1 << UPM11) | (1 << UPM10));
- break;
- case CDC_PARITY_Even:
- ConfigMask = (1 << UPM11);
- break;
- }
-
- if (CDCInterfaceInfo->State.LineEncoding.CharFormat == CDC_LINEENCODING_TwoStopBits)
- ConfigMask |= (1 << USBS1);
-
- switch (CDCInterfaceInfo->State.LineEncoding.DataBits)
- {
- case 6:
- ConfigMask |= (1 << UCSZ10);
- break;
- case 7:
- ConfigMask |= (1 << UCSZ11);
- break;
- case 8:
- ConfigMask |= ((1 << UCSZ11) | (1 << UCSZ10));
- break;
- }
-
- /* Must turn off USART before reconfiguring it, otherwise incorrect operation may occur */
- UCSR1B = 0;
- UCSR1A = 0;
- UCSR1C = 0;
-
- /* Special case 57600 baud for compatibility with the ATmega328 bootloader. */
- UBRR1 = (CDCInterfaceInfo->State.LineEncoding.BaudRateBPS == 57600)
- ? SERIAL_UBBRVAL(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS)
- : SERIAL_2X_UBBRVAL(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS);
-
- UCSR1C = ConfigMask;
- UCSR1A = (CDCInterfaceInfo->State.LineEncoding.BaudRateBPS == 57600) ? 0 : (1 << U2X1);
- UCSR1B = ((1 << RXCIE1) | (1 << TXEN1) | (1 << RXEN1));
-}
-
-/** ISR to manage the reception of data from the serial port, placing received bytes into a circular buffer
- * for later transmission to the host.
- */
-ISR(USART1_RX_vect, ISR_BLOCK)
-{
- uint8_t ReceivedByte = UDR1;
-
- if (USB_DeviceState == DEVICE_STATE_Configured)
- RingBuffer_Insert(&USARTtoUSB_Buffer, ReceivedByte);
-}
-
-/** Event handler for the CDC Class driver Host-to-Device Line Encoding Changed event.
- *
- * \param[in] CDCInterfaceInfo Pointer to the CDC class interface configuration structure being referenced
- */
-void EVENT_CDC_Device_ControLineStateChanged(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo)
-{
- bool CurrentDTRState = (CDCInterfaceInfo->State.ControlLineStates.HostToDevice &
CDC_CONTROL_LINE_OUT_DTR);
-
- if (CurrentDTRState)
- AVR_RESET_LINE_PORT &= ~AVR_RESET_LINE_MASK;
- else
- AVR_RESET_LINE_PORT |= AVR_RESET_LINE_MASK;
-}
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2010.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.fourwalledcubicle.com
+*/
+
+/*
+ Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaim all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ *
+ * Main source file for the Arduino-usbserial project. This file contains the main tasks of
+ * the project and is responsible for the initial application hardware configuration.
+ */
+
+#include "Arduino-usbserial.h"
+
+/** Circular buffer to hold data from the host before it is sent to the device via the serial port. */
+RingBuff_t USBtoUSART_Buffer;
+
+/** Circular buffer to hold data from the serial port before it is sent to the host. */
+RingBuff_t USARTtoUSB_Buffer;
+
+/** Pulse generation counters to keep track of the number of milliseconds remaining for each pulse type */
+volatile struct
+{
+ uint8_t TxLEDPulse; /**< Milliseconds remaining for data Tx LED pulse */
+ uint8_t RxLEDPulse; /**< Milliseconds remaining for data Rx LED pulse */
+ uint8_t PingPongLEDPulse; /**< Milliseconds remaining for enumeration Tx/Rx ping-pong LED pulse */
+} PulseMSRemaining;
+
+/** LUFA CDC Class driver interface configuration and state information. This structure is
+ * passed to all CDC Class driver functions, so that multiple instances of the same class
+ * within a device can be differentiated from one another.
+ */
+USB_ClassInfo_CDC_Device_t VirtualSerial_CDC_Interface =
+ {
+ .Config =
+ {
+ .ControlInterfaceNumber = 0,
+
+ .DataINEndpointNumber = CDC_TX_EPNUM,
+ .DataINEndpointSize = CDC_TXRX_EPSIZE,
+ .DataINEndpointDoubleBank = false,
+
+ .DataOUTEndpointNumber = CDC_RX_EPNUM,
+ .DataOUTEndpointSize = CDC_TXRX_EPSIZE,
+ .DataOUTEndpointDoubleBank = false,
+
+ .NotificationEndpointNumber = CDC_NOTIFICATION_EPNUM,
+ .NotificationEndpointSize = CDC_NOTIFICATION_EPSIZE,
+ .NotificationEndpointDoubleBank = false,
+ },
+ };
+
+/** Main program entry point. This routine contains the overall program flow, including initial
+ * setup of all components and the main program loop.
+ */
+int main(void)
+{
+ SetupHardware();
+
+ RingBuffer_InitBuffer(&USBtoUSART_Buffer);
+ RingBuffer_InitBuffer(&USARTtoUSB_Buffer);
+
+ sei();
+
+ for (;;)
+ {
+ /* Only try to read in bytes from the CDC interface if the transmit buffer is not full */
+ if (!(RingBuffer_IsFull(&USBtoUSART_Buffer)))
+ {
+ int16_t ReceivedByte = CDC_Device_ReceiveByte(&VirtualSerial_CDC_Interface);
+
+ /* Read bytes from the USB OUT endpoint into the USART transmit buffer */
+ if (!(ReceivedByte < 0))
+ RingBuffer_Insert(&USBtoUSART_Buffer, ReceivedByte);
+ }
+
+ /* Check if the UART receive buffer flush timer has expired or the buffer is nearly full */
+ RingBuff_Count_t BufferCount = RingBuffer_GetCount(&USARTtoUSB_Buffer);
+ if ((TIFR0 & (1 << TOV0)) || (BufferCount > BUFFER_NEARLY_FULL))
+ {
+ TIFR0 |= (1 << TOV0);
+
+ if (USARTtoUSB_Buffer.Count) {
+ LEDs_TurnOnLEDs(LEDMASK_TX);
+ PulseMSRemaining.TxLEDPulse = TX_RX_LED_PULSE_MS;
+ }
+
+ /* Read bytes from the USART receive buffer into the USB IN endpoint */
+ while (BufferCount--)
+ CDC_Device_SendByte(&VirtualSerial_CDC_Interface,
RingBuffer_Remove(&USARTtoUSB_Buffer));
+
+ /* Turn off TX LED(s) once the TX pulse period has elapsed */
+ if (PulseMSRemaining.TxLEDPulse && !(--PulseMSRemaining.TxLEDPulse))
+ LEDs_TurnOffLEDs(LEDMASK_TX);
+
+ /* Turn off RX LED(s) once the RX pulse period has elapsed */
+ if (PulseMSRemaining.RxLEDPulse && !(--PulseMSRemaining.RxLEDPulse))
+ LEDs_TurnOffLEDs(LEDMASK_RX);
+ }
+
+ /* Load the next byte from the USART transmit buffer into the USART */
+ if (!(RingBuffer_IsEmpty(&USBtoUSART_Buffer))) {
+ Serial_TxByte(RingBuffer_Remove(&USBtoUSART_Buffer));
+
+ LEDs_TurnOnLEDs(LEDMASK_RX);
+ PulseMSRemaining.RxLEDPulse = TX_RX_LED_PULSE_MS;
+ }
+
+ CDC_Device_USBTask(&VirtualSerial_CDC_Interface);
+ USB_USBTask();
+ }
+}
+
+/** Configures the board hardware and chip peripherals for the demo's functionality. */
+void SetupHardware(void)
+{
+ /* Disable watchdog if enabled by bootloader/fuses */
+ MCUSR &= ~(1 << WDRF);
+ wdt_disable();
+
+ /* Hardware Initialization */
+ Serial_Init(9600, false);
+ LEDs_Init();
+ USB_Init();
+
+ /* Start the flush timer so that overflows occur rapidly to push received bytes to the USB interface
*/
+ TCCR0B = (1 << CS02);
+
+ /* Pull target /RESET line high */
+ AVR_RESET_LINE_PORT |= AVR_RESET_LINE_MASK;
+ AVR_RESET_LINE_DDR |= AVR_RESET_LINE_MASK;
+}
+
+/** Event handler for the library USB Configuration Changed event. */
+void EVENT_USB_Device_ConfigurationChanged(void)
+{
+ CDC_Device_ConfigureEndpoints(&VirtualSerial_CDC_Interface);
+}
+
+/** Event handler for the library USB Unhandled Control Request event. */
+void EVENT_USB_Device_UnhandledControlRequest(void)
+{
+ CDC_Device_ProcessControlRequest(&VirtualSerial_CDC_Interface);
+}
+
+/** Event handler for the CDC Class driver Line Encoding Changed event.
+ *
+ * \param[in] CDCInterfaceInfo Pointer to the CDC class interface configuration structure being referenced
+ */
+void EVENT_CDC_Device_LineEncodingChanged(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo)
+{
+ uint8_t ConfigMask = 0;
+
+ switch (CDCInterfaceInfo->State.LineEncoding.ParityType)
+ {
+ case CDC_PARITY_Odd:
+ ConfigMask = ((1 << UPM11) | (1 << UPM10));
+ break;
+ case CDC_PARITY_Even:
+ ConfigMask = (1 << UPM11);
+ break;
+ }
+
+ if (CDCInterfaceInfo->State.LineEncoding.CharFormat == CDC_LINEENCODING_TwoStopBits)
+ ConfigMask |= (1 << USBS1);
+
+ switch (CDCInterfaceInfo->State.LineEncoding.DataBits)
+ {
+ case 6:
+ ConfigMask |= (1 << UCSZ10);
+ break;
+ case 7:
+ ConfigMask |= (1 << UCSZ11);
+ break;
+ case 8:
+ ConfigMask |= ((1 << UCSZ11) | (1 << UCSZ10));
+ break;
+ }
+
+ /* Must turn off USART before reconfiguring it, otherwise incorrect operation may occur */
+ UCSR1B = 0;
+ UCSR1A = 0;
+ UCSR1C = 0;
+
+ /* Special case 57600 baud for compatibility with the ATmega328 bootloader. */
+ UBRR1 = (CDCInterfaceInfo->State.LineEncoding.BaudRateBPS == 57600)
+ ? SERIAL_UBBRVAL(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS)
+ : SERIAL_2X_UBBRVAL(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS);
+
+ UCSR1C = ConfigMask;
+ UCSR1A = (CDCInterfaceInfo->State.LineEncoding.BaudRateBPS == 57600) ? 0 : (1 << U2X1);
+ UCSR1B = ((1 << RXCIE1) | (1 << TXEN1) | (1 << RXEN1));
+}
+
+/** ISR to manage the reception of data from the serial port, placing received bytes into a circular buffer
+ * for later transmission to the host.
+ */
+ISR(USART1_RX_vect, ISR_BLOCK)
+{
+ uint8_t ReceivedByte = UDR1;
+
+ if (USB_DeviceState == DEVICE_STATE_Configured)
+ RingBuffer_Insert(&USARTtoUSB_Buffer, ReceivedByte);
+}
+
+/** Event handler for the CDC Class driver Host-to-Device Line Encoding Changed event.
+ *
+ * \param[in] CDCInterfaceInfo Pointer to the CDC class interface configuration structure being referenced
+ */
+void EVENT_CDC_Device_ControLineStateChanged(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo)
+{
+ bool CurrentDTRState = (CDCInterfaceInfo->State.ControlLineStates.HostToDevice &
CDC_CONTROL_LINE_OUT_DTR);
+
+ if (CurrentDTRState)
+ AVR_RESET_LINE_PORT &= ~AVR_RESET_LINE_MASK;
+ else
+ AVR_RESET_LINE_PORT |= AVR_RESET_LINE_MASK;
+}
diff --git a/hardware/arduino/firmwares/atmegaxxu2/arduino-usbserial/Arduino-usbserial.h
b/hardware/arduino/firmwares/atmegaxxu2/arduino-usbserial/Arduino-usbserial.h
index 99fde39..7aec405 100644
--- a/hardware/arduino/firmwares/atmegaxxu2/arduino-usbserial/Arduino-usbserial.h
+++ b/hardware/arduino/firmwares/atmegaxxu2/arduino-usbserial/Arduino-usbserial.h
@@ -1,79 +1,79 @@
-/*
- LUFA Library
- Copyright (C) Dean Camera, 2010.
-
- dean [at] fourwalledcubicle [dot] com
- www.fourwalledcubicle.com
-*/
-
-/*
- Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
-
- Permission to use, copy, modify, distribute, and sell this
- software and its documentation for any purpose is hereby granted
- without fee, provided that the above copyright notice appear in
- all copies and that both that the copyright notice and this
- permission notice and warranty disclaimer appear in supporting
- documentation, and that the name of the author not be used in
- advertising or publicity pertaining to distribution of the
- software without specific, written prior permission.
-
- The author disclaim all warranties with regard to this
- software, including all implied warranties of merchantability
- and fitness. In no event shall the author be liable for any
- special, indirect or consequential damages or any damages
- whatsoever resulting from loss of use, data or profits, whether
- in an action of contract, negligence or other tortious action,
- arising out of or in connection with the use or performance of
- this software.
-*/
-
-/** \file
- *
- * Header file for Arduino-usbserial.c.
- */
-
-#ifndef _ARDUINO_USBSERIAL_H_
-#define _ARDUINO_USBSERIAL_H_
-
- /* Includes: */
- #include <avr/io.h>
- #include <avr/wdt.h>
- #include <avr/interrupt.h>
- #include <avr/power.h>
-
- #include "Descriptors.h"
-
- #include "Lib/LightweightRingBuff.h"
-
- #include <LUFA/Version.h>
- #include <LUFA/Drivers/Board/LEDs.h>
- #include <LUFA/Drivers/Peripheral/Serial.h>
- #include <LUFA/Drivers/USB/USB.h>
- #include <LUFA/Drivers/USB/Class/CDC.h>
-
- /* Macros: */
- /** LED mask for the library LED driver, to indicate TX activity. */
- #define LEDMASK_TX LEDS_LED1
-
- /** LED mask for the library LED driver, to indicate RX activity. */
- #define LEDMASK_RX LEDS_LED2
-
- /** LED mask for the library LED driver, to indicate that an error has occurred in the USB
interface. */
- #define LEDMASK_ERROR (LEDS_LED1 | LEDS_LED2)
-
- /** LED mask for the library LED driver, to indicate that the USB interface is busy. */
- #define LEDMASK_BUSY (LEDS_LED1 | LEDS_LED2)
-
- /* Function Prototypes: */
- void SetupHardware(void);
-
- void EVENT_USB_Device_Connect(void);
- void EVENT_USB_Device_Disconnect(void);
- void EVENT_USB_Device_ConfigurationChanged(void);
- void EVENT_USB_Device_UnhandledControlRequest(void);
-
- void EVENT_CDC_Device_LineEncodingChanged(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo);
- void EVENT_CDC_Device_ControLineStateChanged(USB_ClassInfo_CDC_Device_t* const
CDCInterfaceInfo);
-
-#endif /* _ARDUINO_USBSERIAL_H_ */
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2010.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.fourwalledcubicle.com
+*/
+
+/*
+ Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaim all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ *
+ * Header file for Arduino-usbserial.c.
+ */
+
+#ifndef _ARDUINO_USBSERIAL_H_
+#define _ARDUINO_USBSERIAL_H_
+
+ /* Includes: */
+ #include <avr/io.h>
+ #include <avr/wdt.h>
+ #include <avr/interrupt.h>
+ #include <avr/power.h>
+
+ #include "Descriptors.h"
+
+ #include "Lib/LightweightRingBuff.h"
+
+ #include <LUFA/Version.h>
+ #include <LUFA/Drivers/Board/LEDs.h>
+ #include <LUFA/Drivers/Peripheral/Serial.h>
+ #include <LUFA/Drivers/USB/USB.h>
+ #include <LUFA/Drivers/USB/Class/CDC.h>
+
+ /* Macros: */
+ /** LED mask for the library LED driver, to indicate TX activity. */
+ #define LEDMASK_TX LEDS_LED1
+
+ /** LED mask for the library LED driver, to indicate RX activity. */
+ #define LEDMASK_RX LEDS_LED2
+
+ /** LED mask for the library LED driver, to indicate that an error has occurred in the USB
interface. */
+ #define LEDMASK_ERROR (LEDS_LED1 | LEDS_LED2)
+
+ /** LED mask for the library LED driver, to indicate that the USB interface is busy. */
+ #define LEDMASK_BUSY (LEDS_LED1 | LEDS_LED2)
+
+ /* Function Prototypes: */
+ void SetupHardware(void);
+
+ void EVENT_USB_Device_Connect(void);
+ void EVENT_USB_Device_Disconnect(void);
+ void EVENT_USB_Device_ConfigurationChanged(void);
+ void EVENT_USB_Device_UnhandledControlRequest(void);
+
+ void EVENT_CDC_Device_LineEncodingChanged(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo);
+ void EVENT_CDC_Device_ControLineStateChanged(USB_ClassInfo_CDC_Device_t* const
CDCInterfaceInfo);
+
+#endif /* _ARDUINO_USBSERIAL_H_ */
diff --git a/hardware/arduino/firmwares/atmegaxxu2/arduino-usbserial/Board/LEDs.h
b/hardware/arduino/firmwares/atmegaxxu2/arduino-usbserial/Board/LEDs.h
index 152e8f5..173cff7 100644
--- a/hardware/arduino/firmwares/atmegaxxu2/arduino-usbserial/Board/LEDs.h
+++ b/hardware/arduino/firmwares/atmegaxxu2/arduino-usbserial/Board/LEDs.h
@@ -1,110 +1,110 @@
-/*
- LUFA Library
- Copyright (C) Dean Camera, 2010.
-
- dean [at] fourwalledcubicle [dot] com
- www.fourwalledcubicle.com
-*/
-
-/*
- Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
-
- Permission to use, copy, modify, distribute, and sell this
- software and its documentation for any purpose is hereby granted
- without fee, provided that the above copyright notice appear in
- all copies and that both that the copyright notice and this
- permission notice and warranty disclaimer appear in supporting
- documentation, and that the name of the author not be used in
- advertising or publicity pertaining to distribution of the
- software without specific, written prior permission.
-
- The author disclaim all warranties with regard to this
- software, including all implied warranties of merchantability
- and fitness. In no event shall the author be liable for any
- special, indirect or consequential damages or any damages
- whatsoever resulting from loss of use, data or profits, whether
- in an action of contract, negligence or other tortious action,
- arising out of or in connection with the use or performance of
- this software.
-*/
-
-/*
- Board LEDs driver for the Benito board, from www.dorkbotpdx.org.
-*/
-
-#ifndef __LEDS_ARDUINOUNO_H__
-#define __LEDS_ARDUINOUNO_H__
-
- /* Includes: */
- #include <avr/io.h>
-
-/* Enable C linkage for C++ Compilers: */
- #if defined(__cplusplus)
- extern "C" {
- #endif
-
- /* Preprocessor Checks: */
- #if !defined(INCLUDE_FROM_LEDS_H)
- #error Do not include this file directly. Include LUFA/Drivers/Board/LEDS.h instead.
- #endif
-
- /* Public Interface - May be used in end-application: */
- /* Macros: */
- /** LED mask for the first LED on the board. */
- #define LEDS_LED1 (1 << 5)
-
- /** LED mask for the second LED on the board. */
- #define LEDS_LED2 (1 << 4)
-
- /** LED mask for all the LEDs on the board. */
- #define LEDS_ALL_LEDS (LEDS_LED1 | LEDS_LED2)
-
- /** LED mask for the none of the board LEDs */
- #define LEDS_NO_LEDS 0
-
- /* Inline Functions: */
- #if !defined(__DOXYGEN__)
- static inline void LEDs_Init(void)
- {
- DDRD |= LEDS_ALL_LEDS;
- PORTD |= LEDS_ALL_LEDS;
- }
-
- static inline void LEDs_TurnOnLEDs(const uint8_t LEDMask)
- {
- PORTD &= ~LEDMask;
- }
-
- static inline void LEDs_TurnOffLEDs(const uint8_t LEDMask)
- {
- PORTD |= LEDMask;
- }
-
- static inline void LEDs_SetAllLEDs(const uint8_t LEDMask)
- {
- PORTD = ((PORTD | LEDS_ALL_LEDS) & ~LEDMask);
- }
-
- static inline void LEDs_ChangeLEDs(const uint8_t LEDMask, const uint8_t ActiveMask)
- {
- PORTD = ((PORTD | ActiveMask) & ~LEDMask);
- }
-
- static inline void LEDs_ToggleLEDs(const uint8_t LEDMask)
- {
- PORTD ^= LEDMask;
- }
-
- static inline uint8_t LEDs_GetLEDs(void) ATTR_WARN_UNUSED_RESULT;
- static inline uint8_t LEDs_GetLEDs(void)
- {
- return (PORTD & LEDS_ALL_LEDS);
- }
- #endif
-
- /* Disable C linkage for C++ Compilers: */
- #if defined(__cplusplus)
- }
- #endif
-
-#endif
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2010.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.fourwalledcubicle.com
+*/
+
+/*
+ Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaim all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/*
+ Board LEDs driver for the Benito board, from www.dorkbotpdx.org.
+*/
+
+#ifndef __LEDS_ARDUINOUNO_H__
+#define __LEDS_ARDUINOUNO_H__
+
+ /* Includes: */
+ #include <avr/io.h>
+
+/* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(INCLUDE_FROM_LEDS_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/LEDS.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** LED mask for the first LED on the board. */
+ #define LEDS_LED1 (1 << 5)
+
+ /** LED mask for the second LED on the board. */
+ #define LEDS_LED2 (1 << 4)
+
+ /** LED mask for all the LEDs on the board. */
+ #define LEDS_ALL_LEDS (LEDS_LED1 | LEDS_LED2)
+
+ /** LED mask for the none of the board LEDs */
+ #define LEDS_NO_LEDS 0
+
+ /* Inline Functions: */
+ #if !defined(__DOXYGEN__)
+ static inline void LEDs_Init(void)
+ {
+ DDRD |= LEDS_ALL_LEDS;
+ PORTD |= LEDS_ALL_LEDS;
+ }
+
+ static inline void LEDs_TurnOnLEDs(const uint8_t LEDMask)
+ {
+ PORTD &= ~LEDMask;
+ }
+
+ static inline void LEDs_TurnOffLEDs(const uint8_t LEDMask)
+ {
+ PORTD |= LEDMask;
+ }
+
+ static inline void LEDs_SetAllLEDs(const uint8_t LEDMask)
+ {
+ PORTD = ((PORTD | LEDS_ALL_LEDS) & ~LEDMask);
+ }
+
+ static inline void LEDs_ChangeLEDs(const uint8_t LEDMask, const uint8_t ActiveMask)
+ {
+ PORTD = ((PORTD | ActiveMask) & ~LEDMask);
+ }
+
+ static inline void LEDs_ToggleLEDs(const uint8_t LEDMask)
+ {
+ PORTD ^= LEDMask;
+ }
+
+ static inline uint8_t LEDs_GetLEDs(void) ATTR_WARN_UNUSED_RESULT;
+ static inline uint8_t LEDs_GetLEDs(void)
+ {
+ return (PORTD & LEDS_ALL_LEDS);
+ }
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
diff --git a/hardware/arduino/firmwares/atmegaxxu2/arduino-usbserial/Descriptors.c
b/hardware/arduino/firmwares/atmegaxxu2/arduino-usbserial/Descriptors.c
index 705dddf..f382eae 100644
--- a/hardware/arduino/firmwares/atmegaxxu2/arduino-usbserial/Descriptors.c
+++ b/hardware/arduino/firmwares/atmegaxxu2/arduino-usbserial/Descriptors.c
@@ -1,277 +1,277 @@
-/*
- LUFA Library
- Copyright (C) Dean Camera, 2010.
-
- dean [at] fourwalledcubicle [dot] com
- www.fourwalledcubicle.com
-*/
-
-/*
- Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
-
- Permission to use, copy, modify, distribute, and sell this
- software and its documentation for any purpose is hereby granted
- without fee, provided that the above copyright notice appear in
- all copies and that both that the copyright notice and this
- permission notice and warranty disclaimer appear in supporting
- documentation, and that the name of the author not be used in
- advertising or publicity pertaining to distribution of the
- software without specific, written prior permission.
-
- The author disclaim all warranties with regard to this
- software, including all implied warranties of merchantability
- and fitness. In no event shall the author be liable for any
- special, indirect or consequential damages or any damages
- whatsoever resulting from loss of use, data or profits, whether
- in an action of contract, negligence or other tortious action,
- arising out of or in connection with the use or performance of
- this software.
-*/
-
-/** \file
- *
- * USB Device Descriptors, for library use when in USB device mode. Descriptors are special
- * computer-readable structures which the host requests upon device enumeration, to determine
- * the device's capabilities and functions.
- */
-
-#include "Descriptors.h"
-
-/* On some devices, there is a factory set internal serial number which can be automatically sent to the
host as
- * the device's serial number when the Device Descriptor's .SerialNumStrIndex entry is set to
USE_INTERNAL_SERIAL.
- * This allows the host to track a device across insertions on different ports, allowing them to retain
allocated
- * resources like COM port numbers and drivers. On demos using this feature, give a warning on unsupported
devices
- * so that the user can supply their own serial number descriptor instead or remove the USE_INTERNAL_SERIAL
value
- * from the Device Descriptor (forcing the host to generate a serial number for each device from the VID,
PID and
- * port location).
- */
-#if (USE_INTERNAL_SERIAL == NO_DESCRIPTOR)
- #warning USE_INTERNAL_SERIAL is not available on this AVR - please manually construct a device serial
descriptor.
-#endif
-
-/** Device descriptor structure. This descriptor, located in FLASH memory, describes the overall
- * device characteristics, including the supported USB version, control endpoint size and the
- * number of device configurations. The descriptor is read out by the USB host when the enumeration
- * process begins.
- */
-USB_Descriptor_Device_t PROGMEM DeviceDescriptor =
-{
- .Header = {.Size = sizeof(USB_Descriptor_Device_t), .Type = DTYPE_Device},
-
- .USBSpecification = VERSION_BCD(01.10),
- .Class = 0x02,
- .SubClass = 0x00,
- .Protocol = 0x00,
-
- .Endpoint0Size = FIXED_CONTROL_ENDPOINT_SIZE,
-
- .VendorID = 0x03EB, // Atmel
-
- .ProductID = 0x204B, // LUFA USB to Serial Demo Application
- .ReleaseNumber = 0x0001,
-
- .ManufacturerStrIndex = 0x01,
- .ProductStrIndex = 0x02,
- .SerialNumStrIndex = USE_INTERNAL_SERIAL,
-
- .NumberOfConfigurations = FIXED_NUM_CONFIGURATIONS
-};
-
-/** Configuration descriptor structure. This descriptor, located in FLASH memory, describes the usage
- * of the device in one of its supported configurations, including information about any device interfaces
- * and endpoints. The descriptor is read out by the USB host during the enumeration process when selecting
- * a configuration so that the host may correctly communicate with the USB device.
- */
-USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor =
-{
- .Config =
- {
- .Header = {.Size = sizeof(USB_Descriptor_Configuration_Header_t),
.Type = DTYPE_Configuration},
-
- .TotalConfigurationSize = sizeof(USB_Descriptor_Configuration_t),
- .TotalInterfaces = 2,
-
- .ConfigurationNumber = 1,
- .ConfigurationStrIndex = NO_DESCRIPTOR,
-
- .ConfigAttributes = (USB_CONFIG_ATTR_BUSPOWERED | USB_CONFIG_ATTR_SELFPOWERED),
-
- .MaxPowerConsumption = USB_CONFIG_POWER_MA(100)
- },
-
- .CDC_CCI_Interface =
- {
- .Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type =
DTYPE_Interface},
-
- .InterfaceNumber = 0,
- .AlternateSetting = 0,
-
- .TotalEndpoints = 1,
-
- .Class = 0x02,
- .SubClass = 0x02,
- .Protocol = 0x01,
-
- .InterfaceStrIndex = NO_DESCRIPTOR
- },
-
- .CDC_Functional_IntHeader =
- {
- .Header = {.Size = sizeof(CDC_FUNCTIONAL_DESCRIPTOR(2)), .Type =
0x24},
- .SubType = 0x00,
-
- .Data = {0x01, 0x10}
- },
-
- .CDC_Functional_AbstractControlManagement =
- {
- .Header = {.Size = sizeof(CDC_FUNCTIONAL_DESCRIPTOR(1)), .Type =
0x24},
- .SubType = 0x02,
-
- .Data = {0x06}
- },
-
- .CDC_Functional_Union =
- {
- .Header = {.Size = sizeof(CDC_FUNCTIONAL_DESCRIPTOR(2)), .Type =
0x24},
- .SubType = 0x06,
-
- .Data = {0x00, 0x01}
- },
-
- .CDC_NotificationEndpoint =
- {
- .Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type =
DTYPE_Endpoint},
-
- .EndpointAddress = (ENDPOINT_DESCRIPTOR_DIR_IN | CDC_NOTIFICATION_EPNUM),
- .Attributes = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC |
ENDPOINT_USAGE_DATA),
- .EndpointSize = CDC_NOTIFICATION_EPSIZE,
- .PollingIntervalMS = 0xFF
- },
-
- .CDC_DCI_Interface =
- {
- .Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type =
DTYPE_Interface},
-
- .InterfaceNumber = 1,
- .AlternateSetting = 0,
-
- .TotalEndpoints = 2,
-
- .Class = 0x0A,
- .SubClass = 0x00,
- .Protocol = 0x00,
-
- .InterfaceStrIndex = NO_DESCRIPTOR
- },
-
- .CDC_DataOutEndpoint =
- {
- .Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type =
DTYPE_Endpoint},
-
- .EndpointAddress = (ENDPOINT_DESCRIPTOR_DIR_OUT | CDC_RX_EPNUM),
- .Attributes = (EP_TYPE_BULK | ENDPOINT_ATTR_NO_SYNC |
ENDPOINT_USAGE_DATA),
- .EndpointSize = CDC_TXRX_EPSIZE,
- .PollingIntervalMS = 0x01
- },
-
- .CDC_DataInEndpoint =
- {
- .Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type =
DTYPE_Endpoint},
-
- .EndpointAddress = (ENDPOINT_DESCRIPTOR_DIR_IN | CDC_TX_EPNUM),
- .Attributes = (EP_TYPE_BULK | ENDPOINT_ATTR_NO_SYNC |
ENDPOINT_USAGE_DATA),
- .EndpointSize = CDC_TXRX_EPSIZE,
- .PollingIntervalMS = 0x01
- }
-};
-
-/** Language descriptor structure. This descriptor, located in FLASH memory, is returned when the host
requests
- * the string descriptor with index 0 (the first index). It is actually an array of 16-bit integers, which
indicate
- * via the language ID table available at USB.org what languages the device supports for its string
descriptors.
- */
-USB_Descriptor_String_t PROGMEM LanguageString =
-{
- .Header = {.Size = USB_STRING_LEN(1), .Type = DTYPE_String},
-
- .UnicodeString = {LANGUAGE_ID_ENG}
-};
-
-/** Manufacturer descriptor string. This is a Unicode string containing the manufacturer's details in human
readable
- * form, and is read out upon request by the host when the appropriate string ID is requested, listed in
the Device
- * Descriptor.
- */
-USB_Descriptor_String_t PROGMEM ManufacturerString =
-{
- .Header = {.Size = USB_STRING_LEN(24), .Type = DTYPE_String},
-
- .UnicodeString = L"Arduino (www.arduino.cc)"
-};
-
-/** Product descriptor string. This is a Unicode string containing the product's details in human readable
form,
- * and is read out upon request by the host when the appropriate string ID is requested, listed in the
Device
- * Descriptor.
- */
-USB_Descriptor_String_t PROGMEM ProductString =
-{
- #if (ARDUINO_MODEL_PID == ARDUINO_UNO_PID)
- .Header = {.Size = USB_STRING_LEN(11), .Type = DTYPE_String},
-
- .UnicodeString = L"Arduino Uno"
- #elif (ARDUINO_MODEL_PID == ARDUINO_MEGA2560_PID)
- .Header = {.Size = USB_STRING_LEN(17), .Type = DTYPE_String},
-
- .UnicodeString = L"Arduino Mega 2560"
- #endif
-
-};
-
-/** This function is called by the library when in device mode, and must be overridden (see library "USB
Descriptors"
- * documentation) by the application code so that the address and size of a requested descriptor can be
given
- * to the USB library. When the device receives a Get Descriptor request on the control endpoint, this
function
- * is called so that the descriptor details can be passed back and the appropriate descriptor sent back to
the
- * USB host.
- */
-uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue,
- const uint8_t wIndex,
- void** const DescriptorAddress)
-{
- const uint8_t DescriptorType = (wValue >> 8);
- const uint8_t DescriptorNumber = (wValue & 0xFF);
-
- void* Address = NULL;
- uint16_t Size = NO_DESCRIPTOR;
-
- switch (DescriptorType)
- {
- case DTYPE_Device:
- Address = (void*)&DeviceDescriptor;
- Size = sizeof(USB_Descriptor_Device_t);
- break;
- case DTYPE_Configuration:
- Address = (void*)&ConfigurationDescriptor;
- Size = sizeof(USB_Descriptor_Configuration_t);
- break;
- case DTYPE_String:
- switch (DescriptorNumber)
- {
- case 0x00:
- Address = (void*)&LanguageString;
- Size = pgm_read_byte(&LanguageString.Header.Size);
- break;
- case 0x01:
- Address = (void*)&ManufacturerString;
- Size = pgm_read_byte(&ManufacturerString.Header.Size);
- break;
- case 0x02:
- Address = (void*)&ProductString;
- Size = pgm_read_byte(&ProductString.Header.Size);
- break;
- }
-
- break;
- }
-
- *DescriptorAddress = Address;
- return Size;
-}
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2010.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.fourwalledcubicle.com
+*/
+
+/*
+ Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaim all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ *
+ * USB Device Descriptors, for library use when in USB device mode. Descriptors are special
+ * computer-readable structures which the host requests upon device enumeration, to determine
+ * the device's capabilities and functions.
+ */
+
+#include "Descriptors.h"
+
+/* On some devices, there is a factory set internal serial number which can be automatically sent to the
host as
+ * the device's serial number when the Device Descriptor's .SerialNumStrIndex entry is set to
USE_INTERNAL_SERIAL.
+ * This allows the host to track a device across insertions on different ports, allowing them to retain
allocated
+ * resources like COM port numbers and drivers. On demos using this feature, give a warning on unsupported
devices
+ * so that the user can supply their own serial number descriptor instead or remove the USE_INTERNAL_SERIAL
value
+ * from the Device Descriptor (forcing the host to generate a serial number for each device from the VID,
PID and
+ * port location).
+ */
+#if (USE_INTERNAL_SERIAL == NO_DESCRIPTOR)
+ #warning USE_INTERNAL_SERIAL is not available on this AVR - please manually construct a device serial
descriptor.
+#endif
+
+/** Device descriptor structure. This descriptor, located in FLASH memory, describes the overall
+ * device characteristics, including the supported USB version, control endpoint size and the
+ * number of device configurations. The descriptor is read out by the USB host when the enumeration
+ * process begins.
+ */
+USB_Descriptor_Device_t PROGMEM DeviceDescriptor =
+{
+ .Header = {.Size = sizeof(USB_Descriptor_Device_t), .Type = DTYPE_Device},
+
+ .USBSpecification = VERSION_BCD(01.10),
+ .Class = 0x02,
+ .SubClass = 0x00,
+ .Protocol = 0x00,
+
+ .Endpoint0Size = FIXED_CONTROL_ENDPOINT_SIZE,
+
+ .VendorID = 0x03EB, // Atmel
+
+ .ProductID = 0x204B, // LUFA USB to Serial Demo Application
+ .ReleaseNumber = 0x0001,
+
+ .ManufacturerStrIndex = 0x01,
+ .ProductStrIndex = 0x02,
+ .SerialNumStrIndex = USE_INTERNAL_SERIAL,
+
+ .NumberOfConfigurations = FIXED_NUM_CONFIGURATIONS
+};
+
+/** Configuration descriptor structure. This descriptor, located in FLASH memory, describes the usage
+ * of the device in one of its supported configurations, including information about any device interfaces
+ * and endpoints. The descriptor is read out by the USB host during the enumeration process when selecting
+ * a configuration so that the host may correctly communicate with the USB device.
+ */
+USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor =
+{
+ .Config =
+ {
+ .Header = {.Size = sizeof(USB_Descriptor_Configuration_Header_t),
.Type = DTYPE_Configuration},
+
+ .TotalConfigurationSize = sizeof(USB_Descriptor_Configuration_t),
+ .TotalInterfaces = 2,
+
+ .ConfigurationNumber = 1,
+ .ConfigurationStrIndex = NO_DESCRIPTOR,
+
+ .ConfigAttributes = (USB_CONFIG_ATTR_BUSPOWERED | USB_CONFIG_ATTR_SELFPOWERED),
+
+ .MaxPowerConsumption = USB_CONFIG_POWER_MA(100)
+ },
+
+ .CDC_CCI_Interface =
+ {
+ .Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type =
DTYPE_Interface},
+
+ .InterfaceNumber = 0,
+ .AlternateSetting = 0,
+
+ .TotalEndpoints = 1,
+
+ .Class = 0x02,
+ .SubClass = 0x02,
+ .Protocol = 0x01,
+
+ .InterfaceStrIndex = NO_DESCRIPTOR
+ },
+
+ .CDC_Functional_IntHeader =
+ {
+ .Header = {.Size = sizeof(CDC_FUNCTIONAL_DESCRIPTOR(2)), .Type =
0x24},
+ .SubType = 0x00,
+
+ .Data = {0x01, 0x10}
+ },
+
+ .CDC_Functional_AbstractControlManagement =
+ {
+ .Header = {.Size = sizeof(CDC_FUNCTIONAL_DESCRIPTOR(1)), .Type =
0x24},
+ .SubType = 0x02,
+
+ .Data = {0x06}
+ },
+
+ .CDC_Functional_Union =
+ {
+ .Header = {.Size = sizeof(CDC_FUNCTIONAL_DESCRIPTOR(2)), .Type =
0x24},
+ .SubType = 0x06,
+
+ .Data = {0x00, 0x01}
+ },
+
+ .CDC_NotificationEndpoint =
+ {
+ .Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type =
DTYPE_Endpoint},
+
+ .EndpointAddress = (ENDPOINT_DESCRIPTOR_DIR_IN | CDC_NOTIFICATION_EPNUM),
+ .Attributes = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC |
ENDPOINT_USAGE_DATA),
+ .EndpointSize = CDC_NOTIFICATION_EPSIZE,
+ .PollingIntervalMS = 0xFF
+ },
+
+ .CDC_DCI_Interface =
+ {
+ .Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type =
DTYPE_Interface},
+
+ .InterfaceNumber = 1,
+ .AlternateSetting = 0,
+
+ .TotalEndpoints = 2,
+
+ .Class = 0x0A,
+ .SubClass = 0x00,
+ .Protocol = 0x00,
+
+ .InterfaceStrIndex = NO_DESCRIPTOR
+ },
+
+ .CDC_DataOutEndpoint =
+ {
+ .Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type =
DTYPE_Endpoint},
+
+ .EndpointAddress = (ENDPOINT_DESCRIPTOR_DIR_OUT | CDC_RX_EPNUM),
+ .Attributes = (EP_TYPE_BULK | ENDPOINT_ATTR_NO_SYNC |
ENDPOINT_USAGE_DATA),
+ .EndpointSize = CDC_TXRX_EPSIZE,
+ .PollingIntervalMS = 0x01
+ },
+
+ .CDC_DataInEndpoint =
+ {
+ .Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type =
DTYPE_Endpoint},
+
+ .EndpointAddress = (ENDPOINT_DESCRIPTOR_DIR_IN | CDC_TX_EPNUM),
+ .Attributes = (EP_TYPE_BULK | ENDPOINT_ATTR_NO_SYNC |
ENDPOINT_USAGE_DATA),
+ .EndpointSize = CDC_TXRX_EPSIZE,
+ .PollingIntervalMS = 0x01
+ }
+};
+
+/** Language descriptor structure. This descriptor, located in FLASH memory, is returned when the host
requests
+ * the string descriptor with index 0 (the first index). It is actually an array of 16-bit integers, which
indicate
+ * via the language ID table available at USB.org what languages the device supports for its string
descriptors.
+ */
+USB_Descriptor_String_t PROGMEM LanguageString =
+{
+ .Header = {.Size = USB_STRING_LEN(1), .Type = DTYPE_String},
+
+ .UnicodeString = {LANGUAGE_ID_ENG}
+};
+
+/** Manufacturer descriptor string. This is a Unicode string containing the manufacturer's details in human
readable
+ * form, and is read out upon request by the host when the appropriate string ID is requested, listed in
the Device
+ * Descriptor.
+ */
+USB_Descriptor_String_t PROGMEM ManufacturerString =
+{
+ .Header = {.Size = USB_STRING_LEN(24), .Type = DTYPE_String},
+
+ .UnicodeString = L"Arduino (www.arduino.cc)"
+};
+
+/** Product descriptor string. This is a Unicode string containing the product's details in human readable
form,
+ * and is read out upon request by the host when the appropriate string ID is requested, listed in the
Device
+ * Descriptor.
+ */
+USB_Descriptor_String_t PROGMEM ProductString =
+{
+ #if (ARDUINO_MODEL_PID == ARDUINO_UNO_PID)
+ .Header = {.Size = USB_STRING_LEN(11), .Type = DTYPE_String},
+
+ .UnicodeString = L"Arduino Uno"
+ #elif (ARDUINO_MODEL_PID == ARDUINO_MEGA2560_PID)
+ .Header = {.Size = USB_STRING_LEN(17), .Type = DTYPE_String},
+
+ .UnicodeString = L"Arduino Mega 2560"
+ #endif
+
+};
+
+/** This function is called by the library when in device mode, and must be overridden (see library "USB
Descriptors"
+ * documentation) by the application code so that the address and size of a requested descriptor can be
given
+ * to the USB library. When the device receives a Get Descriptor request on the control endpoint, this
function
+ * is called so that the descriptor details can be passed back and the appropriate descriptor sent back to
the
+ * USB host.
+ */
+uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue,
+ const uint8_t wIndex,
+ void** const DescriptorAddress)
+{
+ const uint8_t DescriptorType = (wValue >> 8);
+ const uint8_t DescriptorNumber = (wValue & 0xFF);
+
+ void* Address = NULL;
+ uint16_t Size = NO_DESCRIPTOR;
+
+ switch (DescriptorType)
+ {
+ case DTYPE_Device:
+ Address = (void*)&DeviceDescriptor;
+ Size = sizeof(USB_Descriptor_Device_t);
+ break;
+ case DTYPE_Configuration:
+ Address = (void*)&ConfigurationDescriptor;
+ Size = sizeof(USB_Descriptor_Configuration_t);
+ break;
+ case DTYPE_String:
+ switch (DescriptorNumber)
+ {
+ case 0x00:
+ Address = (void*)&LanguageString;
+ Size = pgm_read_byte(&LanguageString.Header.Size);
+ break;
+ case 0x01:
+ Address = (void*)&ManufacturerString;
+ Size = pgm_read_byte(&ManufacturerString.Header.Size);
+ break;
+ case 0x02:
+ Address = (void*)&ProductString;
+ Size = pgm_read_byte(&ProductString.Header.Size);
+ break;
+ }
+
+ break;
+ }
+
+ *DescriptorAddress = Address;
+ return Size;
+}
diff --git a/hardware/arduino/firmwares/atmegaxxu2/arduino-usbserial/Descriptors.h
b/hardware/arduino/firmwares/atmegaxxu2/arduino-usbserial/Descriptors.h
index 3ac4e52..b19b938 100644
--- a/hardware/arduino/firmwares/atmegaxxu2/arduino-usbserial/Descriptors.h
+++ b/hardware/arduino/firmwares/atmegaxxu2/arduino-usbserial/Descriptors.h
@@ -1,88 +1,88 @@
-/*
- LUFA Library
- Copyright (C) Dean Camera, 2010.
-
- dean [at] fourwalledcubicle [dot] com
- www.fourwalledcubicle.com
-*/
-
-/*
- Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
-
- Permission to use, copy, modify, distribute, and sell this
- software and its documentation for any purpose is hereby granted
- without fee, provided that the above copyright notice appear in
- all copies and that both that the copyright notice and this
- permission notice and warranty disclaimer appear in supporting
- documentation, and that the name of the author not be used in
- advertising or publicity pertaining to distribution of the
- software without specific, written prior permission.
-
- The author disclaim all warranties with regard to this
- software, including all implied warranties of merchantability
- and fitness. In no event shall the author be liable for any
- special, indirect or consequential damages or any damages
- whatsoever resulting from loss of use, data or profits, whether
- in an action of contract, negligence or other tortious action,
- arising out of or in connection with the use or performance of
- this software.
-*/
-
-/** \file
- *
- * Header file for Descriptors.c.
- */
-
-#ifndef _DESCRIPTORS_H_
-#define _DESCRIPTORS_H_
-
- /* Includes: */
- #include <avr/pgmspace.h>
-
- #include <LUFA/Drivers/USB/USB.h>
- #include <LUFA/Drivers/USB/Class/CDC.h>
-
- /* Product-specific definitions: */
- #define ARDUINO_UNO_PID 0x0001
- #define ARDUINO_MEGA2560_PID 0x0010
-
- /* Macros: */
- /** Endpoint number of the CDC device-to-host notification IN endpoint. */
- #define CDC_NOTIFICATION_EPNUM 2
-
- /** Endpoint number of the CDC device-to-host data IN endpoint. */
- #define CDC_TX_EPNUM 3
-
- /** Endpoint number of the CDC host-to-device data OUT endpoint. */
- #define CDC_RX_EPNUM 4
-
- /** Size in bytes of the CDC device-to-host notification IN endpoint. */
- #define CDC_NOTIFICATION_EPSIZE 8
-
- /** Size in bytes of the CDC data IN and OUT endpoints. */
- #define CDC_TXRX_EPSIZE 64
-
- /* Type Defines: */
- /** Type define for the device configuration descriptor structure. This must be defined in the
- * application code, as the configuration descriptor contains several sub-descriptors which
- * vary between devices, and which describe the device's usage to the host.
- */
- typedef struct
- {
- USB_Descriptor_Configuration_Header_t Config;
- USB_Descriptor_Interface_t CDC_CCI_Interface;
- CDC_FUNCTIONAL_DESCRIPTOR(2) CDC_Functional_IntHeader;
- CDC_FUNCTIONAL_DESCRIPTOR(1) CDC_Functional_AbstractControlManagement;
- CDC_FUNCTIONAL_DESCRIPTOR(2) CDC_Functional_Union;
- USB_Descriptor_Endpoint_t CDC_NotificationEndpoint;
- USB_Descriptor_Interface_t CDC_DCI_Interface;
- USB_Descriptor_Endpoint_t CDC_DataOutEndpoint;
- USB_Descriptor_Endpoint_t CDC_DataInEndpoint;
- } USB_Descriptor_Configuration_t;
-
- /* Function Prototypes: */
- uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue,
- const uint8_t wIndex,
- void** const DescriptorAddress) ATTR_WARN_UNUSED_RESULT
ATTR_NON_NULL_PTR_ARG(3);
-
-#endif
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2010.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.fourwalledcubicle.com
+*/
+
+/*
+ Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaim all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ *
+ * Header file for Descriptors.c.
+ */
+
+#ifndef _DESCRIPTORS_H_
+#define _DESCRIPTORS_H_
+
+ /* Includes: */
+ #include <avr/pgmspace.h>
+
+ #include <LUFA/Drivers/USB/USB.h>
+ #include <LUFA/Drivers/USB/Class/CDC.h>
+
+ /* Product-specific definitions: */
+ #define ARDUINO_UNO_PID 0x0001
+ #define ARDUINO_MEGA2560_PID 0x0010
+
+ /* Macros: */
+ /** Endpoint number of the CDC device-to-host notification IN endpoint. */
+ #define CDC_NOTIFICATION_EPNUM 2
+
+ /** Endpoint number of the CDC device-to-host data IN endpoint. */
+ #define CDC_TX_EPNUM 3
+
+ /** Endpoint number of the CDC host-to-device data OUT endpoint. */
+ #define CDC_RX_EPNUM 4
+
+ /** Size in bytes of the CDC device-to-host notification IN endpoint. */
+ #define CDC_NOTIFICATION_EPSIZE 8
+
+ /** Size in bytes of the CDC data IN and OUT endpoints. */
+ #define CDC_TXRX_EPSIZE 64
+
+ /* Type Defines: */
+ /** Type define for the device configuration descriptor structure. This must be defined in the
+ * application code, as the configuration descriptor contains several sub-descriptors which
+ * vary between devices, and which describe the device's usage to the host.
+ */
+ typedef struct
+ {
+ USB_Descriptor_Configuration_Header_t Config;
+ USB_Descriptor_Interface_t CDC_CCI_Interface;
+ CDC_FUNCTIONAL_DESCRIPTOR(2) CDC_Functional_IntHeader;
+ CDC_FUNCTIONAL_DESCRIPTOR(1) CDC_Functional_AbstractControlManagement;
+ CDC_FUNCTIONAL_DESCRIPTOR(2) CDC_Functional_Union;
+ USB_Descriptor_Endpoint_t CDC_NotificationEndpoint;
+ USB_Descriptor_Interface_t CDC_DCI_Interface;
+ USB_Descriptor_Endpoint_t CDC_DataOutEndpoint;
+ USB_Descriptor_Endpoint_t CDC_DataInEndpoint;
+ } USB_Descriptor_Configuration_t;
+
+ /* Function Prototypes: */
+ uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue,
+ const uint8_t wIndex,
+ void** const DescriptorAddress) ATTR_WARN_UNUSED_RESULT
ATTR_NON_NULL_PTR_ARG(3);
+
+#endif
diff --git a/hardware/arduino/firmwares/atmegaxxu2/arduino-usbserial/Lib/LightweightRingBuff.h
b/hardware/arduino/firmwares/atmegaxxu2/arduino-usbserial/Lib/LightweightRingBuff.h
index fb48c1f..404e8c0 100644
--- a/hardware/arduino/firmwares/atmegaxxu2/arduino-usbserial/Lib/LightweightRingBuff.h
+++ b/hardware/arduino/firmwares/atmegaxxu2/arduino-usbserial/Lib/LightweightRingBuff.h
@@ -1,197 +1,197 @@
-/*
- LUFA Library
- Copyright (C) Dean Camera, 2010.
-
- dean [at] fourwalledcubicle [dot] com
- www.fourwalledcubicle.com
-*/
-
-/*
- Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
-
- Permission to use, copy, modify, distribute, and sell this
- software and its documentation for any purpose is hereby granted
- without fee, provided that the above copyright notice appear in
- all copies and that both that the copyright notice and this
- permission notice and warranty disclaimer appear in supporting
- documentation, and that the name of the author not be used in
- advertising or publicity pertaining to distribution of the
- software without specific, written prior permission.
-
- The author disclaim all warranties with regard to this
- software, including all implied warranties of merchantability
- and fitness. In no event shall the author be liable for any
- special, indirect or consequential damages or any damages
- whatsoever resulting from loss of use, data or profits, whether
- in an action of contract, negligence or other tortious action,
- arising out of or in connection with the use or performance of
- this software.
-*/
-
-/** \file
- *
- * Ultra lightweight ring buffer, for fast insertion/deletion.
- */
-
-#ifndef _ULW_RING_BUFF_H_
-#define _ULW_RING_BUFF_H_
-
- /* Includes: */
- #include <util/atomic.h>
-
- #include <stdint.h>
- #include <stdbool.h>
-
- /* Defines: */
- /** Size of each ring buffer, in data elements - must be between 1 and 255. */
- #define BUFFER_SIZE 128
-
- /** Maximum number of data elements to buffer before forcing a flush.
- * Must be less than BUFFER_SIZE
- */
- #define BUFFER_NEARLY_FULL 96
-
- /** Type of data to store into the buffer. */
- #define RingBuff_Data_t uint8_t
-
- /** Datatype which may be used to store the count of data stored in a buffer, retrieved
- * via a call to \ref RingBuffer_GetCount().
- */
- #if (BUFFER_SIZE <= 0xFF)
- #define RingBuff_Count_t uint8_t
- #else
- #define RingBuff_Count_t uint16_t
- #endif
-
- /* Type Defines: */
- /** Type define for a new ring buffer object. Buffers should be initialized via a call to
- * \ref RingBuffer_InitBuffer() before use.
- */
- typedef struct
- {
- RingBuff_Data_t Buffer[BUFFER_SIZE]; /**< Internal ring buffer data, referenced by
the buffer pointers. */
- RingBuff_Data_t* In; /**< Current storage location in the circular buffer */
- RingBuff_Data_t* Out; /**< Current retrieval location in the circular buffer */
- RingBuff_Count_t Count;
- } RingBuff_t;
-
- /* Inline Functions: */
- /** Initializes a ring buffer ready for use. Buffers must be initialized via this function
- * before any operations are called upon them. Already initialized buffers may be reset
- * by re-initializing them using this function.
- *
- * \param[out] Buffer Pointer to a ring buffer structure to initialize
- */
- static inline void RingBuffer_InitBuffer(RingBuff_t* const Buffer)
- {
- ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
- {
- Buffer->In = Buffer->Buffer;
- Buffer->Out = Buffer->Buffer;
- }
- }
-
- /** Retrieves the minimum number of bytes stored in a particular buffer. This value is
computed
- * by entering an atomic lock on the buffer while the IN and OUT locations are fetched, so
that
- * the buffer cannot be modified while the computation takes place. This value should be
cached
- * when reading out the contents of the buffer, so that as small a time as possible is spent
- * in an atomic lock.
- *
- * \note The value returned by this function is guaranteed to only be the minimum number of
bytes
- * stored in the given buffer; this value may change as other threads write new data
and so
- * the returned number should be used only to determine how many successive reads may
safely
- * be performed on the buffer.
- *
- * \param[in] Buffer Pointer to a ring buffer structure whose count is to be computed
- */
- static inline RingBuff_Count_t RingBuffer_GetCount(RingBuff_t* const Buffer)
- {
- RingBuff_Count_t Count;
-
- ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
- {
- Count = Buffer->Count;
- }
-
- return Count;
- }
-
- /** Atomically determines if the specified ring buffer contains any free space. This should
- * be tested before storing data to the buffer, to ensure that no data is lost due to a
- * buffer overrun.
- *
- * \param[in,out] Buffer Pointer to a ring buffer structure to insert into
- *
- * \return Boolean true if the buffer contains no free space, false otherwise
- */
- static inline bool RingBuffer_IsFull(RingBuff_t* const Buffer)
- {
- return (RingBuffer_GetCount(Buffer) == BUFFER_SIZE);
- }
-
- /** Atomically determines if the specified ring buffer contains any data. This should
- * be tested before removing data from the buffer, to ensure that the buffer does not
- * underflow.
- *
- * If the data is to be removed in a loop, store the total number of bytes stored in the
- * buffer (via a call to the \ref RingBuffer_GetCount() function) in a temporary variable
- * to reduce the time spent in atomicity locks.
- *
- * \param[in,out] Buffer Pointer to a ring buffer structure to insert into
- *
- * \return Boolean true if the buffer contains no free space, false otherwise
- */
- static inline bool RingBuffer_IsEmpty(RingBuff_t* const Buffer)
- {
- return (RingBuffer_GetCount(Buffer) == 0);
- }
-
- /** Inserts an element into the ring buffer.
- *
- * \note Only one execution thread (main program thread or an ISR) may insert into a single
buffer
- * otherwise data corruption may occur. Insertion and removal may occur from different
execution
- * threads.
- *
- * \param[in,out] Buffer Pointer to a ring buffer structure to insert into
- * \param[in] Data Data element to insert into the buffer
- */
- static inline void RingBuffer_Insert(RingBuff_t* const Buffer,
- const RingBuff_Data_t Data)
- {
- *Buffer->In = Data;
-
- if (++Buffer->In == &Buffer->Buffer[BUFFER_SIZE])
- Buffer->In = Buffer->Buffer;
-
- ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
- {
- Buffer->Count++;
- }
- }
-
- /** Removes an element from the ring buffer.
- *
- * \note Only one execution thread (main program thread or an ISR) may remove from a single
buffer
- * otherwise data corruption may occur. Insertion and removal may occur from different
execution
- * threads.
- *
- * \param[in,out] Buffer Pointer to a ring buffer structure to retrieve from
- *
- * \return Next data element stored in the buffer
- */
- static inline RingBuff_Data_t RingBuffer_Remove(RingBuff_t* const Buffer)
- {
- RingBuff_Data_t Data = *Buffer->Out;
-
- if (++Buffer->Out == &Buffer->Buffer[BUFFER_SIZE])
- Buffer->Out = Buffer->Buffer;
-
- ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
- {
- Buffer->Count--;
- }
-
- return Data;
- }
-
-#endif
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2010.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.fourwalledcubicle.com
+*/
+
+/*
+ Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaim all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ *
+ * Ultra lightweight ring buffer, for fast insertion/deletion.
+ */
+
+#ifndef _ULW_RING_BUFF_H_
+#define _ULW_RING_BUFF_H_
+
+ /* Includes: */
+ #include <util/atomic.h>
+
+ #include <stdint.h>
+ #include <stdbool.h>
+
+ /* Defines: */
+ /** Size of each ring buffer, in data elements - must be between 1 and 255. */
+ #define BUFFER_SIZE 128
+
+ /** Maximum number of data elements to buffer before forcing a flush.
+ * Must be less than BUFFER_SIZE
+ */
+ #define BUFFER_NEARLY_FULL 96
+
+ /** Type of data to store into the buffer. */
+ #define RingBuff_Data_t uint8_t
+
+ /** Datatype which may be used to store the count of data stored in a buffer, retrieved
+ * via a call to \ref RingBuffer_GetCount().
+ */
+ #if (BUFFER_SIZE <= 0xFF)
+ #define RingBuff_Count_t uint8_t
+ #else
+ #define RingBuff_Count_t uint16_t
+ #endif
+
+ /* Type Defines: */
+ /** Type define for a new ring buffer object. Buffers should be initialized via a call to
+ * \ref RingBuffer_InitBuffer() before use.
+ */
+ typedef struct
+ {
+ RingBuff_Data_t Buffer[BUFFER_SIZE]; /**< Internal ring buffer data, referenced by
the buffer pointers. */
+ RingBuff_Data_t* In; /**< Current storage location in the circular buffer */
+ RingBuff_Data_t* Out; /**< Current retrieval location in the circular buffer */
+ RingBuff_Count_t Count;
+ } RingBuff_t;
+
+ /* Inline Functions: */
+ /** Initializes a ring buffer ready for use. Buffers must be initialized via this function
+ * before any operations are called upon them. Already initialized buffers may be reset
+ * by re-initializing them using this function.
+ *
+ * \param[out] Buffer Pointer to a ring buffer structure to initialize
+ */
+ static inline void RingBuffer_InitBuffer(RingBuff_t* const Buffer)
+ {
+ ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
+ {
+ Buffer->In = Buffer->Buffer;
+ Buffer->Out = Buffer->Buffer;
+ }
+ }
+
+ /** Retrieves the minimum number of bytes stored in a particular buffer. This value is
computed
+ * by entering an atomic lock on the buffer while the IN and OUT locations are fetched, so
that
+ * the buffer cannot be modified while the computation takes place. This value should be
cached
+ * when reading out the contents of the buffer, so that as small a time as possible is spent
+ * in an atomic lock.
+ *
+ * \note The value returned by this function is guaranteed to only be the minimum number of
bytes
+ * stored in the given buffer; this value may change as other threads write new data
and so
+ * the returned number should be used only to determine how many successive reads may
safely
+ * be performed on the buffer.
+ *
+ * \param[in] Buffer Pointer to a ring buffer structure whose count is to be computed
+ */
+ static inline RingBuff_Count_t RingBuffer_GetCount(RingBuff_t* const Buffer)
+ {
+ RingBuff_Count_t Count;
+
+ ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
+ {
+ Count = Buffer->Count;
+ }
+
+ return Count;
+ }
+
+ /** Atomically determines if the specified ring buffer contains any free space. This should
+ * be tested before storing data to the buffer, to ensure that no data is lost due to a
+ * buffer overrun.
+ *
+ * \param[in,out] Buffer Pointer to a ring buffer structure to insert into
+ *
+ * \return Boolean true if the buffer contains no free space, false otherwise
+ */
+ static inline bool RingBuffer_IsFull(RingBuff_t* const Buffer)
+ {
+ return (RingBuffer_GetCount(Buffer) == BUFFER_SIZE);
+ }
+
+ /** Atomically determines if the specified ring buffer contains any data. This should
+ * be tested before removing data from the buffer, to ensure that the buffer does not
+ * underflow.
+ *
+ * If the data is to be removed in a loop, store the total number of bytes stored in the
+ * buffer (via a call to the \ref RingBuffer_GetCount() function) in a temporary variable
+ * to reduce the time spent in atomicity locks.
+ *
+ * \param[in,out] Buffer Pointer to a ring buffer structure to insert into
+ *
+ * \return Boolean true if the buffer contains no free space, false otherwise
+ */
+ static inline bool RingBuffer_IsEmpty(RingBuff_t* const Buffer)
+ {
+ return (RingBuffer_GetCount(Buffer) == 0);
+ }
+
+ /** Inserts an element into the ring buffer.
+ *
+ * \note Only one execution thread (main program thread or an ISR) may insert into a single
buffer
+ * otherwise data corruption may occur. Insertion and removal may occur from different
execution
+ * threads.
+ *
+ * \param[in,out] Buffer Pointer to a ring buffer structure to insert into
+ * \param[in] Data Data element to insert into the buffer
+ */
+ static inline void RingBuffer_Insert(RingBuff_t* const Buffer,
+ const RingBuff_Data_t Data)
+ {
+ *Buffer->In = Data;
+
+ if (++Buffer->In == &Buffer->Buffer[BUFFER_SIZE])
+ Buffer->In = Buffer->Buffer;
+
+ ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
+ {
+ Buffer->Count++;
+ }
+ }
+
+ /** Removes an element from the ring buffer.
+ *
+ * \note Only one execution thread (main program thread or an ISR) may remove from a single
buffer
+ * otherwise data corruption may occur. Insertion and removal may occur from different
execution
+ * threads.
+ *
+ * \param[in,out] Buffer Pointer to a ring buffer structure to retrieve from
+ *
+ * \return Next data element stored in the buffer
+ */
+ static inline RingBuff_Data_t RingBuffer_Remove(RingBuff_t* const Buffer)
+ {
+ RingBuff_Data_t Data = *Buffer->Out;
+
+ if (++Buffer->Out == &Buffer->Buffer[BUFFER_SIZE])
+ Buffer->Out = Buffer->Buffer;
+
+ ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
+ {
+ Buffer->Count--;
+ }
+
+ return Data;
+ }
+
+#endif
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]