diff --git a/ChangeLog b/ChangeLog index 917c2aa5..013c69fd 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,22 @@ +2007-11-07 Joerg Wunsch + + * main.c: Add setup and teardown hooks to the programmer + definition. If present, call the setup hook immediately after + finding the respective programmer object, and schedule the + teardown hook to be called upon exit. This allows the + programmer implementation to dynamically allocate private + programmer data. + * pgm.c: (Ditto.) + * pgm.h: (Ditto.) + * avr910.c: Convert static programmer data into dynamically + allocated data. + * butterfly.c: (Ditto.) + * jtagmkI.c: (Ditto.) + * jtagmkII.c: (Ditto.) + * stk500v2.c: (Ditto.) + * usbasp.c: (Ditto.) + * usbtiny.c: (Ditto.) + 2007-11-06 Joerg Wunsch * butterfly.c: Remove the no_show_func_info() calls, as Brian diff --git a/avr910.c b/avr910.c index 16ad7cb9..1c15895c 100644 --- a/avr910.c +++ b/avr910.c @@ -1,6 +1,7 @@ /* * avrdude - A Downloader/Uploader for AVR device programmers * Copyright (C) 2003-2004 Theodore A. Roth + * Copyright 2007 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 @@ -40,7 +41,31 @@ #include "avr910.h" #include "serial.h" -static char has_auto_incr_addr; +/* + * Private data for this programmer. + */ +struct pdata +{ + char has_auto_incr_addr; +}; + +#define PDATA(pgm) ((struct pdata *)(pgm->cookie)) + +static void avr910_setup(PROGRAMMER * pgm) +{ + if ((pgm->cookie = malloc(sizeof(struct pdata))) == 0) { + fprintf(stderr, + "%s: avr910_setup(): Out of memory allocating private data\n", + progname); + exit(1); + } + memset(pgm->cookie, 0, sizeof(struct pdata)); +} + +static void avr910_teardown(PROGRAMMER * pgm) +{ + free(pgm->cookie); +} static int avr910_send(PROGRAMMER * pgm, char * buf, size_t len) @@ -164,8 +189,8 @@ static int avr910_initialize(PROGRAMMER * pgm, AVRPART * p) /* See if programmer supports autoincrement of address. */ avr910_send(pgm, "a", 1); - avr910_recv(pgm, &has_auto_incr_addr, 1); - if (has_auto_incr_addr == 'Y') + avr910_recv(pgm, &PDATA(pgm)->has_auto_incr_addr, 1); + if (PDATA(pgm)->has_auto_incr_addr == 'Y') fprintf(stderr, "Programmer supports auto addr increment.\n"); /* Get list of devices that the programmer supports. */ @@ -442,7 +467,7 @@ static int avr910_paged_write_flash(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, page_addr = addr; page_bytes = page_size; } - else if ((has_auto_incr_addr != 'Y') && ((addr & 0x01) == 0)) { + else if ((PDATA(pgm)->has_auto_incr_addr != 'Y') && ((addr & 0x01) == 0)) { avr910_set_addr(pgm, addr>>1); } @@ -482,7 +507,7 @@ static int avr910_paged_write_eeprom(PROGRAMMER * pgm, AVRPART * p, addr++; - if (has_auto_incr_addr != 'Y') { + if (PDATA(pgm)->has_auto_incr_addr != 'Y') { avr910_set_addr(pgm, addr); } @@ -548,7 +573,7 @@ static int avr910_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, addr++; - if (has_auto_incr_addr != 'Y') { + if (PDATA(pgm)->has_auto_incr_addr != 'Y') { avr910_set_addr(pgm, addr); } @@ -608,4 +633,7 @@ void avr910_initpgm(PROGRAMMER * pgm) pgm->paged_load = avr910_paged_load; pgm->read_sig_bytes = avr910_read_sig_bytes; + + pgm->setup = avr910_setup; + pgm->teardown = avr910_teardown; } diff --git a/butterfly.c b/butterfly.c index d2dfed12..5b0b732a 100644 --- a/butterfly.c +++ b/butterfly.c @@ -1,7 +1,7 @@ /* * avrdude - A Downloader/Uploader for AVR device programmers * Copyright (C) 2003-2004 Theodore A. Roth - * Copyright (C) 2005 Joerg Wunsch + * Copyright (C) 2005, 2007 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 @@ -50,8 +50,32 @@ #include "butterfly.h" #include "serial.h" -static char has_auto_incr_addr; -static unsigned buffersize = 0; +/* + * Private data for this programmer. + */ +struct pdata +{ + char has_auto_incr_addr; + unsigned int buffersize; +}; + +#define PDATA(pgm) ((struct pdata *)(pgm->cookie)) + +static void butterfly_setup(PROGRAMMER * pgm) +{ + if ((pgm->cookie = malloc(sizeof(struct pdata))) == 0) { + fprintf(stderr, + "%s: butterfly_setup(): Out of memory allocating private data\n", + progname); + exit(1); + } + memset(pgm->cookie, 0, sizeof(struct pdata)); +} + +static void butterfly_teardown(PROGRAMMER * pgm) +{ + free(pgm->cookie); +} static int butterfly_send(PROGRAMMER * pgm, char * buf, size_t len) { @@ -245,8 +269,8 @@ static int butterfly_initialize(PROGRAMMER * pgm, AVRPART * p) /* See if programmer supports autoincrement of address. */ butterfly_send(pgm, "a", 1); - butterfly_recv(pgm, &has_auto_incr_addr, 1); - if (has_auto_incr_addr == 'Y') + butterfly_recv(pgm, &PDATA(pgm)->has_auto_incr_addr, 1); + if (PDATA(pgm)->has_auto_incr_addr == 'Y') fprintf(stderr, "Programmer supports auto addr increment.\n"); /* Check support for buffered memory access, abort if not available */ @@ -260,12 +284,12 @@ static int butterfly_initialize(PROGRAMMER * pgm, AVRPART * p) exit(1); }; butterfly_recv(pgm, &c, 1); - buffersize = (unsigned int)(unsigned char)c<<8; + PDATA(pgm)->buffersize = (unsigned int)(unsigned char)c<<8; butterfly_recv(pgm, &c, 1); - buffersize += (unsigned int)(unsigned char)c; + PDATA(pgm)->buffersize += (unsigned int)(unsigned char)c; fprintf(stderr, "Programmer supports buffered memory access with buffersize=%i bytes.\n", - buffersize); + PDATA(pgm)->buffersize); /* Get list of devices that the programmer supports. */ @@ -519,7 +543,7 @@ static int butterfly_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, unsigned int addr = 0; unsigned int max_addr = n_bytes; char *cmd; - unsigned int blocksize = buffersize; + unsigned int blocksize = PDATA(pgm)->buffersize; int use_ext_addr = m->op[AVR_OP_LOAD_EXT_ADDR] != NULL; if (strcmp(m->desc, "flash") && strcmp(m->desc, "eeprom")) @@ -581,7 +605,7 @@ static int butterfly_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, { /* use buffered mode */ char cmd[4]; - int blocksize = buffersize; + int blocksize = PDATA(pgm)->buffersize; cmd[0] = 'g'; cmd[3] = toupper(m->desc[0]); @@ -664,4 +688,7 @@ void butterfly_initpgm(PROGRAMMER * pgm) pgm->paged_load = butterfly_paged_load; pgm->read_sig_bytes = butterfly_read_sig_bytes; + + pgm->setup = butterfly_setup; + pgm->teardown = butterfly_teardown; } diff --git a/jtagmkI.c b/jtagmkI.c index 1282ab88..94c84885 100644 --- a/jtagmkI.c +++ b/jtagmkI.c @@ -1,6 +1,6 @@ /* * avrdude - A Downloader/Uploader for AVR device programmers - * Copyright (C) 2005 Joerg Wunsch + * Copyright (C) 2005, 2007 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 @@ -41,24 +41,29 @@ #include "serial.h" /* - * XXX There should really be a programmer-specific private data - * pointer in struct PROGRAMMER. + * Private data for this programmer. */ -static int initial_baudrate; +struct pdata +{ + int 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; + /* + * See jtagmkI_read_byte() for an explanation of the flash and + * EEPROM page caches. + */ + unsigned char *flash_pagecache; + unsigned long flash_pageaddr; + unsigned int flash_pagesize; -static unsigned char *eeprom_pagecache; -static unsigned long eeprom_pageaddr; -static unsigned int eeprom_pagesize; + unsigned char *eeprom_pagecache; + unsigned long eeprom_pageaddr; + unsigned int eeprom_pagesize; + + int prog_enabled; /* Cached value of PROGRAMMING status. */ +}; + +#define PDATA(pgm) ((struct pdata *)(pgm->cookie)) -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 @@ -104,6 +109,23 @@ static void jtagmkI_print_parms1(PROGRAMMER * pgm, const char * p); static int jtagmkI_resync(PROGRAMMER *pgm, int maxtries, int signon); +static void jtagmkI_setup(PROGRAMMER * pgm) +{ + if ((pgm->cookie = malloc(sizeof(struct pdata))) == 0) { + fprintf(stderr, + "%s: jtagmkI_setup(): Out of memory allocating private data\n", + progname); + exit(1); + } + memset(pgm->cookie, 0, sizeof(struct pdata)); +} + +static void jtagmkI_teardown(PROGRAMMER * pgm) +{ + free(pgm->cookie); +} + + static void u32_to_b3(unsigned char *b, unsigned long l) { @@ -381,10 +403,10 @@ static void jtagmkI_set_devdescr(PROGRAMMER * pgm, AVRPART * p) 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); + PDATA(pgm)->flash_pagesize = m->page_size; + u16_to_b2(sendbuf.dd.uiFlashPageSize, PDATA(pgm)->flash_pagesize); } else if (strcmp(m->desc, "eeprom") == 0) { - sendbuf.dd.ucEepromPageSize = eeprom_pagesize = m->page_size; + sendbuf.dd.ucEepromPageSize = PDATA(pgm)->eeprom_pagesize = m->page_size; } } @@ -448,7 +470,7 @@ static int jtagmkI_program_enable(PROGRAMMER * pgm) { unsigned char buf[1], resp[2]; - if (prog_enabled) + if (PDATA(pgm)->prog_enabled) return 0; buf[0] = CMD_ENTER_PROGMODE; @@ -472,7 +494,7 @@ static int jtagmkI_program_enable(PROGRAMMER * pgm) fprintf(stderr, "OK\n"); } - prog_enabled = 1; + PDATA(pgm)->prog_enabled = 1; return 0; } @@ -481,7 +503,7 @@ static int jtagmkI_program_disable(PROGRAMMER * pgm) { unsigned char buf[1], resp[2]; - if (!prog_enabled) + if (!PDATA(pgm)->prog_enabled) return 0; if (pgm->fd.ifd != -1) { @@ -506,7 +528,7 @@ static int jtagmkI_program_disable(PROGRAMMER * pgm) fprintf(stderr, "OK\n"); } } - prog_enabled = 0; + PDATA(pgm)->prog_enabled = 0; return 0; } @@ -539,7 +561,7 @@ static int jtagmkI_initialize(PROGRAMMER * pgm, AVRPART * p) jtagmkI_drain(pgm, 0); - if ((serdev->flags & SERDEV_FL_CANSETSPEED) && initial_baudrate != pgm->baudrate) { + if ((serdev->flags & SERDEV_FL_CANSETSPEED) && PDATA(pgm)->initial_baudrate != pgm->baudrate) { if ((b = jtagmkI_get_baud(pgm->baudrate)) == 0) { fprintf(stderr, "%s: jtagmkI_initialize(): unsupported baudrate %d\n", progname, pgm->baudrate); @@ -549,7 +571,7 @@ static int jtagmkI_initialize(PROGRAMMER * pgm, AVRPART * p) "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 */ + PDATA(pgm)->initial_baudrate = pgm->baudrate; /* don't adjust again later */ serial_setspeed(&pgm->fd, pgm->baudrate); } } @@ -584,24 +606,24 @@ static int jtagmkI_initialize(PROGRAMMER * pgm, AVRPART * p) */ 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); + jtagmkI_setparm(pgm, PARM_FLASH_PAGESIZE_LOW, PDATA(pgm)->flash_pagesize & 0xff); + jtagmkI_setparm(pgm, PARM_FLASH_PAGESIZE_HIGH, PDATA(pgm)->flash_pagesize >> 8); + jtagmkI_setparm(pgm, PARM_EEPROM_PAGESIZE, PDATA(pgm)->eeprom_pagesize & 0xff); - free(flash_pagecache); - free(eeprom_pagecache); - if ((flash_pagecache = malloc(flash_pagesize)) == NULL) { + free(PDATA(pgm)->flash_pagecache); + free(PDATA(pgm)->eeprom_pagecache); + if ((PDATA(pgm)->flash_pagecache = malloc(PDATA(pgm)->flash_pagesize)) == NULL) { fprintf(stderr, "%s: jtagmkI_initialize(): Out of memory\n", progname); return -1; } - if ((eeprom_pagecache = malloc(eeprom_pagesize)) == NULL) { + if ((PDATA(pgm)->eeprom_pagecache = malloc(PDATA(pgm)->eeprom_pagesize)) == NULL) { fprintf(stderr, "%s: jtagmkI_initialize(): Out of memory\n", progname); - free(flash_pagecache); + free(PDATA(pgm)->flash_pagecache); return -1; } - flash_pageaddr = eeprom_pageaddr = (unsigned long)-1L; + PDATA(pgm)->flash_pageaddr = PDATA(pgm)->eeprom_pageaddr = (unsigned long)-1L; if (jtagmkI_reset(pgm) < 0) return -1; @@ -622,10 +644,10 @@ static int jtagmkI_initialize(PROGRAMMER * pgm, AVRPART * p) static void jtagmkI_disable(PROGRAMMER * pgm) { - free(flash_pagecache); - flash_pagecache = NULL; - free(eeprom_pagecache); - eeprom_pagecache = NULL; + free(PDATA(pgm)->flash_pagecache); + PDATA(pgm)->flash_pagecache = NULL; + free(PDATA(pgm)->eeprom_pagecache); + PDATA(pgm)->eeprom_pagecache = NULL; (void)jtagmkI_program_disable(pgm); } @@ -644,7 +666,7 @@ static int jtagmkI_open(PROGRAMMER * pgm, char * port) fprintf(stderr, "%s: jtagmkI_open()\n", progname); strcpy(pgm->port, port); - initial_baudrate = -1L; + PDATA(pgm)->initial_baudrate = -1L; for (i = 0; i < sizeof(baudtab) / sizeof(baudtab[0]); i++) { if (verbose >= 2) @@ -659,7 +681,7 @@ static int jtagmkI_open(PROGRAMMER * pgm, char * port) jtagmkI_drain(pgm, 0); if (jtagmkI_getsync(pgm) == 0) { - initial_baudrate = baudtab[i].baud; + PDATA(pgm)->initial_baudrate = baudtab[i].baud; if (verbose >= 2) fprintf(stderr, "%s: jtagmkI_open(): succeeded\n", progname); return 0; @@ -689,15 +711,15 @@ static void jtagmkI_close(PROGRAMMER * pgm) * appears to make AVR Studio happier when it is about to access the * ICE later on. */ - if ((serdev->flags & SERDEV_FL_CANSETSPEED) && initial_baudrate != pgm->baudrate) { - if ((b = jtagmkI_get_baud(initial_baudrate)) == 0) { + if ((serdev->flags & SERDEV_FL_CANSETSPEED) && PDATA(pgm)->initial_baudrate != pgm->baudrate) { + if ((b = jtagmkI_get_baud(PDATA(pgm)->initial_baudrate)) == 0) { fprintf(stderr, "%s: jtagmkI_close(): unsupported baudrate %d\n", - progname, initial_baudrate); + progname, PDATA(pgm)->initial_baudrate); } else { if (verbose >= 2) fprintf(stderr, "%s: jtagmkI_close(): " "trying to set baudrate to %d\n", - progname, initial_baudrate); + progname, PDATA(pgm)->initial_baudrate); if (jtagmkI_setparm(pgm, PARM_BITRATE, b) == 0) { serial_setspeed(&pgm->fd, pgm->baudrate); } @@ -746,13 +768,13 @@ static int jtagmkI_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, 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; + PDATA(pgm)->flash_pageaddr = (unsigned long)-1L; + page_size = PDATA(pgm)->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; + PDATA(pgm)->eeprom_pageaddr = (unsigned long)-1L; + page_size = PDATA(pgm)->eeprom_pagesize; } datacmd[0] = CMD_DATA; @@ -968,15 +990,15 @@ static int jtagmkI_read_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem, cmd[1] = MTYPE_FLASH_PAGE; pagesize = mem->page_size; paddr = addr & ~(pagesize - 1); - paddr_ptr = &flash_pageaddr; - cache_ptr = flash_pagecache; + paddr_ptr = &PDATA(pgm)->flash_pageaddr; + cache_ptr = PDATA(pgm)->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; + paddr_ptr = &PDATA(pgm)->eeprom_pageaddr; + cache_ptr = PDATA(pgm)->eeprom_pagecache; } else if (strcmp(mem->desc, "lfuse") == 0) { cmd[1] = MTYPE_FUSE_BITS; addr = 0; @@ -1078,11 +1100,11 @@ static int jtagmkI_write_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem, if (strcmp(mem->desc, "flash") == 0) { cmd[1] = MTYPE_SPM; need_progmode = 0; - flash_pageaddr = (unsigned long)-1L; + PDATA(pgm)->flash_pageaddr = (unsigned long)-1L; } else if (strcmp(mem->desc, "eeprom") == 0) { cmd[1] = MTYPE_EEPROM; need_progmode = 0; - eeprom_pageaddr = (unsigned long)-1L; + PDATA(pgm)->eeprom_pageaddr = (unsigned long)-1L; } else if (strcmp(mem->desc, "lfuse") == 0) { cmd[1] = MTYPE_FUSE_BITS; addr = 0; @@ -1374,5 +1396,7 @@ void jtagmkI_initpgm(PROGRAMMER * pgm) pgm->paged_load = jtagmkI_paged_load; pgm->print_parms = jtagmkI_print_parms; pgm->set_sck_period = jtagmkI_set_sck_period; + pgm->setup = jtagmkI_setup; + pgm->teardown = jtagmkI_teardown; pgm->page_size = 256; } diff --git a/jtagmkII.c b/jtagmkII.c index b0b02efd..130b0de0 100644 --- a/jtagmkII.c +++ b/jtagmkII.c @@ -1,6 +1,6 @@ /* * avrdude - A Downloader/Uploader for AVR device programmers - * Copyright (C) 2005,2006 Joerg Wunsch + * Copyright (C) 2005-2007 Joerg Wunsch * * Derived from stk500 code which is: * Copyright (C) 2002-2004 Brian S. Dean @@ -52,28 +52,35 @@ /* - * XXX There should really be a programmer-specific private data - * pointer in struct PROGRAMMER. + * Private data for this programmer. */ -static unsigned short command_sequence; /* Next cmd seqno to issue. */ +struct pdata +{ + unsigned short command_sequence; /* Next cmd seqno to issue. */ -/* - * See jtagmkII_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; + /* + * See jtagmkII_read_byte() for an explanation of the flash and + * EEPROM page caches. + */ + unsigned char *flash_pagecache; + unsigned long flash_pageaddr; + unsigned int flash_pagesize; -static unsigned char *eeprom_pagecache; -static unsigned long eeprom_pageaddr; -static unsigned int eeprom_pagesize; + unsigned char *eeprom_pagecache; + unsigned long eeprom_pageaddr; + unsigned int eeprom_pagesize; -static int prog_enabled; /* Cached value of PROGRAMMING status. */ -static unsigned char serno[6]; /* JTAG ICE serial number. */ + int prog_enabled; /* Cached value of PROGRAMMING status. */ + unsigned char serno[6]; /* JTAG ICE serial number. */ -/* JTAG chain stuff */ -static unsigned char jtagchain[4]; + /* JTAG chain stuff */ + unsigned char jtagchain[4]; + + /* The length of the device descriptor is firmware-dependent. */ + size_t device_descriptor_length; +}; + +#define PDATA(pgm) ((struct pdata *)(pgm->cookie)) /* * The OCDEN fuse is bit 7 of the high fuse (hfuse). In order to @@ -113,9 +120,6 @@ static struct { */ #define PGM_FL_IS_DW (0x0001) -/* 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); static int jtagmkII_write_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem, @@ -126,6 +130,23 @@ static int jtagmkII_setparm(PROGRAMMER * pgm, unsigned char parm, unsigned char * value); static void jtagmkII_print_parms1(PROGRAMMER * pgm, char * p); +static void jtagmkII_setup(PROGRAMMER * pgm) +{ + if ((pgm->cookie = malloc(sizeof(struct pdata))) == 0) { + fprintf(stderr, + "%s: jtagmkII_setup(): Out of memory allocating private data\n", + progname); + exit(1); + } + memset(pgm->cookie, 0, sizeof(struct pdata)); +} + +static void jtagmkII_teardown(PROGRAMMER * pgm) +{ + free(pgm->cookie); +} + + static unsigned long b4_to_u32(unsigned char *b) { @@ -353,7 +374,7 @@ int jtagmkII_send(PROGRAMMER * pgm, unsigned char * data, size_t len) } buf[0] = MESSAGE_START; - u16_to_b2(buf + 1, command_sequence); + u16_to_b2(buf + 1, PDATA(pgm)->command_sequence); u32_to_b4(buf + 3, len); buf[7] = TOKEN; memcpy(buf + 8, data, len); @@ -549,10 +570,10 @@ int jtagmkII_recv(PROGRAMMER * pgm, unsigned char **msg) { if (verbose >= 3) fprintf(stderr, "%s: jtagmkII_recv(): " "Got message seqno %d (command_sequence == %d)\n", - progname, r_seqno, command_sequence); - if (r_seqno == command_sequence) { - if (++command_sequence == 0xffff) - command_sequence = 0; + progname, r_seqno, PDATA(pgm)->command_sequence); + if (r_seqno == PDATA(pgm)->command_sequence) { + if (++(PDATA(pgm)->command_sequence) == 0xffff) + PDATA(pgm)->command_sequence = 0; /* * We move the payload to the beginning of the buffer, to make * the job easier for the caller. We have to return the @@ -569,7 +590,7 @@ int jtagmkII_recv(PROGRAMMER * pgm, unsigned char **msg) { if (verbose >= 2) fprintf(stderr, "%s: jtagmkII_recv(): " "got wrong sequence number, %u != %u\n", - progname, r_seqno, command_sequence); + progname, r_seqno, PDATA(pgm)->command_sequence); } free(*msg); } @@ -611,7 +632,7 @@ int jtagmkII_getsync(PROGRAMMER * pgm, int mode) { if ((c = resp[0]) == RSP_SIGN_ON) { fwver = ((unsigned)resp[8] << 8) | (unsigned)resp[7]; hwver = (unsigned)resp[9]; - memcpy(serno, resp + 10, 6); + memcpy(PDATA(pgm)->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", @@ -632,7 +653,7 @@ int jtagmkII_getsync(PROGRAMMER * pgm, int mode) { (unsigned)resp[9]); fprintf(stderr, "Serial number: " "%02x:%02x:%02x:%02x:%02x:%02x\n", - serno[0], serno[1], serno[2], serno[3], serno[4], serno[5]); + PDATA(pgm)->serno[0], PDATA(pgm)->serno[1], PDATA(pgm)->serno[2], PDATA(pgm)->serno[3], PDATA(pgm)->serno[4], PDATA(pgm)->serno[5]); resp[status - 1] = '\0'; fprintf(stderr, "Device ID: %s\n", resp + 16); @@ -656,7 +677,7 @@ int jtagmkII_getsync(PROGRAMMER * pgm, int mode) { return -1; } - device_descriptor_length = sizeof(struct device_descriptor); + PDATA(pgm)->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 @@ -668,20 +689,20 @@ int jtagmkII_getsync(PROGRAMMER * pgm, int mode) { */ #define FWVER(maj, min) ((maj << 8) | (min)) if (hwver == 0 && fwver < FWVER(3, 16)) { - device_descriptor_length -= 2; + PDATA(pgm)->device_descriptor_length -= 2; fprintf(stderr, "%s: jtagmkII_getsync(): " "S_MCU firmware version might be too old to work correctly\n", progname); } else if (hwver == 0 && fwver < FWVER(4, 0)) { - device_descriptor_length -= 2; + PDATA(pgm)->device_descriptor_length -= 2; } if (verbose >= 2 && mode != EMULATOR_MODE_SPI) fprintf(stderr, "%s: jtagmkII_getsync(): Using a %zu-byte device descriptor\n", - progname, device_descriptor_length); + progname, PDATA(pgm)->device_descriptor_length); if (mode == EMULATOR_MODE_SPI || mode == EMULATOR_MODE_HV) { - device_descriptor_length = 0; + PDATA(pgm)->device_descriptor_length = 0; if (hwver == 0 && fwver < FWVER(4, 14)) { fprintf(stderr, "%s: jtagmkII_getsync(): ISP functionality requires firmware " @@ -843,16 +864,16 @@ static void jtagmkII_set_devdescr(PROGRAMMER * pgm, AVRPART * p) for (ln = lfirst(p->mem); ln; ln = lnext(ln)) { m = ldata(ln); if (strcmp(m->desc, "flash") == 0) { - flash_pagesize = m->page_size; + PDATA(pgm)->flash_pagesize = m->page_size; u32_to_b4(sendbuf.dd.ulFlashSize, m->size); - u16_to_b2(sendbuf.dd.uiFlashPageSize, flash_pagesize); - u16_to_b2(sendbuf.dd.uiFlashpages, m->size / flash_pagesize); + u16_to_b2(sendbuf.dd.uiFlashPageSize, PDATA(pgm)->flash_pagesize); + u16_to_b2(sendbuf.dd.uiFlashpages, m->size / PDATA(pgm)->flash_pagesize); if (p->flags & AVRPART_HAS_DW) { memcpy(sendbuf.dd.ucFlashInst, p->flash_instr, FLASH_INSTR_SIZE); memcpy(sendbuf.dd.ucEepromInst, p->eeprom_instr, EEPROM_INSTR_SIZE); } } else if (strcmp(m->desc, "eeprom") == 0) { - sendbuf.dd.ucEepromPageSize = eeprom_pagesize = m->page_size; + sendbuf.dd.ucEepromPageSize = PDATA(pgm)->eeprom_pagesize = m->page_size; } } @@ -861,7 +882,7 @@ static void jtagmkII_set_devdescr(PROGRAMMER * pgm, AVRPART * p) "Sending set device descriptor command: ", progname); jtagmkII_send(pgm, (unsigned char *)&sendbuf, - device_descriptor_length + sizeof(unsigned char)); + PDATA(pgm)->device_descriptor_length + sizeof(unsigned char)); status = jtagmkII_recv(pgm, &resp); if (status <= 0) { @@ -952,7 +973,7 @@ static int jtagmkII_program_enable(PROGRAMMER * pgm) int status; unsigned char buf[1], *resp, c; - if (prog_enabled) + if (PDATA(pgm)->prog_enabled) return 0; buf[0] = CMND_ENTER_PROGMODE; @@ -989,7 +1010,7 @@ static int jtagmkII_program_enable(PROGRAMMER * pgm) return -1; } - prog_enabled = 1; + PDATA(pgm)->prog_enabled = 1; return 0; } @@ -998,7 +1019,7 @@ static int jtagmkII_program_disable(PROGRAMMER * pgm) int status; unsigned char buf[1], *resp, c; - if (!prog_enabled) + if (!PDATA(pgm)->prog_enabled) return 0; buf[0] = CMND_LEAVE_PROGMODE; @@ -1033,7 +1054,7 @@ static int jtagmkII_program_disable(PROGRAMMER * pgm) return -1; } - prog_enabled = 0; + PDATA(pgm)->prog_enabled = 0; (void)jtagmkII_reset(pgm, 0x01); return 0; @@ -1112,7 +1133,7 @@ static int jtagmkII_initialize(PROGRAMMER * pgm, AVRPART * p) return -1; } - if (jtagmkII_setparm(pgm, PAR_DAISY_CHAIN_INFO, jtagchain) < 0) { + if (jtagmkII_setparm(pgm, PAR_DAISY_CHAIN_INFO, PDATA(pgm)->jtagchain) < 0) { fprintf(stderr, "%s: jtagmkII_initialize(): Failed to setup JTAG chain\n", progname); return -1; @@ -1123,20 +1144,20 @@ static int jtagmkII_initialize(PROGRAMMER * pgm, AVRPART * p) */ jtagmkII_set_devdescr(pgm, p); - free(flash_pagecache); - free(eeprom_pagecache); - if ((flash_pagecache = malloc(flash_pagesize)) == NULL) { + free(PDATA(pgm)->flash_pagecache); + free(PDATA(pgm)->eeprom_pagecache); + if ((PDATA(pgm)->flash_pagecache = malloc(PDATA(pgm)->flash_pagesize)) == NULL) { fprintf(stderr, "%s: jtagmkII_initialize(): Out of memory\n", progname); return -1; } - if ((eeprom_pagecache = malloc(eeprom_pagesize)) == NULL) { + if ((PDATA(pgm)->eeprom_pagecache = malloc(PDATA(pgm)->eeprom_pagesize)) == NULL) { fprintf(stderr, "%s: jtagmkII_initialize(): Out of memory\n", progname); - free(flash_pagecache); + free(PDATA(pgm)->flash_pagecache); return -1; } - flash_pageaddr = eeprom_pageaddr = (unsigned long)-1L; + PDATA(pgm)->flash_pageaddr = PDATA(pgm)->eeprom_pageaddr = (unsigned long)-1L; if (jtagmkII_reset(pgm, 0x01) < 0) return -1; @@ -1159,10 +1180,10 @@ static int jtagmkII_initialize(PROGRAMMER * pgm, AVRPART * p) static void jtagmkII_disable(PROGRAMMER * pgm) { - free(flash_pagecache); - flash_pagecache = NULL; - free(eeprom_pagecache); - eeprom_pagecache = NULL; + free(PDATA(pgm)->flash_pagecache); + PDATA(pgm)->flash_pagecache = NULL; + free(PDATA(pgm)->eeprom_pagecache); + PDATA(pgm)->eeprom_pagecache = NULL; if (!(pgm->flag & PGM_FL_IS_DW)) (void)jtagmkII_program_disable(pgm); @@ -1199,10 +1220,10 @@ static int jtagmkII_parseextparms(PROGRAMMER * pgm, LISTID extparms) progname, progbuf, ub, ua, bb, ba); } - jtagchain[0] = ub; - jtagchain[1] = ua; - jtagchain[2] = bb; - jtagchain[3] = ba; + PDATA(pgm)->jtagchain[0] = ub; + PDATA(pgm)->jtagchain[1] = ua; + PDATA(pgm)->jtagchain[2] = bb; + PDATA(pgm)->jtagchain[3] = ba; continue; } @@ -1405,7 +1426,7 @@ void jtagmkII_close(PROGRAMMER * pgm) if (verbose >= 2) fprintf(stderr, "%s: jtagmkII_close()\n", progname); - if (device_descriptor_length) { + if (PDATA(pgm)->device_descriptor_length) { /* When in JTAG mode, restart target. */ buf[0] = CMND_GO; if (verbose >= 2) @@ -1500,12 +1521,12 @@ static int jtagmkII_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, cmd[0] = CMND_WRITE_MEMORY; if (strcmp(m->desc, "flash") == 0) { cmd[1] = MTYPE_FLASH_PAGE; - flash_pageaddr = (unsigned long)-1L; - page_size = flash_pagesize; + PDATA(pgm)->flash_pageaddr = (unsigned long)-1L; + page_size = PDATA(pgm)->flash_pagesize; } else if (strcmp(m->desc, "eeprom") == 0) { cmd[1] = MTYPE_EEPROM_PAGE; - eeprom_pageaddr = (unsigned long)-1L; - page_size = eeprom_pagesize; + PDATA(pgm)->eeprom_pageaddr = (unsigned long)-1L; + page_size = PDATA(pgm)->eeprom_pagesize; if (pgm->flag & PGM_FL_IS_DW) { free(cmd); return -1; @@ -1708,8 +1729,8 @@ static int jtagmkII_read_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem, cmd[1] = MTYPE_FLASH_PAGE; pagesize = mem->page_size; paddr = addr & ~(pagesize - 1); - paddr_ptr = &flash_pageaddr; - cache_ptr = flash_pagecache; + paddr_ptr = &PDATA(pgm)->flash_pageaddr; + cache_ptr = PDATA(pgm)->flash_pagecache; } else if (strcmp(mem->desc, "eeprom") == 0) { if (pgm->flag & PGM_FL_IS_DW) { /* debugWire cannot use page access for EEPROM */ @@ -1718,8 +1739,8 @@ static int jtagmkII_read_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem, cmd[1] = MTYPE_EEPROM_PAGE; pagesize = mem->page_size; paddr = addr & ~(pagesize - 1); - paddr_ptr = &eeprom_pageaddr; - cache_ptr = eeprom_pagecache; + paddr_ptr = &PDATA(pgm)->eeprom_pageaddr; + cache_ptr = PDATA(pgm)->eeprom_pagecache; } } else if (strcmp(mem->desc, "lfuse") == 0) { cmd[1] = MTYPE_FUSE_BITS; @@ -1877,13 +1898,13 @@ static int jtagmkII_write_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem, if (strcmp(mem->desc, "flash") == 0) { cmd[1] = MTYPE_SPM; need_progmode = 0; - flash_pageaddr = (unsigned long)-1L; + PDATA(pgm)->flash_pageaddr = (unsigned long)-1L; if (pgm->flag & PGM_FL_IS_DW) unsupp = 1; } else if (strcmp(mem->desc, "eeprom") == 0) { cmd[1] = MTYPE_EEPROM; need_progmode = 0; - eeprom_pageaddr = (unsigned long)-1L; + PDATA(pgm)->eeprom_pageaddr = (unsigned long)-1L; } else if (strcmp(mem->desc, "lfuse") == 0) { cmd[1] = MTYPE_FUSE_BITS; addr = 0; @@ -2137,7 +2158,7 @@ static void jtagmkII_display(PROGRAMMER * pgm, const char * p) fprintf(stderr, "%sS_MCU hardware version: %d\n", p, hw[1]); fprintf(stderr, "%sS_MCU firmware version: %d.%02d\n", p, fw[3], fw[2]); fprintf(stderr, "%sSerial number: %02x:%02x:%02x:%02x:%02x:%02x\n", - p, serno[0], serno[1], serno[2], serno[3], serno[4], serno[5]); + p, PDATA(pgm)->serno[0], PDATA(pgm)->serno[1], PDATA(pgm)->serno[2], PDATA(pgm)->serno[3], PDATA(pgm)->serno[4], PDATA(pgm)->serno[5]); jtagmkII_print_parms1(pgm, p); @@ -2215,6 +2236,8 @@ void jtagmkII_initpgm(PROGRAMMER * pgm) pgm->print_parms = jtagmkII_print_parms; pgm->set_sck_period = jtagmkII_set_sck_period; pgm->parseextparams = jtagmkII_parseextparms; + pgm->setup = jtagmkII_setup; + pgm->teardown = jtagmkII_teardown; pgm->page_size = 256; } @@ -2243,6 +2266,8 @@ void jtagmkII_dw_initpgm(PROGRAMMER * pgm) pgm->paged_write = jtagmkII_paged_write; pgm->paged_load = jtagmkII_paged_load; pgm->print_parms = jtagmkII_print_parms; + pgm->setup = jtagmkII_setup; + pgm->teardown = jtagmkII_teardown; pgm->page_size = 256; pgm->flag = PGM_FL_IS_DW; } @@ -2274,6 +2299,8 @@ void jtagmkII_dragon_initpgm(PROGRAMMER * pgm) pgm->print_parms = jtagmkII_print_parms; pgm->set_sck_period = jtagmkII_set_sck_period; pgm->parseextparams = jtagmkII_parseextparms; + pgm->setup = jtagmkII_setup; + pgm->teardown = jtagmkII_teardown; pgm->page_size = 256; } @@ -2302,6 +2329,8 @@ void jtagmkII_dragon_dw_initpgm(PROGRAMMER * pgm) pgm->paged_write = jtagmkII_paged_write; pgm->paged_load = jtagmkII_paged_load; pgm->print_parms = jtagmkII_print_parms; + pgm->setup = jtagmkII_setup; + pgm->teardown = jtagmkII_teardown; pgm->page_size = 256; pgm->flag = PGM_FL_IS_DW; } diff --git a/main.c b/main.c index 8c059745..db8d7bba 100644 --- a/main.c +++ b/main.c @@ -1,6 +1,7 @@ /* * avrdude - A Downloader/Uploader for AVR device programmers * Copyright (C) 2000-2005 Brian S. Dean + * Copyright 2007 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 @@ -74,6 +75,8 @@ static LISTID updates; static LISTID extended_params; +static PROGRAMMER * pgm; + /* * global options */ @@ -222,6 +225,12 @@ static void list_parts(FILE * f, const char *prefix, LISTID avrparts) walk_avrparts(avrparts, list_avrparts_callback, &c); } +static void exithook(void) +{ + if (pgm->teardown) + pgm->teardown(pgm); +} + /* * main routine */ @@ -238,7 +247,6 @@ int main(int argc, char * argv []) struct stat sb; UPDATE * upd; LNODEID * ln; - PROGRAMMER * pgm; /* options / operating mode variables */ @@ -636,6 +644,13 @@ int main(int argc, char * argv []) exit(1); } + if (pgm->setup) { + pgm->setup(pgm); + } + if (pgm->teardown) { + atexit(exithook); + } + if (lsize(extended_params) > 0) { if (pgm->parseextparams == NULL) { fprintf(stderr, diff --git a/pgm.c b/pgm.c index 5c6dd4f3..a9502721 100644 --- a/pgm.c +++ b/pgm.c @@ -1,6 +1,7 @@ /* * avrdude - A Downloader/Uploader for AVR device programmers * Copyright (C) 2002-2004 Brian S. Dean + * Copyright 2007 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 @@ -126,6 +127,8 @@ PROGRAMMER * pgm_new(void) pgm->set_fosc = NULL; pgm->perform_osccal = NULL; pgm->parseextparams = NULL; + pgm->setup = NULL; + pgm->teardown = NULL; return pgm; } diff --git a/pgm.h b/pgm.h index 3672afc5..f22767cc 100644 --- a/pgm.h +++ b/pgm.h @@ -1,6 +1,7 @@ /* * avrdude - A Downloader/Uploader for AVR device programmers * Copyright (C) 2002-2004 Brian S. Dean + * Copyright 2007 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 @@ -100,8 +101,11 @@ typedef struct programmer_t { int (*parseexitspecs) (struct programmer_t * pgm, char *s); int (*perform_osccal) (struct programmer_t * pgm); int (*parseextparams) (struct programmer_t * pgm, LISTID xparams); + void (*setup) (struct programmer_t * pgm); + void (*teardown) (struct programmer_t * pgm); char config_file[PATH_MAX]; /* config file where defined */ int lineno; /* config file line number */ + void *cookie; /* for private use by the programmer */ char flag; /* for private use of the programmer */ } PROGRAMMER; diff --git a/stk500v2.c b/stk500v2.c index a08e583d..b58fa004 100644 --- a/stk500v2.c +++ b/stk500v2.c @@ -3,7 +3,7 @@ * Copyright (C) 2005 Erik Walthinsen * Copyright (C) 2002-2004 Brian S. Dean * Copyright (C) 2006 David Moore - * Copyright (C) 2006 Joerg Wunsch + * Copyright (C) 2006,2007 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 @@ -87,18 +87,27 @@ enum hvmode /* - * See stk500pp_read_byte() for an explanation of the flash and - * EEPROM page caches. + * Private data for this programmer. */ -static unsigned char *flash_pagecache; -static unsigned long flash_pageaddr; -static unsigned int flash_pagesize; +struct pdata +{ + /* + * See stk500pp_read_byte() for an explanation of the flash and + * EEPROM page caches. + */ + unsigned char *flash_pagecache; + unsigned long flash_pageaddr; + unsigned int flash_pagesize; -static unsigned char *eeprom_pagecache; -static unsigned long eeprom_pageaddr; -static unsigned int eeprom_pagesize; + unsigned char *eeprom_pagecache; + unsigned long eeprom_pageaddr; + unsigned int eeprom_pagesize; + + unsigned char command_sequence; +}; + +#define PDATA(pgm) ((struct pdata *)(pgm->cookie)) -static unsigned char command_sequence = 1; static enum { @@ -190,6 +199,24 @@ static unsigned int stk500v2_mode_for_pagesize(unsigned int pagesize); static int stk500v2_set_sck_period_mk2(PROGRAMMER * pgm, double v); +static void stk500v2_setup(PROGRAMMER * pgm) +{ + if ((pgm->cookie = malloc(sizeof(struct pdata))) == 0) { + fprintf(stderr, + "%s: stk500v2_setup(): Out of memory allocating private data\n", + progname); + exit(1); + } + memset(pgm->cookie, 0, sizeof(struct pdata)); + PDATA(pgm)->command_sequence = 1; +} + +static void stk500v2_teardown(PROGRAMMER * pgm) +{ + free(pgm->cookie); +} + + static unsigned short b2_to_u16(unsigned char *b) { @@ -280,7 +307,7 @@ static int stk500v2_send(PROGRAMMER * pgm, unsigned char * data, size_t len) return stk500v2_jtagmkII_send(pgm, data, len); buf[0] = MESSAGE_START; - buf[1] = command_sequence; + buf[1] = PDATA(pgm)->command_sequence; buf[2] = len / 256; buf[3] = len % 256; buf[4] = TOKEN; @@ -400,10 +427,10 @@ static int stk500v2_recv(PROGRAMMER * pgm, unsigned char msg[], size_t maxsize) break; case sSEQNUM: DEBUGRECV("hoping for sequence...\n"); - if (c == command_sequence) { + if (c == PDATA(pgm)->command_sequence) { DEBUGRECV("got it, incrementing\n"); state = sSIZE1; - command_sequence++; + PDATA(pgm)->command_sequence++; } else { DEBUGRECV("sorry\n"); state = sSTART; @@ -828,32 +855,32 @@ static int stk500hv_initialize(PROGRAMMER * pgm, AVRPART * p, enum hvmode mode) * caches. For devices/memory that are not page oriented, treat * them as page size 1 for EEPROM, and 2 for flash. */ - flash_pagesize = 2; - eeprom_pagesize = 1; + PDATA(pgm)->flash_pagesize = 2; + PDATA(pgm)->eeprom_pagesize = 1; for (ln = lfirst(p->mem); ln; ln = lnext(ln)) { m = ldata(ln); if (strcmp(m->desc, "flash") == 0) { if (m->page_size > 0) - flash_pagesize = m->page_size; + PDATA(pgm)->flash_pagesize = m->page_size; } else if (strcmp(m->desc, "eeprom") == 0) { if (m->page_size > 0) - eeprom_pagesize = m->page_size; + PDATA(pgm)->eeprom_pagesize = m->page_size; } } - free(flash_pagecache); - free(eeprom_pagecache); - if ((flash_pagecache = malloc(flash_pagesize)) == NULL) { + free(PDATA(pgm)->flash_pagecache); + free(PDATA(pgm)->eeprom_pagecache); + if ((PDATA(pgm)->flash_pagecache = malloc(PDATA(pgm)->flash_pagesize)) == NULL) { fprintf(stderr, "%s: stk500pp_initialize(): Out of memory\n", progname); return -1; } - if ((eeprom_pagecache = malloc(eeprom_pagesize)) == NULL) { + if ((PDATA(pgm)->eeprom_pagecache = malloc(PDATA(pgm)->eeprom_pagesize)) == NULL) { fprintf(stderr, "%s: stk500pp_initialize(): Out of memory\n", progname); - free(flash_pagecache); + free(PDATA(pgm)->flash_pagecache); return -1; } - flash_pageaddr = eeprom_pageaddr = (unsigned long)-1L; + PDATA(pgm)->flash_pageaddr = PDATA(pgm)->eeprom_pageaddr = (unsigned long)-1L; return pgm->program_enable(pgm, p); } @@ -902,10 +929,10 @@ static void stk500hv_disable(PROGRAMMER * pgm, enum hvmode mode) unsigned char buf[16]; int result; - free(flash_pagecache); - flash_pagecache = NULL; - free(eeprom_pagecache); - eeprom_pagecache = NULL; + free(PDATA(pgm)->flash_pagecache); + PDATA(pgm)->flash_pagecache = NULL; + free(PDATA(pgm)->eeprom_pagecache); + PDATA(pgm)->eeprom_pagecache = NULL; buf[0] = mode == PPMODE? CMD_LEAVE_PROGMODE_PP: CMD_LEAVE_PROGMODE_HVSP; buf[1] = 15; // p->hvleavestabdelay; @@ -1065,8 +1092,8 @@ static int stk500hv_read_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem, if (pagesize == 0) pagesize = 2; paddr = addr & ~(pagesize - 1); - paddr_ptr = &flash_pageaddr; - cache_ptr = flash_pagecache; + paddr_ptr = &PDATA(pgm)->flash_pageaddr; + cache_ptr = PDATA(pgm)->flash_pagecache; addrshift = 1; /* * If bit 31 is set, this indicates that the following read/write @@ -1084,8 +1111,8 @@ static int stk500hv_read_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem, if (pagesize == 0) pagesize = 1; paddr = addr & ~(pagesize - 1); - paddr_ptr = &eeprom_pageaddr; - cache_ptr = eeprom_pagecache; + paddr_ptr = &PDATA(pgm)->eeprom_pageaddr; + cache_ptr = PDATA(pgm)->eeprom_pagecache; } else if (strcmp(mem->desc, "lfuse") == 0 || strcmp(mem->desc, "fuse") == 0) { buf[0] = mode == PPMODE? CMD_READ_FUSE_PP: CMD_READ_FUSE_HVSP; @@ -1195,8 +1222,8 @@ static int stk500hv_write_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem, if (pagesize == 0) pagesize = 2; paddr = addr & ~(pagesize - 1); - paddr_ptr = &flash_pageaddr; - cache_ptr = flash_pagecache; + paddr_ptr = &PDATA(pgm)->flash_pageaddr; + cache_ptr = PDATA(pgm)->flash_pagecache; addrshift = 1; /* * If bit 31 is set, this indicates that the following read/write @@ -1213,8 +1240,8 @@ static int stk500hv_write_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem, if (pagesize == 0) pagesize = 1; paddr = addr & ~(pagesize - 1); - paddr_ptr = &eeprom_pageaddr; - cache_ptr = eeprom_pagecache; + paddr_ptr = &PDATA(pgm)->eeprom_pageaddr; + cache_ptr = PDATA(pgm)->eeprom_pagecache; } else if (strcmp(mem->desc, "lfuse") == 0 || strcmp(mem->desc, "fuse") == 0) { buf[0] = mode == PPMODE? CMD_PROGRAM_FUSE_PP: CMD_PROGRAM_FUSE_HVSP; @@ -1487,7 +1514,7 @@ static int stk500hv_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, // determine which command is to be used if (strcmp(m->desc, "flash") == 0) { addrshift = 1; - flash_pageaddr = (unsigned long)-1L; + PDATA(pgm)->flash_pageaddr = (unsigned long)-1L; commandbuf[0] = mode == PPMODE? CMD_PROGRAM_FLASH_PP: CMD_PROGRAM_FLASH_HVSP; /* * If bit 31 is set, this indicates that the following read/write @@ -1499,7 +1526,7 @@ static int stk500hv_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, use_ext_addr = (1U << 31); } } else if (strcmp(m->desc, "eeprom") == 0) { - eeprom_pageaddr = (unsigned long)-1L; + PDATA(pgm)->eeprom_pageaddr = (unsigned long)-1L; commandbuf[0] = mode == PPMODE? CMD_PROGRAM_EEPROM_PP: CMD_PROGRAM_EEPROM_HVSP; } /* @@ -2386,6 +2413,8 @@ void stk500v2_initpgm(PROGRAMMER * pgm) pgm->set_fosc = stk500v2_set_fosc; pgm->set_sck_period = stk500v2_set_sck_period; pgm->perform_osccal = stk500v2_perform_osccal; + pgm->setup = stk500v2_setup; + pgm->teardown = stk500v2_teardown; pgm->page_size = 256; } @@ -2417,6 +2446,8 @@ void stk500pp_initpgm(PROGRAMMER * pgm) pgm->set_varef = stk500v2_set_varef; pgm->set_fosc = stk500v2_set_fosc; pgm->set_sck_period = stk500v2_set_sck_period; + pgm->setup = stk500v2_setup; + pgm->teardown = stk500v2_teardown; pgm->page_size = 256; } @@ -2448,6 +2479,8 @@ void stk500hvsp_initpgm(PROGRAMMER * pgm) pgm->set_varef = stk500v2_set_varef; pgm->set_fosc = stk500v2_set_fosc; pgm->set_sck_period = stk500v2_set_sck_period; + pgm->setup = stk500v2_setup; + pgm->teardown = stk500v2_teardown; pgm->page_size = 256; } @@ -2478,6 +2511,8 @@ void stk500v2_jtagmkII_initpgm(PROGRAMMER * pgm) pgm->print_parms = stk500v2_print_parms; pgm->set_sck_period = stk500v2_set_sck_period_mk2; pgm->perform_osccal = stk500v2_perform_osccal; + pgm->setup = stk500v2_setup; + pgm->teardown = stk500v2_teardown; pgm->page_size = 256; } @@ -2507,6 +2542,8 @@ void stk500v2_dragon_isp_initpgm(PROGRAMMER * pgm) pgm->paged_load = stk500v2_paged_load; pgm->print_parms = stk500v2_print_parms; pgm->set_sck_period = stk500v2_set_sck_period_mk2; + pgm->setup = stk500v2_setup; + pgm->teardown = stk500v2_teardown; pgm->page_size = 256; } @@ -2538,6 +2575,8 @@ void stk500v2_dragon_pp_initpgm(PROGRAMMER * pgm) pgm->set_varef = stk500v2_set_varef; pgm->set_fosc = stk500v2_set_fosc; pgm->set_sck_period = stk500v2_set_sck_period_mk2; + pgm->setup = stk500v2_setup; + pgm->teardown = stk500v2_teardown; pgm->page_size = 256; } @@ -2569,5 +2608,7 @@ void stk500v2_dragon_hvsp_initpgm(PROGRAMMER * pgm) pgm->set_varef = stk500v2_set_varef; pgm->set_fosc = stk500v2_set_fosc; pgm->set_sck_period = stk500v2_set_sck_period_mk2; + pgm->setup = stk500v2_setup; + pgm->teardown = stk500v2_teardown; pgm->page_size = 256; } diff --git a/usbasp.c b/usbasp.c index 6bfe14e0..c4266af5 100644 --- a/usbasp.c +++ b/usbasp.c @@ -1,6 +1,7 @@ /* * avrdude - A Downloader/Uploader for AVR device programmers * Copyright (C) 2006 Thomas Fischl + * Copyright 2007 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 @@ -41,16 +42,42 @@ #ifdef HAVE_LIBUSB #include -static usb_dev_handle *usbhandle; +/* + * Private data for this programmer. + */ +struct pdata +{ + usb_dev_handle *usbhandle; +}; + +#define PDATA(pgm) ((struct pdata *)(pgm->cookie)) + +static void usbasp_setup(PROGRAMMER * pgm) +{ + if ((pgm->cookie = malloc(sizeof(struct pdata))) == 0) { + fprintf(stderr, + "%s: usbasp_setup(): Out of memory allocating private data\n", + progname); + exit(1); + } + memset(pgm->cookie, 0, sizeof(struct pdata)); +} + +static void usbasp_teardown(PROGRAMMER * pgm) +{ + free(pgm->cookie); +} + /* * wrapper for usb_control_msg call */ -static int usbasp_transmit(unsigned char receive, unsigned char functionid, +static int usbasp_transmit(PROGRAMMER * pgm, + unsigned char receive, unsigned char functionid, unsigned char send[4], unsigned char * buffer, int buffersize) { int nbytes; - nbytes = usb_control_msg(usbhandle, + nbytes = usb_control_msg(PDATA(pgm)->usbhandle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | (receive << 7), functionid, (send[1] << 8) | send[0], @@ -158,11 +185,11 @@ static int usbasp_open(PROGRAMMER * pgm, char * port) { usb_init(); - if (usbOpenDevice(&usbhandle, USBASP_SHARED_VID, "www.fischl.de", + if (usbOpenDevice(&PDATA(pgm)->usbhandle, USBASP_SHARED_VID, "www.fischl.de", USBASP_SHARED_PID, "USBasp") != 0) { /* check if device with old VID/PID is available */ - if (usbOpenDevice(&usbhandle, USBASP_OLD_VID, "www.fischl.de", + if (usbOpenDevice(&PDATA(pgm)->usbhandle, USBASP_OLD_VID, "www.fischl.de", USBASP_OLD_PID, "USBasp") != 0) { /* no USBasp found */ @@ -190,9 +217,9 @@ static void usbasp_close(PROGRAMMER * pgm) { unsigned char temp[4]; memset(temp, 0, sizeof(temp)); - usbasp_transmit(1, USBASP_FUNC_DISCONNECT, temp, temp, sizeof(temp)); + usbasp_transmit(pgm, 1, USBASP_FUNC_DISCONNECT, temp, temp, sizeof(temp)); - usb_close(usbhandle); + usb_close(PDATA(pgm)->usbhandle); } @@ -201,7 +228,7 @@ static int usbasp_initialize(PROGRAMMER * pgm, AVRPART * p) unsigned char temp[4]; memset(temp, 0, sizeof(temp)); - usbasp_transmit(1, USBASP_FUNC_CONNECT, temp, temp, sizeof(temp)); + usbasp_transmit(pgm, 1, USBASP_FUNC_CONNECT, temp, temp, sizeof(temp)); usleep(100000); @@ -232,7 +259,7 @@ static int usbasp_cmd(PROGRAMMER * pgm, unsigned char cmd[4], unsigned char res[4]) { int nbytes = - usbasp_transmit(1, USBASP_FUNC_TRANSMIT, cmd, res, sizeof(res)); + usbasp_transmit(pgm, 1, USBASP_FUNC_TRANSMIT, cmd, res, sizeof(res)); if(nbytes != 4){ fprintf(stderr, "%s: error: wrong responds size\n", @@ -254,7 +281,7 @@ static int usbasp_program_enable(PROGRAMMER * pgm, AVRPART * p) cmd[0] = 0; int nbytes = - usbasp_transmit(1, USBASP_FUNC_ENABLEPROG, cmd, res, sizeof(res)); + usbasp_transmit(pgm, 1, USBASP_FUNC_ENABLEPROG, cmd, res, sizeof(res)); if ((nbytes != 1) | (res[0] != 0)) { fprintf(stderr, "%s: error: programm enable: target doesn't answer. %x \n", @@ -323,7 +350,7 @@ static int usbasp_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, cmd[1] = address >> 8; cmd[2] = address >> 16; cmd[3] = address >> 24; - usbasp_transmit(1, USBASP_FUNC_SETLONGADDRESS, cmd, temp, sizeof(temp)); + usbasp_transmit(pgm, 1, USBASP_FUNC_SETLONGADDRESS, cmd, temp, sizeof(temp)); /* send command with address (compatibility mode) - if firmware on usbasp doesn't support newmode, then they use address from this */ @@ -333,7 +360,7 @@ static int usbasp_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, cmd[2] = 0; cmd[3] = 0; - n = usbasp_transmit(1, function, cmd, buffer, blocksize); + n = usbasp_transmit(pgm, 1, function, cmd, buffer, blocksize); if (n != blocksize) { fprintf(stderr, "%s: error: wrong reading bytes %x\n", @@ -388,7 +415,7 @@ static int usbasp_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, cmd[1] = address >> 8; cmd[2] = address >> 16; cmd[3] = address >> 24; - usbasp_transmit(1, USBASP_FUNC_SETLONGADDRESS, cmd, temp, sizeof(temp)); + usbasp_transmit(pgm, 1, USBASP_FUNC_SETLONGADDRESS, cmd, temp, sizeof(temp)); /* normal command - firmware what support newmode - use address from previous command, firmware what doesn't support newmode - ignore previous command and use address from this command */ @@ -399,7 +426,7 @@ static int usbasp_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, cmd[3] = (blockflags & 0x0F) + ((page_size & 0xF00) >> 4); //TP: Mega128 fix blockflags = 0; - n = usbasp_transmit(0, function, cmd, buffer, blocksize); + n = usbasp_transmit(pgm, 0, function, cmd, buffer, blocksize); if (n != blocksize) { fprintf(stderr, "%s: error: wrong count at writing %x\n", @@ -443,6 +470,8 @@ void usbasp_initpgm(PROGRAMMER * pgm) pgm->paged_write = usbasp_paged_write; pgm->paged_load = usbasp_paged_load; + pgm->setup = usbasp_setup; + pgm->teardown = usbasp_teardown; } diff --git a/usbtiny.c b/usbtiny.c index edf1322f..333453fe 100644 --- a/usbtiny.c +++ b/usbtiny.c @@ -47,18 +47,42 @@ typedef unsigned long ulong_t; extern int avr_write_byte_default ( PROGRAMMER* pgm, AVRPART* p, AVRMEM* mem, ulong_t addr, unsigned char data ); -static usb_dev_handle* usb_handle; -static int sck_period; -static int chunk_size; +/* + * Private data for this programmer. + */ +struct pdata +{ + usb_dev_handle *usb_handle; + int sck_period; + int chunk_size; +}; +#define PDATA(pgm) ((struct pdata *)(pgm->cookie)) // ---------------------------------------------------------------------- +static void usbtiny_setup(PROGRAMMER * pgm) +{ + if ((pgm->cookie = malloc(sizeof(struct pdata))) == 0) { + fprintf(stderr, + "%s: usbtiny_setup(): Out of memory allocating private data\n", + progname); + exit(1); + } + memset(pgm->cookie, 0, sizeof(struct pdata)); +} + +static void usbtiny_teardown(PROGRAMMER * pgm) +{ + free(pgm->cookie); +} + // Wrapper for simple usb_control_msg messages -static int usb_control (unsigned int requestid, unsigned int val, unsigned int index ) +static int usb_control (PROGRAMMER * pgm, + unsigned int requestid, unsigned int val, unsigned int index ) { int nbytes; - nbytes = usb_control_msg( usb_handle, + nbytes = usb_control_msg( PDATA(pgm)->usb_handle, USB_ENDPOINT_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, requestid, val, index, // 2 bytes each of data @@ -73,7 +97,8 @@ static int usb_control (unsigned int requestid, unsigned int val, unsigned int i } // Wrapper for simple usb_control_msg messages to receive data from programmer -static int usb_in (unsigned int requestid, unsigned int val, unsigned int index, +static int usb_in (PROGRAMMER * pgm, + unsigned int requestid, unsigned int val, unsigned int index, unsigned char* buffer, int buflen, int bitclk ) { int nbytes; @@ -83,7 +108,7 @@ static int usb_in (unsigned int requestid, unsigned int val, unsigned int index, // figuring the bit-clock time and buffer size and adding to the standard USB timeout. timeout = USB_TIMEOUT + (buflen * bitclk) / 1000; - nbytes = usb_control_msg( usb_handle, + nbytes = usb_control_msg( PDATA(pgm)->usb_handle, USB_ENDPOINT_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, requestid, val, index, @@ -99,8 +124,9 @@ static int usb_in (unsigned int requestid, unsigned int val, unsigned int index, } // Wrapper for simple usb_control_msg messages to send data to programmer -static int usb_out (unsigned int requestid, unsigned int val, unsigned int index, - unsigned char* buffer, int buflen, int bitclk ) +static int usb_out (PROGRAMMER * pgm, + unsigned int requestid, unsigned int val, unsigned int index, + unsigned char* buffer, int buflen, int bitclk ) { int nbytes; int timeout; @@ -109,7 +135,7 @@ static int usb_out (unsigned int requestid, unsigned int val, unsigned int index // figuring the bit-clock time and buffer size and adding to the standard USB timeout. timeout = USB_TIMEOUT + (buflen * bitclk) / 1000; - nbytes = usb_control_msg( usb_handle, + nbytes = usb_control_msg( PDATA(pgm)->usb_handle, USB_ENDPOINT_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, requestid, val, index, @@ -157,7 +183,7 @@ static int usbtiny_open(PROGRAMMER* pgm, char* name) usb_find_busses(); // have libusb scan all the usb busses available usb_find_devices(); // have libusb scan all the usb devices available - usb_handle = NULL; + PDATA(pgm)->usb_handle = NULL; // now we iterate through all the busses and devices for ( bus = usb_busses; bus; bus = bus->next ) { @@ -165,10 +191,10 @@ static int usbtiny_open(PROGRAMMER* pgm, char* name) if (dev->descriptor.idVendor == USBTINY_VENDOR && dev->descriptor.idProduct == USBTINY_PRODUCT ) { // found match? - usb_handle = usb_open(dev); // attempt to connect to device + PDATA(pgm)->usb_handle = usb_open(dev); // attempt to connect to device // wrong permissions or something? - if (!usb_handle) { + if (!PDATA(pgm)->usb_handle) { fprintf(stderr, "%s: Warning: cannot open USB device: %s\n", progname, usb_strerror()); continue; @@ -177,7 +203,7 @@ static int usbtiny_open(PROGRAMMER* pgm, char* name) } } - if (!usb_handle) { + if (!PDATA(pgm)->usb_handle) { fprintf( stderr, "%s: Error: Could not find USBtiny device (0x%x/0x%x)\n", progname, USBTINY_VENDOR, USBTINY_PRODUCT ); exit(1); @@ -189,22 +215,22 @@ static int usbtiny_open(PROGRAMMER* pgm, char* name) /* Clean up the handle for the usbtiny */ static void usbtiny_close ( PROGRAMMER* pgm ) { - if (! usb_handle) { + if (! PDATA(pgm)->usb_handle) { return; // not a valid handle, bail! } - usb_close(usb_handle); // ask libusb to clean up - usb_handle = NULL; + usb_close(PDATA(pgm)->usb_handle); // ask libusb to clean up + PDATA(pgm)->usb_handle = NULL; } /* A simple calculator function determines the maximum size of data we can shove through a USB connection without getting errors */ -static void usbtiny_set_chunk_size (int period) +static void usbtiny_set_chunk_size (PROGRAMMER * pgm, int period) { - chunk_size = CHUNK_SIZE; // start with the maximum (default) - while (chunk_size > 8 && period > 16) { + PDATA(pgm)->chunk_size = CHUNK_SIZE; // start with the maximum (default) + while (PDATA(pgm)->chunk_size > 8 && period > 16) { // Reduce the chunk size for a slow SCK to reduce // the maximum time of a single USB transfer. - chunk_size >>= 1; + PDATA(pgm)->chunk_size >>= 1; period >>= 1; } } @@ -213,23 +239,23 @@ static void usbtiny_set_chunk_size (int period) USBtiny to update itself to the new frequency */ static int usbtiny_set_sck_period (PROGRAMMER *pgm, double v) { - sck_period = (int)(v * 1e6 + 0.5); // convert from us to 'int', the 0.5 is for rounding up + PDATA(pgm)->sck_period = (int)(v * 1e6 + 0.5); // convert from us to 'int', the 0.5 is for rounding up // Make sure its not 0, as that will confuse the usbtiny - if (sck_period < SCK_MIN) - sck_period = SCK_MIN; + if (PDATA(pgm)->sck_period < SCK_MIN) + PDATA(pgm)->sck_period = SCK_MIN; // We can't go slower, due to the byte-size of the clock variable - if (sck_period > SCK_MAX) - sck_period = SCK_MAX; + if (PDATA(pgm)->sck_period > SCK_MAX) + PDATA(pgm)->sck_period = SCK_MAX; - printf( "%s: Setting SCK period to %d usec\n", progname, sck_period ); + printf( "%s: Setting SCK period to %d usec\n", progname, PDATA(pgm)->sck_period ); // send the command to the usbtiny device. - usb_control(USBTINY_POWERUP, sck_period, RESET_LOW); // MEME: for at90's fix resetstate? + usb_control(pgm, USBTINY_POWERUP, PDATA(pgm)->sck_period, RESET_LOW); // MEME: for at90's fix resetstate? // with the new speed, we'll have to update how much data we send per usb transfer - usbtiny_set_chunk_size(sck_period); + usbtiny_set_chunk_size(pgm, PDATA(pgm)->sck_period); return 0; } @@ -244,13 +270,13 @@ static int usbtiny_initialize (PROGRAMMER *pgm, AVRPART *p ) usbtiny_set_sck_period(pgm, pgm->bitclock); } else { // -B option not specified: use default - sck_period = SCK_DEFAULT; + PDATA(pgm)->sck_period = SCK_DEFAULT; if (verbose) { printf( "%s: Using SCK period of %d usec\n", - progname, sck_period ); + progname, PDATA(pgm)->sck_period ); } - usb_control( USBTINY_POWERUP, sck_period, RESET_LOW ); - usbtiny_set_chunk_size(sck_period); + usb_control(pgm, USBTINY_POWERUP, PDATA(pgm)->sck_period, RESET_LOW ); + usbtiny_set_chunk_size(pgm, PDATA(pgm)->sck_period); } // Let the device wake up. @@ -259,8 +285,8 @@ static int usbtiny_initialize (PROGRAMMER *pgm, AVRPART *p ) // Attempt to use the underlying avrdude methods to connect (MEME: is this kosher?) if (! usbtiny_avr_op(pgm, p, AVR_OP_PGM_ENABLE, res)) { // no response, RESET and try again - usb_control(USBTINY_POWERUP, sck_period, RESET_HIGH); - usb_control(USBTINY_POWERUP, sck_period, RESET_LOW); + usb_control(pgm, USBTINY_POWERUP, PDATA(pgm)->sck_period, RESET_HIGH); + usb_control(pgm, USBTINY_POWERUP, PDATA(pgm)->sck_period, RESET_LOW); usleep(50000); if ( ! usbtiny_avr_op( pgm, p, AVR_OP_PGM_ENABLE, res)) { // give up @@ -273,10 +299,10 @@ static int usbtiny_initialize (PROGRAMMER *pgm, AVRPART *p ) /* Tell the USBtiny to release the output pins, etc */ static void usbtiny_powerdown(PROGRAMMER * pgm) { - if (!usb_handle) { + if (!PDATA(pgm)->usb_handle) { return; // wasn't connected in the first place } - usb_control(USBTINY_POWERDOWN, 0, 0); // Send USB control command to device + usb_control(pgm, USBTINY_POWERDOWN, 0, 0); // Send USB control command to device } /* Send a 4-byte SPI command to the USBtinyISP for execution @@ -288,10 +314,10 @@ static int usbtiny_cmd(PROGRAMMER * pgm, unsigned char cmd[4], unsigned char res // Make sure its empty so we don't read previous calls if it fails memset(res, '\0', sizeof(res) ); - nbytes = usb_in( USBTINY_SPI, + nbytes = usb_in( pgm, USBTINY_SPI, (cmd[1] << 8) | cmd[0], // convert to 16-bit words (cmd[3] << 8) | cmd[2], // " - res, sizeof(res), 8 * sck_period ); + res, sizeof(res), 8 * PDATA(pgm)->sck_period ); if (verbose > 1) { // print out the data we sent and received printf( "CMD: [%02x %02x %02x %02x] [%02x %02x %02x %02x]\n", @@ -352,7 +378,7 @@ static int usbtiny_paged_load (PROGRAMMER * pgm, AVRPART * p, AVRMEM* m, } for (i = 0; i < n_bytes; i += chunk) { - chunk = chunk_size; // start with the maximum chunk size possible + chunk = PDATA(pgm)->chunk_size; // start with the maximum chunk size possible // If we want to xmit less than a chunk, thats OK if (chunk > n_bytes-i) @@ -360,12 +386,13 @@ static int usbtiny_paged_load (PROGRAMMER * pgm, AVRPART * p, AVRMEM* m, // Send the chunk of data to the USBtiny with the function we want // to perform - usb_in(function, // EEPROM or flash + usb_in(pgm, + function, // EEPROM or flash 0, // delay between SPI commands i, // index m->buf + i, // pointer to where we store data chunk, // number of bytes - 32 * sck_period); // each byte gets turned into a 4-byte SPI cmd + 32 * PDATA(pgm)->sck_period); // each byte gets turned into a 4-byte SPI cmd // usb_in() multiplies this per byte. // Tell avrdude how we're doing to provide user feedback @@ -400,13 +427,13 @@ static int usbtiny_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, if (! m->paged) { // Does this chip not support paged writes? i = (m->readback[1] << 8) | m->readback[0]; - usb_control( USBTINY_POLL_BYTES, i, 0 ); + usb_control(pgm, USBTINY_POLL_BYTES, i, 0 ); delay = m->max_write_delay; } for (i=0; i < n_bytes; i=next) { // start with the max chunk size - chunk = chunk_size; + chunk = PDATA(pgm)->chunk_size; // we can only write a page at a time anyways if (m->paged && chunk > page_size) @@ -416,12 +443,13 @@ static int usbtiny_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, if (chunk > n_bytes-i) chunk = n_bytes - i; - usb_out(function, // Flash or EEPROM + usb_out(pgm, + function, // Flash or EEPROM delay, // How much to wait between each byte i, // Index of data m->buf + i, // Pointer to data chunk, // Number of bytes to write - 32 * sck_period + delay // each byte gets turned into a + 32 * PDATA(pgm)->sck_period + delay // each byte gets turned into a // 4-byte SPI cmd usb_in() multiplies // this per byte. Then add the cmd-delay ); @@ -460,6 +488,8 @@ extern void usbtiny_initpgm ( PROGRAMMER* pgm ) pgm->paged_load = usbtiny_paged_load; pgm->paged_write = usbtiny_paged_write; pgm->set_sck_period = usbtiny_set_sck_period; + pgm->setup = usbtiny_setup; + pgm->teardown = usbtiny_teardown; } #else /* !HAVE_LIBUSB */