Add support for ATMega163.

Add support for reading/writing ATMega163 lock and fuse bits.
Unfortunately, in looking at the specs for other ATMega parts, they
use entirely different instruction formats for these commands.  Thus,
these routines won't work for the ATMega103, for example.

Add support for sending raw command bytes via the interactive terminal
interface.  This allows one to execute any programming instruction on
the target device, whether or not avrprog supports it explicitly or
not.  Thus, one can use this feature to program fuse / lock bits, or
access any other feature of a current or future device that avrprog
does not know how to do.

Add in comments, an experimental instruction format in the
configuration file.  If this works out, it would allow supporting new
parts and non-orthoganal instructions across existing parts without
making avrprog code changes.


git-svn-id: svn://svn.savannah.nongnu.org/avrdude/trunk/avrdude@99 81a1dc3b-b13d-400b-aceb-764788c761c2
This commit is contained in:
Brian S. Dean 2001-11-19 17:44:24 +00:00
parent 76fb1330af
commit f1af5d3981
6 changed files with 338 additions and 91 deletions

214
avr.c
View File

@ -49,75 +49,6 @@ extern PROGRAMMER * pgm;
char * avr_version = "$Id$";
/* Need to add information for 2323, 2343, and 4414 */
#if 0
struct avrpart parts[] = {
{"AT90S1200", "1200", 20000,
{{0, 64, 0, 0, 9000, 20000, {0x00, 0xff }, NULL}, /* eeprom */
{0, 1024, 0, 0, 9000, 20000, {0xff, 0 }, NULL}}}, /* flash */
{"AT90S2313", "2313", 20000,
{{0, 128, 0, 0, 9000, 20000, {0x80, 0x7f }, NULL}, /* eeprom */
{0, 2048, 0, 0, 9000, 20000, {0x7f, 0 }, NULL}}}, /* flash */
{"AT90S2333", "2333", 20000,
{{0, 128, 0, 0, 9000, 20000, {0x00, 0xff }, NULL}, /* eeprom */
{0, 2048, 0, 0, 9000, 20000, {0xff, 0 }, NULL}}}, /* flash */
{"AT90S4433", "4433", 20000,
{{0, 256, 0, 0, 9000, 20000, {0x00, 0xff }, NULL}, /* eeprom */
{0, 4096, 0, 0, 9000, 20000, {0xff, 0 }, NULL}}}, /* flash */
{"AT90S4434", "4434", 20000,
{{0, 256, 0, 0, 9000, 20000, {0x00, 0xff }, NULL}, /* eeprom */
{0, 4096, 0, 0, 9000, 20000, {0xff, 0 }, NULL}}}, /* flash */
{"AT90S8515", "8515", 20000,
{{0, 512, 0, 0, 9000, 20000, {0x80, 0x7f }, NULL}, /* eeprom */
{0, 8192, 0, 0, 9000, 20000, {0x7f, 0x00 }, NULL}}}, /* flash */
{"AT90S8535", "8535", 20000,
{{0, 512, 0, 0, 9000, 20000, {0x00, 0xff }, NULL}, /* eeprom */
{0, 8192, 0, 0, 9000, 20000, {0xff, 0x00 }, NULL}}}, /* flash */
{"ATMEGA103", "103", 56000*2,
{{0, 4096, 0, 0, 64000, 69000, {0x80, 0x7f }, NULL}, /* eeprom */
{1, 131072, 256, 512, 22000, 56000, {0xff, 0x00 }, NULL}}}, /* flash */
};
#define N_AVRPARTS (sizeof(parts)/sizeof(struct avrpart))
int avr_list_parts(FILE * f, char * prefix)
{
int i;
for (i=0; i<N_AVRPARTS; i++) {
fprintf(f, "%s%s = %s\n",
prefix, parts[i].optiontag, parts[i].partdesc);
}
return i;
}
struct avrpart * avr_find_part(char * p)
{
int i;
for (i=0; i<N_AVRPARTS; i++) {
if (strcmp(parts[i].optiontag, p)==0) {
return &parts[i];
}
}
return NULL;
}
#endif
AVRPART * avr_new_part(void)
{
AVRPART * p;
@ -228,6 +159,133 @@ int avr_cmd(int fd, unsigned char cmd[4], unsigned char res[4])
}
/*
* read a calibration byte
*/
unsigned char avr_read_calibration(int fd, AVRPART * p)
{
unsigned char cmd[4];
unsigned char res[4];
LED_ON(fd, pgm->pinno[PIN_LED_PGM]);
LED_OFF(fd, pgm->pinno[PIN_LED_ERR]);
cmd[0] = 0x38;
cmd[1] = 0x00; /* don't care */
cmd[2] = 0x00;
cmd[3] = 0x00; /* don't care */
avr_cmd(fd, cmd, res);
LED_OFF(fd, pgm->pinno[PIN_LED_PGM]);
return res[3]; /* calibration byte */
}
/*
* read a fuse byte
*/
unsigned char avr_read_fuse(int fd, AVRPART * p, int high)
{
unsigned char cmd[4];
unsigned char res[4];
static unsigned char cmdbyte1[2] = { 0x50, 0x58 };
static unsigned char cmdbyte2[2] = { 0x00, 0x08 };
LED_ON(fd, pgm->pinno[PIN_LED_PGM]);
LED_OFF(fd, pgm->pinno[PIN_LED_ERR]);
cmd[0] = cmdbyte1[high];
cmd[1] = cmdbyte2[high];
cmd[2] = 0; /* don't care */
cmd[3] = 0; /* don't care */
avr_cmd(fd, cmd, res);
LED_OFF(fd, pgm->pinno[PIN_LED_PGM]);
return res[3]; /* fuse bits */
}
/*
* write a fuse byte
*/
int avr_write_fuse(int fd, AVRPART * p, int high, unsigned char b)
{
unsigned char cmd[4];
unsigned char res[4];
static unsigned char cmdbyte[2] = { 0xa0, 0xa8 };
LED_ON(fd, pgm->pinno[PIN_LED_PGM]);
LED_OFF(fd, pgm->pinno[PIN_LED_ERR]);
cmd[0] = 0xac;
cmd[1] = cmdbyte[high];
cmd[2] = 0x00; /* don't care */
cmd[3] = b; /* fuse bits */
avr_cmd(fd, cmd, res);
usleep(2000);
LED_OFF(fd, pgm->pinno[PIN_LED_PGM]);
return 0;
}
/*
* read a lock byte
*/
unsigned char avr_read_lock(int fd, AVRPART * p)
{
unsigned char cmd[4];
unsigned char res[4];
LED_ON(fd, pgm->pinno[PIN_LED_PGM]);
LED_OFF(fd, pgm->pinno[PIN_LED_ERR]);
cmd[0] = 0x58;
cmd[1] = 0x00;
cmd[2] = 0;
cmd[3] = 0; /* don't care */
avr_cmd(fd, cmd, res);
LED_OFF(fd, pgm->pinno[PIN_LED_PGM]);
return res[3]; /* lock bits */
}
/*
* write a lock byte
*/
int avr_write_lock(int fd, AVRPART * p, unsigned char b)
{
unsigned char cmd[4];
unsigned char res[4];
LED_ON(fd, pgm->pinno[PIN_LED_PGM]);
LED_OFF(fd, pgm->pinno[PIN_LED_ERR]);
cmd[0] = 0x5c;
cmd[1] = 0xe0;
cmd[2] = 0; /* don't care */
cmd[3] = b; /* lock bits */
avr_cmd(fd, cmd, res);
usleep(2000);
LED_OFF(fd, pgm->pinno[PIN_LED_PGM]);
return 0;
}
/*
* read a byte of data from the indicated memory region
*/
@ -265,19 +323,20 @@ unsigned char avr_read_byte(int fd, AVRPART * p,
/*
* Read the entirety of the specified memory type into the
* corresponding buffer of the avrpart pointed to by 'p'.
* corresponding buffer of the avrpart pointed to by 'p'. If size =
* 0, read the entire contents, otherwize, read 'size' bytes.
*
* Return the number of bytes read, or -1 if an error occurs.
*/
int avr_read(int fd, AVRPART * p, int memtype)
* Return the number of bytes read, or -1 if an error occurs. */
int avr_read(int fd, AVRPART * p, int memtype, int size)
{
unsigned char rbyte;
unsigned long i;
unsigned char * buf;
int size;
buf = p->mem[memtype].buf;
size = p->mem[memtype].size;
if (size == 0) {
size = p->mem[memtype].size;
}
for (i=0; i<size; i++) {
rbyte = avr_read_byte(fd, p, memtype, i);
@ -292,6 +351,9 @@ int avr_read(int fd, AVRPART * p, int memtype)
}
/*
* write a byte of data to the indicated memory region
*/
@ -643,6 +705,8 @@ char * avr_memtstr(int memtype)
switch (memtype) {
case AVR_M_EEPROM : return "eeprom"; break;
case AVR_M_FLASH : return "flash"; break;
case AVR_M_FUSE : return "fuse-bit"; break;
case AVR_M_LOCK : return "fock-bit"; break;
default : return "unknown-memtype"; break;
}
}

14
avr.h
View File

@ -42,6 +42,8 @@
*/
#define AVR_M_EEPROM 0
#define AVR_M_FLASH 1
#define AVR_M_FUSE 2
#define AVR_M_LOCK 3
#define AVR_MAXMEMTYPES 2 /* just flash and eeprom */
@ -86,10 +88,20 @@ unsigned char avr_txrx(int fd, unsigned char byte);
int avr_cmd(int fd, unsigned char cmd[4], unsigned char res[4]);
unsigned char avr_read_calibration(int fd, AVRPART * p);
unsigned char avr_read_fuse(int fd, AVRPART * p, int high);
int avr_write_fuse(int fd, AVRPART * p, int high, unsigned char b);
unsigned char avr_read_lock(int fd, AVRPART * p);
int avr_write_lock(int fd, AVRPART * p, unsigned char b);
unsigned char avr_read_byte(int fd, AVRPART * p,
int memtype, unsigned long addr);
int avr_read(int fd, AVRPART * p, int memtype);
int avr_read(int fd, AVRPART * p, int memtype, int size);
int avr_write_bank(int fd, AVRPART * p, int memtype,
unsigned short bank);

View File

@ -360,6 +360,25 @@ part
readback_p1 = 0xff;
readback_p2 = 0xff;
;
/*
instructions
instr "pe", "programming enable" [ "1010 1100", "0101 0011", "xxxx xxxx", "xxxx xxxx" ];
instr "ce", "chip erase" [ "1010 1100", "100x xxxx", "xxxx xxxx", "xxxx xxxx" ];
instr "rpm", "read program memory" [ "0010 H000", "xxxa aaaa", "bbbb bbbb", "oooo oooo" ];
instr "lpmp" "load program memory page" [ "0100 H000", "xxxx xxxx", "xxbb bbbb", "iiii iiii" ];
instr "wpmp", "write program memory page" [ "0100 1100", "xxxa aaaa", "bbxx xxxx", "xxxx xxxx" ];
instr "rep", "read eeprom memory" [ "1010 0000", "xxxx xxxa", "bbbb bbbb", "oooo oooo" ];
instr "wep", "write eeprom memory" [ "1100 0000", "xxxx xxxa", "bbbb bbbb", "iiii iiii" ];
instr "rlb", "read lock bits" [ "0101 1000", "0000 0000", "xxxx 0xxx", "xxoo oooo" ];
instr "wlb", "write lock bits" [ "1010 1100", "111x xxxx", "xxxx xxxx", "11ii iiii" ];
instr "rsb", "read signature byte" [ "0011 0000", "xxxx xxxx", "xxxx xxbb", "oooo oooo" ];
instr "wfb", "write fuse bits" [ "1010 1100", "1010 0000", "xxxx xxxx", "ii11 iiii" ];
instr "wfhb", "write fuse high bits" [ "1010 1100", "1010 1000", "xxxx xxxx", "1111 1iii" ];
instr "rfb", "read fuse bits" [ "0101 0000", "0000 0000", "xxxx xxxx", "ooxx oooo" ];
instr "rfhb", "read fuse high bits" [ "0101 1000", "0000 1000", "xxxx xxxx", "xxxx 1ooo" ];
instr "rcb", "read calibration byte" [ "0011 1000", "xxxx xxxx", "0000 0000", "oooo oooo" ];
;
*/
;
part

4
main.c
View File

@ -893,7 +893,7 @@ int main(int argc, char * argv [])
*/
fprintf(stderr, "%s: reading %s memory:\n",
progname, avr_memtstr(memtype));
rc = avr_read(fd, p, memtype);
rc = avr_read(fd, p, memtype, 0);
if (rc < 0) {
fprintf(stderr, "%s: failed to read all of %s memory, rc=%d\n",
progname, avr_memtstr(memtype), rc);
@ -969,7 +969,7 @@ int main(int argc, char * argv [])
progname, avr_memtstr(memtype), inputf);
fprintf(stderr, "%s: reading on-chip %s data:\n",
progname, avr_memtstr(memtype));
rc = avr_read(fd, v, memtype);
rc = avr_read(fd, v, memtype, vsize);
if (rc < 0) {
fprintf(stderr, "%s: failed to read all of %s memory, rc=%d\n",
progname, avr_memtstr(memtype), rc);

24
ppi.c
View File

@ -35,6 +35,8 @@
#include "ppi.h"
#define SLOW_TOGGLE 0
extern char * progname;
struct ppipins_t {
@ -224,8 +226,17 @@ int ppi_setall(int fd, int reg, int val)
int ppi_pulse(int fd, int reg, int bit)
{
ppi_toggle(fd, reg, bit);
#if SLOW_TOGGLE
usleep(1000);
#endif
ppi_toggle(fd, reg, bit);
#if SLOW_TOGGLE
usleep(1000);
#endif
return 0;
}
@ -246,6 +257,10 @@ int ppi_setpin(int fd, int pin, int value)
else
ppi_clr(fd, pins[pin].reg, pins[pin].bit);
#if SLOW_TOGGLE
usleep(1000);
#endif
return 0;
}
@ -280,8 +295,17 @@ int ppi_pulsepin(int fd, int pin)
pin--;
ppi_toggle(fd, pins[pin].reg, pins[pin].bit);
#if SLOW_TOGGLE
usleep(1000);
#endif
ppi_toggle(fd, pins[pin].reg, pins[pin].bit);
#if SLOW_TOGGLE
usleep(1000);
#endif
return 0;
}

154
term.c
View File

@ -64,12 +64,16 @@ int cmd_erase (int fd, struct avrpart * p, int argc, char *argv[]);
int cmd_sig (int fd, struct avrpart * p, int argc, char *argv[]);
int cmd_cal (int fd, struct avrpart * p, int argc, char *argv[]);
int cmd_part (int fd, struct avrpart * p, int argc, char *argv[]);
int cmd_help (int fd, struct avrpart * p, int argc, char *argv[]);
int cmd_quit (int fd, struct avrpart * p, int argc, char *argv[]);
int cmd_send (int fd, struct avrpart * p, int argc, char *argv[]);
struct command cmd[] = {
{ "dump", cmd_dump, "dump memory : %s [eeprom|flash] <addr> <N-Bytes>" },
@ -77,7 +81,9 @@ struct command cmd[] = {
{ "write", cmd_write, "write memory : %s [eeprom|flash] <addr> <b1> <b2> ... <bN>" },
{ "erase", cmd_erase, "perform a chip erase" },
{ "sig", cmd_sig, "display device signature bytes" },
{ "cal", cmd_cal, "display device calibration byte" },
{ "part", cmd_part, "display the current part settings" },
{ "send", cmd_send, "send a command : %s <b1> <b2> <b3> <b4>" },
{ "help", cmd_help, "help" },
{ "?", cmd_help, "help" },
{ "quit", cmd_quit, "quit" }
@ -215,7 +221,7 @@ int cmd_dump(int fd, struct avrpart * p, int argc, char * argv[])
}
else {
if (!((argc == 2) || (argc == 4))) {
fprintf(stderr, "Usage: dump flash|eeprom [<addr> <len>]\n");
fprintf(stderr, "Usage: dump flash|eeprom|fuse|lock [<addr> <len>]\n");
return -1;
}
@ -226,6 +232,14 @@ int cmd_dump(int fd, struct avrpart * p, int argc, char * argv[])
else if (strncasecmp(argv[1],"eeprom",l)==0) {
memtype = AVR_M_EEPROM;
}
else if ((strncasecmp(argv[1],"fuse",l)==0)||
(strncasecmp(argv[1],"fuse-bit",l)==0)) {
memtype = AVR_M_FUSE;
}
else if ((strncasecmp(argv[1],"lock",l)==0)||
(strncasecmp(argv[1],"lock-bit",l)==0)) {
memtype = AVR_M_LOCK;
}
else {
fprintf(stderr, "%s (dump): invalid memory type \"%s\"\n",
progname, argv[1]);
@ -249,7 +263,20 @@ int cmd_dump(int fd, struct avrpart * p, int argc, char * argv[])
}
}
maxsize = p->mem[memtype].size;
maxsize = 0;
switch (memtype) {
case AVR_M_FLASH:
case AVR_M_EEPROM:
maxsize = p->mem[memtype].size;
break;
case AVR_M_FUSE:
maxsize = 2;
break;
case AVR_M_LOCK:
maxsize = 1;
break;
}
if (argc == 2) {
addr = 0;
@ -273,8 +300,20 @@ int cmd_dump(int fd, struct avrpart * p, int argc, char * argv[])
return -1;
}
for (i=0; i<len; i++)
buf[i] = avr_read_byte(fd, p, memtype, addr+i);
for (i=0; i<len; i++) {
switch (memtype) {
case AVR_M_FLASH:
case AVR_M_EEPROM:
buf[i] = avr_read_byte(fd, p, memtype, addr+i);
break;
case AVR_M_FUSE:
buf[i] = avr_read_fuse(fd, p, addr+i);
break;
case AVR_M_LOCK:
buf[i] = avr_read_lock(fd, p);
break;
}
}
hexdump_buf(stdout, addr, buf, len);
@ -298,8 +337,8 @@ int cmd_write(int fd, struct avrpart * p, int argc, char * argv[])
int werror;
if (argc < 4) {
fprintf(stderr,
"Usage: write flash|eeprom <addr> <byte1> <byte2> ... byteN>\n");
fprintf(stderr, "Usage: write flash|eeprom|fuse <addr> <byte1> "
"<byte2> ... byteN>\n");
return -1;
}
@ -310,19 +349,39 @@ int cmd_write(int fd, struct avrpart * p, int argc, char * argv[])
else if (strncasecmp(argv[1],"eeprom",l)==0) {
memtype = AVR_M_EEPROM;
}
else if ((strncasecmp(argv[1],"fuse",l)==0)||
(strncasecmp(argv[1],"fuse-bit",l)==0)) {
memtype = AVR_M_FUSE;
}
else if ((strncasecmp(argv[1],"lock",l)==0)||
(strncasecmp(argv[1],"lock-bit",l)==0)) {
memtype = AVR_M_LOCK;
}
else {
fprintf(stderr, "%s (write): invalid memory type \"%s\"\n",
progname, argv[1]);
return -1;
}
if (p->mem[memtype].paged) {
fprintf(stderr, "%s (write): sorry, interactive write of page addressed "
"memory is not supported\n", progname);
return -1;
}
maxsize = 0;
maxsize = p->mem[memtype].size;
switch (memtype) {
case AVR_M_FLASH:
case AVR_M_EEPROM:
if (p->mem[memtype].paged) {
fprintf(stderr, "%s (write): sorry, interactive write of page "
"addressed memory is not supported\n", progname);
return -1;
}
maxsize = p->mem[memtype].size;
break;
case AVR_M_FUSE:
maxsize = 2;
break;
case AVR_M_LOCK:
maxsize = 1;
break;
}
addr = strtoul(argv[2], &e, 0);
if (*e || (e == argv[2])) {
@ -360,13 +419,28 @@ int cmd_write(int fd, struct avrpart * p, int argc, char * argv[])
if (*e || (e == argv[i])) {
fprintf(stderr, "%s (write): can't parse byte \"%s\"\n",
progname, argv[i]);
free(buf);
return -1;
}
}
LED_OFF(fd, pgm->pinno[PIN_LED_ERR]);
for (werror=0, i=0; i<len; i++) {
rc = avr_write_byte(fd, p, memtype, addr+i, buf[i]);
rc = 0;
switch (memtype) {
case AVR_M_EEPROM:
case AVR_M_FLASH:
rc = avr_write_byte(fd, p, memtype, addr+i, buf[i]);
break;
case AVR_M_FUSE:
rc = avr_write_fuse(fd, p, addr+i, buf[i]);
break;
case AVR_M_LOCK:
rc = avr_write_lock(fd, p, buf[i]);
break;
}
if (rc) {
fprintf(stderr, "%s (write): error writing 0x%02x at 0x%04x\n",
progname, buf[i], addr+i);
@ -385,6 +459,49 @@ int cmd_write(int fd, struct avrpart * p, int argc, char * argv[])
}
int cmd_send(int fd, struct avrpart * p, int argc, char * argv[])
{
unsigned char cmd[4], res[4];
char * e;
int i;
int len;
if (argc != 5) {
fprintf(stderr, "Usage: send <byte1> <byte2> <byte3> <byte4>\n");
return -1;
}
/* number of bytes to write at the specified address */
len = argc - 1;
/* load command bytes */
for (i=1; i<argc; i++) {
cmd[i-1] = strtoul(argv[i], &e, 0);
if (*e || (e == argv[i])) {
fprintf(stderr, "%s (send): can't parse byte \"%s\"\n",
progname, argv[i]);
return -1;
}
}
LED_OFF(fd, pgm->pinno[PIN_LED_ERR]);
avr_cmd(fd, cmd, res);
/*
* display results
*/
fprintf(stderr, "results:");
for (i=0; i<len; i++)
fprintf(stderr, " %02x", res[i]);
fprintf(stderr, "\n");
fprintf(stdout, "\n");
return 0;
}
int cmd_erase(int fd, struct avrpart * p, int argc, char * argv[])
{
fprintf(stderr, "%s: erasing chip\n", progname);
@ -418,6 +535,17 @@ int cmd_sig(int fd, struct avrpart * p, int argc, char * argv[])
}
int cmd_cal(int fd, struct avrpart * p, int argc, char * argv[])
{
unsigned char byte;
byte = avr_read_calibration(fd, p);
fprintf(stdout, "\nDevice calibration = 0x%02x\n\n", byte);
return 0;
}
int cmd_quit(int fd, struct avrpart * p, int argc, char * argv[])
{
return 1;