mac-rom-simm-programmer/hal/at90usb646/LUFA/DoxygenPages/SoftwareBootloaderJump.txt
Doug Brown 7425af761a Break out code into a HAL, optimize flash operations
This makes the code pretty easily portable to other architectures if someone
wants to make a more modern SIMM programmer. I also was pretty careful to split
responsibilities of the different components and give the existing components
better names. I'm pretty happy with the organization of the code now.

As part of this change I have also heavily optimized the code. In particular,
the read and write cycle routines are very important to the overall performance
of the programmer. In these routines I had to make some tradeoffs of code
performance versus prettiness, but the overall result is much faster
programming.

Some of these performance changes are the result of what I discovered when
I upgraded my AVR compiler. I discovered that it is smarter at looking at 32-bit
variables when I use a union instead of bitwise operations.

I also shaved off more CPU cycles by carefully making a few small tweaks. I
added a bypass for the "program only some chips" mask, because it was adding
unnecessary CPU cycles for a feature that is rarely used. I removed the
verification feature from the write routine, because we can always verify the
data after the write chunk is complete, which is more efficient. I also added
assumptions about the initial/final state of the CS/OE/WE pins, which allowed me
to remove more valuable CPU cycles from the read/write cycle routines.

There are also a few enormous performance optimizations I should have done a
long time ago:

1) The code was only handling one received byte per main loop iteration. Reading
   every byte available cut nearly a minute off of the 8 MB programming time.
2) The code wasn't taking advantage of the faster programming command available
   in the chips used on the 8 MB SIMM.

The end result of all of these optimizations is I have programming time of the
8 MB SIMM down to 3:31 (it used to be 8:43).

Another minor issue I fixed: the Micron SIMM chip identification wasn't working
properly. It was outputting the manufacturer ID again instead of the device ID.
2020-11-27 00:16:35 -08:00

72 lines
2.8 KiB
Plaintext

/** \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_SoftwareBootloaderStart Entering the Bootloader via Software
*
* A common requirement of many applications is the ability to jump to the programmed bootloader of a chip
* on demand, via the code's firmware (i.e. not as a result of any physical user interaction with the
* hardware). This might be required because the device does not have any physical user input, or simply
* just to streamline the device upgrade process on the host PC.
*
* The following C code snippets may be used to enter the bootloader upon request by the user application.
* By using the watchdog to physically reset the controller, it is ensured that all system hardware is
* completely reset to their defaults before the bootloader is run. This is important; since bootloaders
* are written to occupy a very limited space, they usually make assumptions about the register states based
* on the default values after a hard-reset of the chip.
*
* \section Sec_SoftareBootAVR8 AVR8 Architecture
* The following software bootloader jump code is written for the AVR8 architecture.
*
* \code
* #include <avr/wdt.h>
* #include <avr/io.h>
* #include <util/delay.h>
*
* #include <LUFA/Common/Common.h>
* #include <LUFA/Drivers/USB/USB.h>
*
* uint32_t Boot_Key ATTR_NO_INIT;
*
* #define MAGIC_BOOT_KEY 0xDC42ACCA
* #define BOOTLOADER_START_ADDRESS (FLASH_SIZE_BYTES - BOOTLOADER_SEC_SIZE_BYTES)
*
* void Bootloader_Jump_Check(void) ATTR_INIT_SECTION(3);
* void Bootloader_Jump_Check(void)
* {
* // If the reset source was the bootloader and the key is correct, clear it and jump to the bootloader
* if ((MCUSR & (1 << WDRF)) && (Boot_Key == MAGIC_BOOT_KEY))
* {
* Boot_Key = 0;
* ((void (*)(void))BOOTLOADER_START_ADDRESS)();
* }
* }
*
* void Jump_To_Bootloader(void)
* {
* // If USB is used, detach from the bus and reset it
* USB_Disable();
*
* // Disable all interrupts
* cli();
*
* // Wait two seconds for the USB detachment to register on the host
* Delay_MS(2000);
*
* // Set the bootloader key to the magic value and force a reset
* Boot_Key = MAGIC_BOOT_KEY;
* wdt_enable(WDTO_250MS);
* for (;;);
* }
* \endcode
*
* Note that the bootloader magic key can be any arbitrary value. The <em>FLASH_SIZE_BYTES</em> and
* <em>BOOTLOADER_SEC_SIZE_BYTES</em> tokens should be replaced with the total flash size of the AVR
* in bytes, and the allocated size of the bootloader section for the target AVR.
*
*/