main.c, pgm.c, pgm.h: 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.

avr910.c, butterfly.c, jtagmkI.c, jtagmkII.c, stk500v2.c, usbasp.c,
usbtiny.c: Convert static programmer data into dynamically allocated
data.


git-svn-id: svn://svn.savannah.nongnu.org/avrdude/trunk/avrdude@764 81a1dc3b-b13d-400b-aceb-764788c761c2
This commit is contained in:
joerg_wunsch 2007-11-07 20:36:12 +00:00
parent 2b6a3f7614
commit 7d70684811
11 changed files with 486 additions and 237 deletions

View File

@ -1,3 +1,22 @@
2007-11-07 Joerg Wunsch <j@uriah.heep.sax.de>
* 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 <j@uriah.heep.sax.de> 2007-11-06 Joerg Wunsch <j@uriah.heep.sax.de>
* butterfly.c: Remove the no_show_func_info() calls, as Brian * butterfly.c: Remove the no_show_func_info() calls, as Brian

View File

@ -1,6 +1,7 @@
/* /*
* avrdude - A Downloader/Uploader for AVR device programmers * avrdude - A Downloader/Uploader for AVR device programmers
* Copyright (C) 2003-2004 Theodore A. Roth <troth@openavr.org> * Copyright (C) 2003-2004 Theodore A. Roth <troth@openavr.org>
* Copyright 2007 Joerg Wunsch <j@uriah.heep.sax.de>
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -40,7 +41,31 @@
#include "avr910.h" #include "avr910.h"
#include "serial.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) 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. */ /* See if programmer supports autoincrement of address. */
avr910_send(pgm, "a", 1); avr910_send(pgm, "a", 1);
avr910_recv(pgm, &has_auto_incr_addr, 1); avr910_recv(pgm, &PDATA(pgm)->has_auto_incr_addr, 1);
if (has_auto_incr_addr == 'Y') if (PDATA(pgm)->has_auto_incr_addr == 'Y')
fprintf(stderr, "Programmer supports auto addr increment.\n"); fprintf(stderr, "Programmer supports auto addr increment.\n");
/* Get list of devices that the programmer supports. */ /* 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_addr = addr;
page_bytes = page_size; 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); avr910_set_addr(pgm, addr>>1);
} }
@ -482,7 +507,7 @@ static int avr910_paged_write_eeprom(PROGRAMMER * pgm, AVRPART * p,
addr++; addr++;
if (has_auto_incr_addr != 'Y') { if (PDATA(pgm)->has_auto_incr_addr != 'Y') {
avr910_set_addr(pgm, addr); avr910_set_addr(pgm, addr);
} }
@ -548,7 +573,7 @@ static int avr910_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
addr++; addr++;
if (has_auto_incr_addr != 'Y') { if (PDATA(pgm)->has_auto_incr_addr != 'Y') {
avr910_set_addr(pgm, addr); avr910_set_addr(pgm, addr);
} }
@ -608,4 +633,7 @@ void avr910_initpgm(PROGRAMMER * pgm)
pgm->paged_load = avr910_paged_load; pgm->paged_load = avr910_paged_load;
pgm->read_sig_bytes = avr910_read_sig_bytes; pgm->read_sig_bytes = avr910_read_sig_bytes;
pgm->setup = avr910_setup;
pgm->teardown = avr910_teardown;
} }

View File

@ -1,7 +1,7 @@
/* /*
* avrdude - A Downloader/Uploader for AVR device programmers * avrdude - A Downloader/Uploader for AVR device programmers
* Copyright (C) 2003-2004 Theodore A. Roth <troth@openavr.org> * Copyright (C) 2003-2004 Theodore A. Roth <troth@openavr.org>
* Copyright (C) 2005 Joerg Wunsch <j@uriah.heep.sax.de> * Copyright (C) 2005, 2007 Joerg Wunsch <j@uriah.heep.sax.de>
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -50,8 +50,32 @@
#include "butterfly.h" #include "butterfly.h"
#include "serial.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) 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. */ /* See if programmer supports autoincrement of address. */
butterfly_send(pgm, "a", 1); butterfly_send(pgm, "a", 1);
butterfly_recv(pgm, &has_auto_incr_addr, 1); butterfly_recv(pgm, &PDATA(pgm)->has_auto_incr_addr, 1);
if (has_auto_incr_addr == 'Y') if (PDATA(pgm)->has_auto_incr_addr == 'Y')
fprintf(stderr, "Programmer supports auto addr increment.\n"); fprintf(stderr, "Programmer supports auto addr increment.\n");
/* Check support for buffered memory access, abort if not available */ /* Check support for buffered memory access, abort if not available */
@ -260,12 +284,12 @@ static int butterfly_initialize(PROGRAMMER * pgm, AVRPART * p)
exit(1); exit(1);
}; };
butterfly_recv(pgm, &c, 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); butterfly_recv(pgm, &c, 1);
buffersize += (unsigned int)(unsigned char)c; PDATA(pgm)->buffersize += (unsigned int)(unsigned char)c;
fprintf(stderr, fprintf(stderr,
"Programmer supports buffered memory access with buffersize=%i bytes.\n", "Programmer supports buffered memory access with buffersize=%i bytes.\n",
buffersize); PDATA(pgm)->buffersize);
/* Get list of devices that the programmer supports. */ /* 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 addr = 0;
unsigned int max_addr = n_bytes; unsigned int max_addr = n_bytes;
char *cmd; char *cmd;
unsigned int blocksize = buffersize; unsigned int blocksize = PDATA(pgm)->buffersize;
int use_ext_addr = m->op[AVR_OP_LOAD_EXT_ADDR] != NULL; int use_ext_addr = m->op[AVR_OP_LOAD_EXT_ADDR] != NULL;
if (strcmp(m->desc, "flash") && strcmp(m->desc, "eeprom")) 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 */ { /* use buffered mode */
char cmd[4]; char cmd[4];
int blocksize = buffersize; int blocksize = PDATA(pgm)->buffersize;
cmd[0] = 'g'; cmd[0] = 'g';
cmd[3] = toupper(m->desc[0]); cmd[3] = toupper(m->desc[0]);
@ -664,4 +688,7 @@ void butterfly_initpgm(PROGRAMMER * pgm)
pgm->paged_load = butterfly_paged_load; pgm->paged_load = butterfly_paged_load;
pgm->read_sig_bytes = butterfly_read_sig_bytes; pgm->read_sig_bytes = butterfly_read_sig_bytes;
pgm->setup = butterfly_setup;
pgm->teardown = butterfly_teardown;
} }

130
jtagmkI.c
View File

@ -1,6 +1,6 @@
/* /*
* avrdude - A Downloader/Uploader for AVR device programmers * avrdude - A Downloader/Uploader for AVR device programmers
* Copyright (C) 2005 Joerg Wunsch <j@uriah.heep.sax.de> * Copyright (C) 2005, 2007 Joerg Wunsch <j@uriah.heep.sax.de>
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -41,24 +41,29 @@
#include "serial.h" #include "serial.h"
/* /*
* XXX There should really be a programmer-specific private data * Private data for this programmer.
* pointer in struct PROGRAMMER.
*/ */
static int initial_baudrate; struct pdata
{
int initial_baudrate;
/* /*
* See jtagmkI_read_byte() for an explanation of the flash and * See jtagmkI_read_byte() for an explanation of the flash and
* EEPROM page caches. * EEPROM page caches.
*/ */
static unsigned char *flash_pagecache; unsigned char *flash_pagecache;
static unsigned long flash_pageaddr; unsigned long flash_pageaddr;
static unsigned int flash_pagesize; unsigned int flash_pagesize;
static unsigned char *eeprom_pagecache; unsigned char *eeprom_pagecache;
static unsigned long eeprom_pageaddr; unsigned long eeprom_pageaddr;
static unsigned int eeprom_pagesize; 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 * The OCDEN fuse is bit 7 of the high fuse (hfuse). In order to
* perform memory operations on MTYPE_SPM and MTYPE_EEPROM, OCDEN * 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 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 static void
u32_to_b3(unsigned char *b, unsigned long l) 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)) { for (ln = lfirst(p->mem); ln; ln = lnext(ln)) {
m = ldata(ln); m = ldata(ln);
if (strcmp(m->desc, "flash") == 0) { if (strcmp(m->desc, "flash") == 0) {
flash_pagesize = m->page_size; PDATA(pgm)->flash_pagesize = m->page_size;
u16_to_b2(sendbuf.dd.uiFlashPageSize, flash_pagesize); u16_to_b2(sendbuf.dd.uiFlashPageSize, PDATA(pgm)->flash_pagesize);
} else if (strcmp(m->desc, "eeprom") == 0) { } 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]; unsigned char buf[1], resp[2];
if (prog_enabled) if (PDATA(pgm)->prog_enabled)
return 0; return 0;
buf[0] = CMD_ENTER_PROGMODE; buf[0] = CMD_ENTER_PROGMODE;
@ -472,7 +494,7 @@ static int jtagmkI_program_enable(PROGRAMMER * pgm)
fprintf(stderr, "OK\n"); fprintf(stderr, "OK\n");
} }
prog_enabled = 1; PDATA(pgm)->prog_enabled = 1;
return 0; return 0;
} }
@ -481,7 +503,7 @@ static int jtagmkI_program_disable(PROGRAMMER * pgm)
{ {
unsigned char buf[1], resp[2]; unsigned char buf[1], resp[2];
if (!prog_enabled) if (!PDATA(pgm)->prog_enabled)
return 0; return 0;
if (pgm->fd.ifd != -1) { if (pgm->fd.ifd != -1) {
@ -506,7 +528,7 @@ static int jtagmkI_program_disable(PROGRAMMER * pgm)
fprintf(stderr, "OK\n"); fprintf(stderr, "OK\n");
} }
} }
prog_enabled = 0; PDATA(pgm)->prog_enabled = 0;
return 0; return 0;
} }
@ -539,7 +561,7 @@ static int jtagmkI_initialize(PROGRAMMER * pgm, AVRPART * p)
jtagmkI_drain(pgm, 0); 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) { if ((b = jtagmkI_get_baud(pgm->baudrate)) == 0) {
fprintf(stderr, "%s: jtagmkI_initialize(): unsupported baudrate %d\n", fprintf(stderr, "%s: jtagmkI_initialize(): unsupported baudrate %d\n",
progname, pgm->baudrate); progname, pgm->baudrate);
@ -549,7 +571,7 @@ static int jtagmkI_initialize(PROGRAMMER * pgm, AVRPART * p)
"trying to set baudrate to %d\n", "trying to set baudrate to %d\n",
progname, pgm->baudrate); progname, pgm->baudrate);
if (jtagmkI_setparm(pgm, PARM_BITRATE, b) == 0) { 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); serial_setspeed(&pgm->fd, pgm->baudrate);
} }
} }
@ -584,24 +606,24 @@ static int jtagmkI_initialize(PROGRAMMER * pgm, AVRPART * p)
*/ */
jtagmkI_set_devdescr(pgm, p); jtagmkI_set_devdescr(pgm, p);
jtagmkI_setparm(pgm, PARM_FLASH_PAGESIZE_LOW, flash_pagesize & 0xff); jtagmkI_setparm(pgm, PARM_FLASH_PAGESIZE_LOW, PDATA(pgm)->flash_pagesize & 0xff);
jtagmkI_setparm(pgm, PARM_FLASH_PAGESIZE_HIGH, flash_pagesize >> 8); jtagmkI_setparm(pgm, PARM_FLASH_PAGESIZE_HIGH, PDATA(pgm)->flash_pagesize >> 8);
jtagmkI_setparm(pgm, PARM_EEPROM_PAGESIZE, eeprom_pagesize & 0xff); jtagmkI_setparm(pgm, PARM_EEPROM_PAGESIZE, PDATA(pgm)->eeprom_pagesize & 0xff);
free(flash_pagecache); free(PDATA(pgm)->flash_pagecache);
free(eeprom_pagecache); free(PDATA(pgm)->eeprom_pagecache);
if ((flash_pagecache = malloc(flash_pagesize)) == NULL) { if ((PDATA(pgm)->flash_pagecache = malloc(PDATA(pgm)->flash_pagesize)) == NULL) {
fprintf(stderr, "%s: jtagmkI_initialize(): Out of memory\n", fprintf(stderr, "%s: jtagmkI_initialize(): Out of memory\n",
progname); progname);
return -1; 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", fprintf(stderr, "%s: jtagmkI_initialize(): Out of memory\n",
progname); progname);
free(flash_pagecache); free(PDATA(pgm)->flash_pagecache);
return -1; 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) if (jtagmkI_reset(pgm) < 0)
return -1; return -1;
@ -622,10 +644,10 @@ static int jtagmkI_initialize(PROGRAMMER * pgm, AVRPART * p)
static void jtagmkI_disable(PROGRAMMER * pgm) static void jtagmkI_disable(PROGRAMMER * pgm)
{ {
free(flash_pagecache); free(PDATA(pgm)->flash_pagecache);
flash_pagecache = NULL; PDATA(pgm)->flash_pagecache = NULL;
free(eeprom_pagecache); free(PDATA(pgm)->eeprom_pagecache);
eeprom_pagecache = NULL; PDATA(pgm)->eeprom_pagecache = NULL;
(void)jtagmkI_program_disable(pgm); (void)jtagmkI_program_disable(pgm);
} }
@ -644,7 +666,7 @@ static int jtagmkI_open(PROGRAMMER * pgm, char * port)
fprintf(stderr, "%s: jtagmkI_open()\n", progname); fprintf(stderr, "%s: jtagmkI_open()\n", progname);
strcpy(pgm->port, port); strcpy(pgm->port, port);
initial_baudrate = -1L; PDATA(pgm)->initial_baudrate = -1L;
for (i = 0; i < sizeof(baudtab) / sizeof(baudtab[0]); i++) { for (i = 0; i < sizeof(baudtab) / sizeof(baudtab[0]); i++) {
if (verbose >= 2) if (verbose >= 2)
@ -659,7 +681,7 @@ static int jtagmkI_open(PROGRAMMER * pgm, char * port)
jtagmkI_drain(pgm, 0); jtagmkI_drain(pgm, 0);
if (jtagmkI_getsync(pgm) == 0) { if (jtagmkI_getsync(pgm) == 0) {
initial_baudrate = baudtab[i].baud; PDATA(pgm)->initial_baudrate = baudtab[i].baud;
if (verbose >= 2) if (verbose >= 2)
fprintf(stderr, "%s: jtagmkI_open(): succeeded\n", progname); fprintf(stderr, "%s: jtagmkI_open(): succeeded\n", progname);
return 0; 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 * appears to make AVR Studio happier when it is about to access the
* ICE later on. * ICE later on.
*/ */
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(initial_baudrate)) == 0) { if ((b = jtagmkI_get_baud(PDATA(pgm)->initial_baudrate)) == 0) {
fprintf(stderr, "%s: jtagmkI_close(): unsupported baudrate %d\n", fprintf(stderr, "%s: jtagmkI_close(): unsupported baudrate %d\n",
progname, initial_baudrate); progname, PDATA(pgm)->initial_baudrate);
} else { } else {
if (verbose >= 2) if (verbose >= 2)
fprintf(stderr, "%s: jtagmkI_close(): " fprintf(stderr, "%s: jtagmkI_close(): "
"trying to set baudrate to %d\n", "trying to set baudrate to %d\n",
progname, initial_baudrate); progname, PDATA(pgm)->initial_baudrate);
if (jtagmkI_setparm(pgm, PARM_BITRATE, b) == 0) { if (jtagmkI_setparm(pgm, PARM_BITRATE, b) == 0) {
serial_setspeed(&pgm->fd, pgm->baudrate); 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; cmd[0] = CMD_WRITE_MEM;
if (strcmp(m->desc, "flash") == 0) { if (strcmp(m->desc, "flash") == 0) {
cmd[1] = MTYPE_FLASH_PAGE; cmd[1] = MTYPE_FLASH_PAGE;
flash_pageaddr = (unsigned long)-1L; PDATA(pgm)->flash_pageaddr = (unsigned long)-1L;
page_size = flash_pagesize; page_size = PDATA(pgm)->flash_pagesize;
is_flash = 1; is_flash = 1;
} else if (strcmp(m->desc, "eeprom") == 0) { } else if (strcmp(m->desc, "eeprom") == 0) {
cmd[1] = MTYPE_EEPROM_PAGE; cmd[1] = MTYPE_EEPROM_PAGE;
eeprom_pageaddr = (unsigned long)-1L; PDATA(pgm)->eeprom_pageaddr = (unsigned long)-1L;
page_size = eeprom_pagesize; page_size = PDATA(pgm)->eeprom_pagesize;
} }
datacmd[0] = CMD_DATA; datacmd[0] = CMD_DATA;
@ -968,15 +990,15 @@ static int jtagmkI_read_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
cmd[1] = MTYPE_FLASH_PAGE; cmd[1] = MTYPE_FLASH_PAGE;
pagesize = mem->page_size; pagesize = mem->page_size;
paddr = addr & ~(pagesize - 1); paddr = addr & ~(pagesize - 1);
paddr_ptr = &flash_pageaddr; paddr_ptr = &PDATA(pgm)->flash_pageaddr;
cache_ptr = flash_pagecache; cache_ptr = PDATA(pgm)->flash_pagecache;
is_flash = 1; is_flash = 1;
} else if (strcmp(mem->desc, "eeprom") == 0) { } else if (strcmp(mem->desc, "eeprom") == 0) {
cmd[1] = MTYPE_EEPROM_PAGE; cmd[1] = MTYPE_EEPROM_PAGE;
pagesize = mem->page_size; pagesize = mem->page_size;
paddr = addr & ~(pagesize - 1); paddr = addr & ~(pagesize - 1);
paddr_ptr = &eeprom_pageaddr; paddr_ptr = &PDATA(pgm)->eeprom_pageaddr;
cache_ptr = eeprom_pagecache; cache_ptr = PDATA(pgm)->eeprom_pagecache;
} else if (strcmp(mem->desc, "lfuse") == 0) { } else if (strcmp(mem->desc, "lfuse") == 0) {
cmd[1] = MTYPE_FUSE_BITS; cmd[1] = MTYPE_FUSE_BITS;
addr = 0; addr = 0;
@ -1078,11 +1100,11 @@ static int jtagmkI_write_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
if (strcmp(mem->desc, "flash") == 0) { if (strcmp(mem->desc, "flash") == 0) {
cmd[1] = MTYPE_SPM; cmd[1] = MTYPE_SPM;
need_progmode = 0; need_progmode = 0;
flash_pageaddr = (unsigned long)-1L; PDATA(pgm)->flash_pageaddr = (unsigned long)-1L;
} else if (strcmp(mem->desc, "eeprom") == 0) { } else if (strcmp(mem->desc, "eeprom") == 0) {
cmd[1] = MTYPE_EEPROM; cmd[1] = MTYPE_EEPROM;
need_progmode = 0; need_progmode = 0;
eeprom_pageaddr = (unsigned long)-1L; PDATA(pgm)->eeprom_pageaddr = (unsigned long)-1L;
} else if (strcmp(mem->desc, "lfuse") == 0) { } else if (strcmp(mem->desc, "lfuse") == 0) {
cmd[1] = MTYPE_FUSE_BITS; cmd[1] = MTYPE_FUSE_BITS;
addr = 0; addr = 0;
@ -1374,5 +1396,7 @@ void jtagmkI_initpgm(PROGRAMMER * pgm)
pgm->paged_load = jtagmkI_paged_load; pgm->paged_load = jtagmkI_paged_load;
pgm->print_parms = jtagmkI_print_parms; pgm->print_parms = jtagmkI_print_parms;
pgm->set_sck_period = jtagmkI_set_sck_period; pgm->set_sck_period = jtagmkI_set_sck_period;
pgm->setup = jtagmkI_setup;
pgm->teardown = jtagmkI_teardown;
pgm->page_size = 256; pgm->page_size = 256;
} }

View File

@ -1,6 +1,6 @@
/* /*
* avrdude - A Downloader/Uploader for AVR device programmers * avrdude - A Downloader/Uploader for AVR device programmers
* Copyright (C) 2005,2006 Joerg Wunsch <j@uriah.heep.sax.de> * Copyright (C) 2005-2007 Joerg Wunsch <j@uriah.heep.sax.de>
* *
* Derived from stk500 code which is: * Derived from stk500 code which is:
* Copyright (C) 2002-2004 Brian S. Dean <bsd@bsdhome.com> * Copyright (C) 2002-2004 Brian S. Dean <bsd@bsdhome.com>
@ -52,28 +52,35 @@
/* /*
* XXX There should really be a programmer-specific private data * Private data for this programmer.
* pointer in struct 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 * See jtagmkII_read_byte() for an explanation of the flash and
* EEPROM page caches. * EEPROM page caches.
*/ */
static unsigned char *flash_pagecache; unsigned char *flash_pagecache;
static unsigned long flash_pageaddr; unsigned long flash_pageaddr;
static unsigned int flash_pagesize; unsigned int flash_pagesize;
static unsigned char *eeprom_pagecache; unsigned char *eeprom_pagecache;
static unsigned long eeprom_pageaddr; unsigned long eeprom_pageaddr;
static unsigned int eeprom_pagesize; unsigned int eeprom_pagesize;
static int prog_enabled; /* Cached value of PROGRAMMING status. */ int prog_enabled; /* Cached value of PROGRAMMING status. */
static unsigned char serno[6]; /* JTAG ICE serial number. */ unsigned char serno[6]; /* JTAG ICE serial number. */
/* JTAG chain stuff */ /* JTAG chain stuff */
static unsigned char jtagchain[4]; 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 * 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) #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, static int jtagmkII_read_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
unsigned long addr, unsigned char * value); unsigned long addr, unsigned char * value);
static int jtagmkII_write_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem, 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); unsigned char * value);
static void jtagmkII_print_parms1(PROGRAMMER * pgm, char * p); 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 static unsigned long
b4_to_u32(unsigned char *b) 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; 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); u32_to_b4(buf + 3, len);
buf[7] = TOKEN; buf[7] = TOKEN;
memcpy(buf + 8, data, len); memcpy(buf + 8, data, len);
@ -549,10 +570,10 @@ int jtagmkII_recv(PROGRAMMER * pgm, unsigned char **msg) {
if (verbose >= 3) if (verbose >= 3)
fprintf(stderr, "%s: jtagmkII_recv(): " fprintf(stderr, "%s: jtagmkII_recv(): "
"Got message seqno %d (command_sequence == %d)\n", "Got message seqno %d (command_sequence == %d)\n",
progname, r_seqno, command_sequence); progname, r_seqno, PDATA(pgm)->command_sequence);
if (r_seqno == command_sequence) { if (r_seqno == PDATA(pgm)->command_sequence) {
if (++command_sequence == 0xffff) if (++(PDATA(pgm)->command_sequence) == 0xffff)
command_sequence = 0; PDATA(pgm)->command_sequence = 0;
/* /*
* We move the payload to the beginning of the buffer, to make * We move the payload to the beginning of the buffer, to make
* the job easier for the caller. We have to return the * 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) if (verbose >= 2)
fprintf(stderr, "%s: jtagmkII_recv(): " fprintf(stderr, "%s: jtagmkII_recv(): "
"got wrong sequence number, %u != %u\n", "got wrong sequence number, %u != %u\n",
progname, r_seqno, command_sequence); progname, r_seqno, PDATA(pgm)->command_sequence);
} }
free(*msg); free(*msg);
} }
@ -611,7 +632,7 @@ int jtagmkII_getsync(PROGRAMMER * pgm, int mode) {
if ((c = resp[0]) == RSP_SIGN_ON) { if ((c = resp[0]) == RSP_SIGN_ON) {
fwver = ((unsigned)resp[8] << 8) | (unsigned)resp[7]; fwver = ((unsigned)resp[8] << 8) | (unsigned)resp[7];
hwver = (unsigned)resp[9]; hwver = (unsigned)resp[9];
memcpy(serno, resp + 10, 6); memcpy(PDATA(pgm)->serno, resp + 10, 6);
if (verbose >= 1 && status > 17) { if (verbose >= 1 && status > 17) {
fprintf(stderr, "JTAG ICE mkII sign-on message:\n"); fprintf(stderr, "JTAG ICE mkII sign-on message:\n");
fprintf(stderr, "Communications protocol version: %u\n", fprintf(stderr, "Communications protocol version: %u\n",
@ -632,7 +653,7 @@ int jtagmkII_getsync(PROGRAMMER * pgm, int mode) {
(unsigned)resp[9]); (unsigned)resp[9]);
fprintf(stderr, "Serial number: " fprintf(stderr, "Serial number: "
"%02x:%02x:%02x:%02x:%02x:%02x\n", "%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'; resp[status - 1] = '\0';
fprintf(stderr, "Device ID: %s\n", fprintf(stderr, "Device ID: %s\n",
resp + 16); resp + 16);
@ -656,7 +677,7 @@ int jtagmkII_getsync(PROGRAMMER * pgm, int mode) {
return -1; 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 * There's no official documentation from Atmel about what firmware
* revision matches what device descriptor length. The algorithm * 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)) #define FWVER(maj, min) ((maj << 8) | (min))
if (hwver == 0 && fwver < FWVER(3, 16)) { if (hwver == 0 && fwver < FWVER(3, 16)) {
device_descriptor_length -= 2; PDATA(pgm)->device_descriptor_length -= 2;
fprintf(stderr, fprintf(stderr,
"%s: jtagmkII_getsync(): " "%s: jtagmkII_getsync(): "
"S_MCU firmware version might be too old to work correctly\n", "S_MCU firmware version might be too old to work correctly\n",
progname); progname);
} else if (hwver == 0 && fwver < FWVER(4, 0)) { } 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) if (verbose >= 2 && mode != EMULATOR_MODE_SPI)
fprintf(stderr, fprintf(stderr,
"%s: jtagmkII_getsync(): Using a %zu-byte device descriptor\n", "%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) { 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)) { if (hwver == 0 && fwver < FWVER(4, 14)) {
fprintf(stderr, fprintf(stderr,
"%s: jtagmkII_getsync(): ISP functionality requires firmware " "%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)) { for (ln = lfirst(p->mem); ln; ln = lnext(ln)) {
m = ldata(ln); m = ldata(ln);
if (strcmp(m->desc, "flash") == 0) { 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); u32_to_b4(sendbuf.dd.ulFlashSize, m->size);
u16_to_b2(sendbuf.dd.uiFlashPageSize, flash_pagesize); u16_to_b2(sendbuf.dd.uiFlashPageSize, PDATA(pgm)->flash_pagesize);
u16_to_b2(sendbuf.dd.uiFlashpages, m->size / flash_pagesize); u16_to_b2(sendbuf.dd.uiFlashpages, m->size / PDATA(pgm)->flash_pagesize);
if (p->flags & AVRPART_HAS_DW) { if (p->flags & AVRPART_HAS_DW) {
memcpy(sendbuf.dd.ucFlashInst, p->flash_instr, FLASH_INSTR_SIZE); memcpy(sendbuf.dd.ucFlashInst, p->flash_instr, FLASH_INSTR_SIZE);
memcpy(sendbuf.dd.ucEepromInst, p->eeprom_instr, EEPROM_INSTR_SIZE); memcpy(sendbuf.dd.ucEepromInst, p->eeprom_instr, EEPROM_INSTR_SIZE);
} }
} else if (strcmp(m->desc, "eeprom") == 0) { } 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: ", "Sending set device descriptor command: ",
progname); progname);
jtagmkII_send(pgm, (unsigned char *)&sendbuf, 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); status = jtagmkII_recv(pgm, &resp);
if (status <= 0) { if (status <= 0) {
@ -952,7 +973,7 @@ static int jtagmkII_program_enable(PROGRAMMER * pgm)
int status; int status;
unsigned char buf[1], *resp, c; unsigned char buf[1], *resp, c;
if (prog_enabled) if (PDATA(pgm)->prog_enabled)
return 0; return 0;
buf[0] = CMND_ENTER_PROGMODE; buf[0] = CMND_ENTER_PROGMODE;
@ -989,7 +1010,7 @@ static int jtagmkII_program_enable(PROGRAMMER * pgm)
return -1; return -1;
} }
prog_enabled = 1; PDATA(pgm)->prog_enabled = 1;
return 0; return 0;
} }
@ -998,7 +1019,7 @@ static int jtagmkII_program_disable(PROGRAMMER * pgm)
int status; int status;
unsigned char buf[1], *resp, c; unsigned char buf[1], *resp, c;
if (!prog_enabled) if (!PDATA(pgm)->prog_enabled)
return 0; return 0;
buf[0] = CMND_LEAVE_PROGMODE; buf[0] = CMND_LEAVE_PROGMODE;
@ -1033,7 +1054,7 @@ static int jtagmkII_program_disable(PROGRAMMER * pgm)
return -1; return -1;
} }
prog_enabled = 0; PDATA(pgm)->prog_enabled = 0;
(void)jtagmkII_reset(pgm, 0x01); (void)jtagmkII_reset(pgm, 0x01);
return 0; return 0;
@ -1112,7 +1133,7 @@ static int jtagmkII_initialize(PROGRAMMER * pgm, AVRPART * p)
return -1; 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", fprintf(stderr, "%s: jtagmkII_initialize(): Failed to setup JTAG chain\n",
progname); progname);
return -1; return -1;
@ -1123,20 +1144,20 @@ static int jtagmkII_initialize(PROGRAMMER * pgm, AVRPART * p)
*/ */
jtagmkII_set_devdescr(pgm, p); jtagmkII_set_devdescr(pgm, p);
free(flash_pagecache); free(PDATA(pgm)->flash_pagecache);
free(eeprom_pagecache); free(PDATA(pgm)->eeprom_pagecache);
if ((flash_pagecache = malloc(flash_pagesize)) == NULL) { if ((PDATA(pgm)->flash_pagecache = malloc(PDATA(pgm)->flash_pagesize)) == NULL) {
fprintf(stderr, "%s: jtagmkII_initialize(): Out of memory\n", fprintf(stderr, "%s: jtagmkII_initialize(): Out of memory\n",
progname); progname);
return -1; 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", fprintf(stderr, "%s: jtagmkII_initialize(): Out of memory\n",
progname); progname);
free(flash_pagecache); free(PDATA(pgm)->flash_pagecache);
return -1; 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) if (jtagmkII_reset(pgm, 0x01) < 0)
return -1; return -1;
@ -1159,10 +1180,10 @@ static int jtagmkII_initialize(PROGRAMMER * pgm, AVRPART * p)
static void jtagmkII_disable(PROGRAMMER * pgm) static void jtagmkII_disable(PROGRAMMER * pgm)
{ {
free(flash_pagecache); free(PDATA(pgm)->flash_pagecache);
flash_pagecache = NULL; PDATA(pgm)->flash_pagecache = NULL;
free(eeprom_pagecache); free(PDATA(pgm)->eeprom_pagecache);
eeprom_pagecache = NULL; PDATA(pgm)->eeprom_pagecache = NULL;
if (!(pgm->flag & PGM_FL_IS_DW)) if (!(pgm->flag & PGM_FL_IS_DW))
(void)jtagmkII_program_disable(pgm); (void)jtagmkII_program_disable(pgm);
@ -1199,10 +1220,10 @@ static int jtagmkII_parseextparms(PROGRAMMER * pgm, LISTID extparms)
progname, progname,
progbuf, ub, ua, bb, ba); progbuf, ub, ua, bb, ba);
} }
jtagchain[0] = ub; PDATA(pgm)->jtagchain[0] = ub;
jtagchain[1] = ua; PDATA(pgm)->jtagchain[1] = ua;
jtagchain[2] = bb; PDATA(pgm)->jtagchain[2] = bb;
jtagchain[3] = ba; PDATA(pgm)->jtagchain[3] = ba;
continue; continue;
} }
@ -1405,7 +1426,7 @@ void jtagmkII_close(PROGRAMMER * pgm)
if (verbose >= 2) if (verbose >= 2)
fprintf(stderr, "%s: jtagmkII_close()\n", progname); fprintf(stderr, "%s: jtagmkII_close()\n", progname);
if (device_descriptor_length) { if (PDATA(pgm)->device_descriptor_length) {
/* When in JTAG mode, restart target. */ /* When in JTAG mode, restart target. */
buf[0] = CMND_GO; buf[0] = CMND_GO;
if (verbose >= 2) if (verbose >= 2)
@ -1500,12 +1521,12 @@ static int jtagmkII_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
cmd[0] = CMND_WRITE_MEMORY; cmd[0] = CMND_WRITE_MEMORY;
if (strcmp(m->desc, "flash") == 0) { if (strcmp(m->desc, "flash") == 0) {
cmd[1] = MTYPE_FLASH_PAGE; cmd[1] = MTYPE_FLASH_PAGE;
flash_pageaddr = (unsigned long)-1L; PDATA(pgm)->flash_pageaddr = (unsigned long)-1L;
page_size = flash_pagesize; page_size = PDATA(pgm)->flash_pagesize;
} else if (strcmp(m->desc, "eeprom") == 0) { } else if (strcmp(m->desc, "eeprom") == 0) {
cmd[1] = MTYPE_EEPROM_PAGE; cmd[1] = MTYPE_EEPROM_PAGE;
eeprom_pageaddr = (unsigned long)-1L; PDATA(pgm)->eeprom_pageaddr = (unsigned long)-1L;
page_size = eeprom_pagesize; page_size = PDATA(pgm)->eeprom_pagesize;
if (pgm->flag & PGM_FL_IS_DW) { if (pgm->flag & PGM_FL_IS_DW) {
free(cmd); free(cmd);
return -1; return -1;
@ -1708,8 +1729,8 @@ static int jtagmkII_read_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
cmd[1] = MTYPE_FLASH_PAGE; cmd[1] = MTYPE_FLASH_PAGE;
pagesize = mem->page_size; pagesize = mem->page_size;
paddr = addr & ~(pagesize - 1); paddr = addr & ~(pagesize - 1);
paddr_ptr = &flash_pageaddr; paddr_ptr = &PDATA(pgm)->flash_pageaddr;
cache_ptr = flash_pagecache; cache_ptr = PDATA(pgm)->flash_pagecache;
} else if (strcmp(mem->desc, "eeprom") == 0) { } else if (strcmp(mem->desc, "eeprom") == 0) {
if (pgm->flag & PGM_FL_IS_DW) { if (pgm->flag & PGM_FL_IS_DW) {
/* debugWire cannot use page access for EEPROM */ /* 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; cmd[1] = MTYPE_EEPROM_PAGE;
pagesize = mem->page_size; pagesize = mem->page_size;
paddr = addr & ~(pagesize - 1); paddr = addr & ~(pagesize - 1);
paddr_ptr = &eeprom_pageaddr; paddr_ptr = &PDATA(pgm)->eeprom_pageaddr;
cache_ptr = eeprom_pagecache; cache_ptr = PDATA(pgm)->eeprom_pagecache;
} }
} else if (strcmp(mem->desc, "lfuse") == 0) { } else if (strcmp(mem->desc, "lfuse") == 0) {
cmd[1] = MTYPE_FUSE_BITS; 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) { if (strcmp(mem->desc, "flash") == 0) {
cmd[1] = MTYPE_SPM; cmd[1] = MTYPE_SPM;
need_progmode = 0; need_progmode = 0;
flash_pageaddr = (unsigned long)-1L; PDATA(pgm)->flash_pageaddr = (unsigned long)-1L;
if (pgm->flag & PGM_FL_IS_DW) if (pgm->flag & PGM_FL_IS_DW)
unsupp = 1; unsupp = 1;
} else if (strcmp(mem->desc, "eeprom") == 0) { } else if (strcmp(mem->desc, "eeprom") == 0) {
cmd[1] = MTYPE_EEPROM; cmd[1] = MTYPE_EEPROM;
need_progmode = 0; need_progmode = 0;
eeprom_pageaddr = (unsigned long)-1L; PDATA(pgm)->eeprom_pageaddr = (unsigned long)-1L;
} else if (strcmp(mem->desc, "lfuse") == 0) { } else if (strcmp(mem->desc, "lfuse") == 0) {
cmd[1] = MTYPE_FUSE_BITS; cmd[1] = MTYPE_FUSE_BITS;
addr = 0; 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 hardware version: %d\n", p, hw[1]);
fprintf(stderr, "%sS_MCU firmware version: %d.%02d\n", p, fw[3], fw[2]); 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", 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); jtagmkII_print_parms1(pgm, p);
@ -2215,6 +2236,8 @@ void jtagmkII_initpgm(PROGRAMMER * pgm)
pgm->print_parms = jtagmkII_print_parms; pgm->print_parms = jtagmkII_print_parms;
pgm->set_sck_period = jtagmkII_set_sck_period; pgm->set_sck_period = jtagmkII_set_sck_period;
pgm->parseextparams = jtagmkII_parseextparms; pgm->parseextparams = jtagmkII_parseextparms;
pgm->setup = jtagmkII_setup;
pgm->teardown = jtagmkII_teardown;
pgm->page_size = 256; pgm->page_size = 256;
} }
@ -2243,6 +2266,8 @@ void jtagmkII_dw_initpgm(PROGRAMMER * pgm)
pgm->paged_write = jtagmkII_paged_write; pgm->paged_write = jtagmkII_paged_write;
pgm->paged_load = jtagmkII_paged_load; pgm->paged_load = jtagmkII_paged_load;
pgm->print_parms = jtagmkII_print_parms; pgm->print_parms = jtagmkII_print_parms;
pgm->setup = jtagmkII_setup;
pgm->teardown = jtagmkII_teardown;
pgm->page_size = 256; pgm->page_size = 256;
pgm->flag = PGM_FL_IS_DW; pgm->flag = PGM_FL_IS_DW;
} }
@ -2274,6 +2299,8 @@ void jtagmkII_dragon_initpgm(PROGRAMMER * pgm)
pgm->print_parms = jtagmkII_print_parms; pgm->print_parms = jtagmkII_print_parms;
pgm->set_sck_period = jtagmkII_set_sck_period; pgm->set_sck_period = jtagmkII_set_sck_period;
pgm->parseextparams = jtagmkII_parseextparms; pgm->parseextparams = jtagmkII_parseextparms;
pgm->setup = jtagmkII_setup;
pgm->teardown = jtagmkII_teardown;
pgm->page_size = 256; pgm->page_size = 256;
} }
@ -2302,6 +2329,8 @@ void jtagmkII_dragon_dw_initpgm(PROGRAMMER * pgm)
pgm->paged_write = jtagmkII_paged_write; pgm->paged_write = jtagmkII_paged_write;
pgm->paged_load = jtagmkII_paged_load; pgm->paged_load = jtagmkII_paged_load;
pgm->print_parms = jtagmkII_print_parms; pgm->print_parms = jtagmkII_print_parms;
pgm->setup = jtagmkII_setup;
pgm->teardown = jtagmkII_teardown;
pgm->page_size = 256; pgm->page_size = 256;
pgm->flag = PGM_FL_IS_DW; pgm->flag = PGM_FL_IS_DW;
} }

17
main.c
View File

@ -1,6 +1,7 @@
/* /*
* avrdude - A Downloader/Uploader for AVR device programmers * avrdude - A Downloader/Uploader for AVR device programmers
* Copyright (C) 2000-2005 Brian S. Dean <bsd@bsdhome.com> * Copyright (C) 2000-2005 Brian S. Dean <bsd@bsdhome.com>
* Copyright 2007 Joerg Wunsch <j@uriah.heep.sax.de>
* *
* This program is free software; you can redistribute it and/or modify * 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 * 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 LISTID extended_params;
static PROGRAMMER * pgm;
/* /*
* global options * global options
*/ */
@ -222,6 +225,12 @@ static void list_parts(FILE * f, const char *prefix, LISTID avrparts)
walk_avrparts(avrparts, list_avrparts_callback, &c); walk_avrparts(avrparts, list_avrparts_callback, &c);
} }
static void exithook(void)
{
if (pgm->teardown)
pgm->teardown(pgm);
}
/* /*
* main routine * main routine
*/ */
@ -238,7 +247,6 @@ int main(int argc, char * argv [])
struct stat sb; struct stat sb;
UPDATE * upd; UPDATE * upd;
LNODEID * ln; LNODEID * ln;
PROGRAMMER * pgm;
/* options / operating mode variables */ /* options / operating mode variables */
@ -636,6 +644,13 @@ int main(int argc, char * argv [])
exit(1); exit(1);
} }
if (pgm->setup) {
pgm->setup(pgm);
}
if (pgm->teardown) {
atexit(exithook);
}
if (lsize(extended_params) > 0) { if (lsize(extended_params) > 0) {
if (pgm->parseextparams == NULL) { if (pgm->parseextparams == NULL) {
fprintf(stderr, fprintf(stderr,

3
pgm.c
View File

@ -1,6 +1,7 @@
/* /*
* avrdude - A Downloader/Uploader for AVR device programmers * avrdude - A Downloader/Uploader for AVR device programmers
* Copyright (C) 2002-2004 Brian S. Dean <bsd@bsdhome.com> * Copyright (C) 2002-2004 Brian S. Dean <bsd@bsdhome.com>
* Copyright 2007 Joerg Wunsch <j@uriah.heep.sax.de>
* *
* This program is free software; you can redistribute it and/or modify * 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 * 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->set_fosc = NULL;
pgm->perform_osccal = NULL; pgm->perform_osccal = NULL;
pgm->parseextparams = NULL; pgm->parseextparams = NULL;
pgm->setup = NULL;
pgm->teardown = NULL;
return pgm; return pgm;
} }

4
pgm.h
View File

@ -1,6 +1,7 @@
/* /*
* avrdude - A Downloader/Uploader for AVR device programmers * avrdude - A Downloader/Uploader for AVR device programmers
* Copyright (C) 2002-2004 Brian S. Dean <bsd@bsdhome.com> * Copyright (C) 2002-2004 Brian S. Dean <bsd@bsdhome.com>
* Copyright 2007 Joerg Wunsch <j@uriah.heep.sax.de>
* *
* This program is free software; you can redistribute it and/or modify * 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 * 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 (*parseexitspecs) (struct programmer_t * pgm, char *s);
int (*perform_osccal) (struct programmer_t * pgm); int (*perform_osccal) (struct programmer_t * pgm);
int (*parseextparams) (struct programmer_t * pgm, LISTID xparams); 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 */ char config_file[PATH_MAX]; /* config file where defined */
int lineno; /* config file line number */ int lineno; /* config file line number */
void *cookie; /* for private use by the programmer */
char flag; /* for private use of the programmer */ char flag; /* for private use of the programmer */
} PROGRAMMER; } PROGRAMMER;

View File

@ -3,7 +3,7 @@
* Copyright (C) 2005 Erik Walthinsen * Copyright (C) 2005 Erik Walthinsen
* Copyright (C) 2002-2004 Brian S. Dean <bsd@bsdhome.com> * Copyright (C) 2002-2004 Brian S. Dean <bsd@bsdhome.com>
* Copyright (C) 2006 David Moore * Copyright (C) 2006 David Moore
* Copyright (C) 2006 Joerg Wunsch <j@uriah.heep.sax.de> * Copyright (C) 2006,2007 Joerg Wunsch <j@uriah.heep.sax.de>
* *
* This program is free software; you can redistribute it and/or modify * 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 * 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 * Private data for this programmer.
* EEPROM page caches.
*/ */
static unsigned char *flash_pagecache; struct pdata
static unsigned long flash_pageaddr; {
static unsigned int flash_pagesize; /*
* 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; unsigned char *eeprom_pagecache;
static unsigned long eeprom_pageaddr; unsigned long eeprom_pageaddr;
static unsigned int eeprom_pagesize; unsigned int eeprom_pagesize;
unsigned char command_sequence;
};
#define PDATA(pgm) ((struct pdata *)(pgm->cookie))
static unsigned char command_sequence = 1;
static enum 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 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 static unsigned short
b2_to_u16(unsigned char *b) 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); return stk500v2_jtagmkII_send(pgm, data, len);
buf[0] = MESSAGE_START; buf[0] = MESSAGE_START;
buf[1] = command_sequence; buf[1] = PDATA(pgm)->command_sequence;
buf[2] = len / 256; buf[2] = len / 256;
buf[3] = len % 256; buf[3] = len % 256;
buf[4] = TOKEN; buf[4] = TOKEN;
@ -400,10 +427,10 @@ static int stk500v2_recv(PROGRAMMER * pgm, unsigned char msg[], size_t maxsize)
break; break;
case sSEQNUM: case sSEQNUM:
DEBUGRECV("hoping for sequence...\n"); DEBUGRECV("hoping for sequence...\n");
if (c == command_sequence) { if (c == PDATA(pgm)->command_sequence) {
DEBUGRECV("got it, incrementing\n"); DEBUGRECV("got it, incrementing\n");
state = sSIZE1; state = sSIZE1;
command_sequence++; PDATA(pgm)->command_sequence++;
} else { } else {
DEBUGRECV("sorry\n"); DEBUGRECV("sorry\n");
state = sSTART; 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 * caches. For devices/memory that are not page oriented, treat
* them as page size 1 for EEPROM, and 2 for flash. * them as page size 1 for EEPROM, and 2 for flash.
*/ */
flash_pagesize = 2; PDATA(pgm)->flash_pagesize = 2;
eeprom_pagesize = 1; PDATA(pgm)->eeprom_pagesize = 1;
for (ln = lfirst(p->mem); ln; ln = lnext(ln)) { for (ln = lfirst(p->mem); ln; ln = lnext(ln)) {
m = ldata(ln); m = ldata(ln);
if (strcmp(m->desc, "flash") == 0) { if (strcmp(m->desc, "flash") == 0) {
if (m->page_size > 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) { } else if (strcmp(m->desc, "eeprom") == 0) {
if (m->page_size > 0) if (m->page_size > 0)
eeprom_pagesize = m->page_size; PDATA(pgm)->eeprom_pagesize = m->page_size;
} }
} }
free(flash_pagecache); free(PDATA(pgm)->flash_pagecache);
free(eeprom_pagecache); free(PDATA(pgm)->eeprom_pagecache);
if ((flash_pagecache = malloc(flash_pagesize)) == NULL) { if ((PDATA(pgm)->flash_pagecache = malloc(PDATA(pgm)->flash_pagesize)) == NULL) {
fprintf(stderr, "%s: stk500pp_initialize(): Out of memory\n", fprintf(stderr, "%s: stk500pp_initialize(): Out of memory\n",
progname); progname);
return -1; 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", fprintf(stderr, "%s: stk500pp_initialize(): Out of memory\n",
progname); progname);
free(flash_pagecache); free(PDATA(pgm)->flash_pagecache);
return -1; 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); return pgm->program_enable(pgm, p);
} }
@ -902,10 +929,10 @@ static void stk500hv_disable(PROGRAMMER * pgm, enum hvmode mode)
unsigned char buf[16]; unsigned char buf[16];
int result; int result;
free(flash_pagecache); free(PDATA(pgm)->flash_pagecache);
flash_pagecache = NULL; PDATA(pgm)->flash_pagecache = NULL;
free(eeprom_pagecache); free(PDATA(pgm)->eeprom_pagecache);
eeprom_pagecache = NULL; PDATA(pgm)->eeprom_pagecache = NULL;
buf[0] = mode == PPMODE? CMD_LEAVE_PROGMODE_PP: CMD_LEAVE_PROGMODE_HVSP; buf[0] = mode == PPMODE? CMD_LEAVE_PROGMODE_PP: CMD_LEAVE_PROGMODE_HVSP;
buf[1] = 15; // p->hvleavestabdelay; buf[1] = 15; // p->hvleavestabdelay;
@ -1065,8 +1092,8 @@ static int stk500hv_read_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
if (pagesize == 0) if (pagesize == 0)
pagesize = 2; pagesize = 2;
paddr = addr & ~(pagesize - 1); paddr = addr & ~(pagesize - 1);
paddr_ptr = &flash_pageaddr; paddr_ptr = &PDATA(pgm)->flash_pageaddr;
cache_ptr = flash_pagecache; cache_ptr = PDATA(pgm)->flash_pagecache;
addrshift = 1; addrshift = 1;
/* /*
* If bit 31 is set, this indicates that the following read/write * 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) if (pagesize == 0)
pagesize = 1; pagesize = 1;
paddr = addr & ~(pagesize - 1); paddr = addr & ~(pagesize - 1);
paddr_ptr = &eeprom_pageaddr; paddr_ptr = &PDATA(pgm)->eeprom_pageaddr;
cache_ptr = eeprom_pagecache; cache_ptr = PDATA(pgm)->eeprom_pagecache;
} else if (strcmp(mem->desc, "lfuse") == 0 || } else if (strcmp(mem->desc, "lfuse") == 0 ||
strcmp(mem->desc, "fuse") == 0) { strcmp(mem->desc, "fuse") == 0) {
buf[0] = mode == PPMODE? CMD_READ_FUSE_PP: CMD_READ_FUSE_HVSP; 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) if (pagesize == 0)
pagesize = 2; pagesize = 2;
paddr = addr & ~(pagesize - 1); paddr = addr & ~(pagesize - 1);
paddr_ptr = &flash_pageaddr; paddr_ptr = &PDATA(pgm)->flash_pageaddr;
cache_ptr = flash_pagecache; cache_ptr = PDATA(pgm)->flash_pagecache;
addrshift = 1; addrshift = 1;
/* /*
* If bit 31 is set, this indicates that the following read/write * 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) if (pagesize == 0)
pagesize = 1; pagesize = 1;
paddr = addr & ~(pagesize - 1); paddr = addr & ~(pagesize - 1);
paddr_ptr = &eeprom_pageaddr; paddr_ptr = &PDATA(pgm)->eeprom_pageaddr;
cache_ptr = eeprom_pagecache; cache_ptr = PDATA(pgm)->eeprom_pagecache;
} else if (strcmp(mem->desc, "lfuse") == 0 || } else if (strcmp(mem->desc, "lfuse") == 0 ||
strcmp(mem->desc, "fuse") == 0) { strcmp(mem->desc, "fuse") == 0) {
buf[0] = mode == PPMODE? CMD_PROGRAM_FUSE_PP: CMD_PROGRAM_FUSE_HVSP; 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 // determine which command is to be used
if (strcmp(m->desc, "flash") == 0) { if (strcmp(m->desc, "flash") == 0) {
addrshift = 1; 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; commandbuf[0] = mode == PPMODE? CMD_PROGRAM_FLASH_PP: CMD_PROGRAM_FLASH_HVSP;
/* /*
* If bit 31 is set, this indicates that the following read/write * 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); use_ext_addr = (1U << 31);
} }
} else if (strcmp(m->desc, "eeprom") == 0) { } 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; 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_fosc = stk500v2_set_fosc;
pgm->set_sck_period = stk500v2_set_sck_period; pgm->set_sck_period = stk500v2_set_sck_period;
pgm->perform_osccal = stk500v2_perform_osccal; pgm->perform_osccal = stk500v2_perform_osccal;
pgm->setup = stk500v2_setup;
pgm->teardown = stk500v2_teardown;
pgm->page_size = 256; pgm->page_size = 256;
} }
@ -2417,6 +2446,8 @@ void stk500pp_initpgm(PROGRAMMER * pgm)
pgm->set_varef = stk500v2_set_varef; pgm->set_varef = stk500v2_set_varef;
pgm->set_fosc = stk500v2_set_fosc; pgm->set_fosc = stk500v2_set_fosc;
pgm->set_sck_period = stk500v2_set_sck_period; pgm->set_sck_period = stk500v2_set_sck_period;
pgm->setup = stk500v2_setup;
pgm->teardown = stk500v2_teardown;
pgm->page_size = 256; pgm->page_size = 256;
} }
@ -2448,6 +2479,8 @@ void stk500hvsp_initpgm(PROGRAMMER * pgm)
pgm->set_varef = stk500v2_set_varef; pgm->set_varef = stk500v2_set_varef;
pgm->set_fosc = stk500v2_set_fosc; pgm->set_fosc = stk500v2_set_fosc;
pgm->set_sck_period = stk500v2_set_sck_period; pgm->set_sck_period = stk500v2_set_sck_period;
pgm->setup = stk500v2_setup;
pgm->teardown = stk500v2_teardown;
pgm->page_size = 256; pgm->page_size = 256;
} }
@ -2478,6 +2511,8 @@ void stk500v2_jtagmkII_initpgm(PROGRAMMER * pgm)
pgm->print_parms = stk500v2_print_parms; pgm->print_parms = stk500v2_print_parms;
pgm->set_sck_period = stk500v2_set_sck_period_mk2; pgm->set_sck_period = stk500v2_set_sck_period_mk2;
pgm->perform_osccal = stk500v2_perform_osccal; pgm->perform_osccal = stk500v2_perform_osccal;
pgm->setup = stk500v2_setup;
pgm->teardown = stk500v2_teardown;
pgm->page_size = 256; pgm->page_size = 256;
} }
@ -2507,6 +2542,8 @@ void stk500v2_dragon_isp_initpgm(PROGRAMMER * pgm)
pgm->paged_load = stk500v2_paged_load; pgm->paged_load = stk500v2_paged_load;
pgm->print_parms = stk500v2_print_parms; pgm->print_parms = stk500v2_print_parms;
pgm->set_sck_period = stk500v2_set_sck_period_mk2; pgm->set_sck_period = stk500v2_set_sck_period_mk2;
pgm->setup = stk500v2_setup;
pgm->teardown = stk500v2_teardown;
pgm->page_size = 256; pgm->page_size = 256;
} }
@ -2538,6 +2575,8 @@ void stk500v2_dragon_pp_initpgm(PROGRAMMER * pgm)
pgm->set_varef = stk500v2_set_varef; pgm->set_varef = stk500v2_set_varef;
pgm->set_fosc = stk500v2_set_fosc; pgm->set_fosc = stk500v2_set_fosc;
pgm->set_sck_period = stk500v2_set_sck_period_mk2; pgm->set_sck_period = stk500v2_set_sck_period_mk2;
pgm->setup = stk500v2_setup;
pgm->teardown = stk500v2_teardown;
pgm->page_size = 256; pgm->page_size = 256;
} }
@ -2569,5 +2608,7 @@ void stk500v2_dragon_hvsp_initpgm(PROGRAMMER * pgm)
pgm->set_varef = stk500v2_set_varef; pgm->set_varef = stk500v2_set_varef;
pgm->set_fosc = stk500v2_set_fosc; pgm->set_fosc = stk500v2_set_fosc;
pgm->set_sck_period = stk500v2_set_sck_period_mk2; pgm->set_sck_period = stk500v2_set_sck_period_mk2;
pgm->setup = stk500v2_setup;
pgm->teardown = stk500v2_teardown;
pgm->page_size = 256; pgm->page_size = 256;
} }

View File

@ -1,6 +1,7 @@
/* /*
* avrdude - A Downloader/Uploader for AVR device programmers * avrdude - A Downloader/Uploader for AVR device programmers
* Copyright (C) 2006 Thomas Fischl * Copyright (C) 2006 Thomas Fischl
* Copyright 2007 Joerg Wunsch <j@uriah.heep.sax.de>
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -41,16 +42,42 @@
#ifdef HAVE_LIBUSB #ifdef HAVE_LIBUSB
#include <usb.h> #include <usb.h>
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 * 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) unsigned char send[4], unsigned char * buffer, int buffersize)
{ {
int nbytes; int nbytes;
nbytes = usb_control_msg(usbhandle, nbytes = usb_control_msg(PDATA(pgm)->usbhandle,
USB_TYPE_VENDOR | USB_RECIP_DEVICE | (receive << 7), USB_TYPE_VENDOR | USB_RECIP_DEVICE | (receive << 7),
functionid, functionid,
(send[1] << 8) | send[0], (send[1] << 8) | send[0],
@ -158,11 +185,11 @@ static int usbasp_open(PROGRAMMER * pgm, char * port)
{ {
usb_init(); 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) { USBASP_SHARED_PID, "USBasp") != 0) {
/* check if device with old VID/PID is available */ /* 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) { USBASP_OLD_PID, "USBasp") != 0) {
/* no USBasp found */ /* no USBasp found */
@ -190,9 +217,9 @@ static void usbasp_close(PROGRAMMER * pgm)
{ {
unsigned char temp[4]; unsigned char temp[4];
memset(temp, 0, sizeof(temp)); 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]; unsigned char temp[4];
memset(temp, 0, sizeof(temp)); 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); usleep(100000);
@ -232,7 +259,7 @@ static int usbasp_cmd(PROGRAMMER * pgm, unsigned char cmd[4],
unsigned char res[4]) unsigned char res[4])
{ {
int nbytes = 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){ if(nbytes != 4){
fprintf(stderr, "%s: error: wrong responds size\n", fprintf(stderr, "%s: error: wrong responds size\n",
@ -254,7 +281,7 @@ static int usbasp_program_enable(PROGRAMMER * pgm, AVRPART * p)
cmd[0] = 0; cmd[0] = 0;
int nbytes = 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)) { if ((nbytes != 1) | (res[0] != 0)) {
fprintf(stderr, "%s: error: programm enable: target doesn't answer. %x \n", 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[1] = address >> 8;
cmd[2] = address >> 16; cmd[2] = address >> 16;
cmd[3] = address >> 24; 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 /* send command with address (compatibility mode) - if firmware on
usbasp doesn't support newmode, then they use address from this */ 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[2] = 0;
cmd[3] = 0; cmd[3] = 0;
n = usbasp_transmit(1, function, cmd, buffer, blocksize); n = usbasp_transmit(pgm, 1, function, cmd, buffer, blocksize);
if (n != blocksize) { if (n != blocksize) {
fprintf(stderr, "%s: error: wrong reading bytes %x\n", 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[1] = address >> 8;
cmd[2] = address >> 16; cmd[2] = address >> 16;
cmd[3] = address >> 24; 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, /* 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 */ 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 cmd[3] = (blockflags & 0x0F) + ((page_size & 0xF00) >> 4); //TP: Mega128 fix
blockflags = 0; blockflags = 0;
n = usbasp_transmit(0, function, cmd, buffer, blocksize); n = usbasp_transmit(pgm, 0, function, cmd, buffer, blocksize);
if (n != blocksize) { if (n != blocksize) {
fprintf(stderr, "%s: error: wrong count at writing %x\n", 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_write = usbasp_paged_write;
pgm->paged_load = usbasp_paged_load; pgm->paged_load = usbasp_paged_load;
pgm->setup = usbasp_setup;
pgm->teardown = usbasp_teardown;
} }

122
usbtiny.c
View File

@ -47,18 +47,42 @@ typedef unsigned long ulong_t;
extern int avr_write_byte_default ( PROGRAMMER* pgm, AVRPART* p, extern int avr_write_byte_default ( PROGRAMMER* pgm, AVRPART* p,
AVRMEM* mem, ulong_t addr, AVRMEM* mem, ulong_t addr,
unsigned char data ); unsigned char data );
static usb_dev_handle* usb_handle; /*
static int sck_period; * Private data for this programmer.
static int chunk_size; */
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 // 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; 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, USB_ENDPOINT_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
requestid, requestid,
val, index, // 2 bytes each of data 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 // 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 ) unsigned char* buffer, int buflen, int bitclk )
{ {
int nbytes; 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. // figuring the bit-clock time and buffer size and adding to the standard USB timeout.
timeout = USB_TIMEOUT + (buflen * bitclk) / 1000; 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, USB_ENDPOINT_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
requestid, requestid,
val, index, 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 // 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, static int usb_out (PROGRAMMER * pgm,
unsigned char* buffer, int buflen, int bitclk ) unsigned int requestid, unsigned int val, unsigned int index,
unsigned char* buffer, int buflen, int bitclk )
{ {
int nbytes; int nbytes;
int timeout; 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. // figuring the bit-clock time and buffer size and adding to the standard USB timeout.
timeout = USB_TIMEOUT + (buflen * bitclk) / 1000; 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, USB_ENDPOINT_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
requestid, requestid,
val, index, 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_busses(); // have libusb scan all the usb busses available
usb_find_devices(); // have libusb scan all the usb devices 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 // now we iterate through all the busses and devices
for ( bus = usb_busses; bus; bus = bus->next ) { 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 if (dev->descriptor.idVendor == USBTINY_VENDOR
&& dev->descriptor.idProduct == USBTINY_PRODUCT ) { // found match? && 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? // wrong permissions or something?
if (!usb_handle) { if (!PDATA(pgm)->usb_handle) {
fprintf(stderr, "%s: Warning: cannot open USB device: %s\n", fprintf(stderr, "%s: Warning: cannot open USB device: %s\n",
progname, usb_strerror()); progname, usb_strerror());
continue; 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", fprintf( stderr, "%s: Error: Could not find USBtiny device (0x%x/0x%x)\n",
progname, USBTINY_VENDOR, USBTINY_PRODUCT ); progname, USBTINY_VENDOR, USBTINY_PRODUCT );
exit(1); exit(1);
@ -189,22 +215,22 @@ static int usbtiny_open(PROGRAMMER* pgm, char* name)
/* Clean up the handle for the usbtiny */ /* Clean up the handle for the usbtiny */
static void usbtiny_close ( PROGRAMMER* pgm ) static void usbtiny_close ( PROGRAMMER* pgm )
{ {
if (! usb_handle) { if (! PDATA(pgm)->usb_handle) {
return; // not a valid handle, bail! return; // not a valid handle, bail!
} }
usb_close(usb_handle); // ask libusb to clean up usb_close(PDATA(pgm)->usb_handle); // ask libusb to clean up
usb_handle = NULL; PDATA(pgm)->usb_handle = NULL;
} }
/* A simple calculator function determines the maximum size of data we can /* A simple calculator function determines the maximum size of data we can
shove through a USB connection without getting errors */ 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) PDATA(pgm)->chunk_size = CHUNK_SIZE; // start with the maximum (default)
while (chunk_size > 8 && period > 16) { while (PDATA(pgm)->chunk_size > 8 && period > 16) {
// Reduce the chunk size for a slow SCK to reduce // Reduce the chunk size for a slow SCK to reduce
// the maximum time of a single USB transfer. // the maximum time of a single USB transfer.
chunk_size >>= 1; PDATA(pgm)->chunk_size >>= 1;
period >>= 1; period >>= 1;
} }
} }
@ -213,23 +239,23 @@ static void usbtiny_set_chunk_size (int period)
USBtiny to update itself to the new frequency */ USBtiny to update itself to the new frequency */
static int usbtiny_set_sck_period (PROGRAMMER *pgm, double v) 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 // Make sure its not 0, as that will confuse the usbtiny
if (sck_period < SCK_MIN) if (PDATA(pgm)->sck_period < SCK_MIN)
sck_period = SCK_MIN; PDATA(pgm)->sck_period = SCK_MIN;
// We can't go slower, due to the byte-size of the clock variable // We can't go slower, due to the byte-size of the clock variable
if (sck_period > SCK_MAX) if (PDATA(pgm)->sck_period > SCK_MAX)
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. // 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 // 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; return 0;
} }
@ -244,13 +270,13 @@ static int usbtiny_initialize (PROGRAMMER *pgm, AVRPART *p )
usbtiny_set_sck_period(pgm, pgm->bitclock); usbtiny_set_sck_period(pgm, pgm->bitclock);
} else { } else {
// -B option not specified: use default // -B option not specified: use default
sck_period = SCK_DEFAULT; PDATA(pgm)->sck_period = SCK_DEFAULT;
if (verbose) { if (verbose) {
printf( "%s: Using SCK period of %d usec\n", 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 ); usb_control(pgm, USBTINY_POWERUP, PDATA(pgm)->sck_period, RESET_LOW );
usbtiny_set_chunk_size(sck_period); usbtiny_set_chunk_size(pgm, PDATA(pgm)->sck_period);
} }
// Let the device wake up. // 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?) // Attempt to use the underlying avrdude methods to connect (MEME: is this kosher?)
if (! usbtiny_avr_op(pgm, p, AVR_OP_PGM_ENABLE, res)) { if (! usbtiny_avr_op(pgm, p, AVR_OP_PGM_ENABLE, res)) {
// no response, RESET and try again // no response, RESET and try again
usb_control(USBTINY_POWERUP, sck_period, RESET_HIGH); usb_control(pgm, USBTINY_POWERUP, PDATA(pgm)->sck_period, RESET_HIGH);
usb_control(USBTINY_POWERUP, sck_period, RESET_LOW); usb_control(pgm, USBTINY_POWERUP, PDATA(pgm)->sck_period, RESET_LOW);
usleep(50000); usleep(50000);
if ( ! usbtiny_avr_op( pgm, p, AVR_OP_PGM_ENABLE, res)) { if ( ! usbtiny_avr_op( pgm, p, AVR_OP_PGM_ENABLE, res)) {
// give up // give up
@ -273,10 +299,10 @@ static int usbtiny_initialize (PROGRAMMER *pgm, AVRPART *p )
/* Tell the USBtiny to release the output pins, etc */ /* Tell the USBtiny to release the output pins, etc */
static void usbtiny_powerdown(PROGRAMMER * pgm) static void usbtiny_powerdown(PROGRAMMER * pgm)
{ {
if (!usb_handle) { if (!PDATA(pgm)->usb_handle) {
return; // wasn't connected in the first place 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 /* 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 // Make sure its empty so we don't read previous calls if it fails
memset(res, '\0', sizeof(res) ); 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[1] << 8) | cmd[0], // convert to 16-bit words
(cmd[3] << 8) | cmd[2], // " (cmd[3] << 8) | cmd[2], // "
res, sizeof(res), 8 * sck_period ); res, sizeof(res), 8 * PDATA(pgm)->sck_period );
if (verbose > 1) { if (verbose > 1) {
// print out the data we sent and received // print out the data we sent and received
printf( "CMD: [%02x %02x %02x %02x] [%02x %02x %02x %02x]\n", 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) { 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 we want to xmit less than a chunk, thats OK
if (chunk > n_bytes-i) 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 // Send the chunk of data to the USBtiny with the function we want
// to perform // to perform
usb_in(function, // EEPROM or flash usb_in(pgm,
function, // EEPROM or flash
0, // delay between SPI commands 0, // delay between SPI commands
i, // index i, // index
m->buf + i, // pointer to where we store data m->buf + i, // pointer to where we store data
chunk, // number of bytes 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. // usb_in() multiplies this per byte.
// Tell avrdude how we're doing to provide user feedback // 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) { if (! m->paged) {
// Does this chip not support paged writes? // Does this chip not support paged writes?
i = (m->readback[1] << 8) | m->readback[0]; 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; delay = m->max_write_delay;
} }
for (i=0; i < n_bytes; i=next) { for (i=0; i < n_bytes; i=next) {
// start with the max chunk size // start with the max chunk size
chunk = chunk_size; chunk = PDATA(pgm)->chunk_size;
// we can only write a page at a time anyways // we can only write a page at a time anyways
if (m->paged && chunk > page_size) 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) if (chunk > n_bytes-i)
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 delay, // How much to wait between each byte
i, // Index of data i, // Index of data
m->buf + i, // Pointer to data m->buf + i, // Pointer to data
chunk, // Number of bytes to write 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 // 4-byte SPI cmd usb_in() multiplies
// this per byte. Then add the cmd-delay // 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_load = usbtiny_paged_load;
pgm->paged_write = usbtiny_paged_write; pgm->paged_write = usbtiny_paged_write;
pgm->set_sck_period = usbtiny_set_sck_period; pgm->set_sck_period = usbtiny_set_sck_period;
pgm->setup = usbtiny_setup;
pgm->teardown = usbtiny_teardown;
} }
#else /* !HAVE_LIBUSB */ #else /* !HAVE_LIBUSB */