use bitbanging on ftdi mpsse when wrong pins are used
* avrftdi.c, avrftdi_private.h: added additional pin check and bitbanging fallback * pindefs.[ch]: added a flag to enable/disable output * ft245r.c: changes because of added flag above git-svn-id: svn://svn.savannah.nongnu.org/avrdude/trunk/avrdude@1184 81a1dc3b-b13d-400b-aceb-764788c761c2
This commit is contained in:
parent
46f7b6b470
commit
da3961e155
|
@ -1,3 +1,11 @@
|
|||
2013-06-19 Rene Liebscher <R.Liebscher@gmx.de>
|
||||
|
||||
use bitbanging on ftdi mpsse when wrong pins are used
|
||||
* avrftdi.c, avrftdi_private.h: added additional pin check
|
||||
and bitbanging fallback
|
||||
* pindefs.[ch]: added a flag to enable/disable output
|
||||
* ft245r.c: changes because of added flag above
|
||||
|
||||
2013-05-17 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
|
||||
|
||||
Submitted by "Malte" and John McCorquodale:
|
||||
|
|
265
avrftdi.c
265
avrftdi.c
|
@ -295,12 +295,124 @@ static void avrftdi_powerdown(PROGRAMMER * pgm)
|
|||
set_pin(pgm, PPI_AVR_VCC, OFF);
|
||||
}
|
||||
|
||||
static inline int set_data(PROGRAMMER * pgm, unsigned char *buf, unsigned char data, bool read_data) {
|
||||
int j;
|
||||
int buf_pos = 0;
|
||||
unsigned char bit = 0x80;
|
||||
avrftdi_t* pdata = to_pdata(pgm);
|
||||
|
||||
for (j=0; j<8; j++) {
|
||||
pdata->pin_value = SET_BITS_0(pdata->pin_value,pgm,PIN_AVR_MOSI,data & bit);
|
||||
pdata->pin_value = SET_BITS_0(pdata->pin_value,pgm,PIN_AVR_SCK,0);
|
||||
buf[buf_pos++] = SET_BITS_LOW;
|
||||
buf[buf_pos++] = (pdata->pin_value) & 0xff;
|
||||
buf[buf_pos++] = (pdata->pin_direction) & 0xff;
|
||||
buf[buf_pos++] = SET_BITS_HIGH;
|
||||
buf[buf_pos++] = ((pdata->pin_value) >> 8) & 0xff;
|
||||
buf[buf_pos++] = ((pdata->pin_direction) >> 8) & 0xff;
|
||||
|
||||
pdata->pin_value = SET_BITS_0(pdata->pin_value,pgm,PIN_AVR_SCK,1);
|
||||
buf[buf_pos++] = SET_BITS_LOW;
|
||||
buf[buf_pos++] = (pdata->pin_value) & 0xff;
|
||||
buf[buf_pos++] = (pdata->pin_direction) & 0xff;
|
||||
buf[buf_pos++] = SET_BITS_HIGH;
|
||||
buf[buf_pos++] = ((pdata->pin_value) >> 8) & 0xff;
|
||||
buf[buf_pos++] = ((pdata->pin_direction) >> 8) & 0xff;
|
||||
|
||||
if (read_data) {
|
||||
buf[buf_pos++] = GET_BITS_LOW;
|
||||
buf[buf_pos++] = GET_BITS_HIGH;
|
||||
}
|
||||
|
||||
bit >>= 1;
|
||||
}
|
||||
return buf_pos;
|
||||
}
|
||||
|
||||
static inline unsigned char extract_data(PROGRAMMER * pgm, unsigned char *buf, int offset) {
|
||||
int j;
|
||||
unsigned char bit = 0x80;
|
||||
unsigned char r = 0;
|
||||
|
||||
buf += offset * 16; // 2 bytes per bit, 8 bits
|
||||
for (j=0; j<8; j++) {
|
||||
uint16_t in = buf[0] | (buf[1] << 8);
|
||||
if (GET_BITS_0(in,pgm,PIN_AVR_MISO)) {
|
||||
r |= bit;
|
||||
}
|
||||
buf += 2; // 2 bytes per input
|
||||
bit >>= 1;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
static int avrftdi_transmit_bb(PROGRAMMER * pgm, unsigned char mode, unsigned char *buf,
|
||||
unsigned char *data, int buf_size)
|
||||
{
|
||||
size_t blocksize;
|
||||
size_t remaining = buf_size;
|
||||
size_t written = 0;
|
||||
avrftdi_t* pdata = to_pdata(pgm);
|
||||
|
||||
// more than this does not work with FT2232D
|
||||
blocksize = 16;//pdata->rx_buffer_size/2; // we are reading 2 bytes per data byte
|
||||
|
||||
while(remaining)
|
||||
{
|
||||
|
||||
size_t transfer_size = (remaining > blocksize) ? blocksize : remaining;
|
||||
|
||||
// (8*2) outputs per data byte, 6 transmit bytes per output (SET_BITS_LOW/HIGH),
|
||||
// (8*1) inputs per data byte, 2 transmit bytes per input (GET_BITS_LOW/HIGH),
|
||||
// 1x SEND_IMMEDIATE
|
||||
unsigned char send_buffer[(8*2*6)*transfer_size+(8*1*2)*transfer_size+7];
|
||||
int len = 0;
|
||||
int i;
|
||||
|
||||
for(i = 0 ; i< transfer_size; i++) {
|
||||
len += set_data(pgm, send_buffer + len, buf[written+i], (mode & MPSSE_DO_READ) != 0);
|
||||
}
|
||||
|
||||
pdata->pin_value = SET_BITS_0(pdata->pin_value,pgm,PIN_AVR_SCK,0);
|
||||
send_buffer[len++] = SET_BITS_LOW;
|
||||
send_buffer[len++] = (pdata->pin_value) & 0xff;
|
||||
send_buffer[len++] = (pdata->pin_direction) & 0xff;
|
||||
send_buffer[len++] = SET_BITS_HIGH;
|
||||
send_buffer[len++] = ((pdata->pin_value) >> 8) & 0xff;
|
||||
send_buffer[len++] = ((pdata->pin_direction) >> 8) & 0xff;
|
||||
|
||||
send_buffer[len++] = SEND_IMMEDIATE;
|
||||
|
||||
E(ftdi_write_data(pdata->ftdic, send_buffer, len) != len, pdata->ftdic);
|
||||
if (mode & MPSSE_DO_READ) {
|
||||
unsigned char recv_buffer[2*16*transfer_size];
|
||||
int n;
|
||||
int k = 0;
|
||||
do {
|
||||
n = ftdi_read_data(pdata->ftdic, &recv_buffer[k], 2*16*transfer_size - k);
|
||||
E(n < 0, pdata->ftdic);
|
||||
k += n;
|
||||
} while (k < transfer_size);
|
||||
|
||||
for(i = 0 ; i< transfer_size; i++) {
|
||||
data[written + i] = extract_data(pgm, recv_buffer, i);
|
||||
}
|
||||
}
|
||||
|
||||
written += transfer_size;
|
||||
remaining -= transfer_size;
|
||||
}
|
||||
|
||||
return written;
|
||||
}
|
||||
|
||||
/* Send 'buf_size' bytes from 'cmd' to device and return data from device in
|
||||
* buffer 'data'.
|
||||
* Write is only performed when mode contains MPSSE_DO_WRITE.
|
||||
* Read is only performed when mode contains MPSSE_DO_WRITE and MPSSE_DO_READ.
|
||||
*/
|
||||
static int avrftdi_transmit(avrftdi_t* pdata, unsigned char mode, unsigned char *buf,
|
||||
static int avrftdi_transmit_mpsse(avrftdi_t* pdata, unsigned char mode, unsigned char *buf,
|
||||
unsigned char *data, int buf_size)
|
||||
{
|
||||
size_t blocksize;
|
||||
|
@ -358,6 +470,15 @@ static int avrftdi_transmit(avrftdi_t* pdata, unsigned char mode, unsigned char
|
|||
return written;
|
||||
}
|
||||
|
||||
static inline int avrftdi_transmit(PROGRAMMER * pgm, unsigned char mode, unsigned char *buf,
|
||||
unsigned char *data, int buf_size)
|
||||
{
|
||||
avrftdi_t* pdata = to_pdata(pgm);
|
||||
if (pdata->use_bitbanging)
|
||||
return avrftdi_transmit_bb(pgm, mode, buf, data, buf_size);
|
||||
else
|
||||
return avrftdi_transmit_mpsse(pdata, mode, buf, data, buf_size);
|
||||
}
|
||||
/* this function tries to sync up with the FTDI. See FTDI application note AN_129.
|
||||
* AN_135 uses 0xab as bad command and enables/disables loopback around synchronisation.
|
||||
* This may fail if data is left in the buffer (i.e. avrdude aborted with ctrl-c)
|
||||
|
@ -477,14 +598,41 @@ static int write_flush(avrftdi_t* pdata)
|
|||
|
||||
}
|
||||
|
||||
static int avrftdi_pin_setup(PROGRAMMER * pgm)
|
||||
static int avrftdi_check_pins_bb(PROGRAMMER * pgm, bool output)
|
||||
{
|
||||
/*************
|
||||
* pin setup *
|
||||
*************/
|
||||
|
||||
int pin;
|
||||
|
||||
/* pin checklist. */
|
||||
struct pin_checklist_t pin_checklist[N_PINS];
|
||||
|
||||
avrftdi_t* pdata = to_pdata(pgm);
|
||||
|
||||
/* value for 8/12/16 bit wide interface */
|
||||
int valid_mask = ((1 << pdata->pin_limit) - 1);
|
||||
|
||||
log_debug("Using valid mask bibanging: 0x%08x\n", valid_mask);
|
||||
static struct pindef_t valid_pins;
|
||||
valid_pins.mask[0] = valid_mask;
|
||||
valid_pins.inverse[0] = valid_mask ;
|
||||
|
||||
/* build pin checklist */
|
||||
for(pin = 0; pin < N_PINS; ++pin) {
|
||||
pin_checklist[pin].pinname = pin;
|
||||
pin_checklist[pin].mandatory = 0;
|
||||
pin_checklist[pin].valid_pins = &valid_pins;
|
||||
}
|
||||
|
||||
/* assumes all checklists above have same number of entries */
|
||||
return pins_check(pgm, pin_checklist, N_PINS, output);
|
||||
}
|
||||
|
||||
static int avrftdi_check_pins_mpsse(PROGRAMMER * pgm, bool output)
|
||||
{
|
||||
int pin;
|
||||
|
||||
/* pin checklist. */
|
||||
struct pin_checklist_t pin_checklist[N_PINS];
|
||||
|
||||
avrftdi_t* pdata = to_pdata(pgm);
|
||||
|
||||
/* SCK/MOSI/MISO are fixed and not invertable?*/
|
||||
|
@ -498,24 +646,67 @@ static int avrftdi_pin_setup(PROGRAMMER * pgm)
|
|||
/* mask out SCK/MISO/MOSI */
|
||||
valid_mask &= ~((1 << FTDI_SCK) | (1 << FTDI_MOSI) | (1 << FTDI_MISO));
|
||||
|
||||
log_debug("Using valid mask: 0x%08x\n", valid_mask);
|
||||
log_debug("Using valid mask mpsse: 0x%08x\n", valid_mask);
|
||||
static struct pindef_t valid_pins_others;
|
||||
valid_pins_others.mask[0] = valid_mask;
|
||||
valid_pins_others.inverse[0] = valid_mask ;
|
||||
|
||||
/* build pin checklist */
|
||||
for(pin = 0; pin < N_PINS; ++pin) {
|
||||
pdata->pin_checklist[pin].pinname = pin;
|
||||
pdata->pin_checklist[pin].mandatory = 0;
|
||||
pdata->pin_checklist[pin].valid_pins = &valid_pins_others;
|
||||
pin_checklist[pin].pinname = pin;
|
||||
pin_checklist[pin].mandatory = 0;
|
||||
pin_checklist[pin].valid_pins = &valid_pins_others;
|
||||
}
|
||||
pdata->pin_checklist[PIN_AVR_SCK].mandatory = 1;
|
||||
pdata->pin_checklist[PIN_AVR_SCK].valid_pins = &valid_pins_SCK;
|
||||
pdata->pin_checklist[PIN_AVR_MOSI].mandatory = 1;
|
||||
pdata->pin_checklist[PIN_AVR_MOSI].valid_pins = &valid_pins_MOSI;
|
||||
pdata->pin_checklist[PIN_AVR_MISO].mandatory = 1;
|
||||
pdata->pin_checklist[PIN_AVR_MISO].valid_pins = &valid_pins_MISO;
|
||||
pdata->pin_checklist[PIN_AVR_RESET].mandatory = 1;
|
||||
|
||||
/* now set mpsse specific pins */
|
||||
pin_checklist[PIN_AVR_SCK].mandatory = 1;
|
||||
pin_checklist[PIN_AVR_SCK].valid_pins = &valid_pins_SCK;
|
||||
pin_checklist[PIN_AVR_MOSI].mandatory = 1;
|
||||
pin_checklist[PIN_AVR_MOSI].valid_pins = &valid_pins_MOSI;
|
||||
pin_checklist[PIN_AVR_MISO].mandatory = 1;
|
||||
pin_checklist[PIN_AVR_MISO].valid_pins = &valid_pins_MISO;
|
||||
pin_checklist[PIN_AVR_RESET].mandatory = 1;
|
||||
|
||||
/* assumes all checklists above have same number of entries */
|
||||
return pins_check(pgm, pin_checklist, N_PINS, output);
|
||||
}
|
||||
|
||||
static int avrftdi_pin_setup(PROGRAMMER * pgm)
|
||||
{
|
||||
int pin;
|
||||
|
||||
/*************
|
||||
* pin setup *
|
||||
*************/
|
||||
|
||||
avrftdi_t* pdata = to_pdata(pgm);
|
||||
|
||||
bool pin_check_mpsse = (0 == avrftdi_check_pins_mpsse(pgm, verbose>3));
|
||||
|
||||
bool pin_check_bitbanging = (0 == avrftdi_check_pins_bb(pgm, verbose>3));
|
||||
|
||||
if (!pin_check_mpsse && !pin_check_bitbanging) {
|
||||
log_err("No valid pin configuration found.\n");
|
||||
avrftdi_check_pins_bb(pgm, true);
|
||||
log_err("Pin configuration for FTDI MPSSE must be:\n");
|
||||
log_err("%s: 0, %s: 1, %s: 2 (is: %s, %s, %s)\n", avr_pin_name(PIN_AVR_SCK),
|
||||
avr_pin_name(PIN_AVR_MOSI), avr_pin_name(PIN_AVR_MISO),
|
||||
pins_to_str(&pgm->pin[PIN_AVR_SCK]),
|
||||
pins_to_str(&pgm->pin[PIN_AVR_MOSI]),
|
||||
pins_to_str(&pgm->pin[PIN_AVR_MISO]));
|
||||
log_err("If other pin configuration is used, fallback to slower bitbanging mode is used.\n");
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
pdata->use_bitbanging = !pin_check_mpsse || 1;
|
||||
if (pdata->use_bitbanging) log_info("Because of pin configuration fallback to bitbanging mode.\n");
|
||||
|
||||
/*
|
||||
* TODO: No need to fail for a wrongly configured led or something.
|
||||
* Maybe we should only fail for SCK; MISO, MOSI, RST (and probably
|
||||
* VCC and BUFF).
|
||||
*/
|
||||
|
||||
/* everything is an output, except MISO */
|
||||
for(pin = 0; pin < N_PINS; ++pin) {
|
||||
|
@ -528,25 +719,6 @@ static int avrftdi_pin_setup(PROGRAMMER * pgm)
|
|||
pdata->led_mask |= pgm->pin[pin].mask[0];
|
||||
}
|
||||
|
||||
/* assumes all checklists above have same number of entries */
|
||||
if (pins_check(pgm, pdata->pin_checklist,N_PINS)) {
|
||||
log_err("Pin configuration for FTDI MPSSE must be:\n");
|
||||
log_err("%s: 0, %s: 1, %s: 2 (is: %s, %s, %s)\n", avr_pin_name(PIN_AVR_SCK),
|
||||
avr_pin_name(PIN_AVR_MOSI), avr_pin_name(PIN_AVR_MISO),
|
||||
pins_to_str(&pgm->pin[PIN_AVR_SCK]),
|
||||
pins_to_str(&pgm->pin[PIN_AVR_MOSI]),
|
||||
pins_to_str(&pgm->pin[PIN_AVR_MISO]));
|
||||
log_err("Please correct your cabling and/or configuration.\n");
|
||||
log_err("If your hardware is fixed, consider using a bitbang programmer.\n");
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO: No need to fail for a wrongly configured led or something.
|
||||
* Maybe we should only fail for SCK; MISO, MOSI, RST (and probably
|
||||
* VCC and BUFF).
|
||||
*/
|
||||
|
||||
log_info("Pin direction mask: %04x\n", pdata->pin_direction);
|
||||
log_info("Pin value mask: %04x\n", pdata->pin_value);
|
||||
|
@ -754,7 +926,7 @@ static int avrftdi_cmd(PROGRAMMER * pgm, unsigned char cmd[4], unsigned char res
|
|||
{
|
||||
/* Do not use 'sizeof(cmd)'. => message from cppcheck:
|
||||
Using sizeof for array given as function argument returns the size of pointer. */
|
||||
return avrftdi_transmit(to_pdata(pgm), MPSSE_DO_READ | MPSSE_DO_WRITE, cmd, res, 4);
|
||||
return avrftdi_transmit(pgm, MPSSE_DO_READ | MPSSE_DO_WRITE, cmd, res, 4);
|
||||
}
|
||||
|
||||
|
||||
|
@ -838,8 +1010,7 @@ avrftdi_lext(avrftdi_t* pdata, AVRPART *p, AVRMEM *m, unsigned int address)
|
|||
static int avrftdi_eeprom_write(PROGRAMMER *pgm, AVRPART *p, AVRMEM *m,
|
||||
unsigned int page_size, unsigned int addr, unsigned int len)
|
||||
{
|
||||
unsigned char cmd[] =
|
||||
{ MPSSE_DO_WRITE | MPSSE_WRITE_NEG, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||
unsigned char cmd[] = { 0x00, 0x00, 0x00, 0x00 };
|
||||
unsigned char *data = &m->buf[addr];
|
||||
unsigned int add;
|
||||
|
||||
|
@ -847,14 +1018,12 @@ static int avrftdi_eeprom_write(PROGRAMMER *pgm, AVRPART *p, AVRMEM *m,
|
|||
|
||||
for (add = addr; add < addr + len; add++)
|
||||
{
|
||||
avr_set_addr(m->op[AVR_OP_WRITE], &cmd[3], add);
|
||||
avr_set_input(m->op[AVR_OP_WRITE], &cmd[3], *data++);
|
||||
|
||||
//avrftdi_transmit(to_pdata(pgm), MPSSE_DO_WRITE, cmd, cmd, 4);
|
||||
E(ftdi_write_data(to_pdata(pgm)->ftdic, cmd, sizeof(cmd)) != sizeof(cmd),
|
||||
to_pdata(pgm)->ftdic);
|
||||
avr_set_addr(m->op[AVR_OP_WRITE], cmd, add);
|
||||
avr_set_input(m->op[AVR_OP_WRITE], cmd, *data++);
|
||||
|
||||
avrftdi_transmit(pgm, MPSSE_DO_WRITE, cmd, cmd, 4);
|
||||
usleep((m->max_write_delay));
|
||||
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
@ -873,7 +1042,7 @@ static int avrftdi_eeprom_read(PROGRAMMER *pgm, AVRPART *p, AVRMEM *m,
|
|||
avr_set_bits(m->op[AVR_OP_READ], cmd);
|
||||
avr_set_addr(m->op[AVR_OP_READ], cmd, add);
|
||||
|
||||
avrftdi_transmit(to_pdata(pgm), MPSSE_DO_READ | MPSSE_DO_WRITE, cmd, cmd, 4);
|
||||
avrftdi_transmit(pgm, MPSSE_DO_READ | MPSSE_DO_WRITE, cmd, cmd, 4);
|
||||
|
||||
avr_get_output(m->op[AVR_OP_READ], cmd, bufptr++);
|
||||
}
|
||||
|
@ -963,7 +1132,7 @@ static int avrftdi_flash_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
|||
buf_dump(buf, buf_size, "command buffer", 0, 16*2);
|
||||
|
||||
log_info("Transmitting buffer of size: %d\n", buf_size);
|
||||
avrftdi_transmit(to_pdata(pgm), MPSSE_DO_WRITE, buf, buf, buf_size);
|
||||
avrftdi_transmit(pgm, MPSSE_DO_WRITE, buf, buf, buf_size);
|
||||
|
||||
bufptr = buf;
|
||||
/* find a poll byte. we cannot poll a value of 0xff, so look
|
||||
|
@ -1053,7 +1222,7 @@ static int avrftdi_flash_read(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
|||
buf_dump(o_buf, sizeof(o_buf), "o_buf", 0, 32);
|
||||
}
|
||||
|
||||
avrftdi_transmit(to_pdata(pgm), MPSSE_DO_READ | MPSSE_DO_WRITE, o_buf, i_buf, len * 4);
|
||||
avrftdi_transmit(pgm, MPSSE_DO_READ | MPSSE_DO_WRITE, o_buf, i_buf, len * 4);
|
||||
|
||||
if(verbose > TRACE) {
|
||||
buf_dump(i_buf, sizeof(i_buf), "i_buf", 0, 32);
|
||||
|
|
|
@ -78,8 +78,8 @@ typedef struct avrftdi_s {
|
|||
int pin_limit;
|
||||
/* internal RX buffer of the device. needed for INOUT transfers */
|
||||
int rx_buffer_size;
|
||||
/* pin checklist. */
|
||||
struct pin_checklist_t pin_checklist[N_PINS];
|
||||
/* use bitbanging instead of mpsse spi */
|
||||
bool use_bitbanging;
|
||||
} avrftdi_t;
|
||||
|
||||
void avrftdi_log(int level, const char * func, int line, const char * fmt, ...);
|
||||
|
|
2
ft245r.c
2
ft245r.c
|
@ -528,7 +528,7 @@ static int ft245r_open(PROGRAMMER * pgm, char * port) {
|
|||
int rv;
|
||||
int devnum = -1;
|
||||
|
||||
rv = pins_check(pgm,pin_checklist,sizeof(pin_checklist)/sizeof(pin_checklist[0]));
|
||||
rv = pins_check(pgm,pin_checklist,sizeof(pin_checklist)/sizeof(pin_checklist[0]), true);
|
||||
if(rv) {
|
||||
pgm->display(pgm, progbuf);
|
||||
return rv;
|
||||
|
|
49
pindefs.c
49
pindefs.c
|
@ -201,7 +201,7 @@ const char * pinmask_to_str(const pinmask_t * const pinmask) {
|
|||
* @param[in] size the number of entries in checklist
|
||||
* @returns 0 if all pin definitions are valid, -1 otherwise
|
||||
*/
|
||||
int pins_check(const struct programmer_t * const pgm, const struct pin_checklist_t * const checklist, const int size) {
|
||||
int pins_check(const struct programmer_t * const pgm, const struct pin_checklist_t * const checklist, const int size, bool output) {
|
||||
static const struct pindef_t no_valid_pins = {{0}, {0}}; // default value if check list does not contain anything else
|
||||
int rv = 0; // return value
|
||||
int pinname; // loop counter through pinnames
|
||||
|
@ -253,46 +253,53 @@ int pins_check(const struct programmer_t * const pgm, const struct pin_checklist
|
|||
already_used_all[segment] |= pgm->pin[pinname].mask[segment];
|
||||
}
|
||||
if(invalid) {
|
||||
fprintf(stderr,
|
||||
"%s: %s: Following pins are not valid pins for this function: %s\n",
|
||||
progname, avr_pin_name(pinname), pinmask_to_str(invalid_used));
|
||||
if(verbose >= 2) {
|
||||
if(output) {
|
||||
fprintf(stderr,
|
||||
"%s: %s: Valid pins for this function are: %s\n",
|
||||
progname, avr_pin_name(pinname), pinmask_to_str(valid_pins->mask));
|
||||
"%s: %s: Following pins are not valid pins for this function: %s\n",
|
||||
progname, avr_pin_name(pinname), pinmask_to_str(invalid_used));
|
||||
if(verbose >= 2) {
|
||||
fprintf(stderr,
|
||||
"%s: %s: Valid pins for this function are: %s\n",
|
||||
progname, avr_pin_name(pinname), pinmask_to_str(valid_pins->mask));
|
||||
}
|
||||
}
|
||||
is_ok = false;
|
||||
}
|
||||
if(inverse) {
|
||||
fprintf(stderr,
|
||||
if(output) {
|
||||
fprintf(stderr,
|
||||
"%s: %s: Following pins are not usable as inverse pins for this function: %s\n",
|
||||
progname, avr_pin_name(pinname), pinmask_to_str(inverse_used));
|
||||
if(verbose >= 2) {
|
||||
fprintf(stderr,
|
||||
"%s: %s: Valid inverse pins for this function are: %s\n",
|
||||
progname, avr_pin_name(pinname), pinmask_to_str(valid_pins->inverse));
|
||||
if(verbose >= 2) {
|
||||
fprintf(stderr,
|
||||
"%s: %s: Valid inverse pins for this function are: %s\n",
|
||||
progname, avr_pin_name(pinname), pinmask_to_str(valid_pins->inverse));
|
||||
}
|
||||
}
|
||||
is_ok = false;
|
||||
}
|
||||
if(used) {
|
||||
fprintf(stderr,
|
||||
"%s: %s: Following pins are set for other functions too: %s\n",
|
||||
progname, avr_pin_name(pinname), pinmask_to_str(already_used));
|
||||
is_ok = false;
|
||||
if(output) {
|
||||
fprintf(stderr,
|
||||
"%s: %s: Following pins are set for other functions too: %s\n",
|
||||
progname, avr_pin_name(pinname), pinmask_to_str(already_used));
|
||||
is_ok = false;
|
||||
}
|
||||
}
|
||||
if(!mandatory_used && is_mandatory && !invalid) {
|
||||
fprintf(stderr,
|
||||
"%s: %s: Mandatory pin is not defined.\n",
|
||||
progname, avr_pin_name(pinname));
|
||||
if(output) {
|
||||
fprintf(stderr,
|
||||
"%s: %s: Mandatory pin is not defined.\n",
|
||||
progname, avr_pin_name(pinname));
|
||||
}
|
||||
is_ok = false;
|
||||
}
|
||||
if(!is_ok) {
|
||||
rv = -1;
|
||||
} else if(verbose >= 3) {
|
||||
} else if(output && verbose >= 3) {
|
||||
fprintf(stderr,
|
||||
"%s: %s: Pin is ok.\n",
|
||||
progname, avr_pin_name(pinname));
|
||||
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
|
|
|
@ -165,9 +165,10 @@ void pgm_fill_old_pins(struct programmer_t * const pgm);
|
|||
* @param[in] pgm the programmer to check
|
||||
* @param[in] checklist the constraint for the pins
|
||||
* @param[in] size the number of entries in checklist
|
||||
* @param[in] output false suppresses error messages to the user
|
||||
* @returns 0 if all pin definitions are valid, -1 otherwise
|
||||
*/
|
||||
int pins_check(const struct programmer_t * const pgm, const struct pin_checklist_t * const checklist, const int size);
|
||||
int pins_check(const struct programmer_t * const pgm, const struct pin_checklist_t * const checklist, const int size, const bool output);
|
||||
|
||||
/**
|
||||
* Returns the name of the pin as string.
|
||||
|
|
Loading…
Reference in New Issue