diff --git a/ChangeLog b/ChangeLog index 8ba2a130..7e419b6c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,17 @@ +2013-05-03 Rene Liebscher + + Create new pin definition data structures to support 0-based pin numbers, + and mixed inverse/non-inverse pin lists. + * avrftdi.c,buspirate.c,linuxgpio.c,par.c,serbb_*.c: added function call + to fill old pinno entries from new pin definitions. + * pindefs.[hc]: added data struct and helper functions for new pin definitions + * avrdude.conf.in: pins in entries using ftdi_syncbb are now 0-based + * config_gram.y: allow combinations of inverted and non-inverted pins in pin lists + * ft245r.c: reworked to work directly with the new pin definitions, + pins are now 0-based, inverse pins are supported, buff is supported + * pgm.[ch]: added new pin definitions field to programmer structure, + adapted pin display functions + 2013-05-03 Hannes Weisbach * avrftdi_private.h: Remove update forward declaration from avrftdi_print to @@ -42,7 +56,7 @@ of the ongoing OUT request and subsequently timeout, because an IN request cannot be issued due to the synchronous part of libftdi. This should fix #38831 and #38659. - + 2013-04-25 Joerg Wunsch * configure.ac(AC_CONFIG_HEADERS): Replace the old AM_CONFIG_HEADER diff --git a/Makefile.am b/Makefile.am index 4d3a3e21..4147addd 100644 --- a/Makefile.am +++ b/Makefile.am @@ -140,6 +140,7 @@ libavrdude_a_SOURCES = \ pgm_type.h \ pickit2.c \ pickit2.h \ + pindefs.c \ pindefs.h \ ppi.c \ ppi.h \ diff --git a/avrdude.conf.in b/avrdude.conf.in index c645054f..f29d9e2c 100644 --- a/avrdude.conf.in +++ b/avrdude.conf.in @@ -645,10 +645,10 @@ programmer desc = "FT245R Synchronous BitBang"; type = "ftdi_syncbb"; connection_type = usb; - miso = 2; # D1 - sck = 1; # D0 - mosi = 3; # D2 - reset = 5; # D4 + miso = 1; # D1 + sck = 0; # D0 + mosi = 2; # D2 + reset = 4; # D4 ; programmer @@ -656,10 +656,10 @@ programmer desc = "FT232R Synchronous BitBang"; type = "ftdi_syncbb"; connection_type = usb; - miso = 2; # RxD - sck = 1; # RTS - mosi = 3; # TxD - reset = 5; # DTR + miso = 1; # RxD + sck = 0; # RTS + mosi = 2; # TxD + reset = 4; # DTR ; # see http://www.bitwizard.nl/wiki/index.php/FTDI_ATmega @@ -668,10 +668,10 @@ programmer desc = "BitWizard ftdi_atmega builtin programmer"; type = "ftdi_syncbb"; connection_type = usb; - miso = 6; # DSR - sck = 7; # DCD - mosi = 4; # CTS - reset = 8; # RI + miso = 5; # DSR + sck = 6; # DCD + mosi = 3; # CTS + reset = 7; # RI ; # see http://www.geocities.jp/arduino_diecimila/bootloader/index_en.html @@ -681,10 +681,10 @@ programmer desc = "Arduino: FT232R connected to ISP"; type = "ftdi_syncbb"; connection_type = usb; - miso = 4; # CTS X3(1) - sck = 6; # DSR X3(2) - mosi = 7; # DCD X3(3) - reset = 8; # RI X3(4) + miso = 3; # CTS X3(1) + sck = 5; # DSR X3(2) + mosi = 6; # DCD X3(3) + reset = 7; # RI X3(4) ; # website mentioned above uses this id diff --git a/avrftdi.c b/avrftdi.c index c931b3df..1742919a 100644 --- a/avrftdi.c +++ b/avrftdi.c @@ -1299,6 +1299,8 @@ void avrftdi_initpgm(PROGRAMMER * pgm) strcpy(pgm->type, "avrftdi"); + pgm_fill_old_pins(pgm); // TODO to be removed if old pin data no longer needed + /* * mandatory functions */ diff --git a/buspirate.c b/buspirate.c index 4f93c0d9..6d75a195 100644 --- a/buspirate.c +++ b/buspirate.c @@ -1283,6 +1283,8 @@ void buspirate_bb_initpgm(struct programmer_t *pgm) { strcpy(pgm->type, "BusPirate_BB"); + pgm_fill_old_pins(pgm); // TODO to be removed if old pin data no longer needed + pgm->display = buspirate_dummy_6; /* BusPirate itself related methods */ diff --git a/config_gram.y b/config_gram.y index 02deb57e..a04906dc 100644 --- a/config_gram.y +++ b/config_gram.y @@ -288,6 +288,8 @@ prog_def : pgm_free(existing_prog); } PUSH(programmers, current_prog); +// pgm_fill_old_pins(current_prog); // TODO to be removed if old pin data no longer needed +// pgm_display_generic(current_prog, id); current_prog = NULL; } ; @@ -533,24 +535,35 @@ prog_parm_usb: } ; -pin_number: +pin_number_non_empty: TKN_NUMBER { assign_pin(pin_name, $1, 0); } | TKN_TILDE TKN_NUMBER { assign_pin(pin_name, $2, 1); } - | - /* empty */ { current_prog->pinno[pin_name] = 0; } ; -pin_list: - num_list { assign_pin_list(0); } +pin_number: + pin_number_non_empty | - TKN_TILDE TKN_NUMBER { assign_pin(pin_name, $2, 1); } + /* empty */ { pin_clear_all(&(current_prog->pin[pin_name])); } +; + +pin_list_element: + pin_number_non_empty | TKN_TILDE TKN_LEFT_PAREN num_list TKN_RIGHT_PAREN { assign_pin_list(1); } +; + +pin_list_non_empty: + pin_list_element | - /* empty */ { - current_prog->pinno[pin_name] = 0; - } + pin_list_non_empty TKN_COMMA pin_list_element +; + + +pin_list: + pin_list_non_empty + | + /* empty */ { pin_clear_all(&(current_prog->pin[pin_name])); } ; prog_parm_pins: @@ -1353,10 +1366,8 @@ static int assign_pin(int pinno, TOKEN * v, int invert) progname, lineno, infile, PIN_MIN, PIN_MAX); exit(1); } - if (invert) - value |= PIN_INVERSE; - current_prog->pinno[pinno] = value; + pin_set_value(&(current_prog->pin[pinno]), value, invert); return 0; } @@ -1370,9 +1381,15 @@ static int assign_pin_list(int invert) while (lsize(number_list)) { t = lrmv_n(number_list, 1); pin = t->value.number; - current_prog->pinno[pin_name] |= (1 << pin); - if (invert) - current_prog->pinno[pin_name] |= PIN_INVERSE; + if ((pin < PIN_MIN) || (pin > PIN_MAX)) { + fprintf(stderr, + "%s: error at line %d of %s: pin must be in the " + "range %d-%d\n", + progname, lineno, infile, PIN_MIN, PIN_MAX); + exit(1); + /* TODO clear list and free tokens if no exit is done */ + } + pin_set_value(&(current_prog->pin[pin_name]), pin, invert); free_token(t); } diff --git a/ft245r.c b/ft245r.c index bd58f7b1..dfb0ff5d 100644 --- a/ft245r.c +++ b/ft245r.c @@ -25,10 +25,10 @@ /* ft245r -- FT245R/FT232R Synchronous BitBangMode Programmer default pin assign FT232R / FT245R - miso = 2; # RxD / D1 - sck = 1; # RTS / D0 - mosi = 3; # TxD / D2 - reset = 5; # DTR / D4 + miso = 1; # RxD / D1 + sck = 0; # RTS / D0 + mosi = 2; # TxD / D2 + reset = 4; # DTR / D4 */ /* @@ -105,10 +105,9 @@ typedef dispatch_semaphore_t sem_t; static struct ftdi_context *handle; static unsigned char ft245r_ddr; -static unsigned char ft245r_sck; -static unsigned char ft245r_mosi; -static unsigned char ft245r_reset; -static unsigned char ft245r_miso; +static unsigned char ft245r_out; +static unsigned char ft245r_in; +static unsigned char saved_signature[3]; #define BUFSIZE 0x2000 @@ -149,22 +148,6 @@ static void *reader (void *arg) { return NULL; } -static inline void setmybits(unsigned char *data, int pins, int v) { - if (v) { - *data |= (pins >> 1); - } else { - *data &= ~(pins >> 1); - } -} - -static inline void setmybit(unsigned char *data, int pinno, int v) { - if (v) { - *data |= (1 << (pinno-1)); - } else { - *data &= ~(1 <<(pinno-1)); - } -} - static int ft245r_send(PROGRAMMER * pgm, unsigned char * buf, size_t len) { int rv; @@ -235,7 +218,6 @@ static int ft245r_chip_erase(PROGRAMMER * pgm, AVRPART * p) { return 0; } -static unsigned char saved_signature[3]; static void ft245r_set_bitclock(PROGRAMMER * pgm) { int r; @@ -265,8 +247,19 @@ static void ft245r_set_bitclock(PROGRAMMER * pgm) { static int set_reset(PROGRAMMER * pgm, int val) { unsigned char buf[1]; - buf[0] = 0; - if (val) buf[0] |= ft245r_reset; + ft245r_out = SET_BITS_0(ft245r_out,pgm,PIN_AVR_RESET,val); + buf[0] = ft245r_out; + + ft245r_send (pgm, buf, 1); + ft245r_recv (pgm, buf, 1); + return 0; +} + +static int set_buff(PROGRAMMER * pgm, int val) { + unsigned char buf[1]; + + ft245r_out = SET_BITS_0(ft245r_out,pgm,PPI_AVR_BUFF,val); + buf[0] = ft245r_out; ft245r_send (pgm, buf, 1); ft245r_recv (pgm, buf, 1); @@ -335,55 +328,65 @@ static int ft245r_read_sig_bytes(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m) { return 3; } -#define check_pin(s) {\ - if ((pgm->pinno[s] & PIN_MASK) == 0) {\ - fprintf(stderr,\ - "%s: pin %s is not set\n",\ - progname,#s);\ - exit(1);\ - }\ - if ((pgm->pinno[s] & PIN_INVERSE) != 0) {\ - fprintf(stderr,\ - "%s: pin %s inverse is not supported.\n",\ - progname,#s);\ - exit(1);\ - }\ +static int ft245r_check_pins(PROGRAMMER * pgm){ + static const int pinlist[] = {PIN_AVR_SCK,PIN_AVR_MOSI,PIN_AVR_MISO,PIN_AVR_RESET,PPI_AVR_BUFF}; + static const pinmask_t valid_pins[PIN_FIELD_SIZE] = { 0x000000ff }; // only lower 8 pins are allowed + pinmask_t already_used[PIN_FIELD_SIZE] = {0}; + int i,j; + + for( i=0; ipin[pinlist[i]].mask[j] & ~valid_pins[j]){ + fprintf(stderr, + "%s: at least one pin is not a valid pin number\n", + progname); + exit(1); + } + // check if it does not use same pins as other function + if(pgm->pin[pinlist[i]].mask[j] & already_used[j]){ + fprintf(stderr, + "%s: at least one pin is set for multiple functions.\n", + progname); + exit(1); + } + already_used[j] |= pgm->pin[pinlist[i]].mask[j]; + } + } + return 0; } /* * initialize the AVR device and prepare it to accept commands */ static int ft245r_initialize(PROGRAMMER * pgm, AVRPART * p) { - check_pin(PIN_AVR_SCK); - check_pin(PIN_AVR_MOSI); - check_pin(PIN_AVR_MISO); - check_pin(PIN_AVR_RESET); + return ft245r_program_enable(pgm, p); } static void ft245r_disable(PROGRAMMER * pgm) { - return; + set_buff(pgm,0); } static void ft245r_enable(PROGRAMMER * pgm) { - /* Do nothing. */ - return; + set_buff(pgm,1); } -static inline int set_data(unsigned char *buf, unsigned char data) { +static inline int set_data(PROGRAMMER * pgm, unsigned char *buf, unsigned char data) { int j; int buf_pos = 0; unsigned char bit = 0x80; for (j=0; j<8; j++) { - buf[buf_pos] = 0; - if (data & bit) buf[buf_pos] |= ft245r_mosi; + ft245r_out = SET_BITS_0(ft245r_out,pgm,PIN_AVR_MOSI,data & bit); + + ft245r_out = SET_BITS_0(ft245r_out,pgm,PIN_AVR_SCK,0); + buf[buf_pos] = ft245r_out; buf_pos++; - buf[buf_pos] = 0; - if (data & bit) buf[buf_pos] |= ft245r_mosi; - buf[buf_pos] |= ft245r_sck; + ft245r_out = SET_BITS_0(ft245r_out,pgm,PIN_AVR_SCK,1); + buf[buf_pos] = ft245r_out; buf_pos++; bit >>= 1; @@ -391,7 +394,7 @@ static inline int set_data(unsigned char *buf, unsigned char data) { return buf_pos; } -static inline unsigned char extract_data(unsigned char *buf, int offset) { +static inline unsigned char extract_data(PROGRAMMER * pgm, unsigned char *buf, int offset) { int j; int buf_pos = 1; unsigned char bit = 0x80; @@ -399,7 +402,7 @@ static inline unsigned char extract_data(unsigned char *buf, int offset) { buf += offset * (8 * FT245R_CYCLES); for (j=0; j<8; j++) { - if (buf[buf_pos] & ft245r_miso) { + if (GET_BITS_0(buf[buf_pos],pgm,PIN_AVR_MISO)) { r |= bit; } buf_pos += FT245R_CYCLES; @@ -409,7 +412,7 @@ static inline unsigned char extract_data(unsigned char *buf, int offset) { } /* to check data */ -static inline unsigned char extract_data_out(unsigned char *buf, int offset) { +static inline unsigned char extract_data_out(PROGRAMMER * pgm, unsigned char *buf, int offset) { int j; int buf_pos = 1; unsigned char bit = 0x80; @@ -417,7 +420,7 @@ static inline unsigned char extract_data_out(unsigned char *buf, int offset) { buf += offset * (8 * FT245R_CYCLES); for (j=0; j<8; j++) { - if (buf[buf_pos] & ft245r_mosi) { + if (GET_BITS_0(buf[buf_pos],pgm,PIN_AVR_MOSI)) { r |= bit; } buf_pos += FT245R_CYCLES; @@ -438,17 +441,17 @@ static int ft245r_cmd(PROGRAMMER * pgm, unsigned char cmd[4], buf_pos = 0; for (i=0; i<4; i++) { - buf_pos += set_data(buf+buf_pos, cmd[i]); + buf_pos += set_data(pgm, buf+buf_pos, cmd[i]); } buf[buf_pos] = 0; buf_pos++; ft245r_send (pgm, buf, buf_pos); ft245r_recv (pgm, buf, buf_pos); - res[0] = extract_data(buf, 0); - res[1] = extract_data(buf, 1); - res[2] = extract_data(buf, 2); - res[3] = extract_data(buf, 3); + res[0] = extract_data(pgm, buf, 0); + res[1] = extract_data(pgm, buf, 1); + res[2] = extract_data(pgm, buf, 2); + res[3] = extract_data(pgm, buf, 3); return 0; } @@ -457,6 +460,9 @@ static int ft245r_cmd(PROGRAMMER * pgm, unsigned char cmd[4], static int ft245r_open(PROGRAMMER * pgm, char * port) { int rv; int devnum = -1; + + ft245r_check_pins(pgm); + strcpy(pgm->port, port); if (strcmp(port,DEFAULT_USB) != 0) { @@ -502,19 +508,29 @@ static int ft245r_open(PROGRAMMER * pgm, char * port) { sem_init (&buf_space, 0, BUFSIZE); pthread_create (&readerthread, NULL, reader, handle); - ft245r_ddr = 0; - setmybit(&ft245r_ddr, pgm->pinno[PIN_AVR_SCK], 1); - setmybit(&ft245r_ddr, pgm->pinno[PIN_AVR_MOSI], 1); - setmybit(&ft245r_ddr, pgm->pinno[PIN_AVR_RESET], 1); + ft245r_ddr = + pgm->pin[PIN_AVR_SCK].mask[0] + | pgm->pin[PIN_AVR_MOSI].mask[0] + | pgm->pin[PIN_AVR_RESET].mask[0] + | pgm->pin[PPI_AVR_BUFF].mask[0] + | pgm->pin[PPI_AVR_VCC].mask[0] + | pgm->pin[PIN_LED_ERR].mask[0] + | pgm->pin[PIN_LED_RDY].mask[0] + | pgm->pin[PIN_LED_PGM].mask[0] + | pgm->pin[PIN_LED_VFY].mask[0]; + + /* set initial values for outputs, no reset everything else is off */ + ft245r_out = 0; + ft245r_out = SET_BITS_0(ft245r_out,pgm,PIN_AVR_RESET,1); + ft245r_out = SET_BITS_0(ft245r_out,pgm,PIN_AVR_SCK,0); + ft245r_out = SET_BITS_0(ft245r_out,pgm,PIN_AVR_MOSI,0); + ft245r_out = SET_BITS_0(ft245r_out,pgm,PPI_AVR_BUFF,0); + ft245r_out = SET_BITS_0(ft245r_out,pgm,PPI_AVR_VCC,0); + ft245r_out = SET_BITS_0(ft245r_out,pgm,PIN_LED_ERR,0); + ft245r_out = SET_BITS_0(ft245r_out,pgm,PIN_LED_RDY,0); + ft245r_out = SET_BITS_0(ft245r_out,pgm,PIN_LED_PGM,0); + ft245r_out = SET_BITS_0(ft245r_out,pgm,PIN_LED_VFY,0); - ft245r_sck = 0; - setmybit(&ft245r_sck, pgm->pinno[PIN_AVR_SCK], 1); - ft245r_mosi = 0; - setmybit(&ft245r_mosi, pgm->pinno[PIN_AVR_MOSI], 1); - ft245r_reset = 0; - setmybit(&ft245r_reset, pgm->pinno[PIN_AVR_RESET], 1); - ft245r_miso = 0; - setmybit(&ft245r_miso, pgm->pinno[PIN_AVR_MISO], 1); rv = ftdi_set_bitmode(handle, ft245r_ddr, BITMODE_SYNCBB); // set Synchronous BitBang @@ -532,6 +548,9 @@ static int ft245r_open(PROGRAMMER * pgm, char * port) { */ ft245r_drain (pgm, 0); + ft245r_send (pgm, &ft245r_out, 1); + ft245r_recv (pgm, &ft245r_in, 1); + return 0; } @@ -548,8 +567,8 @@ static void ft245r_close(PROGRAMMER * pgm) { } static void ft245r_display(PROGRAMMER * pgm, const char * p) { - fprintf(stderr, "%sPin assignment : 1..8 = DBUS0..7, 9..12 = GPIO0..3\n",p); - pgm_display_generic_mask(pgm, p, SHOW_AVR_PINS); + fprintf(stderr, "%sPin assignment : 0..7 = DBUS0..7\n",p);/* , 8..11 = GPIO0..3\n",p);*/ + pgm_display_generic_mask(pgm, p, SHOW_AVR_PINS|1<buf[addr++] = extract_data(buf , (j * 4 + 3)); + m->buf[addr++] = extract_data(pgm, buf , (j * 4 + 3)); } return 1; } @@ -653,10 +672,10 @@ static int ft245r_paged_write_flash(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, buf_pos = 0; do_page_write = 0; for (j=0; j< FT245R_FRAGMENT_SIZE/8/FT245R_CYCLES/4; j++) { - buf_pos += set_data(buf+buf_pos, (addr & 1)?0x48:0x40 ); - buf_pos += set_data(buf+buf_pos, (addr >> 9) & 0xff ); - buf_pos += set_data(buf+buf_pos, (addr >> 1) & 0xff ); - buf_pos += set_data(buf+buf_pos, m->buf[addr]); + buf_pos += set_data(pgm, buf+buf_pos, (addr & 1)?0x48:0x40 ); + buf_pos += set_data(pgm, buf+buf_pos, (addr >> 9) & 0xff ); + buf_pos += set_data(pgm, buf+buf_pos, (addr >> 1) & 0xff ); + buf_pos += set_data(pgm, buf+buf_pos, m->buf[addr]); addr ++; i++; if ( (m->paged) && @@ -676,19 +695,20 @@ static int ft245r_paged_write_flash(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, memset(cmd, 0, 4); avr_set_bits(lext, cmd); avr_set_addr(lext, cmd, addr_wk/2); - buf_pos += set_data(buf+buf_pos, cmd[0]); - buf_pos += set_data(buf+buf_pos, cmd[1]); - buf_pos += set_data(buf+buf_pos, cmd[2]); - buf_pos += set_data(buf+buf_pos, cmd[3]); + buf_pos += set_data(pgm, buf+buf_pos, cmd[0]); + buf_pos += set_data(pgm, buf+buf_pos, cmd[1]); + buf_pos += set_data(pgm, buf+buf_pos, cmd[2]); + buf_pos += set_data(pgm, buf+buf_pos, cmd[3]); } - buf_pos += set_data(buf+buf_pos, 0x4C); /* Issue Page Write */ - buf_pos += set_data(buf+buf_pos,(addr_wk >> 9) & 0xff); - buf_pos += set_data(buf+buf_pos,(addr_wk >> 1) & 0xff); - buf_pos += set_data(buf+buf_pos, 0); + buf_pos += set_data(pgm, buf+buf_pos, 0x4C); /* Issue Page Write */ + buf_pos += set_data(pgm, buf+buf_pos,(addr_wk >> 9) & 0xff); + buf_pos += set_data(pgm, buf+buf_pos,(addr_wk >> 1) & 0xff); + buf_pos += set_data(pgm, buf+buf_pos, 0); } #endif if (i >= n_bytes) { - buf[buf_pos++] = 0; // sck down + ft245r_out = SET_BITS_0(ft245r_out,pgm,PIN_AVR_SCK,0); // sck down + buf[buf_pos++] = ft245r_out; } ft245r_send(pgm, buf, buf_pos); put_request(addr_save, buf_pos, 0); @@ -696,8 +716,8 @@ static int ft245r_paged_write_flash(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, #if 0 fprintf(stderr, "send addr 0x%04x bufsize %d [%02x %02x] page_write %d\n", addr_save,buf_pos, - extract_data_out(buf , (0*4 + 3) ), - extract_data_out(buf , (1*4 + 3) ), + extract_data_out(pgm, buf , (0*4 + 3) ), + extract_data_out(pgm, buf , (1*4 + 3) ), do_page_write); #endif req_count++; @@ -768,15 +788,16 @@ static int ft245r_paged_load_flash(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, addr_save = addr; for (j=0; j< FT245R_FRAGMENT_SIZE/8/FT245R_CYCLES/4; j++) { if (i >= n_bytes) break; - buf_pos += set_data(buf+buf_pos, (addr & 1)?0x28:0x20 ); - buf_pos += set_data(buf+buf_pos, (addr >> 9) & 0xff ); - buf_pos += set_data(buf+buf_pos, (addr >> 1) & 0xff ); - buf_pos += set_data(buf+buf_pos, 0); + buf_pos += set_data(pgm, buf+buf_pos, (addr & 1)?0x28:0x20 ); + buf_pos += set_data(pgm, buf+buf_pos, (addr >> 9) & 0xff ); + buf_pos += set_data(pgm, buf+buf_pos, (addr >> 1) & 0xff ); + buf_pos += set_data(pgm, buf+buf_pos, 0); addr ++; i++; } if (i >= n_bytes) { - buf[buf_pos++] = 0; // sck down + ft245r_out = SET_BITS_0(ft245r_out,pgm,PIN_AVR_SCK,0); // sck down + buf[buf_pos++] = ft245r_out; } n = j; ft245r_send(pgm, buf, buf_pos); diff --git a/linuxgpio.c b/linuxgpio.c index ed464f6b..e6452e2c 100644 --- a/linuxgpio.c +++ b/linuxgpio.c @@ -216,7 +216,8 @@ static int linuxgpio_highpulsepin(PROGRAMMER * pgm, int pin) static void linuxgpio_display(PROGRAMMER *pgm, const char *p) { - /* MAYBE */ + fprintf(stderr, "%sPin assignment : /sys/class/gpio/gpio{n}\n",p); + pgm_display_generic_mask(pgm, p, SHOW_AVR_PINS); } static void linuxgpio_enable(PROGRAMMER *pgm) @@ -311,6 +312,8 @@ void linuxgpio_initpgm(PROGRAMMER *pgm) { strcpy(pgm->type, "linuxgpio"); + pgm_fill_old_pins(pgm); // TODO to be removed if old pin data no longer needed + pgm->rdy_led = bitbang_rdy_led; pgm->err_led = bitbang_err_led; pgm->pgm_led = bitbang_pgm_led; diff --git a/main.c b/main.c index b9e91888..9c14147e 100644 --- a/main.c +++ b/main.c @@ -921,6 +921,12 @@ int main(int argc, char * argv []) pgm->ispdelay = ispdelay; } + if (verbose) { + avr_display(stderr, p, progbuf, verbose); + fprintf(stderr, "\n"); + programmer_display(pgm, progbuf); + } + rc = pgm->open(pgm, port); if (rc < 0) { exitrc = 1; @@ -937,7 +943,7 @@ int main(int argc, char * argv []) if (pgm->perform_osccal == 0) { fprintf(stderr, "%s: programmer does not support RC oscillator calibration\n", - progname); + progname); exitrc = 1; } else { fprintf(stderr, "%s: performing RC oscillator calibration\n", progname); @@ -951,12 +957,6 @@ int main(int argc, char * argv []) goto main_exit; } - if (verbose) { - avr_display(stderr, p, progbuf, verbose); - fprintf(stderr, "\n"); - programmer_display(pgm, progbuf); - } - if (quell_progress < 2) { fprintf(stderr, "\n"); } diff --git a/par.c b/par.c index 15d7c5ed..dab3293c 100644 --- a/par.c +++ b/par.c @@ -359,6 +359,8 @@ void par_initpgm(PROGRAMMER * pgm) { strcpy(pgm->type, "PPI"); + pgm_fill_old_pins(pgm); // TODO to be removed if old pin data no longer needed + pgm->exit_vcc = EXIT_VCC_UNSPEC; pgm->exit_reset = EXIT_RESET_UNSPEC; pgm->exit_datahigh = EXIT_DATAHIGH_UNSPEC; diff --git a/pgm.c b/pgm.c index c42a56fa..b82e0847 100644 --- a/pgm.c +++ b/pgm.c @@ -211,65 +211,57 @@ void programmer_display(PROGRAMMER * pgm, const char * p) pgm->display(pgm, p); } -static char * pins_to_str(unsigned int pmask) +static char * pins_to_str(const struct pindef_t * const pindef) { - static char buf[64]; + static char buf[(PIN_MAX+1)*5]; // should be enough for PIN_MAX=255 + char *p = buf; + int n; int pin; - char b2[8]; + const char * fmt; - if ((pmask & PIN_MASK) == 0) - return " (not used)"; - - buf[0] = ' '; - buf[1] = 0; - for (pin = 0; pin <= 17; pin++) { - if (pmask & (1 << pin)) { - sprintf(b2, "%d", pin); - if (buf[1] != 0) - strcat(buf, ","); - strcat(buf, b2); + buf[0] = 0; + for (pin = PIN_MIN; pin <= PIN_MAX; pin++) { + int index = pin/PIN_FIELD_ELEMENT_SIZE; + int bit = pin%PIN_FIELD_ELEMENT_SIZE; + if (pindef->mask[index] & (1 << bit)) { + if (pindef->inverse[index] & (1 << bit)) { + fmt = (buf[0]==0)?"~%d":",~%d"; + } else { + fmt = (buf[0]==0)?" %d":",%d"; + } + n = sprintf(p, fmt, pin); + p += n; } } - return buf; -} - -static char * pin_to_str(unsigned int pin) -{ - static char buf[12]; - - if ((pin & PIN_MASK) == 0) + if (buf[0] == 0) return " (not used)"; - buf[0] = (pin & PIN_INVERSE)?'~':' '; - buf[1] = 0; - sprintf(buf+1, "%d", pin & PIN_MASK); - return buf; } void pgm_display_generic_mask(PROGRAMMER * pgm, const char * p, unsigned int show) { if(show & (1<pinno[PPI_AVR_VCC])); + fprintf(stderr, "%s VCC = %s\n", p, pins_to_str(&pgm->pin[PPI_AVR_VCC])); if(show & (1<pinno[PPI_AVR_BUFF])); + fprintf(stderr, "%s BUFF = %s\n", p, pins_to_str(&pgm->pin[PPI_AVR_BUFF])); if(show & (1<pinno[PIN_AVR_RESET])); + fprintf(stderr, "%s RESET = %s\n", p, pins_to_str(&pgm->pin[PIN_AVR_RESET])); if(show & (1<pinno[PIN_AVR_SCK])); + fprintf(stderr, "%s SCK = %s\n", p, pins_to_str(&pgm->pin[PIN_AVR_SCK])); if(show & (1<pinno[PIN_AVR_MOSI])); + fprintf(stderr, "%s MOSI = %s\n", p, pins_to_str(&pgm->pin[PIN_AVR_MOSI])); if(show & (1<pinno[PIN_AVR_MISO])); + fprintf(stderr, "%s MISO = %s\n", p, pins_to_str(&pgm->pin[PIN_AVR_MISO])); if(show & (1<pinno[PIN_LED_ERR])); + fprintf(stderr, "%s ERR LED = %s\n", p, pins_to_str(&pgm->pin[PIN_LED_ERR])); if(show & (1<pinno[PIN_LED_RDY])); + fprintf(stderr, "%s RDY LED = %s\n", p, pins_to_str(&pgm->pin[PIN_LED_RDY])); if(show & (1<pinno[PIN_LED_PGM])); + fprintf(stderr, "%s PGM LED = %s\n", p, pins_to_str(&pgm->pin[PIN_LED_PGM])); if(show & (1<pinno[PIN_LED_VFY])); + fprintf(stderr, "%s VFY LED = %s\n", p, pins_to_str(&pgm->pin[PIN_LED_VFY])); } void pgm_display_generic(PROGRAMMER * pgm, const char * p) diff --git a/pgm.h b/pgm.h index 57eecc41..0ad7f59c 100644 --- a/pgm.h +++ b/pgm.h @@ -68,6 +68,7 @@ typedef struct programmer_t { char port[PGM_PORTLEN]; void (*initpgm)(struct programmer_t * pgm); unsigned int pinno[N_PINS]; + struct pindef_t pin[N_PINS]; exit_vcc_t exit_vcc; exit_reset_t exit_reset; exit_datahigh_t exit_datahigh; diff --git a/pindefs.c b/pindefs.c new file mode 100644 index 00000000..9ce9ddc3 --- /dev/null +++ b/pindefs.c @@ -0,0 +1,126 @@ +/* + * avrdude - A Downloader/Uploader for AVR device programmers + * Copyright (C) 2000-2004 Brian S. Dean + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/* $Id: pindefs.h 1132 2013-01-09 19:23:30Z rliebscher $ */ + +#include +#include +#include +#include "pindefs.h" +#include "pgm.h" + +/** + * Adds a pin in the pin definition as normal or inverse pin. + * + * @param[out] pindef pin definition to update + * @param[in] pin number of pin [0..PIN_MAX] + * @param[in] inverse inverse (true) or normal (false) pin + */ +void pin_set_value(struct pindef_t * const pindef, const int pin, const bool inverse){ + + pindef->mask[pin/PIN_FIELD_ELEMENT_SIZE] |= 1 << (pin % PIN_FIELD_ELEMENT_SIZE); + if (inverse) + pindef->inverse[pin/PIN_FIELD_ELEMENT_SIZE] |= (1 << (pin % PIN_FIELD_ELEMENT_SIZE)); + else + pindef->inverse[pin/PIN_FIELD_ELEMENT_SIZE] &= ~(1 << (pin % PIN_FIELD_ELEMENT_SIZE)); +} + +/** + * Clear all defined pins in pindef. + * + * @param[out] pindef pin definition to clear + */ +void pin_clear_all(struct pindef_t * const pindef){ + memset(pindef,0,sizeof(struct pindef_t)); +} + +/** + * Convert new pin definition to old pin number + * + * @param[in] pindef new pin definition structure + * @param[out] pinno old pin definition integer + */ +static void pin_fill_old_pinno(const struct pindef_t * const pindef, unsigned int * const pinno){ + bool found = false; + int i; + for (i=0;imask[i/PIN_FIELD_ELEMENT_SIZE] & (1 << (i % PIN_FIELD_ELEMENT_SIZE))){ + if(found){ + fprintf(stderr,"Multiple pins found\n"); //TODO + exit(1); + } + found = true; + *pinno = i; + if (pindef->inverse[i/PIN_FIELD_ELEMENT_SIZE] & (1 << (i % PIN_FIELD_ELEMENT_SIZE))){ + *pinno |= PIN_INVERSE; + } + } + } +} + +/** + * Convert new pin definition to old pinlist, does not support mixed inverted/non-inverted pin + * + * @param[in] pindef new pin definition structure + * @param[out] pinno old pin definition integer + */ +static void pin_fill_old_pinlist(const struct pindef_t * const pindef, unsigned int * const pinno){ + int i; + + for (i=0;imask[i] & ~PIN_MASK) != 0){ + fprintf(stderr,"Pins of higher index than max field size for old pinno found\n"); + exit(1); + } + if (pindef->mask[i] == pindef->inverse[i]) { /* all set bits in mask are set in inverse */ + *pinno = pindef->mask[i]; + *pinno |= PIN_INVERSE; + } else if (pindef->mask[i] == ((~pindef->inverse[i]) & pindef->mask[i])) { /* all set bits in mask are cleared in inverse */ + *pinno = pindef->mask[i]; + } else { + fprintf(stderr,"pins have different polarity set\n"); + exit(1); + } + } else if (pindef->mask[i] != 0){ + fprintf(stderr,"Pins have higher number than fit in old format\n"); + exit(1); + } + } +} + + +/** + * Convert for given programmer new pin definitions to old pin definitions. + * + * @param[inout] pgm programmer whose pins shall be converted. + */ +void pgm_fill_old_pins(struct programmer_t * const pgm) { + + pin_fill_old_pinlist(&(pgm->pin[PPI_AVR_VCC]), &(pgm->pinno[PPI_AVR_VCC])); + pin_fill_old_pinlist(&(pgm->pin[PPI_AVR_BUFF]), &(pgm->pinno[PPI_AVR_BUFF])); + pin_fill_old_pinno( &(pgm->pin[PIN_AVR_RESET]),&(pgm->pinno[PIN_AVR_RESET])); + pin_fill_old_pinno( &(pgm->pin[PIN_AVR_SCK]), &(pgm->pinno[PIN_AVR_SCK])); + pin_fill_old_pinno( &(pgm->pin[PIN_AVR_MOSI]), &(pgm->pinno[PIN_AVR_MOSI])); + pin_fill_old_pinno( &(pgm->pin[PIN_AVR_MISO]), &(pgm->pinno[PIN_AVR_MISO])); + pin_fill_old_pinno( &(pgm->pin[PIN_LED_ERR]), &(pgm->pinno[PIN_LED_ERR])); + pin_fill_old_pinno( &(pgm->pin[PIN_LED_RDY]), &(pgm->pinno[PIN_LED_RDY])); + pin_fill_old_pinno( &(pgm->pin[PIN_LED_PGM]), &(pgm->pinno[PIN_LED_PGM])); + pin_fill_old_pinno( &(pgm->pin[PIN_LED_VFY]), &(pgm->pinno[PIN_LED_VFY])); + +} \ No newline at end of file diff --git a/pindefs.h b/pindefs.h index 884ce0ff..8948dab9 100644 --- a/pindefs.h +++ b/pindefs.h @@ -23,6 +23,17 @@ #include +/* lets try to select at least 32 bits */ +#ifdef HAVE_STDINT_H +#include +typedef uint32_t pinmask_t; +#else +typedef unsigned long pinmask_t; +#endif + +#include + + enum { PPI_AVR_VCC=1, PPI_AVR_BUFF, @@ -36,9 +47,75 @@ enum { PIN_LED_VFY, N_PINS }; + #define PIN_MASK (UINT_MAX>>1) #define PIN_INVERSE (~(PIN_MASK)) /* flag for inverted pin in serbb */ -#define PIN_MIN 1 /* smallest allowed pin number */ +#define PIN_MIN 0 /* smallest allowed pin number */ +#define PIN_MAX 31 /* largest allowed pin number */ + +#ifdef HAVE_LINUX_GPIO +/* Embedded systems might have a lot more gpio than only 0-31 */ +#undef PIN_MAX #define PIN_MAX 255 /* largest allowed pin number */ +#endif + +/** Number of pins in each element of the bitfield */ +#define PIN_FIELD_ELEMENT_SIZE (sizeof(pinmask_t) * 8) +/** Numer of elements to store the complete bitfield of all pins */ +#define PIN_FIELD_SIZE ((PIN_MAX + PIN_FIELD_ELEMENT_SIZE)/PIN_FIELD_ELEMENT_SIZE) + +/** + * This sets the corresponding bits to 1 or 0, the inverse mask is used to invert the value in necessary. + * It uses only the lowest element (index=0) of the bitfield, which should be enough for most + * programmers. + * + * @param[in] x input value + * @param[in] pgm the programmer whose pin definitions to use + * @param[in] pinname the logical name of the pin (PIN_AVR_*, ...) + * @param[in] level the logical level (level != 0 => 1, level == 0 => 0), + * if the pin is defined as inverted the resulting bit is also inverted + * @returns the input value with the relevant bits modified + */ +#define SET_BITS_0(x,pgm,pinname,level) (((x) & ~(pgm)->pin[pinname].mask[0]) \ + | (\ + (pgm)->pin[pinname].mask[0] & ( \ + (level) \ + ?~((pgm)->pin[pinname].inverse[0]) \ + : ((pgm)->pin[pinname].inverse[0]) \ + ) \ + ) \ +) + +/** + * Check if the corresponding bit is set (returns != 0) or cleared. + * The inverse mask is used, to invert the relevant bits. + * If the pin definition contains multiple pins, then a single set pin leads to return value != 0. + * Then you have to check the relevant bits of the returned value, if you need more information. + * It uses only the lowest element (index=0) of the bitfield, which should be enough for most + * programmers. + * + * @param[in] x input value + * @param[in] pgm the programmer whose pin definitions to use + * @param[in] pinname the logical name of the pin (PIN_AVR_*, ...) + * @returns the input value with only the relevant bits (which are already inverted, + * so you get always the logical level) + */ +#define GET_BITS_0(x,pgm,pinname) (((x) ^ (pgm)->pin[pinname].inverse[0]) & (pgm)->pin[pinname].mask[0]) + +/** + * Data structure to hold used pins by logical function (PIN_AVR_*, ...) + */ +struct pindef_t { + pinmask_t mask[PIN_FIELD_SIZE]; ///< bitfield of used pins + pinmask_t inverse[PIN_FIELD_SIZE]; ///< bitfield of inverse/normal usage of used pins +}; + +void pin_set_value(struct pindef_t * const pindef, const int pin, const bool inverse); + +void pin_clear_all(struct pindef_t * const pindef); + +struct programmer_t; /* forward declaration */ +void pgm_fill_old_pins(struct programmer_t * const pgm); #endif + diff --git a/serbb_posix.c b/serbb_posix.c index efade447..da9e5830 100644 --- a/serbb_posix.c +++ b/serbb_posix.c @@ -289,6 +289,8 @@ void serbb_initpgm(PROGRAMMER *pgm) { strcpy(pgm->type, "SERBB"); + pgm_fill_old_pins(pgm); // TODO to be removed if old pin data no longer needed + pgm->rdy_led = bitbang_rdy_led; pgm->err_led = bitbang_err_led; pgm->pgm_led = bitbang_pgm_led; diff --git a/serbb_win32.c b/serbb_win32.c index a12675a6..58a5147e 100644 --- a/serbb_win32.c +++ b/serbb_win32.c @@ -350,6 +350,8 @@ void serbb_initpgm(PROGRAMMER *pgm) { strcpy(pgm->type, "SERBB"); + pgm_fill_old_pins(pgm); // TODO to be removed if old pin data no longer needed + pgm->rdy_led = bitbang_rdy_led; pgm->err_led = bitbang_err_led; pgm->pgm_led = bitbang_pgm_led;