2003-03-13 03:52:19 +00:00
|
|
|
/*
|
|
|
|
* avrdude - A Downloader/Uploader for AVR device programmers
|
2004-12-22 01:52:45 +00:00
|
|
|
* Copyright (C) 2003-2004 Theodore A. Roth <troth@openavr.org>
|
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
2007-11-07 20:36:12 +00:00
|
|
|
* Copyright 2007 Joerg Wunsch <j@uriah.heep.sax.de>
|
2003-03-13 03:52:19 +00:00
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* $Id$ */
|
|
|
|
|
|
|
|
/*
|
|
|
|
* avrdude interface for Atmel Low Cost Serial programmers which adher to the
|
|
|
|
* protocol described in application note avr910.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "ac_cfg.h"
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <errno.h>
|
2004-06-24 11:05:07 +00:00
|
|
|
#include <sys/time.h>
|
|
|
|
#include <unistd.h>
|
2003-03-13 03:52:19 +00:00
|
|
|
|
2007-01-24 21:07:54 +00:00
|
|
|
#include "avrdude.h"
|
2003-03-13 03:52:19 +00:00
|
|
|
#include "avr.h"
|
2007-01-24 22:43:46 +00:00
|
|
|
#include "config.h"
|
2003-03-13 03:52:19 +00:00
|
|
|
#include "pgm.h"
|
|
|
|
#include "avr910.h"
|
|
|
|
#include "serial.h"
|
|
|
|
|
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
2007-11-07 20:36:12 +00:00
|
|
|
/*
|
|
|
|
* 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);
|
|
|
|
}
|
2003-04-06 00:47:16 +00:00
|
|
|
|
2003-03-13 03:52:19 +00:00
|
|
|
|
|
|
|
static int avr910_send(PROGRAMMER * pgm, char * buf, size_t len)
|
|
|
|
{
|
2006-12-11 12:47:35 +00:00
|
|
|
return serial_send(&pgm->fd, (unsigned char *)buf, len);
|
2003-03-13 03:52:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int avr910_recv(PROGRAMMER * pgm, char * buf, size_t len)
|
|
|
|
{
|
2005-05-11 17:09:22 +00:00
|
|
|
int rv;
|
|
|
|
|
2006-12-11 12:47:35 +00:00
|
|
|
rv = serial_recv(&pgm->fd, (unsigned char *)buf, len);
|
2005-05-11 17:09:22 +00:00
|
|
|
if (rv < 0) {
|
|
|
|
fprintf(stderr,
|
|
|
|
"%s: avr910_recv(): programmer is not responding\n",
|
|
|
|
progname);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
return 0;
|
2003-03-13 03:52:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int avr910_drain(PROGRAMMER * pgm, int display)
|
|
|
|
{
|
2006-12-11 12:47:35 +00:00
|
|
|
return serial_drain(&pgm->fd, display);
|
2003-03-13 03:52:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-03-17 06:20:02 +00:00
|
|
|
static void avr910_vfy_cmd_sent(PROGRAMMER * pgm, char * errmsg)
|
|
|
|
{
|
|
|
|
char c;
|
|
|
|
|
|
|
|
avr910_recv(pgm, &c, 1);
|
|
|
|
if (c != '\r') {
|
|
|
|
fprintf(stderr, "%s: error: programmer did not respond to command: %s\n",
|
|
|
|
progname, errmsg);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-03-13 03:52:19 +00:00
|
|
|
/*
|
|
|
|
* issue the 'chip erase' command to the AVR device
|
|
|
|
*/
|
|
|
|
static int avr910_chip_erase(PROGRAMMER * pgm, AVRPART * p)
|
|
|
|
{
|
2003-03-17 06:20:02 +00:00
|
|
|
avr910_send(pgm, "e", 1);
|
|
|
|
avr910_vfy_cmd_sent(pgm, "chip erase");
|
2003-03-16 18:19:37 +00:00
|
|
|
|
2004-04-17 19:37:14 +00:00
|
|
|
/*
|
|
|
|
* avr910 firmware may not delay long enough
|
|
|
|
*/
|
|
|
|
usleep (p->chip_erase_delay);
|
|
|
|
|
2003-03-13 03:52:19 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2003-03-24 07:09:16 +00:00
|
|
|
|
|
|
|
static void avr910_enter_prog_mode(PROGRAMMER * pgm)
|
|
|
|
{
|
|
|
|
avr910_send(pgm, "P", 1);
|
|
|
|
avr910_vfy_cmd_sent(pgm, "enter prog mode");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void avr910_leave_prog_mode(PROGRAMMER * pgm)
|
|
|
|
{
|
|
|
|
avr910_send(pgm, "L", 1);
|
|
|
|
avr910_vfy_cmd_sent(pgm, "leave prog mode");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-03-13 03:52:19 +00:00
|
|
|
/*
|
|
|
|
* issue the 'program enable' command to the AVR device
|
|
|
|
*/
|
|
|
|
static int avr910_program_enable(PROGRAMMER * pgm, AVRPART * p)
|
|
|
|
{
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* initialize the AVR device and prepare it to accept commands
|
|
|
|
*/
|
|
|
|
static int avr910_initialize(PROGRAMMER * pgm, AVRPART * p)
|
|
|
|
{
|
2003-03-17 06:20:02 +00:00
|
|
|
char id[8];
|
2003-03-16 18:19:37 +00:00
|
|
|
char sw[2];
|
|
|
|
char hw[2];
|
2003-03-17 06:20:02 +00:00
|
|
|
char buf[10];
|
|
|
|
char type;
|
2006-09-20 21:32:18 +00:00
|
|
|
char c, devtype_1st;
|
2003-03-17 06:20:02 +00:00
|
|
|
int dev_supported = 0;
|
2004-01-12 22:48:50 +00:00
|
|
|
AVRPART * part;
|
2003-03-16 18:19:37 +00:00
|
|
|
|
2003-03-17 06:20:02 +00:00
|
|
|
/* Get the programmer identifier. Programmer returns exactly 7 chars
|
|
|
|
_without_ the null.*/
|
2003-03-16 18:19:37 +00:00
|
|
|
|
|
|
|
avr910_send(pgm, "S", 1);
|
2003-03-17 06:20:02 +00:00
|
|
|
memset (id, 0, sizeof(id));
|
|
|
|
avr910_recv(pgm, id, sizeof(id)-1);
|
2003-03-16 18:19:37 +00:00
|
|
|
|
|
|
|
/* Get the HW and SW versions to see if the programmer is present. */
|
|
|
|
|
|
|
|
avr910_send(pgm, "V", 1);
|
|
|
|
avr910_recv(pgm, sw, sizeof(sw));
|
|
|
|
|
|
|
|
avr910_send(pgm, "v", 1);
|
|
|
|
avr910_recv(pgm, hw, sizeof(hw));
|
|
|
|
|
2003-03-17 06:20:02 +00:00
|
|
|
/* Get the programmer type (serial or parallel). Expect serial. */
|
|
|
|
|
|
|
|
avr910_send(pgm, "p", 1);
|
|
|
|
avr910_recv(pgm, &type, 1);
|
|
|
|
|
|
|
|
fprintf(stderr, "Found programmer: Id = \"%s\"; type = %c\n", id, type);
|
2003-04-06 00:47:16 +00:00
|
|
|
fprintf(stderr, " Software Version = %c.%c; ", sw[0], sw[1]);
|
|
|
|
fprintf(stderr, "Hardware Version = %c.%c\n", hw[0], hw[1]);
|
|
|
|
|
|
|
|
/* See if programmer supports autoincrement of address. */
|
|
|
|
|
|
|
|
avr910_send(pgm, "a", 1);
|
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
2007-11-07 20:36:12 +00:00
|
|
|
avr910_recv(pgm, &PDATA(pgm)->has_auto_incr_addr, 1);
|
|
|
|
if (PDATA(pgm)->has_auto_incr_addr == 'Y')
|
2003-04-06 00:47:16 +00:00
|
|
|
fprintf(stderr, "Programmer supports auto addr increment.\n");
|
2003-03-16 18:19:37 +00:00
|
|
|
|
|
|
|
/* Get list of devices that the programmer supports. */
|
|
|
|
|
|
|
|
avr910_send(pgm, "t", 1);
|
2003-03-17 06:20:02 +00:00
|
|
|
fprintf(stderr, "\nProgrammer supports the following devices:\n");
|
2006-09-20 21:32:18 +00:00
|
|
|
devtype_1st = 0;
|
2003-03-16 18:19:37 +00:00
|
|
|
while (1) {
|
|
|
|
avr910_recv(pgm, &c, 1);
|
2006-09-20 21:32:18 +00:00
|
|
|
if (devtype_1st == 0)
|
|
|
|
devtype_1st = c;
|
2003-03-16 18:19:37 +00:00
|
|
|
if (c == 0)
|
|
|
|
break;
|
2004-01-12 22:48:50 +00:00
|
|
|
part = locate_part_by_avr910_devcode(part_list, c);
|
|
|
|
|
|
|
|
fprintf(stderr, " Device code: 0x%02x = %s\n", c, part ? part->desc : "(unknown)");
|
2003-03-17 06:20:02 +00:00
|
|
|
|
|
|
|
/* FIXME: Need to lookup devcode and report the device. */
|
|
|
|
|
|
|
|
if (p->avr910_devcode == c)
|
|
|
|
dev_supported = 1;
|
2003-03-16 18:19:37 +00:00
|
|
|
};
|
2003-03-17 06:20:02 +00:00
|
|
|
fprintf(stderr,"\n");
|
|
|
|
|
|
|
|
if (!dev_supported) {
|
|
|
|
fprintf(stderr,
|
2006-09-20 21:32:18 +00:00
|
|
|
"%s: %s: selected device is not supported by programmer: %s\n",
|
|
|
|
progname, ovsigck? "warning": "error", p->id);
|
|
|
|
if (!ovsigck)
|
|
|
|
exit(1);
|
2003-03-17 06:20:02 +00:00
|
|
|
}
|
|
|
|
|
2006-09-20 21:32:18 +00:00
|
|
|
/* Tell the programmer which part we selected.
|
|
|
|
If the user forced the selection, use the first device
|
|
|
|
type that is supported by the programmer. */
|
2003-03-17 06:20:02 +00:00
|
|
|
|
|
|
|
buf[0] = 'T';
|
2006-09-20 21:32:18 +00:00
|
|
|
buf[1] = ovsigck? devtype_1st: p->avr910_devcode;
|
2003-03-17 06:20:02 +00:00
|
|
|
|
|
|
|
avr910_send(pgm, buf, 2);
|
|
|
|
avr910_vfy_cmd_sent(pgm, "select device");
|
|
|
|
|
|
|
|
avr910_enter_prog_mode(pgm);
|
2003-03-16 18:19:37 +00:00
|
|
|
|
2003-03-13 03:52:19 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void avr910_disable(PROGRAMMER * pgm)
|
|
|
|
{
|
2003-03-17 06:20:02 +00:00
|
|
|
/* Do nothing. */
|
2003-03-16 18:19:37 +00:00
|
|
|
|
2003-03-13 03:52:19 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void avr910_enable(PROGRAMMER * pgm)
|
|
|
|
{
|
2003-03-16 18:19:37 +00:00
|
|
|
/* Do nothing. */
|
|
|
|
|
2003-03-13 03:52:19 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* transmit an AVR device command and return the results; 'cmd' and
|
|
|
|
* 'res' must point to at least a 4 byte data buffer
|
|
|
|
*/
|
|
|
|
static int avr910_cmd(PROGRAMMER * pgm, unsigned char cmd[4],
|
|
|
|
unsigned char res[4])
|
|
|
|
{
|
2005-08-30 01:30:05 +00:00
|
|
|
char buf[5];
|
2003-03-17 06:20:02 +00:00
|
|
|
|
2003-09-05 16:40:55 +00:00
|
|
|
/* FIXME: Insert version check here */
|
|
|
|
|
|
|
|
buf[0] = '.'; /* New Universal Command */
|
|
|
|
buf[1] = cmd[0];
|
|
|
|
buf[2] = cmd[1];
|
|
|
|
buf[3] = cmd[2];
|
|
|
|
buf[4] = cmd[3];
|
|
|
|
|
|
|
|
avr910_send (pgm, buf, 5);
|
|
|
|
avr910_recv (pgm, buf, 2);
|
|
|
|
|
|
|
|
res[0] = 0x00; /* Dummy value */
|
|
|
|
res[1] = cmd[0];
|
|
|
|
res[2] = cmd[1];
|
|
|
|
res[3] = buf[0];
|
2003-03-17 06:20:02 +00:00
|
|
|
|
2003-03-16 18:19:37 +00:00
|
|
|
return 0;
|
2003-03-13 03:52:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-01-28 20:01:44 +00:00
|
|
|
static int avr910_open(PROGRAMMER * pgm, char * port)
|
2003-03-13 03:52:19 +00:00
|
|
|
{
|
2004-01-03 18:36:44 +00:00
|
|
|
/*
|
|
|
|
* If baudrate was not specified use 19.200 Baud
|
|
|
|
*/
|
|
|
|
if(pgm->baudrate == 0) {
|
|
|
|
pgm->baudrate = 19200;
|
|
|
|
}
|
|
|
|
|
2003-03-13 03:52:19 +00:00
|
|
|
strcpy(pgm->port, port);
|
2006-12-11 12:47:35 +00:00
|
|
|
serial_open(port, pgm->baudrate, &pgm->fd);
|
2003-03-13 03:52:19 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* drain any extraneous input
|
|
|
|
*/
|
|
|
|
avr910_drain (pgm, 0);
|
2004-06-24 11:05:07 +00:00
|
|
|
|
|
|
|
return 0;
|
2003-03-13 03:52:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void avr910_close(PROGRAMMER * pgm)
|
|
|
|
{
|
2003-03-17 06:20:02 +00:00
|
|
|
avr910_leave_prog_mode(pgm);
|
2003-03-16 18:19:37 +00:00
|
|
|
|
2006-12-11 12:47:35 +00:00
|
|
|
serial_close(&pgm->fd);
|
|
|
|
pgm->fd.ifd = -1;
|
2003-03-13 03:52:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-01-30 13:41:54 +00:00
|
|
|
static void avr910_display(PROGRAMMER * pgm, const char * p)
|
2003-03-13 03:52:19 +00:00
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2003-03-24 07:09:16 +00:00
|
|
|
|
|
|
|
static void avr910_set_addr(PROGRAMMER * pgm, unsigned long addr)
|
|
|
|
{
|
2005-08-30 01:30:05 +00:00
|
|
|
char cmd[3];
|
2003-03-24 07:09:16 +00:00
|
|
|
|
|
|
|
cmd[0] = 'A';
|
|
|
|
cmd[1] = (addr >> 8) & 0xff;
|
|
|
|
cmd[2] = addr & 0xff;
|
|
|
|
|
|
|
|
avr910_send(pgm, cmd, sizeof(cmd));
|
|
|
|
avr910_vfy_cmd_sent(pgm, "set addr");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-04-06 07:10:44 +00:00
|
|
|
static int avr910_write_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
|
|
|
unsigned long addr, unsigned char value)
|
|
|
|
{
|
2005-08-30 01:30:05 +00:00
|
|
|
char cmd[2];
|
2003-04-06 07:10:44 +00:00
|
|
|
|
|
|
|
if (strcmp(m->desc, "flash") == 0) {
|
|
|
|
if (addr & 0x01) {
|
|
|
|
cmd[0] = 'C'; /* Write Program Mem high byte */
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
cmd[0] = 'c';
|
|
|
|
}
|
|
|
|
|
|
|
|
addr >>= 1;
|
|
|
|
}
|
|
|
|
else if (strcmp(m->desc, "eeprom") == 0) {
|
|
|
|
cmd[0] = 'D';
|
|
|
|
}
|
|
|
|
else {
|
2007-05-15 22:00:29 +00:00
|
|
|
return avr_write_byte_default(pgm, p, m, addr, value);
|
2003-04-06 07:10:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
cmd[1] = value;
|
|
|
|
|
|
|
|
avr910_set_addr(pgm, addr);
|
|
|
|
|
|
|
|
avr910_send(pgm, cmd, sizeof(cmd));
|
|
|
|
avr910_vfy_cmd_sent(pgm, "write byte");
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int avr910_read_byte_flash(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
|
|
|
unsigned long addr, unsigned char * value)
|
|
|
|
{
|
|
|
|
static int cached = 0;
|
|
|
|
static unsigned char cvalue;
|
|
|
|
static unsigned long caddr;
|
|
|
|
|
|
|
|
if (cached && ((caddr + 1) == addr)) {
|
|
|
|
*value = cvalue;
|
|
|
|
cached = 0;
|
|
|
|
}
|
|
|
|
else {
|
2005-08-30 01:30:05 +00:00
|
|
|
char buf[2];
|
2003-04-06 07:10:44 +00:00
|
|
|
|
|
|
|
avr910_set_addr(pgm, addr >> 1);
|
|
|
|
|
|
|
|
avr910_send(pgm, "R", 1);
|
|
|
|
|
|
|
|
/* Read back the program mem word (MSB first) */
|
|
|
|
avr910_recv(pgm, buf, sizeof(buf));
|
|
|
|
|
|
|
|
if ((addr & 0x01) == 0) {
|
|
|
|
*value = buf[1];
|
2005-09-18 00:28:19 +00:00
|
|
|
// cached = 1;
|
2003-04-06 07:10:44 +00:00
|
|
|
cvalue = buf[0];
|
|
|
|
caddr = addr;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
*value = buf[0];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int avr910_read_byte_eeprom(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
|
|
|
unsigned long addr, unsigned char * value)
|
|
|
|
{
|
|
|
|
avr910_set_addr(pgm, addr);
|
|
|
|
avr910_send(pgm, "d", 1);
|
2005-08-30 01:30:05 +00:00
|
|
|
avr910_recv(pgm, (char *)value, 1);
|
2003-04-06 07:10:44 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int avr910_read_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
|
|
|
unsigned long addr, unsigned char * value)
|
|
|
|
{
|
|
|
|
if (strcmp(m->desc, "flash") == 0) {
|
|
|
|
return avr910_read_byte_flash(pgm, p, m, addr, value);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (strcmp(m->desc, "eeprom") == 0) {
|
|
|
|
return avr910_read_byte_eeprom(pgm, p, m, addr, value);
|
|
|
|
}
|
|
|
|
|
2007-05-15 22:00:29 +00:00
|
|
|
return avr_read_byte_default(pgm, p, m, addr, value);
|
2003-04-06 07:10:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-04-06 00:47:16 +00:00
|
|
|
static int avr910_paged_write_flash(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
|
|
|
int page_size, int n_bytes)
|
2003-03-24 07:09:16 +00:00
|
|
|
{
|
2003-04-06 00:47:16 +00:00
|
|
|
unsigned char cmd[] = {'c', 'C'};
|
2005-08-30 01:30:05 +00:00
|
|
|
char buf[2];
|
2003-04-06 00:47:16 +00:00
|
|
|
unsigned int addr = 0;
|
|
|
|
unsigned int max_addr = n_bytes;
|
2003-05-14 05:14:32 +00:00
|
|
|
unsigned int page_addr;
|
|
|
|
int page_bytes = page_size;
|
2003-08-28 23:02:25 +00:00
|
|
|
int page_wr_cmd_pending = 0;
|
2003-03-24 07:09:16 +00:00
|
|
|
|
2003-05-14 05:14:32 +00:00
|
|
|
page_addr = addr;
|
2003-04-06 00:47:16 +00:00
|
|
|
avr910_set_addr(pgm, addr>>1);
|
2003-03-24 07:09:16 +00:00
|
|
|
|
2003-04-06 00:47:16 +00:00
|
|
|
while (addr < max_addr) {
|
2003-05-14 05:14:32 +00:00
|
|
|
page_wr_cmd_pending = 1;
|
2003-04-06 00:47:16 +00:00
|
|
|
buf[0] = cmd[addr & 0x01];
|
|
|
|
buf[1] = m->buf[addr];
|
|
|
|
avr910_send(pgm, buf, sizeof(buf));
|
|
|
|
avr910_vfy_cmd_sent(pgm, "write byte");
|
2003-03-24 07:09:16 +00:00
|
|
|
|
2003-04-06 00:47:16 +00:00
|
|
|
addr++;
|
2003-05-14 05:14:32 +00:00
|
|
|
page_bytes--;
|
2003-03-24 07:09:16 +00:00
|
|
|
|
2005-09-18 00:28:19 +00:00
|
|
|
if (m->paged && (page_bytes == 0)) {
|
2003-05-14 05:14:32 +00:00
|
|
|
/* Send the "Issue Page Write" if we have sent a whole page. */
|
|
|
|
|
|
|
|
avr910_set_addr(pgm, page_addr>>1);
|
|
|
|
avr910_send(pgm, "m", 1);
|
|
|
|
avr910_vfy_cmd_sent(pgm, "flush page");
|
|
|
|
|
2005-09-18 00:28:19 +00:00
|
|
|
page_wr_cmd_pending = 0;
|
|
|
|
usleep(m->max_write_delay);
|
|
|
|
avr910_set_addr(pgm, addr>>1);
|
|
|
|
|
2003-05-14 05:14:32 +00:00
|
|
|
/* Set page address for next page. */
|
|
|
|
|
|
|
|
page_addr = addr;
|
|
|
|
page_bytes = page_size;
|
|
|
|
}
|
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
2007-11-07 20:36:12 +00:00
|
|
|
else if ((PDATA(pgm)->has_auto_incr_addr != 'Y') && ((addr & 0x01) == 0)) {
|
2005-09-18 00:28:19 +00:00
|
|
|
avr910_set_addr(pgm, addr>>1);
|
|
|
|
}
|
2003-07-29 22:08:21 +00:00
|
|
|
|
|
|
|
report_progress (addr, max_addr, NULL);
|
2003-05-14 05:14:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* If we didn't send the page wr cmd after the last byte written in the
|
|
|
|
loop, send it now. */
|
|
|
|
|
|
|
|
if (page_wr_cmd_pending) {
|
|
|
|
avr910_set_addr(pgm, page_addr>>1);
|
|
|
|
avr910_send(pgm, "m", 1);
|
|
|
|
avr910_vfy_cmd_sent(pgm, "flush final page");
|
2005-09-18 00:28:19 +00:00
|
|
|
usleep(m->max_write_delay);
|
2003-03-24 07:09:16 +00:00
|
|
|
}
|
|
|
|
|
2003-04-06 00:47:16 +00:00
|
|
|
return addr;
|
2003-03-24 07:09:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-04-06 00:47:16 +00:00
|
|
|
static int avr910_paged_write_eeprom(PROGRAMMER * pgm, AVRPART * p,
|
|
|
|
AVRMEM * m, int page_size, int n_bytes)
|
2003-03-24 07:09:16 +00:00
|
|
|
{
|
2005-08-30 01:30:05 +00:00
|
|
|
char cmd[2];
|
2003-04-06 00:47:16 +00:00
|
|
|
unsigned int addr = 0;
|
|
|
|
unsigned int max_addr = n_bytes;
|
2003-03-24 07:09:16 +00:00
|
|
|
|
2003-04-06 00:47:16 +00:00
|
|
|
avr910_set_addr(pgm, addr);
|
2003-03-24 07:09:16 +00:00
|
|
|
|
2003-04-06 00:47:16 +00:00
|
|
|
cmd[0] = 'D';
|
2003-03-24 07:09:16 +00:00
|
|
|
|
2003-04-06 00:47:16 +00:00
|
|
|
while (addr < max_addr) {
|
|
|
|
cmd[1] = m->buf[addr];
|
|
|
|
avr910_send(pgm, cmd, sizeof(cmd));
|
|
|
|
avr910_vfy_cmd_sent(pgm, "write byte");
|
2005-09-18 00:28:19 +00:00
|
|
|
usleep(m->max_write_delay);
|
2003-03-24 07:09:16 +00:00
|
|
|
|
2003-04-06 00:47:16 +00:00
|
|
|
addr++;
|
2003-03-24 07:09:16 +00:00
|
|
|
|
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
2007-11-07 20:36:12 +00:00
|
|
|
if (PDATA(pgm)->has_auto_incr_addr != 'Y') {
|
2003-04-06 00:47:16 +00:00
|
|
|
avr910_set_addr(pgm, addr);
|
2003-03-24 07:09:16 +00:00
|
|
|
}
|
2003-07-29 22:08:21 +00:00
|
|
|
|
|
|
|
report_progress (addr, max_addr, NULL);
|
2003-03-24 07:09:16 +00:00
|
|
|
}
|
|
|
|
|
2003-04-06 00:47:16 +00:00
|
|
|
return addr;
|
2003-03-24 07:09:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-04-17 19:37:14 +00:00
|
|
|
static int avr910_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
2003-04-06 00:47:16 +00:00
|
|
|
int page_size, int n_bytes)
|
2003-03-24 07:09:16 +00:00
|
|
|
{
|
2003-04-06 00:47:16 +00:00
|
|
|
if (strcmp(m->desc, "flash") == 0) {
|
|
|
|
return avr910_paged_write_flash(pgm, p, m, page_size, n_bytes);
|
|
|
|
}
|
|
|
|
else if (strcmp(m->desc, "eeprom") == 0) {
|
|
|
|
return avr910_paged_write_eeprom(pgm, p, m, page_size, n_bytes);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return -2;
|
|
|
|
}
|
2003-03-24 07:09:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-04-06 00:47:16 +00:00
|
|
|
static int avr910_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
|
|
|
int page_size, int n_bytes)
|
2003-03-24 07:09:16 +00:00
|
|
|
{
|
2005-08-30 01:30:05 +00:00
|
|
|
char cmd;
|
2003-04-06 00:47:16 +00:00
|
|
|
int rd_size;
|
|
|
|
unsigned int addr = 0;
|
|
|
|
unsigned int max_addr;
|
2005-08-30 01:30:05 +00:00
|
|
|
char buf[2];
|
2003-03-24 07:09:16 +00:00
|
|
|
|
|
|
|
if (strcmp(m->desc, "flash") == 0) {
|
2003-04-06 00:47:16 +00:00
|
|
|
cmd = 'R';
|
|
|
|
rd_size = 2; /* read two bytes per addr */
|
|
|
|
}
|
|
|
|
else if (strcmp(m->desc, "eeprom") == 0) {
|
|
|
|
cmd = 'd';
|
|
|
|
rd_size = 1;
|
2003-03-24 07:09:16 +00:00
|
|
|
}
|
2003-04-06 00:47:16 +00:00
|
|
|
else {
|
|
|
|
return -2;
|
|
|
|
}
|
|
|
|
|
|
|
|
max_addr = n_bytes/rd_size;
|
2003-03-24 07:09:16 +00:00
|
|
|
|
2003-04-06 00:47:16 +00:00
|
|
|
avr910_set_addr(pgm, addr);
|
|
|
|
|
|
|
|
while (addr < max_addr) {
|
|
|
|
avr910_send(pgm, &cmd, 1);
|
2003-04-09 20:37:28 +00:00
|
|
|
if (cmd == 'R') {
|
|
|
|
/* The 'R' command returns two bytes, MSB first, we need to put the data
|
|
|
|
into the memory buffer LSB first. */
|
|
|
|
avr910_recv(pgm, buf, 2);
|
|
|
|
m->buf[addr*2] = buf[1]; /* LSB */
|
|
|
|
m->buf[addr*2+1] = buf[0]; /* MSB */
|
|
|
|
}
|
|
|
|
else {
|
2005-08-30 01:30:05 +00:00
|
|
|
avr910_recv(pgm, (char *)&m->buf[addr], 1);
|
2003-04-09 20:37:28 +00:00
|
|
|
}
|
2003-04-06 00:47:16 +00:00
|
|
|
|
|
|
|
addr++;
|
|
|
|
|
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
2007-11-07 20:36:12 +00:00
|
|
|
if (PDATA(pgm)->has_auto_incr_addr != 'Y') {
|
2003-04-06 00:47:16 +00:00
|
|
|
avr910_set_addr(pgm, addr);
|
|
|
|
}
|
2003-07-29 22:08:21 +00:00
|
|
|
|
|
|
|
report_progress (addr, max_addr, NULL);
|
2003-03-24 07:09:16 +00:00
|
|
|
}
|
|
|
|
|
2003-04-06 00:47:16 +00:00
|
|
|
return addr * rd_size;
|
2003-03-24 07:09:16 +00:00
|
|
|
}
|
|
|
|
|
2003-03-17 06:20:02 +00:00
|
|
|
/* Signature byte reads are always 3 bytes. */
|
|
|
|
|
|
|
|
static int avr910_read_sig_bytes(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m)
|
|
|
|
{
|
2006-09-01 10:03:12 +00:00
|
|
|
unsigned char tmp;
|
|
|
|
|
2003-03-17 06:20:02 +00:00
|
|
|
if (m->size < 3) {
|
|
|
|
fprintf(stderr, "%s: memsize too small for sig byte read", progname);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
avr910_send(pgm, "s", 1);
|
2005-08-30 01:30:05 +00:00
|
|
|
avr910_recv(pgm, (char *)m->buf, 3);
|
2006-09-01 10:03:12 +00:00
|
|
|
/* Returned signature has wrong order. */
|
|
|
|
tmp = m->buf[2];
|
|
|
|
m->buf[2] = m->buf[0];
|
|
|
|
m->buf[0] = tmp;
|
2003-03-17 06:20:02 +00:00
|
|
|
|
|
|
|
return 3;
|
|
|
|
}
|
|
|
|
|
2003-03-13 03:52:19 +00:00
|
|
|
|
|
|
|
void avr910_initpgm(PROGRAMMER * pgm)
|
|
|
|
{
|
|
|
|
strcpy(pgm->type, "avr910");
|
|
|
|
|
|
|
|
/*
|
|
|
|
* mandatory functions
|
|
|
|
*/
|
|
|
|
pgm->initialize = avr910_initialize;
|
|
|
|
pgm->display = avr910_display;
|
|
|
|
pgm->enable = avr910_enable;
|
|
|
|
pgm->disable = avr910_disable;
|
|
|
|
pgm->program_enable = avr910_program_enable;
|
|
|
|
pgm->chip_erase = avr910_chip_erase;
|
|
|
|
pgm->cmd = avr910_cmd;
|
|
|
|
pgm->open = avr910_open;
|
|
|
|
pgm->close = avr910_close;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* optional functions
|
|
|
|
*/
|
2003-03-17 06:20:02 +00:00
|
|
|
|
2003-04-06 07:10:44 +00:00
|
|
|
pgm->write_byte = avr910_write_byte;
|
|
|
|
pgm->read_byte = avr910_read_byte;
|
|
|
|
|
2003-04-06 00:47:16 +00:00
|
|
|
pgm->paged_write = avr910_paged_write;
|
|
|
|
pgm->paged_load = avr910_paged_load;
|
2003-04-06 07:10:44 +00:00
|
|
|
|
2003-03-17 06:20:02 +00:00
|
|
|
pgm->read_sig_bytes = avr910_read_sig_bytes;
|
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
2007-11-07 20:36:12 +00:00
|
|
|
|
|
|
|
pgm->setup = avr910_setup;
|
|
|
|
pgm->teardown = avr910_teardown;
|
2003-03-13 03:52:19 +00:00
|
|
|
}
|