From 6ba0f493b4cfe8dc794f7dc93ac8bddbf354fd9e Mon Sep 17 00:00:00 2001 From: joerg_wunsch Date: Wed, 11 May 2005 20:06:23 +0000 Subject: [PATCH] Quite some cleanup of the JTAG ICE mkII stuff. . Implement the new EECRAddress field in the device descriptor that is required by the 4.x firmware; make an uneducated guess about what firmware requires what length of device descriptor -- perhaps Atmel can be convinced to publish an official matrix for that. . Specify EECR in the config file where required. Obviously, only locations that differ from the 0x3c default are mentioned in the XML files, so by now, this only affects the AT90CAN128 for us. . After clarification with Atmel, EnablePageProgramming should really default to 1, and only cleared if specified by an XML parameter. So far, only the XML files for the ATmega256x and ATmega406 do specify it at all, and they specify a 1, too. . Drop the entire OCDEN fuse heuristic. If OCDEN is unprogrammed at startup, issue a warning that single-byte EEPROM updates won't be possible. Leave it to the user to program the fuse if desired. That way, we won't run into any issue of prematurely wearing out the hfuse EEPROM cell. Interestingly enough, this also solved the problem of the target not restarting from scratch upon sign-off. git-svn-id: svn://svn.savannah.nongnu.org/avrdude/trunk/avrdude@461 81a1dc3b-b13d-400b-aceb-764788c761c2 --- avrdude.conf.in | 3 ++ avrpart.c | 2 +- avrpart.h | 1 + config_gram.y | 7 +++ jtagmkII.c | 108 +++++++++++++++++---------------------------- jtagmkII_private.h | 10 +---- lexer.l | 1 + 7 files changed, 55 insertions(+), 77 deletions(-) diff --git a/avrdude.conf.in b/avrdude.conf.in index 824cc675..0ea49cf2 100644 --- a/avrdude.conf.in +++ b/avrdude.conf.in @@ -67,6 +67,8 @@ # idr = ; # IO addr of IDR (OCD) reg. # rampz = ; # IO addr of RAMPZ reg. # spmcr = ; # mem addr of SPMC[S]R reg. +# eecr = ; # mem addr of EECR reg. +# # (only when != 0x3c) # # memory # paged = ; # yes / no @@ -2051,6 +2053,7 @@ part idr = 0x31; spmcr = 0x57; rampz = 0x3b; + eecr = 0x3f; memory "eeprom" paged = no; /* leave this "no" */ diff --git a/avrpart.c b/avrpart.c index 78e112ce..612da347 100644 --- a/avrpart.c +++ b/avrpart.c @@ -366,7 +366,7 @@ AVRPART * avr_new_part(void) p->desc[0] = 0; p->reset_disposition = RESET_DEDICATED; p->retry_pulse = PIN_AVR_SCK; - p->flags = AVRPART_SERIALOK | AVRPART_PARALLELOK; + p->flags = AVRPART_SERIALOK | AVRPART_PARALLELOK | AVRPART_ENABLEPAGEPROGRAMMING; p->config_file[0] = 0; p->lineno = 0; diff --git a/avrpart.h b/avrpart.h index 138a6ebb..8cd644c3 100644 --- a/avrpart.h +++ b/avrpart.h @@ -111,6 +111,7 @@ typedef struct avrpart { unsigned char idr; /* JTAG ICE mkII XML file parameter */ unsigned char rampz; /* JTAG ICE mkII XML file parameter */ unsigned char spmcr; /* JTAG ICE mkII XML file parameter */ + unsigned short eecr; /* JTAC ICE mkII XML file parameter */ OPCODE * op[AVR_OP_MAX]; /* opcodes */ diff --git a/config_gram.y b/config_gram.y index f7fe7713..88c65148 100644 --- a/config_gram.y +++ b/config_gram.y @@ -154,6 +154,7 @@ static int parse_cmdbits(OPCODE * op); %token K_IDR /* address of OCD register in IO space */ %token K_RAMPZ /* address of RAMPZ reg. in IO space */ %token K_SPMCR /* address of SPMC[S]R in memory space */ +%token K_EECR /* address of EECR in memory space */ %token TKN_COMMA %token TKN_EQUAL @@ -637,6 +638,12 @@ part_parm : free_token($3); } | + K_EECR TKN_EQUAL TKN_NUMBER + { + current_part->eecr = $3->value.number; + free_token($3); + } | + K_SERIAL TKN_EQUAL yesno { if ($3->primary == K_YES) diff --git a/jtagmkII.c b/jtagmkII.c index d3f8d357..79386234 100644 --- a/jtagmkII.c +++ b/jtagmkII.c @@ -71,20 +71,17 @@ static int prog_enabled; /* Cached value of PROGRAMMING status. */ static unsigned char serno[6]; /* JTAG ICE serial number. */ /* * The OCDEN fuse is bit 7 of the high fuse (hfuse). In order to - * perform memory operations on MTYPE_SPM and MTYPE_EEPROM, we need to - * enable on-chip debugging, as these memory types are apparently - * emulated by running MCU instructions on the target MCU. We cache - * the original value here, so it can be restored before exiting. - * User-requested hfuse updates will always mask out the OCDEN fuse - * then, only updating the cached copy. + * perform memory operations on MTYPE_SPM and MTYPE_EEPROM, OCDEN + * needs to be programmed. * * OCDEN should probably rather be defined via the configuration, but * if this ever changes to a different fuse byte for one MCU, quite * some code here needs to be generalized anyway. */ #define OCDEN (1 << 7) -static unsigned char hfuse_backup; -static int internal_hfuse_handling; + +/* The length of the device descriptor is firmware-dependent. */ +static size_t device_descriptor_length; static int jtagmkII_read_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem, unsigned long addr, unsigned char * value); @@ -537,6 +534,7 @@ static int jtagmkII_getsync(PROGRAMMER * pgm) { #define MAXTRIES 33 unsigned char buf[3], *resp, c = 0xff; int status; + unsigned int fwver; if (verbose >= 3) fprintf(stderr, "%s: jtagmkII_getsync()\n", progname); @@ -563,6 +561,8 @@ static int jtagmkII_getsync(PROGRAMMER * pgm) { if (status > 0) { if ((c = resp[0]) == RSP_SIGN_ON) { + fwver = ((unsigned)resp[8] << 8) | (unsigned)resp[7]; + memcpy(serno, resp + 10, 6); if (verbose >= 1 && status > 17) { fprintf(stderr, "JTAG ICE mkII sign-on message:\n"); fprintf(stderr, "Communications protocol version: %u\n", @@ -581,7 +581,6 @@ static int jtagmkII_getsync(PROGRAMMER * pgm) { (unsigned)resp[8], (unsigned)resp[7]); fprintf(stderr, " hardware version: %u\n", (unsigned)resp[9]); - memcpy(serno, resp + 10, 6); fprintf(stderr, "Serial number: " "%02x:%02x:%02x:%02x:%02x:%02x\n", serno[0], serno[1], serno[2], serno[3], serno[4], serno[5]); @@ -608,6 +607,28 @@ static int jtagmkII_getsync(PROGRAMMER * pgm) { return -1; } + device_descriptor_length = sizeof(struct device_descriptor); + /* + * There's no official documentation from Atmel about what firmware + * revision matches what device descriptor length. The algorithm + * below has been found empirically. + */ +#define FWVER(maj, min) ((maj << 8) | (min)) + if (fwver < FWVER(3, 16)) { + device_descriptor_length -= 2; + fprintf(stderr, + "%s: jtagmkII_getsync(): " + "S_MCU firmware version might be too old to work correctly\n", + progname); + } else if (fwver < FWVER(4, 0)) { + device_descriptor_length -= 2; + } +#undef FWVER + if (verbose >= 2) + fprintf(stderr, + "%s: jtagmkII_getsync(): Using a %u-byte device descriptor\n", + progname, device_descriptor_length); + /* Turn the ICE into JTAG mode */ buf[0] = EMULATOR_MODE_JTAG; if (jtagmkII_setparm(pgm, PAR_EMULATOR_MODE, buf) < 0) @@ -718,6 +739,7 @@ static void jtagmkII_set_devdescr(PROGRAMMER * pgm, AVRPART * p) sendbuf.dd.ucSPMCRAddress = p->spmcr; sendbuf.dd.ucRAMPZAddress = p->rampz; sendbuf.dd.ucIDRAddress = p->idr; + u16_to_b2(sendbuf.dd.EECRAddress, p->eecr); sendbuf.dd.ucAllowFullPageBitstream = (p->flags & AVRPART_ALLOWFULLPAGEBITSTREAM) != 0; sendbuf.dd.EnablePageProgramming = @@ -738,7 +760,8 @@ static void jtagmkII_set_devdescr(PROGRAMMER * pgm, AVRPART * p) fprintf(stderr, "%s: jtagmkII_set_devdescr(): " "Sending set device descriptor command: ", progname); - jtagmkII_send(pgm, (unsigned char *)&sendbuf, sizeof sendbuf); + jtagmkII_send(pgm, (unsigned char *)&sendbuf, + device_descriptor_length + sizeof(unsigned char)); status = jtagmkII_recv(pgm, &resp); if (status <= 0) { @@ -986,19 +1009,14 @@ static int jtagmkII_initialize(PROGRAMMER * pgm, AVRPART * p) if (jtagmkII_reset(pgm) < 0) return -1; - internal_hfuse_handling = 1; strcpy(hfuse.desc, "hfuse"); - if (jtagmkII_read_byte(pgm, p, &hfuse, 1, &hfuse_backup) < 0) { - internal_hfuse_handling = 0; + if (jtagmkII_read_byte(pgm, p, &hfuse, 1, &b) < 0) return -1; - } - b = hfuse_backup; - b &= ~OCDEN; - if (jtagmkII_write_byte(pgm, p, &hfuse, 1, b) < 0) { - internal_hfuse_handling = 0; - return -1; - } - internal_hfuse_handling = 0; + if ((b & OCDEN) != 0) + fprintf(stderr, + "%s: jtagmkII_initialize(): warning: OCDEN fuse not programmed, " + "single-byte EEPROM updates not possible\n", + progname); return 0; } @@ -1050,46 +1068,10 @@ static void jtagmkII_close(PROGRAMMER * pgm) { int status; unsigned char buf[1], *resp, c; - AVRMEM hfuse; if (verbose >= 2) fprintf(stderr, "%s: jtagmkII_close()\n", progname); - internal_hfuse_handling = 1; - strcpy(hfuse.desc, "hfuse"); - (void)jtagmkII_write_byte(pgm, NULL, &hfuse, 1, hfuse_backup); - internal_hfuse_handling = 0; - - buf[0] = CMND_RESET; - if (verbose >= 2) - fprintf(stderr, "%s: jtagmkII_close(): Sending restore target command: ", - progname); - jtagmkII_send(pgm, buf, 1); - - status = jtagmkII_recv(pgm, &resp); - if (status <= 0) { - if (verbose >= 2) - putc('\n', stderr); - fprintf(stderr, - "%s: jtagmkII_close(): " - "timeout/error communicating with programmer (status %d)\n", - progname, status); - } else { - if (verbose >= 3) { - putc('\n', stderr); - jtagmkII_prmsg(pgm, resp, status); - } else if (verbose == 2) - fprintf(stderr, "0x%02x (%d bytes msg)\n", resp[0], status); - c = resp[0]; - free(resp); - if (c != RSP_OK) { - fprintf(stderr, - "%s: jtagmkII_close(): " - "bad response to restore target command: 0x%02x\n", - progname, c); - } - } - buf[0] = CMND_GO; if (verbose >= 2) fprintf(stderr, "%s: jtagmkII_close(): Sending GO command: ", @@ -1397,10 +1379,6 @@ static int jtagmkII_read_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem, } else if (strcmp(mem->desc, "hfuse") == 0) { cmd[1] = MTYPE_FUSE_BITS; addr = 1; - if (!internal_hfuse_handling) { - *value = hfuse_backup; - return 0; - } } else if (strcmp(mem->desc, "efuse") == 0) { cmd[1] = MTYPE_FUSE_BITS; addr = 2; @@ -1497,7 +1475,7 @@ static int jtagmkII_write_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem, { unsigned char cmd[11]; unsigned char *resp = NULL, writedata; - int status, tries, need_progmode = 1, is_hfuse = 0; + int status, tries, need_progmode = 1; if (verbose >= 2) fprintf(stderr, "%s: jtagmkII_write_byte(.., %s, 0x%lx, ...)\n", @@ -1519,10 +1497,6 @@ static int jtagmkII_write_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem, } else if (strcmp(mem->desc, "hfuse") == 0) { cmd[1] = MTYPE_FUSE_BITS; addr = 1; - if (!internal_hfuse_handling) { - is_hfuse = 1; - writedata &= ~OCDEN; - } } else if (strcmp(mem->desc, "efuse") == 0) { cmd[1] = MTYPE_FUSE_BITS; addr = 2; @@ -1583,8 +1557,6 @@ static int jtagmkII_write_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem, goto fail; } - if (is_hfuse && !internal_hfuse_handling) - hfuse_backup = data; free(resp); return 0; diff --git a/jtagmkII_private.h b/jtagmkII_private.h index 6558a824..03f80ff9 100644 --- a/jtagmkII_private.h +++ b/jtagmkII_private.h @@ -285,12 +285,6 @@ struct device_descriptor unsigned char ucPCMaskExtended; /* For parts with extended PC */ unsigned char ucPCMaskHigh; /* PC high mask */ unsigned char ucEindAddress; /* Selects reset type. [EIND address...] */ - /* Does not work yet, M_MCU f/w rev 3.11, S_MCU f/w rev 3.16 */ - /* unsigned char EECRAddress[2]; */ /* EECR IO address */ + /* new as of early 2005, firmware 4.x */ + unsigned char EECRAddress[2]; /* EECR memory-mapped IO address */ }; - -#define fill_b4(u) \ -{ ((u) & 0xffUL), (((u) & 0xff00UL) >> 8), \ - (((u) & 0xff0000UL) >> 16), (((u) & 0xff000000UL) >> 24) } -#define fill_b2(u) \ -{ ((u) & 0xff), (((u) & 0xff00) >> 8) } diff --git a/lexer.l b/lexer.l index f240a9bd..a8386fc1 100644 --- a/lexer.l +++ b/lexer.l @@ -130,6 +130,7 @@ default_parallel { yylval=NULL; return K_DEFAULT_PARALLEL; } default_programmer { yylval=NULL; return K_DEFAULT_PROGRAMMER; } default_serial { yylval=NULL; return K_DEFAULT_SERIAL; } devicecode { yylval=NULL; return K_DEVICECODE; } +eecr { yylval=NULL; return K_EECR; } eeprom { yylval=NULL; return K_EEPROM; } enablepageprogramming { yylval=NULL; return K_ENABLEPAGEPROGRAMMING; } errled { yylval=NULL; return K_ERRLED; }