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>
|
||||
|
||||
Submitted by <chris@awaretechs.com>:
|
||||
|
|
3
NEWS
3
NEWS
|
@ -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:
|
||||
|
|
21
avrdude.1
21
avrdude.1
|
@ -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
|
||||
|
|
91
bitbang.c
91
bitbang.c
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
21
main.c
|
@ -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
31
par.c
|
@ -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
1
pgm.h
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue