[submodule "protocol/lufa/LUFA-git"] | |||||
path = protocol/lufa/LUFA-git | |||||
url = https://github.com/abcminiuser/lufa.git | |||||
[submodule "protocol/usb_hid/USB_Host_Shield_2.0"] | |||||
path = protocol/usb_hid/USB_Host_Shield_2.0 | |||||
url = https://github.com/felis/USB_Host_Shield_2.0.git |
LUFA_DIR = protocol/lufa | LUFA_DIR = protocol/lufa | ||||
# Path to the LUFA library | # Path to the LUFA library | ||||
ifeq (, $(wildcard $(TMK_DIR)/$(LUFA_DIR)/LUFA-git/LUFA/Version.h)) | |||||
LUFA_PATH ?= $(LUFA_DIR)/LUFA-120730 | |||||
else | |||||
LUFA_PATH ?= $(LUFA_DIR)/LUFA-git | |||||
endif | |||||
LUFA_PATH ?= $(LUFA_DIR)/LUFA-git | |||||
# Create the LUFA source path variables by including the LUFA makefile | # Create the LUFA source path variables by including the LUFA makefile |
# | |||||
# LUFA Library | |||||
# Copyright (C) Dean Camera, 2012. | |||||
# | |||||
# dean [at] fourwalledcubicle [dot] com | |||||
# www.lufa-lib.org | |||||
# | |||||
LUFA_BUILD_MODULES += SOURCES | |||||
LUFA_BUILD_TARGETS += | |||||
LUFA_BUILD_MANDATORY_VARS += LUFA_PATH ARCH | |||||
LUFA_BUILD_OPTIONAL_VARS += | |||||
LUFA_BUILD_PROVIDED_VARS += LUFA_SRC_USB LUFA_SRC_USBCLASS LUFA_SRC_TEMPERATURE LUFA_SRC_SERIAL LUFA_SRC_TWI LUFA_SRC_PLATFORM | |||||
LUFA_BUILD_PROVIDED_MACROS += | |||||
# ----------------------------------------------------------------------------- | |||||
# LUFA Sources Buildsystem Makefile Module. | |||||
# ----------------------------------------------------------------------------- | |||||
# DESCRIPTION: | |||||
# Provides a set of makefile variables for the various LUFA module sources. | |||||
# Once included, the sources required to use a given LUFA module will become | |||||
# available using the makefile variable names listed in the LUFA project | |||||
# documentation. | |||||
# ----------------------------------------------------------------------------- | |||||
# TARGETS: | |||||
# | |||||
# (None) | |||||
# | |||||
# MANDATORY PARAMETERS: | |||||
# | |||||
# LUFA_PATH - Path to the LUFA library core | |||||
# ARCH - Device architecture name | |||||
# | |||||
# OPTIONAL PARAMETERS: | |||||
# | |||||
# (None) | |||||
# | |||||
# PROVIDED VARIABLES: | |||||
# | |||||
# LUFA_SRC_USB - List of LUFA USB driver source files | |||||
# LUFA_SRC_USBCLASS - List of LUFA USB Class driver source files | |||||
# LUFA_SRC_TEMPERATURE - List of LUFA temperature sensor driver source | |||||
# files | |||||
# LUFA_SRC_SERIAL - List of LUFA Serial U(S)ART driver source files | |||||
# LUFA_SRC_TWI - List of LUFA TWI driver source files | |||||
# LUFA_SRC_PLATFORM - List of LUFA architecture specific platform | |||||
# management source files | |||||
# | |||||
# PROVIDED MACROS: | |||||
# | |||||
# (None) | |||||
# | |||||
# ----------------------------------------------------------------------------- | |||||
SHELL = /bin/sh | |||||
ERROR_IF_UNSET ?= $(if $(filter undefined, $(origin $(strip $(1)))), $(error Makefile $(strip $(1)) value not set)) | |||||
ERROR_IF_EMPTY ?= $(if $(strip $($(strip $(1)))), , $(error Makefile $(strip $(1)) option cannot be blank)) | |||||
ERROR_IF_NONBOOL ?= $(if $(filter Y N, $($(strip $(1)))), , $(error Makefile $(strip $(1)) option must be Y or N)) | |||||
# Sanity check user supplied values | |||||
$(foreach MANDATORY_VAR, $(LUFA_BUILD_MANDATORY_VARS), $(call ERROR_IF_UNSET, $(MANDATORY_VAR))) | |||||
$(call ERROR_IF_EMPTY, LUFA_PATH) | |||||
$(call ERROR_IF_EMPTY, ARCH) | |||||
# Allow LUFA_ROOT_PATH to be overridden elsewhere to support legacy LUFA makefiles | |||||
LUFA_ROOT_PATH ?= $(patsubst %/,%,$(LUFA_PATH)) | |||||
# Construct LUFA module source variables | |||||
LUFA_SRC_USB := $(LUFA_ROOT_PATH)/Drivers/USB/Core/$(ARCH)/Device_$(ARCH).c \ | |||||
$(LUFA_ROOT_PATH)/Drivers/USB/Core/$(ARCH)/Endpoint_$(ARCH).c \ | |||||
$(LUFA_ROOT_PATH)/Drivers/USB/Core/$(ARCH)/Host_$(ARCH).c \ | |||||
$(LUFA_ROOT_PATH)/Drivers/USB/Core/$(ARCH)/Pipe_$(ARCH).c \ | |||||
$(LUFA_ROOT_PATH)/Drivers/USB/Core/$(ARCH)/USBController_$(ARCH).c \ | |||||
$(LUFA_ROOT_PATH)/Drivers/USB/Core/$(ARCH)/USBInterrupt_$(ARCH).c \ | |||||
$(LUFA_ROOT_PATH)/Drivers/USB/Core/$(ARCH)/EndpointStream_$(ARCH).c \ | |||||
$(LUFA_ROOT_PATH)/Drivers/USB/Core/$(ARCH)/PipeStream_$(ARCH).c \ | |||||
$(LUFA_ROOT_PATH)/Drivers/USB/Core/ConfigDescriptors.c \ | |||||
$(LUFA_ROOT_PATH)/Drivers/USB/Core/DeviceStandardReq.c \ | |||||
$(LUFA_ROOT_PATH)/Drivers/USB/Core/Events.c \ | |||||
$(LUFA_ROOT_PATH)/Drivers/USB/Core/HostStandardReq.c \ | |||||
$(LUFA_ROOT_PATH)/Drivers/USB/Core/USBTask.c \ | |||||
$(LUFA_ROOT_PATH)/Drivers/USB/Class/Common/HIDParser.c | |||||
LUFA_SRC_USBCLASS := $(LUFA_ROOT_PATH)/Drivers/USB/Class/Device/AudioClassDevice.c \ | |||||
$(LUFA_ROOT_PATH)/Drivers/USB/Class/Device/CDCClassDevice.c \ | |||||
$(LUFA_ROOT_PATH)/Drivers/USB/Class/Device/HIDClassDevice.c \ | |||||
$(LUFA_ROOT_PATH)/Drivers/USB/Class/Device/MassStorageClassDevice.c \ | |||||
$(LUFA_ROOT_PATH)/Drivers/USB/Class/Device/MIDIClassDevice.c \ | |||||
$(LUFA_ROOT_PATH)/Drivers/USB/Class/Device/RNDISClassDevice.c \ | |||||
$(LUFA_ROOT_PATH)/Drivers/USB/Class/Host/AndroidAccessoryClassHost.c \ | |||||
$(LUFA_ROOT_PATH)/Drivers/USB/Class/Host/AudioClassHost.c \ | |||||
$(LUFA_ROOT_PATH)/Drivers/USB/Class/Host/CDCClassHost.c \ | |||||
$(LUFA_ROOT_PATH)/Drivers/USB/Class/Host/HIDClassHost.c \ | |||||
$(LUFA_ROOT_PATH)/Drivers/USB/Class/Host/MassStorageClassHost.c \ | |||||
$(LUFA_ROOT_PATH)/Drivers/USB/Class/Host/MIDIClassHost.c \ | |||||
$(LUFA_ROOT_PATH)/Drivers/USB/Class/Host/PrinterClassHost.c \ | |||||
$(LUFA_ROOT_PATH)/Drivers/USB/Class/Host/RNDISClassHost.c \ | |||||
$(LUFA_ROOT_PATH)/Drivers/USB/Class/Host/StillImageClassHost.c | |||||
LUFA_SRC_TEMPERATURE := $(LUFA_ROOT_PATH)/Drivers/Board/Temperature.c | |||||
LUFA_SRC_SERIAL := $(LUFA_ROOT_PATH)/Drivers/Peripheral/$(ARCH)/Serial_$(ARCH).c | |||||
LUFA_SRC_TWI := $(LUFA_ROOT_PATH)/Drivers/Peripheral/$(ARCH)/TWI_$(ARCH).c | |||||
ifeq ($(ARCH), UC3) | |||||
LUFA_SRC_PLATFORM := $(LUFA_ROOT_PATH)/Platform/UC3/Exception.S \ | |||||
$(LUFA_ROOT_PATH)/Platform/UC3/InterruptManagement.c | |||||
else | |||||
LUFA_SRC_PLATFORM := | |||||
endif | |||||
# Build a list of all available module sources | |||||
LUFA_SRC_ALL_FILES := $(LUFA_SRC_USB) \ | |||||
$(LUFA_SRC_USBCLASS) \ | |||||
$(LUFA_SRC_TEMPERATURE) \ | |||||
$(LUFA_SRC_SERIAL) \ | |||||
$(LUFA_SRC_TWI) \ | |||||
$(LUFA_SRC_PLATFORM) |
/** \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. | |||||
*/ | |||||
/** \page Page_TokenSummary Summary of Compile Tokens | |||||
* | |||||
* The following lists all the possible tokens which can be defined in a project makefile, and passed to the | |||||
* compiler via the -D switch, to alter the LUFA library code. These tokens may alter the library behaviour, | |||||
* or remove features unused by a given application in order to save flash space. | |||||
* | |||||
* \note If the \c USE_LUFA_CONFIG_HEADER token is defined, the library will include a header file named \c LUFAConfig.h located | |||||
* in the user directory where the below compile time tokens may be defined. This allows for an alternative to makefile | |||||
* defined tokens for configuring the library. | |||||
* | |||||
* \section Sec_SummaryNonUSBTokens Non USB Related Tokens | |||||
* This section describes compile tokens which affect non-USB sections of the LUFA library. | |||||
* | |||||
* - <b>DISABLE_TERMINAL_CODES</b> - (\ref Group_Terminal) - <i>All Architectures</i> \n | |||||
* If an application contains ANSI terminal control codes listed in TerminalCodes.h, it might be desired to remove them | |||||
* at compile time for use with a terminal which is non-ANSI control code aware, without modifying the source code. If | |||||
* this token is defined, all ANSI control codes in the application code from the TerminalCodes.h header are removed from | |||||
* the source code at compile time. | |||||
* | |||||
* | |||||
* \section Sec_SummaryUSBClassTokens USB Class Driver Related Tokens | |||||
* This section describes compile tokens which affect USB class-specific drivers in the LUFA library. | |||||
* | |||||
* - <b>HID_HOST_BOOT_PROTOCOL_ONLY</b> - (\ref Group_USBClassHIDHost) - <i>All Architectures</i> \n | |||||
* By default, the USB HID Host class driver is designed to work with HID devices using either the Boot or Report HID | |||||
* communication protocols. On devices where the Report protocol is not used (i.e. in applications where only basic | |||||
* Mouse or Keyboard operation is desired, using boot compatible devices), the code responsible for the Report protocol | |||||
* mode can be removed to save space in the compiled application by defining this token. When defined, it is still necessary | |||||
* to explicitly put the attached device into Boot protocol mode via a call to \ref HID_Host_SetBootProtocol(). | |||||
* | |||||
* - <b>HID_STATETABLE_STACK_DEPTH</b>=<i>x</i> - (\ref Group_HIDParser) - <i>All Architectures</i> \n | |||||
* HID reports may contain PUSH and POP elements, to store and retrieve the current HID state table onto a stack. This | |||||
* allows for reports to save the state table before modifying it slightly for a data item, and then restore the previous | |||||
* state table in a compact manner. This token may be defined to a non-zero 8-bit value to give the maximum depth of the state | |||||
* table stack. If not defined, this defaults to the value indicated in the HID.h file documentation. | |||||
* | |||||
* - <b>HID_USAGE_STACK_DEPTH</b>=<i>x</i> - (\ref Group_HIDParser) - <i>All Architectures</i> \n | |||||
* HID reports generally contain many USAGE elements, which are assigned to INPUT, OUTPUT and FEATURE items in succession | |||||
* when multiple items are defined at once (via REPORT COUNT elements). This allows for several items to be defined with | |||||
* different usages in a compact manner. This token may be defined to a non-zero 8-bit value to set the maximum depth of the | |||||
* usage stack, indicating the maximum number of USAGE items which can be stored temporarily until the next INPUT, OUTPUT | |||||
* and FEATURE item. If not defined, this defaults to the value indicated in the HID.h file documentation. | |||||
* | |||||
* - <b>HID_MAX_COLLECTIONS</b>=<i>x</i> - (\ref Group_HIDParser) - <i>All Architectures</i> \n | |||||
* HID reports generally contain several COLLECTION elements, used to group related data items together. Collection information | |||||
* is stored separately in the processed usage structure (and referred to by the data elements in the structure) to save space. | |||||
* This token may be defined to a non-zero 8-bit value to set the maximum number of COLLECTION items which can be processed by the | |||||
* parser into the resultant processed report structure. If not defined, this defaults to the value indicated in the HID.h file | |||||
* documentation. | |||||
* | |||||
* - <b>HID_MAX_REPORTITEMS</b>=<i>x</i> - (\ref Group_HIDParser) - <i>All Architectures</i> \n | |||||
* All HID reports contain one or more INPUT, OUTPUT and/or FEATURE items describing the data which can be sent to and from the HID | |||||
* device. Each item has associated usages, bit offsets in the item reports and other associated data indicating the manner in which | |||||
* the report data should be interpreted by the host. This token may be defined to a non-zero 8-bit value to set the maximum number of | |||||
* data elements which can be stored in the processed HID report structure, including INPUT, OUTPUT and (if enabled) FEATURE items. | |||||
* If a item has a multiple count (i.e. a REPORT COUNT of more than 1), each item in the report count is placed separately in the | |||||
* processed HID report table. If not defined, this defaults to the value indicated in the HID.h file documentation. | |||||
* | |||||
* - <b>HID_MAX_REPORT_IDS</b>=<i>x</i> - (\ref Group_HIDParser) - <i>All Architectures</i> \n | |||||
* HID reports may contain several report IDs, to logically distinguish grouped device data from one another - for example, a combination | |||||
* keyboard and mouse might use report IDs to separate the keyboard reports from the mouse reports. In order to determine the size of each | |||||
* report, and thus know how many bytes must be read or written, the size of each report (IN, OUT and FEATURE) must be calculated and | |||||
* stored. This token may be defined to a non-zero 8-bit value to set the maximum number of report IDs in a device which can be processed | |||||
* and their sizes calculated/stored into the resultant processed report structure. If not defined, this defaults to the value indicated in | |||||
* the HID.h file documentation. | |||||
* | |||||
* - <b>NO_CLASS_DRIVER_AUTOFLUSH</b> - (\ref Group_USBClassDrivers) - <i>All Architectures</i> \n | |||||
* Many of the device and host mode class drivers automatically flush any data waiting to be written to an interface, when the corresponding | |||||
* USB management task is executed. This is usually desirable to ensure that any queued data is sent as soon as possible once and new data is | |||||
* constructed in the main program loop. However, if flushing is to be controlled manually by the user application via the *_Flush() commands, | |||||
* the compile time token may be defined in the application's makefile to disable automatic flushing during calls to the class driver USB | |||||
* management tasks. | |||||
* | |||||
* | |||||
* \section Sec_SummaryUSBTokens General USB Driver Related Tokens | |||||
* This section describes compile tokens which affect USB driver stack as a whole in the LUFA library. | |||||
* | |||||
* - <b>ORDERED_EP_CONFIG</b> - (\ref Group_EndpointManagement , \ref Group_PipeManagement) - <i>AVR8, UC3</i> \n | |||||
* The USB AVRs do not allow for Endpoints and Pipes to be configured out of order; they <i>must</i> be configured in an ascending order to | |||||
* prevent data corruption issues. However, by default LUFA employs a workaround to allow for unordered Endpoint/Pipe initialization. This compile | |||||
* time token may be used to restrict the initialization order to ascending indexes only in exchange for a smaller compiled binary size. Use | |||||
* caution when applied to applications using the library USB Class drivers; the user application must ensure that all endpoints and pipes are | |||||
* allocated sequentially. | |||||
* | |||||
* - <b>USE_STATIC_OPTIONS</b>=<i>x</i> - (\ref Group_USBManagement) - <i>All Architectures</i> \n | |||||
* By default, the USB_Init() function accepts dynamic options at runtime to alter the library behaviour, including whether the USB pad | |||||
* voltage regulator is enabled, and the device speed when in device mode. By defining this token to a mask comprised of the USB options | |||||
* mask defines usually passed as the Options parameter to USB_Init(), the resulting compiled binary can be decreased in size by removing | |||||
* the dynamic options code, and replacing it with the statically set options. When defined, the USB_Init() function no longer accepts an | |||||
* Options parameter. | |||||
* | |||||
* - <b>USB_DEVICE_ONLY</b> - (\ref Group_USBManagement) - <i>All Architectures</i> \n | |||||
* For the USB AVR models supporting both device and host USB modes, the USB_Init() function contains a Mode parameter which specifies the | |||||
* mode the library should be initialized to. If only device mode is required, the code for USB host mode can be removed from the binary to | |||||
* save space. When defined, the USB_Init() function no longer accepts a Mode parameter. This define is irrelevant on smaller USB AVRs which | |||||
* do not support host mode. | |||||
* | |||||
* - <b>USB_HOST_ONLY</b> - (\ref Group_USBManagement) - <i>All Architectures</i> \n | |||||
* Same as USB_DEVICE_ONLY, except the library is fixed to USB host mode rather than USB device mode. Not available on some USB AVR models. | |||||
* | |||||
* - <b>USB_STREAM_TIMEOUT_MS</b>=<i>x</i> - (\ref Group_USBManagement) - <i>All Architectures</i> \n | |||||
* When endpoint and/or pipe stream functions are used, by default there is a timeout between each transfer which the connected device or host | |||||
* must satisfy, or the stream function aborts the remaining data transfer. This token may be defined to a non-zero 16-bit value to set the timeout | |||||
* period for stream transfers, specified in milliseconds. If not defined, the default value specified in LowLevel.h is used instead. | |||||
* | |||||
* - <b>NO_LIMITED_CONTROLLER_CONNECT</b> - (\ref Group_Events) - <i>AVR8 Only</i> \n | |||||
* On the smaller USB AVRs, the USB controller lacks VBUS events to determine the physical connection state of the USB bus to a host. In lieu of | |||||
* VBUS events, the library attempts to determine the connection state via the bus suspension and wake up events instead. This however may be | |||||
* slightly inaccurate due to the possibility of the host suspending the bus while the device is still connected. If accurate connection status is | |||||
* required, the VBUS line of the USB connector should be routed to an AVR pin to detect its level, so that the USB_DeviceState global | |||||
* can be accurately set and the \ref EVENT_USB_Device_Connect() and \ref EVENT_USB_Device_Disconnect() events manually raised by the RAISE_EVENT macro. | |||||
* When defined, this token disables the library's auto-detection of the connection state by the aforementioned suspension and wake up events. | |||||
* | |||||
* - <b>NO_SOF_EVENTS</b> - (\ref Group_Events) - <i>All Architectures</i> \n | |||||
* By default, there exists a LUFA application event for the start of each USB frame while the USB bus is not suspended in either host or device mode. | |||||
* This event can be selectively enabled or disabled by calling the appropriate device or host mode function. When this compile time token is defined, | |||||
* the ability to receive USB Start of Frame events via the \ref EVENT_USB_Device_StartOfFrame() or \ref EVENT_USB_Host_StartOfFrame() events is removed, | |||||
* reducing the compiled program's binary size. | |||||
* | |||||
* | |||||
* \section Sec_SummaryUSBDeviceTokens USB Device Mode Driver Related Tokens | |||||
* This section describes compile tokens which affect USB driver stack of the LUFA library when used in Device mode. | |||||
* | |||||
* - <b>USE_RAM_DESCRIPTORS</b> - (\ref Group_StdDescriptors) - <i>AVR8 Only</i> \n | |||||
* Define this token to indicate to the USB driver that all device descriptors are stored in RAM, rather than being located in any one | |||||
* of the AVR's memory spaces. RAM descriptors may be desirable in applications where the descriptors need to be modified at runtime. | |||||
* | |||||
* - <b>USE_FLASH_DESCRIPTORS</b> - (\ref Group_StdDescriptors) - <i>AVR8 Only</i> \n | |||||
* Similar to USE_RAM_DESCRIPTORS, but all descriptors are stored in the AVR's FLASH memory rather than RAM. | |||||
* | |||||
* - <b>USE_EEPROM_DESCRIPTORS</b> - (\ref Group_StdDescriptors) - <i>AVR8 Only</i> \n | |||||
* Similar to USE_RAM_DESCRIPTORS, but all descriptors are stored in the AVR's EEPROM memory rather than RAM. | |||||
* | |||||
* - <b>NO_INTERNAL_SERIAL</b> - (\ref Group_StdDescriptors) - <i>All Architectures</i> \n | |||||
* Some AVR models contain a unique serial number which can be used as the device serial number, while in device mode. This allows | |||||
* the host to uniquely identify the device regardless of if it is moved between USB ports on the same computer, allowing allocated | |||||
* resources (such as drivers, COM Port number allocations) to be preserved. This is not needed in many apps, and so the code that | |||||
* performs this task can be disabled by defining this option and passing it to the compiler via the -D switch. | |||||
* | |||||
* - <b>FIXED_CONTROL_ENDPOINT_SIZE</b>=<i>x</i> - (\ref Group_EndpointManagement) - <i>All Architectures</i> \n | |||||
* By default, the library determines the size of the control endpoint (when in device mode) by reading the device descriptor. | |||||
* Normally this reduces the amount of configuration required for the library, allows the value to change dynamically (if | |||||
* descriptors are stored in EEPROM or RAM rather than flash memory) and reduces code maintenance. However, this token can be | |||||
* defined to a non-zero value instead to give the size in bytes of the control endpoint, to reduce the size of the compiled | |||||
* binary. | |||||
* | |||||
* - <b>DEVICE_STATE_AS_GPIOR</b> - (\ref Group_Device) - <i>AVR8 Only</i> \n | |||||
* One of the most frequently used global variables in the stack is the USB_DeviceState global, which indicates the current state of | |||||
* the Device State Machine. To reduce the amount of code and time required to access and modify this global in an application, this token | |||||
* may be defined to a value between 0 and 2 to fix the state variable into one of the three general purpose IO registers inside the AVR | |||||
* reserved for application use. When defined, the corresponding GPIOR register should not be used within the user application except | |||||
* implicitly via the library APIs. | |||||
* | |||||
* - <b>FIXED_NUM_CONFIGURATIONS</b>=<i>x</i> - (\ref Group_Device) - <i>All Architectures</i> \n | |||||
* By default, the library determines the number of configurations a USB device supports by reading the device descriptor. This reduces | |||||
* the amount of configuration required to set up the library, and allows the value to change dynamically (if descriptors are stored in | |||||
* EEPROM or RAM rather than flash memory) and reduces code maintenance. However, this value may be fixed via this token in the project | |||||
* makefile to reduce the compiled size of the binary at the expense of flexibility. | |||||
* | |||||
* - <b>CONTROL_ONLY_DEVICE</b> - (\ref Group_Device) - <i>All Architectures</i> \n | |||||
* In some limited USB device applications, there are no device endpoints other than the control endpoint; i.e. all device communication | |||||
* is through control endpoint requests. Defining this token will remove several features related to the selection and control of device | |||||
* endpoints internally, saving space. Generally, this is usually only useful in (some) bootloaders and is best avoided. | |||||
* | |||||
* - <b>MAX_ENDPOINT_INDEX</b> - (\ref Group_Device) - <i>XMEGA Only</i> \n | |||||
* Defining this value to the highest index (not address - this excludes the direction flag) endpoint within the device will restrict the | |||||
* number of FIFOs created internally for the endpoint buffers, reducing the total RAM usage. | |||||
* | |||||
* - <b>INTERRUPT_CONTROL_ENDPOINT</b> - (\ref Group_USBManagement) - <i>All Architectures</i> \n | |||||
* Some applications prefer to not call the USB_USBTask() management task regularly while in device mode, as it can complicate code significantly. | |||||
* Instead, when device mode is used this token can be passed to the library via the -D switch to allow the library to manage the USB control | |||||
* endpoint entirely via USB controller interrupts asynchronously to the user application. When defined, USB_USBTask() does not need to be called | |||||
* when in USB device mode. | |||||
* | |||||
* - <b>NO_DEVICE_REMOTE_WAKEUP</b> - (\ref Group_Device) - <i>All Architectures</i> \n | |||||
* Many devices do not require the use of the Remote Wakeup features of USB, used to wake up the USB host when suspended. On these devices, | |||||
* the code required to manage device Remote Wakeup can be disabled by defining this token and passing it to the library via the -D switch. | |||||
* | |||||
* - <b>NO_DEVICE_SELF_POWER</b> - (\ref Group_Device) - <i>All Architectures</i> \n | |||||
* USB devices may be bus powered, self powered, or a combination of both. When a device can be both bus powered and self powered, the host may | |||||
* query the device to determine the current power source, via \ref USB_Device_CurrentlySelfPowered. For solely bus powered devices, this global | |||||
* and the code required to manage it may be disabled by passing this token to the library via the -D switch. | |||||
* | |||||
* | |||||
* \section Sec_SummaryUSBHostTokens USB Host Mode Driver Related Tokens | |||||
* | |||||
* This section describes compile tokens which affect USB driver stack of the LUFA library when used in Host mode. | |||||
* | |||||
* - <b>HOST_STATE_AS_GPIOR</b> - (\ref Group_Host) - <i>AVR8 Only</i> \n | |||||
* One of the most frequently used global variables in the stack is the USB_HostState global, which indicates the current state of | |||||
* the Host State Machine. To reduce the amount of code and time required to access and modify this global in an application, this token | |||||
* may be defined to a value between 0 and 2 to fix the state variable into one of the three general purpose IO registers inside the AVR | |||||
* reserved for application use. When defined, the corresponding GPIOR register should not be used within the user application except | |||||
* implicitly via the library APIs. | |||||
* | |||||
* - <b>USB_HOST_TIMEOUT_MS</b>=<i>x</i> - (\ref Group_Host) - <i>All Architectures</i> \n | |||||
* When a control transfer is initiated in host mode to an attached device, a timeout is used to abort the transfer if the attached | |||||
* device fails to respond within the timeout period. This token may be defined to a non-zero 16-bit value to set the timeout period for | |||||
* control transfers, specified in milliseconds. If not defined, the default value specified in Host.h is used instead. | |||||
* | |||||
* - <b>HOST_DEVICE_SETTLE_DELAY_MS</b>=<i>x</i> - (\ref Group_Host) - <i>All Architectures</i> \n | |||||
* Some devices require a delay of up to 5 seconds after they are connected to VBUS before the enumeration process can be started, or | |||||
* they will fail to enumerate correctly. By placing a delay before the enumeration process, it can be ensured that the bus has settled | |||||
* back to a known idle state before communications occur with the device. This token may be defined to a 16-bit value to set the device | |||||
* settle period, specified in milliseconds. If not defined, the default value specified in Host.h is used instead. | |||||
* | |||||
* - <b>INVERTED_VBUS_ENABLE_LINE</b> - (\ref Group_Host) - <i>All Architectures</i> \n | |||||
* If enabled, this will indicate that the USB target VBUS line polarity is inverted; i.e. it should be pulled low to enable VBUS to the | |||||
* target, and pulled high to stop the target VBUS generation. | |||||
* | |||||
* \attention On AVR8 architecture devices, this compile time option requires \c NO_AUTO_VBUS_MANAGEMENT to be set. | |||||
* | |||||
* - <b>NO_AUTO_VBUS_MANAGEMENT</b> - (\ref Group_Host) - <i>All Architectures</i> \n | |||||
* Disables the automatic management of VBUS to the target, i.e. automatic shut down in the even of an overcurrent situation. When enabled, VBUS | |||||
* is enabled while the USB controller is initialized in USB Host mode. | |||||
*/ | |||||
/** \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. | |||||
*/ | |||||
/** \page Page_KnownIssues Known Issues | |||||
* The following are known issues present in each official LUFA release. This list should contain all known | |||||
* issues in the library. Most of these issues should be corrected in the future release - see | |||||
* \ref Page_FutureChanges for a list of planned changes in future releases. | |||||
* | |||||
* \section Sec_KnownIssues120730 Version 120730 | |||||
* - AVR8 Architecture | |||||
* - No known issues. | |||||
* - UC3 Architecture | |||||
* \warning The UC3 device support is currently <b>experimental</b> (incomplete and/or non-functional), and is included for preview purposes only. \n | |||||
* | |||||
* - No demos, bootloaders or projects have been ported for the UC3 devices in the current release, | |||||
* although the architecture is supported in the LUFA core library. | |||||
* - DMA transfers to and from the USB controller are not yet implemented for this release. | |||||
* - The UC3C, UC3D and UC3L sub-families of UC3 are not currently supported by the library due to their | |||||
* altered USB controller design. | |||||
* - The various \c CreateStream() functions for creating standard \c <stdio.h> compatible virtual file | |||||
* streams are not available on the UC3 architecture, due to a lack of suitable library support. | |||||
* - XMEGA Architecture | |||||
* \warning The XMEGA device support is currently <b>experimental</b> (incomplete and/or non-functional), and is included for preview purposes only. | |||||
* | |||||
* - No demos, bootloaders or projects have been ported for the XMEGA devices in the current release, | |||||
* although the architecture is supported in the LUFA core library. | |||||
* - Endpoints of more than 64 bytes are not currently supported in this release. | |||||
* - Isochronous endpoints are not currently supported in this release. As a result, the audio class | |||||
* cannot be used on XMEGA devices. | |||||
* - Multiple-bank endpoints are not currently supported in this release. | |||||
* - Early revisions of the ATXMEGA128A1U are incompatible with LUFA, due to their various errata | |||||
* relating to the USB controller. | |||||
* - Architecture Independent | |||||
* - The HID parser fails for array type elements that have a MIN and MAX usage applied; each element | |||||
* in the array will receive a unique incrementing usage from the MIN value, up to MAX. | |||||
* - The LUFA library is not watchdog aware, and thus timeouts are possible if short periods are used | |||||
* and a lengthy USB operation is initiated. | |||||
* - Build System | |||||
* - No known issues. | |||||
*/ | |||||
/** \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. | |||||
*/ | |||||
/** | |||||
* \page Page_LicenseInfo Source Code License | |||||
* | |||||
* The LUFA library is currently released under the MIT license, included below. | |||||
* | |||||
* Commercial entities can opt out of the public disclosure clause in this license | |||||
* for a one-time US$1500 payment. This provides a non-exclusive modified MIT licensed which | |||||
* allows for the free use of the LUFA library, bootloaders and (where the sole copyright | |||||
* is attributed to Dean Camera) demos without public disclosure within an organization, in | |||||
* addition to three free hours of consultation with the library author, and priority support. | |||||
* Please visit the Commercial License link on \ref Page_Resources for more information on | |||||
* ordering a commercial license for your company. | |||||
* | |||||
* \verbinclude License.txt | |||||
*/ | |||||
/** \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. | |||||
*/ | |||||
/** \page Page_VIDPID VID and PID values | |||||
* | |||||
* \section Sec_VIDPID_Allocations VID and PID Allocations | |||||
* The LUFA library uses VID/PID combinations generously donated by Atmel. The following VID/PID combinations | |||||
* are used within the LUFA demos, and thus may be re-used by derivations of each demo. Free PID values may be | |||||
* used by future LUFA demo projects. | |||||
* | |||||
* <b>These VID/PID values should not be used in commercial designs under any circumstances.</b> Private projects | |||||
* may use the following values freely, but must accept any collisions due to other LUFA derived private projects | |||||
* sharing identical values. It is suggested that private projects using interfaces compatible with existing | |||||
* demos share the same VID/PID value. | |||||
* | |||||
* <table> | |||||
* | |||||
* <tr> | |||||
* <td> | |||||
* <b>VID</b> | |||||
* </td> | |||||
* <td> | |||||
* <b>PID</b> | |||||
* </td> | |||||
* <td> | |||||
* <b>Usage</b> | |||||
* </td> | |||||
* </tr> | |||||
* | |||||
* <tr> | |||||
* <td> | |||||
* 0x03EB | |||||
* </td> | |||||
* <td> | |||||
* 0x2040 | |||||
* </td> | |||||
* <td> | |||||
* Test VID/PID (See below) | |||||
* </td> | |||||
* | |||||
* <tr> | |||||
* <td> | |||||
* 0x03EB | |||||
* </td> | |||||
* <td> | |||||
* 0x2041 | |||||
* </td> | |||||
* <td> | |||||
* Mouse Demo Application | |||||
* </td> | |||||
* </tr> | |||||
* | |||||
* <tr> | |||||
* <td> | |||||
* 0x03EB | |||||
* </td> | |||||
* <td> | |||||
* 0x2042 | |||||
* </td> | |||||
* <td> | |||||
* Keyboard Demo Application | |||||
* </td> | |||||
* </tr> | |||||
* | |||||
* <tr> | |||||
* <td> | |||||
* 0x03EB | |||||
* </td> | |||||
* <td> | |||||
* 0x2043 | |||||
* </td> | |||||
* <td> | |||||
* Joystick Demo Application | |||||
* </td> | |||||
* </tr> | |||||
* | |||||
* <tr> | |||||
* <td> | |||||
* 0x03EB | |||||
* </td> | |||||
* <td> | |||||
* 0x2044 | |||||
* </td> | |||||
* <td> | |||||
* CDC Demo Application | |||||
* </td> | |||||
* </tr> | |||||
* | |||||
* <tr> | |||||
* <td> | |||||
* 0x03EB | |||||
* </td> | |||||
* <td> | |||||
* 0x2045 | |||||
* </td> | |||||
* <td> | |||||
* Mass Storage Demo Application | |||||
* </td> | |||||
* </tr> | |||||
* | |||||
* <tr> | |||||
* <td> | |||||
* 0x03EB | |||||
* </td> | |||||
* <td> | |||||
* 0x2046 | |||||
* </td> | |||||
* <td> | |||||
* Audio Output Demo Application | |||||
* </td> | |||||
* </tr> | |||||
* | |||||
* <tr> | |||||
* <td> | |||||
* 0x03EB | |||||
* </td> | |||||
* <td> | |||||
* 0x2047 | |||||
* </td> | |||||
* <td> | |||||
* Audio Input Demo Application | |||||
* </td> | |||||
* </tr> | |||||
* | |||||
* <tr> | |||||
* <td> | |||||
* 0x03EB | |||||
* </td> | |||||
* <td> | |||||
* 0x2048 | |||||
* </td> | |||||
* <td> | |||||
* MIDI Demo Application | |||||
* </td> | |||||
* </tr> | |||||
* | |||||
* <tr> | |||||
* <td> | |||||
* 0x03EB | |||||
* </td> | |||||
* <td> | |||||
* 0x2049 | |||||
* </td> | |||||
* <td> | |||||
* MagStripe Project | |||||
* </td> | |||||
* </tr> | |||||
* | |||||
* <tr> | |||||
* <td> | |||||
* 0x03EB | |||||
* </td> | |||||
* <td> | |||||
* 0x204A | |||||
* </td> | |||||
* <td> | |||||
* CDC Bootloader | |||||
* </td> | |||||
* </tr> | |||||
* | |||||
* <tr> | |||||
* <td> | |||||
* 0x03EB | |||||
* </td> | |||||
* <td> | |||||
* 0x204B | |||||
* </td> | |||||
* <td> | |||||
* USB to Serial Demo Application | |||||
* </td> | |||||
* </tr> | |||||
* | |||||
* <tr> | |||||
* <td> | |||||
* 0x03EB | |||||
* </td> | |||||
* <td> | |||||
* 0x204C | |||||
* </td> | |||||
* <td> | |||||
* RNDIS Demo Application | |||||
* </td> | |||||
* </tr> | |||||
* | |||||
* <tr> | |||||
* <td> | |||||
* 0x03EB | |||||
* </td> | |||||
* <td> | |||||
* 0x204D | |||||
* </td> | |||||
* <td> | |||||
* Combined Keyboard and Mouse Demo Application | |||||
* </td> | |||||
* </tr> | |||||
* | |||||
* <tr> | |||||
* <td> | |||||
* 0x03EB | |||||
* </td> | |||||
* <td> | |||||
* 0x204E | |||||
* </td> | |||||
* <td> | |||||
* Dual CDC Demo Application | |||||
* </td> | |||||
* </tr> | |||||
* | |||||
* <tr> | |||||
* <td> | |||||
* 0x03EB | |||||
* </td> | |||||
* <td> | |||||
* 0x204F | |||||
* </td> | |||||
* <td> | |||||
* Generic HID Demo Application | |||||
* </td> | |||||
* </tr> | |||||
* | |||||
* <tr> | |||||
* <td> | |||||
* 0x03EB | |||||
* </td> | |||||
* <td> | |||||
* 0x2060 | |||||
* </td> | |||||
* <td> | |||||
* Benito Programmer Project | |||||
* </td> | |||||
* </tr> | |||||
* | |||||
* <tr> | |||||
* <td> | |||||
* 0x03EB | |||||
* </td> | |||||
* <td> | |||||
* 0x2061 | |||||
* </td> | |||||
* <td> | |||||
* Combined Mass Storage and Keyboard Demo | |||||
* </td> | |||||
* </tr> | |||||
* | |||||
* <tr> | |||||
* <td> | |||||
* 0x03EB | |||||
* </td> | |||||
* <td> | |||||
* 0x2062 | |||||
* </td> | |||||
* <td> | |||||
* Combined CDC and Mouse Demo | |||||
* </td> | |||||
* </tr> | |||||
* | |||||
* <tr> | |||||
* <td> | |||||
* 0x03EB | |||||
* </td> | |||||
* <td> | |||||
* 0x2063 | |||||
* </td> | |||||
* <td> | |||||
* Mass Storage/HID Interface Datalogger Project | |||||
* </td> | |||||
* </tr> | |||||
* | |||||
* <tr> | |||||
* <td> | |||||
* 0x03EB | |||||
* </td> | |||||
* <td> | |||||
* 0x2064 | |||||
* </td> | |||||
* <td> | |||||
* Interfaceless Control-Only LUFA Devices | |||||
* </td> | |||||
* </tr> | |||||
* | |||||
* <tr> | |||||
* <td> | |||||
* 0x03EB | |||||
* </td> | |||||
* <td> | |||||
* 0x2065 | |||||
* </td> | |||||
* <td> | |||||
* Test and Measurement Demo | |||||
* </td> | |||||
* </tr> | |||||
* | |||||
* <tr> | |||||
* <td> | |||||
* 0x03EB | |||||
* </td> | |||||
* <td> | |||||
* 0x2066 | |||||
* </td> | |||||
* <td> | |||||
* Multiple Report Keyboard/Mouse HID Demo | |||||
* </td> | |||||
* </tr> | |||||
* | |||||
* <tr> | |||||
* <td> | |||||
* 0x03EB | |||||
* </td> | |||||
* <td> | |||||
* 0x2067 | |||||
* </td> | |||||
* <td> | |||||
* HID Class Bootloader | |||||
* </td> | |||||
* </tr> | |||||
* | |||||
* <tr> | |||||
* <td> | |||||
* 0x03EB | |||||
* </td> | |||||
* <td> | |||||
* 0x2068 | |||||
* </td> | |||||
* <td> | |||||
* Virtual Serial/Mass Storage Demo | |||||
* </td> | |||||
* </tr> | |||||
* | |||||
* <tr> | |||||
* <td> | |||||
* 0x03EB | |||||
* </td> | |||||
* <td> | |||||
* 0x2069 | |||||
* </td> | |||||
* <td> | |||||
* Webserver Project | |||||
* </td> | |||||
* </tr> | |||||
* | |||||
* <tr> | |||||
* <td> | |||||
* 0x03EB | |||||
* </td> | |||||
* <td> | |||||
* 0x206A | |||||
* </td> | |||||
* <td> | |||||
* Media Control Project | |||||
* </td> | |||||
* </tr> | |||||
* | |||||
* <tr> | |||||
* <td> | |||||
* 0x03EB | |||||
* </td> | |||||
* <td> | |||||
* 0x206B | |||||
* </td> | |||||
* <td> | |||||
* <i>Currently Unallocated</i> | |||||
* </td> | |||||
* </tr> | |||||
* | |||||
* <tr> | |||||
* <td> | |||||
* 0x03EB | |||||
* </td> | |||||
* <td> | |||||
* 0x206C | |||||
* </td> | |||||
* <td> | |||||
* <i>Currently Unallocated</i> | |||||
* </td> | |||||
* </tr> | |||||
* | |||||
* <tr> | |||||
* <td> | |||||
* 0x03EB | |||||
* </td> | |||||
* <td> | |||||
* 0x206D | |||||
* </td> | |||||
* <td> | |||||
* <i>Currently Unallocated</i> | |||||
* </td> | |||||
* </tr> | |||||
* | |||||
* <tr> | |||||
* <td> | |||||
* 0x03EB | |||||
* </td> | |||||
* <td> | |||||
* 0x206E | |||||
* </td> | |||||
* <td> | |||||
* <i>Currently Unallocated</i> | |||||
* </td> | |||||
* </tr> | |||||
* | |||||
* <tr> | |||||
* <td> | |||||
* 0x03EB | |||||
* </td> | |||||
* <td> | |||||
* 0x206F | |||||
* </td> | |||||
* <td> | |||||
* <i>Currently Unallocated</i> | |||||
* </td> | |||||
* </tr> | |||||
* | |||||
* </table> | |||||
* | |||||
* \section Sec_Test_VIDPID The Test VID/PID Combination | |||||
* For use in testing of LUFA powered devices during development only, by non-commercial entities. | |||||
* All devices must accept collisions on this VID/PID range (from other in-development LUFA devices) | |||||
* to be resolved by using a unique release number in the Device Descriptor. No devices using this | |||||
* VID/PID combination may be released to the general public. | |||||
*/ | |||||
/** \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. | |||||
*/ | |||||
/** \page Page_WritingBoardDrivers Writing LUFA Board Drivers | |||||
* | |||||
* LUFA ships with several basic pre-made board drivers, to control hardware present on the supported board | |||||
* hardware - such as Dataflash ICs, LEDs, Joysticks, or other hardware peripherals. When compiling an application | |||||
* which makes use of one or more board drivers located in LUFA/Drivers/Board, you must also indicate what board | |||||
* hardware you are using in your project makefile. This is done by defining the BOARD macro using the -D switch | |||||
* passed to the compiler, with a constant of BOARD_{Name}. For example <b>-DBOARD=BOARD_USBKEY</b> instructs the | |||||
* compiler to use the USBKEY board hardware drivers. | |||||
* | |||||
* If your application does not use *any* board level drivers, you can omit the definition of the BOARD macro. | |||||
* However, some users may wish to write their own custom board hardware drivers which are to remain compatible | |||||
* with the LUFA hardware API. To do this, the BOARD macro should be defined to the value BOARD_USER. This indicates | |||||
* that the board level drivers should be located in a folder named "Board" located inside the application's folder. | |||||
* | |||||
* When used, the driver stub files located in the LUFA/CodeTemplates/DriverStubs folder should be copied to the user | |||||
* Board/ directory, and fleshed out to include the values and code needed to control the custom board hardware. Once | |||||
* done, the existing LUFA board level APIs (accessed in the regular LUFA/Drivers/Board/ folder) will redirect to the | |||||
* user board drivers, maintaining code compatibility and allowing for a different board to be selected through the | |||||
* project makefile with no code changes. | |||||
*/ | |||||
Subproject commit b6c18b2a7c544653efbe12a1d4e8ba65e7d83c35 |
*.o | |||||
*.d | |||||
*.elf | |||||
*.hex | |||||
*.eep | |||||
*.sym | |||||
*.bin | |||||
*.lss | |||||
*.map | |||||
*.bak | |||||
*.class | |||||
Documentation/ | |||||
LUFA/StudioIntegration/ProjectGenerator/* | |||||
LUFA/StudioIntegration/DocBook/* |
/* | |||||
LUFA Library | |||||
Copyright (C) Dean Camera, 2014. | |||||
dean [at] fourwalledcubicle [dot] com | |||||
www.lufa-lib.org | |||||
*/ | |||||
/* | |||||
Copyright 2014 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); | |||||
} |
/* | |||||
LUFA Library | |||||
Copyright (C) Dean Camera, 2014. | |||||
dean [at] fourwalledcubicle [dot] com | |||||
www.lufa-lib.org | |||||
*/ | |||||
/* | |||||
Copyright 2014 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 | |||||
/* | |||||
LUFA Library | |||||
Copyright (C) Dean Camera, 2014. | |||||
dean [at] fourwalledcubicle [dot] com | |||||
www.lufa-lib.org | |||||
*/ | |||||
/* | |||||
Copyright 2014 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 |
/* | |||||
LUFA Library | |||||
Copyright (C) Dean Camera, 2014. | |||||
dean [at] fourwalledcubicle [dot] com | |||||
www.lufa-lib.org | |||||
*/ | |||||
/* | |||||
Copyright 2014 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_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(); | |||||
#endif | |||||
/* 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)) | |||||
JumpToApplication |= true; | |||||
/* If a request has been made to jump to the user application, honor it */ | |||||
if (JumpToApplication) | |||||
{ | |||||
/* 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(); | |||||
} | |||||
/* 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_write_byte((uint8_t*)((intptr_t)(CurrAddress >> 1)), FetchNextCommandByte()); | |||||
/* Increment the address counter after use */ | |||||
CurrAddress += 2; | |||||
} | |||||
} | |||||
/* If in FLASH programming mode, commit the page after writing */ | |||||
if (MemoryType == 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_write_byte((uint8_t*)((intptr_t)(CurrAddress >> 1)), FetchNextCommandByte()); | |||||
/* Increment the address after use */ | |||||
CurrAddress += 2; | |||||
/* Send confirmation byte back to the host */ | |||||
WriteNextResponseByte('\r'); | |||||
} | |||||
else if (Command == 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(); | |||||
} | |||||
/* | |||||
LUFA Library | |||||
Copyright (C) Dean Camera, 2014. | |||||
dean [at] fourwalledcubicle [dot] com | |||||
www.lufa-lib.org | |||||
*/ | |||||
/* | |||||
Copyright 2014 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 | |||||
/** \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 | |||||
* | |||||
* This bootloader is designed to be started via the HWB mechanism of the USB AVRs; ground the HWB pin (see device | |||||
* datasheet) then momentarily ground /RESET to start the bootloader. This assumes the HWBE fuse is set and the BOOTRST | |||||
* fuse is cleared. | |||||
* | |||||
* 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. | |||||
* | |||||
* \par After loading an application, it is not run automatically on startup. | |||||
* Some USB AVR boards ship with the BOOTRST fuse set, causing the bootloader | |||||
* to run automatically when the device is reset. In most cases, the BOOTRST | |||||
* fuse should be disabled and the HWBE fuse used instead to run the bootloader | |||||
* when needed. | |||||
* | |||||
* \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> | |||||
*/ | |||||
/* | |||||
LUFA Library | |||||
Copyright (C) Dean Camera, 2014. | |||||
dean [at] fourwalledcubicle [dot] com | |||||
www.lufa-lib.org | |||||
*/ | |||||
/* | |||||
Copyright 2014 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 |
/* | |||||
LUFA Library | |||||
Copyright (C) Dean Camera, 2014. | |||||
dean [at] fourwalledcubicle [dot] com | |||||
www.lufa-lib.org | |||||
*/ | |||||
/* | |||||
Copyright 2014 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 |
/* | |||||
LUFA Library | |||||
Copyright (C) Dean Camera, 2014. | |||||
dean [at] fourwalledcubicle [dot] com | |||||
www.lufa-lib.org | |||||
*/ | |||||
/* | |||||
Copyright 2014 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 uint8_t wIndex, | |||||
const void** const DescriptorAddress) | |||||
{ | |||||
const uint8_t DescriptorType = (wValue >> 8); | |||||
const uint8_t DescriptorNumber = (wValue & 0xFF); | |||||
const void* Address = NULL; | |||||
uint16_t Size = NO_DESCRIPTOR; | |||||
switch (DescriptorType) | |||||
{ | |||||
case DTYPE_Device: | |||||
Address = &DeviceDescriptor; | |||||
Size = sizeof(USB_Descriptor_Device_t); | |||||
break; | |||||
case DTYPE_Configuration: | |||||
Address = &ConfigurationDescriptor; | |||||
Size = sizeof(USB_Descriptor_Configuration_t); | |||||
break; | |||||
case DTYPE_String: | |||||
if (DescriptorNumber == 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; | |||||
} | |||||
/* | |||||
LUFA Library | |||||
Copyright (C) Dean Camera, 2014. | |||||
dean [at] fourwalledcubicle [dot] com | |||||
www.lufa-lib.org | |||||
*/ | |||||
/* | |||||
Copyright 2014 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 0x94 | |||||
#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 uint8_t wIndex, | |||||
const void** const DescriptorAddress) | |||||
ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(3); | |||||
#endif | |||||
;************************************************************ | |||||
; Windows USB CDC ACM Setup File | |||||
; Copyright (c) 2000 Microsoft Corporation | |||||
;************************************************************ | |||||
[DefaultInstall] | |||||
CopyINF="LUFA CDC Bootloader.inf" | |||||
[Version] | |||||
Signature="$Windows NT$" | |||||
Class=Ports | |||||
ClassGuid={4D36E978-E325-11CE-BFC1-08002BE10318} | |||||
Provider=%MFGNAME% | |||||
DriverVer=7/1/2012,10.0.0.0 | |||||
[Manufacturer] | |||||
%MFGNAME%=DeviceList, NTx86, NTamd64, NTia64 | |||||
[SourceDisksNames] | |||||
[SourceDisksFiles] | |||||
[DestinationDirs] | |||||
DefaultDestDir=12 | |||||
[DriverInstall] | |||||
Include=mdmcpq.inf | |||||
CopyFiles=FakeModemCopyFileSection | |||||
AddReg=DriverInstall.AddReg | |||||
[DriverInstall.Services] | |||||
Include=mdmcpq.inf | |||||
AddService=usbser, 0x00000002, LowerFilter_Service_Inst | |||||
[DriverInstall.AddReg] | |||||
HKR,,EnumPropPages32,,"msports.dll,SerialPortPropPageProvider" | |||||
;------------------------------------------------------------------------------ | |||||
; Vendor and Product ID Definitions | |||||
;------------------------------------------------------------------------------ | |||||
; When developing your USB device, the VID and PID used in the PC side | |||||
; application program and the firmware on the microcontroller must match. | |||||
; Modify the below line to use your VID and PID. Use the format as shown below. | |||||
; Note: One INF file can be used for multiple devices with different VID and PIDs. | |||||
; For each supported device, append ",USB\VID_xxxx&PID_yyyy" to the end of the line. | |||||
;------------------------------------------------------------------------------ | |||||
[DeviceList] | |||||
%DESCRIPTION%=DriverInstall, USB\VID_03EB&PID_204A | |||||
[DeviceList.NTx86] | |||||
%DESCRIPTION%=DriverInstall, USB\VID_03EB&PID_204A | |||||
[DeviceList.NTamd64] | |||||
%DESCRIPTION%=DriverInstall, USB\VID_03EB&PID_204A | |||||
[DeviceList.NTia64] | |||||
%DESCRIPTION%=DriverInstall, USB\VID_03EB&PID_204A | |||||
;------------------------------------------------------------------------------ | |||||
; String Definitions | |||||
;------------------------------------------------------------------------------ | |||||
;Modify these strings to customize your device | |||||
;------------------------------------------------------------------------------ | |||||
[Strings] | |||||
MFGNAME="http://www.lufa-lib.org" | |||||
DESCRIPTION="LUFA CDC Class Bootloader" |
<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> |
# | |||||
# LUFA Library | |||||
# Copyright (C) Dean Camera, 2014. | |||||
# | |||||
# 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 build script makefiles | |||||
include $(LUFA_PATH)/Build/lufa_core.mk | |||||
include $(LUFA_PATH)/Build/lufa_sources.mk | |||||
include $(LUFA_PATH)/Build/lufa_build.mk | |||||
include $(LUFA_PATH)/Build/lufa_cppcheck.mk | |||||
include $(LUFA_PATH)/Build/lufa_doxygen.mk | |||||
include $(LUFA_PATH)/Build/lufa_avrdude.mk | |||||
include $(LUFA_PATH)/Build/lufa_atprogram.mk |
/* | |||||
LUFA Library | |||||
Copyright (C) Dean Camera, 2014. | |||||
dean [at] fourwalledcubicle [dot] com | |||||
www.lufa-lib.org | |||||
*/ | |||||
/* | |||||
Copyright 2014 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); | |||||
} | |||||
/* | |||||
LUFA Library | |||||
Copyright (C) Dean Camera, 2014. | |||||
dean [at] fourwalledcubicle [dot] com | |||||
www.lufa-lib.org | |||||
*/ | |||||
/* | |||||
Copyright 2014 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 | |||||
/* | |||||
LUFA Library | |||||
Copyright (C) Dean Camera, 2014. | |||||
dean [at] fourwalledcubicle [dot] com | |||||
www.lufa-lib.org | |||||
*/ | |||||
/* | |||||
Copyright 2014 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 |
/* | |||||
LUFA Library | |||||
Copyright (C) Dean Camera, 2014. | |||||
dean [at] fourwalledcubicle [dot] com | |||||
www.lufa-lib.org | |||||
*/ | |||||
/* | |||||
Copyright 2014 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_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(); | |||||
#endif | |||||
/* 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)) | |||||
JumpToApplication |= true; | |||||
/* If a request has been made to jump to the user application, honor it */ | |||||
if (JumpToApplication) | |||||
{ | |||||
/* 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); | |||||
/* Enable global interrupts so that the USB stack can function */ | |||||
GlobalInterruptEnable(); | |||||
/* Run the USB management task while the bootloader is supposed to be running */ | |||||
while (RunBootloader || WaitForExit) | |||||
USB_USBTask(); | |||||
/* Reset configured hardware back to their original states for the user application */ | |||||
ResetHardware(); | |||||
/* Start the user application */ | |||||
AppStartPtr(); | |||||
} | |||||
/** Configures all hardware required for the bootloader. */ | |||||
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)); | |||||
} | |||||
/** 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; | |||||
} | |||||
/** 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_write_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 */ | |||||
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]; | |||||
if (IS_ONEBYTE_COMMAND(SentCommand.Data, 0x00)) // Read bootloader info | |||||
{ | |||||
ResponseByte = BootloaderInfo[DataIndexToRead]; | |||||
} | |||||
else if (IS_ONEBYTE_COMMAND(SentCommand.Data, 0x01)) // Read signature byte | |||||
{ | |||||
if (DataIndexToRead < 0x60) | |||||
ResponseByte = SignatureInfo[DataIndexToRead - 0x30]; | |||||
else | |||||
ResponseByte = SignatureInfo[DataIndexToRead - 0x60 + 3]; | |||||
} | |||||
} | |||||
/* | |||||
LUFA Library | |||||
Copyright (C) Dean Camera, 2014. | |||||
dean [at] fourwalledcubicle [dot] com | |||||
www.lufa-lib.org | |||||
*/ | |||||
/* | |||||
Copyright 2014 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 | |||||
/** \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 | |||||
* | |||||
* This bootloader is designed to be started via the HWB mechanism of the USB AVRs; ground the HWB pin (see device | |||||
* datasheet) then momentarily ground /RESET to start the bootloader. This assumes the HWBE fuse is set and the BOOTRST | |||||
* fuse is cleared. | |||||
* | |||||
* 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. | |||||
* | |||||
* \par After loading an application, it is not run automatically on startup. | |||||
* Some USB AVR boards ship with the BOOTRST fuse set, causing the bootloader | |||||
* to run automatically when the device is reset. In most cases, the BOOTRST | |||||
* fuse should be disabled and the HWBE fuse used instead to run the bootloader | |||||
* when needed. | |||||
* | |||||
* \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> | |||||
*/ | |||||
/* | |||||
LUFA Library | |||||
Copyright (C) Dean Camera, 2014. | |||||
dean [at] fourwalledcubicle [dot] com | |||||
www.lufa-lib.org | |||||
*/ | |||||
/* | |||||
Copyright 2014 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 |
/* | |||||
LUFA Library | |||||
Copyright (C) Dean Camera, 2014. | |||||
dean [at] fourwalledcubicle [dot] com | |||||
www.lufa-lib.org | |||||
*/ | |||||
/* | |||||
Copyright 2014 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 |
/* | |||||
LUFA Library | |||||
Copyright (C) Dean Camera, 2014. | |||||
dean [at] fourwalledcubicle [dot] com | |||||
www.lufa-lib.org | |||||
*/ | |||||
/* | |||||
Copyright 2014 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"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 DFU"); | |||||
/** This function is called by the library when in device mode, and must be overridden (see library "USB Descriptors" | |||||
* documentation) by the application code so that the address and size of a requested descriptor can be given | |||||
* to the USB library. When the device receives a Get Descriptor request on the control endpoint, this function | |||||
* is called so that the descriptor details can be passed back and the appropriate descriptor sent back to the | |||||
* USB host. | |||||
*/ | |||||
uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue, | |||||
const uint8_t wIndex, | |||||
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; | |||||
} | |||||
/* | |||||
LUFA Library | |||||
Copyright (C) Dean Camera, 2014. | |||||
dean [at] fourwalledcubicle [dot] com | |||||
www.lufa-lib.org | |||||
*/ | |||||
/* | |||||
Copyright 2014 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 0x94 | |||||
#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 uint8_t wIndex, | |||||
const void** const DescriptorAddress) | |||||
ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(3); | |||||
#endif | |||||
<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> |
# | |||||
# LUFA Library | |||||
# Copyright (C) Dean Camera, 2014. | |||||
# | |||||
# 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 = 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 = 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 build script makefiles | |||||
include $(LUFA_PATH)/Build/lufa_core.mk | |||||
include $(LUFA_PATH)/Build/lufa_sources.mk | |||||
include $(LUFA_PATH)/Build/lufa_build.mk | |||||
include $(LUFA_PATH)/Build/lufa_cppcheck.mk | |||||
include $(LUFA_PATH)/Build/lufa_doxygen.mk | |||||
include $(LUFA_PATH)/Build/lufa_avrdude.mk | |||||
include $(LUFA_PATH)/Build/lufa_atprogram.mk |
/* | |||||
LUFA Library | |||||
Copyright (C) Dean Camera, 2014. | |||||
dean [at] fourwalledcubicle [dot] com | |||||
www.lufa-lib.org | |||||
*/ | |||||
/* | |||||
Copyright 2014 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)) | |||||
{ | |||||
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(); | |||||
/* 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 | |||||
{ | |||||
/* 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; | |||||
} | |||||
} | |||||
/* | |||||
LUFA Library | |||||
Copyright (C) Dean Camera, 2014. | |||||
dean [at] fourwalledcubicle [dot] com | |||||
www.lufa-lib.org | |||||
*/ | |||||
/* | |||||
Copyright 2014 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); | |||||
void EVENT_USB_Device_UnhandledControlRequest(void); | |||||
#endif | |||||
/** \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 HWB mechanism of the USB AVRs; ground the HWB pin (see device | |||||
* datasheet) then momentarily ground /RESET to start the bootloader. This assumes the HWBE fuse is set and the 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 non-compatible with the cross-platform loader GUI. 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 BOOTRST fuse set, causing the bootloader | |||||
* to run automatically when the device is reset. In most cases, the BOOTRST | |||||
* fuse should 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> | |||||
*/ |
/* | |||||
LUFA Library | |||||
Copyright (C) Dean Camera, 2014. | |||||
dean [at] fourwalledcubicle [dot] com | |||||
www.lufa-lib.org | |||||
*/ | |||||
/* | |||||
Copyright 2014 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 |
/* | |||||
LUFA Library | |||||
Copyright (C) Dean Camera, 2014. | |||||
dean [at] fourwalledcubicle [dot] com | |||||
www.lufa-lib.org | |||||
*/ | |||||
/* | |||||
Copyright 2014 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_Printer, | |||||
.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 uint8_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 | |||||
{ | |||||
Address = &HIDReport; | |||||
Size = sizeof(HIDReport); | |||||
} | |||||
*DescriptorAddress = Address; | |||||
return Size; | |||||
} | |||||
/* | |||||
LUFA Library | |||||
Copyright (C) Dean Camera, 2014. | |||||
dean [at] fourwalledcubicle [dot] com | |||||
www.lufa-lib.org | |||||
*/ | |||||
/* | |||||
Copyright 2014 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_Printer = 0, /**< Printer 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 uint8_t wIndex, | |||||
const void** const DescriptorAddress) | |||||
ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(3); | |||||
#endif | |||||
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 | |||||
hid_bootloader_cli.exe: hid_bootloader_cli.c | |||||
$(CC) $(CFLAGS) -s -DUSE_WIN32 -o hid_bootloader_cli.exe hid_bootloader_cli.c -lhid -lsetupapi | |||||
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 |
OS ?= FreeBSD | |||||
#OS ?= NetBSD | |||||
#OS ?= OpenBSD | |||||
CFLAGS ?= -O2 -Wall | |||||
CC ?= gcc | |||||
.if $(OS) == "FreeBSD" | |||||
CFLAGS += -DUSE_LIBUSB | |||||
LIBS = -lusb | |||||
.elif $(OS) == "NetBSD" || $(OS) == "OpenBSD" | |||||
CFLAGS += -DUSE_UHID | |||||
LIBS = | |||||
.endif | |||||
hid_bootloader_cli: hid_bootloader_cli.c | |||||
$(CC) $(CFLAGS) -s -o hid_bootloader_cli hid_bootloader_cli.c $(LIBS) | |||||
clean: | |||||
rm -f hid_bootloader_cli |
GNU GENERAL PUBLIC LICENSE | |||||
Version 3, 29 June 2007 | |||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> | |||||
Everyone is permitted to copy and distribute verbatim copies | |||||
of this license document, but changing it is not allowed. | |||||
Preamble | |||||
The GNU General Public License is a free, copyleft license for | |||||
software and other kinds of works. | |||||
The licenses for most software and other practical works are designed | |||||
to take away your freedom to share and change the works. By contrast, | |||||
the GNU General Public License is intended to guarantee your freedom to | |||||
share and change all versions of a program--to make sure it remains free | |||||
software for all its users. We, the Free Software Foundation, use the | |||||
GNU General Public License for most of our software; it applies also to | |||||
any other work released this way by its authors. You can apply it to | |||||
your programs, too. | |||||
When we speak of free software, we are referring to freedom, not | |||||
price. Our General Public Licenses are designed to make sure that you | |||||
have the freedom to distribute copies of free software (and charge for | |||||
them if you wish), that you receive source code or can get it if you | |||||
want it, that you can change the software or use pieces of it in new | |||||
free programs, and that you know you can do these things. | |||||
To protect your rights, we need to prevent others from denying you | |||||
these rights or asking you to surrender the rights. Therefore, you have | |||||
certain responsibilities if you distribute copies of the software, or if | |||||
you modify it: responsibilities to respect the freedom of others. | |||||
For example, if you distribute copies of such a program, whether | |||||
gratis or for a fee, you must pass on to the recipients the same | |||||
freedoms that you received. You must make sure that they, too, receive | |||||
or can get the source code. And you must show them these terms so they | |||||
know their rights. | |||||
Developers that use the GNU GPL protect your rights with two steps: | |||||
(1) assert copyright on the software, and (2) offer you this License | |||||
giving you legal permission to copy, distribute and/or modify it. | |||||
For the developers' and authors' protection, the GPL clearly explains | |||||
that there is no warranty for this free software. For both users' and | |||||
authors' sake, the GPL requires that modified versions be marked as | |||||
changed, so that their problems will not be attributed erroneously to | |||||
authors of previous versions. | |||||
Some devices are designed to deny users access to install or run | |||||
modified versions of the software inside them, although the manufacturer | |||||
can do so. This is fundamentally incompatible with the aim of | |||||
protecting users' freedom to change the software. The systematic | |||||
pattern of such abuse occurs in the area of products for individuals to | |||||
use, which is precisely where it is most unacceptable. Therefore, we | |||||
have designed this version of the GPL to prohibit the practice for those | |||||
products. If such problems arise substantially in other domains, we | |||||
stand ready to extend this provision to those domains in future versions | |||||
of the GPL, as needed to protect the freedom of users. | |||||
Finally, every program is threatened constantly by software patents. | |||||
States should not allow patents to restrict development and use of | |||||
software on general-purpose computers, but in those that do, we wish to | |||||
avoid the special danger that patents applied to a free program could | |||||
make it effectively proprietary. To prevent this, the GPL assures that | |||||
patents cannot be used to render the program non-free. | |||||
The precise terms and conditions for copying, distribution and | |||||
modification follow. | |||||
TERMS AND CONDITIONS | |||||
0. Definitions. | |||||
"This License" refers to version 3 of the GNU General Public License. | |||||
"Copyright" also means copyright-like laws that apply to other kinds of | |||||
works, such as semiconductor masks. | |||||
"The Program" refers to any copyrightable work licensed under this | |||||
License. Each licensee is addressed as "you". "Licensees" and | |||||
"recipients" may be individuals or organizations. | |||||
To "modify" a work means to copy from or adapt all or part of the work | |||||
in a fashion requiring copyright permission, other than the making of an | |||||
exact copy. The resulting work is called a "modified version" of the | |||||
earlier work or a work "based on" the earlier work. | |||||
A "covered work" means either the unmodified Program or a work based | |||||
on the Program. | |||||
To "propagate" a work means to do anything with it that, without | |||||
permission, would make you directly or secondarily liable for | |||||
infringement under applicable copyright law, except executing it on a | |||||
computer or modifying a private copy. Propagation includes copying, | |||||
distribution (with or without modification), making available to the | |||||
public, and in some countries other activities as well. | |||||
To "convey" a work means any kind of propagation that enables other | |||||
parties to make or receive copies. Mere interaction with a user through | |||||
a computer network, with no transfer of a copy, is not conveying. | |||||
An interactive user interface displays "Appropriate Legal Notices" | |||||
to the extent that it includes a convenient and prominently visible | |||||
feature that (1) displays an appropriate copyright notice, and (2) | |||||
tells the user that there is no warranty for the work (except to the | |||||
extent that warranties are provided), that licensees may convey the | |||||
work under this License, and how to view a copy of this License. If | |||||
the interface presents a list of user commands or options, such as a | |||||
menu, a prominent item in the list meets this criterion. | |||||
1. Source Code. | |||||
The "source code" for a work means the preferred form of the work | |||||
for making modifications to it. "Object code" means any non-source | |||||
form of a work. | |||||
A "Standard Interface" means an interface that either is an official | |||||
standard defined by a recognized standards body, or, in the case of | |||||
interfaces specified for a particular programming language, one that | |||||
is widely used among developers working in that language. | |||||
The "System Libraries" of an executable work include anything, other | |||||
than the work as a whole, that (a) is included in the normal form of | |||||
packaging a Major Component, but which is not part of that Major | |||||
Component, and (b) serves only to enable use of the work with that | |||||
Major Component, or to implement a Standard Interface for which an | |||||
implementation is available to the public in source code form. A | |||||
"Major Component", in this context, means a major essential component | |||||
(kernel, window system, and so on) of the specific operating system | |||||
(if any) on which the executable work runs, or a compiler used to | |||||
produce the work, or an object code interpreter used to run it. | |||||
The "Corresponding Source" for a work in object code form means all | |||||
the source code needed to generate, install, and (for an executable | |||||
work) run the object code and to modify the work, including scripts to | |||||
control those activities. However, it does not include the work's | |||||
System Libraries, or general-purpose tools or generally available free | |||||
programs which are used unmodified in performing those activities but | |||||
which are not part of the work. For example, Corresponding Source | |||||
includes interface definition files associated with source files for | |||||
the work, and the source code for shared libraries and dynamically | |||||
linked subprograms that the work is specifically designed to require, | |||||
such as by intimate data communication or control flow between those | |||||
subprograms and other parts of the work. | |||||
The Corresponding Source need not include anything that users | |||||
can regenerate automatically from other parts of the Corresponding | |||||
Source. | |||||
The Corresponding Source for a work in source code form is that | |||||
same work. | |||||
2. Basic Permissions. | |||||
All rights granted under this License are granted for the term of | |||||
copyright on the Program, and are irrevocable provided the stated | |||||
conditions are met. This License explicitly affirms your unlimited | |||||
permission to run the unmodified Program. The output from running a | |||||
covered work is covered by this License only if the output, given its | |||||
content, constitutes a covered work. This License acknowledges your | |||||
rights of fair use or other equivalent, as provided by copyright law. | |||||
You may make, run and propagate covered works that you do not | |||||
convey, without conditions so long as your license otherwise remains | |||||
in force. You may convey covered works to others for the sole purpose | |||||
of having them make modifications exclusively for you, or provide you | |||||
with facilities for running those works, provided that you comply with | |||||
the terms of this License in conveying all material for which you do | |||||
not control copyright. Those thus making or running the covered works | |||||
for you must do so exclusively on your behalf, under your direction | |||||
and control, on terms that prohibit them from making any copies of | |||||
your copyrighted material outside their relationship with you. | |||||
Conveying under any other circumstances is permitted solely under | |||||
the conditions stated below. Sublicensing is not allowed; section 10 | |||||
makes it unnecessary. | |||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law. | |||||
No covered work shall be deemed part of an effective technological | |||||
measure under any applicable law fulfilling obligations under article | |||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or | |||||
similar laws prohibiting or restricting circumvention of such | |||||
measures. | |||||
When you convey a covered work, you waive any legal power to forbid | |||||
circumvention of technological measures to the extent such circumvention | |||||
is effected by exercising rights under this License with respect to | |||||
the covered work, and you disclaim any intention to limit operation or | |||||
modification of the work as a means of enforcing, against the work's | |||||
users, your or third parties' legal rights to forbid circumvention of | |||||
technological measures. | |||||
4. Conveying Verbatim Copies. | |||||
You may convey verbatim copies of the Program's source code as you | |||||
receive it, in any medium, provided that you conspicuously and | |||||
appropriately publish on each copy an appropriate copyright notice; | |||||
keep intact all notices stating that this License and any | |||||
non-permissive terms added in accord with section 7 apply to the code; | |||||
keep intact all notices of the absence of any warranty; and give all | |||||
recipients a copy of this License along with the Program. | |||||
You may charge any price or no price for each copy that you convey, | |||||
and you may offer support or warranty protection for a fee. | |||||
5. Conveying Modified Source Versions. | |||||
You may convey a work based on the Program, or the modifications to | |||||
produce it from the Program, in the form of source code under the | |||||
terms of section 4, provided that you also meet all of these conditions: | |||||
a) The work must carry prominent notices stating that you modified | |||||
it, and giving a relevant date. | |||||
b) The work must carry prominent notices stating that it is | |||||
released under this License and any conditions added under section | |||||
7. This requirement modifies the requirement in section 4 to | |||||
"keep intact all notices". | |||||
c) You must license the entire work, as a whole, under this | |||||
License to anyone who comes into possession of a copy. This | |||||
License will therefore apply, along with any applicable section 7 | |||||
additional terms, to the whole of the work, and all its parts, | |||||
regardless of how they are packaged. This License gives no | |||||
permission to license the work in any other way, but it does not | |||||
invalidate such permission if you have separately received it. | |||||
d) If the work has interactive user interfaces, each must display | |||||
Appropriate Legal Notices; however, if the Program has interactive | |||||
interfaces that do not display Appropriate Legal Notices, your | |||||
work need not make them do so. | |||||
A compilation of a covered work with other separate and independent | |||||
works, which are not by their nature extensions of the covered work, | |||||
and which are not combined with it such as to form a larger program, | |||||
in or on a volume of a storage or distribution medium, is called an | |||||
"aggregate" if the compilation and its resulting copyright are not | |||||
used to limit the access or legal rights of the compilation's users | |||||
beyond what the individual works permit. Inclusion of a covered work | |||||
in an aggregate does not cause this License to apply to the other | |||||
parts of the aggregate. | |||||
6. Conveying Non-Source Forms. | |||||
You may convey a covered work in object code form under the terms | |||||
of sections 4 and 5, provided that you also convey the | |||||
machine-readable Corresponding Source under the terms of this License, | |||||
in one of these ways: | |||||
a) Convey the object code in, or embodied in, a physical product | |||||
(including a physical distribution medium), accompanied by the | |||||
Corresponding Source fixed on a durable physical medium | |||||
customarily used for software interchange. | |||||
b) Convey the object code in, or embodied in, a physical product | |||||
(including a physical distribution medium), accompanied by a | |||||
written offer, valid for at least three years and valid for as | |||||
long as you offer spare parts or customer support for that product | |||||
model, to give anyone who possesses the object code either (1) a | |||||
copy of the Corresponding Source for all the software in the | |||||
product that is covered by this License, on a durable physical | |||||
medium customarily used for software interchange, for a price no | |||||
more than your reasonable cost of physically performing this | |||||
conveying of source, or (2) access to copy the | |||||
Corresponding Source from a network server at no charge. | |||||
c) Convey individual copies of the object code with a copy of the | |||||
written offer to provide the Corresponding Source. This | |||||
alternative is allowed only occasionally and noncommercially, and | |||||
only if you received the object code with such an offer, in accord | |||||
with subsection 6b. | |||||
d) Convey the object code by offering access from a designated | |||||
place (gratis or for a charge), and offer equivalent access to the | |||||
Corresponding Source in the same way through the same place at no | |||||
further charge. You need not require recipients to copy the | |||||
Corresponding Source along with the object code. If the place to | |||||
copy the object code is a network server, the Corresponding Source | |||||
may be on a different server (operated by you or a third party) | |||||
that supports equivalent copying facilities, provided you maintain | |||||
clear directions next to the object code saying where to find the | |||||
Corresponding Source. Regardless of what server hosts the | |||||
Corresponding Source, you remain obligated to ensure that it is | |||||
available for as long as needed to satisfy these requirements. | |||||
e) Convey the object code using peer-to-peer transmission, provided | |||||
you inform other peers where the object code and Corresponding | |||||
Source of the work are being offered to the general public at no | |||||
charge under subsection 6d. | |||||
A separable portion of the object code, whose source code is excluded | |||||
from the Corresponding Source as a System Library, need not be | |||||
included in conveying the object code work. | |||||
A "User Product" is either (1) a "consumer product", which means any | |||||
tangible personal property which is normally used for personal, family, | |||||
or household purposes, or (2) anything designed or sold for incorporation | |||||
into a dwelling. In determining whether a product is a consumer product, | |||||
doubtful cases shall be resolved in favor of coverage. For a particular | |||||
product received by a particular user, "normally used" refers to a | |||||
typical or common use of that class of product, regardless of the status | |||||
of the particular user or of the way in which the particular user | |||||
actually uses, or expects or is expected to use, the product. A product | |||||
is a consumer product regardless of whether the product has substantial | |||||
commercial, industrial or non-consumer uses, unless such uses represent | |||||
the only significant mode of use of the product. | |||||
"Installation Information" for a User Product means any methods, | |||||
procedures, authorization keys, or other information required to install | |||||
and execute modified versions of a covered work in that User Product from | |||||
a modified version of its Corresponding Source. The information must | |||||
suffice to ensure that the continued functioning of the modified object | |||||
code is in no case prevented or interfered with solely because | |||||
modification has been made. | |||||
If you convey an object code work under this section in, or with, or | |||||
specifically for use in, a User Product, and the conveying occurs as | |||||
part of a transaction in which the right of possession and use of the | |||||
User Product is transferred to the recipient in perpetuity or for a | |||||
fixed term (regardless of how the transaction is characterized), the | |||||
Corresponding Source conveyed under this section must be accompanied | |||||
by the Installation Information. But this requirement does not apply | |||||
if neither you nor any third party retains the ability to install | |||||
modified object code on the User Product (for example, the work has | |||||
been installed in ROM). | |||||
The requirement to provide Installation Information does not include a | |||||
requirement to continue to provide support service, warranty, or updates | |||||
for a work that has been modified or installed by the recipient, or for | |||||
the User Product in which it has been modified or installed. Access to a | |||||
network may be denied when the modification itself materially and | |||||
adversely affects the operation of the network or violates the rules and | |||||
protocols for communication across the network. | |||||
Corresponding Source conveyed, and Installation Information provided, | |||||
in accord with this section must be in a format that is publicly | |||||
documented (and with an implementation available to the public in | |||||
source code form), and must require no special password or key for | |||||
unpacking, reading or copying. | |||||
7. Additional Terms. | |||||
"Additional permissions" are terms that supplement the terms of this | |||||
License by making exceptions from one or more of its conditions. | |||||
Additional permissions that are applicable to the entire Program shall | |||||
be treated as though they were included in this License, to the extent | |||||
that they are valid under applicable law. If additional permissions | |||||
apply only to part of the Program, that part may be used separately | |||||
under those permissions, but the entire Program remains governed by | |||||
this License without regard to the additional permissions. | |||||
When you convey a copy of a covered work, you may at your option | |||||
remove any additional permissions from that copy, or from any part of | |||||
it. (Additional permissions may be written to require their own | |||||
removal in certain cases when you modify the work.) You may place | |||||
additional permissions on material, added by you to a covered work, | |||||
for which you have or can give appropriate copyright permission. | |||||
Notwithstanding any other provision of this License, for material you | |||||
add to a covered work, you may (if authorized by the copyright holders of | |||||
that material) supplement the terms of this License with terms: | |||||
a) Disclaiming warranty or limiting liability differently from the | |||||
terms of sections 15 and 16 of this License; or | |||||
b) Requiring preservation of specified reasonable legal notices or | |||||
author attributions in that material or in the Appropriate Legal | |||||
Notices displayed by works containing it; or | |||||
c) Prohibiting misrepresentation of the origin of that material, or | |||||
requiring that modified versions of such material be marked in | |||||
reasonable ways as different from the original version; or | |||||
d) Limiting the use for publicity purposes of names of licensors or | |||||
authors of the material; or | |||||
e) Declining to grant rights under trademark law for use of some | |||||
trade names, trademarks, or service marks; or | |||||
f) Requiring indemnification of licensors and authors of that | |||||
material by anyone who conveys the material (or modified versions of | |||||
it) with contractual assumptions of liability to the recipient, for | |||||
any liability that these contractual assumptions directly impose on | |||||
those licensors and authors. | |||||
All other non-permissive additional terms are considered "further | |||||
restrictions" within the meaning of section 10. If the Program as you | |||||
received it, or any part of it, contains a notice stating that it is | |||||
governed by this License along with a term that is a further | |||||
restriction, you may remove that term. If a license document contains | |||||
a further restriction but permits relicensing or conveying under this | |||||
License, you may add to a covered work material governed by the terms | |||||
of that license document, provided that the further restriction does | |||||
not survive such relicensing or conveying. | |||||
If you add terms to a covered work in accord with this section, you | |||||
must place, in the relevant source files, a statement of the | |||||
additional terms that apply to those files, or a notice indicating | |||||
where to find the applicable terms. | |||||
Additional terms, permissive or non-permissive, may be stated in the | |||||
form of a separately written license, or stated as exceptions; | |||||
the above requirements apply either way. | |||||
8. Termination. | |||||
You may not propagate or modify a covered work except as expressly | |||||
provided under this License. Any attempt otherwise to propagate or | |||||
modify it is void, and will automatically terminate your rights under | |||||
this License (including any patent licenses granted under the third | |||||
paragraph of section 11). | |||||
However, if you cease all violation of this License, then your | |||||
license from a particular copyright holder is reinstated (a) | |||||
provisionally, unless and until the copyright holder explicitly and | |||||
finally terminates your license, and (b) permanently, if the copyright | |||||
holder fails to notify you of the violation by some reasonable means | |||||
prior to 60 days after the cessation. | |||||
Moreover, your license from a particular copyright holder is | |||||
reinstated permanently if the copyright holder notifies you of the | |||||
violation by some reasonable means, this is the first time you have | |||||
received notice of violation of this License (for any work) from that | |||||
copyright holder, and you cure the violation prior to 30 days after | |||||
your receipt of the notice. | |||||
Termination of your rights under this section does not terminate the | |||||
licenses of parties who have received copies or rights from you under | |||||
this License. If your rights have been terminated and not permanently | |||||
reinstated, you do not qualify to receive new licenses for the same | |||||
material under section 10. | |||||
9. Acceptance Not Required for Having Copies. | |||||
You are not required to accept this License in order to receive or | |||||
run a copy of the Program. Ancillary propagation of a covered work | |||||
occurring solely as a consequence of using peer-to-peer transmission | |||||
to receive a copy likewise does not require acceptance. However, | |||||
nothing other than this License grants you permission to propagate or | |||||
modify any covered work. These actions infringe copyright if you do | |||||
not accept this License. Therefore, by modifying or propagating a | |||||
covered work, you indicate your acceptance of this License to do so. | |||||
10. Automatic Licensing of Downstream Recipients. | |||||
Each time you convey a covered work, the recipient automatically | |||||
receives a license from the original licensors, to run, modify and | |||||
propagate that work, subject to this License. You are not responsible | |||||
for enforcing compliance by third parties with this License. | |||||
An "entity transaction" is a transaction transferring control of an | |||||
organization, or substantially all assets of one, or subdividing an | |||||
organization, or merging organizations. If propagation of a covered | |||||
work results from an entity transaction, each party to that | |||||
transaction who receives a copy of the work also receives whatever | |||||
licenses to the work the party's predecessor in interest had or could | |||||
give under the previous paragraph, plus a right to possession of the | |||||
Corresponding Source of the work from the predecessor in interest, if | |||||
the predecessor has it or can get it with reasonable efforts. | |||||
You may not impose any further restrictions on the exercise of the | |||||
rights granted or affirmed under this License. For example, you may | |||||
not impose a license fee, royalty, or other charge for exercise of | |||||
rights granted under this License, and you may not initiate litigation | |||||
(including a cross-claim or counterclaim in a lawsuit) alleging that | |||||
any patent claim is infringed by making, using, selling, offering for | |||||
sale, or importing the Program or any portion of it. | |||||
11. Patents. | |||||
A "contributor" is a copyright holder who authorizes use under this | |||||
License of the Program or a work on which the Program is based. The | |||||
work thus licensed is called the contributor's "contributor version". | |||||
A contributor's "essential patent claims" are all patent claims | |||||
owned or controlled by the contributor, whether already acquired or | |||||
hereafter acquired, that would be infringed by some manner, permitted | |||||
by this License, of making, using, or selling its contributor version, | |||||
but do not include claims that would be infringed only as a | |||||
consequence of further modification of the contributor version. For | |||||
purposes of this definition, "control" includes the right to grant | |||||
patent sublicenses in a manner consistent with the requirements of | |||||
this License. | |||||
Each contributor grants you a non-exclusive, worldwide, royalty-free | |||||
patent license under the contributor's essential patent claims, to | |||||
make, use, sell, offer for sale, import and otherwise run, modify and | |||||
propagate the contents of its contributor version. | |||||
In the following three paragraphs, a "patent license" is any express | |||||
agreement or commitment, however denominated, not to enforce a patent | |||||
(such as an express permission to practice a patent or covenant not to | |||||
sue for patent infringement). To "grant" such a patent license to a | |||||
party means to make such an agreement or commitment not to enforce a | |||||
patent against the party. | |||||
If you convey a covered work, knowingly relying on a patent license, | |||||
and the Corresponding Source of the work is not available for anyone | |||||
to copy, free of charge and under the terms of this License, through a | |||||
publicly available network server or other readily accessible means, | |||||
then you must either (1) cause the Corresponding Source to be so | |||||
available, or (2) arrange to deprive yourself of the benefit of the | |||||
patent license for this particular work, or (3) arrange, in a manner | |||||
consistent with the requirements of this License, to extend the patent | |||||
license to downstream recipients. "Knowingly relying" means you have | |||||
actual knowledge that, but for the patent license, your conveying the | |||||
covered work in a country, or your recipient's use of the covered work | |||||
in a country, would infringe one or more identifiable patents in that | |||||
country that you have reason to believe are valid. | |||||
If, pursuant to or in connection with a single transaction or | |||||
arrangement, you convey, or propagate by procuring conveyance of, a | |||||
covered work, and grant a patent license to some of the parties | |||||
receiving the covered work authorizing them to use, propagate, modify | |||||
or convey a specific copy of the covered work, then the patent license | |||||
you grant is automatically extended to all recipients of the covered | |||||
work and works based on it. | |||||
A patent license is "discriminatory" if it does not include within | |||||
the scope of its coverage, prohibits the exercise of, or is | |||||
conditioned on the non-exercise of one or more of the rights that are | |||||
specifically granted under this License. You may not convey a covered | |||||
work if you are a party to an arrangement with a third party that is | |||||
in the business of distributing software, under which you make payment | |||||
to the third party based on the extent of your activity of conveying | |||||
the work, and under which the third party grants, to any of the | |||||
parties who would receive the covered work from you, a discriminatory | |||||
patent license (a) in connection with copies of the covered work | |||||
conveyed by you (or copies made from those copies), or (b) primarily | |||||
for and in connection with specific products or compilations that | |||||
contain the covered work, unless you entered into that arrangement, | |||||
or that patent license was granted, prior to 28 March 2007. | |||||
Nothing in this License shall be construed as excluding or limiting | |||||
any implied license or other defenses to infringement that may | |||||
otherwise be available to you under applicable patent law. | |||||
12. No Surrender of Others' Freedom. | |||||
If conditions are imposed on you (whether by court order, agreement or | |||||
otherwise) that contradict the conditions of this License, they do not | |||||
excuse you from the conditions of this License. If you cannot convey a | |||||
covered work so as to satisfy simultaneously your obligations under this | |||||
License and any other pertinent obligations, then as a consequence you may | |||||
not convey it at all. For example, if you agree to terms that obligate you | |||||
to collect a royalty for further conveying from those to whom you convey | |||||
the Program, the only way you could satisfy both those terms and this | |||||
License would be to refrain entirely from conveying the Program. | |||||
13. Use with the GNU Affero General Public License. | |||||
Notwithstanding any other provision of this License, you have | |||||
permission to link or combine any covered work with a work licensed | |||||
under version 3 of the GNU Affero General Public License into a single | |||||
combined work, and to convey the resulting work. The terms of this | |||||
License will continue to apply to the part which is the covered work, | |||||
but the special requirements of the GNU Affero General Public License, | |||||
section 13, concerning interaction through a network will apply to the | |||||
combination as such. | |||||
14. Revised Versions of this License. | |||||
The Free Software Foundation may publish revised and/or new versions of | |||||
the GNU General Public License from time to time. Such new versions will | |||||
be similar in spirit to the present version, but may differ in detail to | |||||
address new problems or concerns. | |||||
Each version is given a distinguishing version number. If the | |||||
Program specifies that a certain numbered version of the GNU General | |||||
Public License "or any later version" applies to it, you have the | |||||
option of following the terms and conditions either of that numbered | |||||
version or of any later version published by the Free Software | |||||
Foundation. If the Program does not specify a version number of the | |||||
GNU General Public License, you may choose any version ever published | |||||
by the Free Software Foundation. | |||||
If the Program specifies that a proxy can decide which future | |||||
versions of the GNU General Public License can be used, that proxy's | |||||
public statement of acceptance of a version permanently authorizes you | |||||
to choose that version for the Program. | |||||
Later license versions may give you additional or different | |||||
permissions. However, no additional obligations are imposed on any | |||||
author or copyright holder as a result of your choosing to follow a | |||||
later version. | |||||
15. Disclaimer of Warranty. | |||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY | |||||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT | |||||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY | |||||
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, | |||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM | |||||
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF | |||||
ALL NECESSARY SERVICING, REPAIR OR CORRECTION. | |||||
16. Limitation of Liability. | |||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING | |||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS | |||||
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY | |||||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE | |||||
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF | |||||
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD | |||||
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), | |||||
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF | |||||
SUCH DAMAGES. | |||||
17. Interpretation of Sections 15 and 16. | |||||
If the disclaimer of warranty and limitation of liability provided | |||||
above cannot be given local legal effect according to their terms, | |||||
reviewing courts shall apply local law that most closely approximates | |||||
an absolute waiver of all civil liability in connection with the | |||||
Program, unless a warranty or assumption of liability accompanies a | |||||
copy of the Program in return for a fee. | |||||
END OF TERMS AND CONDITIONS | |||||
How to Apply These Terms to Your New Programs | |||||
If you develop a new program, and you want it to be of the greatest | |||||
possible use to the public, the best way to achieve this is to make it | |||||
free software which everyone can redistribute and change under these terms. | |||||
To do so, attach the following notices to the program. It is safest | |||||
to attach them to the start of each source file to most effectively | |||||
state the exclusion of warranty; and each file should have at least | |||||
the "copyright" line and a pointer to where the full notice is found. | |||||
<one line to give the program's name and a brief idea of what it does.> | |||||
Copyright (C) <year> <name of author> | |||||
This program is free software: you can redistribute it and/or modify | |||||
it under the terms of the GNU General Public License as published by | |||||
the Free Software Foundation, either version 3 of the License, or | |||||
(at your option) any later version. | |||||
This program is distributed in the hope that it will be useful, | |||||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
GNU General Public License for more details. | |||||
You should have received a copy of the GNU General Public License | |||||
along with this program. If not, see <http://www.gnu.org/licenses/>. | |||||
Also add information on how to contact you by electronic and paper mail. | |||||
If the program does terminal interaction, make it output a short | |||||
notice like this when it starts in an interactive mode: | |||||
<program> Copyright (C) <year> <name of author> | |||||
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. | |||||
This is free software, and you are welcome to redistribute it | |||||
under certain conditions; type `show c' for details. | |||||
The hypothetical commands `show w' and `show c' should show the appropriate | |||||
parts of the General Public License. Of course, your program's commands | |||||
might be different; for a GUI interface, you would use an "about box". | |||||
You should also get your employer (if you work as a programmer) or school, | |||||
if any, to sign a "copyright disclaimer" for the program, if necessary. | |||||
For more information on this, and how to apply and follow the GNU GPL, see | |||||
<http://www.gnu.org/licenses/>. | |||||
The GNU General Public License does not permit incorporating your program | |||||
into proprietary programs. If your program is a subroutine library, you | |||||
may consider it more useful to permit linking proprietary applications with | |||||
the library. If this is what you want to do, use the GNU Lesser General | |||||
Public License instead of this License. But first, please read | |||||
<http://www.gnu.org/philosophy/why-not-lgpl.html>. |
""" | |||||
LUFA Library | |||||
Copyright (C) Dean Camera, 2014. | |||||
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 (http://bialix.com/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) |
<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> |
# | |||||
# LUFA Library | |||||
# Copyright (C) Dean Camera, 2014. | |||||
# | |||||
# 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 -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 build script makefiles | |||||
include $(LUFA_PATH)/Build/lufa_core.mk | |||||
include $(LUFA_PATH)/Build/lufa_sources.mk | |||||
include $(LUFA_PATH)/Build/lufa_build.mk | |||||
include $(LUFA_PATH)/Build/lufa_cppcheck.mk | |||||
include $(LUFA_PATH)/Build/lufa_doxygen.mk | |||||
include $(LUFA_PATH)/Build/lufa_avrdude.mk | |||||
include $(LUFA_PATH)/Build/lufa_atprogram.mk |
/* | |||||
LUFA Library | |||||
Copyright (C) Dean Camera, 2014. | |||||
dean [at] fourwalledcubicle [dot] com | |||||
www.lufa-lib.org | |||||
*/ | |||||
/* | |||||
Copyright 2014 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); | |||||
} | |||||
/* | |||||
LUFA Library | |||||
Copyright (C) Dean Camera, 2014. | |||||
dean [at] fourwalledcubicle [dot] com | |||||
www.lufa-lib.org | |||||
*/ | |||||
/* | |||||
Copyright 2014 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 | |||||
/* | |||||
LUFA Library | |||||
Copyright (C) Dean Camera, 2014. | |||||
dean [at] fourwalledcubicle [dot] com | |||||
www.lufa-lib.org | |||||
*/ | |||||
/* | |||||
Copyright 2014 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 |
/* | |||||
LUFA Library | |||||
Copyright (C) Dean Camera, 2014. | |||||
dean [at] fourwalledcubicle [dot] com | |||||
www.lufa-lib.org | |||||
*/ | |||||
/* | |||||
Copyright 2014 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(); | |||||
#endif | |||||
/* 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)) | |||||
{ | |||||
MagicBootKey = 0; | |||||
JumpToApplication = true; | |||||
} | |||||
if (JumpToApplication) | |||||
{ | |||||
// 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; | |||||
} |
/* | |||||
LUFA Library | |||||
Copyright (C) Dean Camera, 2014. | |||||
dean [at] fourwalledcubicle [dot] com | |||||
www.lufa-lib.org | |||||
*/ | |||||
/* | |||||
Copyright 2014 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 | |||||
/** \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 | |||||
* | |||||
* This bootloader is designed to be started via the HWB mechanism of the USB AVRs; ground the HWB pin (see device | |||||
* datasheet) then momentarily ground /RESET to start the bootloader. This assumes the HWBE fuse is set and the BOOTRST | |||||
* fuse is cleared. | |||||
* | |||||
* 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. | |||||
* | |||||
* \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. | |||||
* | |||||
* \par After loading an application, it is not run automatically on startup. | |||||
* Some USB AVR boards ship with the BOOTRST fuse set, causing the bootloader | |||||
* to run automatically when the device is reset. In most cases, the BOOTRST | |||||
* fuse should be disabled and the HWBE fuse used instead to run the bootloader | |||||
* when needed. | |||||
* | |||||
* \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> | |||||
*/ | |||||
/* | |||||
LUFA Library | |||||
Copyright (C) Dean Camera, 2014. | |||||
dean [at] fourwalledcubicle [dot] com | |||||
www.lufa-lib.org | |||||
*/ | |||||
/* | |||||
Copyright 2014 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 |
/* | |||||
LUFA Library | |||||
Copyright (C) Dean Camera, 2014. | |||||
dean [at] fourwalledcubicle [dot] com | |||||
www.lufa-lib.org | |||||
*/ | |||||
/* | |||||
Copyright 2014 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 |
/* | |||||
LUFA Library | |||||
Copyright (C) Dean Camera, 2014. | |||||
dean [at] fourwalledcubicle [dot] com | |||||
www.lufa-lib.org | |||||
*/ | |||||
/* | |||||
Copyright 2014 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 uint8_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; | |||||
} | |||||
/* | |||||
LUFA Library | |||||
Copyright (C) Dean Camera, 2014. | |||||
dean [at] fourwalledcubicle [dot] com | |||||
www.lufa-lib.org | |||||
*/ | |||||
/* | |||||
Copyright 2014 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 uint8_t wIndex, | |||||
const void** const DescriptorAddress) | |||||
ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(3) AUX_BOOT_SECTION; | |||||
#endif | |||||
/* | |||||
LUFA Library | |||||
Copyright (C) Dean Camera, 2014. | |||||
dean [at] fourwalledcubicle [dot] com | |||||
www.lufa-lib.org | |||||
*/ | |||||
/* | |||||
Copyright 2014 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; | |||||
} | |||||
/* | |||||
LUFA Library | |||||
Copyright (C) Dean Camera, 2014. | |||||
dean [at] fourwalledcubicle [dot] com | |||||
www.lufa-lib.org | |||||
*/ | |||||
/* | |||||
Copyright 2014 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 | |||||
/* | |||||
LUFA Library | |||||
Copyright (C) Dean Camera, 2014. | |||||
dean [at] fourwalledcubicle [dot] com | |||||
www.lufa-lib.org | |||||
*/ | |||||
/* | |||||
Copyright 2014 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(); | |||||
} |
/* | |||||
LUFA Library | |||||
Copyright (C) Dean Camera, 2014. | |||||
dean [at] fourwalledcubicle [dot] com | |||||
www.lufa-lib.org | |||||
*/ | |||||
/* | |||||
Copyright 2014 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 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 n0 MSDOS Filename character 1 | |||||
* \param n1 MSDOS Filename character 2 | |||||
* \param n2 MSDOS Filename character 3 | |||||
* \param n3 MSDOS Filename character 4 | |||||
* \param n4 MSDOS Filename character 5 | |||||
* \param n5 MSDOS Filename character 6 | |||||
* \param n6 MSDOS Filename character 7 | |||||
* \param n7 MSDOS Filename character 8 | |||||
* \param e0 MSDOS Extension character 1 | |||||
* \param e1 MSDOS Extension character 2 | |||||
* \param 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 |
<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> |
# | |||||
# LUFA Library | |||||
# Copyright (C) Dean Camera, 2014. | |||||
# | |||||
# 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 build script makefiles | |||||
include $(LUFA_PATH)/Build/lufa_core.mk | |||||
include $(LUFA_PATH)/Build/lufa_sources.mk | |||||
include $(LUFA_PATH)/Build/lufa_build.mk | |||||
include $(LUFA_PATH)/Build/lufa_cppcheck.mk | |||||
include $(LUFA_PATH)/Build/lufa_doxygen.mk | |||||
include $(LUFA_PATH)/Build/lufa_avrdude.mk | |||||
include $(LUFA_PATH)/Build/lufa_atprogram.mk |
/* | |||||
LUFA Library | |||||
Copyright (C) Dean Camera, 2014. | |||||
dean [at] fourwalledcubicle [dot] com | |||||
www.lufa-lib.org | |||||
*/ | |||||
/* | |||||
Copyright 2014 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); | |||||
} |
/* | |||||
LUFA Library | |||||
Copyright (C) Dean Camera, 2014. | |||||
dean [at] fourwalledcubicle [dot] com | |||||
www.lufa-lib.org | |||||
*/ | |||||
/* | |||||
Copyright 2014 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 | |||||
/* | |||||
LUFA Library | |||||
Copyright (C) Dean Camera, 2014. | |||||
dean [at] fourwalledcubicle [dot] com | |||||
www.lufa-lib.org | |||||
*/ | |||||
/* | |||||
Copyright 2014 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 |
/* | |||||
LUFA Library | |||||
Copyright (C) Dean Camera, 2014. | |||||
dean [at] fourwalledcubicle [dot] com | |||||
www.lufa-lib.org | |||||
*/ | |||||
/* | |||||
Copyright 2014 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) | |||||
{ | |||||
/* 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)) | |||||
{ | |||||
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); | |||||
} |
/* | |||||
LUFA Library | |||||
Copyright (C) Dean Camera, 2014. | |||||
dean [at] fourwalledcubicle [dot] com | |||||
www.lufa-lib.org | |||||
*/ | |||||
/* | |||||
Copyright 2014 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 | |||||
/** \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 | |||||
* | |||||
* This bootloader is designed to be started via the HWB mechanism of the USB AVRs; ground the HWB pin (see device | |||||
* datasheet) then momentarily ground /RESET to start the bootloader. This assumes the HWBE fuse is set and the BOOTRST | |||||
* fuse is cleared. | |||||
* | |||||
* \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. | |||||
* | |||||
* \par After loading an application, it is not run automatically on startup. | |||||
* Some USB AVR boards ship with the BOOTRST fuse set, causing the bootloader | |||||
* to run automatically when the device is reset. In most cases, the BOOTRST | |||||
* fuse should be disabled and the HWBE fuse used instead to run the bootloader | |||||
* when needed. | |||||
* | |||||
* \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> | |||||
*/ | |||||
/* | |||||
LUFA Library | |||||
Copyright (C) Dean Camera, 2014. | |||||
dean [at] fourwalledcubicle [dot] com | |||||
www.lufa-lib.org | |||||
*/ | |||||
/* | |||||
Copyright 2014 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 |
/* | |||||
LUFA Library | |||||
Copyright (C) Dean Camera, 2014. | |||||
dean [at] fourwalledcubicle [dot] com | |||||
www.lufa-lib.org | |||||
*/ | |||||
/* | |||||
Copyright 2014 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 uint8_t wIndex, | |||||
const void** const DescriptorAddress) | |||||
{ | |||||
const uint8_t DescriptorType = (wValue >> 8); | |||||
const uint8_t DescriptorNumber = (wValue & 0xFF); | |||||
const void* Address = NULL; | |||||
uint16_t Size = NO_DESCRIPTOR; | |||||
switch (DescriptorType) | |||||
{ | |||||
case DTYPE_Device: | |||||
Address = &DeviceDescriptor; | |||||
Size = sizeof(USB_Descriptor_Device_t); | |||||
break; | |||||
case DTYPE_Configuration: | |||||
Address = &ConfigurationDescriptor; | |||||
Size = sizeof(USB_Descriptor_Configuration_t); | |||||
break; | |||||
case DTYPE_String: | |||||
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; | |||||
} | |||||
/* | |||||
LUFA Library | |||||
Copyright (C) Dean Camera, 2014. | |||||
dean [at] fourwalledcubicle [dot] com | |||||
www.lufa-lib.org | |||||
*/ | |||||
/* | |||||
Copyright 2014 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 uint8_t wIndex, | |||||
const void** const DescriptorAddress) | |||||
ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(3); | |||||
#endif | |||||
<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> |
# | |||||
# LUFA Library | |||||
# Copyright (C) Dean Camera, 2014. | |||||
# | |||||
# 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 build script makefiles | |||||
include $(LUFA_PATH)/Build/lufa_core.mk | |||||
include $(LUFA_PATH)/Build/lufa_sources.mk | |||||
include $(LUFA_PATH)/Build/lufa_build.mk | |||||
include $(LUFA_PATH)/Build/lufa_cppcheck.mk | |||||
include $(LUFA_PATH)/Build/lufa_doxygen.mk | |||||
include $(LUFA_PATH)/Build/lufa_avrdude.mk | |||||
include $(LUFA_PATH)/Build/lufa_atprogram.mk |
# | |||||
# LUFA Library | |||||
# Copyright (C) Dean Camera, 2014. | |||||
# | |||||
# 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) |
/* | |||||
LUFA Library | |||||
Copyright (C) Dean Camera, 2014. | |||||
dean [at] fourwalledcubicle [dot] com | |||||
www.lufa-lib.org | |||||
*/ | |||||
/* | |||||
Copyright 2014 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 | |||||
/** @} */ | |||||
/* | |||||
LUFA Library | |||||
Copyright (C) Dean Camera, 2014. | |||||
dean [at] fourwalledcubicle [dot] com | |||||
www.lufa-lib.org | |||||
*/ | |||||
/* | |||||
Copyright 2014 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 | |||||
/* | |||||
LUFA Library | |||||
Copyright (C) Dean Camera, 2014. | |||||
dean [at] fourwalledcubicle [dot] com | |||||
www.lufa-lib.org | |||||
*/ | |||||
/* | |||||
Copyright 2014 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 | |||||
/* | |||||
LUFA Library | |||||
Copyright (C) Dean Camera, 2014. | |||||
dean [at] fourwalledcubicle [dot] com | |||||
www.lufa-lib.org | |||||
*/ | |||||
/* | |||||
Copyright 2014 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 | |||||
/* | |||||
LUFA Library | |||||
Copyright (C) Dean Camera, 2014. | |||||
dean [at] fourwalledcubicle [dot] com | |||||
www.lufa-lib.org | |||||
*/ | |||||
/* | |||||
Copyright 2014 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 | |||||
# | |||||
# LUFA Library | |||||
# Copyright (C) Dean Camera, 2014. | |||||
# | |||||
# 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 : | |||||
# | |||||
# ----------------- 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 : | |||||
# |
/* | |||||
LUFA Library | |||||
Copyright (C) Dean Camera, 2014. | |||||
dean [at] fourwalledcubicle [dot] com | |||||
www.lufa-lib.org | |||||
*/ | |||||
/* | |||||
Copyright 2014 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; | |||||
} | |||||
# | |||||
# LUFA Library | |||||
# Copyright (C) Dean Camera, 2014. | |||||
# | |||||
# 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 LUFA build script makefiles | |||||
include $(LUFA_PATH)/Build/lufa_core.mk |
# | |||||
# LUFA Library | |||||
# Copyright (C) Dean Camera, 2014. | |||||
# | |||||
# 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 build script makefiles | |||||
include $(LUFA_PATH)/Build/lufa_build.mk |
# | |||||
# LUFA Library | |||||
# Copyright (C) Dean Camera, 2014. | |||||
# | |||||
# 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 : | |||||
# |
# | |||||
# LUFA Library | |||||
# Copyright (C) Dean Camera, 2014. | |||||
# | |||||
# 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 LUFA build script makefiles | |||||
include $(LUFA_PATH)/Build/lufa_core.mk |
/* | |||||
LUFA Library | |||||
Copyright (C) Dean Camera, 2014. | |||||
dean [at] fourwalledcubicle [dot] com | |||||
www.lufa-lib.org | |||||
*/ | |||||
/* | |||||
Copyright 2014 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: |
/* | |||||
LUFA Library | |||||
Copyright (C) Dean Camera, 2014. | |||||
dean [at] fourwalledcubicle [dot] com | |||||
www.lufa-lib.org | |||||
*/ | |||||
/* | |||||
Copyright 2014 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 |
/* | |||||
LUFA Library | |||||
Copyright (C) Dean Camera, 2014. | |||||
dean [at] fourwalledcubicle [dot] com | |||||
www.lufa-lib.org | |||||
*/ | |||||
/* | |||||
Copyright 2014 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" |
/* | |||||
LUFA Library | |||||
Copyright (C) Dean Camera, 2014. | |||||
dean [at] fourwalledcubicle [dot] com | |||||
www.lufa-lib.org | |||||
*/ | |||||
/* | |||||
Copyright 2014 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" |
# | |||||
# LUFA Library | |||||
# Copyright (C) Dean Camera, 2014. | |||||
# | |||||
# 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 LUFA build script makefiles | |||||
include $(LUFA_PATH)/Build/lufa_core.mk |