Implement STK500 (v2) HVSP mode.

* stk500v2.c: Add new functions for HVSP support.
* stk500v2.h: Add prototype for the stk500hvsp programmer.
* avrpart.h: Add fields to struct avrpart for new features.
* config_gram.y: Extend the configuration syntax for new
features required for HVSP support.
* lexer.l: (Ditto.)
* avrdude.conf.in: Add HVSP support for ATtiny13 and
ATtiny45 as an example.
* avrdude.1: Document stk500hvsp.
* doc/avrdude.texi: (Ditto.)


git-svn-id: svn://svn.savannah.nongnu.org/avrdude/trunk/avrdude@595 81a1dc3b-b13d-400b-aceb-764788c761c2
This commit is contained in:
joerg_wunsch 2006-07-21 21:53:49 +00:00
parent b6a0b21a18
commit e9b535423e
9 changed files with 467 additions and 109 deletions

View File

@ -1,3 +1,17 @@
2006-07-21 Joerg Wunsch <j@uriah.heep.sax.de>
Implement STK500 (v2) HVSP mode.
* stk500v2.c: Add new functions for HVSP support.
* stk500v2.h: Add prototype for the stk500hvsp programmer.
* avrpart.h: Add fields to struct avrpart for new features.
* config_gram.y: Extend the configuration syntax for new
features required for HVSP support.
* lexer.l: (Ditto.)
* avrdude.conf.in: Add HVSP support for ATtiny13 and
ATtiny45 as an example.
* avrdude.1: Document stk500hvsp.
* doc/avrdude.texi: (Ditto.)
2006-07-21 Joerg Wunsch <j@uriah.heep.sax.de>
* avrpart.c: Print the very verbose memory details only

View File

@ -99,8 +99,9 @@ Atmel's STK500 programmer is also supported and connects to a serial
port.
Both, firmware versions 1.x and 2.x can be handled, but require a
different programmer type specification (by now).
Using firmware version 2, parallel programming is also supported
(programmer type stk500pp).
Using firmware version 2, high-voltage programming is also supported,
both parallel and serial
(programmer types stk500pp and stk500hvsp).
.Pp
The simple serial programmer described in Atmel's application note
AVR910, and the bootloader described in Atmel's application note

View File

@ -15,7 +15,8 @@
# programmer
# id = <id1> [, <id2> [, <id3>] ...] ; # <idN> are quoted strings
# desc = <description> ; # quoted string
# type = par | stk500 | stk500v2 | stk500pp | avr910 | jtagmki | jtagmkii; # programmer type
# type = par | stk500 | stk500v2 | stk500pp | stk500hvsp |
# avr910 | jtagmki | jtagmkii; # programmer type
# baudrate = <num> ; # baudrate for avr910-programmer
# vcc = <num1> [, <num2> ... ] ; # pin number(s)
# reset = <num> ; # pin number
@ -50,7 +51,7 @@
# # STK500v2 parameters, to be taken from Atmel's XML files
# timeout = <num> ;
# stabdelay = <num> ;
# cmdexdelay = <num> ;
# cmdexedelay = <num> ;
# synchloops = <num> ;
# bytedelay = <num> ;
# pollvalue = <num> ;
@ -62,22 +63,26 @@
# delay = <num> ;
# blocksize = <num> ;
# readsize = <num> ;
# # STK500v2 parallel programming parameters, from XML
# pp_controlstack = <num>, <num>, ...;
# ppenterstabdelay = <num>;
# progmodedelay = <num>;
# hvspcmdexedelay = <num> ;
# # STK500v2 HV programming parameters, from XML
# pp_controlstack = <num>, <num>, ...; # PP only
# hvsp_controlstack = <num>, <num>, ...; # HVSP only
# hventerstabdelay = <num>;
# progmodedelay = <num>; # PP only
# latchcycles = <num>;
# togglevtg = <num>;
# poweroffdelay = <num>;
# resetdelayms = <num>;
# resetdelayus = <num>;
# ppleavestabdelay = <num>;
# hvleavestabdelay = <num>;
# resetdelay = <num>;
# chiperasepulsewidth = <num>;
# synchcycles = <num>; # HVSP only
# chiperasepulsewidth = <num>; # PP only
# chiperasepolltimeout = <num>;
# programfusepulsewidth = <num>;
# chiperasetime = <num>; # HVSP only
# programfusepulsewidth = <num>; # PP only
# programfusepolltimeout = <num>;
# programlockpulsewidth = <num>;
# programlockpulsewidth = <num>; # PP only
# programlockpolltimeout = <num>;
# # JTAG ICE mkII parameters, also from XML files
# allowfullpagebitstream = <yes/no> ;
@ -281,6 +286,12 @@ programmer
type = stk500pp;
;
programmer
id = "stk500hvsp";
desc = "Atmel STK500 V2 in high-voltage serial programming mode";
type = stk500hvsp;
;
programmer
id = "avr910";
desc = "Atmel Low Cost Serial Programmer";
@ -721,8 +732,30 @@ part
postdelay = 1;
pollmethod = 1;
hvsp_controlstack =
0x4C, 0x0C, 0x1C, 0x2C, 0x3C, 0x64, 0x74, 0x66,
0x68, 0x78, 0x68, 0x68, 0x7A, 0x6A, 0x68, 0x78,
0x78, 0x7D, 0x6D, 0x0C, 0x80, 0x40, 0x20, 0x10,
0x11, 0x08, 0x04, 0x02, 0x03, 0x08, 0x04, 0x00;
hventerstabdelay = 100;
progmodedelay = 0;
hvspcmdexedelay = 0;
synchcycles = 6;
latchcycles = 1;
togglevtg = 1;
poweroffdelay = 25;
resetdelayms = 0;
resetdelayus = 90;
hvleavestabdelay = 100;
resetdelay = 25;
chiperasepolltimeout = 40;
chiperasetime = 0;
programfusepolltimeout = 25;
programlockpolltimeout = 25;
memory "eeprom"
size = 64;
page_size = 4;
min_write_delay = 4000;
max_write_delay = 4000;
readback_p1 = 0xff;
@ -1624,14 +1657,14 @@ part
0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F,
0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B,
0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00;
ppenterstabdelay = 100;
hventerstabdelay = 100;
progmodedelay = 0;
latchcycles = 0;
togglevtg = 0;
poweroffdelay = 0;
resetdelayms = 0;
resetdelayus = 0;
ppleavestabdelay = 15;
hvleavestabdelay = 15;
resetdelay = 15;
chiperasepulsewidth = 15;
chiperasepolltimeout = 0;
@ -2412,14 +2445,14 @@ part
0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F,
0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B,
0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00;
ppenterstabdelay = 100;
hventerstabdelay = 100;
progmodedelay = 100;
latchcycles = 6;
togglevtg = 0;
poweroffdelay = 0;
resetdelayms = 0;
resetdelayus = 0;
ppleavestabdelay = 15;
hvleavestabdelay = 15;
resetdelay = 15;
chiperasepulsewidth = 0;
chiperasepolltimeout = 10;
@ -5876,8 +5909,30 @@ part
postdelay = 1;
pollmethod = 1;
hvsp_controlstack =
0x4C, 0x0C, 0x1C, 0x2C, 0x3C, 0x64, 0x74, 0x66,
0x68, 0x78, 0x68, 0x68, 0x7A, 0x6A, 0x68, 0x78,
0x78, 0x7D, 0x6D, 0x0C, 0x80, 0x40, 0x20, 0x10,
0x11, 0x08, 0x04, 0x02, 0x03, 0x08, 0x04, 0x00;
hventerstabdelay = 100;
progmodedelay = 0;
hvspcmdexedelay = 0;
synchcycles = 6;
latchcycles = 1;
togglevtg = 1;
poweroffdelay = 25;
resetdelayms = 0;
resetdelayus = 50;
hvleavestabdelay = 100;
resetdelay = 25;
chiperasepolltimeout = 40;
chiperasetime = 0;
programfusepolltimeout = 25;
programlockpolltimeout = 25;
memory "eeprom"
size = 256;
page_size = 4;
min_write_delay = 4000;
max_write_delay = 4500;
readback_p1 = 0xff;

