_SP12DEV RUNTIME COMMAND DEFINITION ENTRIES Sp12 version 2.0 is a serial mode (in-circuit) programmer for the AVR family of microcontrollers. It should be able to support all of them, but we've added entries to _sp12dev only for the uCs we use ourselves, and for some very close relatives. You can easily add entries for missing family members; it's mostly a matter of copying parts of the `serial programming instruction set' table in the datasheet. Editing _sp12dev also allows you to customize some of sp12's behaviour. Let's have a look at what has been defined for the ATtiny15: begin 0690 -i690 -iT15 The device code consists of two `signature bytes' which the uC will normally report to sp12. In some cases, two different device codes apply to the same device; in that case, there have to be two `begin' lines. (Have a look at the entry for the ATmega103.) When a device is locked, it may not report a valid device code. In that case, recognition has to be forced with the -i option (see sp12.txt). The line `-i690' tells sp12 to expect the device code as identifier, but you can also use a name like -iTiny15, -iTiny15L, or an abbreviation as short as -iT15. Sp12 attempts to match what's on the command line with the -i definitions in _sp12dev by first looking for the first defined character, in this case the `T' (which has to be upper case in _sp12dev, but case is ignored on the command line). Everything before the `T' is ignored; defined characters following the `T' must all be there, and digits must match (be all there and in the right order, no undefined digits allowed), but superfluous letters are allowed. So -S1200 in _sp12dev matches -iAT90S1200 on the command line, and also -iat90ls1200, -iat90s1200a, -iLS1200 and so on. The definition for ATmega8 is just M8, which matches names like -iMega8L, but not -iMega128. DEVICENAME = ATtiny15L FLASHSIZE = 512 EEPROMSIZE = 64 PAGEMODE = 0 PAGESIZE = The above lines define the name, the flash size in (16-bit) words and the size of the eeprom area, also in (8-bit) words. The page mode is zero because the Tiny15's flash is programmed one address at a time, which means there is no page size to define. READ_LOCK = lhlh hlll xxxx xxxx xxxx xxxx xxxx x21x WRITE_LOCK = hlhl hhll hhhh h21h xxxx xxxx xxxx xxxx Commands are defined nearly as shown in the `serial programming instruction set'. That table shows for instance: Write lock bits 1010 1100 1111 1211 xxxx xxxx xxxx xxxx With the `21' marking the lock bits in a slightly different font. Sp12 wants a one belonging to the command written as h, and a zero as l, to get a clear difference between those and the lock or fuse bits, which appear variously as numbers, capital letters or i's and o's. LOCK_MESSAGE = 11 - no lock LOCK_MESSAGE = 10 - write protected LOCK_MESSAGE = 00 - read/write protected You can define any message you like. To sp12 it's just a string, put on screen when the associated read or write command is used. For instance, sp12 -rL results in: 11 are the lock bits read from an ATtiny15L 11 - no lock 10 - write protected 00 - read/write protected NOTE: Some AVR uC lock commands reverse the bit sequence on readout, examples being the AT90S8535, 4434, 2323, 2343 and Tiny22. And these uCs have no `read locks' command; the locks and fuses are separately programmed, but read together. So you write-protect them with sp12 -wL10 while the result can be read back with sp12 -rF resulting in: 01011111 are the fuse bits read from an AT90S8535 11xccccx - no lock 01xccccx - write protected 00xccccx - read/write protected xx0ccccx - serial programming enabled xxxcccc0 - FSTRT reset delay, datasheet p20 The more often used read and write protection is done with a less confusing sp12 -wL00 WRITE_FUSES = hlhl hhll hlhx xxxx xxxx xxxx 87lh hh43 READ_FUSES = lhlh llll xxxx xxxx xxxx xxxx 8765 xx43 Here matters get a little more complicated. The Tiny15 does in fact allow you to write the fuses 6 (SPIEN) and 5 (RSTDSBL). But setting the first to `1' or the second to `0' would block further serial mode programming access, making the uC useless when you have no `high voltage' programmer, or need to program in-circuit. That's why `lh' replaces these fuses in our write command, fixing their values. An accidentally wrong command like sp12 -wF10100010 is largely ignored by the programmer, as shown by its response: 10011110 are the fuse bits written into an ATtiny15L 0x0111xx - BODLEVEL 4V (default 2.7V) x00111xx - brownout detection enabled xx0111CK - reset delay select (datasheet p15) FUSES_MESSAGE = 0x0111xx - BODLEVEL 4V (default 2.7V) FUSES_MESSAGE = x00111xx - brownout detection enabled FUSES_MESSAGE = xx0111CK - reset delay select (datasheet p15) The fuses message can be altered into anything you like. WRITE_HIGH_FUSES = READ_HIGH_FUSES = HIGH_FUSES_MESSAGE = WRITE_EXTD_FUSES = READ_EXTD_FUSES = EXTD_FUSES_MESSAGE = READ_CALIBRATION = llhh hlll xxxx xxxx llll llll oooo oooo CALIB_MESSAGE = single calibration byte (datasheet p55) The final command to define is `read calibration byte', as the little uC as no high or extended fuses. An entry for the rather more complex ATmega8 needs a bit more work: begin 0793 -i793 -iM8 DEVICENAME = ATmega8 FLASHSIZE = 4096 EEPROMSIZE = 512 PAGEMODE = 1 PAGESIZE = 32 The page size has to be entered in (16-bit) words. READ_LOCK = lhlh hlll llll llll xxxx xxxx xxoo oooo WRITE_LOCK = hlhl hhll hhhx xxxx xxxx xxxx hhii iiii LOCK_MESSAGE = xxxx11 - no lock LOCK_MESSAGE = xxxx10 - write protected LOCK_MESSAGE = xxxx00 - read/write protected LOCK_MESSAGE = BTLKxx - Boot lock, datasheet p116 READ_FUSES = lhlh llll llll llll xxxx xxxx oooo oooo WRITE_FUSES = hlhl hhll hlhl llll xxxx xxxx iiii iiii FUSES_MESSAGE = 0xxxxxxx - BODLEVEL 4V (default 2.7V) FUSES_MESSAGE = x0xxxxxx - brownout detection enabled FUSES_MESSAGE = xxSUxxxx - reset delay, datasheet p28 FUSES_MESSAGE = xxxxCKSE - clock select, datasheet p24 WRITE_HIGH_FUSES = hlhl hhll hlhl hlll xxxx xxxx hili iiii READ_HIGH_FUSES = lhlh hlll llll hlll xxxx xxxx oooo oooo Note the h and l between the i's in the write fuses command. Bit-7 is the RSTDSBL fuse; if set to zero, it makes further serial mode programming impossible, so it has been defined high. According to the datasheet we can't change bit-5 (SPIEN), but it has been defined low anyway. Taking away bit-7 causes sp12 to expect a -wH string which is seven bits long, for instance sp12 -wH1010001 resulting in: 1010001 are the high fuse bits written into an ATmega8 1xxxxxxx - PC6 is reset pin x0xxxxxx - WDT always on xx0xxxxx - serial programming enabled xxx0xxxx - CKOPT max, datasheet p24 xxxx0xxx - eeprom not erased xxxxxBZx - boot size, datasheet p215 xxxxxxx0 - reset at boot loader, p204 Assuming you're using a fixed pitch font, the 7-bit string will be correctly aligned with the 8-bit message lines. HIGH_FUSES_MESSAGE = 1xxxxxxx - PC6 is reset pin HIGH_FUSES_MESSAGE = x0xxxxxx - WDT always on HIGH_FUSES_MESSAGE = xx0xxxxx - serial programming enabled HIGH_FUSES_MESSAGE = xxx0xxxx - CKOPT max, datasheet p24 HIGH_FUSES_MESSAGE = xxxx0xxx - eeprom not erased HIGH_FUSES_MESSAGE = xxxxxBZx - boot size, datasheet p215 HIGH_FUSES_MESSAGE = xxxxxxx0 - reset at boot loader, p204 WRITE_EXTD_FUSES = READ_EXTD_FUSES = EXTD_FUSES_MESSAGE = READ_CALIBRATION = llhh hlll llxx xxxx llll llll oooo oooo CALIB_MESSAGE = four calibration bytes (datasheet p28 p29 p218) An entry for the new Tiny2313 is no more difficult than the above, but do note that use of the `debugwire' feature means you lose the resetpin - so it can't be used when you depend on a serial mode programmer like sp12. The entry in the current _sp12dev guards accidental changes of the DWEN, SPIEN and RSTDISBL fuses: WRITE_HIGH_FUSES = hlhl hhll hlhl hlll xxxx xxxx hili iiih A new command introduced in the Tiny2313 is `poll rdy/bsy': POLL_RDY_BSY = hhhh llll llll llll xxxx xxxx xxxx xxxo When this command is part of an _sp12dev entry, the -o option is ignored. And for devices which obey this new programming command, -o must be ignored, as -o1 would cause errors. I hope it will indeed prove easy to add entries to _sp12dev. Do be sure to use the latest datasheets and errata when making them. I had some trouble with an older sheet for the Mega163, which contained a totally wrong `read lock bits' command...