SpenceKonde / AVRProg

Objective: AVRProg.h library to include in Arduino sketch which will be able to program another AVR via ISP or UPDI
GNU General Public License v2.0
3 stars 0 forks source link

AVRProg

Objective: AVRProg.h library to include in Arduino sketch which will be able to program another AVR via ISP or UPDI

Target Hardware

Questions

ISP and UPDI modes

Each mode will need separate implementation of the functions. Ideally we want as much as possible to remain the same, though, and we want a single sketch to be able to use more than one programming mode if they so choose....

I mean, once this much is in... there's a clear structure by which others could a new "mode" to support, say, STK500 programming or something, right?

Data format, function signatures

My first thought is that we would have some staticly defined buffers of the maximum sizes we were willing to work with...

// Both of these get memset() to 0xFF on startup...
uint8_t ReadBuffer[512];  // Largest page size is curently the AVR Dx-series
uint8_t WriteBuffer[512]; // Also used for EEPROM - but see below, I think for EEPROM, we ought to have a union with a 16-bit datatype.
uint8_t SignatureRow[64]; // Most of this is empty (in theory - it looks like there may be undocumented stuff here that could act as a
                          // chip ID on classic parts... or maybe just some of them...
                          // But within classic parts, there are a few wacky parts that have something at, 
                          // say, byte 0x2C (t841) in the "device signature impression table"
                          // and the tinyAVR parts do store their cal constants above 32k. 
uint8_t Fuses[16];        // Dx-series defines size of fuses at 16-bytes, read fuses stored here.

Read functions

Write functions

Proposed API

Note above question which influences how these might be named. I am inclined to outlaw unaligned read fros init(...) - initialize an ISP programming interface; will require passing arguments that setPart(uint8_t sig0, uint8_t sig1 uint8_t sig2) - set the device (using the device ID); sig0 is unnecessary as it's always 0x1E. readSignature() - Read the signature

You get the idea. Naturally the modern AVRs would also get a USERROW read and write function; note that tinyAVR and megaAVR can rewrite bytewise in userrow, Dx-series can only erase the whole tyhing... so it ought to have an option to control what it should do if it finds that there's something already written to a byte it is told to write... (return error and don't write, write over it knowing that the data won't match what was written, or read in the parts of the USERROW trhat aren't being written, erase it, and write the rewrite it....

Shortcut to determine flash, pagesize from signatures

Flash = 1024 << (SIGNATURE_1 & 0x0F); 

There are only three exceptions to the rule of flash size and signature: tiny4 and tiny5 (0x90, 0x09 and 0x0A) have 512b of flash, not the expected 1k, the ATmega40 - a 40K flash chip with a 32k signature (what a weirdo flash size! Then again, that whole part is bizarre - also utterly uninteresting for most of us, unless you want to make a battery management system, and are most comfortable programming AVRs (in that case, it's just what the doctor ordered)... And the 4808/4809: 0x96, 0x50/0x51. The sequential SIGNATURE_2 byte would have been 0x10 or 0x11. If they ever release a non-xmega AVR with a 3/4ths flash size like that again, I guess we'll find out if thats a well-reasoned pattern or the result of a slapdash effort to figure out how to signify that in the signature. In support of the "slapdash" theory, the xmega numbering started from 0x40... and, ah, there's already a 0x1E9651 - the ATxmega64b3...

The low six bits of the final signature byte seem to be simply the order in which the parts were designed... including parts that got canceled very close to release. It does look like with the release of the "modern" AVR parts in 2016, they cheated in some sizes, and skipped a few numbers. The high bit in SIGNATURE_2 indicates that there's something weird about the part.

Anyway; simple rules can be used to determine the flash size, page size, and so on from the device ID - basically a list of parts with exceptions, plus the general rules...

Parting thought...

It would sure make it easy to make standalone programmers... One of the incredibly frustrating things about jtag2updi is that it is so far from an Arduino sketch that adapting it to a standlone programmer is nigh impossible. Which kinda sucks, and frankly is sort of holding back the UPDI ecosystem... This is the sort of thing I would love to do if I didn't have three cores to work on already...