diff --git a/Makefile.am b/Makefile.am index 1e579e4b..54eb0562 100644 --- a/Makefile.am +++ b/Makefile.am @@ -69,6 +69,9 @@ avrdude_SOURCES = \ crc16.h \ fileio.c \ fileio.h \ + jtagmkI.c \ + jtagmkI.h \ + jtagmkI_private.h \ jtagmkII.c \ jtagmkII.h \ jtagmkII_private.h \ diff --git a/avrdude.conf.in b/avrdude.conf.in index 1cd5f052..6483e32b 100644 --- a/avrdude.conf.in +++ b/avrdude.conf.in @@ -15,7 +15,7 @@ # programmer # id = [, [, ] ...] ; # are quoted strings # desc = ; # quoted string -# type = par | stk500 | stk500v2 | avr910 | jtagmkii; # programmer type +# type = par | stk500 | stk500v2 | avr910 | jtagmki | jtagmkii; # programmer type # baudrate = ; # baudrate for avr910-programmer # vcc = [, ... ] ; # pin number(s) # reset = ; # pin number @@ -269,6 +269,29 @@ programmer type = butterfly; ; +programmer + id = "jtagmkI"; + desc = "Atmel JTAG ICE (mkI)"; + baudrate = 115200; # default is 115200 + type = jtagmki; +; + +# easier to type +programmer + id = "jtag1"; + desc = "Atmel JTAG ICE (mkI)"; + baudrate = 115200; # default is 115200 + type = jtagmki; +; + +# easier to type +programmer + id = "jtag1slow"; + desc = "Atmel JTAG ICE (mkI)"; + baudrate = 19200; + type = jtagmki; +; + programmer id = "jtagmkII"; desc = "Atmel JTAG ICE mkII"; diff --git a/config_gram.y b/config_gram.y index 21c842c9..307f7aee 100644 --- a/config_gram.y +++ b/config_gram.y @@ -38,6 +38,7 @@ #include "avr910.h" #include "butterfly.h" #include "avr.h" +#include "jtagmkI.h" #include "jtagmkII.h" #if defined(WIN32NATIVE) @@ -90,6 +91,7 @@ static int parse_cmdbits(OPCODE * op); %token K_FLASH %token K_ID %token K_IO +%token K_JTAG_MKI %token K_JTAG_MKII %token K_LOADPAGE %token K_MAX_WRITE_DELAY @@ -358,6 +360,12 @@ prog_parm : } } | + K_TYPE TKN_EQUAL K_JTAG_MKI { + { + jtagmkI_initpgm(current_prog); + } + } | + K_TYPE TKN_EQUAL K_JTAG_MKII { { jtagmkII_initpgm(current_prog); diff --git a/jtagmkI.c b/jtagmkI.c new file mode 100644 index 00000000..0d5a25cc --- /dev/null +++ b/jtagmkI.c @@ -0,0 +1,1355 @@ +/* + * avrdude - A Downloader/Uploader for AVR device programmers + * Copyright (C) 2005 Joerg Wunsch + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* $Id$ */ + +/* + * avrdude interface for Atmel JTAG ICE (mkI) programmer + */ + +#include "ac_cfg.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "avr.h" +#include "crc16.h" +#include "pgm.h" +#include "jtagmkI_private.h" +#include "serial.h" +extern int verbose; +extern char * progname; +extern int do_cycles; + +/* + * XXX There should really be a programmer-specific private data + * pointer in struct PROGRAMMER. + */ +static long initial_baudrate; + +/* + * See jtagmkI_read_byte() for an explanation of the flash and + * EEPROM page caches. + */ +static unsigned char *flash_pagecache; +static unsigned long flash_pageaddr; +static unsigned int flash_pagesize; + +static unsigned char *eeprom_pagecache; +static unsigned long eeprom_pageaddr; +static unsigned int eeprom_pagesize; + +static int prog_enabled; /* Cached value of PROGRAMMING status. */ +/* + * The OCDEN fuse is bit 7 of the high fuse (hfuse). In order to + * 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) + +/* + * Table of baud rates supported by the mkI ICE, accompanied by their + * internal parameter value. + * + * 19200 is the initial value of the ICE after powerup, and virtually + * all connections then switch to 115200. As the table is also used + * to try connecting at startup, we keep these two entries on top to + * speedup the program start. + */ +const static struct { + long baud; + unsigned char val; +} baudtab[] = { + { 19200L, 0xfa }, + { 115200L, 0xff }, + { 9600L, 0xf4 }, + { 38400L, 0xfd }, + { 57600L, 0xfe }, +/* { 14400L, 0xf8 }, */ /* not supported by serial driver */ +}; + +static int jtagmkI_read_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem, + unsigned long addr, unsigned char * value); +static int jtagmkI_write_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem, + unsigned long addr, unsigned char data); +static int jtagmkI_set_sck_period(PROGRAMMER * pgm, double v); +static int jtagmkI_getparm(PROGRAMMER * pgm, unsigned char parm, + unsigned char * value); +static int jtagmkI_setparm(PROGRAMMER * pgm, unsigned char parm, + unsigned char value); +static void jtagmkI_print_parms1(PROGRAMMER * pgm, char * p); + +static int jtagmkI_resync(PROGRAMMER *pgm, int maxtries); + +static void +u32_to_b3(unsigned char *b, unsigned long l) +{ + b[2] = l & 0xff; + b[1] = (l >> 8) & 0xff; + b[0] = (l >> 16) & 0xff; +} + +static void +u16_to_b2(unsigned char *b, unsigned short l) +{ + b[0] = l & 0xff; + b[1] = (l >> 8) & 0xff; +} + +static void jtagmkI_prmsg(PROGRAMMER * pgm, unsigned char * data, size_t len) +{ + int i; + + if (verbose >= 4) { + fprintf(stderr, "Raw message:\n"); + + for (i = 0; i < len; i++) { + fprintf(stderr, "0x%02x ", data[i]); + if (i % 16 == 15) + putc('\n', stderr); + else + putchar(' '); + } + if (i % 16 != 0) + putc('\n', stderr); + } + + switch (data[0]) { + case RESP_OK: + fprintf(stderr, "OK\n"); + break; + + case RESP_FAILED: + fprintf(stderr, "FAILED\n"); + break; + + case RESP_BREAK: + fprintf(stderr, "breakpoint hit\n"); + break; + + case RESP_INFO: + fprintf(stderr, "IDR dirty\n"); + break; + + case RESP_SYNC_ERROR: + fprintf(stderr, "Synchronization lost\n"); + break; + + case RESP_SLEEP: + fprintf(stderr, "sleep instruction hit\n"); + break; + + case RESP_POWER: + fprintf(stderr, "target power lost\n"); + + default: + fprintf(stderr, "unknown message 0x%02x\n", data[0]); + } + + putc('\n', stderr); +} + + +static int jtagmkI_send(PROGRAMMER * pgm, unsigned char * data, size_t len) +{ + unsigned char *buf; + + if (verbose >= 3) + fprintf(stderr, "\n%s: jtagmkI_send(): sending %zd bytes\n", + progname, len); + + if ((buf = malloc(len + 2)) == NULL) + { + fprintf(stderr, "%s: jtagmkI_send(): out of memory", + progname); + exit(1); + } + + memcpy(buf, data, len); + buf[len] = ' '; /* "CRC" */ + buf[len + 1] = ' '; /* EOP */ + + if (serial_send(pgm->fd, buf, len + 2) != 0) { + fprintf(stderr, + "%s: jtagmkI_send(): failed to send command to serial port\n", + progname); + exit(1); + } + + free(buf); + + return 0; +} + +static void jtagmkI_recv(PROGRAMMER * pgm, unsigned char * buf, size_t len) +{ + if (serial_recv(pgm->fd, buf, len) != 0) { + fprintf(stderr, + "\n%s: jtagmkI_recv(): failed to send command to serial port\n", + progname); + exit(1); + } + if (verbose >= 3) { + putc('\n', stderr); + jtagmkI_prmsg(pgm, buf, len); + } +} + + +static int jtagmkI_drain(PROGRAMMER * pgm, int display) +{ + return serial_drain(pgm->fd, display); +} + + +static int jtagmkI_resync(PROGRAMMER * pgm, int maxtries) +{ + int tries; + unsigned char buf[1], resp[1]; + long otimeout = serial_recv_timeout; + + serial_recv_timeout = 200; + + if (verbose >= 3) + fprintf(stderr, "%s: jtagmkI_resync()\n", progname); + + jtagmkI_drain(pgm, 0); + + for (tries = 0; tries < maxtries; tries++) { + + /* Get the sign-on information. */ + buf[0] = CMD_GET_SYNC; + if (verbose >= 2) + fprintf(stderr, "%s: jtagmkI_resync(): Sending sync command: ", + progname); + + if (serial_send(pgm->fd, buf, 1) != 0) { + fprintf(stderr, + "\n%s: jtagmkI_resync(): failed to send command to serial port\n", + progname); + serial_recv_timeout = otimeout; + return -1; + } + if (serial_recv(pgm->fd, resp, 1) == 0 && resp[0] == RESP_OK) { + if (verbose >= 2) + fprintf(stderr, "got RESP_OK\n"); + break; + } + } + if (tries >= maxtries) { + if (verbose >= 2) + fprintf(stderr, + "%s: jtagmkI_resync(): " + "timeout/error communicating with programmer\n", + progname); + serial_recv_timeout = otimeout; + return -1; + } + + serial_recv_timeout = otimeout; + return 0; +} + +static int jtagmkI_getsync(PROGRAMMER * pgm) +{ + unsigned char buf[1], resp[9]; + + if (jtagmkI_resync(pgm, 5) < 0) + return -1; + + if (verbose >= 2) + fprintf(stderr, "%s: jtagmkI_getsync(): Sending sign-on command: ", + progname); + + buf[0] = CMD_GET_SIGNON; + jtagmkI_send(pgm, buf, 1); + jtagmkI_recv(pgm, resp, 9); + if (verbose >= 2) { + resp[8] = '\0'; + fprintf(stderr, "got %s\n", resp + 1); + } + + return 0; +} + +static int jtagmkI_cmd(PROGRAMMER * pgm, unsigned char cmd[4], + unsigned char res[4]) +{ + + fprintf(stderr, "%s: jtagmkI_command(): no direct SPI supported for JTAG\n", + progname); + return -1; +} + + +/* + * issue the 'chip erase' command to the AVR device + */ +static int jtagmkI_chip_erase(PROGRAMMER * pgm, AVRPART * p) +{ + unsigned char buf[1], resp[2]; + + buf[0] = CMD_CHIP_ERASE; + if (verbose >= 2) + fprintf(stderr, "%s: jtagmkI_chip_erase(): Sending chip erase command: ", + progname); + jtagmkI_send(pgm, buf, 1); + jtagmkI_recv(pgm, resp, 2); + if (resp[0] != RESP_OK) { + if (verbose >= 2) + putc('\n', stderr); + fprintf(stderr, + "%s: jtagmkI_chip_erase(): " + "timeout/error communicating with programmer (resp %c)\n", + progname, resp[0]); + return -1; + } else { + if (verbose == 2) + fprintf(stderr, "OK\n"); + } + + pgm->initialize(pgm, p); + + return 0; +} + +static void jtagmkI_set_devdescr(PROGRAMMER * pgm, AVRPART * p) +{ + unsigned char resp[2]; + LNODEID ln; + AVRMEM * m; + struct { + unsigned char cmd; + struct device_descriptor dd; + } sendbuf; + + memset(&sendbuf, 0, sizeof sendbuf); + sendbuf.cmd = CMD_SET_DEVICE_DESCRIPTOR; + sendbuf.dd.ucSPMCRAddress = p->spmcr; + sendbuf.dd.ucRAMPZAddress = p->rampz; + sendbuf.dd.ucIDRAddress = p->idr; + for (ln = lfirst(p->mem); ln; ln = lnext(ln)) { + m = ldata(ln); + if (strcmp(m->desc, "flash") == 0) { + flash_pagesize = m->page_size; + u16_to_b2(sendbuf.dd.uiFlashPageSize, flash_pagesize); + } else if (strcmp(m->desc, "eeprom") == 0) { + sendbuf.dd.ucEepromPageSize = eeprom_pagesize = m->page_size; + } + } + + if (verbose >= 2) + fprintf(stderr, "%s: jtagmkI_set_devdescr(): " + "Sending set device descriptor command: ", + progname); + jtagmkI_send(pgm, (unsigned char *)&sendbuf, sizeof(sendbuf)); + + jtagmkI_recv(pgm, resp, 2); + if (resp[0] != RESP_OK) { + if (verbose >= 2) + putc('\n', stderr); + fprintf(stderr, + "%s: jtagmkI_set_devdescr(): " + "timeout/error communicating with programmer (resp %c)\n", + progname, resp[0]); + } else { + if (verbose == 2) + fprintf(stderr, "OK\n"); + } +} + +/* + * Reset the target. + */ +static int jtagmkI_reset(PROGRAMMER * pgm) +{ + unsigned char buf[1], resp[2]; + + buf[0] = CMD_RESET; + if (verbose >= 2) + fprintf(stderr, "%s: jtagmkI_reset(): Sending reset command: ", + progname); + jtagmkI_send(pgm, buf, 1); + + jtagmkI_recv(pgm, resp, 2); + if (resp[0] != RESP_OK) { + if (verbose >= 2) + putc('\n', stderr); + fprintf(stderr, + "%s: jtagmkI_reset(): " + "timeout/error communicating with programmer (resp %c)\n", + progname, resp[0]); + return -1; + } else { + if (verbose == 2) + fprintf(stderr, "OK\n"); + } + + return 0; +} + +static int jtagmkI_program_enable_dummy(PROGRAMMER * pgm, AVRPART * p) +{ + + return 0; +} + +static int jtagmkI_program_enable(PROGRAMMER * pgm) +{ + unsigned char buf[1], resp[2]; + + if (prog_enabled) + return 0; + + buf[0] = CMD_ENTER_PROGMODE; + if (verbose >= 2) + fprintf(stderr, "%s: jtagmkI_program_enable(): " + "Sending enter progmode command: ", + progname); + jtagmkI_send(pgm, buf, 1); + + jtagmkI_recv(pgm, resp, 2); + if (resp[0] != RESP_OK) { + if (verbose >= 2) + putc('\n', stderr); + fprintf(stderr, + "%s: jtagmkI_program_enable(): " + "timeout/error communicating with programmer (resp %c)\n", + progname, resp[0]); + return -1; + } else { + if (verbose == 2) + fprintf(stderr, "OK\n"); + } + + prog_enabled = 1; + + return 0; +} + +static int jtagmkI_program_disable(PROGRAMMER * pgm) +{ + unsigned char buf[1], resp[2]; + + if (!prog_enabled) + return 0; + + if (pgm->fd != -1) { + buf[0] = CMD_LEAVE_PROGMODE; + if (verbose >= 2) + fprintf(stderr, "%s: jtagmkI_program_disable(): " + "Sending leave progmode command: ", + progname); + jtagmkI_send(pgm, buf, 1); + + jtagmkI_recv(pgm, resp, 2); + if (resp[0] != RESP_OK) { + if (verbose >= 2) + putc('\n', stderr); + fprintf(stderr, + "%s: jtagmkI_program_disable(): " + "timeout/error communicating with programmer (resp %c)\n", + progname, resp[0]); + return -1; + } else { + if (verbose == 2) + fprintf(stderr, "OK\n"); + } + + (void)jtagmkI_reset(pgm); + } + prog_enabled = 0; + + return 0; +} + +static unsigned char jtagmkI_get_baud(long baud) +{ + int i; + + for (i = 0; i < sizeof baudtab / sizeof baudtab[0]; i++) + if (baud == baudtab[i].baud) + return baudtab[i].val; + + return 0; +} + +/* + * initialize the AVR device and prepare it to accept commands + */ +static int jtagmkI_initialize(PROGRAMMER * pgm, AVRPART * p) +{ + AVRMEM hfuse; + char cmd[1], resp[2]; + unsigned char b; + + if (!(p->flags & AVRPART_HAS_JTAG)) { + fprintf(stderr, "%s: jtagmkI_initialize(): part %s has no JTAG interface\n", + progname, p->desc); + return -1; + } + + jtagmkI_drain(pgm, 0); + + if (initial_baudrate != pgm->baudrate) { + if ((b = jtagmkI_get_baud(pgm->baudrate)) == 0) { + fprintf(stderr, "%s: jtagmkI_initialize(): unsupported baudrate %d\n", + progname, pgm->baudrate); + } else { + if (verbose >= 2) + fprintf(stderr, "%s: jtagmkI_initialize(): " + "trying to set baudrate to %d\n", + progname, pgm->baudrate); + if (jtagmkI_setparm(pgm, PARM_BITRATE, b) == 0) { + initial_baudrate = pgm->baudrate; /* don't adjust again later */ + serial_setspeed(pgm->fd, pgm->baudrate); + } + } + } + + if (pgm->bitclock != 0.0) { + if (verbose >= 2) + fprintf(stderr, "%s: jtagmkI_initialize(): " + "trying to set JTAG clock period to %.1f us\n", + progname, pgm->bitclock); + if (jtagmkI_set_sck_period(pgm, pgm->bitclock) != 0) + return -1; + } + + cmd[0] = CMD_STOP; + jtagmkI_send(pgm, cmd, 1); + jtagmkI_recv(pgm, resp, 5); + if (resp[0] != RESP_OK) { + if (verbose >= 2) + putc('\n', stderr); + fprintf(stderr, + "%s: jtagmkI_initialize(): " + "timeout/error communicating with programmer (resp %c)\n", + progname, resp[0]); + } else { + if (verbose == 2) + fprintf(stderr, "OK\n"); + } + + /* + * Must set the device descriptor before entering programming mode. + */ + jtagmkI_set_devdescr(pgm, p); + + jtagmkI_setparm(pgm, PARM_FLASH_PAGESIZE_LOW, flash_pagesize & 0xff); + jtagmkI_setparm(pgm, PARM_FLASH_PAGESIZE_HIGH, flash_pagesize >> 8); + jtagmkI_setparm(pgm, PARM_EEPROM_PAGESIZE, eeprom_pagesize & 0xff); + + free(flash_pagecache); + free(eeprom_pagecache); + if ((flash_pagecache = malloc(flash_pagesize)) == NULL) { + fprintf(stderr, "%s: jtagmkI_initialize(): Out of memory\n", + progname); + return -1; + } + if ((eeprom_pagecache = malloc(eeprom_pagesize)) == NULL) { + fprintf(stderr, "%s: jtagmkI_initialize(): Out of memory\n", + progname); + free(flash_pagecache); + return -1; + } + flash_pageaddr = eeprom_pageaddr = (unsigned long)-1L; + + if (jtagmkI_reset(pgm) < 0) + return -1; + + strcpy(hfuse.desc, "hfuse"); + if (jtagmkI_read_byte(pgm, p, &hfuse, 1, &b) < 0) + return -1; + if ((b & OCDEN) != 0) + fprintf(stderr, + "%s: jtagmkI_initialize(): warning: OCDEN fuse not programmed, " + "single-byte EEPROM updates not possible\n", + progname); + + return 0; +} + + +static void jtagmkI_disable(PROGRAMMER * pgm) +{ + + free(flash_pagecache); + flash_pagecache = NULL; + free(eeprom_pagecache); + eeprom_pagecache = NULL; + + (void)jtagmkI_program_disable(pgm); +} + +static void jtagmkI_enable(PROGRAMMER * pgm) +{ + return; +} + + +static int jtagmkI_open(PROGRAMMER * pgm, char * port) +{ + size_t i; + + if (verbose >= 2) + fprintf(stderr, "%s: jtagmkI_open()\n", progname); + + strcpy(pgm->port, port); + initial_baudrate = -1L; + + for (i = 0; i < sizeof(baudtab) / sizeof(baudtab[0]); i++) { + if (verbose >= 2) + fprintf(stderr, + "%s: jtagmkI_open(): trying to sync at baud rate %ld:\n", + progname, baudtab[i].baud); + pgm->fd = serial_open(port, baudtab[i].baud); + + /* + * drain any extraneous input + */ + jtagmkI_drain(pgm, 0); + + if (jtagmkI_getsync(pgm) == 0) { + initial_baudrate = baudtab[i].baud; + if (verbose >= 2) + fprintf(stderr, "%s: jtagmkI_open(): succeeded\n", progname); + return 0; + } + + serial_close(pgm->fd); + } + + fprintf(stderr, + "%s: jtagmkI_open(): failed to synchronize to ICE\n", + progname); + pgm->fd = -1; + + return -1; +} + + +static void jtagmkI_close(PROGRAMMER * pgm) +{ + unsigned char buf[1], resp[2]; + + if (verbose >= 2) + fprintf(stderr, "%s: jtagmkI_close()\n", progname); + + if (pgm->fd != -1) { + buf[0] = CMD_GO; + if (verbose >= 2) + fprintf(stderr, "%s: jtagmkI_close(): Sending GO command: ", + progname); + jtagmkI_send(pgm, buf, 1); + jtagmkI_recv(pgm, resp, 1); + if (resp[0] != RESP_OK) { + if (verbose >= 2) + putc('\n', stderr); + fprintf(stderr, + "%s: jtagmkI_close(): " + "timeout/error communicating with programmer (resp %c)\n", + progname, resp[0]); + exit(1); + } else { + if (verbose == 2) + fprintf(stderr, "OK\n"); + } + + serial_close(pgm->fd); + } + + pgm->fd = -1; +} + + +static int jtagmkI_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, + int page_size, int n_bytes) +{ + int addr, block_size, send_size, tries; + unsigned char cmd[6], *datacmd; + unsigned char resp[2]; + int is_flash = 0; + long otimeout = serial_recv_timeout; +#define MAXTRIES 3 + + if (verbose >= 2) + fprintf(stderr, "%s: jtagmkI_paged_write(.., %s, %d, %d)\n", + progname, m->desc, page_size, n_bytes); + + if (jtagmkI_program_enable(pgm) < 0) + return -1; + + if (page_size == 0) page_size = 256; + + if (page_size > 256) { + fprintf(stderr, "%s: jtagmkI_paged_write(): page size %d too large\n", + progname, page_size); + return -1; + } + + if ((datacmd = malloc(page_size + 1)) == NULL) { + fprintf(stderr, "%s: jtagmkI_paged_write(): Out of memory\n", + progname); + return -1; + } + + cmd[0] = CMD_WRITE_MEM; + if (strcmp(m->desc, "flash") == 0) { + cmd[1] = MTYPE_FLASH_PAGE; + flash_pageaddr = (unsigned long)-1L; + page_size = flash_pagesize; + is_flash = 1; + } else if (strcmp(m->desc, "eeprom") == 0) { + cmd[1] = MTYPE_EEPROM_PAGE; + eeprom_pageaddr = (unsigned long)-1L; + page_size = eeprom_pagesize; + } + datacmd[0] = CMD_DATA; + + serial_recv_timeout = 1000; + for (addr = 0; addr < n_bytes; addr += page_size) { + report_progress(addr, n_bytes,NULL); + + tries = 0; + again: + + if (tries != 0 && jtagmkI_resync(pgm, 2000) < 0) { + fprintf(stderr, + "%s: jtagmkI_paged_write(): sync loss, retries exhausted\n", + progname); + return -1; + } + + if ((n_bytes-addr) < page_size) + block_size = n_bytes - addr; + else + block_size = page_size; + if (verbose >= 3) + fprintf(stderr, "%s: jtagmkI_paged_write(): " + "block_size at addr %d is %d\n", + progname, addr, block_size); + + /* We always write full pages. */ + send_size = page_size; + if (is_flash) { + cmd[2] = send_size / 2 - 1; + u32_to_b3(cmd + 3, addr / 2); + } else { + cmd[2] = send_size - 1; + u32_to_b3(cmd + 3, addr); + } + + if (verbose >= 2) + fprintf(stderr, "%s: jtagmkI_paged_write(): " + "Sending write memory command: ", + progname); + + /* First part, send the write command. */ + jtagmkI_send(pgm, cmd, 6); + jtagmkI_recv(pgm, resp, 1); + if (resp[0] != RESP_OK) { + if (verbose >= 2) + putc('\n', stderr); + fprintf(stderr, + "%s: jtagmkI_paged_write(): " + "timeout/error communicating with programmer (resp %c)\n", + progname, resp[0]); + if (tries++ < MAXTRIES) + goto again; + serial_recv_timeout = otimeout; + return -1; + } else { + if (verbose == 2) + fprintf(stderr, "OK\n"); + } + + /* + * The JTAG ICE will refuse to write anything but a full page, at + * least for the flash ROM. If a partial page has been requested, + * set the remainder to 0xff. (Maybe we should rather read back + * the existing contents instead before? Doesn't matter much, as + * bits cannot be written to 1 anyway.) + */ + memset(datacmd + 1, 0xff, page_size); + memcpy(datacmd + 1, m->buf + addr, block_size); + + /* Second, send the data command. */ + jtagmkI_send(pgm, datacmd, send_size + 1); + jtagmkI_recv(pgm, resp, 2); + if (resp[1] != RESP_OK) { + if (verbose >= 2) + putc('\n', stderr); + fprintf(stderr, + "%s: jtagmkI_paged_write(): " + "timeout/error communicating with programmer (resp %c)\n", + progname, resp[0]); + if (tries++ < MAXTRIES) + goto again; + serial_recv_timeout = otimeout; + return -1; + } else { + if (verbose == 2) + fprintf(stderr, "OK\n"); + } + } + + free(datacmd); + serial_recv_timeout = otimeout; + +#undef MAXTRIES + return n_bytes; +} + +static int jtagmkI_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, + int page_size, int n_bytes) +{ + int addr, block_size, read_size, is_flash = 0, tries; + unsigned char cmd[6], resp[256 * 2 + 3]; + long otimeout = serial_recv_timeout; +#define MAXTRIES 3 + + if (verbose >= 2) + fprintf(stderr, "%s: jtagmkI_paged_load(.., %s, %d, %d)\n", + progname, m->desc, page_size, n_bytes); + + if (jtagmkI_program_enable(pgm) < 0) + return -1; + + page_size = m->readsize; + + cmd[0] = CMD_READ_MEM; + if (strcmp(m->desc, "flash") == 0) { + cmd[1] = MTYPE_FLASH_PAGE; + is_flash = 1; + } else if (strcmp(m->desc, "eeprom") == 0) { + cmd[1] = MTYPE_EEPROM_PAGE; + } + + if (page_size > (is_flash? 512: 256)) { + fprintf(stderr, "%s: jtagmkI_paged_load(): page size %d too large\n", + progname, page_size); + return -1; + } + + serial_recv_timeout = 1000; + for (addr = 0; addr < n_bytes; addr += page_size) { + report_progress(addr, n_bytes,NULL); + + tries = 0; + again: + if (tries != 0 && jtagmkI_resync(pgm, 2000) < 0) { + fprintf(stderr, + "%s: jtagmkI_paged_load(): sync loss, retries exhausted\n", + progname); + return -1; + } + + if ((n_bytes-addr) < page_size) + block_size = n_bytes - addr; + else + block_size = page_size; + if (verbose >= 3) + fprintf(stderr, "%s: jtagmkI_paged_load(): " + "block_size at addr %d is %d\n", + progname, addr, block_size); + + if (is_flash) { + read_size = 2 * ((block_size + 1) / 2); /* round up */ + cmd[2] = read_size / 2 - 1; + u32_to_b3(cmd + 3, addr / 2); + } else { + read_size = page_size; + cmd[2] = page_size - 1; + u32_to_b3(cmd + 3, addr); + } + + if (verbose >= 2) + fprintf(stderr, "%s: jtagmkI_paged_load(): Sending read memory command: ", + progname); + + jtagmkI_send(pgm, cmd, 6); + jtagmkI_recv(pgm, resp, read_size + 3); + + if (resp[read_size + 3 - 1] != RESP_OK) { + if (verbose >= 2) + putc('\n', stderr); + fprintf(stderr, + "%s: jtagmkI_paged_load(): " + "timeout/error communicating with programmer (resp %c)\n", + progname, resp[read_size + 3 - 1]); + if (tries++ < MAXTRIES) + goto again; + + serial_recv_timeout = otimeout; + return -1; + } else { + if (verbose == 2) + fprintf(stderr, "OK\n"); + } + + memcpy(m->buf + addr, resp + 1, block_size); + } + serial_recv_timeout = otimeout; + +#undef MAXTRIES + return n_bytes; +} + +static int jtagmkI_read_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem, + unsigned long addr, unsigned char * value) +{ + unsigned char cmd[6]; + unsigned char resp[256 * 2 + 3], *cache_ptr = NULL; + unsigned long paddr = 0UL, *paddr_ptr = NULL; + unsigned int pagesize = 0; + int respsize = 3 + 1; + int is_flash = 0; + + if (verbose >= 2) + fprintf(stderr, "%s: jtagmkI_read_byte(.., %s, 0x%lx, ...)\n", + progname, mem->desc, addr); + + if (jtagmkI_program_enable(pgm) < 0) + return -1; + + cmd[0] = CMD_READ_MEM; + + if (strcmp(mem->desc, "flash") == 0) { + cmd[1] = MTYPE_FLASH_PAGE; + pagesize = mem->page_size; + paddr = addr & ~(pagesize - 1); + paddr_ptr = &flash_pageaddr; + cache_ptr = flash_pagecache; + is_flash = 1; + } else if (strcmp(mem->desc, "eeprom") == 0) { + cmd[1] = MTYPE_EEPROM_PAGE; + pagesize = mem->page_size; + paddr = addr & ~(pagesize - 1); + paddr_ptr = &eeprom_pageaddr; + cache_ptr = eeprom_pagecache; + } else if (strcmp(mem->desc, "lfuse") == 0) { + cmd[1] = MTYPE_FUSE_BITS; + addr = 0; + } else if (strcmp(mem->desc, "hfuse") == 0) { + cmd[1] = MTYPE_FUSE_BITS; + addr = 1; + } else if (strcmp(mem->desc, "efuse") == 0) { + cmd[1] = MTYPE_FUSE_BITS; + addr = 2; + } else if (strcmp(mem->desc, "lock") == 0) { + cmd[1] = MTYPE_LOCK_BITS; + } else if (strcmp(mem->desc, "calibration") == 0) { + cmd[1] = MTYPE_OSCCAL_BYTE; + } else if (strcmp(mem->desc, "signature") == 0) { + cmd[1] = MTYPE_SIGN_JTAG; + } + + /* + * To improve the read speed, we used paged reads for flash and + * EEPROM, and cache the results in a page cache. + * + * Page cache validation is based on "{flash,eeprom}_pageaddr" + * (holding the base address of the most recent cache fill + * operation). This variable is set to (unsigned long)-1L when the + * cache needs to be invalidated. + */ + if (pagesize && paddr == *paddr_ptr) { + *value = cache_ptr[addr & (pagesize - 1)]; + return 0; + } + + if (pagesize) { + if (is_flash) { + cmd[2] = pagesize / 2 - 1; + u32_to_b3(cmd + 3, paddr / 2); + } else { + cmd[2] = pagesize - 1; + u32_to_b3(cmd + 3, paddr); + } + respsize = 3 + pagesize; + } else { + if (cmd[1] == MTYPE_FUSE_BITS) { + /* + * The mkI ICE has a bug where it doesn't read efuse correctly + * when reading it as a single byte @offset 2, while reading all + * fuses at once does work. + */ + cmd[2] = 3 - 1; + u32_to_b3(cmd + 3, 0); + respsize = 3 + 3; + } else { + cmd[2] = 1 - 1; + u32_to_b3(cmd + 3, addr); + } + } + + jtagmkI_send(pgm, cmd, 6); + jtagmkI_recv(pgm, resp, respsize); + + if (resp[respsize - 1] != RESP_OK) { + if (verbose >= 2) + putc('\n', stderr); + fprintf(stderr, + "%s: jtagmkI_read_byte(): " + "timeout/error communicating with programmer (resp %c)\n", + progname, resp[respsize - 1]); + exit(1); + } else { + if (verbose == 2) + fprintf(stderr, "OK\n"); + } + + if (pagesize) { + *paddr_ptr = paddr; + memcpy(cache_ptr, resp + 1, pagesize); + *value = cache_ptr[addr & (pagesize - 1)]; + } else if (cmd[1] == MTYPE_FUSE_BITS) { + /* extract the desired fuse */ + *value = resp[1 + addr]; + } else + *value = resp[1]; + + return 0; +} + +static int jtagmkI_write_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem, + unsigned long addr, unsigned char data) +{ + unsigned char cmd[6], datacmd[1 * 2 + 1]; + unsigned char resp[1], writedata; + int len, need_progmode = 1; + + if (verbose >= 2) + fprintf(stderr, "%s: jtagmkI_write_byte(.., %s, 0x%lx, ...)\n", + progname, mem->desc, addr); + + writedata = data; + cmd[0] = CMD_WRITE_MEM; + if (strcmp(mem->desc, "flash") == 0) { + cmd[1] = MTYPE_SPM; + need_progmode = 0; + flash_pageaddr = (unsigned long)-1L; + } else if (strcmp(mem->desc, "eeprom") == 0) { + cmd[1] = MTYPE_EEPROM; + need_progmode = 0; + eeprom_pageaddr = (unsigned long)-1L; + } else if (strcmp(mem->desc, "lfuse") == 0) { + cmd[1] = MTYPE_FUSE_BITS; + addr = 0; + } else if (strcmp(mem->desc, "hfuse") == 0) { + cmd[1] = MTYPE_FUSE_BITS; + addr = 1; + } else if (strcmp(mem->desc, "efuse") == 0) { + cmd[1] = MTYPE_FUSE_BITS; + addr = 2; + } else if (strcmp(mem->desc, "lock") == 0) { + cmd[1] = MTYPE_LOCK_BITS; + } else if (strcmp(mem->desc, "calibration") == 0) { + cmd[1] = MTYPE_OSCCAL_BYTE; + } else if (strcmp(mem->desc, "signature") == 0) { + cmd[1] = MTYPE_SIGN_JTAG; + } + + if (need_progmode) { + if (jtagmkI_program_enable(pgm) < 0) + return -1; + } else { + if (jtagmkI_program_disable(pgm) < 0) + return -1; + } + + cmd[2] = 1; + if (cmd[1] == MTYPE_SPM) { + /* + * Flash is word-addressed, but we cannot handle flash anyway + * here, as it needs to be written one page at a time... + */ + u32_to_b3(cmd + 3, addr / 2); + } else { + u32_to_b3(cmd + 3, addr); + } + /* First part, send the write command. */ + jtagmkI_send(pgm, cmd, 6); + jtagmkI_recv(pgm, resp, 1); + if (resp[0] != RESP_OK) { + if (verbose >= 2) + putc('\n', stderr); + fprintf(stderr, + "%s: jtagmkI_write_byte(): " + "timeout/error communicating with programmer (resp %c)\n", + progname, resp[0]); + return -1; + } else { + if (verbose == 2) + fprintf(stderr, "OK\n"); + } + + /* Now, send the data buffer. */ + datacmd[0] = CMD_DATA; + if (cmd[1] == MTYPE_SPM) { + len = 3; + if ((addr & 1) != 0) { + datacmd[1] = 0; + datacmd[2] = writedata; + } else { + datacmd[1] = writedata; + datacmd[2] = 0; + } + } else { + len = 2; + datacmd[1] = writedata; + } + jtagmkI_send(pgm, datacmd, len); + jtagmkI_recv(pgm, resp, 1); + if (resp[0] != RESP_OK) { + if (verbose >= 2) + putc('\n', stderr); + fprintf(stderr, + "%s: jtagmkI_write_byte(): " + "timeout/error communicating with programmer (resp %c)\n", + progname, resp[0]); + return -1; + } else { + if (verbose == 2) + fprintf(stderr, "OK\n"); + } + + return 0; +} + + +/* + * Set the JTAG clock. The actual frequency is quite a bit of + * guesswork, based on the values claimed by AVR Studio. Inside the + * JTAG ICE, the value is the delay count of a delay loop between the + * JTAG clock edges. A count of 0 bypasses the delay loop. + * + * As the STK500 expresses it as a period length (and we actualy do + * program a period length as well), we rather call it by that name. + */ +static int jtagmkI_set_sck_period(PROGRAMMER * pgm, double v) +{ + unsigned char dur; + + v = 1 / v; /* convert to frequency */ + if (v >= 1e6) + dur = JTAG_BITRATE_1_MHz; + else if (v >= 499e3) + dur = JTAG_BITRATE_500_kHz; + else if (v >= 249e3) + dur = JTAG_BITRATE_250_kHz; + else + dur = JTAG_BITRATE_125_kHz; + + return jtagmkI_setparm(pgm, PARM_CLOCK, dur); +} + + +/* + * Read an emulator parameter. The result is exactly one byte, + * multi-byte parameters get two different parameter names for + * their components. + */ +static int jtagmkI_getparm(PROGRAMMER * pgm, unsigned char parm, + unsigned char * value) +{ + unsigned char buf[2], resp[3]; + + if (verbose >= 2) + fprintf(stderr, "%s: jtagmkI_getparm()\n", progname); + + buf[0] = CMD_GET_PARAM; + buf[1] = parm; + if (verbose >= 2) + fprintf(stderr, "%s: jtagmkI_getparm(): " + "Sending get parameter command (parm 0x%02x): ", + progname, parm); + jtagmkI_send(pgm, buf, 2); + + jtagmkI_recv(pgm, resp, 3); + if (resp[0] != RESP_OK) { + if (verbose >= 2) + putc('\n', stderr); + fprintf(stderr, + "%s: jtagmkI_getparm(): " + "timeout/error communicating with programmer (resp %c)\n", + progname, resp[0]); + return -1; + } else if (resp[2] != RESP_OK) { + if (verbose >= 2) + putc('\n', stderr); + fprintf(stderr, + "%s: jtagmkI_getparm(): " + "unknown parameter 0x%02x\n", + progname, parm); + return -1; + } else { + if (verbose == 2) + fprintf(stderr, "OK, value 0x%02x\n", resp[1]); + } + + *value = resp[1]; + + return 0; +} + +/* + * Write an emulator parameter. + */ +static int jtagmkI_setparm(PROGRAMMER * pgm, unsigned char parm, + unsigned char value) +{ + unsigned char buf[3], resp[2]; + + if (verbose >= 2) + fprintf(stderr, "%s: jtagmkI_setparm()\n", progname); + + buf[0] = CMD_SET_PARAM; + buf[1] = parm; + buf[2] = value; + if (verbose >= 2) + fprintf(stderr, "%s: jtagmkI_setparm(): " + "Sending set parameter command (parm 0x%02x): ", + progname, parm); + jtagmkI_send(pgm, buf, 3); + jtagmkI_recv(pgm, resp, 2); + if (resp[0] != RESP_OK) { + if (verbose >= 2) + putc('\n', stderr); + fprintf(stderr, + "%s: jtagmkI_setparm(): " + "timeout/error communicating with programmer (resp %c)\n", + progname, resp[0]); + return -1; + } else { + if (verbose == 2) + fprintf(stderr, "OK\n"); + } + + return 0; +} + + +static void jtagmkI_display(PROGRAMMER * pgm, char * p) +{ + + unsigned char hw, fw; + + if (jtagmkI_getparm(pgm, PARM_HW_VERSION, &hw) < 0 || + jtagmkI_getparm(pgm, PARM_SW_VERSION, &fw) < 0) + return; + + fprintf(stderr, "%sICE hardware version: 0x%02x\n", p, hw); + fprintf(stderr, "%sICE firmware version: 0x%02x\n", p, fw); + + jtagmkI_print_parms1(pgm, p); + + return; +} + + +static void jtagmkI_print_parms1(PROGRAMMER * pgm, char * p) +{ + unsigned char vtarget, jtag_clock; + const char *clkstr; + double clk; + + if (jtagmkI_getparm(pgm, PARM_OCD_VTARGET, &vtarget) < 0 || + jtagmkI_getparm(pgm, PARM_CLOCK, &jtag_clock) < 0) + return; + + switch ((unsigned)jtag_clock) { + case JTAG_BITRATE_1_MHz: + clkstr = "1 MHz"; + clk = 1e6; + break; + + case JTAG_BITRATE_500_kHz: + clkstr = "500 kHz"; + clk = 500e3; + break; + + case JTAG_BITRATE_250_kHz: + clkstr = "250 kHz"; + clk = 250e3; + break; + + case JTAG_BITRATE_125_kHz: + clkstr = "125 kHz"; + clk = 125e3; + break; + + default: + clkstr = "???"; + clk = 1e6; + } + + fprintf(stderr, "%sVtarget : %.1f V\n", p, + 6.25 * (unsigned)vtarget / 255.0); + fprintf(stderr, "%sJTAG clock : %s (%.1f us)\n", p, clkstr, + 1.0e6 / clk); + + return; +} + + +static void jtagmkI_print_parms(PROGRAMMER * pgm) +{ + jtagmkI_print_parms1(pgm, ""); +} + + +void jtagmkI_initpgm(PROGRAMMER * pgm) +{ + strcpy(pgm->type, "JTAGMKI"); + + /* + * mandatory functions + */ + pgm->initialize = jtagmkI_initialize; + pgm->display = jtagmkI_display; + pgm->enable = jtagmkI_enable; + pgm->disable = jtagmkI_disable; + pgm->program_enable = jtagmkI_program_enable_dummy; + pgm->chip_erase = jtagmkI_chip_erase; + pgm->cmd = jtagmkI_cmd; + pgm->open = jtagmkI_open; + pgm->close = jtagmkI_close; + + /* + * optional functions + */ + pgm->paged_write = jtagmkI_paged_write; + pgm->paged_load = jtagmkI_paged_load; + pgm->read_byte = jtagmkI_read_byte; + pgm->write_byte = jtagmkI_write_byte; + pgm->print_parms = jtagmkI_print_parms; + pgm->set_sck_period = jtagmkI_set_sck_period; + pgm->page_size = 256; +} diff --git a/jtagmkI.h b/jtagmkI.h new file mode 100644 index 00000000..99534108 --- /dev/null +++ b/jtagmkI.h @@ -0,0 +1,28 @@ +/* + * avrdude - A Downloader/Uploader for AVR device programmers + * Copyright (C) 2002-2004 Brian S. Dean + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* $Id$ */ + +#ifndef jtagmkI_h +#define jtagmkI_h + +void jtagmkI_initpgm (PROGRAMMER * pgm); + +#endif + diff --git a/jtagmkI_private.h b/jtagmkI_private.h new file mode 100644 index 00000000..ec185c99 --- /dev/null +++ b/jtagmkI_private.h @@ -0,0 +1,169 @@ +/* + * avrdude - A Downloader/Uploader for AVR device programmers + * Copyright (C) 2005 Joerg Wunsch + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* $Id$ */ + + +/* + * JTAG ICE mkI definitions + */ + +/* ICE command codes */ +/* 0x20 Get Synch [Resp_OK] */ +#define CMD_GET_SYNC ' ' + +/* 0x31 Single Step [Sync_CRC/EOP] [Resp_OK] */ +/* 0x32 Read PC [Sync_CRC/EOP] [Resp_OK] [program counter] + * [Resp_OK] */ +/* 0x33 Write PC [program counter] [Sync_CRC/EOP] [Resp_OK] + * [Resp_OK] */ +/* 0xA2 Firmware Upgrade [upgrade string] [Sync_CRC/EOP] [Resp_OK] + * [Resp_OK] */ +/* 0xA0 Set Device Descriptor [device info] [Sync_CRC/EOP] [Resp_OK] + * [Resp_OK] */ +#define CMD_SET_DEVICE_DESCRIPTOR 0xA0 + +/* 0x42 Set Parameter [parameter] [setting] [Sync_CRC/EOP] [Resp_OK] + * [Resp_OK] */ +#define CMD_SET_PARAM 'B' + +/* 0x46 Forced Stop [Sync_CRC/EOP] [Resp_OK] [checksum][program + * counter] [Resp_OK] */ +#define CMD_STOP 'F' + +/* 0x47 Go [Sync_CRC/EOP] [Resp_OK] */ +#define CMD_GO 'G' + +/* 0x52 Read Memory [memory type] [word count] [start address] + * [Sync_CRC/EOP] [Resp_OK] [word 0] ... [word n] [checksum] + * [Resp_OK] */ +#define CMD_READ_MEM 'R' + +/* 0x53 Get Sign On [Sync_CRC/EOP] [Resp_OK] ["AVRNOCD"] [Resp_OK] */ +#define CMD_GET_SIGNON 'S' + +/* 0XA1 Erase Page spm [address] [Sync_CRC/EOP] [Resp_OK] [Resp_OK] */ + +/* 0x57 Write Memory [memory type] [word count] [start address] + * [Sync_CRC/EOP] [Resp_OK] [Cmd_DATA] [word 0] ... [word n] */ +#define CMD_WRITE_MEM 'W' + +/* Second half of write memory: the data command. Undocumented. */ +#define CMD_DATA 'h' + +/* 0x64 Get Debug Info [Sync_CRC/EOP] [Resp_OK] [0x00] [Resp_OK] */ +/* 0x71 Get Parameter [parameter] [Sync_CRC/EOP] [Resp_OK] [setting] + * [Resp_OK] */ +#define CMD_GET_PARAM 'q' + +/* 0x78 Reset [Sync_CRC/EOP] [Resp_OK] [Resp_OK] */ +#define CMD_RESET 'x' + +/* 0xA3 Enter Progmode [Sync_CRC/EOP] [Resp_OK] [Resp_OK] */ +#define CMD_ENTER_PROGMODE 0xa3 + +/* 0xA4 Leave Progmode [Sync_CRC/EOP] [Resp_OK] [Resp_OK] */ +#define CMD_LEAVE_PROGMODE 0xa4 + +/* 0xA5 Chip Erase [Sync_CRC/EOP] [Resp_OK] [Resp_OK] */ +#define CMD_CHIP_ERASE 0xa5 + + +/* ICE responses */ +#define RESP_OK 'A' +#define RESP_BREAK 'B' +#define RESP_INFO 'G' +#define RESP_FAILED 'F' +#define RESP_SYNC_ERROR 'E' +#define RESP_SLEEP 'H' +#define RESP_POWER 'I' + +#define PARM_BITRATE 'b' +#define PARM_SW_VERSION 0x7b +#define PARM_HW_VERSION 0x7a +#define PARM_IREG_HIGH 0x81 +#define PARM_IREG_LOW 0x82 +#define PARM_OCD_VTARGET 0x84 +#define PARM_OCD_BREAK_CAUSE 0x85 +#define PARM_CLOCK 0x86 +#define PARM_EXTERNAL_RESET 0x8b +#define PARM_FLASH_PAGESIZE_LOW 0x88 +#define PARM_FLASH_PAGESIZE_HIGH 0x89 +#define PARM_EEPROM_PAGESIZE 0x8a +#define PARM_TIMERS_RUNNING 0xa0 +#define PARM_BP_FLOW 0xa1 +#define PARM_BP_X_HIGH 0xa2 +#define PARM_BP_X_LOW 0xa3 +#define PARM_BP_Y_HIGH 0xa4 +#define PARM_BP_Y_LOW 0xa5 +#define PARM_BP_MODE 0xa6 +#define PARM_JTAGID_BYTE0 0xa7 +#define PARM_JTAGID_BYTE1 0xa8 +#define PARM_JTAGID_BYTE2 0xa9 +#define PARM_JTAGID_BYTE3 0xaa +#define PARM_UNITS_BEFORE 0xab +#define PARM_UNITS_AFTER 0xac +#define PARM_BIT_BEFORE 0xad +#define PARM_BIT_AFTER 0xae +#define PARM_PSB0_LOW 0xaf +#define PARM_PSBO_HIGH 0xb0 +#define PARM_PSB1_LOW 0xb1 +#define PARM_PSB1_HIGH 0xb2 +#define PARM_MCU_MODE 0xb3 + +#define JTAG_BITRATE_1_MHz 0xff +#define JTAG_BITRATE_500_kHz 0xfe +#define JTAG_BITRATE_250_kHz 0xfd +#define JTAG_BITRATE_125_kHz 0xfb + +/* memory types for CMND_{READ,WRITE}_MEMORY */ +#define MTYPE_IO_SHADOW 0x30 /* cached IO registers? */ +#define MTYPE_SRAM 0x20 /* target's SRAM or [ext.] IO registers */ +#define MTYPE_EEPROM 0x22 /* EEPROM, what way? */ +#define MTYPE_EVENT 0x60 /* ICE event memory */ +#define MTYPE_SPM 0xA0 /* flash through LPM/SPM */ +#define MTYPE_FLASH_PAGE 0xB0 /* flash in programming mode */ +#define MTYPE_EEPROM_PAGE 0xB1 /* EEPROM in programming mode */ +#define MTYPE_FUSE_BITS 0xB2 /* fuse bits in programming mode */ +#define MTYPE_LOCK_BITS 0xB3 /* lock bits in programming mode */ +#define MTYPE_SIGN_JTAG 0xB4 /* signature in programming mode */ +#define MTYPE_OSCCAL_BYTE 0xB5 /* osccal cells in programming mode */ + +struct device_descriptor +{ + unsigned char ucReadIO[8]; /*LSB = IOloc 0, MSB = IOloc63 */ + unsigned char ucWriteIO[8]; /*LSB = IOloc 0, MSB = IOloc63 */ + unsigned char ucReadIOShadow[8]; /*LSB = IOloc 0, MSB = IOloc63 */ + unsigned char ucWriteIOShadow[8]; /*LSB = IOloc 0, MSB = IOloc63 */ + unsigned char ucReadExtIO[20]; /*LSB = IOloc 96, MSB = IOloc255 */ + unsigned char ucWriteExtIO[20]; /*LSB = IOloc 96, MSB = IOloc255 */ + unsigned char ucReadIOExtShadow[20]; /*LSB = IOloc 96, MSB = IOloc255 */ + unsigned char ucWriteIOExtShadow[20];/*LSB = IOloc 96, MSB = IOloc255 */ + unsigned char ucIDRAddress; /*IDR address */ + unsigned char ucSPMCRAddress; /*SPMCR Register address and dW BasePC */ + unsigned char ucRAMPZAddress; /*RAMPZ Register address in SRAM I/O */ + /*space */ + unsigned char uiFlashPageSize[2]; /*Device Flash Page Size, Size = */ + /*2 exp ucFlashPageSize */ + unsigned char ucEepromPageSize; /*Device Eeprom Page Size in bytes */ + unsigned char ulBootAddress[4]; /*Device Boot Loader Start Address */ + unsigned char uiUpperExtIOLoc; /*Topmost (last) extended I/O */ + /*location, 0 if no external I/O */ +}; diff --git a/lexer.l b/lexer.l index b99ad3a4..7cc91768 100644 --- a/lexer.l +++ b/lexer.l @@ -141,6 +141,7 @@ flash { yylval=NULL; return K_FLASH; } has_jtag { yylval=NULL; return K_HAS_JTAG; } id { yylval=NULL; return K_ID; } idr { yylval=NULL; return K_IDR; } +jtagmki { yylval=NULL; return K_JTAG_MKI; } jtagmkii { yylval=NULL; return K_JTAG_MKII; } max_write_delay { yylval=NULL; return K_MAX_WRITE_DELAY; } memory { yylval=NULL; return K_MEMORY; }