www.nutsvolts.com/index.php?/magazine/article/october2010_SmileysWorkshop
Programmer. It is compatible with the AVRProg utility that
comes with AVRStudio [I use AVRProg for the Butterfly in
my C Programming book, but for this Workshop we’ll use
avrdude which also speaks AVR109]. This protocol covers
reading and writing Flash and lockbits and EEPROM and
reading Fuse Bits, but we will only look at the Flash.
AVR109 Commands We Use
The heart of our bootloader is the function
AVR109CommandParser() shown next. This function
contains a switch statement that calls one of the AVR109
commands, depending on the command byte received
over the serial port. Not all the AVR109 commands are
used since only those chosen are needed for a simple
bootloader. Most of the function names are the same as
the command name and are somewhat self explanatory
[autoIncrementAddress() is called by the command byte
‘a’ which tells the bootloader to auto increment the
address — whoa, this code is almost self-documenting!].
[This is a joke since anyone who claims their code is self-documenting is wrong and should be ignored from that
point forward (as should their code). They are also
dangerous (as is their code), but we’ll save that for
another rant.]
// Note that the function name is the command
// except where otherwise commented.
void AVR109CommandParser()
{
uint8_t cmd;
while(1)// Loop forever
{
cmd = receiveByte();
switch (cmd)
{
case ‘P’: // Enter program mode
case ‘L’: // Leave program mode
sendByte(‘\r’);
break;
case ‘a’:
autoIncrementAddress();
break;
■ FIGURE 2. Project Options Custom.
62
October 2010
case ‘A’:
setAddress();
break;
case ‘e’:
chipErase();
break;
case ‘T’:
selectDeviceType();
break;
case ‘s’:
readSignatureBytes();
break;
case ‘t’:
returnSupportedDeviceCodes();
break;
case ‘S’:
returnSoftwareIdentifier();
break;
case ‘p’:
returnProgrammerType();
break;
case ‘b’:
checkBlockSupport();
break;
case ‘B’: // Start Block Flash Load
case ‘g’: // Start Block Flash Read
startBlockAction(cmd);
break;
case ‘E’:
exitBootloader();
break;
default:
if(cmd != 0x1B) sendByte(‘?’);
break;
}
}
}
Some of these functions are required by avrdude
when running in the AVR109 mode, though several don’t
do much and wouldn’t really be needed if you want to
write your own PC side bootloader and use it with a
device that you already know about. You wouldn’t need
to get the identifying info such as the signature byte, the
programmer type, nor would you need to see if it supports
blocks. Neither would you need to tell it to enter or leave
the programming mode since what else would it do?
In that latter case, all we do is return a ‘\r’ that lies to
avrdude so that it will continue working. Why write our
own when avrdude is a great and free program? I’m not
going to try to write another version of it just to save a
few bytes of code. Remember that this bootloader just
barely gets in under the 1,024 byte limit and the next
lower limit is 512 bytes, so we’d have to eliminate half the
code to have a chance of getting there (and that isn’t
likely). If you really need to go that low, check out some
of the assembly language bootloaders and PC side
programs that communicate with them.
The critical action takes place in the startBlock
Action(cmd) function:
void startBlockAction(uint8_t cmd)
{
uint8_t tempRec;
uint16_t tempSize;
tempSize = (receiveByte() << 8)
| receiveByte();
// dummy read for type - we only do flash
// NOT EEPROM
tempRec = receiveByte();
if(cmd == ‘B’) blockFlashLoad( tempSize );