View File

@ -121,21 +121,24 @@ typedef struct avrpart {
enum ctl_stack_t ctl_stack_type; /* what to use the ctl stack for */
unsigned char controlstack[CTL_STACK_SIZE]; /* stk500v2 PP/HVSP ctl stack */
int ppenterstabdelay; /* stk500 v2 pp mode parameter */
int progmodedelay; /* stk500 v2 pp mode parameter */
int latchcycles; /* stk500 v2 pp mode parameter */
int togglevtg; /* stk500 v2 pp mode parameter */
int poweroffdelay; /* stk500 v2 pp mode parameter */
int resetdelayms; /* stk500 v2 pp mode parameter */
int resetdelayus; /* stk500 v2 pp mode parameter */
int ppleavestabdelay; /* stk500 v2 pp mode parameter */
int resetdelay; /* stk500 v2 pp mode parameter */
int chiperasepulsewidth; /* stk500 v2 pp mode parameter */
int chiperasepolltimeout; /* stk500 v2 pp mode parameter */
int programfusepulsewidth; /* stk500 v2 pp mode parameter */
int programfusepolltimeout; /* stk500 v2 pp mode parameter */
int programlockpulsewidth; /* stk500 v2 pp mode parameter */
int programlockpolltimeout; /* stk500 v2 pp mode parameter */
int hventerstabdelay; /* stk500 v2 hv mode parameter */
int progmodedelay; /* stk500 v2 hv mode parameter */
int latchcycles; /* stk500 v2 hv mode parameter */
int togglevtg; /* stk500 v2 hv mode parameter */
int poweroffdelay; /* stk500 v2 hv mode parameter */
int resetdelayms; /* stk500 v2 hv mode parameter */
int resetdelayus; /* stk500 v2 hv mode parameter */
int hvleavestabdelay; /* stk500 v2 hv mode parameter */
int resetdelay; /* stk500 v2 hv mode parameter */
int chiperasepulsewidth; /* stk500 v2 hv mode parameter */
int chiperasepolltimeout; /* stk500 v2 hv mode parameter */
int chiperasetime; /* stk500 v2 hv mode parameter */
int programfusepulsewidth; /* stk500 v2 hv mode parameter */
int programfusepolltimeout; /* stk500 v2 hv mode parameter */
int programlockpulsewidth; /* stk500 v2 hv mode parameter */
int programlockpolltimeout; /* stk500 v2 hv mode parameter */
int synchcycles; /* stk500 v2 hv mode parameter */
int hvspcmdexedelay; /* stk500 v2 xml file parameter */
unsigned char idr; /* JTAG ICE mkII XML file parameter */
unsigned char rampz; /* JTAG ICE mkII XML file parameter */

View File

@ -121,6 +121,7 @@ static int parse_cmdbits(OPCODE * op);
%token K_SIGNATURE
%token K_SIZE
%token K_STK500
%token K_STK500HVSP
%token K_STK500PP
%token K_STK500V2
%token K_AVR910
@ -138,6 +139,7 @@ static int parse_cmdbits(OPCODE * op);
%token K_TIMEOUT
%token K_STABDELAY
%token K_CMDEXEDELAY
%token K_HVSPCMDEXEDELAY
%token K_SYNCHLOOPS
%token K_BYTEDELAY
%token K_POLLVALUE
@ -149,25 +151,29 @@ static int parse_cmdbits(OPCODE * op);
%token K_DELAY
%token K_BLOCKSIZE
%token K_READSIZE
/* PP mode */
%token K_PPENTERSTABDELAY
/* HV mode */
%token K_HVENTERSTABDELAY
%token K_PROGMODEDELAY
%token K_LATCHCYCLES
%token K_TOGGLEVTG
%token K_POWEROFFDELAY
%token K_RESETDELAYMS
%token K_RESETDELAYUS
%token K_PPLEAVESTABDELAY
%token K_HVLEAVESTABDELAY
%token K_RESETDELAY
%token K_SYNCHCYCLES
%token K_HVCMDEXEDELAY
%token K_CHIPERASEPULSEWIDTH
%token K_CHIPERASEPOLLTIMEOUT
%token K_CHIPERASETIME
%token K_PROGRAMFUSEPULSEWIDTH
%token K_PROGRAMFUSEPOLLTIMEOUT
%token K_PROGRAMLOCKPULSEWIDTH
%token K_PROGRAMLOCKPOLLTIMEOUT
%token K_PP_CONTROLSTACK
%token K_HVSP_CONTROLSTACK
/* JTAG ICE mkII specific parameters */
%token K_ALLOWFULLPAGEBITSTREAM /*
@ -372,6 +378,12 @@ prog_parm :
}
} |
K_TYPE TKN_EQUAL K_STK500HVSP {
{
stk500hvsp_initpgm(current_prog);
}
} |
K_TYPE TKN_EQUAL K_STK500PP {
{
stk500pp_initpgm(current_prog);
@ -614,6 +626,48 @@ part_parm :
}
} |
K_HVSP_CONTROLSTACK TKN_EQUAL num_list {
{
TOKEN * t;
unsigned nbytes;
int ok;
if (current_part->ctl_stack_type != CTL_STACK_NONE)
{
fprintf(stderr,
"%s: error at line %d of %s: "
"control stack already defined\n",
progname, lineno, infile);
exit(1);
}
current_part->ctl_stack_type = CTL_STACK_HVSP;
nbytes = 0;
ok = 1;
while (lsize(number_list)) {
t = lrmv_n(number_list, 1);
if (nbytes < CTL_STACK_SIZE)
{
current_part->controlstack[nbytes] = t->value.number;
nbytes++;
}
else
{
ok = 0;
}
free_token(t);
}
if (!ok)
{
fprintf(stderr,
"%s: Warning: line %d of %s: "
"too many bytes in control stack\n",
progname, lineno, infile);
}
}
} |
K_CHIP_ERASE_DELAY TKN_EQUAL TKN_NUMBER
{
current_part->chip_erase_delay = $3->value.number;
@ -660,6 +714,12 @@ part_parm :
free_token($3);
} |
K_HVSPCMDEXEDELAY TKN_EQUAL TKN_NUMBER
{
current_part->hvspcmdexedelay = $3->value.number;
free_token($3);
} |
K_SYNCHLOOPS TKN_EQUAL TKN_NUMBER
{
current_part->synchloops = $3->value.number;
@ -702,9 +762,9 @@ part_parm :
free_token($3);
} |
K_PPENTERSTABDELAY TKN_EQUAL TKN_NUMBER
K_HVENTERSTABDELAY TKN_EQUAL TKN_NUMBER
{
current_part->ppenterstabdelay = $3->value.number;
current_part->hventerstabdelay = $3->value.number;
free_token($3);
} |
@ -744,9 +804,9 @@ part_parm :
free_token($3);
} |
K_PPLEAVESTABDELAY TKN_EQUAL TKN_NUMBER
K_HVLEAVESTABDELAY TKN_EQUAL TKN_NUMBER
{
current_part->ppleavestabdelay = $3->value.number;
current_part->hvleavestabdelay = $3->value.number;
free_token($3);
} |
@ -768,6 +828,12 @@ part_parm :
free_token($3);
} |
K_CHIPERASETIME TKN_EQUAL TKN_NUMBER
{
current_part->chiperasetime = $3->value.number;
free_token($3);
} |
K_PROGRAMFUSEPULSEWIDTH TKN_EQUAL TKN_NUMBER
{
current_part->programfusepulsewidth = $3->value.number;
@ -792,6 +858,12 @@ part_parm :
free_token($3);
} |
K_SYNCHCYCLES TKN_EQUAL TKN_NUMBER
{
current_part->synchcycles = $3->value.number;
free_token($3);
} |
K_HAS_JTAG TKN_EQUAL yesno
{
if ($3->primary == K_YES)

View File

@ -499,6 +499,10 @@ STK200
@itemx stk500
Atmel STK500
@itemx stk500hvsp
Atmel STK500 in high-voltage serial programming mode
(version 2.x firmware only)
@itemx stk500pp
Atmel STK500 in parallel programming mode (version 2.x
firmware only)
@ -1898,7 +1902,7 @@ programming works, and is documented that way in the Atmel AVR
datasheets.
In order to successfully program the EEPROM that way, a prior chip
erase (with the EESAVE fuse unprogrammed) is required.
This also applies to the STK500 in parallel programming mode.
This also applies to the STK500 in high-voltage programming mode.
@end itemize

View File

@ -171,6 +171,7 @@ signature { yylval=NULL; return K_SIGNATURE; }
size { yylval=NULL; return K_SIZE; }
spmcr { yylval=NULL; return K_SPMCR; }
stk500 { yylval=NULL; return K_STK500; }
stk500hvsp { yylval=NULL; return K_STK500HVSP; }
stk500pp { yylval=NULL; return K_STK500PP; }
stk500v2 { yylval=NULL; return K_STK500V2; }
stk500_devcode { yylval=NULL; return K_STK500_DEVCODE; }
@ -181,6 +182,7 @@ vfyled { yylval=NULL; return K_VFYLED; }
timeout { yylval=NULL; return K_TIMEOUT; }
stabdelay { yylval=NULL; return K_STABDELAY; }
cmdexedelay { yylval=NULL; return K_CMDEXEDELAY; }
hvspcmdexedelay { yylval=NULL; return K_HVSPCMDEXEDELAY; }
synchloops { yylval=NULL; return K_SYNCHLOOPS; }
bytedelay { yylval=NULL; return K_BYTEDELAY; }
pollvalue { yylval=NULL; return K_POLLVALUE; }
@ -193,17 +195,20 @@ delay { yylval=NULL; return K_DELAY; }
blocksize { yylval=NULL; return K_BLOCKSIZE; }
readsize { yylval=NULL; return K_READSIZE; }
pp_controlstack { yylval=NULL; return K_PP_CONTROLSTACK; }
ppenterstabdelay { yylval=NULL; return K_PPENTERSTABDELAY; }
hvsp_controlstack { yylval=NULL; return K_HVSP_CONTROLSTACK; }
hventerstabdelay { yylval=NULL; return K_HVENTERSTABDELAY; }
progmodedelay { yylval=NULL; return K_PROGMODEDELAY; }
latchcycles { yylval=NULL; return K_LATCHCYCLES; }
togglevtg { yylval=NULL; return K_TOGGLEVTG; }
poweroffdelay { yylval=NULL; return K_POWEROFFDELAY; }
resetdelayms { yylval=NULL; return K_RESETDELAYMS; }
resetdelayus { yylval=NULL; return K_RESETDELAYUS; }
ppleavestabdelay { yylval=NULL; return K_PPLEAVESTABDELAY; }
hvleavestabdelay { yylval=NULL; return K_HVLEAVESTABDELAY; }
resetdelay { yylval=NULL; return K_RESETDELAY; }
synchcycles { yylval=NULL; return K_SYNCHCYCLES; }
chiperasepulsewidth { yylval=NULL; return K_CHIPERASEPULSEWIDTH; }
chiperasepolltimeout { yylval=NULL; return K_CHIPERASEPOLLTIMEOUT; }
chiperasetime { yylval=NULL; return K_CHIPERASETIME; }
programfusepulsewidth { yylval=NULL; return K_PROGRAMFUSEPULSEWIDTH; }
programfusepolltimeout { yylval=NULL; return K_PROGRAMFUSEPOLLTIMEOUT; }
programlockpulsewidth { yylval=NULL; return K_PROGRAMLOCKPULSEWIDTH; }

View File

@ -68,6 +68,11 @@
#define DEBUGRECV(format,args...)
#endif
enum hvmode
{
PPMODE, HVSPMODE
};
extern int verbose;
extern char * progname;
@ -399,11 +404,11 @@ static int stk500v2_cmd(PROGRAMMER * pgm, unsigned char cmd[4],
}
static int stk500pp_cmd(PROGRAMMER * pgm, unsigned char cmd[4],
static int stk500hv_cmd(PROGRAMMER * pgm, unsigned char cmd[4],
unsigned char res[4])
{
fprintf(stderr, "%s: stk500pp_command(): no direct SPI supported for PP mode\n",
fprintf(stderr, "%s: stk500hv_command(): no direct SPI supported for PP mode\n",
progname);
return -1;
}
@ -439,18 +444,24 @@ static int stk500v2_chip_erase(PROGRAMMER * pgm, AVRPART * p)
}
/*
* issue the 'chip erase' command to the AVR device, parallel mode
* issue the 'chip erase' command to the AVR device, generic HV mode
*/
static int stk500pp_chip_erase(PROGRAMMER * pgm, AVRPART * p)
static int stk500hv_chip_erase(PROGRAMMER * pgm, AVRPART * p, enum hvmode mode)
{
int result;
unsigned char buf[3];
pgm->pgm_led(pgm, ON);
buf[0] = CMD_CHIP_ERASE_PP;
buf[1] = p->chiperasepulsewidth;
buf[2] = p->chiperasepolltimeout;
if (mode == PPMODE) {
buf[0] = CMD_CHIP_ERASE_PP;
buf[1] = p->chiperasepulsewidth;
buf[2] = p->chiperasepolltimeout;
} else {
buf[0] = CMD_CHIP_ERASE_HVSP;
buf[1] = p->chiperasepolltimeout;
buf[2] = p->chiperasetime;
}
result = stk500v2_command(pgm, buf, 3, sizeof(buf));
usleep(p->chip_erase_delay);
pgm->initialize(pgm, p);
@ -460,6 +471,22 @@ static int stk500pp_chip_erase(PROGRAMMER * pgm, AVRPART * p)
return result;
}
/*
* issue the 'chip erase' command to the AVR device, parallel mode
*/
static int stk500pp_chip_erase(PROGRAMMER * pgm, AVRPART * p)
{
return stk500hv_chip_erase(pgm, p, PPMODE);
}
/*
* issue the 'chip erase' command to the AVR device, HVSP mode
*/
static int stk500hvsp_chip_erase(PROGRAMMER * pgm, AVRPART * p)
{
return stk500hv_chip_erase(pgm, p, HVSPMODE);
}
/*
* issue the 'program enable' command to the AVR device
*/
@ -477,7 +504,7 @@ static int stk500v2_program_enable(PROGRAMMER * pgm, AVRPART * p)
buf[1] = p->timeout;
buf[2] = p->stabdelay;
buf[3] = p->cmdexedelay;
buf[4] = p->synchloops;
buf[4] = p->synchcycles;
buf[5] = p->bytedelay;
buf[6] = p->pollvalue;
buf[7] = p->pollindex;
@ -494,7 +521,7 @@ static int stk500pp_program_enable(PROGRAMMER * pgm, AVRPART * p)
unsigned char buf[16];
buf[0] = CMD_ENTER_PROGMODE_PP;
buf[1] = p->ppenterstabdelay;
buf[1] = p->hventerstabdelay;
buf[2] = p->progmodedelay;
buf[3] = p->latchcycles;
buf[4] = p->togglevtg;
@ -505,6 +532,26 @@ static int stk500pp_program_enable(PROGRAMMER * pgm, AVRPART * p)
return stk500v2_command(pgm, buf, 8, sizeof(buf));
}
/*
* issue the 'program enable' command to the AVR device, HVSP mode
*/
static int stk500hvsp_program_enable(PROGRAMMER * pgm, AVRPART * p)
{
unsigned char buf[16];
buf[0] = CMD_ENTER_PROGMODE_HVSP;
buf[1] = p->hventerstabdelay;
buf[2] = p->hvspcmdexedelay;
buf[3] = p->synchcycles;
buf[4] = p->latchcycles;
buf[5] = p->togglevtg;
buf[6] = p->poweroffdelay;
buf[7] = p->resetdelayms;
buf[8] = p->resetdelayus;
return stk500v2_command(pgm, buf, 9, sizeof(buf));
}
/*
@ -517,20 +564,22 @@ static int stk500v2_initialize(PROGRAMMER * pgm, AVRPART * p)
/*
* initialize the AVR device and prepare it to accept commands, parallel mode
* initialize the AVR device and prepare it to accept commands, generic HV mode
*/
static int stk500pp_initialize(PROGRAMMER * pgm, AVRPART * p)
static int stk500hv_initialize(PROGRAMMER * pgm, AVRPART * p, enum hvmode mode)
{
unsigned char buf[CTL_STACK_SIZE + 1];
int result;
LNODEID ln;
AVRMEM * m;
if (p->ctl_stack_type != CTL_STACK_PP) {
if (p->ctl_stack_type != (mode == PPMODE? CTL_STACK_PP: CTL_STACK_HVSP)) {
fprintf(stderr,
"%s: stk500pp_initialize(): "
"parallel programming control stack not defined for part \"%s\"\n",
progname, p->desc);
"%s: stk500hv_initialize(): "
"%s programming control stack not defined for part \"%s\"\n",
progname,
(mode == PPMODE? "parallel": "high-voltage serial"),
p->desc);
return -1;
}
@ -582,6 +631,21 @@ static int stk500pp_initialize(PROGRAMMER * pgm, AVRPART * p)
return pgm->program_enable(pgm, p);
}
/*
* initialize the AVR device and prepare it to accept commands, PP mode
*/
static int stk500pp_initialize(PROGRAMMER * pgm, AVRPART * p)
{
return stk500hv_initialize(pgm, p, PPMODE);
}
/*
* initialize the AVR device and prepare it to accept commands, HVSP mode
*/
static int stk500hvsp_initialize(PROGRAMMER * pgm, AVRPART * p)
{
return stk500hv_initialize(pgm, p, HVSPMODE);
}
static void stk500v2_disable(PROGRAMMER * pgm)
{
@ -603,7 +667,10 @@ static void stk500v2_disable(PROGRAMMER * pgm)
return;
}
static void stk500pp_disable(PROGRAMMER * pgm)
/*
* Leave programming mode, generic HV mode
*/
static void stk500hv_disable(PROGRAMMER * pgm, enum hvmode mode)
{
unsigned char buf[16];
int result;
@ -613,15 +680,15 @@ static void stk500pp_disable(PROGRAMMER * pgm)
free(eeprom_pagecache);
eeprom_pagecache = NULL;
buf[0] = CMD_LEAVE_PROGMODE_PP;
buf[1] = 15; // p->ppleavestabdelay;
buf[0] = mode == PPMODE? CMD_LEAVE_PROGMODE_PP: CMD_LEAVE_PROGMODE_HVSP;
buf[1] = 15; // p->hvleavestabdelay;
buf[2] = 15; // p->resetdelay;
result = stk500v2_command(pgm, buf, 3, sizeof(buf));
if (result < 0 || buf[1] != STATUS_CMD_OK) {
fprintf(stderr,
"%s: stk500pp_disable(): "
"%s: stk500hv_disable(): "
"failed to leave programming mode, got 0x%02x\n",
progname,buf[1]);
exit(1);
@ -630,6 +697,22 @@ static void stk500pp_disable(PROGRAMMER * pgm)
return;
}
/*
* Leave programming mode, PP mode
*/
static void stk500pp_disable(PROGRAMMER * pgm)
{
stk500hv_disable(pgm, PPMODE);
}
/*
* Leave programming mode, HVSP mode
*/
static void stk500hvsp_disable(PROGRAMMER * pgm)
{
stk500hv_disable(pgm, HVSPMODE);
}
static void stk500v2_enable(PROGRAMMER * pgm)
{
return;
@ -715,8 +798,12 @@ static int stk500v2_loadaddr(PROGRAMMER * pgm, unsigned int addr)
}
static int stk500pp_read_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
unsigned long addr, unsigned char * value)
/*
* Read a single byte, generic HV mode
*/
static int stk500hv_read_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
unsigned long addr, unsigned char * value,
enum hvmode mode)
{
int result, cmdlen = 2;
char buf[266];
@ -725,14 +812,11 @@ static int stk500pp_read_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
unsigned char *cache_ptr = NULL;
if (verbose >= 2)
fprintf(stderr, "%s: stk500pp_read_byte(.., %s, 0x%lx, ...)\n",
fprintf(stderr, "%s: stk500hv_read_byte(.., %s, 0x%lx, ...)\n",
progname, mem->desc, addr);
if (stk500pp_program_enable(pgm, p) < 0)
return -1;
if (strcmp(mem->desc, "flash") == 0) {
buf[0] = CMD_READ_FLASH_PP;
buf[0] = mode == PPMODE? CMD_READ_FLASH_PP: CMD_READ_FLASH_HVSP;
cmdlen = 3;
pagesize = mem->page_size;
if (pagesize == 0)
@ -751,7 +835,7 @@ static int stk500pp_read_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
use_ext_addr = (1U << 31);
}
} else if (strcmp(mem->desc, "eeprom") == 0) {
buf[0] = CMD_READ_EEPROM_PP;
buf[0] = mode == PPMODE? CMD_READ_EEPROM_PP: CMD_READ_EEPROM_HVSP;
cmdlen = 3;
pagesize = mem->page_size;
if (pagesize == 0)
@ -761,24 +845,24 @@ static int stk500pp_read_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
cache_ptr = eeprom_pagecache;
} else if (strcmp(mem->desc, "lfuse") == 0 ||
strcmp(mem->desc, "fuse") == 0) {
buf[0] = CMD_READ_FUSE_PP;
buf[0] = mode == PPMODE? CMD_READ_FUSE_PP: CMD_READ_FUSE_HVSP;
addr = 0;
} else if (strcmp(mem->desc, "hfuse") == 0) {
buf[0] = CMD_READ_FUSE_PP;
buf[0] = mode == PPMODE? CMD_READ_FUSE_PP: CMD_READ_FUSE_HVSP;
addr = 1;
} else if (strcmp(mem->desc, "efuse") == 0) {
buf[0] = CMD_READ_FUSE_PP;
buf[0] = mode == PPMODE? CMD_READ_FUSE_PP: CMD_READ_FUSE_HVSP;
addr = 2;
} else if (strcmp(mem->desc, "lock") == 0) {
buf[0] = CMD_READ_LOCK_PP;
buf[0] = mode == PPMODE? CMD_READ_LOCK_PP: CMD_READ_LOCK_HVSP;
} else if (strcmp(mem->desc, "calibration") == 0) {
buf[0] = CMD_READ_OSCCAL_PP;
buf[0] = mode == PPMODE? CMD_READ_OSCCAL_PP: CMD_READ_OSCCAL_HVSP;
} else if (strcmp(mem->desc, "signature") == 0) {
buf[0] = CMD_READ_SIGNATURE_PP;
buf[0] = mode == PPMODE? CMD_READ_SIGNATURE_PP: CMD_READ_SIGNATURE_HVSP;
}
/*
* In parallel mode, we have to use paged reads for flash and
* In HV mode, we have to use paged reads for flash and
* EEPROM, and cache the results in a page cache.
*
* Page cache validation is based on "{flash,eeprom}_pageaddr"
@ -803,14 +887,14 @@ static int stk500pp_read_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
}
if (verbose >= 2)
fprintf(stderr, "%s: stk500pp_read_byte(): Sending read memory command: ",
fprintf(stderr, "%s: stk500hv_read_byte(): Sending read memory command: ",
progname);
result = stk500v2_command(pgm, buf, cmdlen, sizeof(buf));
if (result < 0 || buf[1] != STATUS_CMD_OK) {
fprintf(stderr,
"%s: stk500pp_read_byte(): "
"%s: stk500hv_read_byte(): "
"timeout/error communicating with programmer (status %d)\n",
progname, result);
return -1;
@ -827,8 +911,30 @@ static int stk500pp_read_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
return 0;
}
static int stk500pp_write_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
unsigned long addr, unsigned char data)
/*
* Read a single byte, PP mode
*/
static int stk500pp_read_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
unsigned long addr, unsigned char * value)
{
return stk500hv_read_byte(pgm, p, mem, addr, value, PPMODE);
}
/*
* Read a single byte, HVSP mode
*/
static int stk500hvsp_read_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
unsigned long addr, unsigned char * value)
{
return stk500hv_read_byte(pgm, p, mem, addr, value, HVSPMODE);
}
/*
* Write one byte, generic HV mode
*/
static int stk500hv_write_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
unsigned long addr, unsigned char data,
enum hvmode mode)
{
int result, cmdlen, timeout = 0, pulsewidth = 0;
char buf[266];
@ -837,14 +943,11 @@ static int stk500pp_write_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
unsigned char *cache_ptr = NULL;
if (verbose >= 2)
fprintf(stderr, "%s: stk500pp_write_byte(.., %s, 0x%lx, ...)\n",
fprintf(stderr, "%s: stk500hv_write_byte(.., %s, 0x%lx, ...)\n",
progname, mem->desc, addr);
if (stk500pp_program_enable(pgm, p) < 0)
return -1;
if (strcmp(mem->desc, "flash") == 0) {
buf[0] = CMD_PROGRAM_FLASH_PP;
buf[0] = mode == PPMODE? CMD_PROGRAM_FLASH_PP: CMD_PROGRAM_FLASH_HVSP;
pagesize = mem->page_size;
if (pagesize == 0)
pagesize = 2;
@ -862,7 +965,7 @@ static int stk500pp_write_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
use_ext_addr = (1U << 31);
}
} else if (strcmp(mem->desc, "eeprom") == 0) {
buf[0] = CMD_PROGRAM_EEPROM_PP;
buf[0] = mode == PPMODE? CMD_PROGRAM_EEPROM_PP: CMD_PROGRAM_EEPROM_HVSP;
pagesize = mem->page_size;
if (pagesize == 0)
pagesize = 1;
@ -871,27 +974,27 @@ static int stk500pp_write_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
cache_ptr = eeprom_pagecache;
} else if (strcmp(mem->desc, "lfuse") == 0 ||
strcmp(mem->desc, "fuse") == 0) {
buf[0] = CMD_PROGRAM_FUSE_PP;
buf[0] = mode == PPMODE? CMD_PROGRAM_FUSE_PP: CMD_PROGRAM_FUSE_HVSP;
addr = 0;
pulsewidth = p->programfusepulsewidth;
timeout = p->programfusepolltimeout;
} else if (strcmp(mem->desc, "hfuse") == 0) {
buf[0] = CMD_PROGRAM_FUSE_PP;
buf[0] = mode == PPMODE? CMD_PROGRAM_FUSE_PP: CMD_PROGRAM_FUSE_HVSP;
addr = 1;
pulsewidth = p->programfusepulsewidth;
timeout = p->programfusepolltimeout;
} else if (strcmp(mem->desc, "efuse") == 0) {
buf[0] = CMD_PROGRAM_FUSE_PP;
buf[0] = mode == PPMODE? CMD_PROGRAM_FUSE_PP: CMD_PROGRAM_FUSE_HVSP;
addr = 2;
pulsewidth = p->programfusepulsewidth;
timeout = p->programfusepolltimeout;
} else if (strcmp(mem->desc, "lock") == 0) {
buf[0] = CMD_PROGRAM_LOCK_PP;
buf[0] = mode == PPMODE? CMD_PROGRAM_LOCK_PP: CMD_PROGRAM_LOCK_HVSP;
pulsewidth = p->programlockpulsewidth;
timeout = p->programlockpolltimeout;
} else {
fprintf(stderr,
"%s: stk500pp_write_byte(): "
"%s: stk500hv_write_byte(): "
"unsupported memory type: %s\n",
progname, mem->desc);
return -1;
@ -900,7 +1003,7 @@ static int stk500pp_write_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
cmdlen = 5 + pagesize;
/*
* In parallel mode, we have to use paged writes for flash and
* In HV mode, we have to use paged writes for flash and
* EEPROM. As both, flash and EEPROM cells can only be programmed
* from `1' to `0' bits (even EEPROM does not support auto-erase in
* parallel mode), we just pre-fill the page cache with 0xff, so all
@ -938,19 +1041,24 @@ static int stk500pp_write_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
} else {
buf[1] = addr;
buf[2] = data;
buf[3] = pulsewidth;
buf[4] = timeout;
if (mode == PPMODE) {
buf[3] = pulsewidth;
buf[4] = timeout;
} else {
buf[3] = timeout;
cmdlen--;
}
}
if (verbose >= 2)
fprintf(stderr, "%s: stk500pp_write_byte(): Sending write memory command: ",
fprintf(stderr, "%s: stk500hv_write_byte(): Sending write memory command: ",
progname);
result = stk500v2_command(pgm, buf, cmdlen, sizeof(buf));
if (result < 0 || buf[1] != STATUS_CMD_OK) {
fprintf(stderr,
"%s: stk500pp_write_byte(): "
"%s: stk500hv_write_byte(): "
"timeout/error communicating with programmer (status %d)\n",
progname, result);
return -1;
@ -964,6 +1072,25 @@ static int stk500pp_write_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
return 0;
}
/*
* Write one byte, PP mode
*/
static int stk500pp_write_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
unsigned long addr, unsigned char data)
{
return stk500hv_write_byte(pgm, p, mem, addr, data, PPMODE);
}
/*
* Write one byte, HVSP mode
*/
static int stk500hvsp_write_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
unsigned long addr, unsigned char data)
{
return stk500hv_write_byte(pgm, p, mem, addr, data, HVSPMODE);
}
static int stk500v2_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
int page_size, int n_bytes)
{
@ -1096,14 +1223,18 @@ static int stk500v2_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
return n_bytes;
}
static int stk500pp_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
int page_size, int n_bytes)
/*
* Write pages of flash/EEPROM, generic HV mode
*/
static int stk500hv_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
int page_size, int n_bytes,
enum hvmode mode)
{
unsigned int addr, block_size, last_addr, hiaddr, addrshift, use_ext_addr;
unsigned char commandbuf[5], buf[266];
int result;
DEBUG("STK500V2: stk500pp_paged_write(..,%s,%d,%d)\n",m->desc,page_size,n_bytes);
DEBUG("STK500V2: stk500hv_paged_write(..,%s,%d,%d)\n",m->desc,page_size,n_bytes);
hiaddr = UINT_MAX;
addrshift = 0;
@ -1113,7 +1244,7 @@ static int stk500pp_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
if (strcmp(m->desc, "flash") == 0) {
addrshift = 1;
flash_pageaddr = (unsigned long)-1L;
commandbuf[0] = CMD_PROGRAM_FLASH_PP;
commandbuf[0] = mode == PPMODE? CMD_PROGRAM_FLASH_PP: CMD_PROGRAM_FLASH_HVSP;
/*
* If bit 31 is set, this indicates that the following read/write
* operation will be performed on a memory that is larger than
@ -1125,7 +1256,7 @@ static int stk500pp_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
}
} else if (strcmp(m->desc, "eeprom") == 0) {
eeprom_pageaddr = (unsigned long)-1L;
commandbuf[0] = CMD_PROGRAM_EEPROM_PP;
commandbuf[0] = mode == PPMODE? CMD_PROGRAM_EEPROM_PP: CMD_PROGRAM_EEPROM_HVSP;
}
/*
* Synthesize the mode byte. This is simpler than adding yet
@ -1158,7 +1289,7 @@ static int stk500pp_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
DEBUG("block_size at addr %d is %d\n",addr,block_size);
if (commandbuf[0] == CMD_PROGRAM_FLASH_PP) {
if (addrshift == 1) {
if (stk500v2_is_page_empty(addr, block_size, m->buf)) {
continue;
}
@ -1180,7 +1311,7 @@ static int stk500pp_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
result = stk500v2_command(pgm, buf, page_size + 5, sizeof(buf));
if (buf[1] != STATUS_CMD_OK) {
fprintf(stderr, "%s: stk500pp_paged_write: write command failed with %d\n",
fprintf(stderr, "%s: stk500hv_paged_write: write command failed with %d\n",
progname, buf[1]);
return -1;
}
@ -1189,6 +1320,24 @@ static int stk500pp_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
return n_bytes;
}
/*
* Write pages of flash/EEPROM, PP mode
*/
static int stk500pp_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
int page_size, int n_bytes)
{
return stk500hv_paged_write(pgm, p, m, page_size, n_bytes, PPMODE);
}
/*
* Write pages of flash/EEPROM, HVSP mode
*/
static int stk500hvsp_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
int page_size, int n_bytes)
{
return stk500hv_paged_write(pgm, p, m, page_size, n_bytes, HVSPMODE);
}
static int stk500v2_is_page_empty(unsigned int address, int page_size,
const unsigned char *buf)
{
@ -1293,14 +1442,18 @@ static int stk500v2_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
}
static int stk500pp_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
int page_size, int n_bytes)
/*
* Read pages of flash/EEPROM, generic HV mode
*/
static int stk500hv_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
int page_size, int n_bytes,
enum hvmode mode)
{
unsigned int addr, block_size, hiaddr, addrshift, use_ext_addr;
unsigned char commandbuf[3], buf[266];
int result;
DEBUG("STK500V2: stk500pp_paged_load(..,%s,%d,%d)\n",m->desc,page_size,n_bytes);
DEBUG("STK500V2: stk500hv_paged_load(..,%s,%d,%d)\n",m->desc,page_size,n_bytes);
page_size = m->readsize;
@ -1310,7 +1463,7 @@ static int stk500pp_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
// determine which command is to be used
if (strcmp(m->desc, "flash") == 0) {
commandbuf[0] = CMD_READ_FLASH_PP;
commandbuf[0] = mode == PPMODE? CMD_READ_FLASH_PP: CMD_READ_FLASH_HVSP;
addrshift = 1;
/*
* If bit 31 is set, this indicates that the following read/write
@ -1323,7 +1476,7 @@ static int stk500pp_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
}
}
else if (strcmp(m->desc, "eeprom") == 0) {
commandbuf[0] = CMD_READ_EEPROM_PP;
commandbuf[0] = mode == PPMODE? CMD_READ_EEPROM_PP: CMD_READ_EEPROM_HVSP;
}
for (addr = 0; addr < n_bytes; addr += page_size) {
@ -1349,7 +1502,7 @@ static int stk500pp_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
result = stk500v2_command(pgm, buf, 3, sizeof(buf));
if (buf[1] != STATUS_CMD_OK) {
fprintf(stderr, "%s: stk500pp_paged_load: read command failed with %d\n",
fprintf(stderr, "%s: stk500hv_paged_load: read command failed with %d\n",
progname, buf[1]);
return -1;
}
@ -1366,6 +1519,24 @@ static int stk500pp_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
return n_bytes;
}
/*
* Read pages of flash/EEPROM, PP mode
*/
static int stk500pp_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
int page_size, int n_bytes)
{
return stk500hv_paged_load(pgm, p, m, page_size, n_bytes, PPMODE);
}
/*
* Read pages of flash/EEPROM, HVSP mode
*/
static int stk500hvsp_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
int page_size, int n_bytes)
{
return stk500hv_paged_load(pgm, p, m, page_size, n_bytes, HVSPMODE);
}
static int stk500v2_set_vtarget(PROGRAMMER * pgm, double v)
{
@ -1746,7 +1917,7 @@ void stk500pp_initpgm(PROGRAMMER * pgm)
pgm->disable = stk500pp_disable;
pgm->program_enable = stk500pp_program_enable;
pgm->chip_erase = stk500pp_chip_erase;
pgm->cmd = stk500pp_cmd;
pgm->cmd = stk500hv_cmd;
pgm->open = stk500v2_open;
pgm->close = stk500v2_close;
@ -1764,3 +1935,35 @@ void stk500pp_initpgm(PROGRAMMER * pgm)
pgm->set_sck_period = stk500v2_set_sck_period;
pgm->page_size = 256;
}
void stk500hvsp_initpgm(PROGRAMMER * pgm)
{
strcpy(pgm->type, "STK500HVSP");
/*
* mandatory functions
*/
pgm->initialize = stk500hvsp_initialize;
pgm->display = stk500v2_display;
pgm->enable = stk500v2_enable;
pgm->disable = stk500hvsp_disable;
pgm->program_enable = stk500hvsp_program_enable;
pgm->chip_erase = stk500hvsp_chip_erase;
pgm->cmd = stk500hv_cmd;
pgm->open = stk500v2_open;
pgm->close = stk500v2_close;
/*
* optional functions
*/
pgm->read_byte = stk500hvsp_read_byte;
pgm->write_byte = stk500hvsp_write_byte;
pgm->paged_write = stk500hvsp_paged_write;
pgm->paged_load = stk500hvsp_paged_load;
pgm->print_parms = stk500v2_print_parms;
pgm->set_vtarget = stk500v2_set_vtarget;
pgm->set_varef = stk500v2_set_varef;
pgm->set_fosc = stk500v2_set_fosc;
pgm->set_sck_period = stk500v2_set_sck_period;
pgm->page_size = 256;
}

View File

@ -24,6 +24,7 @@
#define stk500v2_h__
void stk500v2_initpgm (PROGRAMMER * pgm);
void stk500hvsp_initpgm (PROGRAMMER * pgm);
void stk500pp_initpgm (PROGRAMMER * pgm);
#endif