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:
parent
0608a54a5e
commit
88e2614ee2
15
ChangeLog
15
ChangeLog
|
@ -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>
|
2006-08-14 Joerg Wunsch <j@uriah.heep.sax.de>
|
||||||
|
|
||||||
Submitted by <chris@awaretechs.com>:
|
Submitted by <chris@awaretechs.com>:
|
||||||
|
|
3
NEWS
3
NEWS
|
@ -22,6 +22,9 @@ Current:
|
||||||
* Add high-voltage mode programming for the STK500 (both,
|
* Add high-voltage mode programming for the STK500 (both,
|
||||||
parallel, and high-voltage serial programming).
|
parallel, and high-voltage serial programming).
|
||||||
|
|
||||||
|
* Allow for specifying the ISP clock delay as an option for
|
||||||
|
bit-bang programming adapters.
|
||||||
|
|
||||||
Version 5.1:
|
Version 5.1:
|
||||||
|
|
||||||
* New devices supported:
|
* New devices supported:
|
||||||
|
|
21
avrdude.1
21
avrdude.1
|
@ -19,7 +19,7 @@
|
||||||
.\"
|
.\"
|
||||||
.\" $Id$
|
.\" $Id$
|
||||||
.\"
|
.\"
|
||||||
.Dd DATE July 19, 2006
|
.Dd DATE August 16, 2006
|
||||||
.Os
|
.Os
|
||||||
.Dt AVRDUDE 1
|
.Dt AVRDUDE 1
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
|
@ -38,6 +38,7 @@
|
||||||
.Op \&, Ns Ar exitspec
|
.Op \&, Ns Ar exitspec
|
||||||
.Oc
|
.Oc
|
||||||
.Op Fl F
|
.Op Fl F
|
||||||
|
.Op Fl i Ar delay
|
||||||
.Op Fl n
|
.Op Fl n
|
||||||
.Op Fl P Ar port
|
.Op Fl P Ar port
|
||||||
.Op Fl q
|
.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
|
that a device has a broken (erased or overwritten) device signature
|
||||||
but is otherwise operating normally, this options is provided to
|
but is otherwise operating normally, this options is provided to
|
||||||
override the check.
|
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
|
.It Fl n
|
||||||
No-write - disables actually writing data to the MCU (useful for debugging
|
No-write - disables actually writing data to the MCU (useful for debugging
|
||||||
.Nm avrdude
|
.Nm avrdude
|
||||||
|
|
91
bitbang.c
91
bitbang.c
|
@ -28,18 +28,103 @@
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
|
#if !defined(WIN32NATIVE)
|
||||||
|
# include <signal.h>
|
||||||
|
# include <sys/time.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "avr.h"
|
#include "avr.h"
|
||||||
#include "pindefs.h"
|
#include "pindefs.h"
|
||||||
#include "pgm.h"
|
#include "pgm.h"
|
||||||
#include "par.h"
|
#include "par.h"
|
||||||
#include "serbb.h"
|
#include "serbb.h"
|
||||||
|
|
||||||
#define SLOW_TOGGLE 0
|
|
||||||
|
|
||||||
extern char * progname;
|
extern char * progname;
|
||||||
extern int do_cycles;
|
extern int do_cycles;
|
||||||
extern int verbose;
|
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
|
* 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 rc;
|
||||||
int tries;
|
int tries;
|
||||||
|
|
||||||
|
bitbang_calibrate_delay();
|
||||||
|
|
||||||
pgm->powerup(pgm);
|
pgm->powerup(pgm);
|
||||||
usleep(20000);
|
usleep(20000);
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
int bitbang_setpin(int fd, int pin, int value);
|
int bitbang_setpin(int fd, int pin, int value);
|
||||||
int bitbang_getpin(int fd, int pin);
|
int bitbang_getpin(int fd, int pin);
|
||||||
int bitbang_highpulsepin(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_rdy_led (PROGRAMMER * pgm, int value);
|
||||||
int bitbang_err_led (PROGRAMMER * pgm, int value);
|
int bitbang_err_led (PROGRAMMER * pgm, int value);
|
||||||
|
|
|
@ -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
|
signature but is otherwise operating normally, this options is provided
|
||||||
to override the check.
|
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
|
@item -n
|
||||||
No-write - disables actually writing data to the MCU (useful for
|
No-write - disables actually writing data to the MCU (useful for
|
||||||
debugging AVRDUDE).
|
debugging AVRDUDE).
|
||||||
|
|
21
main.c
21
main.c
|
@ -105,6 +105,7 @@ void usage(void)
|
||||||
" -C <config-file> Specify location of configuration file.\n"
|
" -C <config-file> Specify location of configuration file.\n"
|
||||||
" -c <programmer> Specify programmer type.\n"
|
" -c <programmer> Specify programmer type.\n"
|
||||||
" -D Disable auto erase for flash memory\n"
|
" -D Disable auto erase for flash memory\n"
|
||||||
|
" -i <delay> ISP Clock Delay [in microseconds]\n"
|
||||||
" -P <port> Specify connection port.\n"
|
" -P <port> Specify connection port.\n"
|
||||||
" -F Override invalid signature check.\n"
|
" -F Override invalid signature check.\n"
|
||||||
" -e Perform a chip erase.\n"
|
" -e Perform a chip erase.\n"
|
||||||
|
@ -695,6 +696,7 @@ int main(int argc, char * argv [])
|
||||||
char * e; /* for strtol() error checking */
|
char * e; /* for strtol() error checking */
|
||||||
int baudrate; /* override default programmer baud rate */
|
int baudrate; /* override default programmer baud rate */
|
||||||
double bitclock; /* Specify programmer bit clock (JTAG ICE) */
|
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 safemode; /* Enable safemode, 1=safemode on, 0=normal */
|
||||||
int silentsafe; /* Don't ask about fuses, 1=silent, 0=normal */
|
int silentsafe; /* Don't ask about fuses, 1=silent, 0=normal */
|
||||||
unsigned char safemode_lfuse = 0xff;
|
unsigned char safemode_lfuse = 0xff;
|
||||||
|
@ -752,6 +754,7 @@ int main(int argc, char * argv [])
|
||||||
set_cycles = -1;
|
set_cycles = -1;
|
||||||
baudrate = 0;
|
baudrate = 0;
|
||||||
bitclock = 0.0;
|
bitclock = 0.0;
|
||||||
|
ispdelay = 0;
|
||||||
safemode = 1; /* Safemode on by default */
|
safemode = 1; /* Safemode on by default */
|
||||||
silentsafe = 0; /* Ask by default */
|
silentsafe = 0; /* Ask by default */
|
||||||
|
|
||||||
|
@ -802,7 +805,7 @@ int main(int argc, char * argv [])
|
||||||
/*
|
/*
|
||||||
* process command line arguments
|
* 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) {
|
switch (ch) {
|
||||||
case 'b': /* override default programmer baud rate */
|
case 'b': /* override default programmer baud rate */
|
||||||
|
@ -823,6 +826,15 @@ int main(int argc, char * argv [])
|
||||||
}
|
}
|
||||||
break;
|
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 */
|
case 'c': /* programmer id */
|
||||||
programmer = optarg;
|
programmer = optarg;
|
||||||
break;
|
break;
|
||||||
|
@ -1133,6 +1145,13 @@ int main(int argc, char * argv [])
|
||||||
pgm->bitclock = bitclock * 1e-6;
|
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);
|
rc = pgm->open(pgm, port);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
exitrc = 1;
|
exitrc = 1;
|
||||||
|
|
31
par.c
31
par.c
|
@ -48,8 +48,6 @@ extern int verbose;
|
||||||
|
|
||||||
#if HAVE_PARPORT
|
#if HAVE_PARPORT
|
||||||
|
|
||||||
#define SLOW_TOGGLE 0
|
|
||||||
|
|
||||||
struct ppipins_t {
|
struct ppipins_t {
|
||||||
int pin;
|
int pin;
|
||||||
int reg;
|
int reg;
|
||||||
|
@ -102,9 +100,8 @@ static int par_setpin(PROGRAMMER * pgm, int pin, int value)
|
||||||
else
|
else
|
||||||
ppi_clr(pgm->fd, ppipins[pin].reg, ppipins[pin].bit);
|
ppi_clr(pgm->fd, ppipins[pin].reg, ppipins[pin].bit);
|
||||||
|
|
||||||
#if SLOW_TOGGLE
|
if (pgm->ispdelay > 1)
|
||||||
usleep(1000);
|
bitbang_delay(pgm->ispdelay);
|
||||||
#endif
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -155,24 +152,20 @@ static int par_highpulsepin(PROGRAMMER * pgm, int pin)
|
||||||
|
|
||||||
if (inverted) {
|
if (inverted) {
|
||||||
ppi_clr(pgm->fd, ppipins[pin].reg, ppipins[pin].bit);
|
ppi_clr(pgm->fd, ppipins[pin].reg, ppipins[pin].bit);
|
||||||
#if SLOW_TOGGLE
|
if (pgm->ispdelay > 1)
|
||||||
usleep(1000);
|
bitbang_delay(pgm->ispdelay);
|
||||||
#endif
|
|
||||||
ppi_set(pgm->fd, ppipins[pin].reg, ppipins[pin].bit);
|
|
||||||
|
|
||||||
#if SLOW_TOGGLE
|
ppi_set(pgm->fd, ppipins[pin].reg, ppipins[pin].bit);
|
||||||
usleep(1000);
|
if (pgm->ispdelay > 1)
|
||||||
#endif
|
bitbang_delay(pgm->ispdelay);
|
||||||
} else {
|
} else {
|
||||||
ppi_set(pgm->fd, ppipins[pin].reg, ppipins[pin].bit);
|
ppi_set(pgm->fd, ppipins[pin].reg, ppipins[pin].bit);
|
||||||
#if SLOW_TOGGLE
|
if (pgm->ispdelay > 1)
|
||||||
usleep(1000);
|
bitbang_delay(pgm->ispdelay);
|
||||||
#endif
|
|
||||||
ppi_clr(pgm->fd, ppipins[pin].reg, ppipins[pin].bit);
|
|
||||||
|
|
||||||
#if SLOW_TOGGLE
|
ppi_clr(pgm->fd, ppipins[pin].reg, ppipins[pin].bit);
|
||||||
usleep(1000);
|
if (pgm->ispdelay > 1)
|
||||||
#endif
|
bitbang_delay(pgm->ispdelay);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
1
pgm.h
1
pgm.h
|
@ -48,6 +48,7 @@ typedef struct programmer_t {
|
||||||
int ppictrl;
|
int ppictrl;
|
||||||
int baudrate;
|
int baudrate;
|
||||||
double bitclock; /* JTAG ICE clock period in microseconds */
|
double bitclock; /* JTAG ICE clock period in microseconds */
|
||||||
|
int ispdelay; /* ISP clock delay */
|
||||||
int fd;
|
int fd;
|
||||||
int page_size; /* page size if the programmer supports paged write/load */
|
int page_size; /* page size if the programmer supports paged write/load */
|
||||||
int (*rdy_led) (struct programmer_t * pgm, int value);
|
int (*rdy_led) (struct programmer_t * pgm, int value);
|
||||||
|
|
|
@ -158,14 +158,12 @@ static int serbb_highpulsepin(PROGRAMMER * pgm, int pin)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
serbb_setpin(pgm, pin, 1);
|
serbb_setpin(pgm, pin, 1);
|
||||||
#if SLOW_TOGGLE
|
if (pgm->ispdelay > 1)
|
||||||
usleep(1000);
|
bitbang_delay(pgm->ispdelay);
|
||||||
#endif
|
|
||||||
serbb_setpin(pgm, pin, 0);
|
|
||||||
|
|
||||||
#if SLOW_TOGGLE
|
serbb_setpin(pgm, pin, 0);
|
||||||
usleep(1000);
|
if (pgm->ispdelay > 1)
|
||||||
#endif
|
bitbang_delay(pgm->ispdelay);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -230,14 +230,12 @@ static int serbb_highpulsepin(PROGRAMMER * pgm, int pin)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
serbb_setpin(pgm, pin, 1);
|
serbb_setpin(pgm, pin, 1);
|
||||||
#if SLOW_TOGGLE
|
if (pgm->ispdelay > 1)
|
||||||
usleep(1000);
|
bitbang_delay(pgm->ispdelay);
|
||||||
#endif
|
|
||||||
serbb_setpin(pgm, pin, 0);
|
|
||||||
|
|
||||||
#if SLOW_TOGGLE
|
serbb_setpin(pgm, pin, 0);
|
||||||
usleep(1000);
|
if (pgm->ispdelay > 1)
|
||||||
#endif
|
bitbang_delay(pgm->ispdelay);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue