The AYUCR Bootloader is a provides a simple interface for reading and writing the processor's flash program and data memory. It can be used to reprogram the processor's firmware using only the serial port interface without an external PIC programmer. This is ideal (and indeed, designed) for users to field update their electronics to fix bugs, add features or repurpose designs entirely.
The AYUCR bootloader (or simply bootloader) Provides a protocol for reading the entire PIC program address space, writing the non-bootloader or "user" portion of the address space and write the entire data address space. Using this protocol it is possible to implement a bootloader driver to read and reprogram the firmware as well as verify the results. It is designed to be relatively robust and error-proof while using less than 256 bytes of program memory and about 70 bytes of SRAM. This includes the bootloader interface, serial I/O routines and low-level flash read/write/erase routines.
In addition to field updates of firmware the bootloader provides features to allow for rapid software development. By using a special, 4-conductor serial cable that uses the DTR line to reset the processor the bootloader driver can reset the processor, send a break signal to trigger the bootloader, update the firmware and resest the process to run the new program. This makes the software development mach easier and far faster than using an external programmer. The same serial line can even be used for debugging output making the whole system similar to a Basic Stamp
There are several ways to initiate the bootloader three of which are common.
- Command Method
- Hardware Method
- Firmware Method
If you are using AYUCR electronics that implement a serial port command interface sending the "B" command will generally put the unit in bootloader mode. If successful the bootloader will echo the "K" prompt (meaning OK) and wait for a command. After that all commands are a single letter as described below. This is the method used by the AYUCR PC Interface
For bench testing the hardware method is generally preferable. When used with a development firmware driver this allows the hardware to be reflashed and reset with minimal software support and without the firmware implementing a command mode. A call to boot_detect is required at the top of the firmware after the initialization routine to detect a request to enter the boot loader on reset. If boot_detect does not receive the signal it will simply return and initialization will proceed normally. There are also some hardware requirements:
- /MCLR line must be enabled (not configured as an I/O pin
- /MCLR must pulled high via a 4K7 ohm resistor
- DTR line of the serial port is connected to the /MCLR pin through an NPN transistor
- Internal weak pullups must be disabled
AYUCR Bootloader Schematic
/MCLR, RB0 and RB1 are pins 4, 6 and 7 on the PIC 16F819 respectively. The NPN transistor serves to invert and level convert the DTR line. When first opened the serial port DTR line is set high resetting the processor. Lower the DTR line will bring the processor out of reset.The sequence of events that the driver initiates to start the bootloader in this configuration is as follows:
- The serial port is opened and configured for the appropriate COMM settings
- Opening the port will have raised the DTR line resetting the processor
- Wait 50ms
- Lower the DTR line to bring the processor out of reset
- Wait 50ms
- Send a break signal of at least 100ms
- Check for bootloader "K" prompt
See Article on Bootloader Development Platform for a complete description of the BLoad development adapter and the BLoad bootloader driver
Custom firmware may call the boot_loader routine directly in software to initiate the bootloader for custom configurations. This is not typical.
The bootloader itself is a simple command processor that expects and executes commanands transmitted over the serial port at either 2400 or 9600 baud depending on the version. One of several response codes are returned after each command is executed. All commands operate on pages of 64 bytes at a time. This translates into pages of 32 program words since each word is 16 bits (actually 14 but the two most significant bits are padding) each page is 64 bytes long. Data memory commands operate on 64 byte data pages. All commands are sent with an additional checksum byte for error checking.
R [ADR] [CHK]
Reads a page of flash program memory. The command is 4 bytes long, 1 byte for the command character 'R', two for the address and 1 checksum byte. This command returns [DATA] followed by [CHK] (65 bytes total)
W [ADR] [DATA] [CHK]
Writes a page to flash program memory. The command is 68 bytes long, 1 byte for the command character 'W', two for the address, a 64 byte data frame and a checksum byte.
E [ADR] [CHK]
Erases a page of flash program memory. The command is 4 bytes long, 1 byte for the command character 'E', two for the address and 1 checksum byte.
D [ADR] [DATA] [CHK]
Writes a page to flash data memory. The command is 68 bytes long, 1 byte for the command character 'D', two for the address, a 64 byte data frame and a checksum byte.
Exits the bootloader and resets the chip. This is not a hard reset and the contents of the data registers will not be reset. Effectively all that is happening is control is transfered to location 0x000 as on power up.
[ADR] - The address is two bytes long and is sent low byte first. The range of address (for the 16F819) is 0x0000 - 0x07FF for Read and 0x0020 - 0x06FF for Erase and Write. The difference is the bootloader will not allow you to overwrite it as this would produce strange results and migh break the firmware requiring a reflash using an external programmer.
[CHK] - A simple checksum of the databytes transmitted for error checking When appended to commands the checksum excludes the first command byte. The checksum for the read and erase commands applies to the 2 [ADR] bytes. The checksum for the write command applies to the 2 [ADR] and the 64 [DATA] bytes. The checksum returned after the 64 [DATA] bytes in the read command is calculated on those bytes.
[DATA] - represents an entire page of flash program memory. The page is organized as 32 low byte/high byte pairs.
K - Ready to accept the next command
R - Address range error
C - Data checksum error
When a command completes successfully the 'K' prompt will be all that is sent. There is no success code. The absense of a R or C error code is enough to indicate success.
The processor will issue a range error (R) if write or erase command and the target address would overwrite the bootloader itself. Overwriting the bootloader region while the processor is executing the bootloader would probably cause weird behavior possibly rendering the chip unusable without reflashing from scratch in a dedicated programmer.
Notice there is no command to read from data memory. This is cause by limited program space to implement features. For updating firmware this is not really a problem. It does mean the data segment can't be verified after writes but this is far less critical than for writes to the program memory
The bootloader is designed to interface with a program which reads the firmware .HEX file and uses the bootloader to write the new firmware to the chip. I have written various bootloader drivers using this protocol in Perl and C#. They are available on the Software page and Bootloader Development Platform Article.
- Reads and parses the .HEX formatted firmware files
- Read the existing firmware from the controller
- Compares the new and old firmware images to ensure that they both have identical bootloader code. Since the new firmware does not overwrite the bootloader this ensures that the new and old firmware is compatible
- Writes the new firmware (minus the bootloader region) to the chip.
- Reads and verifies the new firmware (From the chip this time) to ensure there were no errors.
This takes a little while at 2400 baud, perhaps 30 seconds. Changes to the firmware that alter the bootloader, serial I/O or flash program memory routines require reflashing the chip externally as these routines all reside in the bootloader-safe region of memory.
The command to read the page starting at 0x0020 (the first user page) is:
0x52 0x20 0x00 0x20
Notice that the address is sent LSB first and that the checksum excludes the command byte (0x52 or 'R'). The bytes above are expressed in hex. The total command length is 4 bytes. The bootloader will return the page requested as 32 two byte words, low bytes first followed by a checksum byte and then the 'K' prompt/success code. If there was an error, perhaps a checksum error indicating a problem receiving the command, the return code would be C followed by K.
The command to erase a page starting at 0x06DF (the last user page) is:
0x45 0xDF 0x06 0xE5
The return code following the operation will be 'K' A return of C followed by K indicates a checksum error.
The command to (attempt) to erase the page starting at 0x0700 (the first bootloader page) is:
0x45 0x00 0x07 0x07
This command will return R followed by K to indicate that a range error occurred.