[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[avrdude-dev] Partial stk500v2 code
From: |
Erik Walthinsen |
Subject: |
[avrdude-dev] Partial stk500v2 code |
Date: |
Mon, 31 Jan 2005 14:51:44 -0800 |
User-agent: |
Debian Thunderbird 1.0 (X11/20050116) |
Attached is what I've got written up so far, in the form of rewrites of
some of the lower level functions in stk500.c.
diff -urN avrdude/Makefile.am avrdude-v2/Makefile.am
--- avrdude/Makefile.am 2005-01-24 13:26:11.000000000 -0800
+++ avrdude-v2/Makefile.am 2005-01-30 16:11:41.000000000 -0800
@@ -82,6 +82,9 @@
stk500.c \
stk500.h \
stk500_private.h \
+ stk500v2.c \
+ stk500v2.h \
+ stk500v2_private.h \
term.c \
term.h
diff -urN avrdude/avrdude.conf.in avrdude-v2/avrdude.conf.in
--- avrdude/avrdude.conf.in 2004-12-21 17:30:30.000000000 -0800
+++ avrdude-v2/avrdude.conf.in 2005-01-30 16:13:18.000000000 -0800
@@ -15,7 +15,7 @@
# programmer
# id = <id1> [, <id2> [, <id3>] ...] ; # <idN> are quoted strings
# desc = <description> ; # quoted string
-# type = par | stk500 | avr910; # programmer type
+# type = par | stk500 | stk500v2 | avr910; # programmer type
# baudrate = <num> ; # baudrate for
avr910-programmer
# vcc = <num1> [, <num2> ... ] ; # pin number(s)
# reset = <num> ; # pin number
@@ -209,12 +209,24 @@
;
programmer
+ id = "avrispv2";
+ desc = "Atmel AVR ISP V2";
+ type = stk500v2;
+;
+
+programmer
id = "stk500";
desc = "Atmel STK500";
type = stk500;
;
programmer
+ id = "stk500v2";
+ desc = "Atmel STK500 V2";
+ type = stk500v2;
+;
+
+programmer
id = "avr910";
desc = "Atmel Low Cost Serial Programmer";
type = avr910;
diff -urN avrdude/config_gram.y avrdude-v2/config_gram.y
--- avrdude/config_gram.y 2004-12-21 17:52:45.000000000 -0800
+++ avrdude-v2/config_gram.y 2005-01-30 16:14:08.000000000 -0800
@@ -33,6 +33,7 @@
#include "ppi.h"
#include "pgm.h"
#include "stk500.h"
+#include "stk500v2.h"
#include "avr910.h"
#include "butterfly.h"
#include "avr.h"
@@ -111,6 +112,7 @@
%token K_SCK
%token K_SIZE
%token K_STK500
+%token K_STK500V2
%token K_AVR910
%token K_BUTTERFLY
%token K_TYPE
@@ -296,6 +298,12 @@
}
} |
+ K_TYPE TKN_EQUAL K_STK500V2 {
+ {
+ stk500v2_initpgm(current_prog);
+ }
+ } |
+
K_TYPE TKN_EQUAL K_AVR910 {
{
avr910_initpgm(current_prog);
diff -urN avrdude/lexer.l avrdude-v2/lexer.l
--- avrdude/lexer.l 2004-12-21 17:52:45.000000000 -0800
+++ avrdude-v2/lexer.l 2005-01-30 16:14:26.000000000 -0800
@@ -155,6 +155,7 @@
serial { yylval=NULL; return K_SERIAL; }
size { yylval=NULL; return K_SIZE; }
stk500 { yylval=NULL; return K_STK500; }
+stk500v2 { yylval=NULL; return K_STK500V2; }
avr910 { yylval=NULL; return K_AVR910; }
butterfly { yylval=NULL; return K_BUTTERFLY; }
type { yylval=NULL; return K_TYPE; }
diff -urN avrdude/stk500v2.c avrdude-v2/stk500v2.c
--- avrdude/stk500v2.c 1969-12-31 16:00:00.000000000 -0800
+++ avrdude-v2/stk500v2.c 2005-01-31 00:53:46.000000000 -0800
@@ -0,0 +1,1149 @@
+/*
+ * avrdude - A Downloader/Uploader for AVR device programmers
+ * Copyright (C) 2002-2004 Brian S. Dean <address@hidden>
+ *
+ * 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: stk500v2.c,v 1.46 2004/12/22 01:52:45 bdean Exp $ */
+
+/*
+ * avrdude interface for Atmel STK500V2 programmer
+ *
+ * Note: most commands use the "universal command" feature of the
+ * programmer in a "pass through" mode, exceptions are "program
+ * enable", "paged read", and "paged write".
+ *
+ */
+
+#include "ac_cfg.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+
+#include "avr.h"
+#include "pgm.h"
+#include "stk500_private.h" // temp until all code converted
+#include "stk500v2_private.h"
+#include "serial.h"
+
+#define STK500V2_XTAL 7372800U
+
+extern int verbose;
+extern char * progname;
+extern int do_cycles;
+
+
+static int stk500v2_getparm(PROGRAMMER * pgm, unsigned parm, unsigned * value);
+static int stk500v2_setparm(PROGRAMMER * pgm, unsigned parm, unsigned value);
+static void stk500v2_print_parms1(PROGRAMMER * pgm, char * p);
+static int stk500v2_is_page_empty(unsigned int address, int page_size,
+ const unsigned char *buf);
+
+
+static int stk500v2_send(PROGRAMMER * pgm, char * data, size_t len)
+{
+ static unsigned char command_sequence = 0;
+ char buf[275 + 6]; // max MESSAGE_BODY of 275 bytes, 6 bytes
overhead
+ int i;
+
+ buf[0] = MESSAGE_START;
+ buf[1] = command_sequence++;
+ buf[2] = len & 0xff;
+ buf[3] = (len >> 8) & 0xff;
+ buf[4] = TOKEN;
+ memcpy(buf+5, data, len);
+
+ // calculate the XOR checksum
+ buf[5+len] = 0;
+ for (i=0;i<5+len;i++)
+ buf[5+len] ^= buf[i];
+
+ return serial_send(pgm->fd, buf, len+6);
+}
+
+
+static int stk500v2_drain(PROGRAMMER * pgm, int display)
+{
+ return serial_drain(pgm->fd, display);
+}
+
+
+static int stk500v2_recv(PROGRAMMER * pgm, char * data)
+{
+ char buf[275 + 6]; // max MESSAGE_BODY of 275 bytes, 6 bytes
overhead
+ int len;
+ int i;
+
+ // first sync to the next message-start header
+ do {
+ serial_recv(pgm->fd, buf, 1);
+ } while (buf[0] != MESSAGE_START);
+ // now read the rest of the fixed header
+ serial_recv(pgm->fd, buf+1, 4);
+ // calculate the length
+ len = buf[2] + (buf[3] << 8);
+ // and read the rest of the message, plus checksum
+ serial_recv(pgm->fd, buf+5, len+1);
+
+ // reverse calculate the XOR checksum
+ for (i=0;i<len+5;i++)
+ buf[5+len] ^= buf[i];
+
+ // if we didn't get zero back, the checksum is wrong
+ if (buf[5+len] != 0) {
+ fprintf(stderr,"%s: stk500v2_recv: message checksum failed\n",
+ progname);
+ stk500v2_drain(pgm, 0);
+ exit(1);
+ }
+
+ // copy the message over
+ memcpy(data, buf+5, len);
+
+ // return the message length
+ return len;
+}
+
+
+static int stk500v2_getsync(PROGRAMMER * pgm)
+{
+ unsigned char buf[32], resp[32];
+ int len;
+
+ /*
+ * get in sync */
+ buf[0] = CMD_SIGN_ON;
+ stk500v2_send(pgm, buf, 1);
+ len = stk500v2_recv(pgm, resp);
+ if (resp[0] != Resp_STK_INSYNC) {
+ fprintf(stderr,
+ "%s: stk500v2_getsync(): not in sync: resp=0x%02x\n",
+ progname, resp[0]);
+ stk500v2_drain(pgm, 0);
+ exit(1);
+ }
+
+ stk500v2_recv(pgm, resp, 1);
+ if (resp[0] != Resp_STK_OK) {
+ fprintf(stderr,
+ "%s: stk500v2_getsync(): can't communicate with device: "
+ "resp=0x%02x\n",
+ progname, resp[0]);
+ exit(1);
+ }
+
+ return 0;
+}
+
+
+/*
+ * transmit an AVR device command and return the results; 'cmd' and
+ * 'res' must point to at least a 4 byte data buffer
+ */
+static int stk500v2_cmd(PROGRAMMER * pgm, unsigned char cmd[4],
+ unsigned char res[4])
+{
+ unsigned char buf[32];
+
+ buf[0] = CMD_CHIP_ERASE_ISP;
+ buf[1] = cmd[0];
+ buf[2] = cmd[1];
+ buf[3] = cmd[2];
+ buf[4] = cmd[3];
+ buf[5] = Sync_CRC_EOP;
+
+ stk500v2_send(pgm, buf, 6);
+
+ stk500v2_recv(pgm, buf, 1);
+ if (buf[0] != Resp_STK_INSYNC) {
+ fprintf(stderr, "%s: stk500v2_cmd(): programmer is out of sync\n",
progname);
+ exit(1);
+ }
+
+ res[0] = cmd[1];
+ res[1] = cmd[2];
+ res[2] = cmd[3];
+ stk500v2_recv(pgm, &res[3], 1);
+
+ stk500v2_recv(pgm, buf, 1);
+ if (buf[0] != Resp_STK_OK) {
+ fprintf(stderr, "%s: stk500v2_cmd(): protocol error\n", progname);
+ exit(1);
+ }
+
+ return 0;
+}
+
+
+
+/*
+ * issue the 'chip erase' command to the AVR device
+ */
+static int stk500v2_chip_erase(PROGRAMMER * pgm, AVRPART * p)
+{
+ unsigned char cmd[4];
+ unsigned char res[4];
+
+ if (p->op[AVR_OP_CHIP_ERASE] == NULL) {
+ fprintf(stderr, "chip erase instruction not defined for part \"%s\"\n",
+ p->desc);
+ return -1;
+ }
+
+ pgm->pgm_led(pgm, ON);
+
+ memset(cmd, 0, sizeof(cmd));
+
+ avr_set_bits(p->op[AVR_OP_CHIP_ERASE], cmd);
+ pgm->cmd(pgm, cmd, res);
+ usleep(p->chip_erase_delay);
+ pgm->initialize(pgm, p);
+
+ pgm->pgm_led(pgm, OFF);
+
+ return 0;
+}
+
+/*
+ * issue the 'program enable' command to the AVR device
+ */
+static int stk500v2_program_enable(PROGRAMMER * pgm, AVRPART * p)
+{
+ int len;
+ unsigned char buf[16];
+
+ buf[0] = CMD_SIGN_ON;
+ stk500v2_send(pgm, buf, 1);
+ len = stk500v2_recv(pgm, buf);
+
+ if (buf[0] != CMD_SIGN_ON) {
+ fprintf(stderr, "%s: stk500v2_program_enable(): can't sign in\n",
+ progname);
+ return -1;
+ }
+
+ if (buf[1] == STATUS_CMD_OK) {
+ return 0;
+ } else {
+ fprintf(stderr,
+ "%s: stk500v2_program_enable(): failed to enter programming mode,
%d\n",
+ progname,buf[1]);
+ return -1;
+ }
+
+ return -1;
+}
+
+
+
+static int stk500v2_set_extended_parms(PROGRAMMER * pgm, int n,
+ unsigned char * cmd)
+{
+ unsigned char buf[16];
+ int tries=0;
+ int i;
+
+ retry:
+
+ tries++;
+
+ buf[0] = Cmnd_STK_SET_DEVICE_EXT;
+ for (i=0; i<n; i++) {
+ buf[1+i] = cmd[i];
+ }
+ i++;
+ buf[i] = Sync_CRC_EOP;
+
+ stk500v2_send(pgm, buf, i+1);
+ stk500v2_recv(pgm, buf, 1);
+ if (buf[0] == Resp_STK_NOSYNC) {
+ if (tries > 33) {
+ fprintf(stderr, "%s: stk500v2_set_extended_parms(): can't get into
sync\n",
+ progname);
+ return -1;
+ }
+ stk500v2_getsync(pgm);
+ goto retry;
+ }
+ else if (buf[0] != Resp_STK_INSYNC) {
+ fprintf(stderr,
+ "%s: stk500v2_set_extended_parms(): protocol error, "
+ "expect=0x%02x, resp=0x%02x\n",
+ progname, Resp_STK_INSYNC, buf[0]);
+ return -1;
+ }
+
+ stk500v2_recv(pgm, buf, 1);
+ if (buf[0] == Resp_STK_OK) {
+ return 0;
+ }
+ else if (buf[0] == Resp_STK_NODEVICE) {
+ fprintf(stderr, "%s: stk500v2_set_extended_parms(): no device\n",
+ progname);
+ return -1;
+ }
+
+ if(buf[0] == Resp_STK_FAILED)
+ {
+ fprintf(stderr,
+ "%s: stk500v2_set_extended_parms(): failed to set extended "
+ "device programming parameters\n",
+ progname);
+ return -1;
+ }
+
+
+ fprintf(stderr, "%s: stk500v2_set_extended_parms(): unknown
response=0x%02x\n",
+ progname, buf[0]);
+
+ return -1;
+}
+
+
+/*
+ * initialize the AVR device and prepare it to accept commands
+ */
+static int stk500v2_initialize(PROGRAMMER * pgm, AVRPART * p)
+{
+ unsigned char buf[32];
+ AVRMEM * m;
+ int tries;
+ unsigned maj, min;
+ int rc;
+ int n_extparms = 3;
+
+ stk500v2_getparm(pgm, PARAM_SW_MAJOR, &maj);
+ stk500v2_getparm(pgm, PARAM_SW_MINOR, &min);
+
+ if ((maj > 1) || ((maj == 1) && (min > 10)))
+ n_extparms = 4;
+
+ tries = 0;
+
+ retry:
+ tries++;
+
+ memset(buf, 0, sizeof(buf));
+
+ /*
+ * set device programming parameters
+ */
+ buf[0] = Cmnd_STK_SET_DEVICE;
+
+ buf[1] = p->stk500_devcode;
+ buf[2] = 0; /* device revision */
+
+ if ((p->flags & AVRPART_SERIALOK) && (p->flags & AVRPART_PARALLELOK))
+ buf[3] = 0; /* device supports parallel and serial programming */
+ else
+ buf[3] = 1; /* device supports parallel only */
+
+ if (p->flags & AVRPART_PARALLELOK) {
+ if (p->flags & AVRPART_PSEUDOPARALLEL) {
+ buf[4] = 0; /* pseudo parallel interface */
+ n_extparms = 0;
+ }
+ else {
+ buf[4] = 1; /* full parallel interface */
+ }
+ }
+
+#if 0
+ fprintf(stderr, "%s: stk500v2_initialize(): n_extparms = %d\n",
+ progname, n_extparms);
+#endif
+
+ buf[5] = 1; /* polling supported - XXX need this in config file */
+ buf[6] = 1; /* programming is self-timed - XXX need in config file */
+
+ m = avr_locate_mem(p, "lock");
+ if (m)
+ buf[7] = m->size;
+ else
+ buf[7] = 0;
+
+ /*
+ * number of fuse bytes
+ */
+ buf[8] = 0;
+ m = avr_locate_mem(p, "fuse");
+ if (m)
+ buf[8] += m->size;
+ m = avr_locate_mem(p, "lfuse");
+ if (m)
+ buf[8] += m->size;
+ m = avr_locate_mem(p, "hfuse");
+ if (m)
+ buf[8] += m->size;
+ m = avr_locate_mem(p, "efuse");
+ if (m)
+ buf[8] += m->size;
+
+ m = avr_locate_mem(p, "flash");
+ if (m) {
+ buf[9] = m->readback[0];
+ buf[10] = m->readback[1];
+ if (m->paged) {
+ buf[13] = (m->page_size >> 8) & 0x00ff;
+ buf[14] = m->page_size & 0x00ff;
+ }
+ buf[17] = (m->size >> 24) & 0xff;
+ buf[18] = (m->size >> 16) & 0xff;
+ buf[19] = (m->size >> 8) & 0xff;
+ buf[20] = m->size & 0xff;
+ }
+ else {
+ buf[9] = 0xff;
+ buf[10] = 0xff;
+ buf[13] = 0;
+ buf[14] = 0;
+ buf[17] = 0;
+ buf[18] = 0;
+ buf[19] = 0;
+ buf[20] = 0;
+ }
+
+ m = avr_locate_mem(p, "eeprom");
+ if (m) {
+ buf[11] = m->readback[0];
+ buf[12] = m->readback[1];
+ buf[15] = (m->size >> 8) & 0x00ff;
+ buf[16] = m->size & 0x00ff;
+ }
+ else {
+ buf[11] = 0xff;
+ buf[12] = 0xff;
+ buf[15] = 0;
+ buf[16] = 0;
+ }
+
+ buf[21] = Sync_CRC_EOP;
+
+ stk500v2_send(pgm, buf, 22);
+ stk500v2_recv(pgm, buf, 1);
+ if (buf[0] == Resp_STK_NOSYNC) {
+ fprintf(stderr,
+ "%s: stk500v2_initialize(): programmer not in sync,
resp=0x%02x\n",
+ progname, buf[0]);
+ if (tries > 33)
+ return -1;
+ stk500v2_getsync(pgm);
+ goto retry;
+ return -1;
+ }
+ else if (buf[0] != Resp_STK_INSYNC) {
+ fprintf(stderr,
+ "%s: stk500v2_initialize(): (a) protocol error, "
+ "expect=0x%02x, resp=0x%02x\n",
+ progname, Resp_STK_INSYNC, buf[0]);
+ return -1;
+ }
+
+ stk500v2_recv(pgm, buf, 1);
+ if (buf[0] != Resp_STK_OK) {
+ fprintf(stderr,
+ "%s: stk500v2_initialize(): (b) protocol error, "
+ "expect=0x%02x, resp=0x%02x\n",
+ progname, Resp_STK_OK, buf[0]);
+ return -1;
+ }
+
+ if (n_extparms) {
+ if ((p->pagel == 0) || (p->bs2 == 0)) {
+ fprintf(stderr,
+ "%s: please define PAGEL and BS2 signals in the configuration "
+ "file for part %s\n",
+ progname, p->desc);
+ }
+ else {
+ buf[0] = n_extparms+1;
+
+ /*
+ * m is currently pointing to eeprom memory if the part has it
+ */
+ if (m)
+ buf[1] = m->page_size;
+ else
+ buf[1] = 0;
+
+ buf[2] = p->pagel;
+ buf[3] = p->bs2;
+
+ if (n_extparms == 4) {
+ if (p->reset_disposition == RESET_DEDICATED)
+ buf[4] = 0;
+ else
+ buf[4] = 1;
+ }
+
+ rc = stk500v2_set_extended_parms(pgm, n_extparms+1, buf);
+ if (rc) {
+ fprintf(stderr, "%s: stk500v2_initialize(): failed\n", progname);
+ exit(1);
+ }
+ }
+ }
+
+ return pgm->program_enable(pgm, p);
+}
+
+
+static void stk500v2_disable(PROGRAMMER * pgm)
+{
+ unsigned char buf[16];
+ int tries=0;
+
+ retry:
+
+ tries++;
+
+ buf[0] = Cmnd_STK_LEAVE_PROGMODE;
+ buf[1] = Sync_CRC_EOP;
+
+ stk500v2_send(pgm, buf, 2);
+ stk500v2_recv(pgm, buf, 1);
+ if (buf[0] == Resp_STK_NOSYNC) {
+ if (tries > 33) {
+ fprintf(stderr, "%s: stk500v2_disable(): can't get into sync\n",
+ progname);
+ return;
+ }
+ stk500v2_getsync(pgm);
+ goto retry;
+ }
+ else if (buf[0] != Resp_STK_INSYNC) {
+ fprintf(stderr,
+ "%s: stk500v2_disable(): protocol error, expect=0x%02x, "
+ "resp=0x%02x\n",
+ progname, Resp_STK_INSYNC, buf[0]);
+ return;
+ }
+
+ stk500v2_recv(pgm, buf, 1);
+ if (buf[0] == Resp_STK_OK) {
+ return;
+ }
+ else if (buf[0] == Resp_STK_NODEVICE) {
+ fprintf(stderr, "%s: stk500v2_disable(): no device\n",
+ progname);
+ return;
+ }
+
+ fprintf(stderr, "%s: stk500v2_disable(): unknown response=0x%02x\n",
+ progname, buf[0]);
+
+ return;
+}
+
+static void stk500v2_enable(PROGRAMMER * pgm)
+{
+ return;
+}
+
+
+static int stk500v2_open(PROGRAMMER * pgm, char * port)
+{
+ strcpy(pgm->port, port);
+ if (pgm->baudrate)
+ pgm->fd = serial_open(port, pgm->baudrate);
+ else
+ pgm->fd = serial_open(port, 115200);
+
+ /*
+ * drain any extraneous input
+ */
+ stk500v2_drain(pgm, 0);
+
+ stk500v2_getsync(pgm);
+
+ stk500v2_drain(pgm, 0);
+
+ return 0;
+}
+
+
+static void stk500v2_close(PROGRAMMER * pgm)
+{
+ serial_close(pgm->fd);
+ pgm->fd = -1;
+}
+
+
+static int stk500v2_loadaddr(PROGRAMMER * pgm, unsigned int addr)
+{
+ unsigned char buf[16];
+ int tries;
+
+ tries = 0;
+ retry:
+ tries++;
+ buf[0] = Cmnd_STK_LOAD_ADDRESS;
+ buf[1] = addr & 0xff;
+ buf[2] = (addr >> 8) & 0xff;
+ buf[3] = Sync_CRC_EOP;
+
+ stk500v2_send(pgm, buf, 4);
+
+ stk500v2_recv(pgm, buf, 1);
+ if (buf[0] == Resp_STK_NOSYNC) {
+ if (tries > 33) {
+ fprintf(stderr, "%s: stk500v2_loadaddr(): can't get into sync\n",
+ progname);
+ return -1;
+ }
+ stk500v2_getsync(pgm);
+ goto retry;
+ }
+ else if (buf[0] != Resp_STK_INSYNC) {
+ fprintf(stderr,
+ "%s: stk500v2_loadaddr(): (a) protocol error, "
+ "expect=0x%02x, resp=0x%02x\n",
+ progname, Resp_STK_INSYNC, buf[0]);
+ return -1;
+ }
+
+ stk500v2_recv(pgm, buf, 1);
+ if (buf[0] == Resp_STK_OK) {
+ return 0;
+ }
+
+ fprintf(stderr,
+ "%s: loadaddr(): (b) protocol error, "
+ "expect=0x%02x, resp=0x%02x\n",
+ progname, Resp_STK_INSYNC, buf[0]);
+
+ return -1;
+}
+
+
+static int stk500v2_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
+ int page_size, int n_bytes)
+{
+ unsigned char buf[16];
+ int memtype;
+ unsigned int addr;
+ int a_div;
+ int block_size;
+ int tries;
+ unsigned int n;
+ int flash;
+
+ if (page_size == 0) {
+ page_size = 128;
+ }
+
+ if (strcmp(m->desc, "flash") == 0) {
+ memtype = 'F';
+ flash = 1;
+ }
+ else if (strcmp(m->desc, "eeprom") == 0) {
+ memtype = 'E';
+ flash = 0;
+ }
+ else {
+ return -2;
+ }
+
+ if ((m->op[AVR_OP_LOADPAGE_LO]) || (m->op[AVR_OP_READ_LO]))
+ a_div = 2;
+ else
+ a_div = 1;
+
+ if (n_bytes > m->size) {
+ n_bytes = m->size;
+ n = m->size;
+ }
+ else {
+ if ((n_bytes % page_size) != 0) {
+ n = n_bytes + page_size - (n_bytes % page_size);
+ }
+ else {
+ n = n_bytes;
+ }
+ }
+
+#if 0
+ fprintf(stderr,
+ "n_bytes = %d\n"
+ "n = %u\n"
+ "a_div = %d\n"
+ "page_size = %d\n",
+ n_bytes, n, a_div, page_size);
+#endif
+
+ for (addr = 0; addr < n; addr += page_size) {
+ report_progress (addr, n_bytes, NULL);
+
+ if (addr + page_size > n_bytes) {
+ block_size = n_bytes % page_size;
+ }
+ else {
+ block_size = page_size;
+ }
+
+ /* Only skip on empty page if programming flash. */
+ if (flash) {
+ if (stk500v2_is_page_empty(addr, block_size, m->buf)) {
+ continue;
+ }
+ }
+ tries = 0;
+ retry:
+ tries++;
+ stk500v2_loadaddr(pgm, addr/a_div);
+ buf[0] = Cmnd_STK_PROG_PAGE;
+ buf[1] = (block_size >> 8) & 0xff;
+ buf[2] = block_size & 0xff;
+ buf[3] = memtype;
+ stk500v2_send(pgm, buf, 4);
+
+ stk500v2_send(pgm, &m->buf[addr], block_size);
+
+ buf[0] = Sync_CRC_EOP;
+ stk500v2_send(pgm, buf, 1);
+
+ stk500v2_recv(pgm, buf, 1);
+ if (buf[0] == Resp_STK_NOSYNC) {
+ if (tries > 33) {
+ fprintf(stderr, "\n%s: stk500v2_paged_write(): can't get into sync\n",
+ progname);
+ return -3;
+ }
+ stk500v2_getsync(pgm);
+ goto retry;
+ }
+ else if (buf[0] != Resp_STK_INSYNC) {
+ fprintf(stderr,
+ "\n%s: stk500v2_paged_write(): (a) protocol error, "
+ "expect=0x%02x, resp=0x%02x\n",
+ progname, Resp_STK_INSYNC, buf[0]);
+ return -4;
+ }
+
+ stk500v2_recv(pgm, buf, 1);
+ if (buf[0] != Resp_STK_OK) {
+ fprintf(stderr,
+ "\n%s: stk500v2_paged_write(): (a) protocol error, "
+ "expect=0x%02x, resp=0x%02x\n",
+ progname, Resp_STK_INSYNC, buf[0]);
+ return -5;
+ }
+ }
+
+ return n_bytes;
+}
+
+static int stk500v2_is_page_empty(unsigned int address, int page_size,
+ const unsigned char *buf)
+{
+ int i;
+ for(i = 0; i < page_size; i++) {
+ if(buf[address + i] != 0xFF) {
+ /* Page is not empty. */
+ return(0);
+ }
+ }
+
+ /* Page is empty. */
+ return(1);
+}
+
+static int stk500v2_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
+ int page_size, int n_bytes)
+{
+ unsigned char buf[16];
+ int memtype;
+ unsigned int addr;
+ int a_div;
+ int tries;
+ unsigned int n;
+ int block_size;
+
+ if (strcmp(m->desc, "flash") == 0) {
+ memtype = 'F';
+ }
+ else if (strcmp(m->desc, "eeprom") == 0) {
+ memtype = 'E';
+ }
+ else {
+ return -2;
+ }
+
+ if ((m->op[AVR_OP_LOADPAGE_LO]) || (m->op[AVR_OP_READ_LO]))
+ a_div = 2;
+ else
+ a_div = 1;
+
+ if (n_bytes > m->size) {
+ n_bytes = m->size;
+ n = m->size;
+ }
+ else {
+ if ((n_bytes % page_size) != 0) {
+ n = n_bytes + page_size - (n_bytes % page_size);
+ }
+ else {
+ n = n_bytes;
+ }
+ }
+
+ for (addr = 0; addr < n; addr += page_size) {
+ report_progress (addr, n_bytes, NULL);
+
+ if (addr + page_size > n_bytes) {
+ block_size = n_bytes % page_size;
+ }
+ else {
+ block_size = page_size;
+ }
+
+ tries = 0;
+ retry:
+ tries++;
+ stk500v2_loadaddr(pgm, addr/a_div);
+ buf[0] = Cmnd_STK_READ_PAGE;
+ buf[1] = (block_size >> 8) & 0xff;
+ buf[2] = block_size & 0xff;
+ buf[3] = memtype;
+ buf[4] = Sync_CRC_EOP;
+ stk500v2_send(pgm, buf, 5);
+
+ stk500v2_recv(pgm, buf, 1);
+ if (buf[0] == Resp_STK_NOSYNC) {
+ if (tries > 33) {
+ fprintf(stderr, "\n%s: stk500v2_paged_load(): can't get into sync\n",
+ progname);
+ return -3;
+ }
+ stk500v2_getsync(pgm);
+ goto retry;
+ }
+ else if (buf[0] != Resp_STK_INSYNC) {
+ fprintf(stderr,
+ "\n%s: stk500v2_paged_load(): (a) protocol error, "
+ "expect=0x%02x, resp=0x%02x\n",
+ progname, Resp_STK_INSYNC, buf[0]);
+ return -4;
+ }
+
+ stk500v2_recv(pgm, &m->buf[addr], block_size);
+
+ stk500v2_recv(pgm, buf, 1);
+ if (buf[0] != Resp_STK_OK) {
+ fprintf(stderr,
+ "\n%s: stk500v2_paged_load(): (a) protocol error, "
+ "expect=0x%02x, resp=0x%02x\n",
+ progname, Resp_STK_INSYNC, buf[0]);
+ return -5;
+ }
+ }
+
+ return n_bytes;
+}
+
+
+static int stk500v2_set_vtarget(PROGRAMMER * pgm, double v)
+{
+ unsigned uaref, utarg;
+
+ utarg = (unsigned)((v + 0.049) * 10);
+
+ if (stk500v2_getparm(pgm, Parm_STK_VADJUST, &uaref) != 0) {
+ fprintf(stderr,
+ "%s: stk500v2_set_vtarget(): cannot obtain V[aref]\n",
+ progname);
+ return -1;
+ }
+
+ if (uaref > utarg) {
+ fprintf(stderr,
+ "%s: stk500v2_set_vtarget(): reducing V[aref] from %.1f to %.1f\n",
+ progname, uaref / 10.0, v);
+ if (stk500v2_setparm(pgm, Parm_STK_VADJUST, utarg)
+ != 0)
+ return -1;
+ }
+ return stk500v2_setparm(pgm, Parm_STK_VTARGET, utarg);
+}
+
+
+static int stk500v2_set_varef(PROGRAMMER * pgm, double v)
+{
+ unsigned uaref, utarg;
+
+ uaref = (unsigned)((v + 0.049) * 10);
+
+ if (stk500v2_getparm(pgm, Parm_STK_VTARGET, &utarg) != 0) {
+ fprintf(stderr,
+ "%s: stk500v2_set_varef(): cannot obtain V[target]\n",
+ progname);
+ return -1;
+ }
+
+ if (uaref > utarg) {
+ fprintf(stderr,
+ "%s: stk500v2_set_varef(): V[aref] must not be greater than "
+ "V[target] = %.1f\n",
+ progname, utarg / 10.0);
+ return -1;
+ }
+ return stk500v2_setparm(pgm, Parm_STK_VADJUST, uaref);
+}
+
+
+static int stk500v2_set_fosc(PROGRAMMER * pgm, double v)
+{
+ unsigned prescale, cmatch, fosc;
+ static unsigned ps[] = {
+ 1, 8, 32, 64, 128, 256, 1024
+ };
+ int idx, rc;
+
+ prescale = cmatch = 0;
+ if (v > 0.0) {
+ if (v > STK500V2_XTAL / 2) {
+ const char *unit;
+ if (v > 1e6) {
+ v /= 1e6;
+ unit = "MHz";
+ } else if (v > 1e3) {
+ v /= 1e3;
+ unit = "kHz";
+ } else
+ unit = "Hz";
+ fprintf(stderr,
+ "%s: stk500v2_set_fosc(): f = %.3f %s too high, using %.3f MHz\n",
+ progname, v, unit, STK500V2_XTAL / 2e6);
+ fosc = STK500V2_XTAL / 2;
+ } else
+ fosc = (unsigned)v;
+
+ for (idx = 0; idx < sizeof(ps) / sizeof(ps[0]); idx++) {
+ if (fosc >= STK500V2_XTAL / (256 * ps[idx] * 2)) {
+ /* this prescaler value can handle our frequency */
+ prescale = idx + 1;
+ cmatch = (unsigned)(STK500V2_XTAL / (2 * fosc * ps[idx])) - 1;
+ break;
+ }
+ }
+ if (idx == sizeof(ps) / sizeof(ps[0])) {
+ fprintf(stderr, "%s: stk500v2_set_fosc(): f = %u Hz too low, %u Hz
min\n",
+ progname, fosc, STK500V2_XTAL / (256 * 1024 * 2));
+ return -1;
+ }
+ }
+
+ if ((rc = stk500v2_setparm(pgm, Parm_STK_OSC_PSCALE, prescale)) != 0
+ || (rc = stk500v2_setparm(pgm, Parm_STK_OSC_CMATCH, cmatch)) != 0)
+ return rc;
+
+ return 0;
+}
+
+
+/* This code assumes that each count of the SCK duration parameter
+ represents 8/f, where f is the clock frequency of the STK500V2 master
+ processors (not the target). This number comes from Atmel
+ application note AVR061. It appears that the STK500V2 bit bangs SCK.
+ For small duration values, the actual SCK width is larger than
+ expected. As the duration value increases, the SCK width error
+ diminishes. */
+static int stk500v2_set_sck_period(PROGRAMMER * pgm, double v)
+{
+ int dur;
+ double min, max;
+
+ min = 8.0 / STK500V2_XTAL;
+ max = 255 * min;
+ dur = v / min + 0.5;
+
+ if (v < min) {
+ dur = 1;
+ fprintf(stderr,
+ "%s: stk500v2_set_sck_period(): p = %.1f us too small, using %.1f
us\n",
+ progname, v / 1e-6, dur * min / 1e-6);
+ } else if (v > max) {
+ dur = 255;
+ fprintf(stderr,
+ "%s: stk500v2_set_sck_period(): p = %.1f us too large, using %.1f
us\n",
+ progname, v / 1e-6, dur * min / 1e-6);
+ }
+
+ return stk500v2_setparm(pgm, Parm_STK_SCK_DURATION, dur);
+}
+
+
+static int stk500v2_getparm(PROGRAMMER * pgm, unsigned char parm, unsigned
char * value)
+{
+ unsigned char buf[16];
+ int len;
+ unsigned v;
+
+ buf[0] = CMD_GET_PARAMETER;
+ buf[1] = parm;
+
+ stk500v2_send(pgm, buf, 2);
+ len = stk500v2_recv(pgm, buf);
+ if (buf[1] != STATUS_CMD_OK) {
+ fprintf(stderr, "\n%s: stk500v2_getparm(): can't get parameter\n",
+ progname);
+ return -1;
+ }
+
+ *value = buf[2];
+
+ return 0;
+}
+
+
+static int stk500v2_setparm(PROGRAMMER * pgm, unsigned char parm, unsigned
char value)
+{
+ unsigned char buf[16];
+ int len;
+
+ buf[0] = CMD_SET_PARAMETER;
+ buf[1] = parm;
+ buf[2] = value;
+
+ stk500v2_send(pgm, buf, 3);
+ len = stk500v2_recv(pgm, buf);
+
+ if (buf[1] != STATUS_CMD_OK) {
+ fprintf(stderr, "\n%s: stk500v2_setparm(): can't set parameter\n",
+ progname);
+ return -1;
+ }
+
+ return 0;
+}
+
+
+static void stk500v2_display(PROGRAMMER * pgm, char * p)
+{
+ unsigned maj, min, hdw, topcard;
+ const char *topcard_name;
+
+ stk500v2_getparm(pgm, PARAM_HW_VER, &hdw);
+ stk500v2_getparm(pgm, PARAM_SW_MAJOR, &maj);
+ stk500v2_getparm(pgm, PARAM_SW_MINOR, &min);
+ stk500v2_getparm(pgm, PARAM_TOPCARD_DETECT, &topcard);
+
+ fprintf(stderr, "%sHardware Version: %d\n", p, hdw);
+ fprintf(stderr, "%sFirmware Version: %d.%d\n", p, maj, min);
+
+ if (1) { // should check to see if it's a stk500 first
+ switch (topcard) {
+ case 0xAA: topcard_name = "STK501", break;
+ case 0x55: topcard_name = "STK502", break;
+ case 0xFA: topcard_name = "STK503", break;
+ case 0xEE: topcard_name = "STK504", break;
+ case 0xE4: topcard_name = "STK505", break;
+ case 0xDD: topcard_name = "STK520", break;
+ default: topcard_name = "Unknown", break;
+ }
+ fprintf(stderr, "%sTopcard : %s\n", p, n);
+ }
+ stk500v2_print_parms1(pgm, p);
+
+ return;
+}
+
+
+static void stk500v2_print_parms1(PROGRAMMER * pgm, char * p)
+{
+ unsigned vtarget, vadjust, osc_pscale, osc_cmatch, sck_duration;
+
+ stk500v2_getparm(pgm, PARAM_VTARGET, &vtarget);
+ stk500v2_getparm(pgm, PARAM_VADJUST, &vadjust);
+ stk500v2_getparm(pgm, PARAM_OSC_PSCALE, &osc_pscale);
+ stk500v2_getparm(pgm, PARAM_OSC_CMATCH, &osc_cmatch);
+ stk500v2_getparm(pgm, PARAM_SCK_DURATION, &sck_duration);
+
+ fprintf(stderr, "%sVtarget : %.1f V\n", p, vtarget / 10.0);
+ fprintf(stderr, "%sVaref : %.1f V\n", p, vadjust / 10.0);
+ fprintf(stderr, "%sOscillator : ", p);
+ if (osc_pscale == 0)
+ fprintf(stderr, "Off\n");
+ else {
+ int prescale = 1;
+ double f = STK500V2_XTAL / 2;
+ const char *unit;
+
+ switch (osc_pscale) {
+ case 2: prescale = 8; break;
+ case 3: prescale = 32; break;
+ case 4: prescale = 64; break;
+ case 5: prescale = 128; break;
+ case 6: prescale = 256; break;
+ case 7: prescale = 1024; break;
+ }
+ f /= prescale;
+ f /= (osc_cmatch + 1);
+ if (f > 1e6) {
+ f /= 1e6;
+ unit = "MHz";
+ } else if (f > 1e3) {
+ f /= 1000;
+ unit = "kHz";
+ } else
+ unit = "Hz";
+ fprintf(stderr, "%.3f %s\n", f, unit);
+ }
+ fprintf(stderr, "%sSCK period : %.1f us\n", p,
+ sck_duration * 8.0e6 / STK500V2_XTAL + 0.05);
+
+ return;
+}
+
+
+static void stk500v2_print_parms(PROGRAMMER * pgm)
+{
+ stk500v2_print_parms1(pgm, "");
+}
+
+
+void stk500v2_initpgm(PROGRAMMER * pgm)
+{
+ strcpy(pgm->type, "STK500V2");
+
+ /*
+ * mandatory functions
+ */
+ pgm->initialize = stk500v2_initialize;
+ pgm->display = stk500v2_display;
+ pgm->enable = stk500v2_enable;
+ pgm->disable = stk500v2_disable;
+ pgm->program_enable = stk500v2_program_enable;
+ pgm->chip_erase = stk500v2_chip_erase;
+ pgm->cmd = stk500v2_cmd;
+ pgm->open = stk500v2_open;
+ pgm->close = stk500v2_close;
+
+ /*
+ * optional functions
+ */
+ pgm->paged_write = stk500v2_paged_write;
+ pgm->paged_load = stk500v2_paged_load;
+ pgm->print_parms = stk500v2_print_parms;
+ pgm->set_vtarget = stk500v2_set_vtarget;
+ pgm->set_varef = stk500v2_set_varef;
+ pgm->set_fosc = stk500v2_set_fosc;
+ pgm->set_sck_period = stk500v2_set_sck_period;
+ pgm->page_size = 256;
+}
diff -urN avrdude/stk500v2.h avrdude-v2/stk500v2.h
--- avrdude/stk500v2.h 1969-12-31 16:00:00.000000000 -0800
+++ avrdude-v2/stk500v2.h 2005-01-30 16:16:49.000000000 -0800
@@ -0,0 +1,29 @@
+/*
+ * avrdude - A Downloader/Uploader for AVR device programmers
+ * Copyright (C) 2002-2004 Brian S. Dean <address@hidden>
+ *
+ * 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: stk500.h,v 1.9 2004/12/22 01:52:45 bdean Exp $ */
+
+#ifndef __stk500v2_h__
+#define __stk500v2_h__
+
+void stk500v2_initpgm (PROGRAMMER * pgm);
+
+#endif
+
+
diff -urN avrdude/stk500v2_private.h avrdude-v2/stk500v2_private.h
--- avrdude/stk500v2_private.h 1969-12-31 16:00:00.000000000 -0800
+++ avrdude-v2/stk500v2_private.h 2005-01-30 17:14:25.000000000 -0800
@@ -0,0 +1,134 @@
+//**** ATMEL AVR - A P P L I C A T I O N N O T E ************************
+//*
+//* Title: AVR068 - STK500 Communication Protocol
+//* Filename: command.h
+//* Version: 1.0
+//* Last updated: 10.01.2005
+//*
+//* Support E-mail: address@hidden
+//*
+//**************************************************************************
+
+// *****************[ STK message constants ]***************************
+
+#define MESSAGE_START 0x1B //= ESC = 27 decimal
+#define TOKEN 0x0E
+
+// *****************[ STK general command constants ]**************************
+
+#define CMD_SIGN_ON 0x01
+#define CMD_SET_PARAMETER 0x02
+#define CMD_GET_PARAMETER 0x03
+#define CMD_SET_DEVICE_PARAMETERS 0x04
+#define CMD_OSCCAL 0x05
+#define CMD_LOAD_ADDRESS 0x06
+#define CMD_FIRMWARE_UPGRADE 0x07
+
+
+// *****************[ STK ISP command constants ]******************************
+
+#define CMD_ENTER_PROGMODE_ISP 0x10
+#define CMD_LEAVE_PROGMODE_ISP 0x11
+#define CMD_CHIP_ERASE_ISP 0x12
+#define CMD_PROGRAM_FLASH_ISP 0x13
+#define CMD_READ_FLASH_ISP 0x14
+#define CMD_PROGRAM_EEPROM_ISP 0x15
+#define CMD_READ_EEPROM_ISP 0x16
+#define CMD_PROGRAM_FUSE_ISP 0x17
+#define CMD_READ_FUSE_ISP 0x18
+#define CMD_PROGRAM_LOCK_ISP 0x19
+#define CMD_READ_LOCK_ISP 0x1A
+#define CMD_READ_SIGNATURE_ISP 0x1B
+#define CMD_READ_OSCCAL_ISP 0x1C
+#define CMD_SPI_MULTI 0x1D
+
+// *****************[ STK PP command constants ]*******************************
+
+#define CMD_ENTER_PROGMODE_PP 0x20
+#define CMD_LEAVE_PROGMODE_PP 0x21
+#define CMD_CHIP_ERASE_PP 0x22
+#define CMD_PROGRAM_FLASH_PP 0x23
+#define CMD_READ_FLASH_PP 0x24
+#define CMD_PROGRAM_EEPROM_PP 0x25
+#define CMD_READ_EEPROM_PP 0x26
+#define CMD_PROGRAM_FUSE_PP 0x27
+#define CMD_READ_FUSE_PP 0x28
+#define CMD_PROGRAM_LOCK_PP 0x29
+#define CMD_READ_LOCK_PP 0x2A
+#define CMD_READ_SIGNATURE_PP 0x2B
+#define CMD_READ_OSCCAL_PP 0x2C
+
+#define CMD_SET_CONTROL_STACK 0x2D
+
+// *****************[ STK HVSP command constants ]*****************************
+
+#define CMD_ENTER_PROGMODE_HVSP 0x30
+#define CMD_LEAVE_PROGMODE_HVSP 0x31
+#define CMD_CHIP_ERASE_HVSP 0x32
+#define CMD_PROGRAM_FLASH_HVSP 0x33
+#define CMD_READ_FLASH_HVSP 0x34
+#define CMD_PROGRAM_EEPROM_HVSP 0x35
+#define CMD_READ_EEPROM_HVSP 0x36
+#define CMD_PROGRAM_FUSE_HVSP 0x37
+#define CMD_READ_FUSE_HVSP 0x38
+#define CMD_PROGRAM_LOCK_HVSP 0x39
+#define CMD_READ_LOCK_HVSP 0x3A
+#define CMD_READ_SIGNATURE_HVSP 0x3B
+#define CMD_READ_OSCCAL_HVSP 0x3C
+
+// *****************[ STK test command constants ]***************************
+
+#define CMD_ENTER_TESTMODE 0x60
+#define CMD_LEAVE_TESTMODE 0x61
+#define CMD_CHIP_WRITE 0x62
+#define CMD_PROGRAM_FLASH_PARTIAL 0x63
+#define CMD_PROGRAM_EEPROM_PARTIAL 0x64
+#define CMD_PROGRAM_SIGNATURE_ROW 0x65
+#define CMD_READ_FLASH_MARGIN 0x66
+#define CMD_READ_EEPROM_MARGIN 0x67
+#define CMD_READ_SIGNATURE_ROW_MARGIN 0x68
+#define CMD_PROGRAM_TEST_FUSE 0x69
+#define CMD_READ_TEST_FUSE 0x6A
+#define CMD_PROGRAM_HIDDEN_FUSE_LOW 0x6B
+#define CMD_READ_HIDDEN_FUSE_LOW 0x6C
+#define CMD_PROGRAM_HIDDEN_FUSE_HIGH 0x6D
+#define CMD_READ_HIDDEN_FUSE_HIGH 0x6E
+#define CMD_PROGRAM_HIDDEN_FUSE_EXT 0x6F
+#define CMD_READ_HIDDEN_FUSE_EXT 0x70
+
+// *****************[ STK status constants ]***************************
+
+// Success
+#define STATUS_CMD_OK 0x00
+
+// Warnings
+#define STATUS_CMD_TOUT 0x80
+#define STATUS_RDY_BSY_TOUT 0x81
+#define STATUS_SET_PARAM_MISSING 0x82
+
+// Errors
+#define STATUS_CMD_FAILED 0xC0
+#define STATUS_CKSUM_ERROR 0xC1
+#define STATUS_CMD_UNKNOWN 0xC9
+
+// *****************[ STK parameter constants ]***************************
+#define PARAM_BUILD_NUMBER_LOW 0x80
+#define PARAM_BUILD_NUMBER_HIGH 0x81
+#define PARAM_HW_VER 0x90
+#define PARAM_SW_MAJOR 0x91
+#define PARAM_SW_MINOR 0x92
+#define PARAM_VTARGET 0x94
+#define PARAM_VADJUST 0x95
+#define PARAM_OSC_PSCALE 0x96
+#define PARAM_OSC_CMATCH 0x97
+#define PARAM_SCK_DURATION 0x98
+#define PARAM_TOPCARD_DETECT 0x9A
+#define PARAM_STATUS 0x9C
+#define PARAM_DATA 0x9D
+#define PARAM_RESET_POLARITY 0x9E
+#define PARAM_CONTROLLER_INIT 0x9F
+
+// *****************[ STK answer constants ]***************************
+
+#define ANSWER_CKSUM_ERROR 0xB0
+
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [avrdude-dev] Partial stk500v2 code,
Erik Walthinsen <=