Merge pull request #1471 from qmk/lufa_lib

Update LUFA and move it to /lib/lufa
example_keyboards 0.5.72
Jack Humbert 8 years ago committed by GitHub
commit 9de443cbf1

@ -2,7 +2,7 @@
#include "bootloader.h" #include "bootloader.h"
#include "action_layer.h" #include "action_layer.h"
#include "eeconfig.h" #include "eeconfig.h"
#include "tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Peripheral/TWI.h" #include "LUFA/Drivers/Peripheral/TWI.h"
#ifdef AUDIO_ENABLE #ifdef AUDIO_ENABLE
#include "audio.h" #include "audio.h"
#endif #endif

@ -0,0 +1,15 @@
*.o
*.d
*.elf
*.hex
*.eep
*.sym
*.bin
*.lss
*.map
*.bak
*.class
Documentation/
LUFA/StudioIntegration/ProjectGenerator/*
LUFA/StudioIntegration/DocBook/*
!LUFA/StudioIntegration/Docbook/mshelp/*

@ -0,0 +1,75 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2017.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2017 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 disclaims 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
*
* Bootloader user application API functions.
*/
#include "BootloaderAPI.h"
void BootloaderAPI_ErasePage(const uint32_t Address)
{
boot_page_erase_safe(Address);
boot_spm_busy_wait();
boot_rww_enable();
}
void BootloaderAPI_WritePage(const uint32_t Address)
{
boot_page_write_safe(Address);
boot_spm_busy_wait();
boot_rww_enable();
}
void BootloaderAPI_FillWord(const uint32_t Address, const uint16_t Word)
{
boot_page_fill_safe(Address, Word);
}
uint8_t BootloaderAPI_ReadSignature(const uint16_t Address)
{
return boot_signature_byte_get(Address);
}
uint8_t BootloaderAPI_ReadFuse(const uint16_t Address)
{
return boot_lock_fuse_bits_get(Address);
}
uint8_t BootloaderAPI_ReadLock(void)
{
return boot_lock_fuse_bits_get(GET_LOCK_BITS);
}
void BootloaderAPI_WriteLock(const uint8_t LockBits)
{
boot_lock_bits_set_safe(LockBits);
}

@ -0,0 +1,58 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2017.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2017 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 disclaims 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 BootloaderAPI.c.
*/
#ifndef _BOOTLOADER_API_H_
#define _BOOTLOADER_API_H_
/* Includes: */
#include <avr/io.h>
#include <avr/boot.h>
#include <stdbool.h>
#include <LUFA/Common/Common.h>
#include "Config/AppConfig.h"
/* Function Prototypes: */
void BootloaderAPI_ErasePage(const uint32_t Address);
void BootloaderAPI_WritePage(const uint32_t Address);
void BootloaderAPI_FillWord(const uint32_t Address, const uint16_t Word);
uint8_t BootloaderAPI_ReadSignature(const uint16_t Address);
uint8_t BootloaderAPI_ReadFuse(const uint16_t Address);
uint8_t BootloaderAPI_ReadLock(void);
void BootloaderAPI_WriteLock(const uint8_t LockBits);
#endif

@ -0,0 +1,91 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2017.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2017 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 disclaims 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.
*/
; Trampolines to actual API implementations if the target address is outside the
; range of a rjmp instruction (can happen with large bootloader sections)
.section .apitable_trampolines, "ax"
.global BootloaderAPI_Trampolines
BootloaderAPI_Trampolines:
BootloaderAPI_ErasePage_Trampoline:
jmp BootloaderAPI_ErasePage
BootloaderAPI_WritePage_Trampoline:
jmp BootloaderAPI_WritePage
BootloaderAPI_FillWord_Trampoline:
jmp BootloaderAPI_FillWord
BootloaderAPI_ReadSignature_Trampoline:
jmp BootloaderAPI_ReadSignature
BootloaderAPI_ReadFuse_Trampoline:
jmp BootloaderAPI_ReadFuse
BootloaderAPI_ReadLock_Trampoline:
jmp BootloaderAPI_ReadLock
BootloaderAPI_WriteLock_Trampoline:
jmp BootloaderAPI_WriteLock
BootloaderAPI_UNUSED1:
ret
BootloaderAPI_UNUSED2:
ret
BootloaderAPI_UNUSED3:
ret
BootloaderAPI_UNUSED4:
ret
BootloaderAPI_UNUSED5:
ret
; API function jump table
.section .apitable_jumptable, "ax"
.global BootloaderAPI_JumpTable
BootloaderAPI_JumpTable:
rjmp BootloaderAPI_ErasePage_Trampoline
rjmp BootloaderAPI_WritePage_Trampoline
rjmp BootloaderAPI_FillWord_Trampoline
rjmp BootloaderAPI_ReadSignature_Trampoline
rjmp BootloaderAPI_ReadFuse_Trampoline
rjmp BootloaderAPI_ReadLock_Trampoline
rjmp BootloaderAPI_WriteLock_Trampoline
rjmp BootloaderAPI_UNUSED1 ; UNUSED ENTRY 1
rjmp BootloaderAPI_UNUSED2 ; UNUSED ENTRY 2
rjmp BootloaderAPI_UNUSED3 ; UNUSED ENTRY 3
rjmp BootloaderAPI_UNUSED4 ; UNUSED ENTRY 4
rjmp BootloaderAPI_UNUSED5 ; UNUSED ENTRY 5
; Bootloader table signatures and information
.section .apitable_signatures, "ax"
.global BootloaderAPI_Signatures
BootloaderAPI_Signatures:
.long BOOT_START_ADDR ; Start address of the bootloader
.word 0xDF00 ; Signature for the CDC class bootloader
.word 0xDCFB ; Signature for a LUFA class bootloader

@ -0,0 +1,673 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2017.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2017 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 disclaims 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_BOOTLOADERCDC_C
#include "BootloaderCDC.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;
/** Magic lock for forced application start. If the HWBE fuse is programmed and BOOTRST is unprogrammed, the bootloader
* will start if the /HWB line of the AVR is held low and the system is reset. However, if the /HWB line is still held
* low when the application attempts to start via a watchdog reset, the bootloader will re-start. If set to the value
* \ref MAGIC_BOOT_KEY the special init function \ref Application_Jump_Check() will force the application to start.
*/
uint16_t MagicBootKey ATTR_NO_INIT;
/** Special startup routine to check if the bootloader was started via a watchdog reset, and if the magic application
* start key has been loaded into \ref MagicBootKey. If the bootloader started via the watchdog and the key is valid,
* this will force the user application to start via a software jump.
*/
void Application_Jump_Check(void)
{
bool JumpToApplication = false;
#if (BOARD == BOARD_LEONARDO)
/* Enable pull-up on the IO13 pin so we can use it to select the mode */
PORTC |= (1 << 7);
Delay_MS(10);
/* If IO13 is not jumpered to ground, start the user application instead */
JumpToApplication = ((PINC & (1 << 7)) != 0);
/* Disable pull-up after the check has completed */
PORTC &= ~(1 << 7);
#elif ((BOARD == BOARD_XPLAIN) || (BOARD == BOARD_XPLAIN_REV1))
/* Disable JTAG debugging */
JTAG_DISABLE();
/* Enable pull-up on the JTAG TCK pin so we can use it to select the mode */
PORTF |= (1 << 4);
Delay_MS(10);
/* If the TCK pin is not jumpered to ground, start the user application instead */
JumpToApplication = ((PINF & (1 << 4)) != 0);
/* Re-enable JTAG debugging */
JTAG_ENABLE();
#else
/* Check if the device's BOOTRST fuse is set */
if (boot_lock_fuse_bits_get(GET_HIGH_FUSE_BITS) & FUSE_BOOTRST)
{
/* If the reset source was not an external reset or the key is correct, clear it and jump to the application */
if (!(MCUSR & (1 << EXTRF)) || (MagicBootKey == MAGIC_BOOT_KEY))
JumpToApplication = true;
/* Clear reset source */
MCUSR &= ~(1 << EXTRF);
}
else
{
/* If the reset source was the bootloader and the key is correct, clear it and jump to the application;
* this can happen in the HWBE fuse is set, and the HBE pin is low during the watchdog reset */
if ((MCUSR & (1 << WDRF)) && (MagicBootKey == MAGIC_BOOT_KEY))
JumpToApplication = true;
/* Clear reset source */
MCUSR &= ~(1 << WDRF);
}
#endif
/* Don't run the user application if the reset vector is blank (no app loaded) */
bool ApplicationValid = (pgm_read_word_near(0) != 0xFFFF);
/* If a request has been made to jump to the user application, honor it */
if (JumpToApplication && ApplicationValid)
{
/* Turn off the watchdog */
MCUSR &= ~(1 << WDRF);
wdt_disable();
/* Clear the boot key and jump to the user application */
MagicBootKey = 0;
// cppcheck-suppress constStatement
((void (*)(void))0x0000)();
}
}
/** 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)
{
/* Setup hardware required for the bootloader */
SetupHardware();
/* Turn on first LED on the board to indicate that the bootloader has started */
LEDs_SetAllLEDs(LEDS_LED1);
/* Enable global interrupts so that the USB stack can function */
GlobalInterruptEnable();
while (RunBootloader)
{
CDC_Task();
USB_USBTask();
}
/* Wait a short time to end all USB transactions and then disconnect */
_delay_us(1000);
/* Disconnect from the host - USB interface will be reset later along with the AVR */
USB_Detach();
/* Unlock the forced application start mode of the bootloader if it is restarted */
MagicBootKey = MAGIC_BOOT_KEY;
/* Enable the watchdog and force a timeout to reset the AVR */
wdt_enable(WDTO_250MS);
for (;;);
}
/** Configures all hardware required for the bootloader. */
static 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);
/* Initialize the USB and other board hardware drivers */
USB_Init();
LEDs_Init();
/* Bootloader active LED toggle timer initialization */
TIMSK1 = (1 << TOIE1);
TCCR1B = ((1 << CS11) | (1 << CS10));
}
/** ISR to periodically toggle the LEDs on the board to indicate that the bootloader is active. */
ISR(TIMER1_OVF_vect, ISR_BLOCK)
{
LEDs_ToggleLEDs(LEDS_LED1 | LEDS_LED2);
}
/** 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_EPADDR, EP_TYPE_INTERRUPT,
CDC_NOTIFICATION_EPSIZE, 1);
Endpoint_ConfigureEndpoint(CDC_TX_EPADDR, EP_TYPE_BULK, CDC_TXRX_EPSIZE, 1);
Endpoint_ConfigureEndpoint(CDC_RX_EPADDR, EP_TYPE_BULK, CDC_TXRX_EPSIZE, 1);
}
/** 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;
}
/* Activity - toggle indicator LEDs */
LEDs_ToggleLEDs(LEDS_LED1 | LEDS_LED2);
/* 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;
case CDC_REQ_SetControlLineState:
if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
{
Endpoint_ClearSETUP();
Endpoint_ClearStatusStage();
}
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 AVR109 protocol command issued.
*
* \param[in] Command Single character AVR109 protocol command indicating what memory operation to perform
*/
static void ReadWriteMemoryBlock(const uint8_t Command)
{
uint16_t BlockSize;
char MemoryType;
uint8_t HighByte = 0;
uint8_t LowByte = 0;
BlockSize = (FetchNextCommandByte() << 8);
BlockSize |= FetchNextCommandByte();
MemoryType = FetchNextCommandByte();
if ((MemoryType != MEMORY_TYPE_FLASH) && (MemoryType != MEMORY_TYPE_EEPROM))
{
/* Send error byte back to the host */
WriteNextResponseByte('?');
return;
}
/* Check if command is to read a memory block */
if (Command == AVR109_COMMAND_BlockRead)
{
/* Re-enable RWW section */
boot_rww_enable();
while (BlockSize--)
{
if (MemoryType == MEMORY_TYPE_FLASH)
{
/* 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 == MEMORY_TYPE_FLASH)
{
boot_page_erase(PageStartAddress);
boot_spm_busy_wait();
}
while (BlockSize--)
{
if (MemoryType == MEMORY_TYPE_FLASH)
{
/* 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_update_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 == MEMORY_TYPE_FLASH)
{
/* 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');
}
}
#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_EPADDR);
/* 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_EPADDR);
/* 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);
}
/** Task to read in AVR109 commands from the CDC data OUT endpoint, process them, perform the required actions
* and send the appropriate response back to the host.
*/
static void CDC_Task(void)
{
/* Select the OUT endpoint */
Endpoint_SelectEndpoint(CDC_RX_EPADDR);
/* Check if endpoint has a command in it sent from the host */
if (!(Endpoint_IsOUTReceived()))
return;
/* Read in the bootloader command (first byte sent from host) */
uint8_t Command = FetchNextCommandByte();
if (Command == AVR109_COMMAND_ExitBootloader)
{
RunBootloader = false;
/* Send confirmation byte back to the host */
WriteNextResponseByte('\r');
}
else if ((Command == AVR109_COMMAND_SetLED) || (Command == AVR109_COMMAND_ClearLED) ||
(Command == AVR109_COMMAND_SelectDeviceType))
{
FetchNextCommandByte();
/* Send confirmation byte back to the host */
WriteNextResponseByte('\r');
}
else if ((Command == AVR109_COMMAND_EnterProgrammingMode) || (Command == AVR109_COMMAND_LeaveProgrammingMode))
{
/* Send confirmation byte back to the host */
WriteNextResponseByte('\r');
}
else if (Command == AVR109_COMMAND_ReadPartCode)
{
/* Return ATMEGA128 part code - this is only to allow AVRProg to use the bootloader */
WriteNextResponseByte(0x44);
WriteNextResponseByte(0x00);
}
else if (Command == AVR109_COMMAND_ReadAutoAddressIncrement)
{
/* Indicate auto-address increment is supported */
WriteNextResponseByte('Y');
}
else if (Command == AVR109_COMMAND_SetCurrentAddress)
{
/* Set the current address to that given by the host (translate 16-bit word address to byte address) */
CurrAddress = (FetchNextCommandByte() << 9);
CurrAddress |= (FetchNextCommandByte() << 1);
/* Send confirmation byte back to the host */
WriteNextResponseByte('\r');
}
else if (Command == AVR109_COMMAND_ReadBootloaderInterface)
{
/* Indicate serial programmer back to the host */
WriteNextResponseByte('S');
}
else if (Command == AVR109_COMMAND_ReadBootloaderIdentifier)
{
/* Write the 7-byte software identifier to the endpoint */
for (uint8_t CurrByte = 0; CurrByte < 7; CurrByte++)
WriteNextResponseByte(SOFTWARE_IDENTIFIER[CurrByte]);
}
else if (Command == AVR109_COMMAND_ReadBootloaderSWVersion)
{
WriteNextResponseByte('0' + BOOTLOADER_VERSION_MAJOR);
WriteNextResponseByte('0' + BOOTLOADER_VERSION_MINOR);
}
else if (Command == AVR109_COMMAND_ReadSignature)
{
WriteNextResponseByte(AVR_SIGNATURE_3);
WriteNextResponseByte(AVR_SIGNATURE_2);
WriteNextResponseByte(AVR_SIGNATURE_1);
}
else if (Command == AVR109_COMMAND_EraseFLASH)
{
/* Clear the application section of flash */
for (uint32_t CurrFlashAddress = 0; CurrFlashAddress < (uint32_t)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 == AVR109_COMMAND_WriteLockbits)
{
/* 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 == AVR109_COMMAND_ReadLockbits)
{
WriteNextResponseByte(boot_lock_fuse_bits_get(GET_LOCK_BITS));
}
else if (Command == AVR109_COMMAND_ReadLowFuses)
{
WriteNextResponseByte(boot_lock_fuse_bits_get(GET_LOW_FUSE_BITS));
}
else if (Command == AVR109_COMMAND_ReadHighFuses)
{
WriteNextResponseByte(boot_lock_fuse_bits_get(GET_HIGH_FUSE_BITS));
}
else if (Command == AVR109_COMMAND_ReadExtendedFuses)
{
WriteNextResponseByte(boot_lock_fuse_bits_get(GET_EXTENDED_FUSE_BITS));
}
#if !defined(NO_BLOCK_SUPPORT)
else if (Command == AVR109_COMMAND_GetBlockWriteSupport)
{
WriteNextResponseByte('Y');
/* Send block size to the host */
WriteNextResponseByte(SPM_PAGESIZE >> 8);
WriteNextResponseByte(SPM_PAGESIZE & 0xFF);
}
else if ((Command == AVR109_COMMAND_BlockWrite) || (Command == AVR109_COMMAND_BlockRead))
{
/* Delegate the block write/read to a separate function for clarity */
ReadWriteMemoryBlock(Command);
}
#endif
#if !defined(NO_FLASH_BYTE_SUPPORT)
else if (Command == AVR109_COMMAND_FillFlashPageWordHigh)
{
/* 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 == AVR109_COMMAND_FillFlashPageWordLow)
{
/* 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 == AVR109_COMMAND_WriteFlashPage)
{
/* 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 == AVR109_COMMAND_ReadFLASHWord)
{
#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 == AVR109_COMMAND_WriteEEPROM)
{
/* Read the byte from the endpoint and write it to the EEPROM */
eeprom_update_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 == AVR109_COMMAND_ReadEEPROM)
{
/* 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 != AVR109_COMMAND_Sync)
{
/* Unknown (non-sync) command, return fail code */
WriteNextResponseByte('?');
}
/* Select the IN endpoint */
Endpoint_SelectEndpoint(CDC_TX_EPADDR);
/* 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_EPADDR);
/* Acknowledge the command from the host */
Endpoint_ClearOUT();
}

@ -0,0 +1,144 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2017.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2017 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 disclaims 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 "BootloaderAPI.h"
#include "Config/AppConfig.h"
#include <LUFA/Drivers/USB/USB.h>
#include <LUFA/Drivers/Board/LEDs.h>
#include <LUFA/Platform/Platform.h>
/* Preprocessor Checks: */
#if !defined(__OPTIMIZE_SIZE__)
#error This bootloader requires that it be optimized for size, not speed, to fit into the target device. Change optimization settings and try again.
#endif
/* 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 "LUFACDC"
/** Magic bootloader key to unlock forced application start mode. */
#define MAGIC_BOOT_KEY 0xDC42
/* Enums: */
/** Possible memory types that can be addressed via the bootloader. */
enum AVR109_Memories
{
MEMORY_TYPE_FLASH = 'F',
MEMORY_TYPE_EEPROM = 'E',
};
/** Possible commands that can be issued to the bootloader. */
enum AVR109_Commands
{
AVR109_COMMAND_Sync = 27,
AVR109_COMMAND_ReadEEPROM = 'd',
AVR109_COMMAND_WriteEEPROM = 'D',
AVR109_COMMAND_ReadFLASHWord = 'R',
AVR109_COMMAND_WriteFlashPage = 'm',
AVR109_COMMAND_FillFlashPageWordLow = 'c',
AVR109_COMMAND_FillFlashPageWordHigh = 'C',
AVR109_COMMAND_GetBlockWriteSupport = 'b',
AVR109_COMMAND_BlockWrite = 'B',
AVR109_COMMAND_BlockRead = 'g',
AVR109_COMMAND_ReadExtendedFuses = 'Q',
AVR109_COMMAND_ReadHighFuses = 'N',
AVR109_COMMAND_ReadLowFuses = 'F',
AVR109_COMMAND_ReadLockbits = 'r',
AVR109_COMMAND_WriteLockbits = 'l',
AVR109_COMMAND_EraseFLASH = 'e',
AVR109_COMMAND_ReadSignature = 's',
AVR109_COMMAND_ReadBootloaderSWVersion = 'V',
AVR109_COMMAND_ReadBootloaderHWVersion = 'v',
AVR109_COMMAND_ReadBootloaderIdentifier = 'S',
AVR109_COMMAND_ReadBootloaderInterface = 'p',
AVR109_COMMAND_SetCurrentAddress = 'A',
AVR109_COMMAND_ReadAutoAddressIncrement = 'a',
AVR109_COMMAND_ReadPartCode = 't',
AVR109_COMMAND_EnterProgrammingMode = 'P',
AVR109_COMMAND_LeaveProgrammingMode = 'L',
AVR109_COMMAND_SelectDeviceType = 'T',
AVR109_COMMAND_SetLED = 'x',
AVR109_COMMAND_ClearLED = 'y',
AVR109_COMMAND_ExitBootloader = 'E',
};
/* 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: */
static void CDC_Task(void);
static void SetupHardware(void);
void Application_Jump_Check(void) ATTR_INIT_SECTION(3);
void EVENT_USB_Device_ConfigurationChanged(void);
#if defined(INCLUDE_FROM_BOOTLOADERCDC_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

@ -0,0 +1,242 @@
/** \file
*
* This file contains special DoxyGen information for the generation of the main page and other special
* documentation pages. It is not a project source file.
*/
/** \mainpage CDC Class USB AVR Bootloader
*
* \section Sec_Compat Demo Compatibility:
*
* The following list indicates what microcontrollers are compatible with this demo.
*
* \li Series 7 USB AVRs (AT90USBxxx7)
* \li Series 6 USB AVRs (AT90USBxxx6)
* \li Series 4 USB AVRs (ATMEGAxxU4)
* \li Series 2 USB AVRs (AT90USBxx2, ATMEGAxxU2)
*
* \section Sec_Info USB Information:
*
* The following table gives a rundown of the USB utilization of this demo.
*
* <table>
* <tr>
* <td><b>USB Mode:</b></td>
* <td>Device</td>
* </tr>
* <tr>
* <td><b>USB Class:</b></td>
* <td>Communications Device Class (CDC)</td>
* </tr>
* <tr>
* <td><b>USB Subclass:</b></td>
* <td>Abstract Control Model (ACM)</td>
* </tr>
* <tr>
* <td><b>Relevant Standards:</b></td>
* <td>USBIF CDC Class Standard</td>
* </tr>
* <tr>
* <td><b>Supported USB Speeds:</b></td>
* <td>Full Speed Mode</td>
* </tr>
* </table>
*
* \section Sec_Description Project Description:
*
* This bootloader enumerates to the host as a CDC Class device (virtual serial port), allowing for AVR109
* protocol compatible programming software to load firmware onto the AVR.
*
* Out of the box this bootloader builds for the AT90USB1287 with an 8KB bootloader section size, and will fit
* into 4KB of bootloader space. If you wish to alter this size and/or change the AVR model, you will need to
* edit the MCU, FLASH_SIZE_KB and BOOT_SECTION_SIZE_KB values in the accompanying makefile.
*
* When the bootloader is running, the board's LED(s) will flash at regular intervals to distinguish the
* bootloader from the normal user application.
*
* \warning <b>THIS BOOTLOADER IS NOT SECURE.</b> Malicious entities can recover written data, even if the device
* lockbits are set.
*
* \section Sec_Running Running the Bootloader
*
* On the USB AVR8 devices, setting the \c HWBE device fuse will cause the bootloader to run if the \c HWB pin of
* the AVR is grounded when the device is reset.
*
* The are two behaviours of this bootloader, depending on the device's fuses:
*
* <b>If the device's BOOTRST fuse is set</b>, the bootloader will run any time the system is reset from
* the external reset pin, unless no valid user application has been loaded. To initiate the bootloader, the
* device's external reset pin should be grounded momentarily.
*
* <b>If the device's BOOTRST fuse is not set</b>, the bootloader will run only if initiated via a software
* jump, or if the \c HWB pin was low during the last device reset (if the \c HWBE fuse is set).
*
* For board specific exceptions to the above, see below.
*
* \subsection SSec_XPLAIN Atmel Xplain Board
* Ground the USB AVR JTAG's \c TCK pin to ground when powering on the board to start the bootloader. This assumes the
* \c HWBE fuse is cleared and the \c BOOTRST fuse is set as the HWBE pin is not user accessible on this board.
*
* \subsection SSec_Leonardo Arduino Leonardo Board
* Ground \c IO13 when powering the board to start the bootloader. This assumes the \c HWBE fuse is cleared and the
* \c BOOTRST fuse is set as the HWBE pin is not user accessible on this board.
*
* \section Sec_Installation Driver Installation
*
* After running this bootloader for the first time on a new computer, you will need to supply the .INF
* file located in this bootloader project's directory as the device's driver when running under Windows.
* This will enable Windows to use its inbuilt CDC drivers, negating the need for custom drivers for the
* device. Other Operating Systems should automatically use their own inbuilt CDC-ACM drivers.
*
* \section Sec_HostApp Host Controller Application
*
* This bootloader is compatible with the open source application AVRDUDE, Atmel's AVRPROG, or other
* applications implementing the AVR109 protocol, which is documented on the Atmel website as an application
* note.
*
* \subsection SSec_AVRDude AVRDUDE (Windows, Mac, Linux)
*
* AVRDude is a free, cross-platform and open source command line programmer for Atmel and third party AVR
* programmers. It is available on the the Windows platform as part of the "WinAVR" package, or on other systems
* either from a build from the official source code, or in many distributions as a precompiled binary package.
*
* To load a new HEX file with AVRDude, specify "AVR109" as the programmer, with the allocated COM port. On Windows
* platforms this will be a COMx port name:
* \code
* avrdude -c AVR109 -p at90usb1287 -P COM0 -U flash:w:Mouse.hex
* \endcode
*
* On Linux systems, this will typically be a /dev/ttyACMx port name:
* \code
* avrdude -c AVR109 -p at90usb1287 -P /dev/ttyACM0 -U flash:w:Mouse.hex
* \endcode
*
* Refer to the AVRDude project documentation for additional usage instructions.
*
* \section Sec_API User Application API
*
* Several user application functions for FLASH and other special memory area manipulations are exposed by the bootloader,
* allowing the user application to call into the bootloader at runtime to read and write FLASH data.
*
* By default, the bootloader API jump table is located 32 bytes from the end of the device's FLASH memory, and follows the
* following layout:
*
* \code
* #define BOOTLOADER_API_TABLE_SIZE 32
* #define BOOTLOADER_API_TABLE_START ((FLASHEND + 1UL) - BOOTLOADER_API_TABLE_SIZE)
* #define BOOTLOADER_API_CALL(Index) (void*)((BOOTLOADER_API_TABLE_START + (Index * 2)) / 2)
*
* void (*BootloaderAPI_ErasePage)(uint32_t Address) = BOOTLOADER_API_CALL(0);
* void (*BootloaderAPI_WritePage)(uint32_t Address) = BOOTLOADER_API_CALL(1);
* void (*BootloaderAPI_FillWord)(uint32_t Address, uint16_t Word) = BOOTLOADER_API_CALL(2);
* uint8_t (*BootloaderAPI_ReadSignature)(uint16_t Address) = BOOTLOADER_API_CALL(3);
* uint8_t (*BootloaderAPI_ReadFuse)(uint16_t Address) = BOOTLOADER_API_CALL(4);
* uint8_t (*BootloaderAPI_ReadLock)(void) = BOOTLOADER_API_CALL(5);
* void (*BootloaderAPI_WriteLock)(uint8_t LockBits) = BOOTLOADER_API_CALL(6);
*
* #define BOOTLOADER_MAGIC_SIGNATURE_START (BOOTLOADER_API_TABLE_START + (BOOTLOADER_API_TABLE_SIZE - 2))
* #define BOOTLOADER_MAGIC_SIGNATURE 0xDCFB
*
* #define BOOTLOADER_CLASS_SIGNATURE_START (BOOTLOADER_API_TABLE_START + (BOOTLOADER_API_TABLE_SIZE - 4))
* #define BOOTLOADER_CDC_SIGNATURE 0xDF00
*
* #define BOOTLOADER_ADDRESS_START (BOOTLOADER_API_TABLE_START + (BOOTLOADER_API_TABLE_SIZE - 8))
* #define BOOTLOADER_ADDRESS_LENGTH 4
* \endcode
*
* From the application the API support of the bootloader can be detected by reading the FLASH memory bytes located at address
* \c BOOTLOADER_MAGIC_SIGNATURE_START and comparing them to the value \c BOOTLOADER_MAGIC_SIGNATURE. The class of bootloader
* can be determined by reading the FLASH memory bytes located at address \c BOOTLOADER_CLASS_SIGNATURE_START and comparing them
* to the value \c BOOTLOADER_CDC_SIGNATURE. The start address of the bootloader can be retrieved by reading the bytes of FLASH
* memory starting from address \c BOOTLOADER_ADDRESS_START.
*
* \subsection SSec_API_MemLayout Device Memory Map
* The following illustration indicates the final memory map of the device when loaded with the bootloader.
*
* \verbatim
* +----------------------------+ 0x0000
* | |
* | |
* | |
* | |
* | |
* | |
* | |
* | |
* | User Application |
* | |
* | |
* | |
* | |
* | |
* | |
* | |
* +----------------------------+ FLASHEND - BOOT_SECTION_SIZE
* | |
* | Bootloader Application |
* | (Not User App. Accessible) |
* | |
* +----------------------------+ FLASHEND - 96
* | API Table Trampolines |
* | (Not User App. Accessible) |
* +----------------------------+ FLASHEND - 32
* | Bootloader API Table |
* | (User App. Accessible) |
* +----------------------------+ FLASHEND - 8
* | Bootloader ID Constants |
* | (User App. Accessible) |
* +----------------------------+ FLASHEND
* \endverbatim
*
* \section Sec_KnownIssues Known Issues:
*
* \par On Linux machines, the CDC bootloader is unstable or inaccessible.
* A change to the \c ModemManager module in many Linux distributions causes
* this module to try to take control over inserted CDC devices, corrupting the
* datastream. A UDEV rule is required to prevent this.
* See <a href=https://groups.google.com/d/msg/lufa-support/CP9cy2bc8yo/kBqsOu-RBeMJ>here</a> for resolution steps.
* If the issue still persists then uninstall modemmanager by executing <tt>sudo apt-get remove modemmanager</tt>, or
* the equivalent using your chosen distribution's package manager.
*
* \par On Linux machines, the CDC bootloader is inaccessible.
* On many Linux systems, non-root users do not have automatic access to newly
* inserted CDC devices. Root privileges or a UDEV rule is required to gain
* access.
* See <a href=https://groups.google.com/d/msg/lufa-support/CP9cy2bc8yo/kBqsOu-RBeMJ>here</a> for resolution steps.
*
* \section Sec_Options Project Options
*
* The following defines can be found in this demo, which can control the demo behaviour when defined, or changed in value.
*
* <table>
* <tr>
* <th><b>Define Name:</b></th>
* <th><b>Location:</b></th>
* <th><b>Description:</b></th>
* </tr>
* <tr>
* <td>NO_BLOCK_SUPPORT</td>
* <td>AppConfig.h</td>
* <td>Define to disable memory block read/write support in the bootloader, requiring all reads and writes to be made
* using the byte-level commands.</td>
* </tr>
* <tr>
* <td>NO_EEPROM_BYTE_SUPPORT</td>
* <td>AppConfig.h</td>
* <td>Define to disable EEPROM memory byte read/write support in the bootloader, requiring all EEPROM reads and writes
* to be made using the block-level commands.</td>
* </tr>
* <tr>
* <td>NO_FLASH_BYTE_SUPPORT</td>
* <td>AppConfig.h</td>
* <td>Define to disable FLASH memory byte read/write support in the bootloader, requiring all FLASH reads and writes
* to be made using the block-level commands.</td>
* </tr>
* <tr>
* <td>NO_LOCK_BYTE_WRITE_SUPPORT</td>
* <td>AppConfig.h</td>
* <td>Define to disable lock byte write support in the bootloader, preventing the lock bits from being set programmatically.</td>
* </tr>
* </table>
*/

@ -0,0 +1,50 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2017.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2017 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 disclaims 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
* \brief Application Configuration Header File
*
* This is a header file which is be used to configure LUFA's
* compile time options, as an alternative to the compile time
* constants supplied through a makefile.
*
* For information on what each token does, refer to the
* \ref Sec_Options section of the application documentation.
*/
#ifndef _APP_CONFIG_H_
#define _APP_CONFIG_H_
// #define NO_BLOCK_SUPPORT
// #define NO_EEPROM_BYTE_SUPPORT
// #define NO_FLASH_BYTE_SUPPORT
// #define NO_LOCK_BYTE_WRITE_SUPPORT
#endif

@ -0,0 +1,93 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2017.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2017 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 disclaims 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
* \brief LUFA Library Configuration Header File
*
* This header file is used to configure LUFA's compile time options,
* as an alternative to the compile time constants supplied through
* a makefile.
*
* For information on what each token does, refer to the LUFA
* manual section "Summary of Compile Tokens".
*/
#ifndef _LUFA_CONFIG_H_
#define _LUFA_CONFIG_H_
#if (ARCH == ARCH_AVR8)
/* Non-USB Related Configuration Tokens: */
// #define DISABLE_TERMINAL_CODES
/* USB Class Driver Related Tokens: */
// #define HID_HOST_BOOT_PROTOCOL_ONLY
// #define HID_STATETABLE_STACK_DEPTH {Insert Value Here}
// #define HID_USAGE_STACK_DEPTH {Insert Value Here}
// #define HID_MAX_COLLECTIONS {Insert Value Here}
// #define HID_MAX_REPORTITEMS {Insert Value Here}
// #define HID_MAX_REPORT_IDS {Insert Value Here}
// #define NO_CLASS_DRIVER_AUTOFLUSH
/* General USB Driver Related Tokens: */
#define ORDERED_EP_CONFIG
#define USE_STATIC_OPTIONS (USB_DEVICE_OPT_FULLSPEED | USB_OPT_REG_ENABLED | USB_OPT_AUTO_PLL)
#define USB_DEVICE_ONLY
// #define USB_HOST_ONLY
// #define USB_STREAM_TIMEOUT_MS {Insert Value Here}
// #define NO_LIMITED_CONTROLLER_CONNECT
#define NO_SOF_EVENTS
/* USB Device Mode Driver Related Tokens: */
#define USE_RAM_DESCRIPTORS
// #define USE_FLASH_DESCRIPTORS
// #define USE_EEPROM_DESCRIPTORS
#define NO_INTERNAL_SERIAL
#define FIXED_CONTROL_ENDPOINT_SIZE 8
#define DEVICE_STATE_AS_GPIOR 0
#define FIXED_NUM_CONFIGURATIONS 1
// #define CONTROL_ONLY_DEVICE
// #define INTERRUPT_CONTROL_ENDPOINT
#define NO_DEVICE_REMOTE_WAKEUP
#define NO_DEVICE_SELF_POWER
/* USB Host Mode Driver Related Tokens: */
// #define HOST_STATE_AS_GPIOR {Insert Value Here}
// #define USB_HOST_TIMEOUT_MS {Insert Value Here}
// #define HOST_DEVICE_SETTLE_DELAY_MS {Insert Value Here}
// #define NO_AUTO_VBUS_MANAGEMENT
// #define INVERTED_VBUS_ENABLE_LINE
#else
#error Unsupported architecture for this LUFA configuration file.
#endif
#endif

@ -0,0 +1,244 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2017.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2017 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 disclaims 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(1,1,0),
.Class = CDC_CSCP_CDCClass,
.SubClass = CDC_CSCP_NoSpecificSubclass,
.Protocol = CDC_CSCP_NoSpecificProtocol,
.Endpoint0Size = FIXED_CONTROL_ENDPOINT_SIZE,
.VendorID = 0x03EB,
.ProductID = 0x204A,
.ReleaseNumber = VERSION_BCD(1,0,0),
.ManufacturerStrIndex = STRING_ID_Manufacturer,
.ProductStrIndex = STRING_ID_Product,
.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_RESERVED,
.MaxPowerConsumption = USB_CONFIG_POWER_MA(100)
},
.CDC_CCI_Interface =
{
.Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},
.InterfaceNumber = INTERFACE_ID_CDC_CCI,
.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(1,1,0),
},
.CDC_Functional_ACM =
{
.Header = {.Size = sizeof(USB_CDC_Descriptor_FunctionalACM_t), .Type = DTYPE_CSInterface},
.Subtype = 0x02,
.Capabilities = 0x02,
},
.CDC_Functional_Union =
{
.Header = {.Size = sizeof(USB_CDC_Descriptor_FunctionalUnion_t), .Type = DTYPE_CSInterface},
.Subtype = 0x06,
.MasterInterfaceNumber = INTERFACE_ID_CDC_CCI,
.SlaveInterfaceNumber = INTERFACE_ID_CDC_DCI,
},
.CDC_NotificationEndpoint =
{
.Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
.EndpointAddress = CDC_NOTIFICATION_EPADDR,
.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 = INTERFACE_ID_CDC_DCI,
.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 = CDC_RX_EPADDR,
.Attributes = (EP_TYPE_BULK | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
.EndpointSize = CDC_TXRX_EPSIZE,
.PollingIntervalMS = 0x05
},
.CDC_DataInEndpoint =
{
.Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
.EndpointAddress = CDC_TX_EPADDR,
.Attributes = (EP_TYPE_BULK | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
.EndpointSize = CDC_TXRX_EPSIZE,
.PollingIntervalMS = 0x05
}
};
/** 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 = USB_STRING_DESCRIPTOR_ARRAY(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.
*/
const USB_Descriptor_String_t ManufacturerString = USB_STRING_DESCRIPTOR(L"Dean Camera");
/** 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 = USB_STRING_DESCRIPTOR(L"LUFA CDC");
/** 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 uint16_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 == STRING_ID_Language)
{
Address = &LanguageString;
Size = LanguageString.Header.Size;
}
else if (DescriptorNumber == STRING_ID_Manufacturer)
{
Address = &ManufacturerString;
Size = ManufacturerString.Header.Size;
}
else if (DescriptorNumber == STRING_ID_Product)
{
Address = &ProductString;
Size = ProductString.Header.Size;
}
break;
}
*DescriptorAddress = Address;
return Size;
}

@ -0,0 +1,158 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2017.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2017 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 disclaims 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>
#include "Config/AppConfig.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_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 0x93
#define AVR_SIGNATURE_3 0x82
#else
#error The selected AVR part is not currently supported by this bootloader.
#endif
/** Endpoint address for the CDC control interface event notification endpoint. */
#define CDC_NOTIFICATION_EPADDR (ENDPOINT_DIR_IN | 2)
/** Endpoint address for the CDC data interface TX (data IN) endpoint. */
#define CDC_TX_EPADDR (ENDPOINT_DIR_IN | 3)
/** Endpoint address for the CDC data interface RX (data OUT) endpoint. */
#define CDC_RX_EPADDR (ENDPOINT_DIR_OUT | 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;
/** Enum for the device interface descriptor IDs within the device. Each interface descriptor
* should have a unique ID index associated with it, which can be used to refer to the
* interface from other descriptors.
*/
enum InterfaceDescriptors_t
{
INTERFACE_ID_CDC_CCI = 0, /**< CDC CCI interface descriptor ID */
INTERFACE_ID_CDC_DCI = 1, /**< CDC DCI interface descriptor ID */
};
/** Enum for the device string descriptor IDs within the device. Each string descriptor should
* have a unique ID index associated with it, which can be used to refer to the string from
* other descriptors.
*/
enum StringDescriptors_t
{
STRING_ID_Language = 0, /**< Supported Languages string descriptor ID (must be zero) */
STRING_ID_Manufacturer = 1, /**< Manufacturer string ID */
STRING_ID_Product = 2, /**< Product string ID */
};
/* Function Prototypes: */
uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue,
const uint16_t wIndex,
const void** const DescriptorAddress)
ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(3);
#endif

@ -0,0 +1,161 @@
<asf xmlversion="1.0">
<project caption="CDC Bootloader - 128KB FLASH / 4KB Boot - AVR8 Architecture" id="lufa.bootloaders.cdc.avr8.128_4" force-caption="true" workspace-name="lufa_cdc_128kb_4kb_">
<require idref="lufa.bootloaders.cdc"/>
<require idref="lufa.boards.dummy.avr8"/>
<generator value="as5_8"/>
<device-support value="at90usb1287"/>
<config name="lufa.drivers.board.name" value="none"/>
<config name="config.compiler.optimization.level" value="size"/>
<build type="define" name="F_CPU" value="16000000UL"/>
<build type="define" name="F_USB" value="16000000UL"/>
<build type="define" name="BOOT_START_ADDR" value="0x1F000"/>
<build type="linker-config" subtype="flags" value="--section-start=.text=0x1F000"/>
<build type="linker-config" subtype="flags" value="--section-start=.apitable_trampolines=0x1FFA0"/>
<build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_Trampolines"/>
<build type="linker-config" subtype="flags" value="--section-start=.apitable_jumptable=0x1FFE0"/>
<build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_JumpTable"/>
<build type="linker-config" subtype="flags" value="--section-start=.apitable_signatures=0x1FFF8"/>
<build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_Signatures"/>
</project>
<project caption="CDC Bootloader - 64KB FLASH / 4KB Boot - AVR8 Architecture" id="lufa.bootloaders.cdc.avr8.64_4" force-caption="true" workspace-name="lufa_cdc_64kb_4kb_">
<require idref="lufa.bootloaders.cdc"/>
<require idref="lufa.boards.dummy.avr8"/>
<generator value="as5_8"/>
<device-support value="at90usb647"/>
<config name="lufa.drivers.board.name" value="none"/>
<config name="config.compiler.optimization.level" value="size"/>
<build type="define" name="F_CPU" value="16000000UL"/>
<build type="define" name="F_USB" value="16000000UL"/>
<build type="define" name="BOOT_START_ADDR" value="0xF000"/>
<build type="linker-config" subtype="flags" value="--section-start=.text=0xF000"/>
<build type="linker-config" subtype="flags" value="--section-start=.apitable_trampolines=0xFFA0"/>
<build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_Trampolines"/>
<build type="linker-config" subtype="flags" value="--section-start=.apitable_jumptable=0xFFE0"/>
<build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_JumpTable"/>
<build type="linker-config" subtype="flags" value="--section-start=.apitable_signatures=0xFFF8"/>
<build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_Signatures"/>
</project>
<project caption="CDC Bootloader - 32KB FLASH / 4KB Boot - AVR8 Architecture" id="lufa.bootloaders.cdc.avr8.32_4" force-caption="true" workspace-name="lufa_cdc_32kb_4kb_">
<require idref="lufa.bootloaders.cdc"/>
<require idref="lufa.boards.dummy.avr8"/>
<generator value="as5_8"/>
<device-support value="atmega32u4"/>
<config name="lufa.drivers.board.name" value="none"/>
<config name="config.compiler.optimization.level" value="size"/>
<build type="define" name="F_CPU" value="16000000UL"/>
<build type="define" name="F_USB" value="16000000UL"/>
<build type="define" name="BOOT_START_ADDR" value="0x7000"/>
<build type="linker-config" subtype="flags" value="--section-start=.text=0x7000"/>
<build type="linker-config" subtype="flags" value="--section-start=.apitable_trampolines=0x7FA0"/>
<build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_Trampolines"/>
<build type="linker-config" subtype="flags" value="--section-start=.apitable_jumptable=0x7FE0"/>
<build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_JumpTable"/>
<build type="linker-config" subtype="flags" value="--section-start=.apitable_signatures=0x7FF8"/>
<build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_Signatures"/>
</project>
<project caption="CDC Bootloader - 16KB FLASH / 4KB Boot - AVR8 Architecture" id="lufa.bootloaders.cdc.avr8.16_4" force-caption="true" workspace-name="lufa_cdc_16kb_4kb_">
<require idref="lufa.bootloaders.cdc"/>
<require idref="lufa.boards.dummy.avr8"/>
<generator value="as5_8"/>
<device-support value="atmega16u2"/>
<config name="lufa.drivers.board.name" value="none"/>
<config name="config.compiler.optimization.level" value="size"/>
<build type="define" name="F_CPU" value="16000000UL"/>
<build type="define" name="F_USB" value="16000000UL"/>
<build type="define" name="BOOT_START_ADDR" value="0x3000"/>
<build type="linker-config" subtype="flags" value="--section-start=.text=0x3000"/>
<build type="linker-config" subtype="flags" value="--section-start=.apitable_trampolines=0x3FA0"/>
<build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_Trampolines"/>
<build type="linker-config" subtype="flags" value="--section-start=.apitable_jumptable=0x3FE0"/>
<build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_JumpTable"/>
<build type="linker-config" subtype="flags" value="--section-start=.apitable_signatures=0x3FF8"/>
<build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_Signatures"/>
</project>
<project caption="CDC Bootloader - 8KB FLASH / 4KB Boot - AVR8 Architecture" id="lufa.bootloaders.cdc.avr8.8_4" force-caption="true" workspace-name="lufa_cdc_8kb_4kb_">
<require idref="lufa.bootloaders.cdc"/>
<require idref="lufa.boards.dummy.avr8"/>
<generator value="as5_8"/>
<device-support value="atmega8u2"/>
<config name="lufa.drivers.board.name" value="none"/>
<config name="config.compiler.optimization.level" value="size"/>
<build type="define" name="F_CPU" value="16000000UL"/>
<build type="define" name="F_USB" value="16000000UL"/>
<build type="define" name="BOOT_START_ADDR" value="0x1000"/>
<build type="linker-config" subtype="flags" value="--section-start=.text=0x1000"/>
<build type="linker-config" subtype="flags" value="--section-start=.apitable_trampolines=0x1FA0"/>
<build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_Trampolines"/>
<build type="linker-config" subtype="flags" value="--section-start=.apitable_jumptable=0x1FE0"/>
<build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_JumpTable"/>
<build type="linker-config" subtype="flags" value="--section-start=.apitable_signatures=0x1FF8"/>
<build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_Signatures"/>
</project>
<module type="application" id="lufa.bootloaders.cdc" caption="CDC Bootloader">
<info type="description" value="summary">
CDC Class Bootloader, capable of reprogramming a device using avrdude or other AVR109 protocol compliant software when plugged into a host.
</info>
<info type="gui-flag" value="move-to-root"/>
<info type="keyword" value="Technology">
<keyword value="Bootloaders"/>
<keyword value="USB Device"/>
</info>
<device-support-alias value="lufa_avr8"/>
<device-support-alias value="lufa_xmega"/>
<device-support-alias value="lufa_uc3"/>
<build type="include-path" value="."/>
<build type="c-source" value="BootloaderCDC.c"/>
<build type="header-file" value="BootloaderCDC.h"/>
<build type="c-source" value="Descriptors.c"/>
<build type="header-file" value="Descriptors.h"/>
<build type="c-source" value="BootloaderAPI.c"/>
<build type="header-file" value="BootloaderAPI.h"/>
<build type="asm-source" value="BootloaderAPITable.S"/>
<build type="module-config" subtype="path" value="Config"/>
<build type="header-file" value="Config/LUFAConfig.h"/>
<build type="header-file" value="Config/AppConfig.h"/>
<build type="distribute" subtype="user-file" value="doxyfile"/>
<build type="distribute" subtype="user-file" value="BootloaderCDC.txt"/>
<build type="distribute" subtype="user-file" value="LUFA CDC Bootloader.inf"/>
<require idref="lufa.common"/>
<require idref="lufa.platform"/>
<require idref="lufa.drivers.usb"/>
<require idref="lufa.drivers.board"/>
<require idref="lufa.drivers.board.leds"/>
</module>
</asf>

File diff suppressed because it is too large Load Diff

@ -0,0 +1,62 @@
#
# LUFA Library
# Copyright (C) Dean Camera, 2017.
#
# dean [at] fourwalledcubicle [dot] com
# www.lufa-lib.org
#
# --------------------------------------
# LUFA Project Makefile.
# --------------------------------------
# Run "make help" for target help.
MCU = at90usb1287
ARCH = AVR8
BOARD = USBKEY
F_CPU = 8000000
F_USB = $(F_CPU)
OPTIMIZATION = s
TARGET = BootloaderCDC
SRC = $(TARGET).c Descriptors.c BootloaderAPI.c BootloaderAPITable.S $(LUFA_SRC_USB)
LUFA_PATH = ../../LUFA
CC_FLAGS = -DUSE_LUFA_CONFIG_HEADER -IConfig/ -DBOOT_START_ADDR=$(BOOT_START_OFFSET)
LD_FLAGS = -Wl,--section-start=.text=$(BOOT_START_OFFSET) $(BOOT_API_LD_FLAGS)
# Flash size and bootloader section sizes of the target, in KB. These must
# match the target's total FLASH size and the bootloader size set in the
# device's fuses.
FLASH_SIZE_KB = 128
BOOT_SECTION_SIZE_KB = 8
# Bootloader address calculation formulas
# Do not modify these macros, but rather modify the dependent values above.
CALC_ADDRESS_IN_HEX = $(shell printf "0x%X" $$(( $(1) )) )
BOOT_START_OFFSET = $(call CALC_ADDRESS_IN_HEX, ($(FLASH_SIZE_KB) - $(BOOT_SECTION_SIZE_KB)) * 1024 )
BOOT_SEC_OFFSET = $(call CALC_ADDRESS_IN_HEX, ($(FLASH_SIZE_KB) * 1024) - ($(strip $(1))) )
# Bootloader linker section flags for relocating the API table sections to
# known FLASH addresses - these should not normally be user-edited.
BOOT_SECTION_LD_FLAG = -Wl,--section-start=$(strip $(1))=$(call BOOT_SEC_OFFSET, $(3)) -Wl,--undefined=$(strip $(2))
BOOT_API_LD_FLAGS = $(call BOOT_SECTION_LD_FLAG, .apitable_trampolines, BootloaderAPI_Trampolines, 96)
BOOT_API_LD_FLAGS += $(call BOOT_SECTION_LD_FLAG, .apitable_jumptable, BootloaderAPI_JumpTable, 32)
BOOT_API_LD_FLAGS += $(call BOOT_SECTION_LD_FLAG, .apitable_signatures, BootloaderAPI_Signatures, 8)
# Default target
all:
# Include LUFA-specific DMBS extension modules
DMBS_LUFA_PATH ?= $(LUFA_PATH)/Build/LUFA
include $(DMBS_LUFA_PATH)/lufa-sources.mk
include $(DMBS_LUFA_PATH)/lufa-gcc.mk
# Include common DMBS build system modules
DMBS_PATH ?= $(LUFA_PATH)/Build/DMBS/DMBS
include $(DMBS_PATH)/core.mk
include $(DMBS_PATH)/cppcheck.mk
include $(DMBS_PATH)/doxygen.mk
include $(DMBS_PATH)/dfu.mk
include $(DMBS_PATH)/gcc.mk
include $(DMBS_PATH)/hid.mk
include $(DMBS_PATH)/avrdude.mk
include $(DMBS_PATH)/atprogram.mk

@ -0,0 +1,76 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2017.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2017 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 disclaims 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
*
* Bootloader user application API functions.
*/
#include "BootloaderAPI.h"
void BootloaderAPI_ErasePage(const uint32_t Address)
{
boot_page_erase_safe(Address);
boot_spm_busy_wait();
boot_rww_enable();
}
void BootloaderAPI_WritePage(const uint32_t Address)
{
boot_page_write_safe(Address);
boot_spm_busy_wait();
boot_rww_enable();
}
void BootloaderAPI_FillWord(const uint32_t Address, const uint16_t Word)
{
boot_page_fill_safe(Address, Word);
}
uint8_t BootloaderAPI_ReadSignature(const uint16_t Address)
{
return boot_signature_byte_get(Address);
}
uint8_t BootloaderAPI_ReadFuse(const uint16_t Address)
{
return boot_lock_fuse_bits_get(Address);
}
uint8_t BootloaderAPI_ReadLock(void)
{
return boot_lock_fuse_bits_get(GET_LOCK_BITS);
}
void BootloaderAPI_WriteLock(const uint8_t LockBits)
{
boot_lock_bits_set_safe(LockBits);
}

@ -0,0 +1,58 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2017.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2017 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 disclaims 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 BootloaderAPI.c.
*/
#ifndef _BOOTLOADER_API_H_
#define _BOOTLOADER_API_H_
/* Includes: */
#include <avr/io.h>
#include <avr/boot.h>
#include <stdbool.h>
#include <LUFA/Common/Common.h>
#include "Config/AppConfig.h"
/* Function Prototypes: */
void BootloaderAPI_ErasePage(const uint32_t Address);
void BootloaderAPI_WritePage(const uint32_t Address);
void BootloaderAPI_FillWord(const uint32_t Address, const uint16_t Word);
uint8_t BootloaderAPI_ReadSignature(const uint16_t Address);
uint8_t BootloaderAPI_ReadFuse(const uint16_t Address);
uint8_t BootloaderAPI_ReadLock(void);
void BootloaderAPI_WriteLock(const uint8_t LockBits);
#endif

@ -0,0 +1,91 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2017.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2017 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 disclaims 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.
*/
; Trampolines to actual API implementations if the target address is outside the
; range of a rjmp instruction (can happen with large bootloader sections)
.section .apitable_trampolines, "ax"
.global BootloaderAPI_Trampolines
BootloaderAPI_Trampolines:
BootloaderAPI_ErasePage_Trampoline:
jmp BootloaderAPI_ErasePage
BootloaderAPI_WritePage_Trampoline:
jmp BootloaderAPI_WritePage
BootloaderAPI_FillWord_Trampoline:
jmp BootloaderAPI_FillWord
BootloaderAPI_ReadSignature_Trampoline:
jmp BootloaderAPI_ReadSignature
BootloaderAPI_ReadFuse_Trampoline:
jmp BootloaderAPI_ReadFuse
BootloaderAPI_ReadLock_Trampoline:
jmp BootloaderAPI_ReadLock
BootloaderAPI_WriteLock_Trampoline:
jmp BootloaderAPI_WriteLock
BootloaderAPI_UNUSED1:
ret
BootloaderAPI_UNUSED2:
ret
BootloaderAPI_UNUSED3:
ret
BootloaderAPI_UNUSED4:
ret
BootloaderAPI_UNUSED5:
ret
; API function jump table
.section .apitable_jumptable, "ax"
.global BootloaderAPI_JumpTable
BootloaderAPI_JumpTable:
rjmp BootloaderAPI_ErasePage_Trampoline
rjmp BootloaderAPI_WritePage_Trampoline
rjmp BootloaderAPI_FillWord_Trampoline
rjmp BootloaderAPI_ReadSignature_Trampoline
rjmp BootloaderAPI_ReadFuse_Trampoline
rjmp BootloaderAPI_ReadLock_Trampoline
rjmp BootloaderAPI_WriteLock_Trampoline
rjmp BootloaderAPI_UNUSED1 ; UNUSED ENTRY 1
rjmp BootloaderAPI_UNUSED2 ; UNUSED ENTRY 2
rjmp BootloaderAPI_UNUSED3 ; UNUSED ENTRY 3
rjmp BootloaderAPI_UNUSED4 ; UNUSED ENTRY 4
rjmp BootloaderAPI_UNUSED5 ; UNUSED ENTRY 5
; Bootloader table signatures and information
.section .apitable_signatures, "ax"
.global BootloaderAPI_Signatures
BootloaderAPI_Signatures:
.long BOOT_START_ADDR ; Start address of the bootloader
.word 0xDF10 ; Signature for the DFU class bootloader, V1
.word 0xDCFB ; Signature for a LUFA class bootloader

@ -0,0 +1,891 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2017.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2017 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 disclaims 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 "BootloaderDFU.h"
/** Flag to indicate if the bootloader is currently running in secure mode, disallowing memory operations
* other than erase. This is initially set to the value set by SECURE_MODE, and cleared by the bootloader
* once a memory erase has completed in a bootloader session.
*/
static bool IsSecure = SECURE_MODE;
/** 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).
*/
static 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.
*/
static bool WaitForExit = false;
/** Current DFU state machine state, one of the values in the DFU_State_t enum. */
static 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.
*/
static uint8_t DFU_Status = OK;
/** Data containing the DFU command sent from the host. */
static 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.
*/
static 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.
*/
static 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.
*/
static 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).
*/
static uint16_t StartAddr = 0x0000;
/** Memory end address, indicating the end address to read from/write to in the memory being addressed (either FLASH
* of EEPROM depending on the issued command from the host).
*/
static uint16_t EndAddr = 0x0000;
/** Magic lock for forced application start. If the HWBE fuse is programmed and BOOTRST is unprogrammed, the bootloader
* will start if the /HWB line of the AVR is held low and the system is reset. However, if the /HWB line is still held
* low when the application attempts to start via a watchdog reset, the bootloader will re-start. If set to the value
* \ref MAGIC_BOOT_KEY the special init function \ref Application_Jump_Check() will force the application to start.
*/
uint16_t MagicBootKey ATTR_NO_INIT;
/** Special startup routine to check if the bootloader was started via a watchdog reset, and if the magic application
* start key has been loaded into \ref MagicBootKey. If the bootloader started via the watchdog and the key is valid,
* this will force the user application to start via a software jump.
*/
void Application_Jump_Check(void)
{
bool JumpToApplication = false;
#if (BOARD == BOARD_LEONARDO)
/* Enable pull-up on the IO13 pin so we can use it to select the mode */
PORTC |= (1 << 7);
Delay_MS(10);
/* If IO13 is not jumpered to ground, start the user application instead */
JumpToApplication = ((PINC & (1 << 7)) != 0);
/* Disable pull-up after the check has completed */
PORTC &= ~(1 << 7);
#elif ((BOARD == BOARD_XPLAIN) || (BOARD == BOARD_XPLAIN_REV1))
/* Disable JTAG debugging */
JTAG_DISABLE();
/* Enable pull-up on the JTAG TCK pin so we can use it to select the mode */
PORTF |= (1 << 4);
Delay_MS(10);
/* If the TCK pin is not jumpered to ground, start the user application instead */
JumpToApplication = ((PINF & (1 << 4)) != 0);
/* Re-enable JTAG debugging */
JTAG_ENABLE();
#else
/* Check if the device's BOOTRST fuse is set */
if (boot_lock_fuse_bits_get(GET_HIGH_FUSE_BITS) & FUSE_BOOTRST)
{
/* If the reset source was not an external reset or the key is correct, clear it and jump to the application */
//if (!(MCUSR & (1 << EXTRF)) || (MagicBootKey == MAGIC_BOOT_KEY))
// JumpToApplication = true;
/* Clear reset source */
MCUSR &= ~(1 << EXTRF);
}
else
{
/* If the reset source was the bootloader and the key is correct, clear it and jump to the application;
* this can happen in the HWBE fuse is set, and the HBE pin is low during the watchdog reset */
//if ((MCUSR & (1 << WDRF)) && (MagicBootKey == MAGIC_BOOT_KEY))
// JumpToApplication = true;
/* Clear reset source */
MCUSR &= ~(1 << WDRF);
}
#endif
/* Don't run the user application if the reset vector is blank (no app loaded) */
bool ApplicationValid = (pgm_read_word_near(0) != 0xFFFF);
/* If a request has been made to jump to the user application, honor it */
if (JumpToApplication && ApplicationValid)
{
/* Turn off the watchdog */
MCUSR &= ~(1 << WDRF);
wdt_disable();
/* Clear the boot key and jump to the user application */
MagicBootKey = 0;
// cppcheck-suppress constStatement
((void (*)(void))0x0000)();
}
}
/** 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();
/* Turn on first LED on the board to indicate that the bootloader has started */
LEDs_SetAllLEDs(LEDS_LED1 | LEDS_LED2);
/* Enable global interrupts so that the USB stack can function */
GlobalInterruptEnable();
#if (BOARD == BOARD_QMK)
uint16_t keypress = 0;
#endif
/* Run the USB management task while the bootloader is supposed to be running */
while (RunBootloader || WaitForExit) {
USB_USBTask();
#if (BOARD == BOARD_QMK)
bool pressed = (PIN(QMK_ESC_ROW) & NUM(QMK_ESC_ROW));
if ((DFU_State == dfuIDLE) && (keypress > 5000) && pressed) {
break;
}
if (pressed) {
keypress++;
} else {
keypress = 0;
}
#endif
}
/* 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. */
static 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);
#if (BOARD == BOARD_QMK)
// column setup
DDR(QMK_ESC_COL) |= NUM(QMK_ESC_COL);
PORT(QMK_ESC_COL) |= NUM(QMK_ESC_COL);
// row setup
DDR(QMK_ESC_ROW) |= NUM(QMK_ESC_ROW);
#endif
/* Initialize the USB and other board hardware drivers */
USB_Init();
LEDs_Init();
/* Bootloader active LED toggle timer initialization */
TIMSK1 = (1 << TOIE1);
TCCR1B = ((1 << CS11) | (1 << CS10));
}
/** Resets all configured hardware required for the bootloader back to their original states. */
static void ResetHardware(void)
{
/* Shut down the USB and other board hardware drivers */
USB_Disable();
LEDs_Disable();
/* Disable Bootloader active LED toggle timer */
TIMSK1 = 0;
TCCR1B = 0;
/* Relocate the interrupt vector table back to the application section */
MCUCR = (1 << IVCE);
MCUCR = 0;
#if (BOARD == BOARD_QMK)
DDR(QMK_ESC_COL) = PORT(QMK_ESC_COL) = DDR(QMK_ESC_ROW) = PORT(QMK_ESC_ROW) = 0;
#endif
}
/** ISR to periodically toggle the LEDs on the board to indicate that the bootloader is active. */
ISR(TIMER1_OVF_vect, ISR_BLOCK)
{
LEDs_ToggleLEDs(LEDS_LED1 | LEDS_LED2);
}
/** 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 DFU interface */
if ((USB_ControlRequest.bmRequestType & (CONTROL_REQTYPE_TYPE | CONTROL_REQTYPE_RECIPIENT)) !=
(REQTYPE_CLASS | REQREC_INTERFACE))
{
return;
}
/* Activity - toggle indicator LEDs */
LEDs_ToggleLEDs(LEDS_LED1 | LEDS_LED2);
/* Get the size of the command and data from the wLength value */
SentCommand.DataSize = USB_ControlRequest.wLength;
switch (USB_ControlRequest.bRequest)
{
case DFU_REQ_DNLOAD:
Endpoint_ClearSETUP();
/* Check if bootloader is waiting to terminate */
if (WaitForExit)
{
/* Bootloader is terminating - process last received command */
ProcessBootloaderCommand();
/* 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_8();
/* 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_8();
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_16_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_update_byte((uint8_t*)StartAddr, Endpoint_Read_8());
/* Adjust counters */
StartAddr++;
}
}
/* Throw away the currently unused DFU file suffix */
DiscardFillerBytes(DFU_FILE_SUFFIX_SIZE);
}
}
Endpoint_ClearOUT();
Endpoint_ClearStatusStage();
break;
case DFU_REQ_UPLOAD:
Endpoint_ClearSETUP();
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_16_LE(StartAddr);
}
else
{
/* Idle state upload - send response to last issued command */
Endpoint_Write_8(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_16_LE(pgm_read_word_far(CurrFlashAddress.Long));
#else
Endpoint_Write_16_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_8(eeprom_read_byte((uint8_t*)StartAddr));
/* Adjust counters */
StartAddr++;
}
}
/* Return to idle state */
DFU_State = dfuIDLE;
}
Endpoint_ClearIN();
Endpoint_ClearStatusStage();
break;
case DFU_REQ_GETSTATUS:
Endpoint_ClearSETUP();
while (!(Endpoint_IsINReady()))
{
if (USB_DeviceState == DEVICE_STATE_Unattached)
return;
}
/* Write 8-bit status value */
Endpoint_Write_8(DFU_Status);
/* Write 24-bit poll timeout value */
Endpoint_Write_8(0);
Endpoint_Write_16_LE(0);
/* Write 8-bit state value */
Endpoint_Write_8(DFU_State);
/* Write 8-bit state string ID number */
Endpoint_Write_8(0);
Endpoint_ClearIN();
Endpoint_ClearStatusStage();
break;
case DFU_REQ_CLRSTATUS:
Endpoint_ClearSETUP();
/* Reset the status value variable to the default OK status */
DFU_Status = OK;
Endpoint_ClearStatusStage();
break;
case DFU_REQ_GETSTATE:
Endpoint_ClearSETUP();
while (!(Endpoint_IsINReady()))
{
if (USB_DeviceState == DEVICE_STATE_Unattached)
return;
}
/* Write the current device state to the endpoint */
Endpoint_Write_8(DFU_State);
Endpoint_ClearIN();
Endpoint_ClearStatusStage();
break;
case DFU_REQ_ABORT:
Endpoint_ClearSETUP();
/* 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_8();
}
}
}
/** 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 < (uint32_t)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
{
/* Unlock the forced application start mode of the bootloader if it is restarted */
MagicBootKey = MAGIC_BOOT_KEY;
/* 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 if a valid application has been loaded */
if (pgm_read_word_near(0) == 0xFFFF)
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 < (uint32_t)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[4] = {0x58, AVR_SIGNATURE_1, AVR_SIGNATURE_2, AVR_SIGNATURE_3};
uint8_t DataIndexToRead = SentCommand.Data[1];
bool ReadAddressInvalid = false;
if (IS_ONEBYTE_COMMAND(SentCommand.Data, 0x00)) // Read bootloader info
{
if (DataIndexToRead < 3)
ResponseByte = BootloaderInfo[DataIndexToRead];
else
ReadAddressInvalid = true;
}
else if (IS_ONEBYTE_COMMAND(SentCommand.Data, 0x01)) // Read signature byte
{
switch (DataIndexToRead)
{
case 0x30:
ResponseByte = SignatureInfo[0];
break;
case 0x31:
ResponseByte = SignatureInfo[1];
break;
case 0x60:
ResponseByte = SignatureInfo[2];
break;
case 0x61:
ResponseByte = SignatureInfo[3];
break;
default:
ReadAddressInvalid = true;
break;
}
}
if (ReadAddressInvalid)
{
/* Set the state and status variables to indicate the error */
DFU_State = dfuERROR;
DFU_Status = errADDRESS;
}
}

@ -0,0 +1,216 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2017.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2017 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 disclaims 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 BootloaderDFU.c.
*/
#ifndef _BOOTLOADER_H_
#define _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 <util/delay.h>
#include <stdbool.h>
#include "Descriptors.h"
#include "BootloaderAPI.h"
#include "Config/AppConfig.h"
#include <LUFA/Drivers/USB/USB.h>
#include <LUFA/Drivers/Board/LEDs.h>
#include <LUFA/Platform/Platform.h>
/* Preprocessor Checks: */
#if !defined(__OPTIMIZE_SIZE__)
#error This bootloader requires that it be optimized for size, not speed, to fit into the target device. Change optimization settings and try again.
#endif
/* Macros: */
/** Major bootloader version number. */
#define BOOTLOADER_VERSION_MINOR 2
/** Minor bootloader version number. */
#define BOOTLOADER_VERSION_REV 0
/** Magic bootloader key to unlock forced application start mode. */
#define MAGIC_BOOT_KEY 0xDC42
/** 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_REQ_DETATCH 0x00
/** DFU class command request to send data from the host to the bootloader. */
#define DFU_REQ_DNLOAD 0x01
/** DFU class command request to send data from the bootloader to the host. */
#define DFU_REQ_UPLOAD 0x02
/** DFU class command request to get the current DFU status and state from the bootloader. */
#define DFU_REQ_GETSTATUS 0x03
/** DFU class command request to reset the current DFU status and state variables to their defaults. */
#define DFU_REQ_CLRSTATUS 0x04
/** DFU class command request to get the current DFU state of the bootloader. */
#define DFU_REQ_GETSTATE 0x05
/** DFU class command request to abort the current multi-request transfer and return to the dfuIDLE state. */
#define DFU_REQ_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 \c 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: */
static void SetupHardware(void);
static void ResetHardware(void);
void EVENT_USB_Device_ControlRequest(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
void Application_Jump_Check(void) ATTR_INIT_SECTION(3);
#endif

@ -0,0 +1,235 @@
/** \file
*
* This file contains special DoxyGen information for the generation of the main page and other special
* documentation pages. It is not a project source file.
*/
/** \mainpage DFU Class USB AVR Bootloader
*
* \section Sec_Compat Demo Compatibility:
*
* The following list indicates what microcontrollers are compatible with this demo.
*
* \li Series 7 USB AVRs (AT90USBxxx7)
* \li Series 6 USB AVRs (AT90USBxxx6)
* \li Series 4 USB AVRs (ATMEGAxxU4) - <i>See \ref SSec_Aux_Space</i>
* \li Series 2 USB AVRs (AT90USBxx2, ATMEGAxxU2) - <i>See \ref SSec_Aux_Space</i>
*
* \section Sec_Info USB Information:
*
* The following table gives a rundown of the USB utilization of this demo.
*
* <table>
* <tr>
* <td><b>USB Mode:</b></td>
* <td>Device</td>
* </tr>
* <tr>
* <td><b>USB Class:</b></td>
* <td>Device Firmware Update Class (DFU)</td>
* </tr>
* <tr>
* <td><b>USB Subclass:</b></td>
* <td>None</td>
* </tr>
* <tr>
* <td><b>Relevant Standards:</b></td>
* <td>USBIF DFU Class Standard, Atmel USB Bootloader Datasheet</td>
* </tr>
* <tr>
* <td><b>Supported USB Speeds:</b></td>
* <td>Low Speed Mode \n
* Full Speed Mode</td>
* </tr>
* </table>
*
* \section Sec_Description Project Description:
*
* This bootloader enumerates to the host as a DFU Class device, allowing for DFU-compatible programming
* software to load firmware onto the AVR.
*
* Out of the box this bootloader builds for the AT90USB1287 with an 8KB bootloader section size, and will fit
* into 4KB of bootloader space. If you wish to alter this size and/or change the AVR model, you will need to
* edit the MCU, FLASH_SIZE_KB and BOOT_SECTION_SIZE_KB values in the accompanying makefile.
*
* When the bootloader is running, the board's LED(s) will flash at regular intervals to distinguish the
* bootloader from the normal user application.
*
* \section Sec_Running Running the Bootloader
*
* On the USB AVR8 devices, setting the \c HWBE device fuse will cause the bootloader to run if the \c HWB pin of
* the AVR is grounded when the device is reset.
*
* The are two behaviours of this bootloader, depending on the device's fuses:
*
* <b>If the device's BOOTRST fuse is set</b>, the bootloader will run any time the system is reset from
* the external reset pin, unless no valid user application has been loaded. To initiate the bootloader, the
* device's external reset pin should be grounded momentarily.
*
* <b>If the device's BOOTRST fuse is not set</b>, the bootloader will run only if initiated via a software
* jump, or if the \c HWB pin was low during the last device reset (if the \c HWBE fuse is set).
*
* For board specific exceptions to the above, see below.
*
* \subsection SSec_XPLAIN Atmel Xplain Board
* Ground the USB AVR JTAG's \c TCK pin to ground when powering on the board to start the bootloader. This assumes the
* \c HWBE fuse is cleared and the \c BOOTRST fuse is set as the HWBE pin is not user accessible on this board.
*
* \subsection SSec_Leonardo Arduino Leonardo Board
* Ground \c IO13 when powering the board to start the bootloader. This assumes the \c HWBE fuse is cleared and the
* \c BOOTRST fuse is set as the HWBE pin is not user accessible on this board.
*
* \section Sec_Installation Driver Installation
*
* This bootloader is designed to be compatible with Atmel's provided Windows DFU class drivers. You will need to
* install Atmel's DFU drivers prior to using this bootloader on Windows platforms. If you are using a 64 bit Windows
* OS, you will need to either disable the driver signing requirement (see online tutorials for details) or use a
* digitally signed version of the official Atmel driver provided by a third party AVR user at
* <a>http://www.avrfreaks.net/index.php?module=Freaks%20Academy&func=viewItem&item_id=2196&item_type=project</a>.
*
* \note This device spoofs Atmel's DFU Bootloader USB VID and PID so that the Atmel DFU bootloader
* drivers included with FLIP will work. If you do not wish to use Atmel's ID codes, please
* manually change them in Descriptors.c and alter your driver's INF file accordingly.
*
* \section Sec_HostApp Host Controller Application
*
* This bootloader is compatible with Atmel's FLIP utility on Windows machines, and dfu-programmer on Linux machines.
*
* \subsection SSec_FLIP FLIP (Windows)
*
* FLIP (Flexible In-System Programmer) is a utility written by Atmel, and distributed for free on the Atmel website.
* The FLIP utility is designed to assist in the bootloader programming of a range of Atmel devices, through several
* popular physical interfaces including USB. It is written in Java, however makes use of native extensions for USB
* support and thus is only offered on Windows.
*
* To program a device using FLIP, refer to the Atmel FLIP documentation.
*
* \subsection SSec_DFUProgrammer dfu-programmer (Linux)
*
* dfu-programmer is an open-source command line solution for the bootloader programming of Atmel devices through a
* USB connection, using the DFU protocol, available for download at <a>http://sourceforge.net/projects/dfu-programmer/</a>.
*
* The following example loads a HEX file into the AVR's FLASH memory using dfu-programmer:
* \code
* dfu-programmer at90usb1287 erase flash Mouse.hex
* \endcode
*
* \section Sec_API User Application API
*
* Several user application functions for FLASH and other special memory area manipulations are exposed by the bootloader,
* allowing the user application to call into the bootloader at runtime to read and write FLASH data.
*
* \warning The APIs exposed by the DFU class bootloader are \b NOT compatible with the API exposed by the official Atmel DFU bootloader.
*
* By default, the bootloader API jump table is located 32 bytes from the end of the device's FLASH memory, and follows the
* following layout:
*
* \code
* #define BOOTLOADER_API_TABLE_SIZE 32
* #define BOOTLOADER_API_TABLE_START ((FLASHEND + 1UL) - BOOTLOADER_API_TABLE_SIZE)
* #define BOOTLOADER_API_CALL(Index) (void*)((BOOTLOADER_API_TABLE_START + (Index * 2)) / 2)
*
* void (*BootloaderAPI_ErasePage)(uint32_t Address) = BOOTLOADER_API_CALL(0);
* void (*BootloaderAPI_WritePage)(uint32_t Address) = BOOTLOADER_API_CALL(1);
* void (*BootloaderAPI_FillWord)(uint32_t Address, uint16_t Word) = BOOTLOADER_API_CALL(2);
* uint8_t (*BootloaderAPI_ReadSignature)(uint16_t Address) = BOOTLOADER_API_CALL(3);
* uint8_t (*BootloaderAPI_ReadFuse)(uint16_t Address) = BOOTLOADER_API_CALL(4);
* uint8_t (*BootloaderAPI_ReadLock)(void) = BOOTLOADER_API_CALL(5);
* void (*BootloaderAPI_WriteLock)(uint8_t LockBits) = BOOTLOADER_API_CALL(6);
*
* #define BOOTLOADER_MAGIC_SIGNATURE_START (BOOTLOADER_API_TABLE_START + (BOOTLOADER_API_TABLE_SIZE - 2))
* #define BOOTLOADER_MAGIC_SIGNATURE 0xDCFB
*
* #define BOOTLOADER_CLASS_SIGNATURE_START (BOOTLOADER_API_TABLE_START + (BOOTLOADER_API_TABLE_SIZE - 4))
* #define BOOTLOADER_DFU_SIGNATURE 0xDF10
*
* #define BOOTLOADER_ADDRESS_START (BOOTLOADER_API_TABLE_START + (BOOTLOADER_API_TABLE_SIZE - 8))
* #define BOOTLOADER_ADDRESS_LENGTH 4
* \endcode
*
* From the application the API support of the bootloader can be detected by reading the FLASH memory bytes located at address
* \c BOOTLOADER_MAGIC_SIGNATURE_START and comparing them to the value \c BOOTLOADER_MAGIC_SIGNATURE. The class of bootloader
* can be determined by reading the FLASH memory bytes located at address \c BOOTLOADER_CLASS_SIGNATURE_START and comparing them
* to the value \c BOOTLOADER_DFU_SIGNATURE. The start address of the bootloader can be retrieved by reading the bytes of FLASH
* memory starting from address \c BOOTLOADER_ADDRESS_START.
*
* \subsection SSec_API_MemLayout Device Memory Map
* The following illustration indicates the final memory map of the device when loaded with the bootloader.
*
* \verbatim
* +----------------------------+ 0x0000
* | |
* | |
* | |
* | |
* | |
* | |
* | |
* | |
* | User Application |
* | |
* | |
* | |
* | |
* | |
* | |
* | |
* | |
* +----------------------------+ FLASHEND - BOOT_AUX_SECTION_SIZE
* | Booloader Start Trampoline |
* | (Not User App. Accessible) |
* +----------------------------+ FLASHEND - (BOOT_AUX_SECTION_SIZE - 4)
* | |
* | Auxillery Bootloader |
* | Space for Smaller Devices |
* | (Not User App. Accessible) |
* | |
* +----------------------------+ FLASHEND - BOOT_SECTION_SIZE
* | |
* | Bootloader Application |
* | (Not User App. Accessible) |
* | |
* +----------------------------+ FLASHEND - 96
* | API Table Trampolines |
* | (Not User App. Accessible) |
* +----------------------------+ FLASHEND - 32
* | Bootloader API Table |
* | (User App. Accessible) |
* +----------------------------+ FLASHEND - 8
* | Bootloader ID Constants |
* | (User App. Accessible) |
* +----------------------------+ FLASHEND
* \endverbatim
*
* \subsection SSec_Aux_Space Auxiliary Bootloader Section
* To make the bootloader function on smaller devices (those with a physical
* bootloader section of smaller than 6KB)
*
* \section Sec_KnownIssues Known Issues:
*
* \par On Linux machines, the DFU bootloader is inaccessible.
* On many Linux systems, non-root users do not have automatic access to newly
* inserted DFU devices. Root privileges or a UDEV rule is required to gain
* access.
* See <a href=https://groups.google.com/d/msg/lufa-support/CP9cy2bc8yo/kBqsOu-RBeMJ>here</a> for resolution steps.
*
* \section Sec_Options Project Options
*
* The following defines can be found in this demo, which can control the demo behaviour when defined, or changed in value.
*
* <table>
* <tr>
* <th><b>Define Name:</b></th>
* <th><b>Location:</b></th>
* <th><b>Description:</b></th>
* </tr>
* <tr>
* <td>SECURE_MODE</td>
* <td>AppConfig.h</td>
* <td>If defined to \c true, the bootloader will not accept any memory commands other than a chip erase on start-up, until an
* erase has been performed. This can be used in conjunction with the AVR's lockbits to prevent the AVRs firmware from
* being dumped by unauthorized persons. When false, all memory operations are allowed at any time.</td>
* </tr>
* </table>
*/

@ -0,0 +1,48 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2017.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2017 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 disclaims 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
* \brief Application Configuration Header File
*
* This is a header file which is be used to configure some of
* the application's compile time options, as an alternative to
* specifying the compile time constants supplied through a
* makefile or build system.
*
* For information on what each token does, refer to the
* \ref Sec_Options section of the application documentation.
*/
#ifndef _APP_CONFIG_H_
#define _APP_CONFIG_H_
#define SECURE_MODE false
#endif

@ -0,0 +1,93 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2017.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2017 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 disclaims 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
* \brief LUFA Library Configuration Header File
*
* This header file is used to configure LUFA's compile time options,
* as an alternative to the compile time constants supplied through
* a makefile.
*
* For information on what each token does, refer to the LUFA
* manual section "Summary of Compile Tokens".
*/
#ifndef _LUFA_CONFIG_H_
#define _LUFA_CONFIG_H_
#if (ARCH == ARCH_AVR8)
/* Non-USB Related Configuration Tokens: */
// #define DISABLE_TERMINAL_CODES
/* USB Class Driver Related Tokens: */
// #define HID_HOST_BOOT_PROTOCOL_ONLY
// #define HID_STATETABLE_STACK_DEPTH {Insert Value Here}
// #define HID_USAGE_STACK_DEPTH {Insert Value Here}
// #define HID_MAX_COLLECTIONS {Insert Value Here}
// #define HID_MAX_REPORTITEMS {Insert Value Here}
// #define HID_MAX_REPORT_IDS {Insert Value Here}
// #define NO_CLASS_DRIVER_AUTOFLUSH
/* General USB Driver Related Tokens: */
// #define ORDERED_EP_CONFIG
#define USE_STATIC_OPTIONS (USB_DEVICE_OPT_FULLSPEED | USB_OPT_REG_ENABLED | USB_OPT_AUTO_PLL)
#define USB_DEVICE_ONLY
// #define USB_HOST_ONLY
// #define USB_STREAM_TIMEOUT_MS {Insert Value Here}
// #define NO_LIMITED_CONTROLLER_CONNECT
#define NO_SOF_EVENTS
/* USB Device Mode Driver Related Tokens: */
#define USE_RAM_DESCRIPTORS
// #define USE_FLASH_DESCRIPTORS
// #define USE_EEPROM_DESCRIPTORS
#define NO_INTERNAL_SERIAL
#define FIXED_CONTROL_ENDPOINT_SIZE 32
#define DEVICE_STATE_AS_GPIOR 0
#define FIXED_NUM_CONFIGURATIONS 1
#define CONTROL_ONLY_DEVICE
// #define INTERRUPT_CONTROL_ENDPOINT
#define NO_DEVICE_REMOTE_WAKEUP
#define NO_DEVICE_SELF_POWER
/* USB Host Mode Driver Related Tokens: */
// #define HOST_STATE_AS_GPIOR {Insert Value Here}
// #define USB_HOST_TIMEOUT_MS {Insert Value Here}
// #define HOST_DEVICE_SETTLE_DELAY_MS {Insert Value Here}
// #define NO_AUTO_VBUS_MANAGEMENT
// #define INVERTED_VBUS_ENABLE_LINE
#else
#error Unsupported architecture for this LUFA configuration file.
#endif
#endif

@ -0,0 +1,185 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2017.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2017 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 disclaims 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(1,1,0),
.Class = USB_CSCP_NoDeviceClass,
.SubClass = USB_CSCP_NoDeviceSubclass,
.Protocol = USB_CSCP_NoDeviceProtocol,
.Endpoint0Size = FIXED_CONTROL_ENDPOINT_SIZE,
.VendorID = 0x03EB,
.ProductID = PRODUCT_ID_CODE,
.ReleaseNumber = VERSION_BCD(0,0,0),
.ManufacturerStrIndex = STRING_ID_Manufacturer,
.ProductStrIndex = STRING_ID_Product,
.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 = 1,
.ConfigurationNumber = 1,
.ConfigurationStrIndex = NO_DESCRIPTOR,
.ConfigAttributes = USB_CONFIG_ATTR_RESERVED,
.MaxPowerConsumption = USB_CONFIG_POWER_MA(100)
},
.DFU_Interface =
{
.Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},
.InterfaceNumber = INTERFACE_ID_DFU,
.AlternateSetting = 0,
.TotalEndpoints = 0,
.Class = 0xFE,
.SubClass = 0x01,
.Protocol = 0x02,
.InterfaceStrIndex = NO_DESCRIPTOR
},
.DFU_Functional =
{
.Header = {.Size = sizeof(USB_Descriptor_DFU_Functional_t), .Type = DTYPE_DFUFunctional},
.Attributes = (ATTR_CAN_UPLOAD | ATTR_CAN_DOWNLOAD),
.DetachTimeout = 0x0000,
.TransferSize = 0x0C00,
.DFUSpecification = VERSION_BCD(1,1,0)
}
};
/** 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 = USB_STRING_DESCRIPTOR_ARRAY(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.
*/
const USB_Descriptor_String_t ManufacturerString = USB_STRING_DESCRIPTOR(L"QMK");
/** 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 = USB_STRING_DESCRIPTOR(L"KB");
/** 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 uint16_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 == STRING_ID_Language)
{
Address = &LanguageString;
Size = LanguageString.Header.Size;
}
else if (DescriptorNumber == STRING_ID_Manufacturer)
{
Address = &ManufacturerString;
Size = ManufacturerString.Header.Size;
}
else if (DescriptorNumber == STRING_ID_Product)
{
Address = &ProductString;
Size = ProductString.Header.Size;
}
break;
}
*DescriptorAddress = Address;
return Size;
}

@ -0,0 +1,194 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2017.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2017 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 disclaims 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>
#include "Config/AppConfig.h"
/* 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_AT90USB647__)
#define PRODUCT_ID_CODE 0x2FF9
#define AVR_SIGNATURE_1 0x1E
#define AVR_SIGNATURE_2 0x96
#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_AT90USB646__)
#define PRODUCT_ID_CODE 0x2FF9
#define AVR_SIGNATURE_1 0x1E
#define AVR_SIGNATURE_2 0x96
#define AVR_SIGNATURE_3 0x82
#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_ATmega16U4__)
#define PRODUCT_ID_CODE 0x2FF3
#define AVR_SIGNATURE_1 0x1E
#define AVR_SIGNATURE_2 0x94
#define AVR_SIGNATURE_3 0x88
#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_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_ATmega8U2__)
#define PRODUCT_ID_CODE 0x2FEE
#define AVR_SIGNATURE_1 0x1E
#define AVR_SIGNATURE_2 0x93
#define AVR_SIGNATURE_3 0x89
#elif defined(__AVR_AT90USB82__)
#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_Descriptor_DFU_Functional_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;
// DFU Interface
USB_Descriptor_Interface_t DFU_Interface;
USB_Descriptor_DFU_Functional_t DFU_Functional;
} USB_Descriptor_Configuration_t;
/** Enum for the device interface descriptor IDs within the device. Each interface descriptor
* should have a unique ID index associated with it, which can be used to refer to the
* interface from other descriptors.
*/
enum InterfaceDescriptors_t
{
INTERFACE_ID_DFU = 0, /**< DFU interface descriptor ID */
};
/** Enum for the device string descriptor IDs within the device. Each string descriptor should
* have a unique ID index associated with it, which can be used to refer to the string from
* other descriptors.
*/
enum StringDescriptors_t
{
STRING_ID_Language = 0, /**< Supported Languages string descriptor ID (must be zero) */
STRING_ID_Manufacturer = 1, /**< Manufacturer string ID */
STRING_ID_Product = 2, /**< Product string ID */
};
/* Function Prototypes: */
uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue,
const uint16_t wIndex,
const void** const DescriptorAddress)
ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(3);
#endif

@ -0,0 +1,156 @@
<asf xmlversion="1.0">
<project caption="DFU Bootloader - 128KB FLASH / 4KB Boot - AVR8 Architecture" id="lufa.bootloaders.dfu.avr8.128_4" force-caption="true" workspace-name="lufa_dfu_128kb_4kb_">
<require idref="lufa.bootloaders.dfu"/>
<require idref="lufa.boards.dummy.avr8"/>
<generator value="as5_8"/>
<device-support value="at90usb1287"/>
<config name="lufa.drivers.board.name" value="none"/>
<config name="config.compiler.optimization.level" value="size"/>
<build type="define" name="F_CPU" value="16000000UL"/>
<build type="define" name="F_USB" value="16000000UL"/>
<build type="define" name="BOOT_START_ADDR" value="0x1F000"/>
<build type="linker-config" subtype="flags" value="--section-start=.text=0x1F000"/>
<build type="linker-config" subtype="flags" value="--section-start=.apitable_trampolines=0x1FFA0"/>
<build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_Trampolines"/>
<build type="linker-config" subtype="flags" value="--section-start=.apitable_jumptable=0x1FFE0"/>
<build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_JumpTable"/>
<build type="linker-config" subtype="flags" value="--section-start=.apitable_signatures=0x1FFF8"/>
<build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_Signatures"/>
</project>
<project caption="DFU Bootloader - 64KB FLASH / 4KB Boot - AVR8 Architecture" id="lufa.bootloaders.dfu.avr8.64_4" force-caption="true" workspace-name="lufa_dfu_64kb_4kb_">
<require idref="lufa.bootloaders.dfu"/>
<require idref="lufa.boards.dummy.avr8"/>
<generator value="as5_8"/>
<device-support value="at90usb647"/>
<config name="lufa.drivers.board.name" value="none"/>
<config name="config.compiler.optimization.level" value="size"/>
<build type="define" name="F_CPU" value="16000000UL"/>
<build type="define" name="F_USB" value="16000000UL"/>
<build type="define" name="BOOT_START_ADDR" value="0xF000"/>
<build type="linker-config" subtype="flags" value="--section-start=.text=0xF000"/>
<build type="linker-config" subtype="flags" value="--section-start=.apitable_trampolines=0xFFA0"/>
<build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_Trampolines"/>
<build type="linker-config" subtype="flags" value="--section-start=.apitable_jumptable=0xFFE0"/>
<build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_JumpTable"/>
<build type="linker-config" subtype="flags" value="--section-start=.apitable_signatures=0xFFF8"/>
<build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_Signatures"/>
</project>
<project caption="DFU Bootloader - 32KB FLASH / 4KB Boot - AVR8 Architecture" id="lufa.bootloaders.dfu.avr8.32_4" force-caption="true" workspace-name="lufa_dfu_32kb_4kb_">
<require idref="lufa.bootloaders.dfu"/>
<require idref="lufa.boards.dummy.avr8"/>
<generator value="as5_8"/>
<device-support value="atmega32u4"/>
<config name="lufa.drivers.board.name" value="none"/>
<config name="config.compiler.optimization.level" value="size"/>
<build type="define" name="F_CPU" value="16000000UL"/>
<build type="define" name="F_USB" value="16000000UL"/>
<build type="define" name="BOOT_START_ADDR" value="0x7000"/>
<build type="linker-config" subtype="flags" value="--section-start=.text=0x7000"/>
<build type="linker-config" subtype="flags" value="--section-start=.apitable_trampolines=0x7FA0"/>
<build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_Trampolines"/>
<build type="linker-config" subtype="flags" value="--section-start=.apitable_jumptable=0x7FE0"/>
<build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_JumpTable"/>
<build type="linker-config" subtype="flags" value="--section-start=.apitable_signatures=0x7FF8"/>
<build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_Signatures"/>
</project>
<project caption="DFU Bootloader - 16KB FLASH / 4KB Boot - AVR8 Architecture" id="lufa.bootloaders.dfu.avr8.16_4" force-caption="true" workspace-name="lufa_dfu_16kb_4kb_">
<require idref="lufa.bootloaders.dfu"/>
<require idref="lufa.boards.dummy.avr8"/>
<generator value="as5_8"/>
<device-support value="atmega16u2"/>
<config name="lufa.drivers.board.name" value="none"/>
<build type="define" name="F_CPU" value="16000000UL"/>
<build type="define" name="F_USB" value="16000000UL"/>
<build type="define" name="BOOT_START_ADDR" value="0x3000"/>
<build type="linker-config" subtype="flags" value="--section-start=.text=0x3000"/>
<build type="linker-config" subtype="flags" value="--section-start=.apitable_trampolines=0x3FA0"/>
<build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_Trampolines"/>
<build type="linker-config" subtype="flags" value="--section-start=.apitable_jumptable=0x3FE0"/>
<build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_JumpTable"/>
<build type="linker-config" subtype="flags" value="--section-start=.apitable_signatures=0x3FF8"/>
<build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_Signatures"/>
</project>
<project caption="DFU Bootloader - 8KB FLASH / 4KB Boot - AVR8 Architecture" id="lufa.bootloaders.dfu.avr8.8_4" force-caption="true" workspace-name="lufa_dfu_8kb_4kb_">
<require idref="lufa.bootloaders.dfu"/>
<require idref="lufa.boards.dummy.avr8"/>
<generator value="as5_8"/>
<device-support value="atmega8u2"/>
<config name="lufa.drivers.board.name" value="none"/>
<build type="define" name="F_CPU" value="16000000UL"/>
<build type="define" name="F_USB" value="16000000UL"/>
<build type="define" name="BOOT_START_ADDR" value="0x1000"/>
<build type="linker-config" subtype="flags" value="--section-start=.text=0x1000"/>
<build type="linker-config" subtype="flags" value="--section-start=.apitable_trampolines=0x1FA0"/>
<build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_Trampolines"/>
<build type="linker-config" subtype="flags" value="--section-start=.apitable_jumptable=0x1FE0"/>
<build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_JumpTable"/>
<build type="linker-config" subtype="flags" value="--section-start=.apitable_signatures=0x1FF8"/>
<build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_Signatures"/>
</project>
<module type="application" id="lufa.bootloaders.dfu" caption="DFU Bootloader">
<info type="description" value="summary">
DFU Class Bootloader, capable of reprogramming a device using the Atmel FLIP or other AVR DFU programming software when plugged into a host.
</info>
<info type="gui-flag" value="move-to-root"/>
<info type="keyword" value="Technology">
<keyword value="Bootloaders"/>
<keyword value="USB Device"/>
</info>
<device-support-alias value="lufa_avr8"/>
<device-support-alias value="lufa_xmega"/>
<device-support-alias value="lufa_uc3"/>
<build type="include-path" value="."/>
<build type="c-source" value="BootloaderDFU.c"/>
<build type="header-file" value="BootloaderDFU.h"/>
<build type="c-source" value="Descriptors.c"/>
<build type="header-file" value="Descriptors.h"/>
<build type="c-source" value="BootloaderAPI.c"/>
<build type="header-file" value="BootloaderAPI.h"/>
<build type="asm-source" value="BootloaderAPITable.S"/>
<build type="module-config" subtype="path" value="Config"/>
<build type="header-file" value="Config/LUFAConfig.h"/>
<build type="header-file" value="Config/AppConfig.h"/>
<build type="distribute" subtype="user-file" value="doxyfile"/>
<build type="distribute" subtype="user-file" value="BootloaderDFU.txt"/>
<require idref="lufa.common"/>
<require idref="lufa.platform"/>
<require idref="lufa.drivers.usb"/>
<require idref="lufa.drivers.board"/>
<require idref="lufa.drivers.board.leds"/>
</module>
</asf>

File diff suppressed because it is too large Load Diff

@ -0,0 +1,62 @@
#
# LUFA Library
# Copyright (C) Dean Camera, 2017.
#
# dean [at] fourwalledcubicle [dot] com
# www.lufa-lib.org
#
# --------------------------------------
# LUFA Project Makefile.
# --------------------------------------
# Run "make help" for target help.
MCU = atmega32u4
ARCH = AVR8
BOARD = QMK
F_CPU = 16000000
F_USB = $(F_CPU)
OPTIMIZATION = s
TARGET = BootloaderDFU
SRC = $(TARGET).c Descriptors.c BootloaderAPI.c BootloaderAPITable.S $(LUFA_SRC_USB)
LUFA_PATH = ../../LUFA
CC_FLAGS = -DUSE_LUFA_CONFIG_HEADER -IConfig/ -DBOOT_START_ADDR=$(BOOT_START_OFFSET)
LD_FLAGS = -Wl,--section-start=.text=$(BOOT_START_OFFSET) $(BOOT_API_LD_FLAGS)
# Flash size and bootloader section sizes of the target, in KB. These must
# match the target's total FLASH size and the bootloader size set in the
# device's fuses.
FLASH_SIZE_KB = 32
BOOT_SECTION_SIZE_KB = 4
# Bootloader address calculation formulas
# Do not modify these macros, but rather modify the dependent values above.
CALC_ADDRESS_IN_HEX = $(shell printf "0x%X" $$(( $(1) )) )
BOOT_START_OFFSET = $(call CALC_ADDRESS_IN_HEX, ($(FLASH_SIZE_KB) - $(BOOT_SECTION_SIZE_KB)) * 1024 )
BOOT_SEC_OFFSET = $(call CALC_ADDRESS_IN_HEX, ($(FLASH_SIZE_KB) * 1024) - ($(strip $(1))) )
# Bootloader linker section flags for relocating the API table sections to
# known FLASH addresses - these should not normally be user-edited.
BOOT_SECTION_LD_FLAG = -Wl,--section-start=$(strip $(1))=$(call BOOT_SEC_OFFSET, $(3)) -Wl,--undefined=$(strip $(2))
BOOT_API_LD_FLAGS = $(call BOOT_SECTION_LD_FLAG, .apitable_trampolines, BootloaderAPI_Trampolines, 96)
BOOT_API_LD_FLAGS += $(call BOOT_SECTION_LD_FLAG, .apitable_jumptable, BootloaderAPI_JumpTable, 32)
BOOT_API_LD_FLAGS += $(call BOOT_SECTION_LD_FLAG, .apitable_signatures, BootloaderAPI_Signatures, 8)
# Default target
all:
# Include LUFA-specific DMBS extension modules
DMBS_LUFA_PATH ?= $(LUFA_PATH)/Build/LUFA
include $(DMBS_LUFA_PATH)/lufa-sources.mk
include $(DMBS_LUFA_PATH)/lufa-gcc.mk
# Include common DMBS build system modules
DMBS_PATH ?= $(LUFA_PATH)/Build/DMBS/DMBS
include $(DMBS_PATH)/core.mk
include $(DMBS_PATH)/cppcheck.mk
include $(DMBS_PATH)/doxygen.mk
include $(DMBS_PATH)/dfu.mk
include $(DMBS_PATH)/gcc.mk
include $(DMBS_PATH)/hid.mk
include $(DMBS_PATH)/avrdude.mk
include $(DMBS_PATH)/atprogram.mk

@ -0,0 +1,198 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2017.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2017 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 disclaims 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 HID class bootloader. This file contains the complete bootloader logic.
*/
#include "BootloaderHID.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
* started via a forced watchdog reset.
*/
static bool RunBootloader = true;
/** Magic lock for forced application start. If the HWBE fuse is programmed and BOOTRST is unprogrammed, the bootloader
* will start if the /HWB line of the AVR is held low and the system is reset. However, if the /HWB line is still held
* low when the application attempts to start via a watchdog reset, the bootloader will re-start. If set to the value
* \ref MAGIC_BOOT_KEY the special init function \ref Application_Jump_Check() will force the application to start.
*/
uint16_t MagicBootKey ATTR_NO_INIT;
/** Special startup routine to check if the bootloader was started via a watchdog reset, and if the magic application
* start key has been loaded into \ref MagicBootKey. If the bootloader started via the watchdog and the key is valid,
* this will force the user application to start via a software jump.
*/
void Application_Jump_Check(void)
{
/* If the reset source was the bootloader and the key is correct, clear it and jump to the application */
if ((MCUSR & (1 << WDRF)) && (MagicBootKey == MAGIC_BOOT_KEY))
{
/* Turn off the watchdog */
MCUSR &= ~(1 << WDRF);
wdt_disable();
/* Clear the boot key and jump to the user application */
MagicBootKey = 0;
// cppcheck-suppress constStatement
((void (*)(void))0x0000)();
}
}
/** 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.
*/
int main(void)
{
/* Setup hardware required for the bootloader */
SetupHardware();
/* Enable global interrupts so that the USB stack can function */
GlobalInterruptEnable();
while (RunBootloader)
USB_USBTask();
/* Disconnect from the host - USB interface will be reset later along with the AVR */
USB_Detach();
/* Unlock the forced application start mode of the bootloader if it is restarted */
MagicBootKey = MAGIC_BOOT_KEY;
/* Enable the watchdog and force a timeout to reset the AVR */
wdt_enable(WDTO_250MS);
for (;;);
}
/** Configures all hardware required for the bootloader. */
static 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);
/* Initialize USB subsystem */
USB_Init();
}
/** 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 HID Report Endpoint */
Endpoint_ConfigureEndpoint(HID_IN_EPADDR, EP_TYPE_INTERRUPT, HID_IN_EPSIZE, 1);
}
/** 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 HID interface */
if ((USB_ControlRequest.bmRequestType & (CONTROL_REQTYPE_TYPE | CONTROL_REQTYPE_RECIPIENT)) !=
(REQTYPE_CLASS | REQREC_INTERFACE))
{
return;
}
/* Process HID specific control requests */
switch (USB_ControlRequest.bRequest)
{
case HID_REQ_SetReport:
Endpoint_ClearSETUP();
/* Wait until the command has been sent by the host */
while (!(Endpoint_IsOUTReceived()));
/* Read in the write destination address */
#if (FLASHEND > 0xFFFF)
uint32_t PageAddress = ((uint32_t)Endpoint_Read_16_LE() << 8);
#else
uint16_t PageAddress = Endpoint_Read_16_LE();
#endif
/* Check if the command is a program page command, or a start application command */
#if (FLASHEND > 0xFFFF)
if ((uint16_t)(PageAddress >> 8) == COMMAND_STARTAPPLICATION)
#else
if (PageAddress == COMMAND_STARTAPPLICATION)
#endif
{
RunBootloader = false;
}
else if (PageAddress < BOOT_START_ADDR)
{
/* Erase the given FLASH page, ready to be programmed */
boot_page_erase(PageAddress);
boot_spm_busy_wait();
/* Write each of the FLASH page's bytes in sequence */
for (uint8_t PageWord = 0; PageWord < (SPM_PAGESIZE / 2); PageWord++)
{
/* Check if endpoint is empty - if so clear it and wait until ready for next packet */
if (!(Endpoint_BytesInEndpoint()))
{
Endpoint_ClearOUT();
while (!(Endpoint_IsOUTReceived()));
}
/* Write the next data word to the FLASH page */
boot_page_fill(PageAddress + ((uint16_t)PageWord << 1), Endpoint_Read_16_LE());
}
/* Write the filled FLASH page to memory */
boot_page_write(PageAddress);
boot_spm_busy_wait();
/* Re-enable RWW section */
boot_rww_enable();
}
Endpoint_ClearOUT();
Endpoint_ClearStatusStage();
break;
}
}

@ -0,0 +1,71 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2017.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2017 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 disclaims 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 BootloaderHID.c.
*/
#ifndef _BOOTLOADERHID_H_
#define _BOOTLOADERHID_H_
/* Includes: */
#include <avr/io.h>
#include <avr/wdt.h>
#include <avr/boot.h>
#include <avr/power.h>
#include <avr/interrupt.h>
#include <stdbool.h>
#include "Descriptors.h"
#include <LUFA/Drivers/USB/USB.h>
#include <LUFA/Platform/Platform.h>
/* Preprocessor Checks: */
#if !defined(__OPTIMIZE_SIZE__)
#error This bootloader requires that it be optimized for size, not speed, to fit into the target device. Change optimization settings and try again.
#endif
/* Macros: */
/** Bootloader special address to start the user application */
#define COMMAND_STARTAPPLICATION 0xFFFF
/** Magic bootloader key to unlock forced application start mode. */
#define MAGIC_BOOT_KEY 0xDC42
/* Function Prototypes: */
static void SetupHardware(void);
void Application_Jump_Check(void) ATTR_INIT_SECTION(3);
void EVENT_USB_Device_ConfigurationChanged(void);
#endif

@ -0,0 +1,105 @@
/** \file
*
* This file contains special DoxyGen information for the generation of the main page and other special
* documentation pages. It is not a project source file.
*/
/** \mainpage HID Class USB AVR Bootloader
*
* \section SSec_Compat Demo Compatibility:
*
* The following list indicates what microcontrollers are compatible with this demo.
*
* \li Series 7 USB AVRs (AT90USBxxx7)
* \li Series 6 USB AVRs (AT90USBxxx6)
* \li Series 4 USB AVRs (ATMEGAxxU4)
* \li Series 2 USB AVRs (AT90USBxx2, ATMEGAxxU2)
*
* \section SSec_Info USB Information:
*
* The following table gives a rundown of the USB utilization of this demo.
*
* <table>
* <tr>
* <td><b>USB Mode:</b></td>
* <td>Device</td>
* </tr>
* <tr>
* <td><b>USB Class:</b></td>
* <td>Human Interface Device Class (HID)</td>
* </tr>
* <tr>
* <td><b>USB Subclass:</b></td>
* <td>N/A</td>
* </tr>
* <tr>
* <td><b>Relevant Standards:</b></td>
* <td>USBIF HID Class Standard \n
* Teensy Programming Protocol Specification</td>
* </tr>
* <tr>
* <td><b>Supported USB Speeds:</b></td>
* <td>Low Speed Mode \n
* Full Speed Mode</td>
* </tr>
* </table>
*
* \section SSec_Description Project Description:
*
* This bootloader enumerates to the host as a HID Class device, allowing for device FLASH programming through
* the supplied command line software, which is a modified version of Paul's TeensyHID Command Line loader code
* from PJRC (used with permission). This bootloader is deliberately non-compatible with the proprietary PJRC
* HalfKay bootloader GUI; only the command line interface software accompanying this bootloader will work with it.
*
* Out of the box this bootloader builds for the AT90USB1287 with an 8KB bootloader section size, and will fit
* into 2KB of bootloader space for the Series 2 USB AVRs (ATMEGAxxU2, AT90USBxx2) or 4KB of bootloader space for
* all other models. If you wish to alter this size and/or change the AVR model, you will need to edit the MCU,
* FLASH_SIZE_KB and BOOT_SECTION_SIZE_KB values in the accompanying makefile.
*
* \warning <b>THIS BOOTLOADER IS NOT SECURE.</b> Malicious entities can recover written data, even if the device
* lockbits are set.
*
* \section Sec_Running Running the Bootloader
*
* This bootloader is designed to be started via the \c HWB mechanism of the USB AVRs; ground the \c HWB pin (see device
* datasheet) then momentarily ground \c /RESET to start the bootloader. This assumes the \c HWBE fuse is set and the
* \c BOOTRST fuse is cleared.
*
* \section Sec_Installation Driver Installation
*
* This bootloader uses the HID class driver inbuilt into all modern operating systems, thus no additional drivers
* need to be supplied for correct operation.
*
* \section Sec_HostApp Host Controller Application
*
* Due to licensing issues, the supplied bootloader is compatible with the HalfKay bootloader protocol designed
* by PJRC, but is <b>not compatible with the cross-platform loader GUI</b>. A modified version of the open source
* cross-platform TeensyLoader application is supplied, which can be compiled under most operating systems. The
* command-line loader application should remain compatible with genuine Teensy boards in addition to boards using
* this custom bootloader.
*
* Once compiled, programs can be loaded into the AVR's FLASH memory through the following example command:
* \code
* hid_bootloader_cli -mmcu=at90usb1287 Mouse.hex
* \endcode
*
* \section Sec_KnownIssues Known Issues:
*
* \par After loading an application, it is not run automatically on startup.
* Some USB AVR boards ship with the \c BOOTRST fuse set, causing the bootloader
* to run automatically when the device is reset. This booloader requires the
* \c BOOTRST be disabled and the HWBE fuse used instead to run the bootloader
* when needed.
*
* \section SSec_Options Project Options
*
* The following defines can be found in this demo, which can control the demo behaviour when defined, or changed in value.
*
* <table>
* <tr>
* <td>
* None
* </td>
* </tr>
* </table>
*/

@ -0,0 +1,93 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2017.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2017 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 disclaims 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
* \brief LUFA Library Configuration Header File
*
* This header file is used to configure LUFA's compile time options,
* as an alternative to the compile time constants supplied through
* a makefile.
*
* For information on what each token does, refer to the LUFA
* manual section "Summary of Compile Tokens".
*/
#ifndef _LUFA_CONFIG_H_
#define _LUFA_CONFIG_H_
#if (ARCH == ARCH_AVR8)
/* Non-USB Related Configuration Tokens: */
// #define DISABLE_TERMINAL_CODES
/* USB Class Driver Related Tokens: */
// #define HID_HOST_BOOT_PROTOCOL_ONLY
// #define HID_STATETABLE_STACK_DEPTH {Insert Value Here}
// #define HID_USAGE_STACK_DEPTH {Insert Value Here}
// #define HID_MAX_COLLECTIONS {Insert Value Here}
// #define HID_MAX_REPORTITEMS {Insert Value Here}
// #define HID_MAX_REPORT_IDS {Insert Value Here}
// #define NO_CLASS_DRIVER_AUTOFLUSH
/* General USB Driver Related Tokens: */
#define ORDERED_EP_CONFIG
#define USE_STATIC_OPTIONS (USB_DEVICE_OPT_FULLSPEED | USB_OPT_REG_ENABLED | USB_OPT_AUTO_PLL)
#define USB_DEVICE_ONLY
// #define USB_HOST_ONLY
// #define USB_STREAM_TIMEOUT_MS {Insert Value Here}
// #define NO_LIMITED_CONTROLLER_CONNECT
#define NO_SOF_EVENTS
/* USB Device Mode Driver Related Tokens: */
#define USE_RAM_DESCRIPTORS
// #define USE_FLASH_DESCRIPTORS
// #define USE_EEPROM_DESCRIPTORS
#define NO_INTERNAL_SERIAL
#define FIXED_CONTROL_ENDPOINT_SIZE 8
#define DEVICE_STATE_AS_GPIOR 0
#define FIXED_NUM_CONFIGURATIONS 1
// #define CONTROL_ONLY_DEVICE
// #define INTERRUPT_CONTROL_ENDPOINT
#define NO_DEVICE_REMOTE_WAKEUP
#define NO_DEVICE_SELF_POWER
/* USB Host Mode Driver Related Tokens: */
// #define HOST_STATE_AS_GPIOR {Insert Value Here}
// #define USB_HOST_TIMEOUT_MS {Insert Value Here}
// #define HOST_DEVICE_SETTLE_DELAY_MS {Insert Value Here}
// #define NO_AUTO_VBUS_MANAGEMENT
// #define INVERTED_VBUS_ENABLE_LINE
#else
#error Unsupported architecture for this LUFA configuration file.
#endif
#endif

@ -0,0 +1,187 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2017.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2017 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 disclaims 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"
/** HID class report descriptor. This is a special descriptor constructed with values from the
* USBIF HID class specification to describe the reports and capabilities of the HID device. This
* descriptor is parsed by the host and its contents used to determine what data (and in what encoding)
* the device will send, and what it may be sent back from the host. Refer to the HID specification for
* more details on HID report descriptors.
*/
const USB_Descriptor_HIDReport_Datatype_t HIDReport[] =
{
HID_RI_USAGE_PAGE(16, 0xFFDC), /* Vendor Page 0xDC */
HID_RI_USAGE(8, 0xFB), /* Vendor Usage 0xFB */
HID_RI_COLLECTION(8, 0x01), /* Vendor Usage 1 */
HID_RI_USAGE(8, 0x02), /* Vendor Usage 2 */
HID_RI_LOGICAL_MINIMUM(8, 0x00),
HID_RI_LOGICAL_MAXIMUM(8, 0xFF),
HID_RI_REPORT_SIZE(8, 0x08),
HID_RI_REPORT_COUNT(16, (sizeof(uint16_t) + SPM_PAGESIZE)),
HID_RI_OUTPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE | HID_IOF_NON_VOLATILE),
HID_RI_END_COLLECTION(0),
};
/** 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(1,1,0),
.Class = USB_CSCP_NoDeviceClass,
.SubClass = USB_CSCP_NoDeviceSubclass,
.Protocol = USB_CSCP_NoDeviceProtocol,
.Endpoint0Size = FIXED_CONTROL_ENDPOINT_SIZE,
.VendorID = 0x03EB,
.ProductID = 0x2067,
.ReleaseNumber = VERSION_BCD(0,0,1),
.ManufacturerStrIndex = NO_DESCRIPTOR,
.ProductStrIndex = NO_DESCRIPTOR,
.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 = 1,
.ConfigurationNumber = 1,
.ConfigurationStrIndex = NO_DESCRIPTOR,
.ConfigAttributes = USB_CONFIG_ATTR_RESERVED,
.MaxPowerConsumption = USB_CONFIG_POWER_MA(100)
},
.HID_Interface =
{
.Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},
.InterfaceNumber = INTERFACE_ID_GenericHID,
.AlternateSetting = 0x00,
.TotalEndpoints = 1,
.Class = HID_CSCP_HIDClass,
.SubClass = HID_CSCP_NonBootSubclass,
.Protocol = HID_CSCP_NonBootProtocol,
.InterfaceStrIndex = NO_DESCRIPTOR
},
.HID_VendorHID =
{
.Header = {.Size = sizeof(USB_HID_Descriptor_HID_t), .Type = HID_DTYPE_HID},
.HIDSpec = VERSION_BCD(1,1,1),
.CountryCode = 0x00,
.TotalReportDescriptors = 1,
.HIDReportType = HID_DTYPE_Report,
.HIDReportLength = sizeof(HIDReport)
},
.HID_ReportINEndpoint =
{
.Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
.EndpointAddress = HID_IN_EPADDR,
.Attributes = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
.EndpointSize = HID_IN_EPSIZE,
.PollingIntervalMS = 0x05
},
};
/** 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 uint16_t wIndex,
const void** const DescriptorAddress)
{
const uint8_t DescriptorType = (wValue >> 8);
const void* Address = NULL;
uint16_t Size = NO_DESCRIPTOR;
/* If/Else If chain compiles slightly smaller than a switch case */
if (DescriptorType == DTYPE_Device)
{
Address = &DeviceDescriptor;
Size = sizeof(USB_Descriptor_Device_t);
}
else if (DescriptorType == DTYPE_Configuration)
{
Address = &ConfigurationDescriptor;
Size = sizeof(USB_Descriptor_Configuration_t);
}
else if (DescriptorType == HID_DTYPE_HID)
{
Address = &ConfigurationDescriptor.HID_VendorHID;
Size = sizeof(USB_HID_Descriptor_HID_t);
}
else if (DescriptorType == HID_DTYPE_Report)
{
Address = &HIDReport;
Size = sizeof(HIDReport);
}
*DescriptorAddress = Address;
return Size;
}

@ -0,0 +1,80 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2017.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2017 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 disclaims 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>
/* 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;
// Generic HID Interface
USB_Descriptor_Interface_t HID_Interface;
USB_HID_Descriptor_HID_t HID_VendorHID;
USB_Descriptor_Endpoint_t HID_ReportINEndpoint;
} USB_Descriptor_Configuration_t;
/** Enum for the device interface descriptor IDs within the device. Each interface descriptor
* should have a unique ID index associated with it, which can be used to refer to the
* interface from other descriptors.
*/
enum InterfaceDescriptors_t
{
INTERFACE_ID_GenericHID = 0, /**< GenericHID interface descriptor ID */
};
/* Macros: */
/** Endpoint address of the HID data IN endpoint. */
#define HID_IN_EPADDR (ENDPOINT_DIR_IN | 1)
/** Size in bytes of the HID reporting IN endpoint. */
#define HID_IN_EPSIZE 64
/* Function Prototypes: */
uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue,
const uint16_t wIndex,
const void** const DescriptorAddress)
ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(3);
#endif

@ -0,0 +1,40 @@
OS ?= LINUX
#OS ?= WINDOWS
#OS ?= MACOSX
#OS ?= BSD
ifeq ($(OS), LINUX) # also works on FreeBSD
CC ?= gcc
CFLAGS ?= -O2 -Wall
hid_bootloader_cli: hid_bootloader_cli.c
$(CC) $(CFLAGS) -s -DUSE_LIBUSB -o hid_bootloader_cli hid_bootloader_cli.c -lusb
else ifeq ($(OS), WINDOWS)
CC = i586-mingw32msvc-gcc
CFLAGS ?= -O2 -Wall
LDLIB = -lsetupapi -lhid
hid_bootloader_cli.exe: hid_bootloader_cli.c
$(CC) $(CFLAGS) -s -DUSE_WIN32 -o hid_bootloader_cli.exe hid_bootloader_cli.c $(LDLIB)
else ifeq ($(OS), MACOSX)
CC ?= gcc
SDK ?= /Developer/SDKs/MacOSX10.5.sdk
CFLAGS ?= -O2 -Wall
hid_bootloader_cli: hid_bootloader_cli.c
$(CC) $(CFLAGS) -DUSE_APPLE_IOKIT -isysroot $(SDK) -o hid_bootloader_cli hid_bootloader_cli.c -Wl,-syslibroot,$(SDK) -framework IOKit -framework CoreFoundation
else ifeq ($(OS), BSD) # works on NetBSD and OpenBSD
CC ?= gcct
CFLAGS ?= -O2 -Wall
hid_bootloader_cli: hid_bootloader_cli.c
$(CC) $(CFLAGS) -s -DUSE_UHID -o hid_bootloader_cli hid_bootloader_cli.c
endif
clean:
rm -f hid_bootloader_cli hid_bootloader_cli.exe

File diff suppressed because it is too large Load Diff

@ -0,0 +1,120 @@
"""
LUFA Library
Copyright (C) Dean Camera, 2017.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
"""
"""
Front-end programmer for the LUFA HID class bootloader.
Usage:
python hid_bootloader_loader.py <Device> <Input>.hex
Example:
python hid_bootloader_loader.py at90usb1287 Mouse.hex
Requires the pywinusb (https://pypi.python.org/pypi/pywinusb/) and
IntelHex (https://pypi.python.org/pypi/IntelHex/) libraries.
"""
import sys
from pywinusb import hid
from intelhex import IntelHex
# Device information table
device_info_map = dict()
device_info_map['at90usb1287'] = {'page_size': 256, 'flash_kb': 128}
device_info_map['at90usb1286'] = {'page_size': 256, 'flash_kb': 128}
device_info_map['at90usb647'] = {'page_size': 256, 'flash_kb': 64}
device_info_map['at90usb646'] = {'page_size': 256, 'flash_kb': 64}
device_info_map['atmega32u4'] = {'page_size': 128, 'flash_kb': 32}
device_info_map['atmega32u2'] = {'page_size': 128, 'flash_kb': 32}
device_info_map['atmega16u4'] = {'page_size': 128, 'flash_kb': 16}
device_info_map['atmega16u2'] = {'page_size': 128, 'flash_kb': 16}
device_info_map['at90usb162'] = {'page_size': 128, 'flash_kb': 16}
device_info_map['atmega8u2'] = {'page_size': 128, 'flash_kb': 8}
device_info_map['at90usb82'] = {'page_size': 128, 'flash_kb': 8}
def get_hid_device_handle():
hid_device_filter = hid.HidDeviceFilter(vendor_id=0x03EB,
product_id=0x2067)
valid_hid_devices = hid_device_filter.get_devices()
if len(valid_hid_devices) is 0:
return None
else:
return valid_hid_devices[0]
def send_page_data(hid_device, address, data):
# Bootloader page data should be the HID Report ID (always zero) followed
# by the starting address to program, then one device's flash page worth
# of data
output_report_data = [0]
output_report_data.extend([address & 0xFF, address >> 8])
output_report_data.extend(data)
hid_device.send_output_report(output_report_data)
def program_device(hex_data, device_info):
hid_device = get_hid_device_handle()
if hid_device is None:
print("No valid HID device found.")
sys.exit(1)
try:
hid_device.open()
print("Connected to bootloader.")
# Program in all data from the loaded HEX file, in a number of device
# page sized chunks
for addr in range(0, hex_data.maxaddr(), device_info['page_size']):
# Compute the address range of the current page in the device
current_page_range = range(addr, addr+device_info['page_size'])
# Extract the data from the hex file at the specified start page
# address and convert it to a regular list of bytes
page_data = [hex_data[i] for i in current_page_range]
print("Writing address 0x%04X-0x%04X" % (current_page_range[0], current_page_range[-1]))
# Devices with more than 64KB of flash should shift down the page
# address so that it is 16-bit (page size is guaranteed to be
# >= 256 bytes so no non-zero address bits are discarded)
if device_info['flash_kb'] < 64:
send_page_data(hid_device, addr, page_data)
else:
send_page_data(hid_device, addr >> 8, page_data)
# Once programming is complete, start the application via a dummy page
# program to the page address 0xFFFF
print("Programming complete, starting application.")
send_page_data(hid_device, 0xFFFF, [0] * device_info['page_size'])
finally:
hid_device.close()
if __name__ == '__main__':
# Load the specified HEX file
try:
hex_data = IntelHex(sys.argv[2])
except:
print("Could not open the specified HEX file.")
sys.exit(1)
# Retrieve the device information entry for the specified device
try:
device_info = device_info_map[sys.argv[1]]
except:
print("Unknown device name specified.")
sys.exit(1)
program_device(hex_data, device_info)

@ -0,0 +1,123 @@
<asf xmlversion="1.0">
<project caption="HID Bootloader - 128KB FLASH / 4KB Boot - AVR8 Architecture" id="lufa.bootloaders.hid.avr8.128_4" force-caption="true" workspace-name="lufa_hid_128kb_4kb_">
<require idref="lufa.bootloaders.hid"/>
<require idref="lufa.boards.dummy.avr8"/>
<generator value="as5_8"/>
<device-support value="at90usb1287"/>
<config name="lufa.drivers.board.name" value="none"/>
<config name="config.compiler.optimization.level" value="size"/>
<build type="define" name="F_CPU" value="16000000UL"/>
<build type="define" name="F_USB" value="16000000UL"/>
<build type="define" name="BOOT_START_ADDR" value="0x1F000"/>
<build type="linker-config" subtype="flags" value="--section-start=.text=0x1F000"/>
</project>
<project caption="HID Bootloader - 64KB FLASH / 4KB Boot - AVR8 Architecture" id="lufa.bootloaders.hid.avr8.64_4" force-caption="true" workspace-name="lufa_hid_64kb_4kb_">
<require idref="lufa.bootloaders.hid"/>
<require idref="lufa.boards.dummy.avr8"/>
<generator value="as5_8"/>
<device-support value="at90usb647"/>
<config name="lufa.drivers.board.name" value="none"/>
<config name="config.compiler.optimization.level" value="size"/>
<build type="define" name="F_CPU" value="16000000UL"/>
<build type="define" name="F_USB" value="16000000UL"/>
<build type="define" name="BOOT_START_ADDR" value="0xF000"/>
<build type="linker-config" subtype="flags" value="--section-start=.text=0xF000"/>
</project>
<project caption="HID Bootloader - 32KB FLASH / 4KB Boot - AVR8 Architecture" id="lufa.bootloaders.hid.avr8.32_4" force-caption="true" workspace-name="lufa_hid_32kb_4kb_">
<require idref="lufa.bootloaders.hid"/>
<require idref="lufa.boards.dummy.avr8"/>
<generator value="as5_8"/>
<device-support value="atmega32u4"/>
<config name="lufa.drivers.board.name" value="none"/>
<config name="config.compiler.optimization.level" value="size"/>
<build type="define" name="F_CPU" value="16000000UL"/>
<build type="define" name="F_USB" value="16000000UL"/>
<build type="define" name="BOOT_START_ADDR" value="0x7000"/>
<build type="linker-config" subtype="flags" value="--section-start=.text=0x7000"/>
</project>
<project caption="HID Bootloader - 16KB FLASH / 2KB Boot - AVR8 Architecture" id="lufa.bootloaders.hid.avr8.16_2" force-caption="true" workspace-name="lufa_hid_16kb_2kb_">
<require idref="lufa.bootloaders.hid"/>
<require idref="lufa.boards.dummy.avr8"/>
<generator value="as5_8"/>
<device-support value="atmega16u2"/>
<config name="lufa.drivers.board.name" value="none"/>
<config name="config.compiler.optimization.level" value="size"/>
<build type="define" name="F_CPU" value="16000000UL"/>
<build type="define" name="F_USB" value="16000000UL"/>
<build type="define" name="BOOT_START_ADDR" value="0x3800"/>
<build type="linker-config" subtype="flags" value="--section-start=.text=0x3800"/>
</project>
<project caption="HID Bootloader - 8KB FLASH / 2KB Boot - AVR8 Architecture" id="lufa.bootloaders.hid.avr8.8_2" force-caption="true" workspace-name="lufa_hid_8kb_2kb_">
<require idref="lufa.bootloaders.hid"/>
<require idref="lufa.boards.dummy.avr8"/>
<generator value="as5_8"/>
<device-support value="atmega8u2"/>
<config name="lufa.drivers.board.name" value="none"/>
<config name="config.compiler.optimization.level" value="size"/>
<build type="define" name="F_CPU" value="16000000UL"/>
<build type="define" name="F_USB" value="16000000UL"/>
<build type="define" name="BOOT_START_ADDR" value="0x1800"/>
<build type="linker-config" subtype="flags" value="--section-start=.text=0x1800"/>
</project>
<module type="application" id="lufa.bootloaders.hid" caption="HID Bootloader">
<info type="description" value="summary">
HID Class Bootloader, capable of reprogramming a device via a custom cross-platform command line utility when plugged into a host.
</info>
<info type="gui-flag" value="move-to-root"/>
<info type="keyword" value="Technology">
<keyword value="Bootloaders"/>
<keyword value="USB Device"/>
</info>
<device-support-alias value="lufa_avr8"/>
<device-support-alias value="lufa_xmega"/>
<device-support-alias value="lufa_uc3"/>
<build type="include-path" value="."/>
<build type="c-source" value="BootloaderHID.c"/>
<build type="header-file" value="BootloaderHID.h"/>
<build type="c-source" value="Descriptors.c"/>
<build type="header-file" value="Descriptors.h"/>
<build type="module-config" subtype="path" value="Config"/>
<build type="header-file" value="Config/LUFAConfig.h"/>
<build type="distribute" subtype="user-file" value="doxyfile"/>
<build type="distribute" subtype="user-file" value="BootloaderHID.txt"/>
<build type="distribute" subtype="directory" value="HostLoaderApp"/>
<build type="distribute" subtype="directory" value="HostLoaderApp_Python"/>
<require idref="lufa.common"/>
<require idref="lufa.platform"/>
<require idref="lufa.drivers.usb"/>
<require idref="lufa.drivers.board"/>
<require idref="lufa.drivers.board.leds"/>
</module>
</asf>

File diff suppressed because it is too large Load Diff

@ -0,0 +1,55 @@
#
# LUFA Library
# Copyright (C) Dean Camera, 2017.
#
# dean [at] fourwalledcubicle [dot] com
# www.lufa-lib.org
#
# --------------------------------------
# LUFA Project Makefile.
# --------------------------------------
# Run "make help" for target help.
MCU = at90usb1287
ARCH = AVR8
BOARD = USBKEY
F_CPU = 8000000
F_USB = $(F_CPU)
OPTIMIZATION = s
TARGET = BootloaderHID
SRC = $(TARGET).c Descriptors.c $(LUFA_SRC_USB)
LUFA_PATH = ../../LUFA
CC_FLAGS = -DUSE_LUFA_CONFIG_HEADER -DBOOT_START_ADDR=$(BOOT_START_OFFSET) -IConfig/
LD_FLAGS = -Wl,--section-start=.text=$(BOOT_START_OFFSET)
# Flash size and bootloader section sizes of the target, in KB. These must
# match the target's total FLASH size and the bootloader size set in the
# device's fuses.
FLASH_SIZE_KB := 128
BOOT_SECTION_SIZE_KB := 8
# Bootloader address calculation formulas
# Do not modify these macros, but rather modify the dependent values above.
CALC_ADDRESS_IN_HEX = $(shell printf "0x%X" $$(( $(1) )) )
BOOT_START_OFFSET = $(call CALC_ADDRESS_IN_HEX, ($(FLASH_SIZE_KB) - $(BOOT_SECTION_SIZE_KB)) * 1024 )
BOOT_SEC_OFFSET = $(call CALC_ADDRESS_IN_HEX, ($(FLASH_SIZE_KB) * 1024) - ($(strip $(1))) )
# Default target
all:
# Include LUFA-specific DMBS extension modules
DMBS_LUFA_PATH ?= $(LUFA_PATH)/Build/LUFA
include $(DMBS_LUFA_PATH)/lufa-sources.mk
include $(DMBS_LUFA_PATH)/lufa-gcc.mk
# Include common DMBS build system modules
DMBS_PATH ?= $(LUFA_PATH)/Build/DMBS/DMBS
include $(DMBS_PATH)/core.mk
include $(DMBS_PATH)/cppcheck.mk
include $(DMBS_PATH)/doxygen.mk
include $(DMBS_PATH)/dfu.mk
include $(DMBS_PATH)/gcc.mk
include $(DMBS_PATH)/hid.mk
include $(DMBS_PATH)/avrdude.mk
include $(DMBS_PATH)/atprogram.mk

@ -0,0 +1,76 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2017.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2017 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 disclaims 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
*
* Bootloader user application API functions.
*/
#include "BootloaderAPI.h"
void BootloaderAPI_ErasePage(const uint32_t Address)
{
boot_page_erase_safe(Address);
boot_spm_busy_wait();
boot_rww_enable();
}
void BootloaderAPI_WritePage(const uint32_t Address)
{
boot_page_write_safe(Address);
boot_spm_busy_wait();
boot_rww_enable();
}
void BootloaderAPI_FillWord(const uint32_t Address, const uint16_t Word)
{
boot_page_fill_safe(Address, Word);
}
uint8_t BootloaderAPI_ReadSignature(const uint16_t Address)
{
return boot_signature_byte_get(Address);
}
uint8_t BootloaderAPI_ReadFuse(const uint16_t Address)
{
return boot_lock_fuse_bits_get(Address);
}
uint8_t BootloaderAPI_ReadLock(void)
{
return boot_lock_fuse_bits_get(GET_LOCK_BITS);
}
void BootloaderAPI_WriteLock(const uint8_t LockBits)
{
boot_lock_bits_set_safe(LockBits);
}

@ -0,0 +1,63 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2017.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2017 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 disclaims 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 BootloaderAPI.c.
*/
#ifndef _BOOTLOADER_API_H_
#define _BOOTLOADER_API_H_
/* Includes: */
#include <avr/io.h>
#include <avr/boot.h>
#include <stdbool.h>
#include <LUFA/Common/Common.h>
/* Macros: */
#if AUX_BOOT_SECTION_SIZE > 0
#define AUX_BOOT_SECTION __attribute__((section(".boot_aux")))
#else
#define AUX_BOOT_SECTION
#endif
/* Function Prototypes: */
void BootloaderAPI_ErasePage(const uint32_t Address);
void BootloaderAPI_WritePage(const uint32_t Address);
void BootloaderAPI_FillWord(const uint32_t Address, const uint16_t Word);
uint8_t BootloaderAPI_ReadSignature(const uint16_t Address);
uint8_t BootloaderAPI_ReadFuse(const uint16_t Address);
uint8_t BootloaderAPI_ReadLock(void);
void BootloaderAPI_WriteLock(const uint8_t LockBits);
#endif

@ -0,0 +1,102 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2017.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2017 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 disclaims 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.
*/
#if AUX_BOOT_SECTION_SIZE > 0
#warning Using a AUX bootloader section in addition to the defined bootloader space (see documentation).
; Trampoline to jump over the AUX bootloader section to the start of the bootloader,
; on devices where an AUX bootloader section is used.
.section .boot_aux_trampoline, "ax"
.global Boot_AUX_Trampoline
Boot_AUX_Trampoline:
jmp BOOT_START_ADDR
#endif
; Trampolines to actual API implementations if the target address is outside the
; range of a rjmp instruction (can happen with large bootloader sections)
.section .apitable_trampolines, "ax"
.global BootloaderAPI_Trampolines
BootloaderAPI_Trampolines:
BootloaderAPI_ErasePage_Trampoline:
jmp BootloaderAPI_ErasePage
BootloaderAPI_WritePage_Trampoline:
jmp BootloaderAPI_WritePage
BootloaderAPI_FillWord_Trampoline:
jmp BootloaderAPI_FillWord
BootloaderAPI_ReadSignature_Trampoline:
jmp BootloaderAPI_ReadSignature
BootloaderAPI_ReadFuse_Trampoline:
jmp BootloaderAPI_ReadFuse
BootloaderAPI_ReadLock_Trampoline:
jmp BootloaderAPI_ReadLock
BootloaderAPI_WriteLock_Trampoline:
jmp BootloaderAPI_WriteLock
BootloaderAPI_UNUSED1:
ret
BootloaderAPI_UNUSED2:
ret
BootloaderAPI_UNUSED3:
ret
BootloaderAPI_UNUSED4:
ret
BootloaderAPI_UNUSED5:
ret
; API function jump table
.section .apitable_jumptable, "ax"
.global BootloaderAPI_JumpTable
BootloaderAPI_JumpTable:
rjmp BootloaderAPI_ErasePage_Trampoline
rjmp BootloaderAPI_WritePage_Trampoline
rjmp BootloaderAPI_FillWord_Trampoline
rjmp BootloaderAPI_ReadSignature_Trampoline
rjmp BootloaderAPI_ReadFuse_Trampoline
rjmp BootloaderAPI_ReadLock_Trampoline
rjmp BootloaderAPI_WriteLock_Trampoline
rjmp BootloaderAPI_UNUSED1 ; UNUSED ENTRY 1
rjmp BootloaderAPI_UNUSED2 ; UNUSED ENTRY 2
rjmp BootloaderAPI_UNUSED3 ; UNUSED ENTRY 3
rjmp BootloaderAPI_UNUSED4 ; UNUSED ENTRY 4
rjmp BootloaderAPI_UNUSED5 ; UNUSED ENTRY 5
; Bootloader table signatures and information
.section .apitable_signatures, "ax"
.global BootloaderAPI_Signatures
BootloaderAPI_Signatures:
.long BOOT_START_ADDR ; Start address of the bootloader
.word 0xDF30 ; Signature for the MS class bootloader, V1
.word 0xDCFB ; Signature for a LUFA class bootloader

@ -0,0 +1,263 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2017.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2017 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 disclaims 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 Mass Storage class bootloader. This file contains the complete bootloader logic.
*/
#define INCLUDE_FROM_BOOTLOADER_MASSSTORAGE_C
#include "BootloaderMassStorage.h"
/** LUFA Mass Storage Class driver interface configuration and state information. This structure is
* passed to all Mass Storage Class driver functions, so that multiple instances of the same class
* within a device can be differentiated from one another.
*/
USB_ClassInfo_MS_Device_t Disk_MS_Interface =
{
.Config =
{
.InterfaceNumber = INTERFACE_ID_MassStorage,
.DataINEndpoint =
{
.Address = MASS_STORAGE_IN_EPADDR,
.Size = MASS_STORAGE_IO_EPSIZE,
.Banks = 1,
},
.DataOUTEndpoint =
{
.Address = MASS_STORAGE_OUT_EPADDR,
.Size = MASS_STORAGE_IO_EPSIZE,
.Banks = 1,
},
.TotalLUNs = 1,
},
};
/** 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
* started via a forced watchdog reset.
*/
bool RunBootloader = true;
/** Magic lock for forced application start. If the HWBE fuse is programmed and BOOTRST is unprogrammed, the bootloader
* will start if the /HWB line of the AVR is held low and the system is reset. However, if the /HWB line is still held
* low when the application attempts to start via a watchdog reset, the bootloader will re-start. If set to the value
* \ref MAGIC_BOOT_KEY the special init function \ref Application_Jump_Check() will force the application to start.
*/
uint16_t MagicBootKey ATTR_NO_INIT;
/** Indicates if the bootloader is allowed to exit immediately if \ref RunBootloader is \c false. During shutdown all
* pending commands must be processed before jumping to the user-application, thus this tracks the main program loop
* iterations since a SCSI command from the host was received.
*/
static uint8_t TicksSinceLastCommand = 0;
/** Special startup routine to check if the bootloader was started via a watchdog reset, and if the magic application
* start key has been loaded into \ref MagicBootKey. If the bootloader started via the watchdog and the key is valid,
* this will force the user application to start via a software jump.
*/
void Application_Jump_Check(void)
{
bool JumpToApplication = false;
#if (BOARD == BOARD_LEONARDO)
/* Enable pull-up on the IO13 pin so we can use it to select the mode */
PORTC |= (1 << 7);
Delay_MS(10);
/* If IO13 is not jumpered to ground, start the user application instead */
JumpToApplication = ((PINC & (1 << 7)) != 0);
/* Disable pull-up after the check has completed */
PORTC &= ~(1 << 7);
#elif ((BOARD == BOARD_XPLAIN) || (BOARD == BOARD_XPLAIN_REV1))
/* Disable JTAG debugging */
JTAG_DISABLE();
/* Enable pull-up on the JTAG TCK pin so we can use it to select the mode */
PORTF |= (1 << 4);
Delay_MS(10);
/* If the TCK pin is not jumpered to ground, start the user application instead */
JumpToApplication = ((PINF & (1 << 4)) != 0);
/* Re-enable JTAG debugging */
JTAG_ENABLE();
#else
/* Check if the device's BOOTRST fuse is set */
if (boot_lock_fuse_bits_get(GET_HIGH_FUSE_BITS) & FUSE_BOOTRST)
{
/* If the reset source was not an external reset or the key is correct, clear it and jump to the application */
if (!(MCUSR & (1 << EXTRF)) || (MagicBootKey == MAGIC_BOOT_KEY))
JumpToApplication = true;
/* Clear reset source */
MCUSR &= ~(1 << EXTRF);
}
else
{
/* If the reset source was the bootloader and the key is correct, clear it and jump to the application;
* this can happen in the HWBE fuse is set, and the HBE pin is low during the watchdog reset */
if ((MCUSR & (1 << WDRF)) && (MagicBootKey == MAGIC_BOOT_KEY))
JumpToApplication = true;
/* Clear reset source */
MCUSR &= ~(1 << WDRF);
}
#endif
/* Don't run the user application if the reset vector is blank (no app loaded) */
bool ApplicationValid = (pgm_read_word_near(0) != 0xFFFF);
/* If a request has been made to jump to the user application, honor it */
if (JumpToApplication && ApplicationValid)
{
/* Turn off the watchdog */
MCUSR &= ~(1 << WDRF);
wdt_disable();
/* Clear the boot key and jump to the user application */
MagicBootKey = 0;
// cppcheck-suppress constStatement
((void (*)(void))0x0000)();
}
}
/** Main program entry point. This routine configures the hardware required by the application, then
* enters a loop to run the application tasks in sequence.
*/
int main(void)
{
SetupHardware();
LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);
GlobalInterruptEnable();
while (RunBootloader || TicksSinceLastCommand++ < 0xFF)
{
MS_Device_USBTask(&Disk_MS_Interface);
USB_USBTask();
}
/* Disconnect from the host - USB interface will be reset later along with the AVR */
USB_Detach();
/* Unlock the forced application start mode of the bootloader if it is restarted */
MagicBootKey = MAGIC_BOOT_KEY;
/* Enable the watchdog and force a timeout to reset the AVR */
wdt_enable(WDTO_250MS);
for (;;);
}
/** Configures the board hardware and chip peripherals for the demo's functionality. */
static 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);
/* Hardware Initialization */
LEDs_Init();
USB_Init();
/* Bootloader active LED toggle timer initialization */
TIMSK1 = (1 << TOIE1);
TCCR1B = ((1 << CS11) | (1 << CS10));
}
/** ISR to periodically toggle the LEDs on the board to indicate that the bootloader is active. */
ISR(TIMER1_OVF_vect, ISR_BLOCK)
{
LEDs_ToggleLEDs(LEDS_LED1 | LEDS_LED2);
}
/** Event handler for the USB_Connect event. This indicates that the device is enumerating via the status LEDs. */
void EVENT_USB_Device_Connect(void)
{
/* Indicate USB enumerating */
LEDs_SetAllLEDs(LEDMASK_USB_ENUMERATING);
}
/** Event handler for the USB_Disconnect event. This indicates that the device is no longer connected to a host via
* the status LEDs and stops the Mass Storage management task.
*/
void EVENT_USB_Device_Disconnect(void)
{
/* Indicate USB not ready */
LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);
}
/** Event handler for the library USB Configuration Changed event. */
void EVENT_USB_Device_ConfigurationChanged(void)
{
bool ConfigSuccess = true;
/* Setup Mass Storage Data Endpoints */
ConfigSuccess &= MS_Device_ConfigureEndpoints(&Disk_MS_Interface);
/* Indicate endpoint configuration success or failure */
LEDs_SetAllLEDs(ConfigSuccess ? LEDMASK_USB_READY : LEDMASK_USB_ERROR);
}
/** Event handler for the library USB Control Request reception event. */
void EVENT_USB_Device_ControlRequest(void)
{
MS_Device_ProcessControlRequest(&Disk_MS_Interface);
}
/** Mass Storage class driver callback function the reception of SCSI commands from the host, which must be processed.
*
* \param[in] MSInterfaceInfo Pointer to the Mass Storage class interface configuration structure being referenced
*/
bool CALLBACK_MS_Device_SCSICommandReceived(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
{
bool CommandSuccess;
LEDs_SetAllLEDs(LEDMASK_USB_BUSY);
CommandSuccess = SCSI_DecodeSCSICommand(MSInterfaceInfo);
LEDs_SetAllLEDs(LEDMASK_USB_READY);
/* Signal that a command was processed, must not exit bootloader yet */
TicksSinceLastCommand = 0;
return CommandSuccess;
}

@ -0,0 +1,99 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2017.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2017 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 disclaims 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 BootloaderMassStorage.c.
*/
#ifndef _BOOTLOADER_MASS_STORAGE_H_
#define _BOOTLOADER_MASS_STORAGE_H_
/* Includes: */
#include <avr/io.h>
#include <avr/wdt.h>
#include <avr/power.h>
#include <avr/interrupt.h>
#include <string.h>
#include "Descriptors.h"
#include "Config/AppConfig.h"
#include "Lib/SCSI.h"
#include <LUFA/Drivers/Board/LEDs.h>
#include <LUFA/Drivers/USB/USB.h>
#include <LUFA/Platform/Platform.h>
/* Preprocessor Checks: */
#if !defined(__OPTIMIZE_SIZE__)
#error This bootloader requires that it be optimized for size, not speed, to fit into the target device. Change optimization settings and try again.
#endif
/* Macros: */
/** LED mask for the library LED driver, to indicate that the USB interface is not ready. */
#define LEDMASK_USB_NOTREADY LEDS_LED1
/** LED mask for the library LED driver, to indicate that the USB interface is enumerating. */
#define LEDMASK_USB_ENUMERATING (LEDS_LED2 | LEDS_LED3)
/** LED mask for the library LED driver, to indicate that the USB interface is ready. */
#define LEDMASK_USB_READY (LEDS_LED2 | LEDS_LED4)
/** LED mask for the library LED driver, to indicate that an error has occurred in the USB interface. */
#define LEDMASK_USB_ERROR (LEDS_LED1 | LEDS_LED3)
/** LED mask for the library LED driver, to indicate that the USB interface is busy. */
#define LEDMASK_USB_BUSY LEDS_LED2
/** Magic bootloader key to unlock forced application start mode. */
#define MAGIC_BOOT_KEY 0xDC42
/* Global Variables: */
extern bool RunBootloader;
/* Function Prototypes: */
int main(void) AUX_BOOT_SECTION;
void Application_Jump_Check(void) ATTR_INIT_SECTION(3);
void EVENT_USB_Device_Connect(void) AUX_BOOT_SECTION;
void EVENT_USB_Device_Disconnect(void) AUX_BOOT_SECTION;
void EVENT_USB_Device_ConfigurationChanged(void) AUX_BOOT_SECTION;
void EVENT_USB_Device_ControlRequest(void) AUX_BOOT_SECTION;
bool CALLBACK_MS_Device_SCSICommandReceived(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) AUX_BOOT_SECTION;
#if defined(INCLUDE_FROM_BOOTLOADER_MASSSTORAGE_C)
static void SetupHardware(void) AUX_BOOT_SECTION;
#endif
#endif

@ -0,0 +1,240 @@
/** \file
*
* This file contains special DoxyGen information for the generation of the main page and other special
* documentation pages. It is not a project source file.
*/
/** \mainpage Mass Storage Class USB AVR Bootloader
*
* \section Sec_Compat Demo Compatibility:
*
* The following list indicates what microcontrollers are compatible with this demo.
*
* \li Series 7 USB AVRs (AT90USBxxx7)
* \li Series 6 USB AVRs (AT90USBxxx6)
* \li Series 4 USB AVRs (ATMEGAxxU4) - <i>See \ref SSec_Aux_Space</i>
* \li ATMEGA32U2 - <i>See \ref SSec_Aux_Space</i>
*
* \section Sec_Info USB Information:
*
* The following table gives a rundown of the USB utilization of this demo.
*
* <table>
* <tr>
* <td><b>USB Mode:</b></td>
* <td>Device</td>
* </tr>
* <tr>
* <td><b>USB Class:</b></td>
* <td>Mass Storage Device</td>
* </tr>
* <tr>
* <td><b>USB Subclass:</b></td>
* <td>Bulk-Only Transport</td>
* </tr>
* <tr>
* <td><b>Relevant Standards:</b></td>
* <td>USBIF Mass Storage Standard \n
* USB Bulk-Only Transport Standard \n
* SCSI Primary Commands Specification \n
* SCSI Block Commands Specification</td>
* </tr>
* <tr>
* <td><b>Supported USB Speeds:</b></td>
* <td>Full Speed Mode</td>
* </tr>
* </table>
*
* \section Sec_Description Project Description:
*
* This bootloader enumerates to the host as a Mass Storage device, capable of reading and writing a new binary
* firmware image file, to load firmware onto the AVR.
*
* Out of the box this bootloader builds for the AT90USB1287 with an 8KB bootloader section size, and will fit
* into 6KB of bootloader space. If you wish to alter this size and/or change the AVR model, you will need to
* edit the MCU, FLASH_SIZE_KB and BOOT_SECTION_SIZE_KB values in the accompanying makefile.
*
* When the bootloader is running, the board's LED(s) will flash at regular intervals to distinguish the
* bootloader from the normal user application.
*
* \warning <b>THIS BOOTLOADER IS NOT SECURE.</b> Malicious entities can recover written data, even if the device
* lockbits are set.
*
* \section Sec_Running Running the Bootloader
*
* On the USB AVR8 devices, setting the \c HWBE device fuse will cause the bootloader to run if the \c HWB pin of
* the AVR is grounded when the device is reset.
*
* The are two behaviours of this bootloader, depending on the device's fuses:
*
* <b>If the device's BOOTRST fuse is set</b>, the bootloader will run any time the system is reset from
* the external reset pin, unless no valid user application has been loaded. To initiate the bootloader, the
* device's external reset pin should be grounded momentarily.
*
* <b>If the device's BOOTRST fuse is not set</b>, the bootloader will run only if initiated via a software
* jump, or if the \c HWB pin was low during the last device reset (if the \c HWBE fuse is set).
*
* For board specific exceptions to the above, see below.
*
* \subsection SSec_XPLAIN Atmel Xplain Board
* Ground the USB AVR JTAG's \c TCK pin to ground when powering on the board to start the bootloader. This assumes the
* \c HWBE fuse is cleared and the \c BOOTRST fuse is set as the HWBE pin is not user accessible on this board.
*
* \subsection SSec_Leonardo Arduino Leonardo Board
* Ground \c IO13 when powering the board to start the bootloader. This assumes the \c HWBE fuse is cleared and the
* \c BOOTRST fuse is set as the HWBE pin is not user accessible on this board.
*
* \section Sec_Installation Driver Installation
*
* This bootloader uses the Mass Storage drivers inbuilt into all modern operating systems, thus no additional
* drivers need to be supplied for correct operation.
*
* \section Sec_HostApp Host Controller Application
*
* This bootloader is compatible with all operating systems that support the FAT12 file system format. To reprogram the
* device, overwrite a file stored on the virtual FAT filesystem with a new binary (BIN format) image. Remember to safely
* remove your device from the host using the host OS's ejection APIs, to ensure all data is correctly flushed to the
* bootloader's virtual filesystem and not cached in the OS's file system driver.
*
* The current device firmware can be read from the device by reading a file from the virtual FAT filesystem. Two files will
* be present:
* - <b>FLASH.BIN</b>, representing the AVR's internal flash memory
* - <b>EEPROM.BIN</b>, representing the AVR's internal EEPROM memory
*
* To convert an existing Intel HEX (.HEX) program file to a binary (.BIN) file suitable for this bootloader, run:
* \code
* avr-objcopy -O binary -R .eeprom -R .fuse -R .lock -R .signature input.hex output.bin
* \endcode
* From a terminal, replacing <tt>input.hex</tt> and <tt>output.bin</tt> with the respective input and output filenames.
* AVR EEPROM data files in Intel HEX format (.EEP) uses a similar technique:
* \code
* avr-objcopy -O binary input.eep output.bin
* \endcode
*
* \warning This bootloader is currently <b>incompatible with the Apple MacOS X OS Finder GUI</b>, due to the
* large amount of meta files this OS attempts to write to the disk along with the new binaries. On
* this platform, firmwares must be copied to the disk via the Terminal application only to prevent
* firmware corruption.
*
* \section Sec_API User Application API
*
* Several user application functions for FLASH and other special memory area manipulations are exposed by the bootloader,
* allowing the user application to call into the bootloader at runtime to read and write FLASH data.
*
* By default, the bootloader API jump table is located 32 bytes from the end of the device's FLASH memory, and follows the
* following layout:
*
* \code
* #define BOOTLOADER_API_TABLE_SIZE 32
* #define BOOTLOADER_API_TABLE_START ((FLASHEND + 1UL) - BOOTLOADER_API_TABLE_SIZE)
* #define BOOTLOADER_API_CALL(Index) (void*)((BOOTLOADER_API_TABLE_START + (Index * 2)) / 2)
*
* void (*BootloaderAPI_ErasePage)(uint32_t Address) = BOOTLOADER_API_CALL(0);
* void (*BootloaderAPI_WritePage)(uint32_t Address) = BOOTLOADER_API_CALL(1);
* void (*BootloaderAPI_FillWord)(uint32_t Address, uint16_t Word) = BOOTLOADER_API_CALL(2);
* uint8_t (*BootloaderAPI_ReadSignature)(uint16_t Address) = BOOTLOADER_API_CALL(3);
* uint8_t (*BootloaderAPI_ReadFuse)(uint16_t Address) = BOOTLOADER_API_CALL(4);
* uint8_t (*BootloaderAPI_ReadLock)(void) = BOOTLOADER_API_CALL(5);
* void (*BootloaderAPI_WriteLock)(uint8_t LockBits) = BOOTLOADER_API_CALL(6);
*
* #define BOOTLOADER_MAGIC_SIGNATURE_START (BOOTLOADER_API_TABLE_START + (BOOTLOADER_API_TABLE_SIZE - 2))
* #define BOOTLOADER_MAGIC_SIGNATURE 0xDCFB
*
* #define BOOTLOADER_CLASS_SIGNATURE_START (BOOTLOADER_API_TABLE_START + (BOOTLOADER_API_TABLE_SIZE - 4))
* #define BOOTLOADER_MASS_STORAGE_SIGNATURE 0xDF30
*
* #define BOOTLOADER_ADDRESS_START (BOOTLOADER_API_TABLE_START + (BOOTLOADER_API_TABLE_SIZE - 8))
* #define BOOTLOADER_ADDRESS_LENGTH 4
* \endcode
*
* From the application the API support of the bootloader can be detected by reading the FLASH memory bytes located at address
* \c BOOTLOADER_MAGIC_SIGNATURE_START and comparing them to the value \c BOOTLOADER_MAGIC_SIGNATURE. The class of bootloader
* can be determined by reading the FLASH memory bytes located at address \c BOOTLOADER_CLASS_SIGNATURE_START and comparing them
* to the value \c BOOTLOADER_MASS_STORAGE_SIGNATURE. The start address of the bootloader can be retrieved by reading the bytes
* of FLASH memory starting from address \c BOOTLOADER_ADDRESS_START.
*
* \subsection SSec_Aux_Space Auxiliary Bootloader Section
* To make the bootloader function on smaller devices (those with a physical bootloader section of smaller than 6KB) a second
* section of memory (called the <i>Auxiliary Bootloader Section</i>) is added before the start of the real bootloader section,
* and is filled with a portion of the bootloader code. This allows smaller devices to run the bootloader, at the cost of an
* additional portion of the device's FLASH (the bootloader section size in KB subtracted from the 6KB total size). A small
* trampoline is inserted at the start of the auxiliary section so that the bootloader will run normally in the case of a blank
* application section.
*
* On devices supporting a 8KB bootloader section size, the AUX section is not created in the final binary.
*
* \subsection SSec_API_MemLayout Device Memory Map
* The following illustration indicates the final memory map of the device when loaded with the bootloader.
*
* \verbatim
* +----------------------------+ 0x0000
* | |
* | |
* | |
* | |
* | |
* | |
* | |
* | |
* | User Application |
* | |
* | |
* | |
* | |
* | |
* | |
* | |
* | |
* +----------------------------+ FLASHEND - BOOT_SECTION_SIZE - BOOT_AUX_SECTION_SIZE
* | Booloader Start Trampoline |
* | (Not User App. Accessible) |
* +----------------------------+ FLASHEND - BOOT_SECTION_SIZE - BOOT_AUX_SECTION_SIZE + 4
* | |
* | Auxiliary Bootloader |
* | Space for Smaller Devices |
* | (Not User App. Accessible) |
* | |
* +----------------------------+ FLASHEND - BOOT_SECTION_SIZE
* | |
* | Bootloader Application |
* | (Not User App. Accessible) |
* | |
* +----------------------------+ FLASHEND - 96
* | API Table Trampolines |
* | (Not User App. Accessible) |
* +----------------------------+ FLASHEND - 32
* | Bootloader API Table |
* | (User App. Accessible) |
* +----------------------------+ FLASHEND - 8
* | Bootloader ID Constants |
* | (User App. Accessible) |
* +----------------------------+ FLASHEND
* \endverbatim
*
* \section Sec_KnownIssues Known Issues:
*
* \par In some cases, the application is not fully loaded into the device.
* Write-caching on some operating systems may interfere with the normal
* operation of the bootloader. Write caching should be disabled when using the
* Mass Storage bootloader, or the file system synced via an appropriate command
* (such as the OS's normal disk ejection command) before disconnecting the device.
*
* \section Sec_Options Project Options
*
* The following defines can be found in this demo, which can control the demo behaviour when defined, or changed in value.
*
* <table>
* <tr>
* <th><b>Define Name:</b></th>
* <th><b>Location:</b></th>
* <th><b>Description:</b></th>
* </tr>
* <tr>
* <td>NO_APP_START_ON_EJECT</td>
* <td>AppConfig.h</td>
* <td>Define to disable automatic start of the loaded application when the virtual
* Mass Storage disk is ejected on the host.</td>
* </tr>
* </table>
*/

@ -0,0 +1,47 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2017.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2017 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 disclaims 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
* \brief Application Configuration Header File
*
* This is a header file which is be used to configure LUFA's
* compile time options, as an alternative to the compile time
* constants supplied through a makefile.
*
* For information on what each token does, refer to the
* \ref Sec_Options section of the application documentation.
*/
#ifndef _APP_CONFIG_H_
#define _APP_CONFIG_H_
// #define NO_APP_START_ON_EJECT
#endif

@ -0,0 +1,93 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2017.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2017 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 disclaims 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
* \brief LUFA Library Configuration Header File
*
* This header file is used to configure LUFA's compile time options,
* as an alternative to the compile time constants supplied through
* a makefile.
*
* For information on what each token does, refer to the LUFA
* manual section "Summary of Compile Tokens".
*/
#ifndef _LUFA_CONFIG_H_
#define _LUFA_CONFIG_H_
#if (ARCH == ARCH_AVR8)
/* Non-USB Related Configuration Tokens: */
// #define DISABLE_TERMINAL_CODES
/* USB Class Driver Related Tokens: */
// #define HID_HOST_BOOT_PROTOCOL_ONLY
// #define HID_STATETABLE_STACK_DEPTH {Insert Value Here}
// #define HID_USAGE_STACK_DEPTH {Insert Value Here}
// #define HID_MAX_COLLECTIONS {Insert Value Here}
// #define HID_MAX_REPORTITEMS {Insert Value Here}
// #define HID_MAX_REPORT_IDS {Insert Value Here}
// #define NO_CLASS_DRIVER_AUTOFLUSH
/* General USB Driver Related Tokens: */
#define ORDERED_EP_CONFIG
#define USE_STATIC_OPTIONS (USB_DEVICE_OPT_FULLSPEED | USB_OPT_REG_ENABLED | USB_OPT_AUTO_PLL)
#define USB_DEVICE_ONLY
// #define USB_HOST_ONLY
// #define USB_STREAM_TIMEOUT_MS {Insert Value Here}
// #define NO_LIMITED_CONTROLLER_CONNECT
#define NO_SOF_EVENTS
/* USB Device Mode Driver Related Tokens: */
#define USE_RAM_DESCRIPTORS
// #define USE_FLASH_DESCRIPTORS
// #define USE_EEPROM_DESCRIPTORS
#define NO_INTERNAL_SERIAL
#define FIXED_CONTROL_ENDPOINT_SIZE 8
#define DEVICE_STATE_AS_GPIOR 0
#define FIXED_NUM_CONFIGURATIONS 1
// #define CONTROL_ONLY_DEVICE
#define INTERRUPT_CONTROL_ENDPOINT
#define NO_DEVICE_REMOTE_WAKEUP
#define NO_DEVICE_SELF_POWER
/* USB Host Mode Driver Related Tokens: */
// #define HOST_STATE_AS_GPIOR {Insert Value Here}
// #define USB_HOST_TIMEOUT_MS {Insert Value Here}
// #define HOST_DEVICE_SETTLE_DELAY_MS {Insert Value Here}
// #define NO_AUTO_VBUS_MANAGEMENT
// #define INVERTED_VBUS_ENABLE_LINE
#else
#error Unsupported architecture for this LUFA configuration file.
#endif
#endif

@ -0,0 +1,157 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2017.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2017 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 disclaims 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(1,1,0),
.Class = USB_CSCP_NoDeviceClass,
.SubClass = USB_CSCP_NoDeviceSubclass,
.Protocol = USB_CSCP_NoDeviceProtocol,
.Endpoint0Size = FIXED_CONTROL_ENDPOINT_SIZE,
.VendorID = 0x03EB,
.ProductID = 0x2045,
.ReleaseNumber = VERSION_BCD(0,0,1),
.ManufacturerStrIndex = NO_DESCRIPTOR,
.ProductStrIndex = NO_DESCRIPTOR,
.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.
*/
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 = 1,
.ConfigurationNumber = 1,
.ConfigurationStrIndex = NO_DESCRIPTOR,
.ConfigAttributes = USB_CONFIG_ATTR_RESERVED,
.MaxPowerConsumption = USB_CONFIG_POWER_MA(100)
},
.MS_Interface =
{
.Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},
.InterfaceNumber = INTERFACE_ID_MassStorage,
.AlternateSetting = 0,
.TotalEndpoints = 2,
.Class = MS_CSCP_MassStorageClass,
.SubClass = MS_CSCP_SCSITransparentSubclass,
.Protocol = MS_CSCP_BulkOnlyTransportProtocol,
.InterfaceStrIndex = NO_DESCRIPTOR
},
.MS_DataInEndpoint =
{
.Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
.EndpointAddress = MASS_STORAGE_IN_EPADDR,
.Attributes = (EP_TYPE_BULK | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
.EndpointSize = MASS_STORAGE_IO_EPSIZE,
.PollingIntervalMS = 0x05
},
.MS_DataOutEndpoint =
{
.Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
.EndpointAddress = MASS_STORAGE_OUT_EPADDR,
.Attributes = (EP_TYPE_BULK | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
.EndpointSize = MASS_STORAGE_IO_EPSIZE,
.PollingIntervalMS = 0x05
}
};
/** 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 uint16_t wIndex,
const void** const DescriptorAddress)
{
const uint8_t DescriptorType = (wValue >> 8);
const void* Address = NULL;
uint16_t Size = NO_DESCRIPTOR;
/* If/Else If chain compiles slightly smaller than a switch case */
if (DescriptorType == DTYPE_Device)
{
Address = &DeviceDescriptor;
Size = sizeof(USB_Descriptor_Device_t);
}
else if (DescriptorType == DTYPE_Configuration)
{
Address = &ConfigurationDescriptor;
Size = sizeof(USB_Descriptor_Configuration_t);
}
*DescriptorAddress = Address;
return Size;
}

@ -0,0 +1,88 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2017.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2017 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 disclaims 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 "BootloaderAPI.h"
/* Macros: */
/** Endpoint address of the Mass Storage device-to-host data IN endpoint. */
#define MASS_STORAGE_IN_EPADDR (ENDPOINT_DIR_IN | 3)
/** Endpoint address of the Mass Storage host-to-device data OUT endpoint. */
#define MASS_STORAGE_OUT_EPADDR (ENDPOINT_DIR_OUT | 4)
/** Size in bytes of the Mass Storage data endpoints. */
#define MASS_STORAGE_IO_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;
// Mass Storage Interface
USB_Descriptor_Interface_t MS_Interface;
USB_Descriptor_Endpoint_t MS_DataInEndpoint;
USB_Descriptor_Endpoint_t MS_DataOutEndpoint;
} USB_Descriptor_Configuration_t;
/** Enum for the device interface descriptor IDs within the device. Each interface descriptor
* should have a unique ID index associated with it, which can be used to refer to the
* interface from other descriptors.
*/
enum InterfaceDescriptors_t
{
INTERFACE_ID_MassStorage = 0, /**< Mass storage interface descriptor ID */
};
/* Function Prototypes: */
uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue,
const uint16_t wIndex,
const void** const DescriptorAddress)
ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(3) AUX_BOOT_SECTION;
#endif

@ -0,0 +1,294 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2017.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2017 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 disclaims 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
*
* SCSI command processing routines, for SCSI commands issued by the host. Mass Storage
* devices use a thin "Bulk-Only Transport" protocol for issuing commands and status information,
* which wrap around standard SCSI device commands for controlling the actual storage medium.
*/
#define INCLUDE_FROM_SCSI_C
#include "SCSI.h"
/** Structure to hold the SCSI response data to a SCSI INQUIRY command. This gives information about the device's
* features and capabilities.
*/
static const SCSI_Inquiry_Response_t InquiryData =
{
.DeviceType = DEVICE_TYPE_BLOCK,
.PeripheralQualifier = 0,
.Removable = true,
.Version = 0,
.ResponseDataFormat = 2,
.NormACA = false,
.TrmTsk = false,
.AERC = false,
.AdditionalLength = 0x1F,
.SoftReset = false,
.CmdQue = false,
.Linked = false,
.Sync = false,
.WideBus16Bit = false,
.WideBus32Bit = false,
.RelAddr = false,
.VendorID = "LUFA",
.ProductID = "Bootloader",
.RevisionID = {'0','.','0','0'},
};
/** Structure to hold the sense data for the last issued SCSI command, which is returned to the host after a SCSI REQUEST SENSE
* command is issued. This gives information on exactly why the last command failed to complete.
*/
static SCSI_Request_Sense_Response_t SenseData =
{
.ResponseCode = 0x70,
.AdditionalLength = 0x0A,
};
/** Main routine to process the SCSI command located in the Command Block Wrapper read from the host. This dispatches
* to the appropriate SCSI command handling routine if the issued command is supported by the device, else it returns
* a command failure due to a ILLEGAL REQUEST.
*
* \param[in] MSInterfaceInfo Pointer to the Mass Storage class interface structure that the command is associated with
*
* \return Boolean \c true if the command completed successfully, \c false otherwise
*/
bool SCSI_DecodeSCSICommand(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
{
bool CommandSuccess = false;
/* Run the appropriate SCSI command hander function based on the passed command */
switch (MSInterfaceInfo->State.CommandBlock.SCSICommandData[0])
{
case SCSI_CMD_INQUIRY:
CommandSuccess = SCSI_Command_Inquiry(MSInterfaceInfo);
break;
case SCSI_CMD_REQUEST_SENSE:
CommandSuccess = SCSI_Command_Request_Sense(MSInterfaceInfo);
break;
case SCSI_CMD_READ_CAPACITY_10:
CommandSuccess = SCSI_Command_Read_Capacity_10(MSInterfaceInfo);
break;
case SCSI_CMD_WRITE_10:
CommandSuccess = SCSI_Command_ReadWrite_10(MSInterfaceInfo, DATA_WRITE);
break;
case SCSI_CMD_READ_10:
CommandSuccess = SCSI_Command_ReadWrite_10(MSInterfaceInfo, DATA_READ);
break;
case SCSI_CMD_MODE_SENSE_6:
CommandSuccess = SCSI_Command_ModeSense_6(MSInterfaceInfo);
break;
case SCSI_CMD_START_STOP_UNIT:
#if !defined(NO_APP_START_ON_EJECT)
/* If the user ejected the volume, signal bootloader exit at next opportunity. */
RunBootloader = ((MSInterfaceInfo->State.CommandBlock.SCSICommandData[4] & 0x03) != 0x02);
#endif
case SCSI_CMD_SEND_DIAGNOSTIC:
case SCSI_CMD_TEST_UNIT_READY:
case SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL:
case SCSI_CMD_VERIFY_10:
/* These commands should just succeed, no handling required */
CommandSuccess = true;
MSInterfaceInfo->State.CommandBlock.DataTransferLength = 0;
break;
default:
/* Update the SENSE key to reflect the invalid command */
SCSI_SET_SENSE(SCSI_SENSE_KEY_ILLEGAL_REQUEST,
SCSI_ASENSE_INVALID_COMMAND,
SCSI_ASENSEQ_NO_QUALIFIER);
break;
}
/* Check if command was successfully processed */
if (CommandSuccess)
{
SCSI_SET_SENSE(SCSI_SENSE_KEY_GOOD,
SCSI_ASENSE_NO_ADDITIONAL_INFORMATION,
SCSI_ASENSEQ_NO_QUALIFIER);
return true;
}
return false;
}
/** Command processing for an issued SCSI INQUIRY command. This command returns information about the device's features
* and capabilities to the host.
*
* \param[in] MSInterfaceInfo Pointer to the Mass Storage class interface structure that the command is associated with
*
* \return Boolean \c true if the command completed successfully, \c false otherwise.
*/
static bool SCSI_Command_Inquiry(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
{
uint16_t AllocationLength = SwapEndian_16(*(uint16_t*)&MSInterfaceInfo->State.CommandBlock.SCSICommandData[3]);
uint16_t BytesTransferred = MIN(AllocationLength, sizeof(InquiryData));
/* Only the standard INQUIRY data is supported, check if any optional INQUIRY bits set */
if ((MSInterfaceInfo->State.CommandBlock.SCSICommandData[1] & ((1 << 0) | (1 << 1))) ||
MSInterfaceInfo->State.CommandBlock.SCSICommandData[2])
{
/* Optional but unsupported bits set - update the SENSE key and fail the request */
SCSI_SET_SENSE(SCSI_SENSE_KEY_ILLEGAL_REQUEST,
SCSI_ASENSE_INVALID_FIELD_IN_CDB,
SCSI_ASENSEQ_NO_QUALIFIER);
return false;
}
Endpoint_Write_Stream_LE(&InquiryData, BytesTransferred, NULL);
/* Pad out remaining bytes with 0x00 */
Endpoint_Null_Stream((AllocationLength - BytesTransferred), NULL);
/* Finalize the stream transfer to send the last packet */
Endpoint_ClearIN();
/* Succeed the command and update the bytes transferred counter */
MSInterfaceInfo->State.CommandBlock.DataTransferLength -= BytesTransferred;
return true;
}
/** Command processing for an issued SCSI REQUEST SENSE command. This command returns information about the last issued command,
* including the error code and additional error information so that the host can determine why a command failed to complete.
*
* \param[in] MSInterfaceInfo Pointer to the Mass Storage class interface structure that the command is associated with
*
* \return Boolean \c true if the command completed successfully, \c false otherwise.
*/
static bool SCSI_Command_Request_Sense(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
{
uint8_t AllocationLength = MSInterfaceInfo->State.CommandBlock.SCSICommandData[4];
uint8_t BytesTransferred = MIN(AllocationLength, sizeof(SenseData));
Endpoint_Write_Stream_LE(&SenseData, BytesTransferred, NULL);
Endpoint_Null_Stream((AllocationLength - BytesTransferred), NULL);
Endpoint_ClearIN();
/* Succeed the command and update the bytes transferred counter */
MSInterfaceInfo->State.CommandBlock.DataTransferLength -= BytesTransferred;
return true;
}
/** Command processing for an issued SCSI READ CAPACITY (10) command. This command returns information about the device's capacity
* on the selected Logical Unit (drive), as a number of OS-sized blocks.
*
* \param[in] MSInterfaceInfo Pointer to the Mass Storage class interface structure that the command is associated with
*
* \return Boolean \c true if the command completed successfully, \c false otherwise.
*/
static bool SCSI_Command_Read_Capacity_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
{
Endpoint_Write_32_BE(LUN_MEDIA_BLOCKS - 1);
Endpoint_Write_32_BE(SECTOR_SIZE_BYTES);
Endpoint_ClearIN();
/* Succeed the command and update the bytes transferred counter */
MSInterfaceInfo->State.CommandBlock.DataTransferLength -= 8;
return true;
}
/** Command processing for an issued SCSI READ (10) or WRITE (10) command. This command reads in the block start address
* and total number of blocks to process, then calls the appropriate low-level Dataflash routine to handle the actual
* reading and writing of the data.
*
* \param[in] MSInterfaceInfo Pointer to the Mass Storage class interface structure that the command is associated with
* \param[in] IsDataRead Indicates if the command is a READ (10) command or WRITE (10) command (DATA_READ or DATA_WRITE)
*
* \return Boolean \c true if the command completed successfully, \c false otherwise.
*/
static bool SCSI_Command_ReadWrite_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo,
const bool IsDataRead)
{
uint16_t BlockAddress;
uint16_t TotalBlocks;
/* Load in the 32-bit block address (SCSI uses big-endian, so have to reverse the byte order) */
BlockAddress = SwapEndian_32(*(uint32_t*)&MSInterfaceInfo->State.CommandBlock.SCSICommandData[2]);
/* Load in the 16-bit total blocks (SCSI uses big-endian, so have to reverse the byte order) */
TotalBlocks = SwapEndian_16(*(uint16_t*)&MSInterfaceInfo->State.CommandBlock.SCSICommandData[7]);
/* Check if the block address is outside the maximum allowable value for the LUN */
if (BlockAddress >= LUN_MEDIA_BLOCKS)
{
/* Block address is invalid, update SENSE key and return command fail */
SCSI_SET_SENSE(SCSI_SENSE_KEY_ILLEGAL_REQUEST,
SCSI_ASENSE_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE,
SCSI_ASENSEQ_NO_QUALIFIER);
return false;
}
/* Determine if the packet is a READ (10) or WRITE (10) command, call appropriate function */
for (uint16_t i = 0; i < TotalBlocks; i++)
{
if (IsDataRead == DATA_READ)
VirtualFAT_ReadBlock(BlockAddress + i);
else
VirtualFAT_WriteBlock(BlockAddress + i);
}
/* Update the bytes transferred counter and succeed the command */
MSInterfaceInfo->State.CommandBlock.DataTransferLength -= ((uint32_t)TotalBlocks * SECTOR_SIZE_BYTES);
return true;
}
/** Command processing for an issued SCSI MODE SENSE (6) command. This command returns various informational pages about
* the SCSI device, as well as the device's Write Protect status.
*
* \param[in] MSInterfaceInfo Pointer to the Mass Storage class interface structure that the command is associated with
*
* \return Boolean \c true if the command completed successfully, \c false otherwise.
*/
static bool SCSI_Command_ModeSense_6(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
{
/* Send an empty header response indicating Write Protect flag is off */
Endpoint_Write_32_LE(0);
Endpoint_ClearIN();
/* Update the bytes transferred counter and succeed the command */
MSInterfaceInfo->State.CommandBlock.DataTransferLength -= 4;
return true;
}

@ -0,0 +1,84 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2017.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2017 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 disclaims 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 SCSI.c.
*/
#ifndef _SCSI_H_
#define _SCSI_H_
/* Includes: */
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <LUFA/Drivers/USB/USB.h>
#include "../BootloaderMassStorage.h"
#include "../Descriptors.h"
#include "VirtualFAT.h"
/* Macros: */
/** Macro to set the current SCSI sense data to the given key, additional sense code and additional sense qualifier. This
* is for convenience, as it allows for all three sense values (returned upon request to the host to give information about
* the last command failure) in a quick and easy manner.
*
* \param[in] Key New SCSI sense key to set the sense code to
* \param[in] Acode New SCSI additional sense key to set the additional sense code to
* \param[in] Aqual New SCSI additional sense key qualifier to set the additional sense qualifier code to
*/
#define SCSI_SET_SENSE(Key, Acode, Aqual) do { SenseData.SenseKey = (Key); \
SenseData.AdditionalSenseCode = (Acode); \
SenseData.AdditionalSenseQualifier = (Aqual); } while (0)
/** Macro for the \ref SCSI_Command_ReadWrite_10() function, to indicate that data is to be read from the storage medium. */
#define DATA_READ true
/** Macro for the \ref SCSI_Command_ReadWrite_10() function, to indicate that data is to be written to the storage medium. */
#define DATA_WRITE false
/** Value for the DeviceType entry in the SCSI_Inquiry_Response_t enum, indicating a Block Media device. */
#define DEVICE_TYPE_BLOCK 0x00
/* Function Prototypes: */
bool SCSI_DecodeSCSICommand(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) AUX_BOOT_SECTION;
#if defined(INCLUDE_FROM_SCSI_C)
static bool SCSI_Command_Inquiry(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) AUX_BOOT_SECTION;
static bool SCSI_Command_Request_Sense(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) AUX_BOOT_SECTION;
static bool SCSI_Command_Read_Capacity_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) AUX_BOOT_SECTION;
static bool SCSI_Command_ReadWrite_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo,
const bool IsDataRead) AUX_BOOT_SECTION;
static bool SCSI_Command_ModeSense_6(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) AUX_BOOT_SECTION;
#endif
#endif

@ -0,0 +1,482 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2017.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2017 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 disclaims 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
*
* Virtualized FAT12 filesystem implementation, to perform self-programming
* in response to read and write requests to the virtual filesystem by the
* host PC.
*/
#define INCLUDE_FROM_VIRTUAL_FAT_C
#include "VirtualFAT.h"
/** FAT filesystem boot sector block, must be the first sector on the physical
* disk so that the host can identify the presence of a FAT filesystem. This
* block is truncated; normally a large bootstrap section is located near the
* end of the block for booting purposes however as this is not meant to be a
* bootable disk it is omitted for space reasons.
*
* \note When returning the boot block to the host, the magic signature 0xAA55
* must be added to the very end of the block to identify it as a boot
* block.
*/
static const FATBootBlock_t BootBlock =
{
.Bootstrap = {0xEB, 0x3C, 0x90},
.Description = "mkdosfs",
.SectorSize = SECTOR_SIZE_BYTES,
.SectorsPerCluster = SECTOR_PER_CLUSTER,
.ReservedSectors = 1,
.FATCopies = 2,
.RootDirectoryEntries = (SECTOR_SIZE_BYTES / sizeof(FATDirectoryEntry_t)),
.TotalSectors16 = LUN_MEDIA_BLOCKS,
.MediaDescriptor = 0xF8,
.SectorsPerFAT = 1,
.SectorsPerTrack = (LUN_MEDIA_BLOCKS % 64),
.Heads = (LUN_MEDIA_BLOCKS / 64),
.HiddenSectors = 0,
.TotalSectors32 = 0,
.PhysicalDriveNum = 0,
.ExtendedBootRecordSig = 0x29,
.VolumeSerialNumber = 0x12345678,
.VolumeLabel = "LUFA BOOT ",
.FilesystemIdentifier = "FAT12 ",
};
/** FAT 8.3 style directory entry, for the virtual FLASH contents file. */
static FATDirectoryEntry_t FirmwareFileEntries[] =
{
/* Root volume label entry; disk label is contained in the Filename and
* Extension fields (concatenated) with a special attribute flag - other
* fields are ignored. Should be the same as the label in the boot block.
*/
[DISK_FILE_ENTRY_VolumeID] =
{
.MSDOS_Directory =
{
.Name = "LUFA BOOT ",
.Attributes = FAT_FLAG_VOLUME_NAME,
.Reserved = {0},
.CreationTime = 0,
.CreationDate = 0,
.StartingCluster = 0,
.Reserved2 = 0,
}
},
/* VFAT Long File Name entry for the virtual firmware file; required to
* prevent corruption from systems that are unable to detect the device
* as being a legacy MSDOS style FAT12 volume. */
[DISK_FILE_ENTRY_FLASH_LFN] =
{
.VFAT_LongFileName =
{
.Ordinal = 1 | FAT_ORDINAL_LAST_ENTRY,
.Attribute = FAT_FLAG_LONG_FILE_NAME,
.Reserved1 = 0,
.Reserved2 = 0,
.Checksum = FAT_CHECKSUM('F','L','A','S','H',' ',' ',' ','B','I','N'),
.Unicode1 = 'F',
.Unicode2 = 'L',
.Unicode3 = 'A',
.Unicode4 = 'S',
.Unicode5 = 'H',
.Unicode6 = '.',
.Unicode7 = 'B',
.Unicode8 = 'I',
.Unicode9 = 'N',
.Unicode10 = 0,
.Unicode11 = 0,
.Unicode12 = 0,
.Unicode13 = 0,
}
},
/* MSDOS file entry for the virtual Firmware image. */
[DISK_FILE_ENTRY_FLASH_MSDOS] =
{
.MSDOS_File =
{
.Filename = "FLASH ",
.Extension = "BIN",
.Attributes = 0,
.Reserved = {0},
.CreationTime = FAT_TIME(1, 1, 0),
.CreationDate = FAT_DATE(14, 2, 1989),
.StartingCluster = 2,
.FileSizeBytes = FLASH_FILE_SIZE_BYTES,
}
},
[DISK_FILE_ENTRY_EEPROM_LFN] =
{
.VFAT_LongFileName =
{
.Ordinal = 1 | FAT_ORDINAL_LAST_ENTRY,
.Attribute = FAT_FLAG_LONG_FILE_NAME,
.Reserved1 = 0,
.Reserved2 = 0,
.Checksum = FAT_CHECKSUM('E','E','P','R','O','M',' ',' ','B','I','N'),
.Unicode1 = 'E',
.Unicode2 = 'E',
.Unicode3 = 'P',
.Unicode4 = 'R',
.Unicode5 = 'O',
.Unicode6 = 'M',
.Unicode7 = '.',
.Unicode8 = 'B',
.Unicode9 = 'I',
.Unicode10 = 'N',
.Unicode11 = 0,
.Unicode12 = 0,
.Unicode13 = 0,
}
},
[DISK_FILE_ENTRY_EEPROM_MSDOS] =
{
.MSDOS_File =
{
.Filename = "EEPROM ",
.Extension = "BIN",
.Attributes = 0,
.Reserved = {0},
.CreationTime = FAT_TIME(1, 1, 0),
.CreationDate = FAT_DATE(14, 2, 1989),
.StartingCluster = 2 + FILE_CLUSTERS(FLASH_FILE_SIZE_BYTES),
.FileSizeBytes = EEPROM_FILE_SIZE_BYTES,
}
},
};
/** Starting cluster of the virtual FLASH.BIN file on disk, tracked so that the
* offset from the start of the data sector can be determined. On Windows
* systems files are usually replaced using the original file's disk clusters,
* while Linux appears to overwrite with an offset which must be compensated for.
*/
static const uint16_t* FLASHFileStartCluster = &FirmwareFileEntries[DISK_FILE_ENTRY_FLASH_MSDOS].MSDOS_File.StartingCluster;
/** Starting cluster of the virtual EEPROM.BIN file on disk, tracked so that the
* offset from the start of the data sector can be determined. On Windows
* systems files are usually replaced using the original file's disk clusters,
* while Linux appears to overwrite with an offset which must be compensated for.
*/
static const uint16_t* EEPROMFileStartCluster = &FirmwareFileEntries[DISK_FILE_ENTRY_EEPROM_MSDOS].MSDOS_File.StartingCluster;
/** Reads a byte of EEPROM out from the EEPROM memory space.
*
* \note This function is required as the avr-libc EEPROM functions do not cope
* with linker relaxations, and a jump longer than 4K of FLASH on the
* larger USB AVRs will break the linker. This function is marked as
* never inlinable and placed into the normal text segment so that the
* call to the EEPROM function will be short even if the AUX boot section
* is used.
*
* \param[in] Address Address of the EEPROM location to read from
*
* \return Read byte of EEPROM data.
*/
static uint8_t ReadEEPROMByte(const uint8_t* const Address)
{
return eeprom_read_byte(Address);
}
/** Writes a byte of EEPROM out to the EEPROM memory space.
*
* \note This function is required as the avr-libc EEPROM functions do not cope
* with linker relaxations, and a jump longer than 4K of FLASH on the
* larger USB AVRs will break the linker. This function is marked as
* never inlinable and placed into the normal text segment so that the
* call to the EEPROM function will be short even if the AUX boot section
* is used.
*
* \param[in] Address Address of the EEPROM location to write to
* \param[in] Data New data to write to the EEPROM location
*/
static void WriteEEPROMByte(uint8_t* const Address,
const uint8_t Data)
{
eeprom_update_byte(Address, Data);
}
/** Updates a FAT12 cluster entry in the FAT file table with the specified next
* chain index. If the cluster is the last in the file chain, the magic value
* \c 0xFFF should be used.
*
* \note FAT data cluster indexes are offset by 2, so that cluster 2 is the
* first file data cluster on the disk. See the FAT specification.
*
* \param[out] FATTable Pointer to the FAT12 allocation table
* \param[in] Index Index of the cluster entry to update
* \param[in] ChainEntry Next cluster index in the file chain
*/
static void UpdateFAT12ClusterEntry(uint8_t* const FATTable,
const uint16_t Index,
const uint16_t ChainEntry)
{
/* Calculate the starting offset of the cluster entry in the FAT12 table */
uint8_t FATOffset = (Index + (Index >> 1));
bool UpperNibble = ((Index & 1) != 0);
/* Check if the start of the entry is at an upper nibble of the byte, fill
* out FAT12 entry as required */
if (UpperNibble)
{
FATTable[FATOffset] = (FATTable[FATOffset] & 0x0F) | ((ChainEntry & 0x0F) << 4);
FATTable[FATOffset + 1] = (ChainEntry >> 4);
}
else
{
FATTable[FATOffset] = ChainEntry;
FATTable[FATOffset + 1] = (FATTable[FATOffset] & 0xF0) | (ChainEntry >> 8);
}
}
/** Updates a FAT12 cluster chain in the FAT file table with a linear chain of
* the specified length.
*
* \note FAT data cluster indexes are offset by 2, so that cluster 2 is the
* first file data cluster on the disk. See the FAT specification.
*
* \param[out] FATTable Pointer to the FAT12 allocation table
* \param[in] Index Index of the start of the cluster chain to update
* \param[in] ChainLength Length of the chain to write, in clusters
*/
static void UpdateFAT12ClusterChain(uint8_t* const FATTable,
const uint16_t Index,
const uint8_t ChainLength)
{
for (uint8_t i = 0; i < ChainLength; i++)
{
uint16_t CurrentCluster = Index + i;
uint16_t NextCluster = CurrentCluster + 1;
/* Mark last cluster as end of file */
if (i == (ChainLength - 1))
NextCluster = 0xFFF;
UpdateFAT12ClusterEntry(FATTable, CurrentCluster, NextCluster);
}
}
/** Reads or writes a block of data from/to the physical device FLASH using a
* block buffer stored in RAM, if the requested block is within the virtual
* firmware file's sector ranges in the emulated FAT file system.
*
* \param[in] BlockNumber Physical disk block to read from/write to
* \param[in,out] BlockBuffer Pointer to the start of the block buffer in RAM
* \param[in] Read If \c true, the requested block is read, if
* \c false, the requested block is written
*/
static void ReadWriteFLASHFileBlock(const uint16_t BlockNumber,
uint8_t* BlockBuffer,
const bool Read)
{
uint16_t FileStartBlock = DISK_BLOCK_DataStartBlock + (*FLASHFileStartCluster - 2) * SECTOR_PER_CLUSTER;
uint16_t FileEndBlock = FileStartBlock + (FILE_SECTORS(FLASH_FILE_SIZE_BYTES) - 1);
/* Range check the write request - abort if requested block is not within the
* virtual firmware file sector range */
if (!((BlockNumber >= FileStartBlock) && (BlockNumber <= FileEndBlock)))
return;
#if (FLASHEND > 0xFFFF)
uint32_t FlashAddress = (uint32_t)(BlockNumber - FileStartBlock) * SECTOR_SIZE_BYTES;
#else
uint16_t FlashAddress = (uint16_t)(BlockNumber - FileStartBlock) * SECTOR_SIZE_BYTES;
#endif
if (Read)
{
/* Read out the mapped block of data from the device's FLASH */
for (uint16_t i = 0; i < SECTOR_SIZE_BYTES; i++)
{
#if (FLASHEND > 0xFFFF)
BlockBuffer[i] = pgm_read_byte_far(FlashAddress++);
#else
BlockBuffer[i] = pgm_read_byte(FlashAddress++);
#endif
}
}
else
{
/* Write out the mapped block of data to the device's FLASH */
for (uint16_t i = 0; i < SECTOR_SIZE_BYTES; i += 2)
{
if ((FlashAddress % SPM_PAGESIZE) == 0)
{
/* Erase the given FLASH page, ready to be programmed */
BootloaderAPI_ErasePage(FlashAddress);
}
/* Write the next data word to the FLASH page */
BootloaderAPI_FillWord(FlashAddress, (BlockBuffer[i + 1] << 8) | BlockBuffer[i]);
FlashAddress += 2;
if ((FlashAddress % SPM_PAGESIZE) == 0)
{
/* Write the filled FLASH page to memory */
BootloaderAPI_WritePage(FlashAddress - SPM_PAGESIZE);
}
}
}
}
/** Reads or writes a block of data from/to the physical device EEPROM using a
* block buffer stored in RAM, if the requested block is within the virtual
* firmware file's sector ranges in the emulated FAT file system.
*
* \param[in] BlockNumber Physical disk block to read from/write to
* \param[in,out] BlockBuffer Pointer to the start of the block buffer in RAM
* \param[in] Read If \c true, the requested block is read, if
* \c false, the requested block is written
*/
static void ReadWriteEEPROMFileBlock(const uint16_t BlockNumber,
uint8_t* BlockBuffer,
const bool Read)
{
uint16_t FileStartBlock = DISK_BLOCK_DataStartBlock + (*EEPROMFileStartCluster - 2) * SECTOR_PER_CLUSTER;
uint16_t FileEndBlock = FileStartBlock + (FILE_SECTORS(EEPROM_FILE_SIZE_BYTES) - 1);
/* Range check the write request - abort if requested block is not within the
* virtual firmware file sector range */
if (!((BlockNumber >= FileStartBlock) && (BlockNumber <= FileEndBlock)))
return;
uint16_t EEPROMAddress = (uint16_t)(BlockNumber - FileStartBlock) * SECTOR_SIZE_BYTES;
if (Read)
{
/* Read out the mapped block of data from the device's EEPROM */
for (uint16_t i = 0; i < SECTOR_SIZE_BYTES; i++)
BlockBuffer[i] = ReadEEPROMByte((uint8_t*)EEPROMAddress++);
}
else
{
/* Write out the mapped block of data to the device's EEPROM */
for (uint16_t i = 0; i < SECTOR_SIZE_BYTES; i++)
WriteEEPROMByte((uint8_t*)EEPROMAddress++, BlockBuffer[i]);
}
}
/** Writes a block of data to the virtual FAT filesystem, from the USB Mass
* Storage interface.
*
* \param[in] BlockNumber Index of the block to write.
*/
void VirtualFAT_WriteBlock(const uint16_t BlockNumber)
{
uint8_t BlockBuffer[SECTOR_SIZE_BYTES];
/* Buffer the entire block to be written from the host */
Endpoint_Read_Stream_LE(BlockBuffer, sizeof(BlockBuffer), NULL);
Endpoint_ClearOUT();
switch (BlockNumber)
{
case DISK_BLOCK_BootBlock:
case DISK_BLOCK_FATBlock1:
case DISK_BLOCK_FATBlock2:
/* Ignore writes to the boot and FAT blocks */
break;
case DISK_BLOCK_RootFilesBlock:
/* Copy over the updated directory entries */
memcpy(FirmwareFileEntries, BlockBuffer, sizeof(FirmwareFileEntries));
break;
default:
ReadWriteFLASHFileBlock(BlockNumber, BlockBuffer, false);
ReadWriteEEPROMFileBlock(BlockNumber, BlockBuffer, false);
break;
}
}
/** Reads a block of data from the virtual FAT filesystem, and sends it to the
* host via the USB Mass Storage interface.
*
* \param[in] BlockNumber Index of the block to read.
*/
void VirtualFAT_ReadBlock(const uint16_t BlockNumber)
{
uint8_t BlockBuffer[SECTOR_SIZE_BYTES];
memset(BlockBuffer, 0x00, sizeof(BlockBuffer));
switch (BlockNumber)
{
case DISK_BLOCK_BootBlock:
memcpy(BlockBuffer, &BootBlock, sizeof(FATBootBlock_t));
/* Add the magic signature to the end of the block */
BlockBuffer[SECTOR_SIZE_BYTES - 2] = 0x55;
BlockBuffer[SECTOR_SIZE_BYTES - 1] = 0xAA;
break;
case DISK_BLOCK_FATBlock1:
case DISK_BLOCK_FATBlock2:
/* Cluster 0: Media type/Reserved */
UpdateFAT12ClusterEntry(BlockBuffer, 0, 0xF00 | BootBlock.MediaDescriptor);
/* Cluster 1: Reserved */
UpdateFAT12ClusterEntry(BlockBuffer, 1, 0xFFF);
/* Cluster 2 onwards: Cluster chain of FLASH.BIN */
UpdateFAT12ClusterChain(BlockBuffer, *FLASHFileStartCluster, FILE_CLUSTERS(FLASH_FILE_SIZE_BYTES));
/* Cluster 2+n onwards: Cluster chain of EEPROM.BIN */
UpdateFAT12ClusterChain(BlockBuffer, *EEPROMFileStartCluster, FILE_CLUSTERS(EEPROM_FILE_SIZE_BYTES));
break;
case DISK_BLOCK_RootFilesBlock:
memcpy(BlockBuffer, FirmwareFileEntries, sizeof(FirmwareFileEntries));
break;
default:
ReadWriteFLASHFileBlock(BlockNumber, BlockBuffer, true);
ReadWriteEEPROMFileBlock(BlockNumber, BlockBuffer, true);
break;
}
/* Write the entire read block Buffer to the host */
Endpoint_Write_Stream_LE(BlockBuffer, sizeof(BlockBuffer), NULL);
Endpoint_ClearIN();
}

@ -0,0 +1,302 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2017.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2017 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 disclaims 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.
*/
#ifndef _VIRTUALFAT_H_
#define _VIRTUALFAT_H_
/* Includes: */
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <LUFA/Drivers/USB/USB.h>
#include "../BootloaderAPI.h"
/* Macros: */
/** Size of the virtual FLASH.BIN file in bytes. */
#define FLASH_FILE_SIZE_BYTES (FLASHEND - (FLASHEND - BOOT_START_ADDR) - AUX_BOOT_SECTION_SIZE)
/** Size of the virtual EEPROM.BIN file in bytes. */
#define EEPROM_FILE_SIZE_BYTES E2END
/** Number of sectors that comprise a single logical disk cluster. */
#define SECTOR_PER_CLUSTER 4
/** Size of a single logical sector on the disk. */
#define SECTOR_SIZE_BYTES 512
/** Size of a logical cluster on the disk, in bytes */
#define CLUSTER_SIZE_BYTES (SECTOR_PER_CLUSTER * SECTOR_SIZE_BYTES)
/** Number of sectors required to store a given size in bytes.
*
* \param[in] size Size of the data that needs to be stored
*
* \return Number of sectors required to store the given data on the disk.
*/
#define FILE_SECTORS(size) ((size / SECTOR_SIZE_BYTES) + ((size % SECTOR_SIZE_BYTES) ? 1 : 0))
/** Number of clusters required to store a given size in bytes.
*
* \param[in] size Size of the data that needs to be stored
*
* \return Number of clusters required to store the given data on the disk.
*/
#define FILE_CLUSTERS(size) ((size / CLUSTER_SIZE_BYTES) + ((size % CLUSTER_SIZE_BYTES) ? 1 : 0))
/** Total number of logical sectors/blocks on the disk. */
#define LUN_MEDIA_BLOCKS (FILE_SECTORS(FLASH_FILE_SIZE_BYTES) + FILE_SECTORS(EEPROM_FILE_SIZE_BYTES) + 32)
/** Converts a given time in HH:MM:SS format to a FAT filesystem time.
*
* \note The minimum seconds resolution of FAT is 2, thus odd seconds
* will be truncated to the previous integer multiple of 2 seconds.
*
* \param[in] hh Hours (0-23)
* \param[in] mm Minutes (0-59)
* \param[in] ss Seconds (0-59)
*
* \return Given time encoded as a FAT filesystem timestamp
*/
#define FAT_TIME(hh, mm, ss) ((hh << 11) | (mm << 5) | (ss >> 1))
/** Converts a given date in DD/MM/YYYY format to a FAT filesystem date.
*
* \param[in] dd Days in the month (1-31)
* \param[in] mm Months in the year (1-12)
* \param[in] yyyy Year (1980 - 2107)
*
* \return Given date encoded as a FAT filesystem datestamp
*/
#define FAT_DATE(dd, mm, yyyy) (((yyyy - 1980) << 9) | (mm << 5) | (dd << 0))
/** Bit-rotates a given 8-bit value once to the right.
*
* \param[in] x Value to rotate right once
*
* \return Bit-rotated input value, rotated once to the right.
*/
#define ROT8(x) ((((x) & 0xFE) >> 1) | (((x) & 1) ? 0x80 : 0x00))
/** Computes the LFN entry checksum of a MSDOS 8.3 format file entry,
* to associate a LFN entry with its short file entry.
*
* \param[in] n0 MSDOS Filename character 1
* \param[in] n1 MSDOS Filename character 2
* \param[in] n2 MSDOS Filename character 3
* \param[in] n3 MSDOS Filename character 4
* \param[in] n4 MSDOS Filename character 5
* \param[in] n5 MSDOS Filename character 6
* \param[in] n6 MSDOS Filename character 7
* \param[in] n7 MSDOS Filename character 8
* \param[in] e0 MSDOS Extension character 1
* \param[in] e1 MSDOS Extension character 2
* \param[in] e2 MSDOS Extension character 3
*
* \return LFN checksum of the given MSDOS 8.3 filename.
*/
#define FAT_CHECKSUM(n0, n1, n2, n3, n4, n5, n6, n7, e0, e1, e2) \
(uint8_t)(ROT8(ROT8(ROT8(ROT8(ROT8(ROT8(ROT8(ROT8(ROT8(ROT8(n0)+n1)+n2)+n3)+n4)+n5)+n6)+n7)+e0)+e1)+e2)
/** \name FAT Filesystem Flags */
//@{
/** FAT attribute flag to indicate a read-only file. */
#define FAT_FLAG_READONLY (1 << 0)
/** FAT attribute flag to indicate a hidden file. */
#define FAT_FLAG_HIDDEN (1 << 1)
/** FAT attribute flag to indicate a system file. */
#define FAT_FLAG_SYSTEM (1 << 2)
/** FAT attribute flag to indicate a Volume name entry. */
#define FAT_FLAG_VOLUME_NAME (1 << 3)
/** FAT attribute flag to indicate a directory entry. */
#define FAT_FLAG_DIRECTORY (1 << 4)
/** FAT attribute flag to indicate a file ready for archiving. */
#define FAT_FLAG_ARCHIVE (1 << 5)
/** FAT pseudo-attribute flag to indicate a Long File Name entry. */
#define FAT_FLAG_LONG_FILE_NAME 0x0F
/** Ordinal flag marker for FAT Long File Name entries to mark the last entry. */
#define FAT_ORDINAL_LAST_ENTRY (1 << 6)
//@}
/* Enums: */
/** Enum for the Root FAT file entry indexes on the disk. This can be used
* to retrieve the current contents of a known directory entry.
*/
enum
{
/** Volume ID directory entry, giving the name of the virtual disk. */
DISK_FILE_ENTRY_VolumeID = 0,
/** Long File Name FAT file entry of the virtual FLASH.BIN image file. */
DISK_FILE_ENTRY_FLASH_LFN = 1,
/** Legacy MSDOS FAT file entry of the virtual FLASH.BIN image file. */
DISK_FILE_ENTRY_FLASH_MSDOS = 2,
/** Long File Name FAT file entry of the virtual EEPROM.BIN image file. */
DISK_FILE_ENTRY_EEPROM_LFN = 3,
/** Legacy MSDOS FAT file entry of the virtual EEPROM.BIN image file. */
DISK_FILE_ENTRY_EEPROM_MSDOS = 4,
};
/** Enum for the physical disk blocks of the virtual disk. */
enum
{
/** Boot sector disk block. */
DISK_BLOCK_BootBlock = 0,
/** First copy of the FAT table block. */
DISK_BLOCK_FATBlock1 = 1,
/** Second copy of the FAT table block. */
DISK_BLOCK_FATBlock2 = 2,
/** Root file and directory entries block. */
DISK_BLOCK_RootFilesBlock = 3,
/** Start block of the disk data section. */
DISK_BLOCK_DataStartBlock = 4,
};
/* Type Definitions: */
/** FAT boot block structure definition, used to identify the core
* parameters of a FAT file system stored on a disk.
*
* \note This definition is truncated to save space; the magic signature
* \c 0xAA55 must be appended to the very end of the block for it
* to be detected by the host as a valid boot block.
*/
typedef struct
{
uint8_t Bootstrap[3];
uint8_t Description[8];
uint16_t SectorSize;
uint8_t SectorsPerCluster;
uint16_t ReservedSectors;
uint8_t FATCopies;
uint16_t RootDirectoryEntries;
uint16_t TotalSectors16;
uint8_t MediaDescriptor;
uint16_t SectorsPerFAT;
uint16_t SectorsPerTrack;
uint16_t Heads;
uint32_t HiddenSectors;
uint32_t TotalSectors32;
uint16_t PhysicalDriveNum;
uint8_t ExtendedBootRecordSig;
uint32_t VolumeSerialNumber;
uint8_t VolumeLabel[11];
uint8_t FilesystemIdentifier[8];
/* uint8_t BootstrapProgram[448]; */
/* uint16_t MagicSignature; */
} FATBootBlock_t;
/** FAT directory entry structure, for the various kinds of File and
* directory descriptors on a FAT disk.
*/
typedef union
{
/** VFAT Long File Name file entry. */
struct
{
uint8_t Ordinal;
uint16_t Unicode1;
uint16_t Unicode2;
uint16_t Unicode3;
uint16_t Unicode4;
uint16_t Unicode5;
uint8_t Attribute;
uint8_t Reserved1;
uint8_t Checksum;
uint16_t Unicode6;
uint16_t Unicode7;
uint16_t Unicode8;
uint16_t Unicode9;
uint16_t Unicode10;
uint16_t Unicode11;
uint16_t Reserved2;
uint16_t Unicode12;
uint16_t Unicode13;
} VFAT_LongFileName;
/** Legacy FAT MSDOS 8.3 file entry. */
struct
{
uint8_t Filename[8];
uint8_t Extension[3];
uint8_t Attributes;
uint8_t Reserved[10];
uint16_t CreationTime;
uint16_t CreationDate;
uint16_t StartingCluster;
uint32_t FileSizeBytes;
} MSDOS_File;
/** Legacy FAT MSDOS (sub-)directory entry. */
struct
{
uint8_t Name[11];
uint8_t Attributes;
uint8_t Reserved[10];
uint16_t CreationTime;
uint16_t CreationDate;
uint16_t StartingCluster;
uint32_t Reserved2;
} MSDOS_Directory;
} FATDirectoryEntry_t;
/* Function Prototypes: */
#if defined(INCLUDE_FROM_VIRTUAL_FAT_C)
static uint8_t ReadEEPROMByte(const uint8_t* const Address) ATTR_NO_INLINE;
static void WriteEEPROMByte(uint8_t* const Address,
const uint8_t Data) ATTR_NO_INLINE;
static void UpdateFAT12ClusterEntry(uint8_t* const FATTable,
const uint16_t Index,
const uint16_t ChainEntry) AUX_BOOT_SECTION;
static void UpdateFAT12ClusterChain(uint8_t* const FATTable,
const uint16_t StartIndex,
const uint8_t ChainLength) AUX_BOOT_SECTION;
static void ReadWriteFLASHFileBlock(const uint16_t BlockNumber,
uint8_t* BlockBuffer,
const bool Read) AUX_BOOT_SECTION;
static void ReadWriteEEPROMFileBlock(const uint16_t BlockNumber,
uint8_t* BlockBuffer,
const bool Read) AUX_BOOT_SECTION;
#endif
void VirtualFAT_WriteBlock(const uint16_t BlockNumber) AUX_BOOT_SECTION;
void VirtualFAT_ReadBlock(const uint16_t BlockNumber) AUX_BOOT_SECTION;
#endif

@ -0,0 +1,156 @@
<asf xmlversion="1.0">
<project caption="Mass Storage Bootloader - 128KB FLASH / 8KB Boot - AVR8 Architecture" id="lufa.bootloaders.mass_storage.avr8.128_8" force-caption="true" workspace-name="lufa_ms_128kb_8kb_">
<require idref="lufa.bootloaders.mass_storage"/>
<require idref="lufa.boards.dummy.avr8"/>
<generator value="as5_8"/>
<device-support value="at90usb1287"/>
<config name="lufa.drivers.board.name" value="none"/>
<config name="config.compiler.optimization.level" value="size"/>
<build type="define" name="F_CPU" value="16000000UL"/>
<build type="define" name="F_USB" value="16000000UL"/>
<build type="define" name="BOOT_START_ADDR" value="0x1E000"/>
<build type="linker-config" subtype="flags" value="--section-start=.text=0x1E000"/>
<build type="define" name="AUX_BOOT_SECTION_SIZE" value="0"/>
<build type="linker-config" subtype="flags" value="--section-start=.apitable_trampolines=0x1FFA0"/>
<build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_Trampolines"/>
<build type="linker-config" subtype="flags" value="--section-start=.apitable_jumptable=0x1FFE0"/>
<build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_JumpTable"/>
<build type="linker-config" subtype="flags" value="--section-start=.apitable_signatures=0x1FFF8"/>
<build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_Signatures"/>
</project>
<project caption="Mass Storage Bootloader - 64KB FLASH / 8KB Boot - AVR8 Architecture" id="lufa.bootloaders.mass_storage.avr8.64_8" force-caption="true" workspace-name="lufa_ms_64kb_8kb_">
<require idref="lufa.bootloaders.mass_storage"/>
<require idref="lufa.boards.dummy.avr8"/>
<generator value="as5_8"/>
<device-support value="at90usb647"/>
<config name="lufa.drivers.board.name" value="none"/>
<config name="config.compiler.optimization.level" value="size"/>
<build type="define" name="F_CPU" value="16000000UL"/>
<build type="define" name="F_USB" value="16000000UL"/>
<build type="define" name="BOOT_START_ADDR" value="0xE000"/>
<build type="linker-config" subtype="flags" value="--section-start=.text=0xE000"/>
<build type="define" name="AUX_BOOT_SECTION_SIZE" value="0"/>
<build type="linker-config" subtype="flags" value="--section-start=.apitable_trampolines=0xFFA0"/>
<build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_Trampolines"/>
<build type="linker-config" subtype="flags" value="--section-start=.apitable_jumptable=0xFFE0"/>
<build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_JumpTable"/>
<build type="linker-config" subtype="flags" value="--section-start=.apitable_signatures=0xFFF8"/>
<build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_Signatures"/>
</project>
<project caption="Mass Storage Bootloader - 32KB FLASH / 4KB Boot (2KB AUX) - AVR8 Architecture" id="lufa.bootloaders.mass_storage.avr8.32_4" force-caption="true" workspace-name="lufa_ms_32kb_4kb_">
<require idref="lufa.bootloaders.mass_storage"/>
<require idref="lufa.boards.dummy.avr8"/>
<generator value="as5_8"/>
<device-support value="atmega32u4"/>
<config name="lufa.drivers.board.name" value="none"/>
<config name="config.compiler.optimization.level" value="size"/>
<build type="define" name="F_CPU" value="16000000UL"/>
<build type="define" name="F_USB" value="16000000UL"/>
<build type="define" name="BOOT_START_ADDR" value="0x7000"/>
<build type="linker-config" subtype="flags" value="--section-start=.text=0x7000"/>
<build type="define" name="AUX_BOOT_SECTION_SIZE" value="2048"/>
<build type="linker-config" subtype="flags" value="--section-start=.boot_aux=0x6810"/>
<build type="linker-config" subtype="flags" value="--section-start=.boot_aux_trampoline=0x6800"/>
<build type="linker-config" subtype="flags" value="--undefined=Boot_AUX_Trampoline"/>
<build type="linker-config" subtype="flags" value="--section-start=.apitable_trampolines=0x7FA0"/>
<build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_Trampolines"/>
<build type="linker-config" subtype="flags" value="--section-start=.apitable_jumptable=0x7FE0"/>
<build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_JumpTable"/>
<build type="linker-config" subtype="flags" value="--section-start=.apitable_signatures=0x7FF8"/>
<build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_Signatures"/>
</project>
<project caption="Mass Storage Bootloader - 16KB FLASH / 4KB Boot (2KB AUX) - AVR8 Architecture" id="lufa.bootloaders.mass_storage.avr8.16_4" force-caption="true" workspace-name="lufa_ms_16kb_4kb_">
<require idref="lufa.bootloaders.mass_storage"/>
<require idref="lufa.boards.dummy.avr8"/>
<generator value="as5_8"/>
<device-support value="atmega16u2"/>
<config name="lufa.drivers.board.name" value="none"/>
<config name="config.compiler.optimization.level" value="size"/>
<build type="define" name="F_CPU" value="16000000UL"/>
<build type="define" name="F_USB" value="16000000UL"/>
<build type="define" name="BOOT_START_ADDR" value="0x3000"/>
<build type="linker-config" subtype="flags" value="--section-start=.text=0x3000"/>
<build type="define" name="AUX_BOOT_SECTION_SIZE" value="2048"/>
<build type="linker-config" subtype="flags" value="--section-start=.boot_aux=0x2810"/>
<build type="linker-config" subtype="flags" value="--section-start=.boot_aux_trampoline=0x2800"/>
<build type="linker-config" subtype="flags" value="--undefined=Boot_AUX_Trampoline"/>
<build type="linker-config" subtype="flags" value="--section-start=.apitable_trampolines=0x3FA0"/>
<build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_Trampolines"/>
<build type="linker-config" subtype="flags" value="--section-start=.apitable_jumptable=0x3FE0"/>
<build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_JumpTable"/>
<build type="linker-config" subtype="flags" value="--section-start=.apitable_signatures=0x3FF8"/>
<build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_Signatures"/>
</project>
<module type="application" id="lufa.bootloaders.mass_storage" caption="Mass Storage Bootloader">
<info type="description" value="summary">
Mass Storage Class Bootloader, capable of reprogramming a device via binary BIN files copied to the virtual FAT12 file-system it creates when plugged into a host.
</info>
<info type="gui-flag" value="move-to-root"/>
<info type="keyword" value="Technology">
<keyword value="Bootloaders"/>
<keyword value="USB Device"/>
</info>
<device-support-alias value="lufa_avr8"/>
<device-support-alias value="lufa_xmega"/>
<device-support-alias value="lufa_uc3"/>
<build type="include-path" value="."/>
<build type="c-source" value="BootloaderMassStorage.c"/>
<build type="header-file" value="BootloaderMassStorage.h"/>
<build type="c-source" value="Descriptors.c"/>
<build type="header-file" value="Descriptors.h"/>
<build type="c-source" value="BootloaderAPI.c"/>
<build type="header-file" value="BootloaderAPI.h"/>
<build type="asm-source" value="BootloaderAPITable.S"/>
<build type="module-config" subtype="path" value="Config"/>
<build type="header-file" value="Config/LUFAConfig.h"/>
<build type="header-file" value="Config/AppConfig.h"/>
<build type="include-path" value="Lib"/>
<build type="header-file" value="Lib/VirtualFAT.h"/>
<build type="c-source" value="Lib/VirtualFAT.c"/>
<build type="header-file" value="Lib/SCSI.h"/>
<build type="c-source" value="Lib/SCSI.c"/>
<build type="distribute" subtype="user-file" value="doxyfile"/>
<build type="distribute" subtype="user-file" value="BootloaderMassStorage.txt"/>
<require idref="lufa.common"/>
<require idref="lufa.platform"/>
<require idref="lufa.drivers.usb"/>
<require idref="lufa.drivers.board"/>
<require idref="lufa.drivers.board.leds"/>
</module>
</asf>

File diff suppressed because it is too large Load Diff

@ -0,0 +1,75 @@
#
# LUFA Library
# Copyright (C) Dean Camera, 2017.
#
# dean [at] fourwalledcubicle [dot] com
# www.lufa-lib.org
#
# --------------------------------------
# LUFA Project Makefile.
# --------------------------------------
# Run "make help" for target help.
MCU = at90usb1287
ARCH = AVR8
BOARD = USBKEY
F_CPU = 8000000
F_USB = $(F_CPU)
OPTIMIZATION = s
TARGET = BootloaderMassStorage
SRC = $(TARGET).c Descriptors.c BootloaderAPI.c BootloaderAPITable.S Lib/SCSI.c Lib/VirtualFAT.c $(LUFA_SRC_USB) $(LUFA_SRC_USBCLASS)
LUFA_PATH = ../../LUFA
CC_FLAGS = -DUSE_LUFA_CONFIG_HEADER -IConfig/ -DBOOT_START_ADDR=$(BOOT_START_OFFSET)
LD_FLAGS = -Wl,--section-start=.text=$(BOOT_START_OFFSET) $(BOOT_API_LD_FLAGS)
# Flash size and bootloader section sizes of the target, in KB. These must
# match the target's total FLASH size and the bootloader size set in the
# device's fuses.
FLASH_SIZE_KB = 128
BOOT_SECTION_SIZE_KB = 8
# Bootloader address calculation formulas
# Do not modify these macros, but rather modify the dependent values above.
CALC_ADDRESS_IN_HEX = $(shell printf "0x%X" $$(( $(1) )) )
BOOT_START_OFFSET = $(call CALC_ADDRESS_IN_HEX, ($(FLASH_SIZE_KB) - $(BOOT_SECTION_SIZE_KB)) * 1024 )
BOOT_SEC_OFFSET = $(call CALC_ADDRESS_IN_HEX, ($(FLASH_SIZE_KB) * 1024) - ($(strip $(1))) )
# Bootloader linker section flags for relocating the API table sections to
# known FLASH addresses - these should not normally be user-edited.
BOOT_SECTION_LD_FLAG = -Wl,--section-start=$(strip $(1))=$(call BOOT_SEC_OFFSET, $(3)) -Wl,--undefined=$(strip $(2))
BOOT_API_LD_FLAGS = $(call BOOT_SECTION_LD_FLAG, .apitable_trampolines, BootloaderAPI_Trampolines, 96)
BOOT_API_LD_FLAGS += $(call BOOT_SECTION_LD_FLAG, .apitable_jumptable, BootloaderAPI_JumpTable, 32)
BOOT_API_LD_FLAGS += $(call BOOT_SECTION_LD_FLAG, .apitable_signatures, BootloaderAPI_Signatures, 8)
# Check if the bootloader needs an AUX section, located before the real bootloader section to store some of the
# bootloader code. This is required for 32KB and smaller devices, where the actual bootloader is 6KB but the maximum
# bootloader section size is 4KB. The actual usable application space will be reduced by 6KB for these devices.
ifeq ($(BOOT_SECTION_SIZE_KB),8)
CC_FLAGS += -DAUX_BOOT_SECTION_SIZE=0
else
AUX_BOOT_SECTION_SIZE_KB = (6 - $(BOOT_SECTION_SIZE_KB))
CC_FLAGS += -DAUX_BOOT_SECTION_SIZE='($(AUX_BOOT_SECTION_SIZE_KB) * 1024)'
LD_FLAGS += -Wl,--section-start=.boot_aux=$(call BOOT_SEC_OFFSET, (($(BOOT_SECTION_SIZE_KB) + $(AUX_BOOT_SECTION_SIZE_KB)) * 1024 - 16))
LD_FLAGS += $(call BOOT_SECTION_LD_FLAG, .boot_aux_trampoline, Boot_AUX_Trampoline, ($(BOOT_SECTION_SIZE_KB) + $(AUX_BOOT_SECTION_SIZE_KB)) * 1024)
endif
# Default target
all:
# Include LUFA-specific DMBS extension modules
DMBS_LUFA_PATH ?= $(LUFA_PATH)/Build/LUFA
include $(DMBS_LUFA_PATH)/lufa-sources.mk
include $(DMBS_LUFA_PATH)/lufa-gcc.mk
# Include common DMBS build system modules
DMBS_PATH ?= $(LUFA_PATH)/Build/DMBS/DMBS
include $(DMBS_PATH)/core.mk
include $(DMBS_PATH)/cppcheck.mk
include $(DMBS_PATH)/doxygen.mk
include $(DMBS_PATH)/dfu.mk
include $(DMBS_PATH)/gcc.mk
include $(DMBS_PATH)/hid.mk
include $(DMBS_PATH)/avrdude.mk
include $(DMBS_PATH)/atprogram.mk

@ -0,0 +1,75 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2017.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2017 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 disclaims 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
*
* Bootloader user application API functions.
*/
#include "BootloaderAPI.h"
void BootloaderAPI_ErasePage(const uint32_t Address)
{
boot_page_erase_safe(Address);
boot_spm_busy_wait();
boot_rww_enable();
}
void BootloaderAPI_WritePage(const uint32_t Address)
{
boot_page_write_safe(Address);
boot_spm_busy_wait();
boot_rww_enable();
}
void BootloaderAPI_FillWord(const uint32_t Address, const uint16_t Word)
{
boot_page_fill_safe(Address, Word);
}
uint8_t BootloaderAPI_ReadSignature(const uint16_t Address)
{
return boot_signature_byte_get(Address);
}
uint8_t BootloaderAPI_ReadFuse(const uint16_t Address)
{
return boot_lock_fuse_bits_get(Address);
}
uint8_t BootloaderAPI_ReadLock(void)
{
return boot_lock_fuse_bits_get(GET_LOCK_BITS);
}
void BootloaderAPI_WriteLock(const uint8_t LockBits)
{
boot_lock_bits_set_safe(LockBits);
}

@ -0,0 +1,56 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2017.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2017 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 disclaims 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 BootloaderAPI.c.
*/
#ifndef _BOOTLOADER_API_H_
#define _BOOTLOADER_API_H_
/* Includes: */
#include <avr/io.h>
#include <avr/boot.h>
#include <stdbool.h>
#include <LUFA/Common/Common.h>
/* Function Prototypes: */
void BootloaderAPI_ErasePage(const uint32_t Address);
void BootloaderAPI_WritePage(const uint32_t Address);
void BootloaderAPI_FillWord(const uint32_t Address, const uint16_t Word);
uint8_t BootloaderAPI_ReadSignature(const uint16_t Address);
uint8_t BootloaderAPI_ReadFuse(const uint16_t Address);
uint8_t BootloaderAPI_ReadLock(void);
void BootloaderAPI_WriteLock(const uint8_t LockBits);
#endif

@ -0,0 +1,91 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2017.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2017 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 disclaims 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.
*/
; Trampolines to actual API implementations if the target address is outside the
; range of a rjmp instruction (can happen with large bootloader sections)
.section .apitable_trampolines, "ax"
.global BootloaderAPI_Trampolines
BootloaderAPI_Trampolines:
BootloaderAPI_ErasePage_Trampoline:
jmp BootloaderAPI_ErasePage
BootloaderAPI_WritePage_Trampoline:
jmp BootloaderAPI_WritePage
BootloaderAPI_FillWord_Trampoline:
jmp BootloaderAPI_FillWord
BootloaderAPI_ReadSignature_Trampoline:
jmp BootloaderAPI_ReadSignature
BootloaderAPI_ReadFuse_Trampoline:
jmp BootloaderAPI_ReadFuse
BootloaderAPI_ReadLock_Trampoline:
jmp BootloaderAPI_ReadLock
BootloaderAPI_WriteLock_Trampoline:
jmp BootloaderAPI_WriteLock
BootloaderAPI_UNUSED1:
ret
BootloaderAPI_UNUSED2:
ret
BootloaderAPI_UNUSED3:
ret
BootloaderAPI_UNUSED4:
ret
BootloaderAPI_UNUSED5:
ret
; API function jump table
.section .apitable_jumptable, "ax"
.global BootloaderAPI_JumpTable
BootloaderAPI_JumpTable:
rjmp BootloaderAPI_ErasePage_Trampoline
rjmp BootloaderAPI_WritePage_Trampoline
rjmp BootloaderAPI_FillWord_Trampoline
rjmp BootloaderAPI_ReadSignature_Trampoline
rjmp BootloaderAPI_ReadFuse_Trampoline
rjmp BootloaderAPI_ReadLock_Trampoline
rjmp BootloaderAPI_WriteLock_Trampoline
rjmp BootloaderAPI_UNUSED1 ; UNUSED ENTRY 1
rjmp BootloaderAPI_UNUSED2 ; UNUSED ENTRY 2
rjmp BootloaderAPI_UNUSED3 ; UNUSED ENTRY 3
rjmp BootloaderAPI_UNUSED4 ; UNUSED ENTRY 4
rjmp BootloaderAPI_UNUSED5 ; UNUSED ENTRY 5
; Bootloader table signatures and information
.section .apitable_signatures, "ax"
.global BootloaderAPI_Signatures
BootloaderAPI_Signatures:
.long BOOT_START_ADDR ; Start address of the bootloader
.word 0xDF20 ; Signature for the Printer class bootloader
.word 0xDCFB ; Signature for a LUFA class bootloader

@ -0,0 +1,487 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2017.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2017 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 disclaims 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 Printer class bootloader. This file contains the complete bootloader logic.
*/
#include "BootloaderPrinter.h"
/** LUFA Printer Class driver interface configuration and state information. This structure is
* passed to all Printer Class driver functions, so that multiple instances of the same class
* within a device can be differentiated from one another.
*/
USB_ClassInfo_PRNT_Device_t TextOnly_Printer_Interface =
{
.Config =
{
.InterfaceNumber = INTERFACE_ID_Printer,
.DataINEndpoint =
{
.Address = PRINTER_IN_EPADDR,
.Size = PRINTER_IO_EPSIZE,
.Banks = 1,
},
.DataOUTEndpoint =
{
.Address = PRINTER_OUT_EPADDR,
.Size = PRINTER_IO_EPSIZE,
.Banks = 1,
},
.IEEE1284String =
"MFG:Generic;"
"MDL:Generic_/_Text_Only;"
"CMD:1284.4;"
"CLS:PRINTER",
},
};
/** Intel HEX parser state machine state information, to track the contents of
* a HEX file streamed in as a sequence of arbitrary bytes.
*/
struct
{
/** Current HEX parser state machine state. */
uint8_t ParserState;
/** Previously decoded numerical byte of data. */
uint8_t PrevData;
/** Currently decoded numerical byte of data. */
uint8_t Data;
/** Indicates if both bytes that correspond to a single decoded numerical
* byte of data (HEX encodes values in ASCII HEX, two characters per byte)
* have been read.
*/
bool ReadMSB;
/** Intel HEX record type of the current Intel HEX record. */
uint8_t RecordType;
/** Numerical bytes of data remaining to be read in the current record. */
uint8_t DataRem;
/** Checksum of the current record received so far. */
uint8_t Checksum;
/** Starting address of the last addressed FLASH page. */
uint32_t PageStartAddress;
/** Current 32-bit byte extended base address in FLASH being targeted. */
uint32_t CurrBaseAddress;
/** Current 32-bit byte address in FLASH being targeted. */
uint32_t CurrAddress;
} HEXParser;
/** Indicates if there is data waiting to be written to a physical page of
* memory in FLASH.
*/
static bool PageDirty = false;
/** 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
* started via a forced watchdog reset.
*/
static bool RunBootloader = true;
/** Magic lock for forced application start. If the HWBE fuse is programmed and BOOTRST is unprogrammed, the bootloader
* will start if the /HWB line of the AVR is held low and the system is reset. However, if the /HWB line is still held
* low when the application attempts to start via a watchdog reset, the bootloader will re-start. If set to the value
* \ref MAGIC_BOOT_KEY the special init function \ref Application_Jump_Check() will force the application to start.
*/
uint16_t MagicBootKey ATTR_NO_INIT;
/** Special startup routine to check if the bootloader was started via a watchdog reset, and if the magic application
* start key has been loaded into \ref MagicBootKey. If the bootloader started via the watchdog and the key is valid,
* this will force the user application to start via a software jump.
*/
void Application_Jump_Check(void)
{
bool JumpToApplication = false;
#if (BOARD == BOARD_LEONARDO)
/* Enable pull-up on the IO13 pin so we can use it to select the mode */
PORTC |= (1 << 7);
Delay_MS(10);
/* If IO13 is not jumpered to ground, start the user application instead */
JumpToApplication = ((PINC & (1 << 7)) != 0);
/* Disable pull-up after the check has completed */
PORTC &= ~(1 << 7);
#elif ((BOARD == BOARD_XPLAIN) || (BOARD == BOARD_XPLAIN_REV1))
/* Disable JTAG debugging */
JTAG_DISABLE();
/* Enable pull-up on the JTAG TCK pin so we can use it to select the mode */
PORTF |= (1 << 4);
Delay_MS(10);
/* If the TCK pin is not jumpered to ground, start the user application instead */
JumpToApplication = ((PINF & (1 << 4)) != 0);
/* Re-enable JTAG debugging */
JTAG_ENABLE();
#else
/* Check if the device's BOOTRST fuse is set */
if (boot_lock_fuse_bits_get(GET_HIGH_FUSE_BITS) & FUSE_BOOTRST)
{
/* If the reset source was not an external reset or the key is correct, clear it and jump to the application */
if (!(MCUSR & (1 << EXTRF)) || (MagicBootKey == MAGIC_BOOT_KEY))
JumpToApplication = true;
/* Clear reset source */
MCUSR &= ~(1 << EXTRF);
}
else
{
/* If the reset source was the bootloader and the key is correct, clear it and jump to the application;
* this can happen in the HWBE fuse is set, and the HBE pin is low during the watchdog reset */
if ((MCUSR & (1 << WDRF)) && (MagicBootKey == MAGIC_BOOT_KEY))
JumpToApplication = true;
/* Clear reset source */
MCUSR &= ~(1 << WDRF);
}
#endif
/* Don't run the user application if the reset vector is blank (no app loaded) */
bool ApplicationValid = (pgm_read_word_near(0) != 0xFFFF);
/* If a request has been made to jump to the user application, honor it */
if (JumpToApplication && ApplicationValid)
{
/* Turn off the watchdog */
MCUSR &= ~(1 << WDRF);
wdt_disable();
/* Clear the boot key and jump to the user application */
MagicBootKey = 0;
// cppcheck-suppress constStatement
((void (*)(void))0x0000)();
}
}
/**
* Converts a given input byte of data from an ASCII encoded HEX value to an integer value.
*
* \note Input HEX bytes are expected to be in uppercase only.
*
* \param[in] Byte ASCII byte of data to convert
*
* \return Integer converted value of the input ASCII encoded HEX byte of data, or -1 if the
* input is not valid ASCII encoded HEX.
*/
static int8_t HexToDecimal(const char Byte)
{
if ((Byte >= 'A') && (Byte <= 'F'))
return (10 + (Byte - 'A'));
else if ((Byte >= '0') && (Byte <= '9'))
return (Byte - '0');
return -1;
}
/**
* Flushes a partially written page of data to physical FLASH, if a page
* boundary has been crossed.
*
* \note If a page flush occurs the global HEX parser state is updated.
*/
static void FlushPageIfRequired(void)
{
/* Abort if no data has been buffered for writing to the current page */
if (!PageDirty)
return;
/* Flush the FLASH page to physical memory if we are crossing a page boundary */
uint32_t NewPageStartAddress = (HEXParser.CurrAddress & ~(SPM_PAGESIZE - 1));
if (HEXParser.PageStartAddress != NewPageStartAddress)
{
boot_page_write(HEXParser.PageStartAddress);
boot_spm_busy_wait();
HEXParser.PageStartAddress = NewPageStartAddress;
PageDirty = false;
}
}
/**
* Parses an input Intel HEX formatted stream one character at a time, loading
* the data contents into the device's internal FLASH memory.
*
* \param[in] ReadCharacter Next input ASCII byte of data to parse
*/
static void ParseIntelHEXByte(const char ReadCharacter)
{
/* Reset the line parser while waiting for a new line to start */
if ((HEXParser.ParserState == HEX_PARSE_STATE_WAIT_LINE) || (ReadCharacter == ':'))
{
HEXParser.Checksum = 0;
HEXParser.CurrAddress = HEXParser.CurrBaseAddress;
HEXParser.ReadMSB = false;
/* ASCII ':' indicates the start of a new HEX record */
if (ReadCharacter == ':')
HEXParser.ParserState = HEX_PARSE_STATE_BYTE_COUNT;
return;
}
/* Only allow ASCII HEX encoded digits, ignore all other characters */
int8_t ReadCharacterDec = HexToDecimal(ReadCharacter);
if (ReadCharacterDec < 0)
return;
/* Read and convert the next nibble of data from the current character */
HEXParser.Data = (HEXParser.Data << 4) | ReadCharacterDec;
HEXParser.ReadMSB = !HEXParser.ReadMSB;
/* Only process further when a full byte (two nibbles) have been read */
if (HEXParser.ReadMSB)
return;
/* Intel HEX checksum is for all fields except starting character and the
* checksum itself
*/
if (HEXParser.ParserState != HEX_PARSE_STATE_CHECKSUM)
HEXParser.Checksum += HEXParser.Data;
switch (HEXParser.ParserState)
{
case HEX_PARSE_STATE_BYTE_COUNT:
HEXParser.DataRem = HEXParser.Data;
HEXParser.ParserState = HEX_PARSE_STATE_ADDRESS_HIGH;
break;
case HEX_PARSE_STATE_ADDRESS_HIGH:
HEXParser.CurrAddress += ((uint16_t)HEXParser.Data << 8);
HEXParser.ParserState = HEX_PARSE_STATE_ADDRESS_LOW;
break;
case HEX_PARSE_STATE_ADDRESS_LOW:
HEXParser.CurrAddress += HEXParser.Data;
HEXParser.ParserState = HEX_PARSE_STATE_RECORD_TYPE;
break;
case HEX_PARSE_STATE_RECORD_TYPE:
HEXParser.RecordType = HEXParser.Data;
HEXParser.ParserState = (HEXParser.DataRem ? HEX_PARSE_STATE_READ_DATA : HEX_PARSE_STATE_CHECKSUM);
break;
case HEX_PARSE_STATE_READ_DATA:
/* Track the number of read data bytes in the record */
HEXParser.DataRem--;
/* Protect the bootloader against being written to */
if (HEXParser.CurrAddress >= BOOT_START_ADDR)
{
HEXParser.ParserState = HEX_PARSE_STATE_WAIT_LINE;
PageDirty = false;
return;
}
/* Wait for a machine word (two bytes) of data to be read */
if (HEXParser.DataRem & 0x01)
{
HEXParser.PrevData = HEXParser.Data;
break;
}
/* Convert the last two received data bytes into a 16-bit word */
uint16_t NewDataWord = ((uint16_t)HEXParser.Data << 8) | HEXParser.PrevData;
switch (HEXParser.RecordType)
{
case HEX_RECORD_TYPE_Data:
/* If we are writing to a new page, we need to erase it first */
if (!(PageDirty))
{
boot_page_erase(HEXParser.PageStartAddress);
boot_spm_busy_wait();
PageDirty = true;
}
/* Fill the FLASH memory buffer with the new word of data */
boot_page_fill(HEXParser.CurrAddress, NewDataWord);
HEXParser.CurrAddress += 2;
/* Flush the FLASH page to physical memory if we are crossing a page boundary */
FlushPageIfRequired();
break;
case HEX_RECORD_TYPE_ExtendedSegmentAddress:
/* Extended address data - store the upper 12-bits of the new address */
HEXParser.CurrBaseAddress = ((uint32_t)NewDataWord << 4);
break;
case HEX_RECORD_TYPE_ExtendedLinearAddress:
/* Extended address data - store the upper 16-bits of the new address */
HEXParser.CurrBaseAddress = ((uint32_t)NewDataWord << 16);
break;
}
if (!HEXParser.DataRem)
HEXParser.ParserState = HEX_PARSE_STATE_CHECKSUM;
break;
case HEX_PARSE_STATE_CHECKSUM:
/* Verify checksum of the completed record */
if (HEXParser.Data != ((~HEXParser.Checksum + 1) & 0xFF))
break;
/* Flush the FLASH page to physical memory if we are crossing a page boundary */
FlushPageIfRequired();
/* If end of the HEX file reached, the bootloader should exit at next opportunity */
if (HEXParser.RecordType == HEX_RECORD_TYPE_EndOfFile)
RunBootloader = false;
break;
default:
HEXParser.ParserState = HEX_PARSE_STATE_WAIT_LINE;
break;
}
}
/** Main program entry point. This routine configures the hardware required by the application, then
* enters a loop to run the application tasks in sequence.
*/
int main(void)
{
SetupHardware();
LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);
GlobalInterruptEnable();
while (RunBootloader)
{
uint8_t BytesReceived = PRNT_Device_BytesReceived(&TextOnly_Printer_Interface);
if (BytesReceived)
{
LEDs_SetAllLEDs(LEDMASK_USB_BUSY);
while (BytesReceived--)
{
int16_t ReceivedByte = PRNT_Device_ReceiveByte(&TextOnly_Printer_Interface);
/* Feed the next byte of data to the HEX parser */
ParseIntelHEXByte(ReceivedByte);
}
LEDs_SetAllLEDs(LEDMASK_USB_READY);
}
PRNT_Device_USBTask(&TextOnly_Printer_Interface);
USB_USBTask();
}
/* Disconnect from the host - USB interface will be reset later along with the AVR */
USB_Detach();
/* Unlock the forced application start mode of the bootloader if it is restarted */
MagicBootKey = MAGIC_BOOT_KEY;
/* Enable the watchdog and force a timeout to reset the AVR */
wdt_enable(WDTO_250MS);
for (;;);
}
/** Configures the board hardware and chip peripherals for the demo's functionality. */
static 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);
/* Hardware Initialization */
LEDs_Init();
USB_Init();
/* Bootloader active LED toggle timer initialization */
TIMSK1 = (1 << TOIE1);
TCCR1B = ((1 << CS11) | (1 << CS10));
}
/** ISR to periodically toggle the LEDs on the board to indicate that the bootloader is active. */
ISR(TIMER1_OVF_vect, ISR_BLOCK)
{
LEDs_ToggleLEDs(LEDS_LED1 | LEDS_LED2);
}
/** Event handler for the USB_Connect event. This indicates that the device is enumerating via the status LEDs. */
void EVENT_USB_Device_Connect(void)
{
/* Indicate USB enumerating */
LEDs_SetAllLEDs(LEDMASK_USB_ENUMERATING);
}
/** Event handler for the USB_Disconnect event. This indicates that the device is no longer connected to a host via
* the status LEDs and stops the Printer management task.
*/
void EVENT_USB_Device_Disconnect(void)
{
/* Indicate USB not ready */
LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);
}
/** Event handler for the USB_ConfigurationChanged event. This is fired when the host set the current configuration
* of the USB device after enumeration - the device endpoints are configured and the Mass Storage management task started.
*/
void EVENT_USB_Device_ConfigurationChanged(void)
{
bool ConfigSuccess = true;
/* Setup Printer Data Endpoints */
ConfigSuccess &= PRNT_Device_ConfigureEndpoints(&TextOnly_Printer_Interface);
/* Reset the HEX parser upon successful connection to a host */
HEXParser.ParserState = HEX_PARSE_STATE_WAIT_LINE;
/* Indicate endpoint configuration success or failure */
LEDs_SetAllLEDs(ConfigSuccess ? LEDMASK_USB_READY : LEDMASK_USB_ERROR);
}
/** 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)
{
PRNT_Device_ProcessControlRequest(&TextOnly_Printer_Interface);
}

@ -0,0 +1,108 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2017.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2017 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 disclaims 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 BootloaderPrinter.c.
*/
#ifndef _BOOTLOADER_PRINTER_H_
#define _BOOTLOADER_PRINTER_H_
/* Includes: */
#include <avr/io.h>
#include <avr/wdt.h>
#include <avr/power.h>
#include <avr/interrupt.h>
#include "Descriptors.h"
#include <LUFA/Drivers/Board/LEDs.h>
#include <LUFA/Drivers/USB/USB.h>
#include <LUFA/Platform/Platform.h>
/* Preprocessor Checks: */
#if !defined(__OPTIMIZE_SIZE__)
#error This bootloader requires that it be optimized for size, not speed, to fit into the target device. Change optimization settings and try again.
#endif
/* Macros: */
/** LED mask for the library LED driver, to indicate that the USB interface is not ready. */
#define LEDMASK_USB_NOTREADY LEDS_LED1
/** LED mask for the library LED driver, to indicate that the USB interface is enumerating. */
#define LEDMASK_USB_ENUMERATING (LEDS_LED2 | LEDS_LED3)
/** LED mask for the library LED driver, to indicate that the USB interface is ready. */
#define LEDMASK_USB_READY (LEDS_LED2 | LEDS_LED4)
/** LED mask for the library LED driver, to indicate that an error has occurred in the USB interface. */
#define LEDMASK_USB_ERROR (LEDS_LED1 | LEDS_LED3)
/** LED mask for the library LED driver, to indicate that the USB interface is busy. */
#define LEDMASK_USB_BUSY LEDS_LED2
/** Magic bootloader key to unlock forced application start mode. */
#define MAGIC_BOOT_KEY 0xDC42
/* Enums: */
/** Intel HEX parser state machine states. */
enum HEX_Parser_States_t
{
HEX_PARSE_STATE_WAIT_LINE, /**< Parser is waiting for a HEX Start of Line character. */
HEX_PARSE_STATE_BYTE_COUNT, /**< Parser is waiting for a record byte count. */
HEX_PARSE_STATE_ADDRESS_HIGH, /**< Parser is waiting for the MSB of a record address. */
HEX_PARSE_STATE_ADDRESS_LOW, /**< Parser is waiting for the LSB of a record address. */
HEX_PARSE_STATE_RECORD_TYPE, /**< Parser is waiting for the record type. */
HEX_PARSE_STATE_READ_DATA, /**< Parser is waiting for more data in the current record. */
HEX_PARSE_STATE_CHECKSUM, /**< Parser is waiting for the checksum of the current record. */
};
/** Intel HEX record types, used to indicate the type of record contained in a line of a HEX file. */
enum HEX_Record_Types_t
{
HEX_RECORD_TYPE_Data = 0, /**< Record contains loadable data. */
HEX_RECORD_TYPE_EndOfFile = 1, /**< End of file record. */
HEX_RECORD_TYPE_ExtendedSegmentAddress = 2, /**< Extended segment start record. */
HEX_RECORD_TYPE_StartSegmentAddress = 3, /**< Normal segment start record. */
HEX_RECORD_TYPE_ExtendedLinearAddress = 4, /**< Extended linear address start record. */
HEX_RECORD_TYPE_StartLinearAddress = 5, /**< Linear address start record. */
};
/* Function Prototypes: */
static 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_ControlRequest(void);
#endif

@ -0,0 +1,202 @@
/** \file
*
* This file contains special DoxyGen information for the generation of the main page and other special
* documentation pages. It is not a project source file.
*/
/** \mainpage Printer Class USB AVR Bootloader
*
* \section Sec_Compat Demo Compatibility:
*
* The following list indicates what microcontrollers are compatible with this demo.
*
* \li Series 7 USB AVRs (AT90USBxxx7)
* \li Series 6 USB AVRs (AT90USBxxx6)
* \li Series 4 USB AVRs (ATMEGAxxU4)
* \li Series 2 USB AVRs (AT90USBxx2, ATMEGAxxU2)
*
* \section Sec_Info USB Information:
*
* The following table gives a rundown of the USB utilization of this demo.
*
* <table>
* <tr>
* <td><b>USB Mode:</b></td>
* <td>Device</td>
* </tr>
* <tr>
* <td><b>USB Class:</b></td>
* <td>Printer Class</td>
* </tr>
* <tr>
* <td><b>USB Subclass:</b></td>
* <td>Printer Subclass</td>
* </tr>
* <tr>
* <td><b>Relevant Standards:</b></td>
* <td>USBIF Printer Class Standard</td>
* </tr>
* <tr>
* <td><b>Supported USB Speeds:</b></td>
* <td>Full Speed Mode</td>
* </tr>
* </table>
*
* \section Sec_Description Project Description:
*
* This bootloader enumerates to the host as a Generic Text Only Printer device, capable of reading and parsing
* "printed" plain-text Intel HEX files to load firmware onto the AVR.
*
* Out of the box this bootloader builds for the AT90USB1287 with an 8KB bootloader section size, and will fit
* into 4KB of bootloader space. If you wish to alter this size and/or change the AVR model, you will need to
* edit the MCU, FLASH_SIZE_KB and BOOT_SECTION_SIZE_KB values in the accompanying makefile.
*
* When the bootloader is running, the board's LED(s) will flash at regular intervals to distinguish the
* bootloader from the normal user application.
*
* \section Sec_Running Running the Bootloader
*
* On the USB AVR8 devices, setting the \c HWBE device fuse will cause the bootloader to run if the \c HWB pin of
* the AVR is grounded when the device is reset.
*
* The are two behaviours of this bootloader, depending on the device's fuses:
*
* <b>If the device's BOOTRST fuse is set</b>, the bootloader will run any time the system is reset from
* the external reset pin, unless no valid user application has been loaded. To initiate the bootloader, the
* device's external reset pin should be grounded momentarily.
*
* <b>If the device's BOOTRST fuse is not set</b>, the bootloader will run only if initiated via a software
* jump, or if the \c HWB pin was low during the last device reset (if the \c HWBE fuse is set).
*
* For board specific exceptions to the above, see below.
*
* \subsection SSec_XPLAIN Atmel Xplain Board
* Ground the USB AVR JTAG's \c TCK pin to ground when powering on the board to start the bootloader. This assumes the
* \c HWBE fuse is cleared and the \c BOOTRST fuse is set as the HWBE pin is not user accessible on this board.
*
* \subsection SSec_Leonardo Arduino Leonardo Board
* Ground \c IO13 when powering the board to start the bootloader. This assumes the \c HWBE fuse is cleared and the
* \c BOOTRST fuse is set as the HWBE pin is not user accessible on this board.
*
* \section Sec_Installation Driver Installation
*
* This bootloader uses the Generic Text-Only printer drivers inbuilt into all modern operating systems, thus no
* additional drivers need to be supplied for correct operation.
*
* \section Sec_HostApp Host Controller Application
*
* This bootloader is compatible with Notepad under Windows, and the command line \c lpr utility under Linux.
*
* \subsection SSec_Notepad Notepad (Windows)
*
* While most text applications under Windows will be compatible with the bootloader, the inbuilt Notepad utility
* is recommended as it will introduce minimal formatting changes to the output stream. To program with Notepad,
* open the target HEX file and print it to the Generic Text Only printer device the bootloader creates.
*
* \subsection SSec_LPR LPR (Linux)
*
* While the CUPS framework under Linux will enumerate the bootloader as a Generic Text-Only printer, many
* applications will refuse to print to the device due to the lack of rich formatting options available. As a result,
* under Linux HEX files must be printed via the low level \c lpr utility instead.
*
* \code
* cat Mouse.hex | lpr
* \endcode
*
* \section Sec_API User Application API
*
* Several user application functions for FLASH and other special memory area manipulations are exposed by the bootloader,
* allowing the user application to call into the bootloader at runtime to read and write FLASH data.
*
* By default, the bootloader API jump table is located 32 bytes from the end of the device's FLASH memory, and follows the
* following layout:
*
* \code
* #define BOOTLOADER_API_TABLE_SIZE 32
* #define BOOTLOADER_API_TABLE_START ((FLASHEND + 1UL) - BOOTLOADER_API_TABLE_SIZE)
* #define BOOTLOADER_API_CALL(Index) (void*)((BOOTLOADER_API_TABLE_START + (Index * 2)) / 2)
*
* void (*BootloaderAPI_ErasePage)(uint32_t Address) = BOOTLOADER_API_CALL(0);
* void (*BootloaderAPI_WritePage)(uint32_t Address) = BOOTLOADER_API_CALL(1);
* void (*BootloaderAPI_FillWord)(uint32_t Address, uint16_t Word) = BOOTLOADER_API_CALL(2);
* uint8_t (*BootloaderAPI_ReadSignature)(uint16_t Address) = BOOTLOADER_API_CALL(3);
* uint8_t (*BootloaderAPI_ReadFuse)(uint16_t Address) = BOOTLOADER_API_CALL(4);
* uint8_t (*BootloaderAPI_ReadLock)(void) = BOOTLOADER_API_CALL(5);
* void (*BootloaderAPI_WriteLock)(uint8_t LockBits) = BOOTLOADER_API_CALL(6);
*
* #define BOOTLOADER_MAGIC_SIGNATURE_START (BOOTLOADER_API_TABLE_START + (BOOTLOADER_API_TABLE_SIZE - 2))
* #define BOOTLOADER_MAGIC_SIGNATURE 0xDCFB
*
* #define BOOTLOADER_CLASS_SIGNATURE_START (BOOTLOADER_API_TABLE_START + (BOOTLOADER_API_TABLE_SIZE - 4))
* #define BOOTLOADER_PRINTER_SIGNATURE 0xDF20
*
* #define BOOTLOADER_ADDRESS_START (BOOTLOADER_API_TABLE_START + (BOOTLOADER_API_TABLE_SIZE - 8))
* #define BOOTLOADER_ADDRESS_LENGTH 4
* \endcode
*
* From the application the API support of the bootloader can be detected by reading the FLASH memory bytes located at address
* \c BOOTLOADER_MAGIC_SIGNATURE_START and comparing them to the value \c BOOTLOADER_MAGIC_SIGNATURE. The class of bootloader
* can be determined by reading the FLASH memory bytes located at address \c BOOTLOADER_CLASS_SIGNATURE_START and comparing them
* to the value \c BOOTLOADER_PRINTER_SIGNATURE. The start address of the bootloader can be retrieved by reading the bytes of FLASH
* memory starting from address \c BOOTLOADER_ADDRESS_START.
*
* \subsection SSec_API_MemLayout Device Memory Map
* The following illustration indicates the final memory map of the device when loaded with the bootloader.
*
* \verbatim
* +----------------------------+ 0x0000
* | |
* | |
* | |
* | |
* | |
* | |
* | |
* | |
* | User Application |
* | |
* | |
* | |
* | |
* | |
* | |
* | |
* +----------------------------+ FLASHEND - BOOT_SECTION_SIZE
* | |
* | Bootloader Application |
* | (Not User App. Accessible) |
* | |
* +----------------------------+ FLASHEND - 96
* | API Table Trampolines |
* | (Not User App. Accessible) |
* +----------------------------+ FLASHEND - 32
* | Bootloader API Table |
* | (User App. Accessible) |
* +----------------------------+ FLASHEND - 8
* | Bootloader ID Constants |
* | (User App. Accessible) |
* +----------------------------+ FLASHEND
* \endverbatim
*
*
* \section Sec_KnownIssues Known Issues:
*
* \par On Linux machines, new firmware fails to be sent to the device via CUPS.
* Only a limited subset of normal printer functionality is exposed via the
* bootloader, causing CUPS to reject print requests from applications that
* are unable to handle true plain-text printing. For best results, the low
* level \c lpr command should be used to print new firmware to the bootloader.
*
* \section Sec_Options Project Options
*
* The following defines can be found in this demo, which can control the demo behaviour when defined, or changed in value.
*
* <table>
* <tr>
* <td>
* None
* </td>
* </tr>
* </table>
*/

@ -0,0 +1,93 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2017.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2017 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 disclaims 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
* \brief LUFA Library Configuration Header File
*
* This header file is used to configure LUFA's compile time options,
* as an alternative to the compile time constants supplied through
* a makefile.
*
* For information on what each token does, refer to the LUFA
* manual section "Summary of Compile Tokens".
*/
#ifndef _LUFA_CONFIG_H_
#define _LUFA_CONFIG_H_
#if (ARCH == ARCH_AVR8)
/* Non-USB Related Configuration Tokens: */
// #define DISABLE_TERMINAL_CODES
/* USB Class Driver Related Tokens: */
// #define HID_HOST_BOOT_PROTOCOL_ONLY
// #define HID_STATETABLE_STACK_DEPTH {Insert Value Here}
// #define HID_USAGE_STACK_DEPTH {Insert Value Here}
// #define HID_MAX_COLLECTIONS {Insert Value Here}
// #define HID_MAX_REPORTITEMS {Insert Value Here}
// #define HID_MAX_REPORT_IDS {Insert Value Here}
// #define NO_CLASS_DRIVER_AUTOFLUSH
/* General USB Driver Related Tokens: */
#define ORDERED_EP_CONFIG
#define USE_STATIC_OPTIONS (USB_DEVICE_OPT_FULLSPEED | USB_OPT_REG_ENABLED | USB_OPT_AUTO_PLL)
#define USB_DEVICE_ONLY
// #define USB_HOST_ONLY
// #define USB_STREAM_TIMEOUT_MS {Insert Value Here}
// #define NO_LIMITED_CONTROLLER_CONNECT
#define NO_SOF_EVENTS
/* USB Device Mode Driver Related Tokens: */
#define USE_RAM_DESCRIPTORS
// #define USE_FLASH_DESCRIPTORS
// #define USE_EEPROM_DESCRIPTORS
#define NO_INTERNAL_SERIAL
#define FIXED_CONTROL_ENDPOINT_SIZE 8
#define DEVICE_STATE_AS_GPIOR 0
#define FIXED_NUM_CONFIGURATIONS 1
// #define CONTROL_ONLY_DEVICE
// #define INTERRUPT_CONTROL_ENDPOINT
#define NO_DEVICE_REMOTE_WAKEUP
#define NO_DEVICE_SELF_POWER
/* USB Host Mode Driver Related Tokens: */
// #define HOST_STATE_AS_GPIOR {Insert Value Here}
// #define USB_HOST_TIMEOUT_MS {Insert Value Here}
// #define HOST_DEVICE_SETTLE_DELAY_MS {Insert Value Here}
// #define NO_AUTO_VBUS_MANAGEMENT
// #define INVERTED_VBUS_ENABLE_LINE
#else
#error Unsupported architecture for this LUFA configuration file.
#endif
#endif

@ -0,0 +1,194 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2017.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2017 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 disclaims 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(1,1,0),
.Class = USB_CSCP_NoDeviceClass,
.SubClass = USB_CSCP_NoDeviceSubclass,
.Protocol = USB_CSCP_NoDeviceProtocol,
.Endpoint0Size = FIXED_CONTROL_ENDPOINT_SIZE,
.VendorID = 0x03EB,
.ProductID = 0x206B,
.ReleaseNumber = VERSION_BCD(0,0,1),
.ManufacturerStrIndex = STRING_ID_Manufacturer,
.ProductStrIndex = STRING_ID_Product,
.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 = 1,
.ConfigurationNumber = 1,
.ConfigurationStrIndex = NO_DESCRIPTOR,
.ConfigAttributes = USB_CONFIG_ATTR_RESERVED,
.MaxPowerConsumption = USB_CONFIG_POWER_MA(100)
},
.Printer_Interface =
{
.Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},
.InterfaceNumber = INTERFACE_ID_Printer,
.AlternateSetting = 0,
.TotalEndpoints = 2,
.Class = PRNT_CSCP_PrinterClass,
.SubClass = PRNT_CSCP_PrinterSubclass,
.Protocol = PRNT_CSCP_BidirectionalProtocol,
.InterfaceStrIndex = NO_DESCRIPTOR
},
.Printer_DataInEndpoint =
{
.Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
.EndpointAddress = PRINTER_IN_EPADDR,
.Attributes = (EP_TYPE_BULK | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
.EndpointSize = PRINTER_IO_EPSIZE,
.PollingIntervalMS = 0x05
},
.Printer_DataOutEndpoint =
{
.Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
.EndpointAddress = PRINTER_OUT_EPADDR,
.Attributes = (EP_TYPE_BULK | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
.EndpointSize = PRINTER_IO_EPSIZE,
.PollingIntervalMS = 0x05
}
};
/** 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 = USB_STRING_DESCRIPTOR_ARRAY(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.
*/
const USB_Descriptor_String_t ManufacturerString = USB_STRING_DESCRIPTOR(L"Dean Camera");
/** 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 = USB_STRING_DESCRIPTOR(L"LUFA Printer Bootloader");
/** 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 uint16_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:
switch (DescriptorNumber)
{
case STRING_ID_Language:
Address = &LanguageString;
Size = LanguageString.Header.Size;
break;
case STRING_ID_Manufacturer:
Address = &ManufacturerString;
Size = ManufacturerString.Header.Size;
break;
case STRING_ID_Product:
Address = &ProductString;
Size = ProductString.Header.Size;
break;
}
break;
}
*DescriptorAddress = Address;
return Size;
}

@ -0,0 +1,96 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2017.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2017 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 disclaims 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>
#include <avr/pgmspace.h>
/* Macros: */
/** Endpoint address of the Printer device-to-host data IN endpoint. */
#define PRINTER_IN_EPADDR (ENDPOINT_DIR_IN | 3)
/** Endpoint address of the Printer host-to-device data OUT endpoint. */
#define PRINTER_OUT_EPADDR (ENDPOINT_DIR_OUT | 4)
/** Size in bytes of the Printer data endpoints. */
#define PRINTER_IO_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;
// Printer Interface
USB_Descriptor_Interface_t Printer_Interface;
USB_Descriptor_Endpoint_t Printer_DataInEndpoint;
USB_Descriptor_Endpoint_t Printer_DataOutEndpoint;
} USB_Descriptor_Configuration_t;
/** Enum for the device interface descriptor IDs within the device. Each string descriptor
* should have a unique ID index associated with it, which can be used to refer to the
* interface from other descriptors.
*/
enum InterfaceDescriptors_t
{
INTERFACE_ID_Printer = 0, /**< Printer interface descriptor ID */
};
/** Enum for the device string descriptor IDs within the device. Each string descriptor should
* have a unique ID index associated with it, which can be used to refer to the string from
* other descriptors.
*/
enum StringDescriptors_t
{
STRING_ID_Language = 0, /**< Supported Languages string descriptor ID (must be zero) */
STRING_ID_Manufacturer = 1, /**< Manufacturer string ID */
STRING_ID_Product = 2, /**< Product string ID */
};
/* Function Prototypes: */
uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue,
const uint16_t wIndex,
const void** const DescriptorAddress)
ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(3);
#endif

@ -0,0 +1,159 @@
<asf xmlversion="1.0">
<project caption="Printer Bootloader - 128KB FLASH / 4KB Boot - AVR8 Architecture" id="lufa.bootloaders.printer.avr8.128_4" force-caption="true" workspace-name="lufa_printer_128kb_4kb_">
<require idref="lufa.bootloaders.printer"/>
<require idref="lufa.boards.dummy.avr8"/>
<generator value="as5_8"/>
<device-support value="at90usb1287"/>
<config name="lufa.drivers.board.name" value="none"/>
<config name="config.compiler.optimization.level" value="size"/>
<build type="define" name="F_CPU" value="16000000UL"/>
<build type="define" name="F_USB" value="16000000UL"/>
<build type="define" name="BOOT_START_ADDR" value="0x1F000"/>
<build type="linker-config" subtype="flags" value="--section-start=.text=0x1F000"/>
<build type="linker-config" subtype="flags" value="--section-start=.apitable_trampolines=0x1FFA0"/>
<build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_Trampolines"/>
<build type="linker-config" subtype="flags" value="--section-start=.apitable_jumptable=0x1FFE0"/>
<build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_JumpTable"/>
<build type="linker-config" subtype="flags" value="--section-start=.apitable_signatures=0x1FFF8"/>
<build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_Signatures"/>
</project>
<project caption="Printer Bootloader - 64KB FLASH / 4KB Boot - AVR8 Architecture" id="lufa.bootloaders.printer.avr8.64_4" force-caption="true" workspace-name="lufa_printer_64kb_4kb_">
<require idref="lufa.bootloaders.printer"/>
<require idref="lufa.boards.dummy.avr8"/>
<generator value="as5_8"/>
<device-support value="at90usb647"/>
<config name="lufa.drivers.board.name" value="none"/>
<config name="config.compiler.optimization.level" value="size"/>
<build type="define" name="F_CPU" value="16000000UL"/>
<build type="define" name="F_USB" value="16000000UL"/>
<build type="define" name="BOOT_START_ADDR" value="0xF000"/>
<build type="linker-config" subtype="flags" value="--section-start=.text=0xF000"/>
<build type="linker-config" subtype="flags" value="--section-start=.apitable_trampolines=0xFFA0"/>
<build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_Trampolines"/>
<build type="linker-config" subtype="flags" value="--section-start=.apitable_jumptable=0xFFE0"/>
<build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_JumpTable"/>
<build type="linker-config" subtype="flags" value="--section-start=.apitable_signatures=0xFFF8"/>
<build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_Signatures"/>
</project>
<project caption="Printer Bootloader - 32KB FLASH / 4KB Boot - AVR8 Architecture" id="lufa.bootloaders.printer.avr8.32_4" force-caption="true" workspace-name="lufa_printer_32kb_4kb_">
<require idref="lufa.bootloaders.printer"/>
<require idref="lufa.boards.dummy.avr8"/>
<generator value="as5_8"/>
<device-support value="atmega32u4"/>
<config name="lufa.drivers.board.name" value="none"/>
<config name="config.compiler.optimization.level" value="size"/>
<build type="define" name="F_CPU" value="16000000UL"/>
<build type="define" name="F_USB" value="16000000UL"/>
<build type="define" name="BOOT_START_ADDR" value="0x7000"/>
<build type="linker-config" subtype="flags" value="--section-start=.text=0x7000"/>
<build type="linker-config" subtype="flags" value="--section-start=.apitable_trampolines=0x7FA0"/>
<build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_Trampolines"/>
<build type="linker-config" subtype="flags" value="--section-start=.apitable_jumptable=0x7FE0"/>
<build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_JumpTable"/>
<build type="linker-config" subtype="flags" value="--section-start=.apitable_signatures=0x7FF8"/>
<build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_Signatures"/>
</project>
<project caption="Printer Bootloader - 16KB FLASH / 4KB Boot - AVR8 Architecture" id="lufa.bootloaders.printer.avr8.16_4" force-caption="true" workspace-name="lufa_printer_16kb_4kb_">
<require idref="lufa.bootloaders.printer"/>
<require idref="lufa.boards.dummy.avr8"/>
<generator value="as5_8"/>
<device-support value="atmega16u2"/>
<config name="lufa.drivers.board.name" value="none"/>
<config name="config.compiler.optimization.level" value="size"/>
<build type="define" name="F_CPU" value="16000000UL"/>
<build type="define" name="F_USB" value="16000000UL"/>
<build type="define" name="BOOT_START_ADDR" value="0x3000"/>
<build type="linker-config" subtype="flags" value="--section-start=.text=0x3000"/>
<build type="linker-config" subtype="flags" value="--section-start=.apitable_trampolines=0x3FA0"/>
<build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_Trampolines"/>
<build type="linker-config" subtype="flags" value="--section-start=.apitable_jumptable=0x3FE0"/>
<build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_JumpTable"/>
<build type="linker-config" subtype="flags" value="--section-start=.apitable_signatures=0x3FF8"/>
<build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_Signatures"/>
</project>
<project caption="Printer Bootloader - 8KB FLASH / 4KB Boot - AVR8 Architecture" id="lufa.bootloaders.printer.avr8.8_4" force-caption="true" workspace-name="lufa_printer_8kb_4kb_">
<require idref="lufa.bootloaders.printer"/>
<require idref="lufa.boards.dummy.avr8"/>
<generator value="as5_8"/>
<device-support value="atmega8u2"/>
<config name="lufa.drivers.board.name" value="none"/>
<config name="config.compiler.optimization.level" value="size"/>
<build type="define" name="F_CPU" value="16000000UL"/>
<build type="define" name="F_USB" value="16000000UL"/>
<build type="define" name="BOOT_START_ADDR" value="0x1000"/>
<build type="linker-config" subtype="flags" value="--section-start=.text=0x1000"/>
<build type="linker-config" subtype="flags" value="--section-start=.apitable_trampolines=0x1FA0"/>
<build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_Trampolines"/>
<build type="linker-config" subtype="flags" value="--section-start=.apitable_jumptable=0x1FE0"/>
<build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_JumpTable"/>
<build type="linker-config" subtype="flags" value="--section-start=.apitable_signatures=0x1FF8"/>
<build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_Signatures"/>
</project>
<module type="application" id="lufa.bootloaders.printer" caption="Printer Bootloader">
<info type="description" value="summary">
Printer Class Bootloader, capable of reprogramming a device by "printing" new HEX files to the virtual Plain-Text printer it creates when plugged into a host.
</info>
<info type="gui-flag" value="move-to-root"/>
<info type="keyword" value="Technology">
<keyword value="Bootloaders"/>
<keyword value="USB Device"/>
</info>
<device-support-alias value="lufa_avr8"/>
<device-support-alias value="lufa_xmega"/>
<device-support-alias value="lufa_uc3"/>
<build type="include-path" value="."/>
<build type="c-source" value="BootloaderPrinter.c"/>
<build type="header-file" value="BootloaderPrinter.h"/>
<build type="c-source" value="Descriptors.c"/>
<build type="header-file" value="Descriptors.h"/>
<build type="c-source" value="BootloaderAPI.c"/>
<build type="header-file" value="BootloaderAPI.h"/>
<build type="asm-source" value="BootloaderAPITable.S"/>
<build type="module-config" subtype="path" value="Config"/>
<build type="header-file" value="Config/LUFAConfig.h"/>
<build type="distribute" subtype="user-file" value="doxyfile"/>
<build type="distribute" subtype="user-file" value="BootloaderPrinter.txt"/>
<require idref="lufa.common"/>
<require idref="lufa.platform"/>
<require idref="lufa.drivers.usb"/>
<require idref="lufa.drivers.board"/>
<require idref="lufa.drivers.board.leds"/>
</module>
</asf>

File diff suppressed because it is too large Load Diff

@ -0,0 +1,62 @@
#
# LUFA Library
# Copyright (C) Dean Camera, 2017.
#
# dean [at] fourwalledcubicle [dot] com
# www.lufa-lib.org
#
# --------------------------------------
# LUFA Project Makefile.
# --------------------------------------
# Run "make help" for target help.
MCU = at90usb1287
ARCH = AVR8
BOARD = USBKEY
F_CPU = 8000000
F_USB = $(F_CPU)
OPTIMIZATION = s
TARGET = BootloaderPrinter
SRC = $(TARGET).c Descriptors.c BootloaderAPI.c BootloaderAPITable.S $(LUFA_SRC_USB) $(LUFA_SRC_USBCLASS)
LUFA_PATH = ../../LUFA
CC_FLAGS = -DUSE_LUFA_CONFIG_HEADER -IConfig/ -DBOOT_START_ADDR=$(BOOT_START_OFFSET)
LD_FLAGS = -Wl,--section-start=.text=$(BOOT_START_OFFSET) $(BOOT_API_LD_FLAGS)
# Flash size and bootloader section sizes of the target, in KB. These must
# match the target's total FLASH size and the bootloader size set in the
# device's fuses.
FLASH_SIZE_KB = 128
BOOT_SECTION_SIZE_KB = 8
# Bootloader address calculation formulas
# Do not modify these macros, but rather modify the dependent values above.
CALC_ADDRESS_IN_HEX = $(shell printf "0x%X" $$(( $(1) )) )
BOOT_START_OFFSET = $(call CALC_ADDRESS_IN_HEX, ($(FLASH_SIZE_KB) - $(BOOT_SECTION_SIZE_KB)) * 1024 )
BOOT_SEC_OFFSET = $(call CALC_ADDRESS_IN_HEX, ($(FLASH_SIZE_KB) * 1024) - ($(strip $(1))) )
# Bootloader linker section flags for relocating the API table sections to
# known FLASH addresses - these should not normally be user-edited.
BOOT_SECTION_LD_FLAG = -Wl,--section-start=$(strip $(1))=$(call BOOT_SEC_OFFSET, $(3)) -Wl,--undefined=$(strip $(2))
BOOT_API_LD_FLAGS = $(call BOOT_SECTION_LD_FLAG, .apitable_trampolines, BootloaderAPI_Trampolines, 96)
BOOT_API_LD_FLAGS += $(call BOOT_SECTION_LD_FLAG, .apitable_jumptable, BootloaderAPI_JumpTable, 32)
BOOT_API_LD_FLAGS += $(call BOOT_SECTION_LD_FLAG, .apitable_signatures, BootloaderAPI_Signatures, 8)
# Default target
all:
# Include LUFA-specific DMBS extension modules
DMBS_LUFA_PATH ?= $(LUFA_PATH)/Build/LUFA
include $(DMBS_LUFA_PATH)/lufa-sources.mk
include $(DMBS_LUFA_PATH)/lufa-gcc.mk
# Include common DMBS build system modules
DMBS_PATH ?= $(LUFA_PATH)/Build/DMBS/DMBS
include $(DMBS_PATH)/core.mk
include $(DMBS_PATH)/cppcheck.mk
include $(DMBS_PATH)/doxygen.mk
include $(DMBS_PATH)/dfu.mk
include $(DMBS_PATH)/gcc.mk
include $(DMBS_PATH)/hid.mk
include $(DMBS_PATH)/avrdude.mk
include $(DMBS_PATH)/atprogram.mk

@ -0,0 +1,46 @@
#
# LUFA Library
# Copyright (C) Dean Camera, 2017.
#
# dean [at] fourwalledcubicle [dot] com
# www.lufa-lib.org
#
# Makefile to build all the LUFA USB Bootloaders. Call with "make all" to
# rebuild all bootloaders.
# Bootloaders are pre-cleaned before each one is built, to ensure any
# custom LUFA library build options are reflected in the compiled
# code.
PROJECT_DIRECTORIES := $(shell ls -d */)
# This makefile is potentially infinitely recursive if something really bad
# happens when determining the set of project directories - hard-abort if
# more than 10 levels deep to avoid angry emails.
ifeq ($(MAKELEVEL), 10)
$(error EMERGENCY ABORT: INFINITE RECURSION DETECTED)
endif
# Need to special-case building without a per-project object directory
ifeq ($(OBJDIR),)
# If no target specified, force "clean all" and disallow parallel build
ifeq ($(MAKECMDGOALS),)
MAKECMDGOALS := clean all
.NOTPARALLEL:
endif
# If one of the targets is to build, force "clean" beforehand and disallow parallel build
ifneq ($(findstring all, $(MAKECMDGOALS)),)
MAKECMDGOALS := clean $(MAKECMDGOALS)
.NOTPARALLEL:
endif
endif
%: $(PROJECT_DIRECTORIES)
@echo . > /dev/null
$(PROJECT_DIRECTORIES):
@$(MAKE) -C $@ $(MAKECMDGOALS)
.PHONY: $(PROJECT_DIRECTORIES)

@ -0,0 +1,82 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2017.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2017 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 disclaims 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
* \brief LUFA Custom Board Hardware Information Driver (Template)
*
* This is a stub driver header file, for implementing custom board
* layout hardware with compatible LUFA board specific drivers. If
* the library is configured to use the BOARD_USER board mode, this
* driver file should be completed and copied into the "/Board/" folder
* inside the application's folder.
*
* This stub is for the board-specific component of the LUFA Board Hardware
* information driver.
*/
#ifndef __BOARD_USER_H__
#define __BOARD_USER_H__
/* Includes: */
// TODO: Add any required includes here
/* Enable C linkage for C++ Compilers: */
#if defined(__cplusplus)
extern "C" {
#endif
/* Preprocessor Checks: */
#if !defined(__INCLUDE_FROM_BOARD_H)
#error Do not include this file directly. Include LUFA/Drivers/Board/Board.h instead.
#endif
/* Public Interface - May be used in end-application: */
/* Macros: */
/** Indicates the board has a hardware Buttons mounted if defined. */
// #define BOARD_HAS_BUTTONS
/** Indicates the board has a hardware Dataflash mounted if defined. */
// #define BOARD_HAS_DATAFLASH
/** Indicates the board has a hardware Joystick mounted if defined. */
// #define BOARD_HAS_JOYSTICK
/** Indicates the board has a hardware LEDs mounted if defined. */
// #define BOARD_HAS_LEDS
/* Disable C linkage for C++ Compilers: */
#if defined(__cplusplus)
}
#endif
#endif
/** @} */

@ -0,0 +1,92 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2017.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2017 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 disclaims 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
* \brief LUFA Custom Board Button Hardware Driver (Template)
*
* This is a stub driver header file, for implementing custom board
* layout hardware with compatible LUFA board specific drivers. If
* the library is configured to use the BOARD_USER board mode, this
* driver file should be completed and copied into the "/Board/" folder
* inside the application's folder.
*
* This stub is for the board-specific component of the LUFA Buttons driver,
* for the control of physical board-mounted GPIO pushbuttons.
*/
#ifndef __BUTTONS_USER_H__
#define __BUTTONS_USER_H__
/* Includes: */
// TODO: Add any required includes here
/* Enable C linkage for C++ Compilers: */
#if defined(__cplusplus)
extern "C" {
#endif
/* Preprocessor Checks: */
#if !defined(__INCLUDE_FROM_BUTTONS_H)
#error Do not include this file directly. Include LUFA/Drivers/Board/Buttons.h instead.
#endif
#define BOARD_DUMMY_BUTTONS_IMPLEMENTATION
/* Public Interface - May be used in end-application: */
/* Macros: */
/** Button mask for the first button on the board. */
#define BUTTONS_BUTTON1 (1 << 0)
/* Inline Functions: */
#if !defined(__DOXYGEN__)
static inline void Buttons_Init(void)
{
}
static inline void Buttons_Disable(void)
{
}
static inline uint8_t Buttons_GetStatus(void) ATTR_WARN_UNUSED_RESULT;
static inline uint8_t Buttons_GetStatus(void)
{
return 0;
}
#endif
/* Disable C linkage for C++ Compilers: */
#if defined(__cplusplus)
}
#endif
#endif

@ -0,0 +1,197 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2017.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2017 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 disclaims 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
* \brief LUFA Custom Board Dataflash Hardware Driver (Template)
*
* This is a stub driver header file, for implementing custom board
* layout hardware with compatible LUFA board specific drivers. If
* the library is configured to use the BOARD_USER board mode, this
* driver file should be completed and copied into the "/Board/" folder
* inside the application's folder.
*
* This stub is for the board-specific component of the LUFA Dataflash
* driver.
*/
#ifndef __DATAFLASH_USER_H__
#define __DATAFLASH_USER_H__
/* Includes: */
// TODO: Add any required includes here
/* Preprocessor Checks: */
#if !defined(__INCLUDE_FROM_DATAFLASH_H)
#error Do not include this file directly. Include LUFA/Drivers/Board/Dataflash.h instead.
#endif
#define BOARD_DUMMY_DATAFLASH_IMPLEMENTATION
/* Private Interface - For use in library only: */
#if !defined(__DOXYGEN__)
/* Macros: */
#define DATAFLASH_CHIPCS_MASK 0
#define DATAFLASH_CHIPCS_DDR 0
#define DATAFLASH_CHIPCS_PORT 0
#endif
/* Public Interface - May be used in end-application: */
/* Macros: */
/** Constant indicating the total number of dataflash ICs mounted on the selected board. */
#define DATAFLASH_TOTALCHIPS 1
/** Mask for no dataflash chip selected. */
#define DATAFLASH_NO_CHIP 0
/** Mask for the first dataflash chip selected. */
#define DATAFLASH_CHIP1 0
/** Mask for the second dataflash chip selected. */
#define DATAFLASH_CHIP2 0
/** Internal main memory page size for the board's dataflash ICs. */
#define DATAFLASH_PAGE_SIZE 0
/** Total number of pages inside each of the board's dataflash ICs. */
#define DATAFLASH_PAGES 0
/* Inline Functions: */
/** Initializes the dataflash driver so that commands and data may be sent to an attached dataflash IC.
* The microcontroller's SPI driver MUST be initialized before any of the dataflash commands are used.
*/
static inline void Dataflash_Init(void)
{
}
/** Sends a byte to the currently selected dataflash IC, and returns a byte from the dataflash.
*
* \param[in] Byte Byte of data to send to the dataflash
*
* \return Last response byte from the dataflash
*/
static inline uint8_t Dataflash_TransferByte(const uint8_t Byte) ATTR_ALWAYS_INLINE;
static inline uint8_t Dataflash_TransferByte(const uint8_t Byte)
{
return 0;
}
/** Sends a byte to the currently selected dataflash IC, and ignores the next byte from the dataflash.
*
* \param[in] Byte Byte of data to send to the dataflash
*/
static inline void Dataflash_SendByte(const uint8_t Byte) ATTR_ALWAYS_INLINE;
static inline void Dataflash_SendByte(const uint8_t Byte)
{
}
/** Sends a dummy byte to the currently selected dataflash IC, and returns the next byte from the dataflash.
*
* \return Last response byte from the dataflash
*/
static inline uint8_t Dataflash_ReceiveByte(void) ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT;
static inline uint8_t Dataflash_ReceiveByte(void)
{
return 0;
}
/** Determines the currently selected dataflash chip.
*
* \return Mask of the currently selected Dataflash chip, either \ref DATAFLASH_NO_CHIP if no chip is selected
* or a DATAFLASH_CHIPn mask (where n is the chip number).
*/
static inline uint8_t Dataflash_GetSelectedChip(void) ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT;
static inline uint8_t Dataflash_GetSelectedChip(void)
{
return 0;
}
/** Selects the given dataflash chip.
*
* \param[in] ChipMask Mask of the Dataflash IC to select, in the form of a \c DATAFLASH_CHIPn mask (where n is
* the chip number).
*/
static inline void Dataflash_SelectChip(const uint8_t ChipMask) ATTR_ALWAYS_INLINE;
static inline void Dataflash_SelectChip(const uint8_t ChipMask)
{
}
/** Deselects the current dataflash chip, so that no dataflash is selected. */
static inline void Dataflash_DeselectChip(void) ATTR_ALWAYS_INLINE;
static inline void Dataflash_DeselectChip(void)
{
}
/** Selects a dataflash IC from the given page number, which should range from 0 to
* ((DATAFLASH_PAGES * DATAFLASH_TOTALCHIPS) - 1). For boards containing only one
* dataflash IC, this will select DATAFLASH_CHIP1. If the given page number is outside
* the total number of pages contained in the boards dataflash ICs, all dataflash ICs
* are deselected.
*
* \param[in] PageAddress Address of the page to manipulate, ranging from
* 0 to ((DATAFLASH_PAGES * DATAFLASH_TOTALCHIPS) - 1).
*/
static inline void Dataflash_SelectChipFromPage(const uint16_t PageAddress)
{
}
/** Toggles the select line of the currently selected dataflash IC, so that it is ready to receive
* a new command.
*/
static inline void Dataflash_ToggleSelectedChipCS(void)
{
}
/** Spin-loops while the currently selected dataflash is busy executing a command, such as a main
* memory page program or main memory to buffer transfer.
*/
static inline void Dataflash_WaitWhileBusy(void)
{
}
/** Sends a set of page and buffer address bytes to the currently selected dataflash IC, for use with
* dataflash commands which require a complete 24-bit address.
*
* \param[in] PageAddress Page address within the selected dataflash IC
* \param[in] BufferByte Address within the dataflash's buffer
*/
static inline void Dataflash_SendAddressBytes(uint16_t PageAddress, const uint16_t BufferByte)
{
}
#endif

@ -0,0 +1,104 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2017.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2017 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 disclaims 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
* \brief LUFA Custom Board Joystick Hardware Driver (Template)
*
* This is a stub driver header file, for implementing custom board
* layout hardware with compatible LUFA board specific drivers. If
* the library is configured to use the BOARD_USER board mode, this
* driver file should be completed and copied into the "/Board/" folder
* inside the application's folder.
*
* This stub is for the board-specific component of the LUFA Joystick
* driver, for a digital four-way (plus button) joystick.
*/
#ifndef __JOYSTICK_USER_H__
#define __JOYSTICK_USER_H__
/* Includes: */
// TODO: Add any required includes here
/* Enable C linkage for C++ Compilers: */
#if defined(__cplusplus)
extern "C" {
#endif
/* Preprocessor Checks: */
#if !defined(__INCLUDE_FROM_JOYSTICK_H)
#error Do not include this file directly. Include LUFA/Drivers/Board/Joystick.h instead.
#endif
#define BOARD_DUMMY_JOYSTICK_IMPLEMENTATION
/* Public Interface - May be used in end-application: */
/* Macros: */
/** Mask for the joystick being pushed in the left direction. */
#define JOY_LEFT 0
/** Mask for the joystick being pushed in the right direction. */
#define JOY_RIGHT 0
/** Mask for the joystick being pushed in the upward direction. */
#define JOY_UP 0
/** Mask for the joystick being pushed in the downward direction. */
#define JOY_DOWN 0
/** Mask for the joystick being pushed inward. */
#define JOY_PRESS 0
/* Inline Functions: */
#if !defined(__DOXYGEN__)
static inline void Joystick_Init(void)
{
}
static inline void Joystick_Disable(void)
{
}
static inline uint8_t Joystick_GetStatus(void) ATTR_WARN_UNUSED_RESULT;
static inline uint8_t Joystick_GetStatus(void)
{
return 0;
}
#endif
/* Disable C linkage for C++ Compilers: */
#if defined(__cplusplus)
}
#endif
#endif

@ -0,0 +1,132 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2017.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2017 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 disclaims 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
* \brief LUFA Custom Board LED Hardware Driver (Template)
*
* This is a stub driver header file, for implementing custom board
* layout hardware with compatible LUFA board specific drivers. If
* the library is configured to use the BOARD_USER board mode, this
* driver file should be completed and copied into the "/Board/" folder
* inside the application's folder.
*
* This stub is for the board-specific component of the LUFA LEDs driver,
* for the LEDs (up to four) mounted on most development boards.
*/
#ifndef __LEDS_USER_H__
#define __LEDS_USER_H__
/* Includes: */
// TODO: Add any required includes here
/* 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
#define BOARD_DUMMY_LEDS_IMPLEMENTATION
/* Public Interface - May be used in end-application: */
/* Macros: */
/** LED mask for the first LED on the board. */
#define LEDS_LED1 (1 << 0)
/** LED mask for the second LED on the board. */
#define LEDS_LED2 (1 << 1)
/** LED mask for the third LED on the board. */
#define LEDS_LED3 (1 << 2)
/** LED mask for the fourth LED on the board. */
#define LEDS_LED4 (1 << 3)
/** LED mask for all the LEDs on the board. */
#define LEDS_ALL_LEDS (LEDS_LED1 | LEDS_LED2 | LEDS_LED3 | LEDS_LED4)
/** LED mask for none of the board LEDs. */
#define LEDS_NO_LEDS 0
/* Inline Functions: */
#if !defined(__DOXYGEN__)
static inline void LEDs_Init(void)
{
}
static inline void LEDs_Disable(void)
{
}
static inline void LEDs_TurnOnLEDs(const uint8_t LEDMask)
{
}
static inline void LEDs_TurnOffLEDs(const uint8_t LEDMask)
{
}
static inline void LEDs_SetAllLEDs(const uint8_t LEDMask)
{
}
static inline void LEDs_ChangeLEDs(const uint8_t LEDMask, const uint8_t ActiveMask)
{
}
static inline void LEDs_ToggleLEDs(const uint8_t LEDMask)
{
}
static inline uint8_t LEDs_GetLEDs(void) ATTR_WARN_UNUSED_RESULT;
static inline uint8_t LEDs_GetLEDs(void)
{
return 0;
}
#endif
/* Disable C linkage for C++ Compilers: */
#if defined(__cplusplus)
}
#endif
#endif

@ -0,0 +1,89 @@
#
# LUFA Library
# Copyright (C) Dean Camera, 2017.
#
# dean [at] fourwalledcubicle [dot] com
# www.lufa-lib.org
#
#
# =============================================================================
# Board configuration map script, processed with the "BoardDriverTest"
# makefile. This script file maps the possible LUFA target BOARD makefile
# values in user projects to a specific architecture and device. This mapping is
# then used by the makefile to build all possible drivers for that board, to
# detect any missing or erroneous functions. To add a new board mapping, use
# the syntax:
#
# BOARD DEFINE = {ARCH} : {MCU} :
#
# And re-run the makefile. Note that each board may have only one target.
# =============================================================================
#
#
# ----------------- AVR8 Boards ------------------
BOARD_ADAFRUITU4 = AVR8 : atmega32u4 :
BOARD_ATAVRUSBRF01 = AVR8 : at90usb1287 :
BOARD_BENITO = AVR8 : at90usb162 :
BOARD_BIGMULTIO = AVR8 : atmega32u4 :
BOARD_BLACKCAT = AVR8 : at90usb162 :
BOARD_BUI = AVR8 : at90usb646 :
BOARD_BUMBLEB = AVR8 : at90usb162 :
BOARD_CULV3 = AVR8 : atmega32u4 :
BOARD_DUCE = AVR8 : atmega32u2 :
BOARD_EVK527 = AVR8 : atmega32u4 :
BOARD_JMDBU2 = AVR8 : atmega32u2 :
BOARD_LEONARDO = AVR8 : atmega32u4 :
BOARD_MAXIMUS = AVR8 : at90usb162 :
BOARD_MICROPENDOUS_32U2 = AVR8 : atmega32u2 :
BOARD_MICROPENDOUS_A = AVR8 : at90usb1287 :
BOARD_MICROPENDOUS_1 = AVR8 : at90usb162 :
BOARD_MICROPENDOUS_2 = AVR8 : atmega32u4 :
BOARD_MICROPENDOUS_3 = AVR8 : at90usb1287 :
BOARD_MICROPENDOUS_4 = AVR8 : at90usb1287 :
BOARD_MICROPENDOUS_DIP = AVR8 : at90usb1287 :
BOARD_MICROPENDOUS_REV1 = AVR8 : at90usb1287 :
BOARD_MICROPENDOUS_REV2 = AVR8 : at90usb1287 :
BOARD_MICROSIN162 = AVR8 : atmega162 :
BOARD_MINIMUS = AVR8 : atmega32u2 :
BOARD_MULTIO = AVR8 : at90usb162 :
BOARD_NONE = AVR8 : at90usb1287 :
BOARD_OLIMEX162 = AVR8 : at90usb162 :
BOARD_OLIMEX32U4 = AVR8 : atmega32u4 :
BOARD_OLIMEXT32U4 = AVR8 : atmega32u4 :
BOARD_OLIMEXISPMK2 = AVR8 : at90usb162 :
BOARD_RZUSBSTICK = AVR8 : at90usb1287 :
BOARD_SPARKFUN8U2 = AVR8 : atmega8u2 :
BOARD_STK525 = AVR8 : at90usb647 :
BOARD_STK526 = AVR8 : at90usb162 :
BOARD_TEENSY = AVR8 : at90usb162 :
BOARD_TEENSY2 = AVR8 : at90usb646 :
BOARD_TUL = AVR8 : atmega32u4 :
BOARD_UDIP = AVR8 : atmega32u2 :
BOARD_UNO = AVR8 : atmega8u2 :
BOARD_USB2AX = AVR8 : atmega32u2 :
BOARD_USB2AX_V3 = AVR8 : atmega32u2 :
BOARD_USB2AX_V31 = AVR8 : atmega32u2 :
BOARD_USBFOO = AVR8 : atmega162 :
BOARD_USBKEY = AVR8 : at90usb1287 :
BOARD_USBTINYMKII = AVR8 : at90usb162 :
BOARD_USER = AVR8 : at90usb1287 :
BOARD_XPLAIN = AVR8 : at90usb1287 :
BOARD_XPLAIN_REV1 = AVR8 : at90usb1287 :
BOARD_STANGE_ISP = AVR8 : at90usb162 :
BOARD_U2S = AVR8 : atmega32u2 :
BOARD_YUN = AVR8 : atmega32u4 :
BOARD_MICRO = AVR8 : atmega32u4 :
BOARD_POLOLUMICRO = AVR8 : atmega32u4 :
BOARD_XPLAINED_MINI = AVR8 : atmega32u4 :
#
# ----------------- XMEGA Boards -----------------
BOARD_A3BU_XPLAINED = XMEGA : atxmega256a3bu :
BOARD_B1_XPLAINED = XMEGA : atxmega128b1 :
BOARD_C3_XPLAINED = XMEGA : atxmega384c3 :
#
# ------------------ UC3 Boards ------------------
BOARD_EVK1100 = UC3 : uc3a0512 :
BOARD_EVK1101 = UC3 : uc3b0256 :
BOARD_EVK1104 = UC3 : uc3a3256 :
BOARD_UC3A3_XPLAINED = UC3 : uc3a3256 :
#

@ -0,0 +1,115 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2017.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2017 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 disclaims 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.
*/
#include <LUFA/Common/Common.h>
#include <LUFA/Drivers/Board/Board.h>
#include <LUFA/Drivers/Board/Buttons.h>
#include <LUFA/Drivers/Board/Dataflash.h>
#include <LUFA/Drivers/Board/LEDs.h>
#include <LUFA/Drivers/Board/Joystick.h>
#if defined(BOARD_HAS_BUTTONS) == defined(BOARD_DUMMY_BUTTONS_IMPLEMENTATION)
#error Mismatch between BOARD_HAS_BUTTONS and implementation.
#endif
#if defined(BOARD_HAS_DATAFLASH) == defined(BOARD_DUMMY_DATAFLASH_IMPLEMENTATION)
#error Mismatch between BOARD_HAS_DATAFLASH and implementation.
#endif
#if defined(BOARD_HAS_LEDS) == defined(BOARD_DUMMY_LEDS_IMPLEMENTATION)
#error Mismatch between BOARD_HAS_LEDS and implementation.
#endif
#if defined(BOARD_HAS_JOYSTICK) == defined(BOARD_DUMMY_JOYSTICK_IMPLEMENTATION)
#error Mismatch between BOARD_HAS_JOYSTICK and implementation.
#endif
int main(void)
{
uint_reg_t Dummy;
/* =============================
* Buttons Compile Check
* ============================= */
// cppcheck-suppress redundantAssignment
Dummy = BUTTONS_BUTTON1;
Buttons_Init();
// cppcheck-suppress redundantAssignment
Dummy = Buttons_GetStatus();
Buttons_Disable();
/* =============================
* Dataflash Compile Check
* ============================= */
// cppcheck-suppress redundantAssignment
Dummy = DATAFLASH_TOTALCHIPS + DATAFLASH_NO_CHIP + DATAFLASH_CHIP1 + DATAFLASH_PAGE_SIZE + DATAFLASH_PAGES;
Dataflash_Init();
Dataflash_TransferByte(0);
Dataflash_SendByte(0);
// cppcheck-suppress redundantAssignment
Dummy = Dataflash_ReceiveByte();
// cppcheck-suppress redundantAssignment
Dummy = Dataflash_GetSelectedChip();
Dataflash_SelectChip(DATAFLASH_CHIP1);
Dataflash_DeselectChip();
Dataflash_SelectChipFromPage(0);
Dataflash_ToggleSelectedChipCS();
Dataflash_WaitWhileBusy();
Dataflash_SendAddressBytes(0, 0);
/* =============================
* LEDs Compile Check
* ============================= */
// cppcheck-suppress redundantAssignment
Dummy = LEDS_LED1 + LEDS_LED2 + LEDS_LED3 + LEDS_LED4;
LEDs_Init();
LEDs_TurnOnLEDs(LEDS_ALL_LEDS);
LEDs_TurnOffLEDs(LEDS_ALL_LEDS);
LEDs_SetAllLEDs(LEDS_ALL_LEDS);
LEDs_ChangeLEDs(LEDS_ALL_LEDS, LEDS_NO_LEDS);
LEDs_ToggleLEDs(LEDS_ALL_LEDS);
// cppcheck-suppress redundantAssignment
Dummy = LEDs_GetLEDs();
LEDs_Disable();
/* =============================
* Joystick Compile Check
* ============================= */
// cppcheck-suppress redundantAssignment
Dummy = JOY_LEFT + JOY_RIGHT + JOY_UP + JOY_DOWN + JOY_PRESS;
Joystick_Init();
// cppcheck-suppress redundantAssignment
Dummy = Joystick_GetStatus();
Joystick_Disable();
(void)Dummy;
}

@ -0,0 +1,69 @@
#
# LUFA Library
# Copyright (C) Dean Camera, 2017.
#
# dean [at] fourwalledcubicle [dot] com
# www.lufa-lib.org
#
# Makefile for the board driver build test. This
# test attempts to build a dummy project with all
# possible board targets using their respective
# compiler.
# Path to the LUFA library core
LUFA_PATH := ../../LUFA/
# Build test cannot be run with multiple parallel jobs
.NOTPARALLEL:
all: begin makeboardlist testboards clean end
begin:
@echo Executing build test "BoardDriverTest".
@echo
end:
@echo Build test "BoardDriverTest" complete.
@echo
makeboardlist:
@grep "BOARD_" $(patsubst %/,%,$(LUFA_PATH))/Common/BoardTypes.h | cut -d'#' -f2 | cut -d' ' -f2 | grep "BOARD_" > BoardList.txt
testboards:
@echo "buildtest:" > BuildMakefile
@while read line; \
do \
build_cfg=`grep "$$line " BoardDeviceMap.cfg | grep -v "#" | cut -d'=' -f2- | sed 's/ //g'`; \
\
build_board=$$line; \
build_arch=`echo $$build_cfg | cut -d':' -f1`; \
build_mcu=`echo $$build_cfg | cut -d':' -f2`; \
\
if ( test -z "$$build_cfg" ); then \
echo "No matching information set for board $$build_board"; \
else \
echo "Found board configuration for $$build_board - $$build_arch, $$build_mcu"; \
\
printf "\t@echo Building dummy project for $$build_board...\n" >> BuildMakefile; \
printf "\t$(MAKE) -f makefile.test clean elf MCU=%s ARCH=%s BOARD=%s\n\n" $$build_mcu $$build_arch $$build_board >> BuildMakefile; \
fi; \
done < BoardList.txt
$(MAKE) -f BuildMakefile buildtest
clean:
rm -f BuildMakefile
rm -f BoardList.txt
$(MAKE) -f makefile.test clean BOARD=NONE ARCH=AVR8 MCU=at90usb1287
$(MAKE) -f makefile.test clean BOARD=NONE ARCH=XMEGA MCU=atxmega128a1u
$(MAKE) -f makefile.test clean BOARD=NONE ARCH=UC3 MCU=uc3a0256
%:
.PHONY: all begin end makeboardlist testboards clean
# Include common DMBS build system modules
DMBS_PATH ?= $(LUFA_PATH)/Build/DMBS/DMBS
include $(DMBS_PATH)/core.mk

@ -0,0 +1,35 @@
#
# LUFA Library
# Copyright (C) Dean Camera, 2017.
#
# dean [at] fourwalledcubicle [dot] com
# www.lufa-lib.org
#
# --------------------------------------
# LUFA Project Makefile.
# --------------------------------------
# Run "make help" for target help.
MCU =
ARCH =
BOARD =
F_CPU = $(F_USB)
F_USB = 8000000
OPTIMIZATION = 1
TARGET = Test
SRC = $(TARGET).c
LUFA_PATH = ../../LUFA
CC_FLAGS = -Werror
DEBUG_LEVEL = 0
# Include LUFA-specific DMBS extension modules
DMBS_LUFA_PATH ?= $(LUFA_PATH)/Build/LUFA
include $(DMBS_LUFA_PATH)/lufa-sources.mk
include $(DMBS_LUFA_PATH)/lufa-gcc.mk
# Include common DMBS build system modules
DMBS_PATH ?= $(LUFA_PATH)/Build/DMBS/DMBS
include $(DMBS_PATH)/core.mk
include $(DMBS_PATH)/gcc.mk

@ -0,0 +1,167 @@
#
# LUFA Library
# Copyright (C) Dean Camera, 2017.
#
# dean [at] fourwalledcubicle [dot] com
# www.lufa-lib.org
#
#
# =============================================================================
# Bootloader configuration map script, processed with the "BootloaderTest"
# makefile. This script file defines the targets for each LUFA bootloader,
# which are then built as part of the build test to ensure that there are no
# failures on all standard configurations. To add a new build target for a
# bootloader to this script, use the format:
#
# BOOTLOADER = {ARCH} : {MCU} : {BOARD} : {FLASH SIZE KB} : {BOOT SIZE KB} : {F_USB MHZ}
#
# And re-run the makefile.
# =============================================================================
#
#
# ------------ CDC Bootloader --------------------
CDC = AVR8 : at90usb1287 : XPLAIN : 128 : 8 : 8 :
CDC = AVR8 : at90usb1287 : NONE : 128 : 8 : 8 :
CDC = AVR8 : at90usb1287 : NONE : 128 : 4 : 8 :
CDC = AVR8 : at90usb647 : NONE : 64 : 4 : 8 :
CDC = AVR8 : at90usb1286 : NONE : 128 : 8 : 8 :
CDC = AVR8 : at90usb1286 : NONE : 128 : 4 : 8 :
CDC = AVR8 : at90usb646 : NONE : 64 : 4 : 8 :
CDC = AVR8 : atmega32u4 : NONE : 32 : 4 : 8 :
CDC = AVR8 : atmega16u4 : NONE : 16 : 4 : 8 :
CDC = AVR8 : atmega32u2 : NONE : 32 : 4 : 8 :
CDC = AVR8 : atmega16u2 : NONE : 16 : 4 : 8 :
CDC = AVR8 : atmega8u2 : NONE : 8 : 4 : 8 :
CDC = AVR8 : at90usb162 : NONE : 16 : 4 : 8 :
CDC = AVR8 : at90usb82 : NONE : 8 : 4 : 8 :
CDC = AVR8 : at90usb1287 : NONE : 128 : 8 : 16 :
CDC = AVR8 : at90usb1287 : NONE : 128 : 4 : 16 :
CDC = AVR8 : at90usb647 : NONE : 64 : 4 : 16 :
CDC = AVR8 : at90usb1286 : NONE : 128 : 8 : 16 :
CDC = AVR8 : at90usb1286 : NONE : 128 : 4 : 16 :
CDC = AVR8 : at90usb646 : NONE : 64 : 4 : 16 :
CDC = AVR8 : atmega32u4 : NONE : 32 : 4 : 16 :
CDC = AVR8 : atmega16u4 : NONE : 16 : 4 : 16 :
CDC = AVR8 : atmega32u2 : NONE : 32 : 4 : 16 :
CDC = AVR8 : atmega16u2 : NONE : 16 : 4 : 16 :
CDC = AVR8 : atmega8u2 : NONE : 8 : 4 : 16 :
CDC = AVR8 : at90usb162 : NONE : 16 : 4 : 16 :
CDC = AVR8 : at90usb82 : NONE : 8 : 4 : 16 :
#
# ------------ DFU Bootloader --------------------
DFU = AVR8 : at90usb1287 : XPLAIN : 128 : 8 : 8 :
DFU = AVR8 : at90usb1287 : NONE : 128 : 8 : 8 :
DFU = AVR8 : at90usb1287 : NONE : 128 : 4 : 8 :
DFU = AVR8 : at90usb647 : NONE : 64 : 4 : 8 :
DFU = AVR8 : at90usb1286 : NONE : 128 : 8 : 8 :
DFU = AVR8 : at90usb1286 : NONE : 128 : 4 : 8 :
DFU = AVR8 : at90usb646 : NONE : 64 : 4 : 8 :
DFU = AVR8 : atmega32u4 : NONE : 32 : 4 : 8 :
DFU = AVR8 : atmega16u4 : NONE : 16 : 4 : 8 :
DFU = AVR8 : atmega32u2 : NONE : 32 : 4 : 8 :
DFU = AVR8 : atmega16u2 : NONE : 16 : 4 : 8 :
DFU = AVR8 : atmega8u2 : NONE : 8 : 4 : 8 :
DFU = AVR8 : at90usb162 : NONE : 16 : 4 : 8 :
DFU = AVR8 : at90usb82 : NONE : 8 : 4 : 8 :
DFU = AVR8 : at90usb1287 : NONE : 128 : 8 : 16 :
DFU = AVR8 : at90usb1287 : NONE : 128 : 4 : 16 :
DFU = AVR8 : at90usb647 : NONE : 64 : 4 : 16 :
DFU = AVR8 : at90usb1286 : NONE : 128 : 8 : 16 :
DFU = AVR8 : at90usb1286 : NONE : 128 : 4 : 16 :
DFU = AVR8 : at90usb646 : NONE : 64 : 4 : 16 :
DFU = AVR8 : atmega32u4 : NONE : 32 : 4 : 16 :
DFU = AVR8 : atmega16u4 : NONE : 16 : 4 : 16 :
DFU = AVR8 : atmega32u2 : NONE : 32 : 4 : 16 :
DFU = AVR8 : atmega16u2 : NONE : 16 : 4 : 16 :
DFU = AVR8 : atmega8u2 : NONE : 8 : 4 : 16 :
DFU = AVR8 : at90usb162 : NONE : 16 : 4 : 16 :
DFU = AVR8 : at90usb82 : NONE : 8 : 4 : 16 :
#
# ------------ HID Bootloader --------------------
HID = AVR8 : at90usb1287 : NONE : 128 : 8 : 8 :
HID = AVR8 : at90usb1287 : NONE : 128 : 4 : 8 :
HID = AVR8 : at90usb647 : NONE : 64 : 4 : 8 :
HID = AVR8 : at90usb1286 : NONE : 128 : 8 : 8 :
HID = AVR8 : at90usb1286 : NONE : 128 : 4 : 8 :
HID = AVR8 : at90usb646 : NONE : 64 : 4 : 8 :
HID = AVR8 : atmega32u4 : NONE : 32 : 4 : 8 :
HID = AVR8 : atmega16u4 : NONE : 16 : 4 : 8 :
HID = AVR8 : atmega32u2 : NONE : 32 : 2 : 8 :
HID = AVR8 : atmega32u2 : NONE : 32 : 4 : 8 :
HID = AVR8 : atmega16u2 : NONE : 16 : 2 : 8 :
HID = AVR8 : atmega16u2 : NONE : 16 : 4 : 8 :
HID = AVR8 : atmega8u2 : NONE : 8 : 2 : 8 :
HID = AVR8 : atmega8u2 : NONE : 8 : 4 : 8 :
HID = AVR8 : at90usb162 : NONE : 16 : 2 : 8 :
HID = AVR8 : at90usb162 : NONE : 16 : 4 : 8 :
HID = AVR8 : at90usb162 : NONE : 16 : 2 : 8 :
HID = AVR8 : at90usb162 : NONE : 16 : 4 : 8 :
HID = AVR8 : at90usb1287 : NONE : 128 : 8 : 8 :
HID = AVR8 : at90usb1287 : NONE : 128 : 4 : 8 :
HID = AVR8 : at90usb647 : NONE : 64 : 4 : 8 :
HID = AVR8 : at90usb1286 : NONE : 128 : 8 : 16 :
HID = AVR8 : at90usb1286 : NONE : 128 : 4 : 16 :
HID = AVR8 : at90usb646 : NONE : 64 : 4 : 16 :
HID = AVR8 : atmega32u4 : NONE : 32 : 4 : 16 :
HID = AVR8 : atmega16u4 : NONE : 16 : 4 : 16 :
HID = AVR8 : atmega32u2 : NONE : 32 : 2 : 16 :
HID = AVR8 : atmega32u2 : NONE : 32 : 4 : 16 :
HID = AVR8 : atmega16u2 : NONE : 16 : 2 : 16 :
HID = AVR8 : atmega16u2 : NONE : 16 : 4 : 16 :
HID = AVR8 : atmega8u2 : NONE : 8 : 2 : 16 :
HID = AVR8 : atmega8u2 : NONE : 8 : 4 : 16 :
HID = AVR8 : at90usb162 : NONE : 16 : 2 : 16 :
HID = AVR8 : at90usb162 : NONE : 16 : 4 : 16 :
HID = AVR8 : at90usb162 : NONE : 16 : 2 : 16 :
HID = AVR8 : at90usb162 : NONE : 16 : 4 : 16 :
#
# ---------- Printer Bootloader ------------------
Printer = AVR8 : at90usb1287 : NONE : 128 : 8 : 8 :
Printer = AVR8 : at90usb1287 : NONE : 128 : 4 : 8 :
Printer = AVR8 : at90usb647 : NONE : 64 : 4 : 8 :
Printer = AVR8 : at90usb1286 : NONE : 128 : 8 : 8 :
Printer = AVR8 : at90usb1286 : NONE : 128 : 4 : 8 :
Printer = AVR8 : at90usb646 : NONE : 64 : 4 : 8 :
Printer = AVR8 : atmega32u4 : NONE : 32 : 4 : 8 :
Printer = AVR8 : atmega16u4 : NONE : 16 : 4 : 8 :
Printer = AVR8 : atmega32u2 : NONE : 32 : 4 : 8 :
Printer = AVR8 : atmega16u2 : NONE : 16 : 4 : 8 :
Printer = AVR8 : atmega8u2 : NONE : 8 : 4 : 8 :
Printer = AVR8 : at90usb162 : NONE : 16 : 4 : 8 :
Printer = AVR8 : at90usb82 : NONE : 8 : 4 : 8 :
Printer = AVR8 : at90usb1287 : NONE : 128 : 8 : 16 :
Printer = AVR8 : at90usb1287 : NONE : 128 : 4 : 16 :
Printer = AVR8 : at90usb647 : NONE : 64 : 4 : 16 :
Printer = AVR8 : at90usb1286 : NONE : 128 : 8 : 16 :
Printer = AVR8 : at90usb1286 : NONE : 128 : 4 : 16 :
Printer = AVR8 : at90usb646 : NONE : 64 : 4 : 16 :
Printer = AVR8 : atmega32u4 : NONE : 32 : 4 : 16 :
Printer = AVR8 : atmega16u4 : NONE : 16 : 4 : 16 :
Printer = AVR8 : atmega32u2 : NONE : 32 : 4 : 16 :
Printer = AVR8 : atmega16u2 : NONE : 16 : 4 : 16 :
Printer = AVR8 : atmega8u2 : NONE : 8 : 4 : 16 :
Printer = AVR8 : at90usb162 : NONE : 16 : 4 : 16 :
Printer = AVR8 : at90usb82 : NONE : 8 : 4 : 16 :
#
# ---------- Mass Storage Bootloader -----------------
MassStorage = AVR8 : at90usb1287 : XPLAIN : 128 : 8 : 8 :
MassStorage = AVR8 : at90usb1287 : NONE : 128 : 8 : 8 :
MassStorage = AVR8 : at90usb1287 : NONE : 128 : 4 : 8 :
MassStorage = AVR8 : at90usb647 : NONE : 64 : 4 : 8 :
MassStorage = AVR8 : at90usb1286 : NONE : 128 : 8 : 8 :
MassStorage = AVR8 : at90usb1286 : NONE : 128 : 4 : 8 :
MassStorage = AVR8 : at90usb646 : NONE : 64 : 4 : 8 :
MassStorage = AVR8 : atmega32u4 : LEONARDO : 32 : 4 : 16 :
MassStorage = AVR8 : atmega32u4 : NONE : 32 : 4 : 8 :
MassStorage = AVR8 : atmega16u4 : NONE : 16 : 4 : 8 :
MassStorage = AVR8 : atmega32u2 : NONE : 32 : 4 : 8 :
MassStorage = AVR8 : at90usb1287 : NONE : 128 : 8 : 16 :
MassStorage = AVR8 : at90usb1287 : NONE : 128 : 4 : 16 :
MassStorage = AVR8 : at90usb647 : NONE : 64 : 4 : 16 :
MassStorage = AVR8 : at90usb1286 : NONE : 128 : 8 : 16 :
MassStorage = AVR8 : at90usb1286 : NONE : 128 : 4 : 16 :
MassStorage = AVR8 : at90usb646 : NONE : 64 : 4 : 16 :
MassStorage = AVR8 : atmega32u4 : NONE : 32 : 4 : 16 :
MassStorage = AVR8 : atmega16u4 : NONE : 16 : 4 : 16 :
MassStorage = AVR8 : atmega32u2 : NONE : 32 : 4 : 16 :
#

@ -0,0 +1,65 @@
#
# LUFA Library
# Copyright (C) Dean Camera, 2017.
#
# dean [at] fourwalledcubicle [dot] com
# www.lufa-lib.org
#
# Makefile for the bootloader build test. This
# test attempts to build all the bootloaders
# with all supported device configurations.
# Path to the LUFA library core
LUFA_PATH := ../../LUFA/
# Build test cannot be run with multiple parallel jobs
.NOTPARALLEL:
all: begin testbootloaders clean end
begin:
@echo Executing build test "BootloaderTest".
@echo
end:
@echo Build test "BootloaderTest" complete.
@echo
testbootloaders:
@echo "buildtest:" > BuildMakefile
@while read line; \
do \
build_cfg=`echo $$line | grep -v "#" | sed 's/ //g'`; \
\
if ( test -n "$$build_cfg" ); then \
build_bootloader=`echo $$build_cfg | cut -d'=' -f1`; \
build_cfg=`echo $$build_cfg | cut -d'=' -f2-`; \
\
build_arch=`echo $$build_cfg | cut -d':' -f1`; \
build_mcu=`echo $$build_cfg | cut -d':' -f2`; \
build_board=`echo $$build_cfg | cut -d':' -f3`; \
build_flashsize=`echo $$build_cfg | cut -d':' -f4`; \
build_bootsize=`echo $$build_cfg | cut -d':' -f5`; \
build_fusb=`echo $$build_cfg | cut -d':' -f6`; \
\
printf "Found '%s' bootloader configuration (FLASH: %3s KB | BOOT: %3s KB | MCU: %12s / %4s | BOARD: %s | F_USB: %sMHz)\n" $$build_bootloader $$build_flashsize $$build_bootsize $$build_mcu $$build_arch $$build_board $$build_fusb; \
\
printf "\t@echo Building bootloader %s - %s - FLASH: %s KB, BOOT: %s KB, BOARD: %s, F_USB: %sMHz\n" $$build_bootloader $$build_mcu $$build_flashsize $$build_bootsize $$build_board $$build_fusb >> BuildMakefile; \
printf "\t$(MAKE) -C $(patsubst %/,%,$(LUFA_PATH))/../Bootloaders/%s/ clean elf ARCH=%s MCU=%s BOARD=%s FLASH_SIZE_KB=%s BOOT_SECTION_SIZE_KB=%s F_USB=%s000000 DEBUG_LEVEL=0\n\n" $$build_bootloader $$build_arch $$build_mcu $$build_board $$build_flashsize $$build_bootsize $$build_fusb >> BuildMakefile; \
fi; \
done < BootloaderDeviceMap.cfg
$(MAKE) -f BuildMakefile buildtest
clean:
rm -f BuildMakefile
%:
.PHONY: all begin end testbootloaders clean
# Include common DMBS build system modules
DMBS_PATH ?= $(LUFA_PATH)/Build/DMBS/DMBS
include $(DMBS_PATH)/core.mk

@ -0,0 +1,41 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2017.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2017 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 disclaims 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.
*/
.section .text
# Mandatory entry point for successful compilation and link
.global main
main:
# Mandatory callback needed for base compile of the USB driver
.global CALLBACK_USB_GetDescriptor
CALLBACK_USB_GetDescriptor:

@ -0,0 +1,56 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2017.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2017 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 disclaims 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.
*/
#include <LUFA/Common/Common.h>
#include <LUFA/Platform/Platform.h>
#include <LUFA/Drivers/USB/USB.h>
#include <LUFA/Drivers/Misc/RingBuffer.h>
#include <LUFA/Drivers/Misc/TerminalCodes.h>
#if (ARCH == ARCH_AVR8)
#if defined(ADC)
#include <LUFA/Drivers/Peripheral/ADC.h>
#endif
#include <LUFA/Drivers/Peripheral/Serial.h>
#include <LUFA/Drivers/Peripheral/SerialSPI.h>
#include <LUFA/Drivers/Peripheral/SPI.h>
#if defined(TWCR)
#include <LUFA/Drivers/Peripheral/TWI.h>
#endif
#elif (ARCH == ARCH_XMEGA)
#include <LUFA/Drivers/Peripheral/Serial.h>
#include <LUFA/Drivers/Peripheral/SerialSPI.h>
#include <LUFA/Drivers/Peripheral/SPI.h>
#include <LUFA/Drivers/Peripheral/TWI.h>
#endif

@ -0,0 +1,31 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2017.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2017 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 disclaims 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.
*/
#include "Modules.h"

@ -0,0 +1,31 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2017.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2017 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 disclaims 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.
*/
#include "Modules.h"

@ -0,0 +1,67 @@
#
# LUFA Library
# Copyright (C) Dean Camera, 2017.
#
# dean [at] fourwalledcubicle [dot] com
# www.lufa-lib.org
#
# Makefile for the module build test. This test
# attempts to build as many modules as possible
# under all supported architectures, and include
# all module headers in a simple C and C++
# application.
# Path to the LUFA library core
LUFA_PATH := ../../LUFA/
# Build test cannot be run with multiple parallel jobs
.NOTPARALLEL:
# List of device families per architecture, one device per architecture sub-family
AVR8_FAMILIES := at90usb1287 at90usb1286 atmega16u4 atmega16u2 at90usb162
XMEGA_FAMILIES := atxmega128a1u atxmega128a3u atxmega256a3bu atxmega128a4u atxmega128b1 atxmega128b3 atxmega128c3 atxmega32c4
UC3_FAMILIES := uc3a0256 uc3a1256 uc3a3256 uc3a4256 uc3b0256 uc3b1256
# List of all device families, with a family postfix
DEVICE_FAMILIES := $(AVR8_FAMILIES:%=%.avr8) $(XMEGA_FAMILIES:%=%.xmega) $(UC3_FAMILIES:%=%.uc3)
all: begin $(DEVICE_FAMILIES) clean end
arch_avr8: begin $(AVR8_FAMILIES:%=%.avr8) end
arch_xmega: begin $(XMEGA_FAMILIES:%=%.xmega) end
arch_uc3: begin $(UC3_FAMILIES:%=%.uc3) end
begin:
@echo Executing build test "ModuleTest".
@echo
end:
@echo Build test "ModuleTest" complete.
@echo
%.avr8:
@echo Building ModuleTest for ARCH=AVR8 MCU=$(@:%.avr8=%)...
$(MAKE) -f makefile.test clean elf ARCH=AVR8 MCU=$(@:%.avr8=%)
%.xmega:
@echo Building ModuleTest for ARCH=XMEGA MCU=$(@:%.xmega=%)...
$(MAKE) -f makefile.test clean elf ARCH=XMEGA MCU=$(@:%.xmega=%)
%.uc3:
@echo Building ModuleTest for ARCH=UC3 MCU=$(@:%.uc3=%)...
$(MAKE) -f makefile.test clean elf ARCH=UC3 MCU=$(@:%.uc3=%)
clean:
$(MAKE) -f makefile.test clean ARCH=AVR8 MCU=$(firstword $(AVR8_FAMILIES))
$(MAKE) -f makefile.test clean ARCH=XMEGA MCU=$(firstword $(XMEGA_FAMILIES))
$(MAKE) -f makefile.test clean ARCH=UC3 MCU=$(firstword $(UC3_FAMILIES))
%:
.PHONY: all arch_avr8 arch_xmega arch_uc3 begin end
# Include common DMBS build system modules
DMBS_PATH ?= $(LUFA_PATH)/Build/DMBS/DMBS
include $(DMBS_PATH)/core.mk

@ -0,0 +1,94 @@
#
# LUFA Library
# Copyright (C) Dean Camera, 2017.
#
# dean [at] fourwalledcubicle [dot] com
# www.lufa-lib.org
#
# --------------------------------------
# LUFA Project Makefile.
# --------------------------------------
# Run "make help" for target help.
MCU =
ARCH =
BOARD = NONE
F_CPU = $(F_USB)
OPTIMIZATION = 1
TARGET = Test
SRC = $(TARGET)_C.c $(TARGET)_CPP.cpp Dummy.S $(LUFA_SRC_USB)
LUFA_PATH = ../../LUFA
DEBUG_LEVEL = 0
ifeq ($(ARCH), AVR8)
F_USB = 8000000
else ifeq ($(ARCH), XMEGA)
F_USB = 48000000
else ifeq ($(ARCH), UC3)
F_USB = 48000000
endif
# Generic C/C++ compiler flags
CC_FLAGS = -Wextra
CC_FLAGS += -Werror
CC_FLAGS += -Wformat=2
CC_FLAGS += -Winit-self
CC_FLAGS += -Wswitch-enum
CC_FLAGS += -Wunused
CC_FLAGS += -Wundef
CC_FLAGS += -Wpointer-arith
CC_FLAGS += -Wcast-align
CC_FLAGS += -Wwrite-strings
CC_FLAGS += -Wlogical-op
CC_FLAGS += -Wmissing-declarations
CC_FLAGS += -Wmissing-field-initializers
CC_FLAGS += -Wmissing-format-attribute
CC_FLAGS += -Woverlength-strings
CC_FLAGS += -Wswitch-default
CC_FLAGS += -Wfloat-equal
CC_FLAGS += -Waggregate-return
CC_FLAGS += -Wmissing-include-dirs
# Disable warnings not supported by the version of GCC used for UC3 targets (FIXME)
ifneq ($(ARCH), UC3)
CC_FLAGS += -Wdouble-promotion
endif
# Only enable redundant declaration warnings for AVR8 target (FIXME)
ifeq ($(ARCH), AVR8)
CC_FLAGS += -Wredundant-decls
endif
# C compiler only flags
C_FLAGS += -Wmissing-parameter-type
C_FLAGS += -Wmissing-prototypes
C_FLAGS += -Wnested-externs
C_FLAGS += -Wbad-function-cast
C_FLAGS += -Wstrict-prototypes
C_FLAGS += -Wold-style-definition
# Disable warnings not supported by the version of GCC used for UC3 targets (FIXME)
ifneq ($(ARCH), UC3)
C_FLAGS += -Wunsuffixed-float-constants
C_FLAGS += -Wjump-misses-init
endif
# Only check C++ compatibility on the build files, to ensure headers are C++ compatible
Test_C.c Test_CPP.cpp: CC_FLAGS += -Wc++-compat
# Potential additional warnings to enable in the future (FIXME)
#CC_FLAGS += -Wcast-qual
#CC_FLAGS += -Wconversion
#CC_FLAGS += -Wsign-conversion
#CC_FLAGS += -pedantic
# Include LUFA-specific DMBS extension modules
DMBS_LUFA_PATH ?= $(LUFA_PATH)/Build/LUFA
include $(DMBS_LUFA_PATH)/lufa-sources.mk
include $(DMBS_LUFA_PATH)/lufa-gcc.mk
# Include common DMBS build system modules
DMBS_PATH ?= $(LUFA_PATH)/Build/DMBS/DMBS
include $(DMBS_PATH)/core.mk
include $(DMBS_PATH)/gcc.mk

@ -0,0 +1,42 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2017.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2017 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 disclaims 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.
*/
.section .text
# Mandatory entry point for successful compilation and link
.global main
main:
# Force code generation of the base USB stack
call USB_Init
# Mandatory callback needed for base compile of the USB driver
.global CALLBACK_USB_GetDescriptor
CALLBACK_USB_GetDescriptor:

@ -0,0 +1,32 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2017.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2017 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 disclaims 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.
*/
#include <LUFA/Common/Common.h>
#include <LUFA/Drivers/USB/USB.h>

@ -0,0 +1,57 @@
#
# LUFA Library
# Copyright (C) Dean Camera, 2017.
#
# dean [at] fourwalledcubicle [dot] com
# www.lufa-lib.org
#
# Makefile for the single USB mode build test.
# This test attempts to build the USB module
# under fixed device and fixed host modes under
# all supported architectures
# Path to the LUFA library core
LUFA_PATH := ../../LUFA/
# Build test cannot be run with multiple parallel jobs
.NOTPARALLEL:
all: begin compile clean end
begin:
@echo Executing build test "SingleUSBModeTest".
@echo
end:
@echo Build test "SingleUSBModeTest" complete.
@echo
compile:
@echo Building SingleUSBModeTest for ARCH=AVR8 in device only mode...
$(MAKE) -f makefile.test clean elf ARCH=AVR8 MCU=at90usb1287 CC_FLAGS='-D USB_DEVICE_ONLY'
@echo Building SingleUSBModeTest for ARCH=AVR8 in host only mode...
$(MAKE) -f makefile.test clean elf ARCH=AVR8 MCU=at90usb1287 CC_FLAGS='-D USB_HOST_ONLY'
@echo Building SingleUSBModeTest for ARCH=XMEGA in device only mode...
$(MAKE) -f makefile.test clean elf ARCH=XMEGA MCU=atxmega128a1u CC_FLAGS='-D USB_DEVICE_ONLY'
@echo Building SingleUSBModeTest for ARCH=UC3 in device only mode...
$(MAKE) -f makefile.test clean elf ARCH=UC3 MCU=uc3a0256 CC_FLAGS='-D USB_DEVICE_ONLY'
@echo Building SingleUSBModeTest for ARCH=UC3 in host only mode...
$(MAKE) -f makefile.test clean elf ARCH=UC3 MCU=uc3a0256 CC_FLAGS='-D USB_HOST_ONLY'
clean:
$(MAKE) -f makefile.test clean ARCH=AVR8 MCU=at90usb1287
$(MAKE) -f makefile.test clean ARCH=XMEGA MCU=atxmega128a1u
$(MAKE) -f makefile.test clean ARCH=UC3 MCU=uc3a0256
%:
.PHONY: begin end compile clean
# Include common DMBS build system modules
DMBS_PATH ?= $(LUFA_PATH)/Build/DMBS/DMBS
include $(DMBS_PATH)/core.mk

@ -0,0 +1,75 @@
#
# LUFA Library
# Copyright (C) Dean Camera, 2017.
#
# dean [at] fourwalledcubicle [dot] com
# www.lufa-lib.org
#
# --------------------------------------
# LUFA Project Makefile.
# --------------------------------------
# Run "make help" for target help.
MCU =
ARCH =
BOARD = NONE
F_CPU = $(F_USB)
DEBUG_LEVEL = 0
ifeq ($(ARCH), AVR8)
F_USB = 8000000
else ifeq ($(ARCH), XMEGA)
F_USB = 48000000
else ifeq ($(ARCH), UC3)
F_USB = 48000000
endif
OPTIMIZATION = 1
TARGET = Test
SRC = Test.c Dummy.S $(LUFA_SRC_USB)
LUFA_PATH = ../../LUFA
# Generic C/C++ compiler flags
CC_FLAGS = -Wextra
CC_FLAGS += -Werror
CC_FLAGS += -Wformat=2
CC_FLAGS += -Winit-self
CC_FLAGS += -Wswitch-enum
CC_FLAGS += -Wunused
CC_FLAGS += -Wundef
CC_FLAGS += -Wpointer-arith
CC_FLAGS += -Wcast-align
CC_FLAGS += -Wwrite-strings
CC_FLAGS += -Wlogical-op
CC_FLAGS += -Wmissing-declarations
CC_FLAGS += -Wmissing-field-initializers
CC_FLAGS += -Wmissing-format-attribute
CC_FLAGS += -Woverlength-strings
# Only enable rendundant declaration warnings for AVR8 target (FIXME)
ifeq ($(ARCH), AVR8)
CC_FLAGS += -Wredundant-decls
endif
# C compiler only flags
C_FLAGS += -Wmissing-parameter-type
C_FLAGS += -Wnested-externs
# Potential additional warnings to enable in the future (FIXME)
#CC_FLAGS += -Wswitch-default
#CC_FLAGS += -Wc++-compat
#CC_FLAGS += -Wcast-qual
#CC_FLAGS += -Wconversion
#CC_FLAGS += -Wjump-misses-init
#CC_FLAGS += -pedantic
# Include LUFA-specific DMBS extension modules
DMBS_LUFA_PATH ?= $(LUFA_PATH)/Build/LUFA
include $(DMBS_LUFA_PATH)/lufa-sources.mk
include $(DMBS_LUFA_PATH)/lufa-gcc.mk
# Include common DMBS build system modules
DMBS_PATH ?= $(LUFA_PATH)/Build/DMBS/DMBS
include $(DMBS_PATH)/core.mk
include $(DMBS_PATH)/gcc.mk

@ -0,0 +1,47 @@
#
# LUFA Library
# Copyright (C) Dean Camera, 2017.
#
# dean [at] fourwalledcubicle [dot] com
# www.lufa-lib.org
#
# Static anlysis of the entire LUFA source tree, using the free cross-platform "cppcheck" tool.
# Path to the LUFA library core
LUFA_PATH := ../../LUFA/
CPPCHECK_EXCLUDES := FATFs/ \
PetiteFATFs/ \
uip/
CPPCHECK_INCLUDES := $(patsubst %/,%,$(LUFA_PATH))/CodeTemplates/ \
$(patsubst %/,%,$(LUFA_PATH))/../Projects/AVRISP-MKII/
CPPCHECK_FLAGS := -U TEMPLATE_FUNC_NAME -U __GNUC__ -U __DOXYGEN__
CPPCHECK_SUPPRESS := variableScope missingInclude unusedFunction
SRC := $(patsubst %/,%,$(LUFA_PATH))/..
# Build test cannot be run with multiple parallel jobs
.NOTPARALLEL:
all: begin cppcheck end
begin:
@echo Executing build test "StaticAnalysisTest".
@echo
end:
@echo Build test "StaticAnalysisTest" complete.
@echo
%:
.PHONY: all begin end
# Include common DMBS build system modules
DMBS_PATH ?= $(LUFA_PATH)/Build/DMBS/DMBS
include $(DMBS_PATH)/core.mk
include $(DMBS_PATH)/cppcheck.mk

@ -0,0 +1,24 @@
#
# LUFA Library
# Copyright (C) Dean Camera, 2017.
#
# dean [at] fourwalledcubicle [dot] com
# www.lufa-lib.org
#
# Makefile to build all the LUFA Build Tests. Build Tests are
# used to verify the correctness of the LUFA library, and are
# not intended to be modified or compiled by non-developers.
all:
%:
@echo Executing \"make $@\" on all LUFA build tests.
@echo
$(MAKE) -C BoardDriverTest $@
$(MAKE) -C BootloaderTest $@
$(MAKE) -C ModuleTest $@
$(MAKE) -C SingleUSBModeTest $@
$(MAKE) -C StaticAnalysisTest $@
@echo
@echo LUFA build test \"make $@\" operation complete.

@ -0,0 +1,274 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2017.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2017 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 disclaims 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 AudioInput demo. This file contains the main tasks of
* the demo and is responsible for the initial application hardware configuration.
*/
#include "AudioInput.h"
/** LUFA Audio Class driver interface configuration and state information. This structure is
* passed to all Audio Class driver functions, so that multiple instances of the same class
* within a device can be differentiated from one another.
*/
USB_ClassInfo_Audio_Device_t Microphone_Audio_Interface =
{
.Config =
{
.ControlInterfaceNumber = INTERFACE_ID_AudioControl,
.StreamingInterfaceNumber = INTERFACE_ID_AudioStream,
.DataINEndpoint =
{
.Address = AUDIO_STREAM_EPADDR,
.Size = AUDIO_STREAM_EPSIZE,
.Banks = 2,
},
},
};
/** Current audio sampling frequency of the streaming audio endpoint. */
static uint32_t CurrentAudioSampleFrequency = 48000;
/** 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();
LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);
GlobalInterruptEnable();
for (;;)
{
Audio_Device_USBTask(&Microphone_Audio_Interface);
USB_USBTask();
}
}
/** Configures the board hardware and chip peripherals for the demo's functionality. */
void SetupHardware(void)
{
#if (ARCH == ARCH_AVR8)
/* Disable watchdog if enabled by bootloader/fuses */
MCUSR &= ~(1 << WDRF);
wdt_disable();
/* Disable clock division */
clock_prescale_set(clock_div_1);
#endif
/* Hardware Initialization */
LEDs_Init();
Buttons_Init();
ADC_Init(ADC_FREE_RUNNING | ADC_PRESCALE_32);
ADC_SetupChannel(MIC_IN_ADC_CHANNEL);
USB_Init();
/* Start the ADC conversion in free running mode */
ADC_StartReading(ADC_REFERENCE_AVCC | ADC_RIGHT_ADJUSTED | ADC_GET_CHANNEL_MASK(MIC_IN_ADC_CHANNEL));
}
/** ISR to handle the reloading of the data endpoint with the next sample. */
ISR(TIMER0_COMPA_vect, ISR_BLOCK)
{
uint8_t PrevEndpoint = Endpoint_GetCurrentEndpoint();
/* Check that the USB bus is ready for the next sample to write */
if (Audio_Device_IsReadyForNextSample(&Microphone_Audio_Interface))
{
int16_t AudioSample;
#if defined(USE_TEST_TONE)
static uint8_t SquareWaveSampleCount;
static int16_t CurrentWaveValue;
/* In test tone mode, generate a square wave at 1/256 of the sample rate */
if (SquareWaveSampleCount++ == 0xFF)
CurrentWaveValue ^= 0x8000;
/* Only generate audio if the board button is being pressed */
AudioSample = (Buttons_GetStatus() & BUTTONS_BUTTON1) ? CurrentWaveValue : 0;
#else
/* Audio sample is ADC value scaled to fit the entire range */
AudioSample = ((SAMPLE_MAX_RANGE / ADC_MAX_RANGE) * ADC_GetResult());
#if defined(MICROPHONE_BIASED_TO_HALF_RAIL)
/* Microphone is biased to half rail voltage, subtract the bias from the sample value */
AudioSample -= (SAMPLE_MAX_RANGE / 2);
#endif
#endif
Audio_Device_WriteSample16(&Microphone_Audio_Interface, AudioSample);
}
Endpoint_SelectEndpoint(PrevEndpoint);
}
/** Event handler for the library USB Connection event. */
void EVENT_USB_Device_Connect(void)
{
LEDs_SetAllLEDs(LEDMASK_USB_ENUMERATING);
/* Sample reload timer initialization */
TIMSK0 = (1 << OCIE0A);
OCR0A = ((F_CPU / 8 / CurrentAudioSampleFrequency) - 1);
TCCR0A = (1 << WGM01); // CTC mode
TCCR0B = (1 << CS01); // Fcpu/8 speed
}
/** Event handler for the library USB Disconnection event. */
void EVENT_USB_Device_Disconnect(void)
{
/* Stop the sample reload timer */
TCCR0B = 0;
LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);
}
/** Event handler for the library USB Configuration Changed event. */
void EVENT_USB_Device_ConfigurationChanged(void)
{
bool ConfigSuccess = true;
ConfigSuccess &= Audio_Device_ConfigureEndpoints(&Microphone_Audio_Interface);
LEDs_SetAllLEDs(ConfigSuccess ? LEDMASK_USB_READY : LEDMASK_USB_ERROR);
}
/** Event handler for the library USB Control Request reception event. */
void EVENT_USB_Device_ControlRequest(void)
{
Audio_Device_ProcessControlRequest(&Microphone_Audio_Interface);
}
/** Audio class driver callback for the setting and retrieval of streaming endpoint properties. This callback must be implemented
* in the user application to handle property manipulations on streaming audio endpoints.
*
* When the DataLength parameter is NULL, this callback should only indicate whether the specified operation is valid for
* the given endpoint index, and should return as fast as possible. When non-NULL, this value may be altered for GET operations
* to indicate the size of the retrieved data.
*
* \note The length of the retrieved data stored into the Data buffer on GET operations should not exceed the initial value
* of the \c DataLength parameter.
*
* \param[in,out] AudioInterfaceInfo Pointer to a structure containing an Audio Class configuration and state.
* \param[in] EndpointProperty Property of the endpoint to get or set, a value from Audio_ClassRequests_t.
* \param[in] EndpointAddress Address of the streaming endpoint whose property is being referenced.
* \param[in] EndpointControl Parameter of the endpoint to get or set, a value from Audio_EndpointControls_t.
* \param[in,out] DataLength For SET operations, the length of the parameter data to set. For GET operations, the maximum
* length of the retrieved data. When NULL, the function should return whether the given property
* and parameter is valid for the requested endpoint without reading or modifying the Data buffer.
* \param[in,out] Data Pointer to a location where the parameter data is stored for SET operations, or where
* the retrieved data is to be stored for GET operations.
*
* \return Boolean \c true if the property get/set was successful, \c false otherwise
*/
bool CALLBACK_Audio_Device_GetSetEndpointProperty(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo,
const uint8_t EndpointProperty,
const uint8_t EndpointAddress,
const uint8_t EndpointControl,
uint16_t* const DataLength,
uint8_t* Data)
{
/* Check the requested endpoint to see if a supported endpoint is being manipulated */
if (EndpointAddress == Microphone_Audio_Interface.Config.DataINEndpoint.Address)
{
/* Check the requested control to see if a supported control is being manipulated */
if (EndpointControl == AUDIO_EPCONTROL_SamplingFreq)
{
switch (EndpointProperty)
{
case AUDIO_REQ_SetCurrent:
/* Check if we are just testing for a valid property, or actually adjusting it */
if (DataLength != NULL)
{
/* Set the new sampling frequency to the value given by the host */
CurrentAudioSampleFrequency = (((uint32_t)Data[2] << 16) | ((uint32_t)Data[1] << 8) | (uint32_t)Data[0]);
/* Adjust sample reload timer to the new frequency */
OCR0A = ((F_CPU / 8 / CurrentAudioSampleFrequency) - 1);
}
return true;
case AUDIO_REQ_GetCurrent:
/* Check if we are just testing for a valid property, or actually reading it */
if (DataLength != NULL)
{
*DataLength = 3;
Data[2] = (CurrentAudioSampleFrequency >> 16);
Data[1] = (CurrentAudioSampleFrequency >> 8);
Data[0] = (CurrentAudioSampleFrequency & 0xFF);
}
return true;
}
}
}
return false;
}
/** Audio class driver callback for the setting and retrieval of streaming interface properties. This callback must be implemented
* in the user application to handle property manipulations on streaming audio interfaces.
*
* When the DataLength parameter is NULL, this callback should only indicate whether the specified operation is valid for
* the given entity and should return as fast as possible. When non-NULL, this value may be altered for GET operations
* to indicate the size of the retrieved data.
*
* \note The length of the retrieved data stored into the Data buffer on GET operations should not exceed the initial value
* of the \c DataLength parameter.
*
* \param[in,out] AudioInterfaceInfo Pointer to a structure containing an Audio Class configuration and state.
* \param[in] Property Property of the interface to get or set, a value from Audio_ClassRequests_t.
* \param[in] EntityAddress Address of the audio entity whose property is being referenced.
* \param[in] Parameter Parameter of the entity to get or set, specific to each type of entity (see USB Audio specification).
* \param[in,out] DataLength For SET operations, the length of the parameter data to set. For GET operations, the maximum
* length of the retrieved data. When NULL, the function should return whether the given property
* and parameter is valid for the requested endpoint without reading or modifying the Data buffer.
* \param[in,out] Data Pointer to a location where the parameter data is stored for SET operations, or where
* the retrieved data is to be stored for GET operations.
*
* \return Boolean \c true if the property GET/SET was successful, \c false otherwise
*/
bool CALLBACK_Audio_Device_GetSetInterfaceProperty(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo,
const uint8_t Property,
const uint8_t EntityAddress,
const uint16_t Parameter,
uint16_t* const DataLength,
uint8_t* Data)
{
/* No audio interface entities in the device descriptor, thus no properties to get or set. */
return false;
}

@ -0,0 +1,94 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2017.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2017 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 disclaims 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 AudioInput.c.
*/
#ifndef _AUDIO_INPUT_H_
#define _AUDIO_INPUT_H_
/* Includes: */
#include <avr/io.h>
#include <avr/wdt.h>
#include <avr/power.h>
#include <avr/interrupt.h>
#include <LUFA/Drivers/Board/LEDs.h>
#include <LUFA/Drivers/Board/Buttons.h>
#include <LUFA/Drivers/Peripheral/ADC.h>
#include <LUFA/Drivers/USB/USB.h>
#include <LUFA/Platform/Platform.h>
#include "Descriptors.h"
#include "Config/AppConfig.h"
/* Macros: */
/** Maximum audio sample value for the microphone input. */
#define SAMPLE_MAX_RANGE 0xFFFF
/** Maximum ADC range for the microphone input. */
#define ADC_MAX_RANGE 0x3FF
/** LED mask for the library LED driver, to indicate that the USB interface is not ready. */
#define LEDMASK_USB_NOTREADY LEDS_LED1
/** LED mask for the library LED driver, to indicate that the USB interface is enumerating. */
#define LEDMASK_USB_ENUMERATING (LEDS_LED2 | LEDS_LED3)
/** LED mask for the library LED driver, to indicate that the USB interface is ready. */
#define LEDMASK_USB_READY (LEDS_LED2 | LEDS_LED4)
/** LED mask for the library LED driver, to indicate that an error has occurred in the USB interface. */
#define LEDMASK_USB_ERROR (LEDS_LED1 | LEDS_LED3)
/* 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_ControlRequest(void);
bool CALLBACK_Audio_Device_GetSetEndpointProperty(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo,
const uint8_t EndpointProperty,
const uint8_t EndpointAddress,
const uint8_t EndpointControl,
uint16_t* const DataLength,
uint8_t* Data) ATTR_NON_NULL_PTR_ARG(1);
bool CALLBACK_Audio_Device_GetSetInterfaceProperty(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo,
const uint8_t Property,
const uint8_t EntityAddress,
const uint16_t Parameter,
uint16_t* const DataLength,
uint8_t* Data);
#endif

@ -0,0 +1,92 @@
/** \file
*
* This file contains special DoxyGen information for the generation of the main page and other special
* documentation pages. It is not a project source file.
*/
/** \mainpage Audio Input Device Demo
*
* \section Sec_Compat Demo Compatibility:
*
* The following list indicates what microcontrollers are compatible with this demo.
*
* \li Series 7 USB AVRs (AT90USBxxx7)
* \li Series 6 USB AVRs (AT90USBxxx6)
* \li Series 4 USB AVRs (ATMEGAxxU4)
*
* \section Sec_Info USB Information:
*
* The following table gives a rundown of the USB utilization of this demo.
*
* <table>
* <tr>
* <td><b>USB Mode:</b></td>
* <td>Device</td>
* </tr>
* <tr>
* <td><b>USB Class:</b></td>
* <td>Audio Class</td>
* </tr>
* <tr>
* <td><b>USB Subclass:</b></td>
* <td>Standard Audio Device</td>
* </tr>
* <tr>
* <td><b>Relevant Standards:</b></td>
* <td>USBIF Audio 1.0 Class Specification \n
* USBIF Audio 1.0 Class Terminal Types Specification \n
* USBIF Audio 1.0 Data Formats Specification</td>
* </tr>
* <tr>
* <td><b>Supported USB Speeds:</b></td>
* <td>Full Speed Mode</td>
* </tr>
* </table>
*
* \section Sec_Description Project Description:
*
* Audio demonstration application. This gives a simple reference
* application for implementing a USB Audio Input device using the
* basic USB Audio 1.0 drivers in all modern OSes (i.e. no special drivers
* required).
*
* On start-up the system will automatically enumerate and function as a
* USB microphone. By default, the demo will produce a square wave test tone
* when the board button is pressed. If USE_TEST_TONE is not defined in the
* project makefile, incoming audio from the ADC channel 1 will be sampled
* and sent to the host computer instead.
*
* When in microphone mode, connect a microphone to the ADC channel 2.
*
* Under Windows, if a driver request dialogue pops up, select the option
* to automatically install the appropriate drivers.
*
* \section Sec_Options Project Options
*
* The following defines can be found in this demo, which can control the demo behaviour when defined, or changed in value.
*
* <table>
* <tr>
* <th><b>Define Name:</b></th>
* <th><b>Location:</b></th>
* <th><b>Description:</b></th>
* </tr>
* <tr>
* <td>MIC_IN_ADC_CHANNEL</td>
* <td>AppConfig.h</td>
* <td>Sets the ADC channel used by the demo for the input audio samples from an attached microphone.</td>
* </tr>
* <tr>
* <td>USE_TEST_TONE</td>
* <td>AppConfig.h</td>
* <td>When defined, this alters the demo to produce a square wave test tone when the first board button is pressed
* instead of sampling the board microphone.</td>
* </tr>
* <tr>
* <td>MICROPHONE_BIASED_TO_HALF_RAIL</td>
* <td>AppConfig.h</td>
* <td>When defined, this alters the demo so that the half VCC bias of the microphone input is subtracted.</td>
* </tr>
* </table>
*/

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save