mirror of
https://github.com/qmk/qmk_firmware.git
synced 2025-06-05 07:52:42 +00:00
Update Mass Storage bootloader so that it can support devices with only 4KB bootloader sections by creating a special AUX section before the real bootloader section to store part of the bootloader code.
This commit is contained in:
parent
f8a1dc7424
commit
be33d3a515
@ -28,6 +28,19 @@
|
|||||||
this software.
|
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
|
; Trampolines to actual API implementations if the target address is outside the
|
||||||
; range of a rjmp instruction (can happen with large bootloader sections)
|
; range of a rjmp instruction (can happen with large bootloader sections)
|
||||||
.section .apitable_trampolines, "ax"
|
.section .apitable_trampolines, "ax"
|
||||||
|
@ -61,6 +61,25 @@ USB_ClassInfo_MS_Device_t Disk_MS_Interface =
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
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);
|
||||||
|
JumpToApplication |= ((PINC & (1 << 7)) != 0);
|
||||||
|
PORTC &= ~(1 << 7);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (JumpToApplication)
|
||||||
|
{
|
||||||
|
// cppcheck-suppress constStatement
|
||||||
|
((void (*)(void))0x0000)();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** Main program entry point. This routine configures the hardware required by the application, then
|
/** Main program entry point. This routine configures the hardware required by the application, then
|
||||||
* enters a loop to run the application tasks in sequence.
|
* enters a loop to run the application tasks in sequence.
|
||||||
*/
|
*/
|
||||||
@ -85,9 +104,6 @@ static void SetupHardware(void)
|
|||||||
MCUSR &= ~(1 << WDRF);
|
MCUSR &= ~(1 << WDRF);
|
||||||
wdt_disable();
|
wdt_disable();
|
||||||
|
|
||||||
/* Disable clock division */
|
|
||||||
clock_prescale_set(clock_div_1);
|
|
||||||
|
|
||||||
/* Relocate the interrupt vector table to the bootloader section */
|
/* Relocate the interrupt vector table to the bootloader section */
|
||||||
MCUCR = (1 << IVCE);
|
MCUCR = (1 << IVCE);
|
||||||
MCUCR = (1 << IVSEL);
|
MCUCR = (1 << IVSEL);
|
||||||
|
@ -39,7 +39,6 @@
|
|||||||
/* Includes: */
|
/* Includes: */
|
||||||
#include <avr/io.h>
|
#include <avr/io.h>
|
||||||
#include <avr/wdt.h>
|
#include <avr/wdt.h>
|
||||||
#include <avr/power.h>
|
|
||||||
#include <avr/interrupt.h>
|
#include <avr/interrupt.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
@ -67,14 +66,18 @@
|
|||||||
#define LEDMASK_USB_BUSY LEDS_LED2
|
#define LEDMASK_USB_BUSY LEDS_LED2
|
||||||
|
|
||||||
/* Function Prototypes: */
|
/* Function Prototypes: */
|
||||||
static void SetupHardware(void);
|
int main(void) AUX_BOOT_SECTION;
|
||||||
|
|
||||||
void EVENT_USB_Device_Connect(void);
|
static void SetupHardware(void) AUX_BOOT_SECTION;
|
||||||
void EVENT_USB_Device_Disconnect(void);
|
|
||||||
void EVENT_USB_Device_ConfigurationChanged(void);
|
|
||||||
void EVENT_USB_Device_ControlRequest(void);
|
|
||||||
|
|
||||||
bool CALLBACK_MS_Device_SCSICommandReceived(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo);
|
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;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -12,6 +12,8 @@
|
|||||||
*
|
*
|
||||||
* \li Series 7 USB AVRs (AT90USBxxx7)
|
* \li Series 7 USB AVRs (AT90USBxxx7)
|
||||||
* \li Series 6 USB AVRs (AT90USBxxx6)
|
* \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:
|
* \section Sec_Info USB Information:
|
||||||
*
|
*
|
||||||
@ -49,7 +51,7 @@
|
|||||||
* firmware image file, to load firmware onto the AVR.
|
* 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
|
* Out of the box this bootloader builds for the AT90USB1287 with an 8KB bootloader section size, and will fit
|
||||||
* into 8KB of bootloader space. If you wish to alter this size and/or change the AVR model, you will need to
|
* 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.
|
* 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
|
* When the bootloader is running, the board's LED(s) will flash at regular intervals to distinguish the
|
||||||
@ -100,6 +102,22 @@
|
|||||||
* #define BOOTLOADER_ADDRESS_LENGTH 4
|
* #define BOOTLOADER_ADDRESS_LENGTH 4
|
||||||
* \endcode
|
* \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
|
* \subsection SSec_API_MemLayout Device Memory Map
|
||||||
* The following illustration indicates the final memory map of the device when loaded with the bootloader.
|
* The following illustration indicates the final memory map of the device when loaded with the bootloader.
|
||||||
*
|
*
|
||||||
@ -121,6 +139,16 @@
|
|||||||
* | |
|
* | |
|
||||||
* | |
|
* | |
|
||||||
* | |
|
* | |
|
||||||
|
* | |
|
||||||
|
* +----------------------------+ 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
|
* +----------------------------+ FLASHEND - BOOT_SECTION_SIZE
|
||||||
* | |
|
* | |
|
||||||
* | Bootloader Application |
|
* | Bootloader Application |
|
||||||
@ -138,12 +166,6 @@
|
|||||||
* +----------------------------+ FLASHEND
|
* +----------------------------+ FLASHEND
|
||||||
* \endverbatim
|
* \endverbatim
|
||||||
*
|
*
|
||||||
* Bootloaders reporting a device release revision number of 1.00 or greater are bootloader API enabled. 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.
|
|
||||||
*
|
|
||||||
* \section Sec_Options Project Options
|
* \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.
|
* The following defines can be found in this demo, which can control the demo behaviour when defined, or changed in value.
|
||||||
|
@ -69,7 +69,7 @@
|
|||||||
#define USE_RAM_DESCRIPTORS
|
#define USE_RAM_DESCRIPTORS
|
||||||
// #define USE_FLASH_DESCRIPTORS
|
// #define USE_FLASH_DESCRIPTORS
|
||||||
// #define USE_EEPROM_DESCRIPTORS
|
// #define USE_EEPROM_DESCRIPTORS
|
||||||
// #define NO_INTERNAL_SERIAL
|
#define NO_INTERNAL_SERIAL
|
||||||
#define FIXED_CONTROL_ENDPOINT_SIZE 8
|
#define FIXED_CONTROL_ENDPOINT_SIZE 8
|
||||||
#define DEVICE_STATE_AS_GPIOR 0
|
#define DEVICE_STATE_AS_GPIOR 0
|
||||||
#define FIXED_NUM_CONFIGURATIONS 1
|
#define FIXED_NUM_CONFIGURATIONS 1
|
||||||
|
@ -60,7 +60,7 @@ const USB_Descriptor_Device_t DeviceDescriptor =
|
|||||||
|
|
||||||
.ManufacturerStrIndex = NO_DESCRIPTOR,
|
.ManufacturerStrIndex = NO_DESCRIPTOR,
|
||||||
.ProductStrIndex = NO_DESCRIPTOR,
|
.ProductStrIndex = NO_DESCRIPTOR,
|
||||||
.SerialNumStrIndex = USE_INTERNAL_SERIAL,
|
.SerialNumStrIndex = NO_DESCRIPTOR,
|
||||||
|
|
||||||
.NumberOfConfigurations = FIXED_NUM_CONFIGURATIONS
|
.NumberOfConfigurations = FIXED_NUM_CONFIGURATIONS
|
||||||
};
|
};
|
||||||
@ -124,17 +124,6 @@ const USB_Descriptor_Configuration_t ConfigurationDescriptor =
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Language descriptor structure. This descriptor, located in FLASH memory, is returned when the host requests
|
|
||||||
* the string descriptor with index 0 (the first index). It is actually an array of 16-bit integers, which indicate
|
|
||||||
* via the language ID table available at USB.org what languages the device supports for its string descriptors.
|
|
||||||
*/
|
|
||||||
const USB_Descriptor_String_t LanguageString =
|
|
||||||
{
|
|
||||||
.Header = {.Size = USB_STRING_LEN(1), .Type = DTYPE_String},
|
|
||||||
|
|
||||||
.UnicodeString = {LANGUAGE_ID_ENG}
|
|
||||||
};
|
|
||||||
|
|
||||||
/** This function is called by the library when in device mode, and must be overridden (see library "USB Descriptors"
|
/** 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
|
* 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
|
* to the USB library. When the device receives a Get Descriptor request on the control endpoint, this function
|
||||||
@ -145,30 +134,21 @@ uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue,
|
|||||||
const uint8_t wIndex,
|
const uint8_t wIndex,
|
||||||
const void** const DescriptorAddress)
|
const void** const DescriptorAddress)
|
||||||
{
|
{
|
||||||
const uint8_t DescriptorType = (wValue >> 8);
|
const uint8_t DescriptorType = (wValue >> 8);
|
||||||
const uint8_t DescriptorNumber = (wValue & 0xFF);
|
|
||||||
|
|
||||||
const void* Address = NULL;
|
const void* Address = NULL;
|
||||||
uint16_t Size = NO_DESCRIPTOR;
|
uint16_t Size = NO_DESCRIPTOR;
|
||||||
|
|
||||||
switch (DescriptorType)
|
/* If/Else If chain compiles slightly smaller than a switch case */
|
||||||
|
if (DescriptorType == DTYPE_Device)
|
||||||
{
|
{
|
||||||
case DTYPE_Device:
|
Address = &DeviceDescriptor;
|
||||||
Address = &DeviceDescriptor;
|
Size = sizeof(USB_Descriptor_Device_t);
|
||||||
Size = sizeof(USB_Descriptor_Device_t);
|
}
|
||||||
break;
|
else if (DescriptorType == DTYPE_Configuration)
|
||||||
case DTYPE_Configuration:
|
{
|
||||||
Address = &ConfigurationDescriptor;
|
Address = &ConfigurationDescriptor;
|
||||||
Size = sizeof(USB_Descriptor_Configuration_t);
|
Size = sizeof(USB_Descriptor_Configuration_t);
|
||||||
break;
|
|
||||||
case DTYPE_String:
|
|
||||||
if (!(DescriptorNumber))
|
|
||||||
{
|
|
||||||
Address = &LanguageString;
|
|
||||||
Size = pgm_read_byte(&LanguageString.Header.Size);
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
*DescriptorAddress = Address;
|
*DescriptorAddress = Address;
|
||||||
|
@ -70,7 +70,7 @@
|
|||||||
uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue,
|
uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue,
|
||||||
const uint8_t wIndex,
|
const uint8_t wIndex,
|
||||||
const void** const DescriptorAddress)
|
const void** const DescriptorAddress)
|
||||||
ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(3);
|
ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(3) AUX_BOOT_SECTION;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -104,9 +104,6 @@ bool SCSI_DecodeSCSICommand(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
|
|||||||
case SCSI_CMD_READ_CAPACITY_10:
|
case SCSI_CMD_READ_CAPACITY_10:
|
||||||
CommandSuccess = SCSI_Command_Read_Capacity_10(MSInterfaceInfo);
|
CommandSuccess = SCSI_Command_Read_Capacity_10(MSInterfaceInfo);
|
||||||
break;
|
break;
|
||||||
case SCSI_CMD_SEND_DIAGNOSTIC:
|
|
||||||
CommandSuccess = SCSI_Command_Send_Diagnostic(MSInterfaceInfo);
|
|
||||||
break;
|
|
||||||
case SCSI_CMD_WRITE_10:
|
case SCSI_CMD_WRITE_10:
|
||||||
CommandSuccess = SCSI_Command_ReadWrite_10(MSInterfaceInfo, DATA_WRITE);
|
CommandSuccess = SCSI_Command_ReadWrite_10(MSInterfaceInfo, DATA_WRITE);
|
||||||
break;
|
break;
|
||||||
@ -116,6 +113,7 @@ bool SCSI_DecodeSCSICommand(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
|
|||||||
case SCSI_CMD_MODE_SENSE_6:
|
case SCSI_CMD_MODE_SENSE_6:
|
||||||
CommandSuccess = SCSI_Command_ModeSense_6(MSInterfaceInfo);
|
CommandSuccess = SCSI_Command_ModeSense_6(MSInterfaceInfo);
|
||||||
break;
|
break;
|
||||||
|
case SCSI_CMD_SEND_DIAGNOSTIC:
|
||||||
case SCSI_CMD_START_STOP_UNIT:
|
case SCSI_CMD_START_STOP_UNIT:
|
||||||
case SCSI_CMD_TEST_UNIT_READY:
|
case SCSI_CMD_TEST_UNIT_READY:
|
||||||
case SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL:
|
case SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL:
|
||||||
@ -227,33 +225,6 @@ static bool SCSI_Command_Read_Capacity_10(USB_ClassInfo_MS_Device_t* const MSInt
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Command processing for an issued SCSI SEND DIAGNOSTIC command. This command performs a quick check of the Dataflash ICs on the
|
|
||||||
* board, and indicates if they are present and functioning correctly. Only the Self-Test portion of the diagnostic command is
|
|
||||||
* supported.
|
|
||||||
*
|
|
||||||
* \param[in] MSInterfaceInfo Pointer to the Mass Storage class interface structure that the command is associated with
|
|
||||||
*
|
|
||||||
* \return Boolean true if the command completed successfully, false otherwise.
|
|
||||||
*/
|
|
||||||
static bool SCSI_Command_Send_Diagnostic(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
|
|
||||||
{
|
|
||||||
/* Check to see if the SELF TEST bit is not set */
|
|
||||||
if (!(MSInterfaceInfo->State.CommandBlock.SCSICommandData[1] & (1 << 2)))
|
|
||||||
{
|
|
||||||
/* Only self-test supported - update SENSE key and fail the command */
|
|
||||||
SCSI_SET_SENSE(SCSI_SENSE_KEY_ILLEGAL_REQUEST,
|
|
||||||
SCSI_ASENSE_INVALID_FIELD_IN_CDB,
|
|
||||||
SCSI_ASENSEQ_NO_QUALIFIER);
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Succeed the command and update the bytes transferred counter */
|
|
||||||
MSInterfaceInfo->State.CommandBlock.DataTransferLength = 0;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Command processing for an issued SCSI READ (10) or WRITE (10) command. This command reads in the block start address
|
/** 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
|
* 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.
|
* reading and writing of the data.
|
||||||
|
@ -42,7 +42,6 @@
|
|||||||
|
|
||||||
#include <LUFA/Drivers/USB/USB.h>
|
#include <LUFA/Drivers/USB/USB.h>
|
||||||
|
|
||||||
#include "../BootloaderMassStorage.h"
|
|
||||||
#include "../Descriptors.h"
|
#include "../Descriptors.h"
|
||||||
#include "VirtualFAT.h"
|
#include "VirtualFAT.h"
|
||||||
|
|
||||||
@ -69,16 +68,15 @@
|
|||||||
#define DEVICE_TYPE_BLOCK 0x00
|
#define DEVICE_TYPE_BLOCK 0x00
|
||||||
|
|
||||||
/* Function Prototypes: */
|
/* Function Prototypes: */
|
||||||
bool SCSI_DecodeSCSICommand(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo);
|
bool SCSI_DecodeSCSICommand(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) AUX_BOOT_SECTION;
|
||||||
|
|
||||||
#if defined(INCLUDE_FROM_SCSI_C)
|
#if defined(INCLUDE_FROM_SCSI_C)
|
||||||
static bool SCSI_Command_Inquiry(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo);
|
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);
|
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);
|
static bool SCSI_Command_Read_Capacity_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) AUX_BOOT_SECTION;
|
||||||
static bool SCSI_Command_Send_Diagnostic(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo);
|
|
||||||
static bool SCSI_Command_ReadWrite_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo,
|
static bool SCSI_Command_ReadWrite_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo,
|
||||||
const bool IsDataRead);
|
const bool IsDataRead) AUX_BOOT_SECTION;
|
||||||
static bool SCSI_Command_ModeSense_6(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo);
|
static bool SCSI_Command_ModeSense_6(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) AUX_BOOT_SECTION;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -151,26 +151,28 @@ static void WriteVirtualBlock(const uint16_t BlockNumber)
|
|||||||
|
|
||||||
if ((BlockNumber >= 4) && (BlockNumber < (4 + FILE_SECTORS(FIRMWARE_FILE_SIZE_BYTES))))
|
if ((BlockNumber >= 4) && (BlockNumber < (4 + FILE_SECTORS(FIRMWARE_FILE_SIZE_BYTES))))
|
||||||
{
|
{
|
||||||
|
#if (FLASHEND > 0xFFFF)
|
||||||
uint32_t WriteFlashAddress = (uint32_t)(BlockNumber - 4) * SECTOR_SIZE_BYTES;
|
uint32_t WriteFlashAddress = (uint32_t)(BlockNumber - 4) * SECTOR_SIZE_BYTES;
|
||||||
|
#else
|
||||||
|
uint16_t WriteFlashAddress = (uint16_t)(BlockNumber - 4) * SECTOR_SIZE_BYTES;
|
||||||
|
#endif
|
||||||
|
|
||||||
for (uint16_t i = 0; i < SECTOR_SIZE_BYTES; i += 2)
|
for (uint16_t i = 0; i < SECTOR_SIZE_BYTES; i += 2)
|
||||||
{
|
{
|
||||||
if ((WriteFlashAddress % SPM_PAGESIZE) == 0)
|
if ((WriteFlashAddress % SPM_PAGESIZE) == 0)
|
||||||
{
|
{
|
||||||
/* Erase the given FLASH page, ready to be programmed */
|
/* Erase the given FLASH page, ready to be programmed */
|
||||||
boot_page_erase(WriteFlashAddress);
|
BootloaderAPI_ErasePage(WriteFlashAddress);
|
||||||
boot_spm_busy_wait();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Write the next data word to the FLASH page */
|
/* Write the next data word to the FLASH page */
|
||||||
boot_page_fill(WriteFlashAddress, (BlockBuffer[i + 1] << 8) | BlockBuffer[i]);
|
BootloaderAPI_FillWord(WriteFlashAddress, (BlockBuffer[i + 1] << 8) | BlockBuffer[i]);
|
||||||
WriteFlashAddress += 2;
|
WriteFlashAddress += 2;
|
||||||
|
|
||||||
if ((WriteFlashAddress % SPM_PAGESIZE) == 0)
|
if ((WriteFlashAddress % SPM_PAGESIZE) == 0)
|
||||||
{
|
{
|
||||||
/* Write the filled FLASH page to memory */
|
/* Write the filled FLASH page to memory */
|
||||||
boot_page_write(WriteFlashAddress - SPM_PAGESIZE);
|
BootloaderAPI_WritePage(WriteFlashAddress - SPM_PAGESIZE);
|
||||||
boot_spm_busy_wait();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -219,10 +221,17 @@ static void ReadVirtualBlock(const uint16_t BlockNumber)
|
|||||||
default: /* Blocks 4 onwards: Data allocation section */
|
default: /* Blocks 4 onwards: Data allocation section */
|
||||||
if ((BlockNumber >= 4) && (BlockNumber < (4 + FILE_SECTORS(FIRMWARE_FILE_SIZE_BYTES))))
|
if ((BlockNumber >= 4) && (BlockNumber < (4 + FILE_SECTORS(FIRMWARE_FILE_SIZE_BYTES))))
|
||||||
{
|
{
|
||||||
|
#if (FLASHEND > 0xFFFF)
|
||||||
uint32_t ReadFlashAddress = (uint32_t)(BlockNumber - 4) * SECTOR_SIZE_BYTES;
|
uint32_t ReadFlashAddress = (uint32_t)(BlockNumber - 4) * SECTOR_SIZE_BYTES;
|
||||||
|
|
||||||
for (uint16_t i = 0; i < SECTOR_SIZE_BYTES; i++)
|
for (uint16_t i = 0; i < SECTOR_SIZE_BYTES; i++)
|
||||||
BlockBuffer[i] = pgm_read_byte_far(ReadFlashAddress++);
|
BlockBuffer[i] = pgm_read_byte_far(ReadFlashAddress++);
|
||||||
|
#else
|
||||||
|
uint16_t ReadFlashAddress = (uint16_t)(BlockNumber - 4) * SECTOR_SIZE_BYTES;
|
||||||
|
|
||||||
|
for (uint16_t i = 0; i < SECTOR_SIZE_BYTES; i++)
|
||||||
|
BlockBuffer[i] = pgm_read_byte(ReadFlashAddress++);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@ -237,8 +246,8 @@ static void ReadVirtualBlock(const uint16_t BlockNumber)
|
|||||||
* PC via the USB Mass Storage interface.
|
* PC via the USB Mass Storage interface.
|
||||||
*
|
*
|
||||||
* \param[in] MSInterfaceInfo Pointer to a structure containing a Mass Storage Class configuration and state
|
* \param[in] MSInterfaceInfo Pointer to a structure containing a Mass Storage Class configuration and state
|
||||||
* \param[in] BlockAddress Data block starting address for the write sequence
|
* \param[in] BlockAddress Data block starting address for the write sequence
|
||||||
* \param[in] TotalBlocks Number of blocks of data to write
|
* \param[in] TotalBlocks Number of blocks of data to write
|
||||||
*/
|
*/
|
||||||
void VirtualFAT_WriteBlocks(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo,
|
void VirtualFAT_WriteBlocks(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo,
|
||||||
const uint32_t BlockAddress,
|
const uint32_t BlockAddress,
|
||||||
@ -256,8 +265,8 @@ void VirtualFAT_WriteBlocks(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo,
|
|||||||
* to the host PC via the USB Mass Storage interface.
|
* to the host PC via the USB Mass Storage interface.
|
||||||
*
|
*
|
||||||
* \param[in] MSInterfaceInfo Pointer to a structure containing a Mass Storage Class configuration and state
|
* \param[in] MSInterfaceInfo Pointer to a structure containing a Mass Storage Class configuration and state
|
||||||
* \param[in] BlockAddress Data block starting address for the read sequence
|
* \param[in] BlockAddress Data block starting address for the read sequence
|
||||||
* \param[in] TotalBlocks Number of blocks of data to read
|
* \param[in] TotalBlocks Number of blocks of data to read
|
||||||
*/
|
*/
|
||||||
void VirtualFAT_ReadBlocks(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo,
|
void VirtualFAT_ReadBlocks(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo,
|
||||||
const uint32_t BlockAddress,
|
const uint32_t BlockAddress,
|
||||||
|
@ -37,9 +37,11 @@
|
|||||||
|
|
||||||
#include <LUFA/Drivers/USB/USB.h>
|
#include <LUFA/Drivers/USB/USB.h>
|
||||||
|
|
||||||
|
#include "../BootloaderAPI.h"
|
||||||
|
|
||||||
/* Macros: */
|
/* Macros: */
|
||||||
/** Size of the virtual FIRMWARE.BIN file in bytes. */
|
/** Size of the virtual FIRMWARE.BIN file in bytes. */
|
||||||
#define FIRMWARE_FILE_SIZE_BYTES (FLASHEND - (FLASHEND - BOOT_START_ADDR))
|
#define FIRMWARE_FILE_SIZE_BYTES (FLASHEND - (FLASHEND - BOOT_START_ADDR) - AUX_BOOT_SECTION_SIZE)
|
||||||
|
|
||||||
/** Number of sectors that comprise a single logical disk cluster. */
|
/** Number of sectors that comprise a single logical disk cluster. */
|
||||||
#define SECTOR_PER_CLUSTER 4
|
#define SECTOR_PER_CLUSTER 4
|
||||||
@ -144,16 +146,16 @@
|
|||||||
#if defined(INCLUDE_FROM_VIRTUAL_FAT_C)
|
#if defined(INCLUDE_FROM_VIRTUAL_FAT_C)
|
||||||
static void UpdateFAT12ClusterEntry(uint8_t* const FATTable,
|
static void UpdateFAT12ClusterEntry(uint8_t* const FATTable,
|
||||||
const uint16_t Index,
|
const uint16_t Index,
|
||||||
const uint16_t ChainEntry);
|
const uint16_t ChainEntry) AUX_BOOT_SECTION;
|
||||||
static void WriteVirtualBlock(const uint16_t BlockNumber);
|
static void WriteVirtualBlock(const uint16_t BlockNumber) AUX_BOOT_SECTION;
|
||||||
static void ReadVirtualBlock(const uint16_t BlockNumber);
|
static void ReadVirtualBlock(const uint16_t BlockNumber) AUX_BOOT_SECTION;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void VirtualFAT_WriteBlocks(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo,
|
void VirtualFAT_WriteBlocks(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo,
|
||||||
const uint32_t BlockAddress,
|
const uint32_t BlockAddress,
|
||||||
uint16_t TotalBlocks);
|
uint16_t TotalBlocks) AUX_BOOT_SECTION;
|
||||||
|
|
||||||
void VirtualFAT_ReadBlocks(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo,
|
void VirtualFAT_ReadBlocks(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo,
|
||||||
const uint32_t BlockAddress,
|
const uint32_t BlockAddress,
|
||||||
uint16_t TotalBlocks);
|
uint16_t TotalBlocks) AUX_BOOT_SECTION;
|
||||||
#endif
|
#endif
|
||||||
|
@ -27,20 +27,33 @@ LD_FLAGS = -Wl,--section-start=.text=$(BOOT_START_OFFSET) $(BOOT_API_LD_FLAG
|
|||||||
# match the target's total FLASH size and the bootloader size set in the
|
# match the target's total FLASH size and the bootloader size set in the
|
||||||
# device's fuses.
|
# device's fuses.
|
||||||
FLASH_SIZE_KB = 128
|
FLASH_SIZE_KB = 128
|
||||||
BOOT_SECTION_SIZE_KB = 8
|
BOOT_SECTION_SIZE_KB = 4
|
||||||
|
|
||||||
# Bootloader address calculation formulas
|
# Bootloader address calculation formulas
|
||||||
# Do not modify these macros, but rather modify the dependent values above.
|
# Do not modify these macros, but rather modify the dependent values above.
|
||||||
CALC_ADDRESS_IN_HEX = $(shell printf "0x%X" $$(( $(1) )) )
|
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_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)) )
|
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
|
# Bootloader linker section flags for relocating the API table sections to
|
||||||
# known FLASH addresses - these should not normally be user-edited.
|
# known FLASH addresses - these should not normally be user-edited.
|
||||||
BOOT_SECTION_LD_FLAG = -Wl,--section-start=.apitable_$(strip $(1))=$(call BOOT_SEC_OFFSET, $(3)) -Wl,--undefined=BootloaderAPI_$(strip $(2))
|
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, trampolines, Trampolines, 96)
|
BOOT_API_LD_FLAGS = $(call BOOT_SECTION_LD_FLAG, .apitable_trampolines, BootloaderAPI_Trampolines, 96)
|
||||||
BOOT_API_LD_FLAGS += $(call BOOT_SECTION_LD_FLAG, jumptable, JumpTable, 32)
|
BOOT_API_LD_FLAGS += $(call BOOT_SECTION_LD_FLAG, .apitable_jumptable, BootloaderAPI_JumpTable, 32)
|
||||||
BOOT_API_LD_FLAGS += $(call BOOT_SECTION_LD_FLAG, signatures, Signatures, 8)
|
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='' -DAUX_BOOT_SECTION_SIZE=0
|
||||||
|
else
|
||||||
|
AUX_BOOT_SECTION_KB = (6 - $(BOOT_SECTION_SIZE_KB))
|
||||||
|
|
||||||
|
CC_FLAGS += -DAUX_BOOT_SECTION='__attribute__((section(".boot_aux")))' -DAUX_BOOT_SECTION_SIZE='($(AUX_BOOT_SECTION_KB) * 1024)'
|
||||||
|
LD_FLAGS += -Wl,--section-start=.boot_aux=$(call BOOT_SEC_OFFSET, (($(BOOT_SECTION_SIZE_KB) + $(AUX_BOOT_SECTION_KB)) * 1024 - 16))
|
||||||
|
LD_FLAGS += $(call BOOT_SECTION_LD_FLAG, .boot_aux_trampoline, Boot_AUX_Trampoline, ($(BOOT_SECTION_SIZE_KB) + $(AUX_BOOT_SECTION_KB)) * 1024)
|
||||||
|
endif
|
||||||
|
|
||||||
# Default target
|
# Default target
|
||||||
all:
|
all:
|
||||||
|
Loading…
Reference in New Issue
Block a user