Merge pull request #1471 from qmk/lufa_lib
Update LUFA and move it to /lib/lufaexample_keyboards 0.5.72
commit
9de443cbf1
@ -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 @@
|
||||
hid_bootloader_cli
|
@ -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…
Reference in New Issue