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:
parent
286405fd74
commit
58a3d35757
19
ChangeLog
19
ChangeLog
|
@ -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>
|
||||
|
||||
* butterfly.c: Remove the no_show_func_info() calls, as Brian
|
||||
|
|
40
avr910.c
40
avr910.c
|
@ -1,6 +1,7 @@
|
|||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* 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
|
||||
* 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;
|
||||
}
|
||||
|
|
47
butterfly.c
47
butterfly.c
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* 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
|
||||
* 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;
|
||||
}
|
||||
|
|
124
jtagmkI.c
124
jtagmkI.c
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* 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
|
||||
* 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;
|
||||
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;
|
||||
}
|
||||
|
|
163
jtagmkII.c
163
jtagmkII.c
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* 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:
|
||||
* Copyright (C) 2002-2004 Brian S. Dean <bsd@bsdhome.com>
|
||||
|
@ -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;
|
||||
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;
|
||||
}
|
||||
|
|
17
main.c
17
main.c
|
@ -1,6 +1,7 @@
|
|||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* 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
|
||||
* 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,
|
||||
|
|
3
pgm.c
3
pgm.c
|
@ -1,6 +1,7 @@
|
|||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* 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
|
||||
* 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;
|
||||
}
|
||||
|
|
4
pgm.h
4
pgm.h
|
@ -1,6 +1,7 @@
|
|||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* 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
|
||||
* 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;
|
||||
|
||||
|
|
111
stk500v2.c
111
stk500v2.c
|
@ -3,7 +3,7 @@
|
|||
* Copyright (C) 2005 Erik Walthinsen
|
||||
* Copyright (C) 2002-2004 Brian S. Dean <bsd@bsdhome.com>
|
||||
* 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
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -87,18 +87,27 @@ enum hvmode
|
|||
|
||||
|
||||
/*
|
||||
* Private data for this programmer.
|
||||
*/
|
||||
struct pdata
|
||||
{
|
||||
/*
|
||||
* See stk500pp_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;
|
||||
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;
|
||||
}
|
||||
|
|
57
usbasp.c
57
usbasp.c
|
@ -1,6 +1,7 @@
|
|||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* 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
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -41,16 +42,42 @@
|
|||
#ifdef HAVE_LIBUSB
|
||||
#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
|
||||
*/
|
||||
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;
|
||||
|
||||
}
|
||||
|
||||
|
|
120
usbtiny.c
120
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,7 +124,8 @@ 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,
|
||||
static int usb_out (PROGRAMMER * pgm,
|
||||
unsigned int requestid, unsigned int val, unsigned int index,
|
||||
unsigned char* buffer, int buflen, int bitclk )
|
||||
{
|
||||
int nbytes;
|
||||
|
@ -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 */
|
||||
|
|
Loading…
Reference in New Issue