From 85cb696790788454fa1543a1769a328138aeb446 Mon Sep 17 00:00:00 2001 From: Joerg Wunsch Date: Sat, 7 Jun 2008 20:55:04 +0000 Subject: [PATCH] Contributed by Klaus Leidinger : Add check for buffermode feature, and use it if present. Can be turned off using -x no_blockmode. * avr910.c: Implement buffermode test and usage. * avrdude.1: Document -x no_blockmode. * doc/avrdude.texi: (Ditto.) git-svn-id: svn://svn.savannah.nongnu.org/avrdude/trunk@771 81a1dc3b-b13d-400b-aceb-764788c761c2 --- avrdude/ChangeLog | 9 ++ avrdude/avr910.c | 194 +++++++++++++++++++++++++++++++-------- avrdude/avrdude.1 | 9 ++ avrdude/doc/avrdude.texi | 5 + 4 files changed, 179 insertions(+), 38 deletions(-) diff --git a/avrdude/ChangeLog b/avrdude/ChangeLog index 664ac2f5..5e0b713d 100644 --- a/avrdude/ChangeLog +++ b/avrdude/ChangeLog @@ -1,3 +1,12 @@ +2008-06-07 Joerg Wunsch + + Contributed by Klaus Leidinger : + Add check for buffermode feature, and use it if present. Can be + turned off using -x no_blockmode. + * avr910.c: Implement buffermode test and usage. + * avrdude.1: Document -x no_blockmode. + * doc/avrdude.texi: (Ditto.) + 2008-03-24 Joerg Wunsch * usb_libusb.c: #undef interface for Win32 diff --git a/avrdude/avr910.c b/avrdude/avr910.c index d7bcec33..aa91e9d9 100644 --- a/avrdude/avr910.c +++ b/avrdude/avr910.c @@ -2,6 +2,7 @@ * avrdude - A Downloader/Uploader for AVR device programmers * Copyright (C) 2003-2004 Theodore A. Roth * Copyright 2007 Joerg Wunsch + * Copyright 2008 Klaus Leidinger * * 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 @@ -31,6 +32,7 @@ #include #include #include +#include #include #include @@ -48,6 +50,9 @@ struct pdata { char has_auto_incr_addr; unsigned char devcode; + unsigned int buffersize; + unsigned char test_blockmode; + unsigned char use_blockmode; }; #define PDATA(pgm) ((struct pdata *)(pgm->cookie)) @@ -61,6 +66,7 @@ static void avr910_setup(PROGRAMMER * pgm) exit(1); } memset(pgm->cookie, 0, sizeof(struct pdata)); + PDATA(pgm)->test_blockmode = 1; } static void avr910_teardown(PROGRAMMER * pgm) @@ -194,6 +200,28 @@ static int avr910_initialize(PROGRAMMER * pgm, AVRPART * p) if (PDATA(pgm)->has_auto_incr_addr == 'Y') fprintf(stderr, "Programmer supports auto addr increment.\n"); + /* Check support for buffered memory access, ignore if not available */ + + if (PDATA(pgm)->test_blockmode == 1) { + avr910_send(pgm, "b", 1); + avr910_recv(pgm, &c, 1); + if (c == 'Y') { + avr910_recv(pgm, &c, 1); + PDATA(pgm)->buffersize = (unsigned int)(unsigned char)c<<8; + avr910_recv(pgm, &c, 1); + PDATA(pgm)->buffersize += (unsigned int)(unsigned char)c; + fprintf(stderr, + "Programmer supports buffered memory access with " + "buffersize = %u bytes.\n", + PDATA(pgm)->buffersize); + PDATA(pgm)->use_blockmode = 1; + } else { + PDATA(pgm)->use_blockmode = 0; + } + } else { + PDATA(pgm)->use_blockmode = 0; + } + if (PDATA(pgm)->devcode == 0) { /* Get list of devices that the programmer supports. */ @@ -319,6 +347,16 @@ static int avr910_parseextparms(PROGRAMMER * pgm, LISTID extparms) continue; } + if (strncmp(extended_param, "no_blockmode", strlen("no_blockmode")) == 0) { + if (verbose >= 2) { + fprintf(stderr, + "%s: avr910_parseextparms(-x): no testing for Blockmode\n", + progname); + } + PDATA(pgm)->test_blockmode = 0; + + continue; + } fprintf(stderr, "%s: avr910_parseextparms(): invalid extended parameter '%s'\n", @@ -567,15 +605,55 @@ static int avr910_paged_write_eeprom(PROGRAMMER * pgm, AVRPART * p, static int avr910_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, int page_size, int n_bytes) { - if (strcmp(m->desc, "flash") == 0) { - return avr910_paged_write_flash(pgm, p, m, page_size, n_bytes); + int rval = 0; + if (PDATA(pgm)->use_blockmode == 0) { + if (strcmp(m->desc, "flash") == 0) { + rval = avr910_paged_write_flash(pgm, p, m, page_size, n_bytes); + } else if (strcmp(m->desc, "eeprom") == 0) { + rval = avr910_paged_write_eeprom(pgm, p, m, page_size, n_bytes); + } else { + rval = -2; + } } - else if (strcmp(m->desc, "eeprom") == 0) { - return avr910_paged_write_eeprom(pgm, p, m, page_size, n_bytes); - } - else { - return -2; + + if (PDATA(pgm)->use_blockmode == 1) { + unsigned int addr = 0; + unsigned int max_addr = n_bytes; + char *cmd; + unsigned int blocksize = PDATA(pgm)->buffersize; + + if (strcmp(m->desc, "flash") && strcmp(m->desc, "eeprom")) + rval = -2; + + if (m->desc[0] == 'e') + blocksize = 1; /* Write to eeprom single bytes only */ + avr910_set_addr(pgm, addr); + + cmd = malloc(4 + blocksize); + if (!cmd) rval = -1; + cmd[0] = 'B'; + cmd[3] = toupper(m->desc[0]); + + while (addr < max_addr) { + if ((max_addr - addr) < blocksize) { + blocksize = max_addr - addr; + }; + memcpy(&cmd[4], &m->buf[addr], blocksize); + cmd[1] = (blocksize >> 8) & 0xff; + cmd[2] = blocksize & 0xff; + + avr910_send(pgm, cmd, 4 + blocksize); + avr910_vfy_cmd_sent(pgm, "write block"); + + addr += blocksize; + + report_progress (addr, max_addr, NULL); + } /* while */ + free(cmd); + + rval = addr; } + return rval; } @@ -587,46 +665,86 @@ static int avr910_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, unsigned int addr = 0; unsigned int max_addr; char buf[2]; + int rval=0; - if (strcmp(m->desc, "flash") == 0) { - cmd = 'R'; - rd_size = 2; /* read two bytes per addr */ - } - else if (strcmp(m->desc, "eeprom") == 0) { - cmd = 'd'; - rd_size = 1; - } - else { - return -2; - } + if (PDATA(pgm)->use_blockmode == 0) { - max_addr = n_bytes/rd_size; - - avr910_set_addr(pgm, addr); - - while (addr < max_addr) { - avr910_send(pgm, &cmd, 1); - 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 { - avr910_recv(pgm, (char *)&m->buf[addr], 1); + if (strcmp(m->desc, "flash") == 0) { + cmd = 'R'; + rd_size = 2; /* read two bytes per addr */ + } else if (strcmp(m->desc, "eeprom") == 0) { + cmd = 'd'; + rd_size = 1; + } else { + rval = -2; } - addr++; + max_addr = n_bytes/rd_size; - if (PDATA(pgm)->has_auto_incr_addr != 'Y') { - avr910_set_addr(pgm, addr); + avr910_set_addr(pgm, addr); + + while (addr < max_addr) { + avr910_send(pgm, &cmd, 1); + 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 { + avr910_recv(pgm, (char *)&m->buf[addr], 1); + } + + addr++; + + if (PDATA(pgm)->has_auto_incr_addr != 'Y') { + avr910_set_addr(pgm, addr); + } + + report_progress (addr, max_addr, NULL); } - report_progress (addr, max_addr, NULL); + rval = addr * rd_size; } - return addr * rd_size; + if (PDATA(pgm)->use_blockmode == 1) { + unsigned int addr = 0; + unsigned int max_addr = n_bytes; + int rd_size = 1; + + /* check parameter syntax: only "flash" or "eeprom" is allowed */ + if (strcmp(m->desc, "flash") && strcmp(m->desc, "eeprom")) + rval = -2; + + /* use buffered mode */ + char cmd[4]; + int blocksize = PDATA(pgm)->buffersize; + + cmd[0] = 'g'; + cmd[3] = toupper(m->desc[0]); + + avr910_set_addr(pgm, addr); + + while (addr < max_addr) { + if ((max_addr - addr) < blocksize) { + blocksize = max_addr - addr; + }; + cmd[1] = (blocksize >> 8) & 0xff; + cmd[2] = blocksize & 0xff; + + avr910_send(pgm, cmd, 4); + avr910_recv(pgm, (char *)&m->buf[addr], blocksize); + + addr += blocksize; + + report_progress (addr, max_addr, NULL); + } + + rval = addr * rd_size; + } + + return rval; } /* Signature byte reads are always 3 bytes. */ diff --git a/avrdude/avrdude.1 b/avrdude/avrdude.1 index 9db8b896..c9e5d829 100644 --- a/avrdude/avrdude.1 +++ b/avrdude/avrdude.1 @@ -796,6 +796,15 @@ command sent to the programmer. can be specified using the conventional number notation of the C programming language. .El +.Bl -tag -offset indent -width indent +.It Ar no_blockmode +Disables the default checking for block transfer capability. +Use +.Ar no_blockmode +only if your +.Ar AVR910 +programmer creates errors during initial sequence. +.El .El .Sh FILES .Bl -tag -offset indent -width /dev/ppi0XXX diff --git a/avrdude/doc/avrdude.texi b/avrdude/doc/avrdude.texi index 026d98c4..064b61dd 100644 --- a/avrdude/doc/avrdude.texi +++ b/avrdude/doc/avrdude.texi @@ -823,6 +823,11 @@ is not verified but used directly within the @code{T} command sent to the programmer. @var{VALUE} can be specified using the conventional number notation of the C programming language. +@item @samp{no_blockmode} +Disables the default checking for block transfer capability. +Use +@samp{no_blockmode} only if your @samp{AVR910} +programmer creates errors during initial sequence. @end table @end table