*ppi.c: Major speed-tuning. Since ioctl() is expensive read from shadow-registers where possible.

git-svn-id: svn://svn.savannah.nongnu.org/avrdude/trunk/avrdude@384 81a1dc3b-b13d-400b-aceb-764788c761c2
This commit is contained in:
Jan-Hinnerk Reichert 2003-11-22 03:31:27 +00:00
parent eed95a739d
commit a26bd26c9e
1 changed files with 63 additions and 45 deletions

108
ppi.c
View File

@ -43,24 +43,33 @@
extern char * progname; extern char * progname;
/* enum {
* set 'get' and 'set' appropriately for subsequent passage to ioctl() PPI_READ,
* to get/set the specified PPI registers. PPI_WRITE,
*/ PPI_SHADOWREAD
static int ppi_getops(int reg, unsigned long * get, unsigned long * set) };
int ppi_shadow_access(int fd, int reg, unsigned char *v, unsigned char action)
{ {
static unsigned char shadow[3];
int shadow_num;
unsigned long set, get;
switch (reg) { switch (reg) {
case PPIDATA: case PPIDATA:
*set = PPISDATA; set = PPISDATA;
*get = PPIGDATA; get = PPIGDATA;
shadow_num = 0;
break; break;
case PPICTRL: case PPICTRL:
*set = PPISCTRL; set = PPISCTRL;
*get = PPIGCTRL; get = PPIGCTRL;
shadow_num = 1;
break; break;
case PPISTATUS: case PPISTATUS:
*set = PPISSTATUS; set = PPISSTATUS;
*get = PPIGSTATUS; get = PPIGSTATUS;
shadow_num = 2;
break; break;
default: default:
fprintf(stderr, "%s: avr_set(): invalid register=%d\n", fprintf(stderr, "%s: avr_set(): invalid register=%d\n",
@ -69,27 +78,37 @@ static int ppi_getops(int reg, unsigned long * get, unsigned long * set)
break; break;
} }
switch (action) {
case PPI_SHADOWREAD:
*v = shadow[shadow_num];
break;
case PPI_READ:
ioctl(fd, get, v);
shadow[shadow_num]=*v;
break;
case PPI_WRITE:
shadow[shadow_num]=*v;
ioctl(fd, set, v);
break;
}
return 0; return 0;
} }
/* /*
* set the indicated bit of the specified register. * set the indicated bit of the specified register.
*/ */
int ppi_set(int fd, int reg, int bit) int ppi_set(int fd, int reg, int bit)
{ {
unsigned char v; unsigned char v;
unsigned long get, set;
int rc; int rc;
rc = ppi_getops(reg, &get, &set); rc = ppi_shadow_access(fd, reg, &v, PPI_SHADOWREAD);
v |= bit;
rc |= ppi_shadow_access(fd, reg, &v, PPI_WRITE);
if (rc) if (rc)
return -1; return -1;
ioctl(fd, get, &v);
v |= bit;
ioctl(fd, set, &v);
return 0; return 0;
} }
@ -100,17 +119,15 @@ int ppi_set(int fd, int reg, int bit)
int ppi_clr(int fd, int reg, int bit) int ppi_clr(int fd, int reg, int bit)
{ {
unsigned char v; unsigned char v;
unsigned long get, set;
int rc; int rc;
rc = ppi_getops(reg, &get, &set); rc = ppi_shadow_access(fd, reg, &v, PPI_SHADOWREAD);
v &= ~bit;
rc |= ppi_shadow_access(fd, reg, &v, PPI_WRITE);
if (rc) if (rc)
return -1; return -1;
ioctl(fd, get, &v);
v &= ~bit;
ioctl(fd, set, &v);
return 0; return 0;
} }
@ -121,16 +138,14 @@ int ppi_clr(int fd, int reg, int bit)
int ppi_get(int fd, int reg, int bit) int ppi_get(int fd, int reg, int bit)
{ {
unsigned char v; unsigned char v;
unsigned long get, set;
int rc; int rc;
rc = ppi_getops(reg, &get, &set); rc = ppi_shadow_access(fd, reg, &v, PPI_READ);
v &= bit;
if (rc) if (rc)
return -1; return -1;
ioctl(fd, get, &v);
v &= bit;
return v; /* v == bit */ return v; /* v == bit */
} }
@ -140,17 +155,15 @@ int ppi_get(int fd, int reg, int bit)
int ppi_toggle(int fd, int reg, int bit) int ppi_toggle(int fd, int reg, int bit)
{ {
unsigned char v; unsigned char v;
unsigned long get, set;
int rc; int rc;
rc = ppi_getops(reg, &get, &set); rc = ppi_shadow_access(fd, reg, &v, PPI_SHADOWREAD);
v ^= bit;
rc |= ppi_shadow_access(fd, reg, &v, PPI_WRITE);
if (rc) if (rc)
return -1; return -1;
ioctl(fd, get, &v);
v ^= bit;
ioctl(fd, set, &v);
return 0; return 0;
} }
@ -161,16 +174,14 @@ int ppi_toggle(int fd, int reg, int bit)
int ppi_getall(int fd, int reg) int ppi_getall(int fd, int reg)
{ {
unsigned char v; unsigned char v;
unsigned long get, set;
int rc; int rc;
rc = ppi_getops(reg, &get, &set); rc = ppi_shadow_access(fd, reg, &v, PPI_READ);
if (rc) if (rc)
return -1; return -1;
ioctl(fd, get, &v); return v; /* v == bit */
return (int)v;
} }
/* /*
@ -179,16 +190,14 @@ int ppi_getall(int fd, int reg)
int ppi_setall(int fd, int reg, int val) int ppi_setall(int fd, int reg, int val)
{ {
unsigned char v; unsigned char v;
unsigned long get, set;
int rc; int rc;
rc = ppi_getops(reg, &get, &set); v = val;
rc = ppi_shadow_access(fd, reg, &v, PPI_WRITE);
if (rc) if (rc)
return -1; return -1;
v = val;
ioctl(fd, set, &v);
return 0; return 0;
} }
@ -196,6 +205,7 @@ int ppi_setall(int fd, int reg, int val)
int ppi_open(char * port) int ppi_open(char * port)
{ {
int fd; int fd;
unsigned char v;
fd = open(port, O_RDWR); fd = open(port, O_RDWR);
if (fd < 0) { if (fd < 0) {
@ -204,6 +214,14 @@ int ppi_open(char * port)
return -1; return -1;
} }
/*
* Initialize shadow registers
*/
ppi_shadow_access (fd, PPIDATA, &v, PPI_READ);
ppi_shadow_access (fd, PPICTRL, &v, PPI_READ);
ppi_shadow_access (fd, PPISTATUS, &v, PPI_READ);
return fd; return fd;
} }