Submitted by Neil Davey:

patch #4539: Ability to control the bit clock (usleep) delay
for ppi interface
* bitbang.c: Implement bitbang_delay() and its calibration.
* bitbang.h: Declare bitbang_delay().
* main.c: Add the ispdelay option (-i).
* pgm.h (struct programmer_t): Add the ispdelay parameter.
* par.c: Add calls to bitbang_delay() when requested.
* serbb_posix.c: (Ditto.)
* serbb_win32.c: (Ditto.)
* avrdude.1: Document the new -i option.
* doc/avrdude.texi: (Ditto.)


git-svn-id: svn://svn.savannah.nongnu.org/avrdude/trunk/avrdude@610 81a1dc3b-b13d-400b-aceb-764788c761c2
This commit is contained in:
Joerg Wunsch 2006-08-17 15:06:20 +00:00
parent 0608a54a5e
commit 88e2614ee2
11 changed files with 188 additions and 37 deletions

View File

@ -1,3 +1,18 @@
2006-08-17 Joerg Wunsch <j@uriah.heep.sax.de>
Submitted by Neil Davey:
patch #4539: Ability to control the bit clock (usleep) delay
for ppi interface
* bitbang.c: Implement bitbang_delay() and its calibration.
* bitbang.h: Declare bitbang_delay().
* main.c: Add the ispdelay option (-i).
* pgm.h (struct programmer_t): Add the ispdelay parameter.
* par.c: Add calls to bitbang_delay() when requested.
* serbb_posix.c: (Ditto.)
* serbb_win32.c: (Ditto.)
* avrdude.1: Document the new -i option.
* doc/avrdude.texi: (Ditto.)
2006-08-14 Joerg Wunsch <j@uriah.heep.sax.de>
Submitted by <chris@awaretechs.com>:

3
NEWS
View File

@ -22,6 +22,9 @@ Current:
* Add high-voltage mode programming for the STK500 (both,
parallel, and high-voltage serial programming).
* Allow for specifying the ISP clock delay as an option for
bit-bang programming adapters.
Version 5.1:
* New devices supported:

View File

@ -19,7 +19,7 @@
.\"
.\" $Id$
.\"
.Dd DATE July 19, 2006
.Dd DATE August 16, 2006
.Os
.Dt AVRDUDE 1
.Sh NAME
@ -38,6 +38,7 @@
.Op \&, Ns Ar exitspec
.Oc
.Op Fl F
.Op Fl i Ar delay
.Op Fl n
.Op Fl P Ar port
.Op Fl q
@ -330,6 +331,24 @@ reasonable before continuing. Since it can happen from time to time
that a device has a broken (erased or overwritten) device signature
but is otherwise operating normally, this options is provided to
override the check.
.It Fl i Ar delay
For bitbang-type programmers, delay for approximately
.Ar delay
microseconds between each bit state change.
If the host system is very fast, or the target runs off a slow clock
(like a 32 kHz crystal, or the 128 kHz internal RC oscillator), this
can become necessary to satisfy the requirement that the ISP clock
frequency must not be higher than 1/4 of the CPU clock frequency.
This is implemented as a spin-loop delay to allow even for very
short delays.
On Unix-style operating systems, the spin loop is initially calibrated
against a system timer, so the number of microseconds might be rather
realistic, assuming a constant system load while
.Nm
is running.
On Win32 operating systems, a preconfigured number of cycles per
microsecond is assumed that might be off a bit for very fast or very
slow machines.
.It Fl n
No-write - disables actually writing data to the MCU (useful for debugging
.Nm avrdude

View File

@ -28,18 +28,103 @@
#include <unistd.h>
#include <errno.h>
#if !defined(WIN32NATIVE)
# include <signal.h>
# include <sys/time.h>
#endif
#include "avr.h"
#include "pindefs.h"
#include "pgm.h"
#include "par.h"
#include "serbb.h"
#define SLOW_TOGGLE 0
extern char * progname;
extern int do_cycles;
extern int verbose;
static int delay_decrement;
#if !defined(WIN32NATIVE)
static volatile int done;
typedef void (*mysighandler_t)(int);
static mysighandler_t saved_alarmhandler;
static void alarmhandler(int signo)
{
done = 1;
signal(SIGALRM, saved_alarmhandler);
}
#endif /* !WIN32NATIVE */
/*
* Calibrate the microsecond delay loop below.
*/
static void bitbang_calibrate_delay(void)
{
/*
* Right now, we don't have any Win32 implementation for this, so we
* can only run on a preconfigured delay stepping there. The figure
* below should at least be correct within an order of magnitude,
* judging from the auto-calibration figures seen on various Unix
* systems on comparable hardware.
*/
#if defined(WIN32NATIVE)
delay_decrement = 100;
#else /* !WIN32NATIVE */
struct itimerval itv;
volatile int i;
if (verbose >= 2)
fprintf(stderr,
"%s: Calibrating delay loop...",
progname);
i = 0;
done = 0;
saved_alarmhandler = signal(SIGALRM, alarmhandler);
/*
* Set ITIMER_REAL to 100 ms. All known systems have a timer
* granularity of 10 ms or better, so counting the delay cycles
* accumulating over 100 ms should give us a rather realistic
* picture, without annoying the user by a lengthy startup time (as
* an alarm(1) would do). Of course, if heavy system activity
* happens just during calibration but stops before the remaining
* part of AVRDUDE runs, this will yield wrong values. There's not
* much we can do about this.
*/
itv.it_value.tv_sec = 0;
itv.it_value.tv_usec = 100000;
itv.it_interval.tv_sec = itv.it_interval.tv_usec = 0;
setitimer(ITIMER_REAL, &itv, 0);
while (!done)
i--;
itv.it_value.tv_sec = itv.it_value.tv_usec = 0;
setitimer(ITIMER_REAL, &itv, 0);
/*
* Calculate back from 100 ms to 1 us.
*/
delay_decrement = -i / 100000;
if (verbose >= 2)
fprintf(stderr,
" calibrated to %d cycles per us\n",
delay_decrement);
#endif /* WIN32NATIVE */
}
/*
* Delay for approximately the number of microseconds specified.
* usleep()'s granularity is usually like 1 ms or 10 ms, so it's not
* really suitable for short delays in bit-bang algorithms.
*/
void bitbang_delay(int us)
{
volatile int del = us * delay_decrement;
while (del > 0)
del--;
}
/*
* transmit and receive a byte of data to/from the AVR device
*/
@ -204,6 +289,8 @@ int bitbang_initialize(PROGRAMMER * pgm, AVRPART * p)
int rc;
int tries;
bitbang_calibrate_delay();
pgm->powerup(pgm);
usleep(20000);

View File

@ -25,6 +25,7 @@
int bitbang_setpin(int fd, int pin, int value);
int bitbang_getpin(int fd, int pin);
int bitbang_highpulsepin(int fd, int pin);
void bitbang_delay(unsigned int us);
int bitbang_rdy_led (PROGRAMMER * pgm, int value);
int bitbang_err_led (PROGRAMMER * pgm, int value);

View File

@ -584,6 +584,23 @@ to time that a device has a broken (erased or overwritten) device
signature but is otherwise operating normally, this options is provided
to override the check.
@item -i @var{delay}
For bitbang-type programmers, delay for approximately
@var{delay}
microseconds between each bit state change.
If the host system is very fast, or the target runs off a slow clock
(like a 32 kHz crystal, or the 128 kHz internal RC oscillator), this
can become necessary to satisfy the requirement that the ISP clock
frequency must not be higher than 1/4 of the CPU clock frequency.
This is implemented as a spin-loop delay to allow even for very
short delays.
On Unix-style operating systems, the spin loop is initially calibrated
against a system timer, so the number of microseconds might be rather
realistic, assuming a constant system load while AVRDUDE is running.
On Win32 operating systems, a preconfigured number of cycles per
microsecond is assumed that might be off a bit for very fast or very
slow machines.
@item -n
No-write - disables actually writing data to the MCU (useful for
debugging AVRDUDE).

21
main.c
View File

@ -105,6 +105,7 @@ void usage(void)
" -C <config-file> Specify location of configuration file.\n"
" -c <programmer> Specify programmer type.\n"
" -D Disable auto erase for flash memory\n"
" -i <delay> ISP Clock Delay [in microseconds]\n"
" -P <port> Specify connection port.\n"
" -F Override invalid signature check.\n"
" -e Perform a chip erase.\n"
@ -695,6 +696,7 @@ int main(int argc, char * argv [])
char * e; /* for strtol() error checking */
int baudrate; /* override default programmer baud rate */
double bitclock; /* Specify programmer bit clock (JTAG ICE) */
int ispdelay; /* Specify the delay for ISP clock */
int safemode; /* Enable safemode, 1=safemode on, 0=normal */
int silentsafe; /* Don't ask about fuses, 1=silent, 0=normal */
unsigned char safemode_lfuse = 0xff;
@ -752,6 +754,7 @@ int main(int argc, char * argv [])
set_cycles = -1;
baudrate = 0;
bitclock = 0.0;
ispdelay = 0;
safemode = 1; /* Safemode on by default */
silentsafe = 0; /* Ask by default */
@ -802,7 +805,7 @@ int main(int argc, char * argv [])
/*
* process command line arguments
*/
while ((ch = getopt(argc,argv,"?b:B:c:C:DeE:Fnp:P:qstU:uvVyY:")) != -1) {
while ((ch = getopt(argc,argv,"?b:B:c:C:DeE:Fi:np:P:qstU:uvVyY:")) != -1) {
switch (ch) {
case 'b': /* override default programmer baud rate */
@ -823,6 +826,15 @@ int main(int argc, char * argv [])
}
break;
case 'i': /* specify isp clock delay */
ispdelay = strtol(optarg, &e,10);
if ((e == optarg) || (*e != 0) || ispdelay == 0) {
fprintf(stderr, "%s: invalid isp clock delay specified '%s'\n",
progname, optarg);
exit(1);
}
break;
case 'c': /* programmer id */
programmer = optarg;
break;
@ -1133,6 +1145,13 @@ int main(int argc, char * argv [])
pgm->bitclock = bitclock * 1e-6;
}
if (ispdelay != 0) {
if (verbose) {
fprintf(stderr, "%sSetting isp clock delay: %3i\n", progbuf, ispdelay);
}
pgm->ispdelay = ispdelay;
}
rc = pgm->open(pgm, port);
if (rc < 0) {
exitrc = 1;

31
par.c
View File

@ -48,8 +48,6 @@ extern int verbose;
#if HAVE_PARPORT
#define SLOW_TOGGLE 0
struct ppipins_t {
int pin;
int reg;
@ -102,9 +100,8 @@ static int par_setpin(PROGRAMMER * pgm, int pin, int value)
else
ppi_clr(pgm->fd, ppipins[pin].reg, ppipins[pin].bit);
#if SLOW_TOGGLE
usleep(1000);
#endif
if (pgm->ispdelay > 1)
bitbang_delay(pgm->ispdelay);
return 0;
}
@ -155,24 +152,20 @@ static int par_highpulsepin(PROGRAMMER * pgm, int pin)
if (inverted) {
ppi_clr(pgm->fd, ppipins[pin].reg, ppipins[pin].bit);
#if SLOW_TOGGLE
usleep(1000);
#endif
ppi_set(pgm->fd, ppipins[pin].reg, ppipins[pin].bit);
if (pgm->ispdelay > 1)
bitbang_delay(pgm->ispdelay);
#if SLOW_TOGGLE
usleep(1000);
#endif
ppi_set(pgm->fd, ppipins[pin].reg, ppipins[pin].bit);
if (pgm->ispdelay > 1)
bitbang_delay(pgm->ispdelay);
} else {
ppi_set(pgm->fd, ppipins[pin].reg, ppipins[pin].bit);
#if SLOW_TOGGLE
usleep(1000);
#endif
ppi_clr(pgm->fd, ppipins[pin].reg, ppipins[pin].bit);
if (pgm->ispdelay > 1)
bitbang_delay(pgm->ispdelay);
#if SLOW_TOGGLE
usleep(1000);
#endif
ppi_clr(pgm->fd, ppipins[pin].reg, ppipins[pin].bit);
if (pgm->ispdelay > 1)
bitbang_delay(pgm->ispdelay);
}
return 0;

1
pgm.h
View File

@ -48,6 +48,7 @@ typedef struct programmer_t {
int ppictrl;
int baudrate;
double bitclock; /* JTAG ICE clock period in microseconds */
int ispdelay; /* ISP clock delay */
int fd;
int page_size; /* page size if the programmer supports paged write/load */
int (*rdy_led) (struct programmer_t * pgm, int value);

View File

@ -158,14 +158,12 @@ static int serbb_highpulsepin(PROGRAMMER * pgm, int pin)
return -1;
serbb_setpin(pgm, pin, 1);
#if SLOW_TOGGLE
usleep(1000);
#endif
serbb_setpin(pgm, pin, 0);
if (pgm->ispdelay > 1)
bitbang_delay(pgm->ispdelay);
#if SLOW_TOGGLE
usleep(1000);
#endif
serbb_setpin(pgm, pin, 0);
if (pgm->ispdelay > 1)
bitbang_delay(pgm->ispdelay);
return 0;
}

View File

@ -230,14 +230,12 @@ static int serbb_highpulsepin(PROGRAMMER * pgm, int pin)
return -1;
serbb_setpin(pgm, pin, 1);
#if SLOW_TOGGLE
usleep(1000);
#endif
serbb_setpin(pgm, pin, 0);
if (pgm->ispdelay > 1)
bitbang_delay(pgm->ispdelay);
#if SLOW_TOGGLE
usleep(1000);
#endif
serbb_setpin(pgm, pin, 0);
if (pgm->ispdelay > 1)
bitbang_delay(pgm->ispdelay);
return 0;
}