diff --git a/ChangeLog b/ChangeLog index d65571ee..d85d3bf6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,17 @@ +2006-07-21 Joerg Wunsch + + 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 * avrpart.c: Print the very verbose memory details only diff --git a/avrdude.1 b/avrdude.1 index e4838d9d..94fa5977 100644 --- a/avrdude.1 +++ b/avrdude.1 @@ -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 diff --git a/avrdude.conf.in b/avrdude.conf.in index bd0ab0dc..a68733ec 100644 --- a/avrdude.conf.in +++ b/avrdude.conf.in @@ -15,7 +15,8 @@ # programmer # id = [, [, ] ...] ; # are quoted strings # desc = ; # quoted string -# type = par | stk500 | stk500v2 | stk500pp | avr910 | jtagmki | jtagmkii; # programmer type +# type = par | stk500 | stk500v2 | stk500pp | stk500hvsp | +# avr910 | jtagmki | jtagmkii; # programmer type # baudrate = ; # baudrate for avr910-programmer # vcc = [, ... ] ; # pin number(s) # reset = ; # pin number @@ -50,7 +51,7 @@ # # STK500v2 parameters, to be taken from Atmel's XML files # timeout = ; # stabdelay = ; -# cmdexdelay = ; +# cmdexedelay = ; # synchloops = ; # bytedelay = ; # pollvalue = ; @@ -62,22 +63,26 @@ # delay = ; # blocksize = ; # readsize = ; -# # STK500v2 parallel programming parameters, from XML -# pp_controlstack = , , ...; -# ppenterstabdelay = ; -# progmodedelay = ; +# hvspcmdexedelay = ; +# # STK500v2 HV programming parameters, from XML +# pp_controlstack = , , ...; # PP only +# hvsp_controlstack = , , ...; # HVSP only +# hventerstabdelay = ; +# progmodedelay = ; # PP only # latchcycles = ; # togglevtg = ; # poweroffdelay = ; # resetdelayms = ; # resetdelayus = ; -# ppleavestabdelay = ; +# hvleavestabdelay = ; # resetdelay = ; -# chiperasepulsewidth = ; +# synchcycles = ; # HVSP only +# chiperasepulsewidth = ; # PP only # chiperasepolltimeout = ; -# programfusepulsewidth = ; +# chiperasetime = ; # HVSP only +# programfusepulsewidth = ; # PP only # programfusepolltimeout = ; -# programlockpulsewidth = ; +# programlockpulsewidth = ; # PP only # programlockpolltimeout = ; # # JTAG ICE mkII parameters, also from XML files # allowfullpagebitstream = ; @@ -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; diff --git a/avrpart.h b/avrpart.h index 18f0325f..0b90faae 100644 --- a/avrpart.h +++ b/avrpart.h @@ -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 */ diff --git a/config_gram.y b/config_gram.y index e3cbfd85..6d2a80c5 100644 --- a/config_gram.y +++ b/config_gram.y @@ -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) diff --git a/doc/avrdude.texi b/doc/avrdude.texi index e8581fd6..5f304a47 100644 --- a/doc/avrdude.texi +++ b/doc/avrdude.texi @@ -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 diff --git a/lexer.l b/lexer.l index 2b66e701..c5976b9f 100644 --- a/lexer.l +++ b/lexer.l @@ -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; } diff --git a/stk500v2.c b/stk500v2.c index 0cf92b4b..5d6b36aa 100644 --- a/stk500v2.c +++ b/stk500v2.c @@ -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; +} diff --git a/stk500v2.h b/stk500v2.h index 4fc96286..11833a74 100644 --- a/stk500v2.h +++ b/stk500v2.h @@ -24,6 +24,7 @@ #define stk500v2_h__ void stk500v2_initpgm (PROGRAMMER * pgm); +void stk500hvsp_initpgm (PROGRAMMER * pgm); void stk500pp_initpgm (PROGRAMMER * pgm); #endif