
  GCBOOT - a bootloader for the PIC18F2525 chip - v8 11/13/10
  ===========================================================

This is a bootloader I made for loading code into my HP21xx USB Disk Adapter.
I looked at several existing bootloaders, including AN851 and AN1310 from
Microchip, DS30, and "TinyBLD" and found they were unsuitable for what I
wanted to do. Specifically they all require a PC app to load the code,
and some also require changes to the PIC app being loaded. My primary needs
were for the bootloader to accept plain hex code sent over a simple serial
port by whatever means with minimal requirements, with little or no change
to the PIC program. A secondary need was to be able to load code into the
PIC without erasing existing code to permit overlays and multiple apps.


Software Stuff
--------------

GCBOOT is written using the Great Cow Basic compiler, available from:
http://gcbasic.sourceforge.net/ (I used version 0.9 10/9/2010)
A Windows exe is provided, for Linux recompile gcbasic.bas using
the Free Basic compiler, available from: http://www.freebasic.net/

GPUTILS or MPASM/MPLAB is required to assemble the resulting code:
http://gputils.sourceforge.net/ (Windows or Linux)
http://www.microchip.com/ (search for MPLAB)

GC Basic's internal assembler can be used if assembly.bi is patched
to permit assembly past address 0x8000 - for the 0.9 version my fix
was to find the comments 'Add high address? (occurs twice) and in the
next two lines after each comment change FRA to (FRA - 32767).

GC Basic and a compatible assembler is not required if using the gcboot.hex
file as-is on a PIC18F2525 chip, it is only needed to modify the bootloader
source code to configure for a different PIC18F chip or compile with different
options. Although for PIC programming you'll probably want these tools anyway.

A programmer is required to initially load the bootloader into the PIC,
I used the Microchip Pickit 2 starter package (DV164120, includes MPLAB)
with the 28-pin demo board (DM164120-3). Alternatively to save bucks just
the programmer (PG164120) can be used with a homemade 28-pin adapter,
download the software (Windows or Linux) from the Microchip site (punch
in "pickit 2" in the search box for download options). A GUI app is provided
for Windows systems. For Linux use PK2CMD from a command line, such as:
pk2cmd -P -F gcboot.hex -T -R -M (this leaves the PIC powered for testing).


GCBOOT Features
---------------

GCBOOT has the following characteristics...

Configured for a 28-pin PIC18F2525 with MCLR reset, internal 32mhz clock.
9600 baud serial port connected to the HW serial port using 3 resistors.
If no serial port is connected then immediately runs the loaded app.
Accepts standard Microchip-format hex files, record len 0 = end of file.
Does not support loading the eeprom, configuration and eeprom data is ignored.
Menu options to program, examine code/ram, wipe code/ram and execute app.
No menu selection needed to load code, just send the hex file (triggers on :)
Terminal emulator or sending app must add a short delay after each line.
Port B bit 0 configured as an output to flash an LED for status.
Bootloader starts at address 0xB000, all app code must be below this.
Existing PIC code is not erased when loading new code unless the same address.
First two words of the application should not be a relative branch or call.
Replaces the first two words with GOTO 0xB000, stores the original at 0xBFF0.
Stores a GOTO 2 at 0xBFF4 in the event the first instruction isn't a GOTO.
PIC app must not assume particular memory/register contents on startup.
Bootloader uses/changes ram from 0x000 to 0x140 and from 0xF00 to 0xFFF.

Source-configurable options...
PIC chip and MCLR config (must be a PIC18F, only tested with PIC18F2525).
Oscillator type and PLL usage (only tested with internal oscillator).
Starting location of the bootloader code and where it stores the app GOTO.
Pin and polarity used to enable the bootloader or run the app.
Serial port baud rate and polarity.
Status LED usage and pin.


Usage
-----

The bootloader is configured to be used with a circuit similar to this...

    O serial                    .----------------.
 O    port                      |            MCLR|--1K---*---10K--< +5V
 RX O--------1K-----------------|TX (C6)         |       |
 O                              |                |       `------*--100--.
 TX O----*---18K----------------|RX (C7)      Vcc|---*--< +5V   |       |
 O       |                      |                |   |         2.2u     O |
    O    `---100K---< +5V       |   PIC18F2525   |  0.1u       _|_        |--
 O                              |                |   |                  O |
    O----.     .--|<|---2.2K----|B0           Vss|---*                  |reset
        _|_   _|_ LED           `----------------'  _|_                _|_

The serial port sends 5V signals, this is compatible with the serial port
hardware in most PC's. The 18K resistor in series with the RX pin limits
current flow from 12V serial outputs, the 100K resistor pulls C7 high when
the serial port is not connected to tell the bootloader to run the app.
If not using a reset switch, MCLR can be connected to Vcc with a 1K resistor
(the resistor is to protect the PIC in the event of misprogramming).

Note that if using the gcboot.hex file as-is, the B0 pin must not be directly
connected to ground or +5V, or to the output of another chip. The source can
be configured to disable the LED output or use another pin.

The software used to access the bootloader must be configured to add a small
amount of delay after each line end (10mS should be sufficient). There is no
hardware handshaking and no byte-by-byte software control, so time must be
given to process each line of hex code. The Windows Hyperterminal program has
an option for line delay, as does most other terminal emulators. Linux systems
can use a simple script to send the hex file even if a terminal emulator is
running, and if desired automatically execute the app after loading. Windows
does not permit such simple user access to the serial port so generally code
needs to be uploaded using a terminal emulator or a custom-written app that
sends the hex file lines with an appropriate line delay.

When the bootloader runs it flashes the status LED on off on with a 1 second
interval to verify timing, then sends the following to the serial terminal...

=== Terry's Bootloader ===  v8 11/13/10
Configuration = 32mhz MCLR LED=portb.0
Select...
P: Program (or just send)
M: Examine ram
V: Examine code
W: Wipe chip
X: Execute app
>

Enter is not needed when selecting options, just send the key. All options
except for X can be cancelled by sending Esc. Entries except for confirms
but including hex can be sent as uppercase or lowercase.

Option P is mostly redundant, only needed if a hex file has extra comments at
the beginning of the file. Otherwise just send the hex file using the terminal
emulator's ascii upload function (or for HyperTerminal by copy/pasting the
hex code, associate .hex files to Notepad for easy access). Upon reception of
each ":" character of the hex file the status LED goes out, and is turned on
after the checksum is received, so the LED will blink as the app is loaded.
A "." is sent to the terminal for each new 32-word block being programmed.
If an error occurs the LED remains off and an error message is sent to the
terminal, Esc must be sent to clear the error condition. In the case of an
address error the bootloader restarts, including the initial startup delay.

Option M prompts for a ram page (0 to F) then lists 256 hex bytes, useful for
examining array contents set by the PIC app to assist in debugging. Example...

> m
HEX digit of block to dump: 1
0100: 6D 29 20 00 FF FF FF FF FF FF FF FF FF FF FF FF
0110: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
0120: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
0130: FF FF FF FF 01 EF 00 F0 FF FF FF FF FF FF FF FF
0140: C1 88 21 88 A0 40 38 05 08 07 C0 06 62 6B 25 9E
0150: C1 10 03 58 02 69 38 8A AE 60 C2 91 B4 20 F8 01
0160: CD 00 51 82 A0 54 02 5E 98 A8 00 40 60 B0 08 EE
0170: 82 58 E4 90 09 1C 00 80 E9 20 20 6E 9C C4 30 83
0180: 32 0C 74 82 21 C0 A2 08 C9 88 78 2F 81 00 0B 9D
0190: 43 D0 0B 11 38 01 04 00 3A 48 53 88 88 D0 41 00
01A0: 4C 65 40 AC 80 46 96 00 05 68 0C 4E A7 E0 39 01
01B0: 86 68 03 02 B2 D4 2C 34 56 8A B6 84 0E 84 04 08
01C0: DC 02 12 22 96 E1 4C 65 2A 42 EC 00 A2 57 00 E1
01D0: 74 81 40 A1 0D A0 48 75 4C A5 4A C6 C8 11 00 A7
01E0: 28 52 A6 61 FA 05 5A 28 E4 51 30 62 4A E0 04 82
01F0: 75 A2 08 6C 84 90 20 08 62 08 46 20 4E F8 01 16

In this example 0x100-0x13F shows the flash buffer for the bottom locations
of an uninitialized PIC, with the first 4 bytes set to jump to the bootloader.
The remaining memory is random bytes after power-up.

Option V prompts for an address (4 hex digits) then lists 128 hex words,
useful for examining program space to see what is loaded where. Example...

> v
HEX Address: BF00
BF00: 1C1C 4548 2058 6964 6967 2074 666F 6220
BF10: 6F6C 6B63 7420 206F 7564 706D 203A 0202
BF20: 203A 0101 0020 0D0D 4548 2058 6441 7264
BF30: 7365 3A73 0020 1212 6553 646E 4520 4353
BF40: 6620 726F 6D20 6E65 2075 0101 002E 1010
BF50: 6E49 6176 696C 2064 6461 7264 7365 2073
BF60: 0D0D 4520 4353 7420 206F 6572 6573 0074
BF70: 0A0A 655A 6F72 7220 6D61 203F 1B1B 655A
BF80: 6F72 6E69 2067 6172 206D 7266 6D6F 3120
BF90: 3034 7420 206F 4645 0046 0C0C 7245 7361
BFA0: 2065 6F63 6564 203F 1919 7528 7070 7265
BFB0: 6163 6573 5920 7420 206F 6F63 666E 7269
BFC0: 296D 0020 FFFF FFFF FFFF FFFF FFFF FFFF
BFD0: FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF
BFE0: FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF
BFF0: FFFF FFFF EF01 F000 FFFF FFFF FFFF FFFF

This shows the last block of memory, the bootloader just about fills it up
so if recompiled with a different version of GCB ensure that the code does
not extend past 0xBFEF, otherwise adjust the defines at the beginning of the
source to relocate lower. The instruction(s) from locations 0x0000 and 0x0002
will be relocated to 0xBFF0 and 0xBFF2 after loading an application,
locations 0xBFF4 and 0xBFF6 contain a JUMP 2 instruction.

Note that PIC18F memory is addressed as bytes with the LSB first, each
word starts on an even address. For convenience the bytes are swapped to
list the hex words normally. With a bit of scripting or program code
option V can be used to implement an extract function.

Option W permits erasing ram and/or code memory. Normally this isn't
needed but can be used when debugging to see what ram locations are
changed or to remove previously loaded code so that newly-loaded code
extents will stand out. The GOTO 0xB000 at location 0 remains after
wiping code memory, but the stored instructions from location 0 are
not erased.

Option X runs the loaded application by executing a jump to BFF0, where
the bootloader stores the application's initial GOTO. If no app has been
loaded it executes FFFF's as nops and wraps around to hit the initial
GOTO 0xB000, rerunning the bootloader.

Whenever the bootloader runs, it checks locations 0-3 to make sure it
contains a GOTO 0xB000, if not then it programs a GOTO 0xB000 at location 0
and a GOTO 2 at location 0xBFF4. This ensures that the bootloader will always
run upon reset, the GOTO 2 is for compatibility with the Hi-Tech C compiler
(use the --rom option to locate the code below the start of the bootloader).


Using the bootloader under Linux
--------------------------------

No specific Windows section is provided - instructions for using GC Basic
under Windows is included with the program, HyperTerminal can be used to
send hex code, and since a VXD driver is needed to access the serial port
the scripting examples do not apply - writing a dedicated hex sender app
for Windows is not trivial and beyond the scope of these docs.

Linux makes it particularly easy to access the serial port using scripts
or any other program, as it's simply a virtual file (usually /dev/ttyS0).
Depending on the system it may be necessary to set up permissions, but I
don't recall having to do anything, I can access /dev/ttyS0 as a normal
user on my Ubuntu 8.04 system.

Multiple programs can access the serial port so it is not necessary to exit
the terminal emulator to send hex code with another application, which is
handy since simple Linux terminal emulators (like dterm) often don't have
a line delay function, thus requiring using a script to send the hex code.
The terminal can remain open to monitor for errors, or just watch the LED.

I use the following bash script to send hex files to the bootloader...

#!/bin/bash
serial=/dev/ttyS0
stty -F $serial 9600
if [ ! -e "$1" ]; then
 echo "Enter name of file to send..."
 read filename
else
 filename="$1"
fi
while read line
do
 echo $line > $serial
 sleep 0.05
done < "$filename"
echo "" > $serial

I named it "sendhex.sh", must be in "unix" line-end format with executable
permissions. Set the serial= line to match the serial port device, the stty
line sets the port to 9600 baud if a terminal emulator has not been run yet.
If no parameter is given or the file doesn't exist it prompts for the file
to send. After each line waits 50 milliseconds (approximately), and sends an
empty line after sending the file because often unix/Linux text files don't
have a line end after the last line.

To automatically execute the loaded app, echo "x" > /dev/ttyS0 at the command
line, or add echo "x" > $serial to the end of the script, if an error occurs
during loading it will be ignored.

From a command shell in the GC Basic directory, assuming myapp.gcb and
sendhex.sh are in the same directory, the following commands can be used...

./gcbasic -a:gcasm myapp.gcb     [compile my application]
./sendhex.sh myapp.hex           [send the hex to the bootloader]
echo "x" > /dev/ttyS0            [start the app]

If the app doesn't work right then I press the reset switch and try again.

To avoid the command line these steps can be put on GUI right-click actions
for .gcb and .hex files, also avoids having to be in the compiler directory.
To do this I created a directory named "picstuff" and copied into it the
gcbasic binary, messages.dat and the include and chipdata directories, and
created two scripts named gcb_compile and sendhex...

------- begin "gcb_compile" ------------------------
#!/bin/bash
if [ -e "$1" ]; then
 xterm -e /media/hdb5/picstuff/gcbasic -a:gcasm "$1"
fi
------- end "gcb_compile" --------------------------

------- begin "sendhex" ----------------------------
#!/bin/bash
if [ -e "$1" ]; then
 serial=/dev/ttyS0
 stty -F $serial 9600
 filename="$1"
 while read line
 do
  echo $line > $serial
  sleep 0.05
 done < "$filename"
 sleep 0.1
 echo "" > $serial
 sleep 1
 echo "x" > $serial
fi
------- end "sendhex" ------------------------------

Note that in the gcb_compile script the full path to the gcbasic binary
must be specified, edit to specify exactly where it's located at.

Also note that the gcbasic command specifies the internal assembler so
it can't be used to assemble the bootloader itself unless assembly.bi has
been fixed to permit assembling past address 0x8000 as instructed in the
"Software Stuff" section above - since this is for Linux, it is assumed
that since gcbasic has to be recompiled anyway that the patch has been made.

The sendhex script is an adaptation of sendhex.sh that requires a filename
parameter and sends the execute command after loading the hex file.

Try as I might I was unable to get pk2cmd to work from a GUI right-click,
the initial bootloader programming must be done from a command line.

In the GUI, associate .gcb (or text) files to the gcb_compile script,
and associate .hex (or text) files to the sendhex script. How this is
done varies from one GUI and another, for Gnome it's done by right-clicking
the file, selecting properties, then using the Open With tab. On my Ubuntu
system I used a mime editor to create a separate file type for hex files,
but I don't have a separate type for gcb files so the association appears
for all text files.

With the scripts in place I can simply right-click my gcbasic source and
compile, then right-click the resulting hex file to send it to the bootloader
to load and run the app.


License
-------

' The source code for the program is written by Terry Newton, it is provided
' as-is and without warranty of any kind. Under no circumstances shall the
' author be held liable for damages resulting from the use of the software.
' The source code itself is public domain and may be used for any purpose.
' The hex file that results from compiling this program includes libraries
' from the Great Cow Basic compiler that are Copyright Hugh Considine
' under the terms of the Lesser GNU Public License version 2.1 or later.
' GC Basic and source code is available from: http://gcbasic.sourceforge.net/

In effect this bootloader may only be distributed for applications where it is
practical to include the required LGPL notification.

----------------------------------------------

These docs last modified 11/13/2010
Terry Newton (wtn90125@yahoo.com)
