mirror of
https://github.com/avrdudes/avrdude.git
synced 2026-09-29 04:18:54 +03:00
Merge pull request #1324 from jkent/avrftdi
add JTAG support to avrftdi
This commit is contained in:
@@ -32,6 +32,10 @@
|
||||
# sck = <pin> ; # pin number
|
||||
# sdo = <pin> ; # pin number
|
||||
# sdi = <pin> ; # pin number
|
||||
# tck = <pin> ; # pin number
|
||||
# tdi = <pin> ; # pin number
|
||||
# tdo = <pin> ; # pin number
|
||||
# tms = <pin> ; # pin number
|
||||
# errled = <pin> ; # pin number
|
||||
# rdyled = <pin> ; # pin number
|
||||
# pgmled = <pin> ; # pin number
|
||||
@@ -994,6 +998,26 @@ programmer parent "ft2232h"
|
||||
pgmled = ~10;
|
||||
;
|
||||
|
||||
#------------------------------------------------------------
|
||||
# ft2232h_jtag
|
||||
#------------------------------------------------------------
|
||||
|
||||
programmer
|
||||
id = "ft2232h_jtag";
|
||||
desc = "FT2232H based generic programmer";
|
||||
type = "avrftdi_jtag";
|
||||
prog_modes = PM_JTAG;
|
||||
connection_type = usb;
|
||||
usbvid = 0x0403;
|
||||
usbpid = 0x6010;
|
||||
usbdev = "A";
|
||||
# JTAG-signals - lower ADBUS-Nibble (default)
|
||||
tck = 0; # AD0 (TCK)
|
||||
tdi = 1; # AD1 (TDI)
|
||||
tdo = 2; # AD2 (TDO)
|
||||
tms = 3; # AD3 (TMS)
|
||||
;
|
||||
|
||||
#------------------------------------------------------------
|
||||
# ft4232h
|
||||
#------------------------------------------------------------
|
||||
@@ -1052,6 +1076,26 @@ programmer
|
||||
sdi = 2; # AD2 (TDO)
|
||||
;
|
||||
|
||||
#------------------------------------------------------------
|
||||
# ft232h_jtag
|
||||
#------------------------------------------------------------
|
||||
|
||||
programmer
|
||||
id = "ft232h_jtag";
|
||||
desc = "FT232H based generic JTAG programmer";
|
||||
type = "avrftdi_jtag";
|
||||
prog_modes = PM_JTAG;
|
||||
connection_type = usb;
|
||||
usbvid = 0x0403;
|
||||
usbpid = 0x6014;
|
||||
usbdev = "A";
|
||||
# JTAG-signals
|
||||
tck = 0; # AD0 (TCK)
|
||||
tdi = 1; # AD1 (TDI)
|
||||
tdo = 2; # AD2 (TDO)
|
||||
tms = 3; # AD3 (TMS)
|
||||
;
|
||||
|
||||
#------------------------------------------------------------
|
||||
# um232h
|
||||
#------------------------------------------------------------
|
||||
@@ -1156,22 +1200,38 @@ programmer
|
||||
# tumpa
|
||||
#------------------------------------------------------------
|
||||
|
||||
# submitted as bug #46020
|
||||
# First SPI connector
|
||||
# User manual: https://www.tiaowiki.com/w/TIAO_USB_Multi_Protocol_Adapter_User%27s_Manual
|
||||
|
||||
programmer
|
||||
programmer parent "ft2232h"
|
||||
id = "tumpa";
|
||||
desc = "TIAO USB Multi-Protocol Adapter";
|
||||
type = "avrftdi";
|
||||
prog_modes = PM_TPI | PM_ISP;
|
||||
connection_type = usb;
|
||||
usbvid = 0x0403;
|
||||
usbpid = 0x8a98;
|
||||
usbdev = "A";
|
||||
usbvendor = "TIAO";
|
||||
reset = 3; # TMS 7
|
||||
sck = 0; # TCK 9
|
||||
sdo = 1; # TDI 5
|
||||
sdi = 2; # TDO 13
|
||||
;
|
||||
|
||||
#------------------------------------------------------------
|
||||
# tumpa-b
|
||||
#------------------------------------------------------------
|
||||
|
||||
# Second SPI connector
|
||||
|
||||
programmer parent "tumpa"
|
||||
id = "tumpa-b";
|
||||
usbdev = "B";
|
||||
;
|
||||
|
||||
#------------------------------------------------------------
|
||||
# tumpa_jtag
|
||||
#------------------------------------------------------------
|
||||
|
||||
programmer parent "ft2232h_jtag"
|
||||
id = "tumpa_jtag";
|
||||
desc = "TIAO USB Multi-Protocol Adapter (JTAG)";
|
||||
usbpid = 0x8a98;
|
||||
usbvendor = "TIAO";
|
||||
buff = ~11;
|
||||
reset = 4; # RST AD4 (Pin 15)
|
||||
;
|
||||
|
||||
#------------------------------------------------------------
|
||||
|
||||
713
src/avrftdi.c
713
src/avrftdi.c
@@ -1,6 +1,7 @@
|
||||
/*
|
||||
* avrftdi - extension for avrdude, Wolfgang Moser, Ville Voipio
|
||||
* Copyright (C) 2011 Hannes Weisbach, Doug Springer
|
||||
* Copyright (C) 2023 Jeff Kent
|
||||
*
|
||||
* 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
|
||||
@@ -60,9 +61,27 @@ void avrftdi_initpgm(PROGRAMMER *pgm) {
|
||||
pgm->open = avrftdi_noftdi_open;
|
||||
}
|
||||
|
||||
void avrftdi_jtag_initpgm(PROGRAMMER *pgm) {
|
||||
strcpy(pgm->type, "avrftdi_jtag");
|
||||
pgm->open = avrftdi_noftdi_open;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
enum { FTDI_SCK = 0, FTDI_SDO, FTDI_SDI, FTDI_RESET };
|
||||
#define PGM_FL_IS_DW (0x0001)
|
||||
#define PGM_FL_IS_PDI (0x0002)
|
||||
#define PGM_FL_IS_JTAG (0x0004)
|
||||
#define PGM_FL_IS_EDBG (0x0008)
|
||||
#define PGM_FL_IS_UPDI (0x0010)
|
||||
#define PGM_FL_IS_TPI (0x0020)
|
||||
|
||||
/* MPSSE pins */
|
||||
enum {
|
||||
FTDI_TCK_SCK = 0,
|
||||
FTDI_TDI_SDO,
|
||||
FTDI_TDO_SDI,
|
||||
FTDI_TMS_CS,
|
||||
};
|
||||
|
||||
static int write_flush(avrftdi_t *);
|
||||
|
||||
@@ -186,37 +205,60 @@ static void buf_dump(const unsigned char *buf, int len, char *desc,
|
||||
*/
|
||||
static int set_frequency(avrftdi_t* ftdi, uint32_t freq)
|
||||
{
|
||||
int32_t divisor;
|
||||
uint8_t buf[3];
|
||||
int32_t clock, divisor;
|
||||
float hs_error, ls_error;
|
||||
uint8_t buf[4], *ptr = buf;
|
||||
|
||||
if (ftdi->ftdic->type == TYPE_232H ||
|
||||
ftdi->ftdic->type == TYPE_2232H ||
|
||||
ftdi->ftdic->type == TYPE_4232H) {
|
||||
|
||||
clock = 60000000;
|
||||
divisor = ((clock / 2) / freq) - 1;
|
||||
hs_error = (float)(clock / 2) / (divisor + 1) / freq;
|
||||
|
||||
clock = 12000000;
|
||||
divisor = ((clock / 2) / freq) - 1;
|
||||
ls_error = (float)(clock / 2) / (divisor + 1) / freq;
|
||||
|
||||
if (ls_error <= hs_error) {
|
||||
*ptr++ = EN_DIV_5;
|
||||
} else {
|
||||
clock = 60000000;
|
||||
divisor = ((clock / 2) / freq) - 1;
|
||||
*ptr++ = DIS_DIV_5;
|
||||
}
|
||||
} else {
|
||||
clock = 12000000;
|
||||
divisor = ((clock / 2) / freq) - 1;
|
||||
}
|
||||
|
||||
/* divisor on 6000000 / freq - 1 */
|
||||
divisor = (6000000 / freq) - 1;
|
||||
if (divisor < 0) {
|
||||
log_warn("Frequency too high (%u > 6 MHz)\n", freq);
|
||||
log_warn("Resetting Frequency to 6MHz\n");
|
||||
log_warn("Frequency too high (%u > %u MHz)\n", freq, clock / 2000000);
|
||||
log_warn("Resetting Frequency to %uMHz\n", clock / 2000000);
|
||||
divisor = 0;
|
||||
}
|
||||
|
||||
if (divisor > 65535) {
|
||||
log_warn("Frequency too low (%u < 91.553 Hz)\n", freq);
|
||||
log_warn("Resetting Frequency to 91.553Hz\n");
|
||||
log_warn("Frequency too low (%u < %.3f Hz)\n", freq, (float) clock / 2 / 65535);
|
||||
log_warn("Resetting Frequency to %.3fHz\n", (float) clock / 2 / 65535);
|
||||
divisor = 65535;
|
||||
}
|
||||
|
||||
log_info("Using frequency: %d\n", 6000000/(divisor+1));
|
||||
log_info("Using frequency: %d\n", clock / 2 / (divisor + 1));
|
||||
log_info("Clock divisor: 0x%04x\n", divisor);
|
||||
|
||||
buf[0] = TCK_DIVISOR;
|
||||
buf[1] = (uint8_t)(divisor & 0xff);
|
||||
buf[2] = (uint8_t)((divisor >> 8) & 0xff);
|
||||
*ptr++ = TCK_DIVISOR;
|
||||
*ptr++ = (uint8_t)(divisor & 0xff);
|
||||
*ptr++ = (uint8_t)(divisor >> 8) & 0xff;
|
||||
|
||||
E(ftdi_write_data(ftdi->ftdic, buf, 3) < 0, ftdi->ftdic);
|
||||
E(ftdi_write_data(ftdi->ftdic, buf, ptr - buf) < 0, ftdi->ftdic);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function sets or clears any pin, except SCK, SDI and SDO. Depending
|
||||
* This function sets or clears any pin, except mandatory pins. Depending
|
||||
* on the pin configuration, a non-zero value sets the pin in the 'active'
|
||||
* state (high active, low active) and a zero value sets the pin in the
|
||||
* inactive state.
|
||||
@@ -550,14 +592,21 @@ static int avrftdi_check_pins_mpsse(const PROGRAMMER *pgm, bool output) {
|
||||
|
||||
/* SCK/SDO/SDI are fixed and not invertible? */
|
||||
/* TODO: inverted SCK/SDI/SDO */
|
||||
static const struct pindef_t valid_pins_SCK = {{0x01},{0x00}};
|
||||
static const struct pindef_t valid_pins_SDO = {{0x02},{0x00}};
|
||||
static const struct pindef_t valid_pins_SDI = {{0x04},{0x00}};
|
||||
static const struct pindef_t valid_pins[4] = {
|
||||
{{0x01}, {0x00}},
|
||||
{{0x02}, {0x00}},
|
||||
{{0x04}, {0x00}},
|
||||
{{0x08}, {0x00}},
|
||||
};
|
||||
|
||||
/* value for 8/12/16 bit wide interface for other pins */
|
||||
int valid_mask = ((1 << pdata->pin_limit) - 1);
|
||||
/* mask out SCK/SDI/SDO */
|
||||
valid_mask &= ~((1 << FTDI_SCK) | (1 << FTDI_SDO) | (1 << FTDI_SDI));
|
||||
|
||||
/* mask MPSSE pins */
|
||||
valid_mask &= ~((1 << FTDI_TCK_SCK) | (1 << FTDI_TDI_SDO) | (1 << FTDI_TDO_SDI));
|
||||
if (pgm->flag == PGM_FL_IS_JTAG) {
|
||||
valid_mask &= ~(1 << FTDI_TMS_CS);
|
||||
}
|
||||
|
||||
log_debug("Using valid mask mpsse: 0x%08x\n", valid_mask);
|
||||
static struct pindef_t valid_pins_others;
|
||||
@@ -572,13 +621,24 @@ static int avrftdi_check_pins_mpsse(const PROGRAMMER *pgm, bool output) {
|
||||
}
|
||||
|
||||
/* now set mpsse specific pins */
|
||||
if (pgm->flag == PGM_FL_IS_JTAG) {
|
||||
pin_checklist[PIN_JTAG_TCK].mandatory = 1;
|
||||
pin_checklist[PIN_JTAG_TCK].valid_pins = &valid_pins[FTDI_TCK_SCK];
|
||||
pin_checklist[PIN_JTAG_TDI].mandatory = 1;
|
||||
pin_checklist[PIN_JTAG_TDI].valid_pins = &valid_pins[FTDI_TDI_SDO];
|
||||
pin_checklist[PIN_JTAG_TDO].mandatory = 1;
|
||||
pin_checklist[PIN_JTAG_TDO].valid_pins = &valid_pins[FTDI_TDO_SDI];
|
||||
pin_checklist[PIN_JTAG_TMS].mandatory = 1;
|
||||
pin_checklist[PIN_JTAG_TMS].valid_pins = &valid_pins[FTDI_TMS_CS];
|
||||
} else {
|
||||
pin_checklist[PIN_AVR_SCK].mandatory = 1;
|
||||
pin_checklist[PIN_AVR_SCK].valid_pins = &valid_pins_SCK;
|
||||
pin_checklist[PIN_AVR_SDO].mandatory = 1;
|
||||
pin_checklist[PIN_AVR_SDO].valid_pins = &valid_pins_SDO;
|
||||
pin_checklist[PIN_AVR_SDI].mandatory = 1;
|
||||
pin_checklist[PIN_AVR_SDI].valid_pins = &valid_pins_SDI;
|
||||
pin_checklist[PIN_AVR_RESET].mandatory = 1;
|
||||
pin_checklist[PIN_AVR_SCK].valid_pins = &valid_pins[FTDI_TCK_SCK];
|
||||
pin_checklist[PIN_AVR_SDO].mandatory = 1;
|
||||
pin_checklist[PIN_AVR_SDO].valid_pins = &valid_pins[FTDI_TDI_SDO];
|
||||
pin_checklist[PIN_AVR_SDI].mandatory = 1;
|
||||
pin_checklist[PIN_AVR_SDI].valid_pins = &valid_pins[FTDI_TDO_SDI];
|
||||
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);
|
||||
@@ -601,11 +661,23 @@ static int avrftdi_pin_setup(const PROGRAMMER *pgm) {
|
||||
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_SDO), avr_pin_name(PIN_AVR_SDI),
|
||||
pins_to_str(&pgm->pin[PIN_AVR_SCK]),
|
||||
pins_to_str(&pgm->pin[PIN_AVR_SDO]),
|
||||
pins_to_str(&pgm->pin[PIN_AVR_SDI]));
|
||||
if (pgm->flag == PGM_FL_IS_JTAG) {
|
||||
log_err("%s: 0, %s: 1, %s: 2, %s :3 (is: %s, %s, %s, %s)\n",
|
||||
avr_pin_name(PIN_JTAG_TCK), avr_pin_name(PIN_JTAG_TDI),
|
||||
avr_pin_name(PIN_JTAG_TDO), avr_pin_name(PIN_JTAG_TMS),
|
||||
pins_to_str(&pgm->pin[PIN_JTAG_TCK]),
|
||||
pins_to_str(&pgm->pin[PIN_JTAG_TDI]),
|
||||
pins_to_str(&pgm->pin[PIN_JTAG_TDO]),
|
||||
pins_to_str(&pgm->pin[PIN_JTAG_TMS]));
|
||||
} else {
|
||||
log_err("%s: 0, %s: 1, %s: 2 (is: %s, %s, %s)\n",
|
||||
avr_pin_name(PIN_AVR_SCK),
|
||||
avr_pin_name(PIN_AVR_SDO),
|
||||
avr_pin_name(PIN_AVR_SDI),
|
||||
pins_to_str(&pgm->pin[PIN_AVR_SCK]),
|
||||
pins_to_str(&pgm->pin[PIN_AVR_SDO]),
|
||||
pins_to_str(&pgm->pin[PIN_AVR_SDI]));
|
||||
}
|
||||
log_err("If other pin configuration is used, fallback to slower bitbanging mode is used.\n");
|
||||
|
||||
return -1;
|
||||
@@ -628,6 +700,20 @@ static int avrftdi_pin_setup(const PROGRAMMER *pgm) {
|
||||
}
|
||||
pdata->pin_direction &= ~pgm->pin[PIN_AVR_SDI].mask[0];
|
||||
|
||||
if (pgm->flag & PGM_FL_IS_JTAG) {
|
||||
if (!pdata->use_bitbanging) {
|
||||
pdata->pin_value &= ~pgm->pin[PIN_JTAG_TCK].mask[0];
|
||||
pdata->pin_value |= pgm->pin[PIN_JTAG_TCK].inverse[0];
|
||||
}
|
||||
pdata->pin_direction &= ~pgm->pin[PIN_JTAG_TDO].mask[0];
|
||||
} else {
|
||||
if (!pdata->use_bitbanging) {
|
||||
pdata->pin_value &= ~pgm->pin[PIN_AVR_SCK].mask[0];
|
||||
pdata->pin_value |= pgm->pin[PIN_AVR_SCK].inverse[0];
|
||||
}
|
||||
pdata->pin_direction &= ~pgm->pin[PIN_AVR_SDI].mask[0];
|
||||
}
|
||||
|
||||
for(pin = PIN_LED_ERR; pin < N_PINS; ++pin) {
|
||||
pdata->led_mask |= pgm->pin[pin].mask[0];
|
||||
}
|
||||
@@ -835,9 +921,14 @@ static int avrftdi_initialize(const PROGRAMMER *pgm, const AVRPART *p) {
|
||||
return pgm->program_enable(pgm, p);
|
||||
}
|
||||
|
||||
static void avrftdi_display(const PROGRAMMER *pgm, const char *p) {
|
||||
// print the full pin definitions as in ft245r ?
|
||||
return;
|
||||
static void avrftdi_display(const PROGRAMMER *pgm, const char *p)
|
||||
{
|
||||
msg_info("%sPin assignment : 0..7 = DBUS0..7, 8..15 = CBUS0..7\n", p);
|
||||
if (pgm->flag & PGM_FL_IS_JTAG) {
|
||||
pgm_display_generic_mask(pgm, p, SHOW_ALL_PINS & ~SHOW_AVR_PINS);
|
||||
} else {
|
||||
pgm_display_generic_mask(pgm, p, SHOW_ALL_PINS & ~SHOW_JTAG_PINS);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1219,13 +1310,523 @@ avrftdi_teardown(PROGRAMMER * pgm)
|
||||
}
|
||||
}
|
||||
|
||||
void avrftdi_initpgm(PROGRAMMER *pgm) {
|
||||
/******************/
|
||||
/* JTAG functions */
|
||||
/******************/
|
||||
|
||||
static int avrftdi_jtag_reset(const PROGRAMMER *pgm)
|
||||
{
|
||||
avrftdi_t *pdata = to_pdata(pgm);
|
||||
unsigned char buf[3], *ptr = buf;
|
||||
|
||||
/* Unknown -> Reset -> Run-Test/Idle */
|
||||
*ptr++ = MPSSE_WRITE_TMS | MPSSE_LSB | MPSSE_BITMODE | MPSSE_WRITE_NEG;
|
||||
*ptr++ = 5;
|
||||
*ptr++ = 0x1f;
|
||||
|
||||
E(ftdi_write_data(pdata->ftdic, buf, ptr - buf) != ptr - buf, pdata->ftdic);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int avrftdi_jtag_ir_out(const PROGRAMMER *pgm, unsigned char ir)
|
||||
{
|
||||
avrftdi_t *pdata = to_pdata(pgm);
|
||||
unsigned char buf[9], *ptr = buf;
|
||||
|
||||
/* Idle -> Select-DR -> Select-IR -> Capture-IR -> Shift-IR */
|
||||
*ptr++ = MPSSE_WRITE_TMS | MPSSE_LSB | MPSSE_BITMODE | MPSSE_WRITE_NEG;
|
||||
*ptr++ = 3;
|
||||
*ptr++ = 0x03;
|
||||
|
||||
/* Clock out first 3 bits */
|
||||
*ptr++ = MPSSE_DO_WRITE | MPSSE_LSB | MPSSE_BITMODE | MPSSE_WRITE_NEG;
|
||||
*ptr++ = 2;
|
||||
*ptr++ = ir & 0x7;
|
||||
|
||||
/* Clock out 4th bit and Shift-IR -> Exit1-IR -> Update-IR -> Idle */
|
||||
*ptr++ = MPSSE_WRITE_TMS | MPSSE_LSB | MPSSE_BITMODE | MPSSE_WRITE_NEG;
|
||||
*ptr++ = 2;
|
||||
*ptr++ = (ir & 0x8) << 4 | 0x03;
|
||||
|
||||
E(ftdi_write_data(pdata->ftdic, buf, ptr - buf) != ptr - buf, pdata->ftdic);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int avrftdi_jtag_dr_out(const PROGRAMMER *pgm, unsigned int dr, int bits)
|
||||
{
|
||||
avrftdi_t *pdata = to_pdata(pgm);
|
||||
unsigned char buf[18], *ptr = buf;
|
||||
|
||||
if (bits <= 0 || bits > 31) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Idle -> Select-DR -> Capture-DR -> Shift-DR */
|
||||
*ptr++ = MPSSE_WRITE_TMS | MPSSE_LSB | MPSSE_BITMODE | MPSSE_WRITE_NEG;
|
||||
*ptr++ = 2;
|
||||
*ptr++ = 0x01;
|
||||
|
||||
while (bits > 8) {
|
||||
/* Write bits */
|
||||
*ptr++ = MPSSE_DO_WRITE | MPSSE_LSB | MPSSE_BITMODE | MPSSE_WRITE_NEG;
|
||||
*ptr++ = 7;
|
||||
*ptr++ = dr & 0xff;
|
||||
bits -= 8;
|
||||
dr >>= 8;
|
||||
}
|
||||
|
||||
if (bits > 1) {
|
||||
/* Write */
|
||||
*ptr++ = MPSSE_DO_WRITE | MPSSE_LSB | MPSSE_BITMODE | MPSSE_WRITE_NEG;
|
||||
*ptr++ = bits - 2;
|
||||
*ptr++ = dr & ((1 << (bits - 1)) - 1);
|
||||
}
|
||||
dr <<= 8 - bits;
|
||||
|
||||
/* Write MSB and Shift-DR -> Exit1-DR -> Update-DR -> Idle */
|
||||
*ptr++ = MPSSE_WRITE_TMS | MPSSE_LSB | MPSSE_BITMODE | MPSSE_WRITE_NEG;
|
||||
*ptr++ = 2;
|
||||
*ptr++ = (dr & 0x80) | 0x03;
|
||||
|
||||
E(ftdi_write_data(pdata->ftdic, buf, ptr - buf) != ptr - buf, pdata->ftdic);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int avrftdi_jtag_dr_inout(const PROGRAMMER *pgm, unsigned int dr,
|
||||
int bits)
|
||||
{
|
||||
avrftdi_t *pdata = to_pdata(pgm);
|
||||
unsigned char buf[19], *ptr = buf;
|
||||
unsigned char bytes = 1, pos;
|
||||
unsigned int dr_in;
|
||||
|
||||
if (bits <= 0 || bits > 31) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Run-Test/Idle -> Select-DR -> Capture-DR -> Shift-DR */
|
||||
*ptr++ = MPSSE_WRITE_TMS | MPSSE_LSB | MPSSE_BITMODE | MPSSE_WRITE_NEG;
|
||||
*ptr++ = 2;
|
||||
*ptr++ = 0x01;
|
||||
|
||||
while (bits > 8) {
|
||||
/* Read/write bits */
|
||||
*ptr++ = MPSSE_DO_READ | MPSSE_DO_WRITE | MPSSE_LSB | MPSSE_BITMODE | MPSSE_WRITE_NEG;
|
||||
*ptr++ = 7;
|
||||
*ptr++ = dr & 0xff;
|
||||
bits -= 8;
|
||||
bytes++;
|
||||
dr >>= 8;
|
||||
}
|
||||
|
||||
if (bits > 1) {
|
||||
/* Read/write */
|
||||
*ptr++ = MPSSE_DO_READ | MPSSE_DO_WRITE | MPSSE_LSB | MPSSE_BITMODE | MPSSE_WRITE_NEG;
|
||||
*ptr++ = bits - 2;
|
||||
*ptr++ = dr & ((1 << (bits - 1)) - 1);
|
||||
bytes++;
|
||||
}
|
||||
dr <<= 8 - bits;
|
||||
|
||||
/* Read/write MSB and Shift-DR -> Exit1-DR -> Update-DR -> Run-Test/Idle */
|
||||
*ptr++ = MPSSE_WRITE_TMS | MPSSE_DO_READ | MPSSE_LSB | MPSSE_BITMODE | MPSSE_WRITE_NEG;
|
||||
*ptr++ = 2;
|
||||
*ptr++ = (dr & 0x80) | 0x03;
|
||||
*ptr++ = SEND_IMMEDIATE;
|
||||
|
||||
E(ftdi_write_data(pdata->ftdic, buf, ptr - buf) != ptr - buf, pdata->ftdic);
|
||||
|
||||
pos = 0;
|
||||
do {
|
||||
int n = ftdi_read_data(pdata->ftdic, &buf[pos], bytes - pos);
|
||||
E(n < 0, pdata->ftdic);
|
||||
pos += n;
|
||||
} while (pos < bytes);
|
||||
|
||||
dr_in = 0;
|
||||
ptr = buf;
|
||||
pos = 0;
|
||||
while (bytes - (ptr - buf) > 2) {
|
||||
dr_in |= *ptr++ << pos;
|
||||
pos += 8;
|
||||
}
|
||||
if (bytes >= 1) {
|
||||
dr_in |= *ptr++ << (pos - 8 + bits - 1);
|
||||
pos += bits - 1;
|
||||
}
|
||||
dr_in |= (*ptr++ & 0x20) << (pos - 5);
|
||||
|
||||
return dr_in;
|
||||
}
|
||||
|
||||
static void avrftdi_jtag_enable(PROGRAMMER *pgm, const AVRPART *p)
|
||||
{
|
||||
if(!ovsigck) {
|
||||
if(str_eq(p->id, "m128a") || str_eq(p->id, "m128") ||
|
||||
str_eq(p->id, "m64a") || str_eq(p->id, "m64") ||
|
||||
str_eq(p->id, "m32a") || str_eq(p->id, "m32") ||
|
||||
str_eq(p->id, "m16a") || str_eq(p->id, "m16") ||
|
||||
str_eq(p->id, "m162")) {
|
||||
pmsg_error("programmer type %s is known not to work for %s\n", pgm->type, p->desc);
|
||||
imsg_error("exiting; use -F to carry on regardless\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
pgm->powerup(pgm);
|
||||
|
||||
set_pin(pgm, PIN_AVR_RESET, OFF);
|
||||
set_pin(pgm, PIN_JTAG_TCK, OFF);
|
||||
usleep(20 * 1000);
|
||||
|
||||
set_pin(pgm, PIN_AVR_RESET, ON);
|
||||
usleep(20 * 1000);
|
||||
}
|
||||
|
||||
static int avrftdi_jtag_initialize(const PROGRAMMER *pgm, const AVRPART *p)
|
||||
{
|
||||
set_pin(pgm, PPI_AVR_BUFF, ON);
|
||||
|
||||
avrftdi_jtag_reset(pgm);
|
||||
|
||||
/* Set RESET */
|
||||
avrftdi_jtag_ir_out(pgm, JTAG_IR_AVR_RESET);
|
||||
avrftdi_jtag_dr_out(pgm, 1, 1);
|
||||
|
||||
/* Write program enable magic */
|
||||
avrftdi_jtag_ir_out(pgm, JTAG_IR_PROG_ENABLE);
|
||||
avrftdi_jtag_dr_out(pgm, 0xa370, 16);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void avrftdi_jtag_disable(const PROGRAMMER *pgm)
|
||||
{
|
||||
avrftdi_t *pdata = to_pdata(pgm);
|
||||
|
||||
/* NOP command */
|
||||
avrftdi_jtag_ir_out(pgm, JTAG_IR_PROG_COMMANDS);
|
||||
avrftdi_jtag_dr_out(pgm, 0x2300, 15);
|
||||
avrftdi_jtag_dr_out(pgm, 0x3300, 15);
|
||||
|
||||
/* Clear program enable */
|
||||
avrftdi_jtag_ir_out(pgm, JTAG_IR_PROG_ENABLE);
|
||||
avrftdi_jtag_dr_out(pgm, 0x0000, 16);
|
||||
|
||||
/* Disable RESET */
|
||||
avrftdi_jtag_ir_out(pgm, JTAG_IR_AVR_RESET);
|
||||
avrftdi_jtag_dr_out(pgm, 0, 1);
|
||||
|
||||
write_flush(pdata);
|
||||
|
||||
set_pin(pgm, PPI_AVR_BUFF, OFF);
|
||||
}
|
||||
|
||||
static int avrftdi_jtag_chip_erase(const PROGRAMMER *pgm, const AVRPART *p)
|
||||
{
|
||||
avrftdi_jtag_ir_out(pgm, JTAG_IR_PROG_COMMANDS);
|
||||
avrftdi_jtag_dr_out(pgm, 0x2380, 15);
|
||||
avrftdi_jtag_dr_out(pgm, 0x3180, 15);
|
||||
avrftdi_jtag_dr_out(pgm, 0x3380, 15);
|
||||
avrftdi_jtag_dr_out(pgm, 0x3380, 15);
|
||||
while (!(avrftdi_jtag_dr_inout(pgm, 0x3380, 15) & 0x0200))
|
||||
;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int avrftdi_jtag_read_byte(const PROGRAMMER *pgm, const AVRPART *p,
|
||||
const AVRMEM *m, unsigned long addr, unsigned char *value)
|
||||
{
|
||||
if (strcmp(m->desc, "lfuse") == 0) {
|
||||
avrftdi_jtag_ir_out(pgm, JTAG_IR_PROG_COMMANDS);
|
||||
avrftdi_jtag_dr_out(pgm, 0x2300 | JTAG_DR_PROG_FUSE_READ, 15);
|
||||
|
||||
/* Read fuse low byte */
|
||||
avrftdi_jtag_dr_out(pgm, 0x3200, 15);
|
||||
*value = avrftdi_jtag_dr_inout(pgm, 0x3300, 15) & 0xff;
|
||||
|
||||
} else if (strcmp(m->desc, "hfuse") == 0) {
|
||||
avrftdi_jtag_ir_out(pgm, JTAG_IR_PROG_COMMANDS);
|
||||
avrftdi_jtag_dr_out(pgm, 0x2300 | JTAG_DR_PROG_FUSE_READ, 15);
|
||||
|
||||
/* Read fuse high byte */
|
||||
avrftdi_jtag_dr_out(pgm, 0x3e00, 15);
|
||||
*value = avrftdi_jtag_dr_inout(pgm, 0x3f00, 15) & 0xff;
|
||||
|
||||
} else if (strcmp(m->desc, "efuse") == 0) {
|
||||
avrftdi_jtag_ir_out(pgm, JTAG_IR_PROG_COMMANDS);
|
||||
avrftdi_jtag_dr_out(pgm, 0x2300 | JTAG_DR_PROG_FUSE_READ, 15);
|
||||
|
||||
/* Read fuse extended byte */
|
||||
avrftdi_jtag_dr_out(pgm, 0x3a00, 15);
|
||||
*value = avrftdi_jtag_dr_inout(pgm, 0x3b00, 15) & 0xff;
|
||||
|
||||
} else if (strcmp(m->desc, "lock") == 0) {
|
||||
avrftdi_jtag_ir_out(pgm, JTAG_IR_PROG_COMMANDS);
|
||||
avrftdi_jtag_dr_out(pgm, 0x2300 | JTAG_DR_PROG_FUSE_READ, 15);
|
||||
|
||||
/* Read lock bits byte */
|
||||
avrftdi_jtag_dr_out(pgm, 0x3600, 15);
|
||||
*value = avrftdi_jtag_dr_inout(pgm, 0x3700, 15) & 0xff;
|
||||
|
||||
} else if (strcmp(m->desc, "signature") == 0) {
|
||||
avrftdi_jtag_ir_out(pgm, JTAG_IR_PROG_COMMANDS);
|
||||
avrftdi_jtag_dr_out(pgm, 0x2300 | JTAG_DR_PROG_SIGCAL_READ, 15);
|
||||
avrftdi_jtag_dr_out(pgm, 0x0300 | (addr & 0xff), 15);
|
||||
|
||||
/* Read signature byte */
|
||||
avrftdi_jtag_dr_out(pgm, 0x3200, 15);
|
||||
*value = avrftdi_jtag_dr_inout(pgm, 0x3300, 15) & 0xff;
|
||||
|
||||
} else if (strcmp(m->desc, "calibration") == 0) {
|
||||
avrftdi_jtag_ir_out(pgm, JTAG_IR_PROG_COMMANDS);
|
||||
avrftdi_jtag_dr_out(pgm, 0x2300 | JTAG_DR_PROG_SIGCAL_READ, 15);
|
||||
avrftdi_jtag_dr_out(pgm, 0x0300 | (addr & 0xff), 15);
|
||||
|
||||
/* Read calibration byte */
|
||||
avrftdi_jtag_dr_out(pgm, 0x3600, 15);
|
||||
*value = avrftdi_jtag_dr_inout(pgm, 0x3700, 15) & 0xff;
|
||||
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int avrftdi_jtag_write_byte(const PROGRAMMER *pgm, const AVRPART *p,
|
||||
const AVRMEM *m, unsigned long addr, unsigned char value)
|
||||
{
|
||||
if (strcmp(m->desc, "lfuse") == 0) {
|
||||
avrftdi_jtag_ir_out(pgm, JTAG_IR_PROG_COMMANDS);
|
||||
avrftdi_jtag_dr_out(pgm, 0x2300 | JTAG_DR_PROG_FUSE_WRITE, 15);
|
||||
|
||||
/* Load data low byte */
|
||||
avrftdi_jtag_dr_out(pgm, 0x1300 | value, 15);
|
||||
|
||||
/* Write fuse low byte */
|
||||
avrftdi_jtag_dr_out(pgm, 0x3300, 15);
|
||||
avrftdi_jtag_dr_out(pgm, 0x3100, 15);
|
||||
avrftdi_jtag_dr_out(pgm, 0x3300, 15);
|
||||
avrftdi_jtag_dr_out(pgm, 0x3300, 15);
|
||||
|
||||
/* Poll for fuse write complete */
|
||||
while (!(avrftdi_jtag_dr_inout(pgm, 0x3300, 15) & 0x0200))
|
||||
;
|
||||
|
||||
} else if (strcmp(m->desc, "hfuse") == 0) {
|
||||
avrftdi_jtag_ir_out(pgm, JTAG_IR_PROG_COMMANDS);
|
||||
avrftdi_jtag_dr_out(pgm, 0x2300 | JTAG_DR_PROG_FUSE_WRITE, 15);
|
||||
|
||||
/* Load data low byte */
|
||||
avrftdi_jtag_dr_out(pgm, 0x1300 | value, 15);
|
||||
|
||||
/* Write fuse low byte */
|
||||
avrftdi_jtag_dr_out(pgm, 0x3700, 15);
|
||||
avrftdi_jtag_dr_out(pgm, 0x3500, 15);
|
||||
avrftdi_jtag_dr_out(pgm, 0x3700, 15);
|
||||
avrftdi_jtag_dr_out(pgm, 0x3700, 15);
|
||||
|
||||
/* Poll for fuse write complete */
|
||||
while (!(avrftdi_jtag_dr_inout(pgm, 0x3700, 15) & 0x0200))
|
||||
;
|
||||
|
||||
} else if (strcmp(m->desc, "efuse") == 0) {
|
||||
avrftdi_jtag_ir_out(pgm, JTAG_IR_PROG_COMMANDS);
|
||||
avrftdi_jtag_dr_out(pgm, 0x2300 | JTAG_DR_PROG_FUSE_WRITE, 15);
|
||||
|
||||
/* Load data low byte */
|
||||
avrftdi_jtag_dr_out(pgm, 0x1300 | value, 15);
|
||||
|
||||
/* Write fuse low byte */
|
||||
avrftdi_jtag_dr_out(pgm, 0x3b00, 15);
|
||||
avrftdi_jtag_dr_out(pgm, 0x3900, 15);
|
||||
avrftdi_jtag_dr_out(pgm, 0x3b00, 15);
|
||||
avrftdi_jtag_dr_out(pgm, 0x3b00, 15);
|
||||
|
||||
/* Poll for fuse write complete */
|
||||
while (!(avrftdi_jtag_dr_inout(pgm, 0x3b00, 15) & 0x0200))
|
||||
;
|
||||
|
||||
} else if (strcmp(m->desc, "lock") == 0) {
|
||||
avrftdi_jtag_ir_out(pgm, JTAG_IR_PROG_COMMANDS);
|
||||
avrftdi_jtag_dr_out(pgm, 0x2300 | JTAG_DR_PROG_LOCK_WRITE, 15);
|
||||
|
||||
/* Load data low byte */
|
||||
avrftdi_jtag_dr_out(pgm, 0x1300 | value | 0xc0, 15);
|
||||
|
||||
/* Write fuse low byte */
|
||||
avrftdi_jtag_dr_out(pgm, 0x3300, 15);
|
||||
avrftdi_jtag_dr_out(pgm, 0x3100, 15);
|
||||
avrftdi_jtag_dr_out(pgm, 0x3300, 15);
|
||||
avrftdi_jtag_dr_out(pgm, 0x3300, 15);
|
||||
|
||||
/* Poll for fuse write complete */
|
||||
while (!(avrftdi_jtag_dr_inout(pgm, 0x3300, 15) & 0x0200))
|
||||
;
|
||||
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int avrftdi_jtag_paged_write(const PROGRAMMER *pgm, const AVRPART *p,
|
||||
const AVRMEM *m, unsigned int page_size, unsigned int addr,
|
||||
unsigned int n_bytes)
|
||||
{
|
||||
unsigned int maxaddr = addr + n_bytes;
|
||||
unsigned char byte;
|
||||
|
||||
if (strcmp(m->desc, "flash") == 0) {
|
||||
avrftdi_jtag_ir_out(pgm, JTAG_IR_PROG_COMMANDS);
|
||||
avrftdi_jtag_dr_out(pgm, 0x2300 | JTAG_DR_PROG_FLASH_WRITE, 15);
|
||||
|
||||
/* Load address */
|
||||
avrftdi_jtag_dr_out(pgm, 0x0b00 | ((addr >> 17) & 0xff), 15);
|
||||
avrftdi_jtag_dr_out(pgm, 0x0700 | ((addr >> 9) & 0xff), 15);
|
||||
avrftdi_jtag_dr_out(pgm, 0x0300 | ((addr >> 1) & 0xff), 15);
|
||||
|
||||
/* Load page data */
|
||||
avrftdi_jtag_ir_out(pgm, JTAG_IR_PROG_PAGELOAD);
|
||||
for (unsigned int i = 0; i < page_size; i++) {
|
||||
byte = i < (maxaddr - addr) ? m->buf[addr + i] : 0xff;
|
||||
avrftdi_jtag_dr_out(pgm, byte, 8);
|
||||
}
|
||||
|
||||
/* Write Flash page */
|
||||
avrftdi_jtag_ir_out(pgm, JTAG_IR_PROG_COMMANDS);
|
||||
avrftdi_jtag_dr_out(pgm, 0x3700, 15);
|
||||
avrftdi_jtag_dr_out(pgm, 0x3500, 15);
|
||||
avrftdi_jtag_dr_out(pgm, 0x3700, 15);
|
||||
avrftdi_jtag_dr_out(pgm, 0x3700, 15);
|
||||
|
||||
/* Wait for completion */
|
||||
while (!(avrftdi_jtag_dr_inout(pgm, 0x3700, 15) & 0x0200))
|
||||
;
|
||||
|
||||
} else if (strcmp(m->desc, "eeprom") == 0) {
|
||||
avrftdi_jtag_ir_out(pgm, JTAG_IR_PROG_COMMANDS);
|
||||
avrftdi_jtag_dr_out(pgm, 0x2300 | JTAG_DR_PROG_EEPROM_WRITE, 15);
|
||||
|
||||
for (; addr < maxaddr; addr += page_size) {
|
||||
for (unsigned int i = 0; i < page_size; i++) {
|
||||
/* Load address */
|
||||
avrftdi_jtag_dr_out(pgm, 0x0700 | ((addr >> 8) & 0xff), 15);
|
||||
avrftdi_jtag_dr_out(pgm, 0x0300 | ((addr + i) & 0xff), 15);
|
||||
|
||||
/* Load data byte */
|
||||
avrftdi_jtag_dr_out(pgm, 0x1300 | m->buf[addr + i], 15);
|
||||
|
||||
/* Latch data */
|
||||
avrftdi_jtag_dr_out(pgm, 0x3700, 15);
|
||||
avrftdi_jtag_dr_out(pgm, 0x7700, 15);
|
||||
avrftdi_jtag_dr_out(pgm, 0x3700, 15);
|
||||
}
|
||||
|
||||
/* Write EEPROM page */
|
||||
avrftdi_jtag_dr_out(pgm, 0x3300, 15);
|
||||
avrftdi_jtag_dr_out(pgm, 0x3100, 15);
|
||||
avrftdi_jtag_dr_out(pgm, 0x3300, 15);
|
||||
avrftdi_jtag_dr_out(pgm, 0x3300, 15);
|
||||
|
||||
/* Wait for completion */
|
||||
while (!(avrftdi_jtag_dr_inout(pgm, 0x3300, 15) & 0x0200))
|
||||
;
|
||||
}
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return n_bytes;
|
||||
}
|
||||
|
||||
static int avrftdi_jtag_paged_read(const PROGRAMMER *pgm, const AVRPART *p,
|
||||
const AVRMEM *m, unsigned int page_size, unsigned int addr,
|
||||
unsigned int n_bytes)
|
||||
{
|
||||
avrftdi_t *pdata = to_pdata(pgm);
|
||||
unsigned int maxaddr = addr + n_bytes;
|
||||
unsigned char *buf, *ptr;
|
||||
unsigned int bytes;
|
||||
|
||||
buf = alloca(n_bytes * 8 + 1);
|
||||
ptr = buf;
|
||||
|
||||
if (strcmp(m->desc, "flash") == 0) {
|
||||
avrftdi_jtag_ir_out(pgm, JTAG_IR_PROG_COMMANDS);
|
||||
avrftdi_jtag_dr_out(pgm, 0x2300 | JTAG_DR_PROG_FLASH_READ, 15);
|
||||
|
||||
/* Load address */
|
||||
avrftdi_jtag_dr_out(pgm, 0x0b00 | ((addr >> 17) & 0xff), 15);
|
||||
avrftdi_jtag_dr_out(pgm, 0x0700 | ((addr >> 9) & 0xff), 15);
|
||||
avrftdi_jtag_dr_out(pgm, 0x0300 | ((addr >> 1) & 0xff), 15);
|
||||
avrftdi_jtag_ir_out(pgm, JTAG_IR_PROG_PAGEREAD);
|
||||
|
||||
for (unsigned int i = addr; i < maxaddr; i++) {
|
||||
/* Run-Test/Idle -> Select-DR -> Capture-DR -> Shift-DR */
|
||||
*ptr++ = MPSSE_WRITE_TMS | MPSSE_LSB | MPSSE_BITMODE | MPSSE_WRITE_NEG;
|
||||
*ptr++ = 2;
|
||||
*ptr++ = 0x01;
|
||||
|
||||
/* Read byte */
|
||||
*ptr++ = MPSSE_DO_READ | MPSSE_LSB | MPSSE_BITMODE;
|
||||
*ptr++ = 6;
|
||||
|
||||
/* Shift-DR -> Exit1-DR -> Update-DR -> Run-Test/Idle */
|
||||
*ptr++ = MPSSE_WRITE_TMS | MPSSE_DO_READ | MPSSE_LSB | MPSSE_BITMODE | MPSSE_WRITE_NEG;
|
||||
*ptr++ = 2;
|
||||
*ptr++ = 0x03;
|
||||
}
|
||||
|
||||
*ptr++ = SEND_IMMEDIATE;
|
||||
E(ftdi_write_data(pdata->ftdic, buf, ptr - buf) != ptr - buf, pdata->ftdic);
|
||||
|
||||
bytes = 0;
|
||||
do {
|
||||
int n = ftdi_read_data(pdata->ftdic, &buf[bytes], n_bytes * 2 - bytes);
|
||||
E(n < 0, pdata->ftdic);
|
||||
bytes += n;
|
||||
} while (bytes < n_bytes * 2);
|
||||
|
||||
for (unsigned int i = 0; i < n_bytes; i++) {
|
||||
m->buf[addr + i] = (buf[i * 2] >> 1) | (buf[(i * 2) + 1] << 2);
|
||||
}
|
||||
|
||||
} else if (strcmp(m->desc, "eeprom") == 0) {
|
||||
avrftdi_jtag_ir_out(pgm, JTAG_IR_PROG_COMMANDS);
|
||||
avrftdi_jtag_dr_out(pgm, 0x2300 | JTAG_DR_PROG_EEPROM_READ, 15);
|
||||
|
||||
for (; addr < maxaddr; addr++) {
|
||||
/* Load address */
|
||||
avrftdi_jtag_dr_out(pgm, 0x0700 | ((addr >> 8) & 0xff), 15);
|
||||
avrftdi_jtag_dr_out(pgm, 0x0300 | (addr & 0xff), 15);
|
||||
|
||||
/* Read data byte */
|
||||
avrftdi_jtag_dr_out(pgm, 0x3300 | (addr & 0xff), 15);
|
||||
avrftdi_jtag_dr_out(pgm, 0x3200, 15);
|
||||
m->buf[addr] = avrftdi_jtag_dr_inout(pgm, 0x3300, 15) & 0xff;
|
||||
}
|
||||
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return n_bytes;
|
||||
}
|
||||
|
||||
void avrftdi_initpgm(PROGRAMMER *pgm)
|
||||
{
|
||||
strcpy(pgm->type, "avrftdi");
|
||||
|
||||
/*
|
||||
* mandatory functions
|
||||
*/
|
||||
|
||||
pgm->initialize = avrftdi_initialize;
|
||||
pgm->display = avrftdi_display;
|
||||
pgm->enable = avrftdi_enable;
|
||||
@@ -1243,23 +1844,53 @@ void avrftdi_initpgm(PROGRAMMER *pgm) {
|
||||
/*
|
||||
* optional functions
|
||||
*/
|
||||
|
||||
pgm->paged_write = avrftdi_paged_write;
|
||||
pgm->paged_load = avrftdi_paged_load;
|
||||
|
||||
pgm->setpin = set_pin;
|
||||
|
||||
pgm->setup = avrftdi_setup;
|
||||
pgm->teardown = avrftdi_teardown;
|
||||
|
||||
pgm->rdy_led = set_led_rdy;
|
||||
pgm->err_led = set_led_err;
|
||||
pgm->pgm_led = set_led_pgm;
|
||||
pgm->vfy_led = set_led_vfy;
|
||||
}
|
||||
|
||||
void avrftdi_jtag_initpgm(PROGRAMMER *pgm)
|
||||
{
|
||||
strcpy(pgm->type, "avrftdi_jtag");
|
||||
|
||||
/*
|
||||
* mandatory functions
|
||||
*/
|
||||
pgm->initialize = avrftdi_jtag_initialize;
|
||||
pgm->display = avrftdi_display;
|
||||
pgm->enable = avrftdi_jtag_enable;
|
||||
pgm->disable = avrftdi_jtag_disable;
|
||||
pgm->powerup = avrftdi_powerup;
|
||||
pgm->powerdown = avrftdi_powerdown;
|
||||
pgm->chip_erase = avrftdi_jtag_chip_erase;
|
||||
pgm->open = avrftdi_open;
|
||||
pgm->close = avrftdi_close;
|
||||
pgm->read_byte = avrftdi_jtag_read_byte;
|
||||
pgm->write_byte = avrftdi_jtag_write_byte;
|
||||
|
||||
/*
|
||||
* optional functions
|
||||
*/
|
||||
pgm->paged_write = avrftdi_jtag_paged_write;
|
||||
pgm->paged_load = avrftdi_jtag_paged_read;
|
||||
pgm->setup = avrftdi_setup;
|
||||
pgm->teardown = avrftdi_teardown;
|
||||
pgm->rdy_led = set_led_rdy;
|
||||
pgm->err_led = set_led_err;
|
||||
pgm->pgm_led = set_led_pgm;
|
||||
pgm->vfy_led = set_led_vfy;
|
||||
pgm->page_size = 256;
|
||||
pgm->flag = PGM_FL_IS_JTAG;
|
||||
}
|
||||
|
||||
#endif /* DO_NOT_BUILD_AVRFTDI */
|
||||
|
||||
|
||||
const char avrftdi_desc[] = "Interface to the MPSSE Engine of FTDI Chips using libftdi.";
|
||||
const char avrftdi_jtag_desc[] = "libftdi JTAG interface";
|
||||
|
||||
|
||||
@@ -29,7 +29,9 @@ extern "C" {
|
||||
|
||||
|
||||
extern const char avrftdi_desc[];
|
||||
extern const char avrftdi_jtag_desc[];
|
||||
void avrftdi_initpgm(PROGRAMMER *pgm);
|
||||
void avrftdi_jtag_initpgm(PROGRAMMER *pgm);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -61,6 +61,33 @@ enum { ERR, WARN, INFO, DEBUG, TRACE };
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
enum {
|
||||
JTAG_IR_EXTEST = 0,
|
||||
JTAG_IR_IDCODE = 1,
|
||||
JTAG_IR_SAMPLE_PRELOAD = 2,
|
||||
JTAG_IR_PROG_ENABLE = 4,
|
||||
JTAG_IR_PROG_COMMANDS = 5,
|
||||
JTAG_IR_PROG_PAGELOAD = 6,
|
||||
JTAG_IR_PROG_PAGEREAD = 7,
|
||||
JTAG_IR_PRIVATE0 = 8,
|
||||
JTAG_IR_PRIVATE1 = 9,
|
||||
JTAG_IR_PRIVATE2 = 10,
|
||||
JTAG_IR_PRIVATE3 = 11,
|
||||
JTAG_IR_AVR_RESET = 12,
|
||||
JTAG_IR_BYPASS = 15,
|
||||
};
|
||||
|
||||
enum jtag_cmd {
|
||||
JTAG_DR_PROG_NONE = 0x00,
|
||||
JTAG_DR_PROG_FLASH_READ = 0x02,
|
||||
JTAG_DR_PROG_EEPROM_READ = 0x03,
|
||||
JTAG_DR_PROG_FUSE_READ = 0x04,
|
||||
JTAG_DR_PROG_SIGCAL_READ = 0x08,
|
||||
JTAG_DR_PROG_FLASH_WRITE = 0x10,
|
||||
JTAG_DR_PROG_EEPROM_WRITE = 0x11,
|
||||
JTAG_DR_PROG_LOCK_WRITE = 0x20,
|
||||
JTAG_DR_PROG_FUSE_WRITE = 0x40,
|
||||
};
|
||||
|
||||
#define to_pdata(pgm) \
|
||||
((avrftdi_t *)((pgm)->cookie))
|
||||
|
||||
@@ -109,6 +109,10 @@ static int pin_name;
|
||||
%token K_SCK
|
||||
%token K_SIGNATURE
|
||||
%token K_SIZE
|
||||
%token K_TCK
|
||||
%token K_TDI
|
||||
%token K_TDO
|
||||
%token K_TMS
|
||||
%token K_USB
|
||||
%token K_USBPID
|
||||
%token K_TYPE
|
||||
@@ -562,6 +566,10 @@ prog_parm_pins:
|
||||
K_SCK TKN_EQUAL {pin_name = PIN_AVR_SCK; clear_pin(pin_name); } pin_number { free_token($1); } |
|
||||
K_SDO TKN_EQUAL {pin_name = PIN_AVR_SDO; clear_pin(pin_name); } pin_number |
|
||||
K_SDI TKN_EQUAL {pin_name = PIN_AVR_SDI; clear_pin(pin_name); } pin_number |
|
||||
K_TCK TKN_EQUAL {pin_name = PIN_JTAG_TCK; clear_pin(pin_name); } pin_number |
|
||||
K_TDI TKN_EQUAL {pin_name = PIN_JTAG_TDI; clear_pin(pin_name); } pin_number |
|
||||
K_TDO TKN_EQUAL {pin_name = PIN_JTAG_TDO; clear_pin(pin_name); } pin_number |
|
||||
K_TMS TKN_EQUAL {pin_name = PIN_JTAG_TMS; clear_pin(pin_name); } pin_number |
|
||||
K_ERRLED TKN_EQUAL {pin_name = PIN_LED_ERR; clear_pin(pin_name); } pin_number |
|
||||
K_RDYLED TKN_EQUAL {pin_name = PIN_LED_RDY; clear_pin(pin_name); } pin_number |
|
||||
K_PGMLED TKN_EQUAL {pin_name = PIN_LED_PGM; clear_pin(pin_name); } pin_number |
|
||||
|
||||
@@ -238,6 +238,10 @@ sdo { yylval=NULL; ccap(); return K_SDO; }
|
||||
serial { yylval=NULL; ccap(); return K_SERIAL; }
|
||||
signature { yylval=NULL; ccap(); return K_SIGNATURE; }
|
||||
spi { yylval=NULL; return K_SPI; }
|
||||
tck { yylval=NULL; ccap(); return K_TCK; }
|
||||
tdi { yylval=NULL; ccap(); return K_TDI; }
|
||||
tdo { yylval=NULL; ccap(); return K_TDO; }
|
||||
tms { yylval=NULL; ccap(); return K_TMS; }
|
||||
type { yylval=NULL; ccap(); return K_TYPE; }
|
||||
usb { yylval=NULL; return K_USB; }
|
||||
usbpid { yylval=NULL; ccap(); return K_USBPID; }
|
||||
|
||||
@@ -424,6 +424,10 @@ enum {
|
||||
PIN_AVR_SCK,
|
||||
PIN_AVR_SDO,
|
||||
PIN_AVR_SDI,
|
||||
PIN_JTAG_TCK,
|
||||
PIN_JTAG_TDI,
|
||||
PIN_JTAG_TDO,
|
||||
PIN_JTAG_TMS,
|
||||
PIN_LED_ERR,
|
||||
PIN_LED_RDY,
|
||||
PIN_LED_PGM,
|
||||
@@ -860,6 +864,7 @@ void programmer_display(PROGRAMMER * pgm, const char * p);
|
||||
#define SHOW_ALL_PINS (~0u)
|
||||
#define SHOW_PPI_PINS ((1<<PPI_AVR_VCC)|(1<<PPI_AVR_BUFF))
|
||||
#define SHOW_AVR_PINS ((1<<PIN_AVR_RESET)|(1<<PIN_AVR_SCK)|(1<<PIN_AVR_SDO)|(1<<PIN_AVR_SDI))
|
||||
#define SHOW_JTAG_PINS ((1<<PIN_JTAG_TCK)|(1<<PIN_JTAG_TDI)|(1<<PIN_JTAG_TDO)|(1<<PIN_JTAG_TMS))
|
||||
#define SHOW_LED_PINS ((1<<PIN_LED_ERR)|(1<<PIN_LED_RDY)|(1<<PIN_LED_PGM)|(1<<PIN_LED_VFY))
|
||||
void pgm_display_generic_mask(const PROGRAMMER *pgm, const char *p, unsigned int show);
|
||||
void pgm_display_generic(const PROGRAMMER *pgm, const char *p);
|
||||
|
||||
@@ -277,6 +277,14 @@ void pgm_display_generic_mask(const PROGRAMMER *pgm, const char *p, unsigned int
|
||||
msg_info("%s SDO = %s\n", p, pins_to_str(&pgm->pin[PIN_AVR_SDO]));
|
||||
if(show & (1<<PIN_AVR_SDI))
|
||||
msg_info("%s SDI = %s\n", p, pins_to_str(&pgm->pin[PIN_AVR_SDI]));
|
||||
if(show & (1<<PIN_JTAG_TCK))
|
||||
msg_info("%s TCK = %s\n", p, pins_to_str(&pgm->pin[PIN_JTAG_TCK]));
|
||||
if(show & (1<<PIN_JTAG_TDI))
|
||||
msg_info("%s TDI = %s\n", p, pins_to_str(&pgm->pin[PIN_JTAG_TDI]));
|
||||
if(show & (1<<PIN_JTAG_TDO))
|
||||
msg_info("%s TDO = %s\n", p, pins_to_str(&pgm->pin[PIN_JTAG_TDO]));
|
||||
if(show & (1<<PIN_JTAG_TMS))
|
||||
msg_info("%s TMS = %s\n", p, pins_to_str(&pgm->pin[PIN_JTAG_TMS]));
|
||||
if(show & (1<<PIN_LED_ERR))
|
||||
msg_info("%s ERR LED = %s\n", p, pins_to_str(&pgm->pin[PIN_LED_ERR]));
|
||||
if(show & (1<<PIN_LED_RDY))
|
||||
|
||||
@@ -64,6 +64,7 @@ const PROGRAMMER_TYPE programmers_types[] = { // Name(s) the programmers call th
|
||||
{"arduino", arduino_initpgm, arduino_desc}, // "Arduino"
|
||||
{"avr910", avr910_initpgm, avr910_desc}, // "avr910"
|
||||
{"avrftdi", avrftdi_initpgm, avrftdi_desc}, // "avrftdi"
|
||||
{"avrftdi_jtag", avrftdi_jtag_initpgm, avrftdi_jtag_desc}, // "avrftdi_jtag"
|
||||
{"buspirate", buspirate_initpgm, buspirate_desc}, // "BusPirate"
|
||||
{"buspirate_bb", buspirate_bb_initpgm, buspirate_bb_desc}, // "BusPirate_BB"
|
||||
{"butterfly", butterfly_initpgm, butterfly_desc}, // "butterfly"
|
||||
|
||||
@@ -130,6 +130,14 @@ int pgm_fill_old_pins(PROGRAMMER * const pgm) {
|
||||
return -1;
|
||||
if (pin_fill_old_pinno(&(pgm->pin[PIN_AVR_SDI]), &(pgm->pinno[PIN_AVR_SDI])) < 0)
|
||||
return -1;
|
||||
if (pin_fill_old_pinno(&(pgm->pin[PIN_JTAG_TCK]), &(pgm->pinno[PIN_JTAG_TCK])) < 0)
|
||||
return -1;
|
||||
if (pin_fill_old_pinno(&(pgm->pin[PIN_JTAG_TDI]), &(pgm->pinno[PIN_JTAG_TDI])) < 0)
|
||||
return -1;
|
||||
if (pin_fill_old_pinno(&(pgm->pin[PIN_JTAG_TDO]), &(pgm->pinno[PIN_JTAG_TDO])) < 0)
|
||||
return -1;
|
||||
if (pin_fill_old_pinno(&(pgm->pin[PIN_JTAG_TMS]), &(pgm->pinno[PIN_JTAG_TMS])) < 0)
|
||||
return -1;
|
||||
if (pin_fill_old_pinno(&(pgm->pin[PIN_LED_ERR]), &(pgm->pinno[PIN_LED_ERR])) < 0)
|
||||
return -1;
|
||||
if (pin_fill_old_pinno(&(pgm->pin[PIN_LED_RDY]), &(pgm->pinno[PIN_LED_RDY])) < 0)
|
||||
@@ -377,6 +385,10 @@ const char * avr_pin_name(int pinname) {
|
||||
case PIN_AVR_SCK : return "SCK";
|
||||
case PIN_AVR_SDO : return "SDO";
|
||||
case PIN_AVR_SDI : return "SDI";
|
||||
case PIN_JTAG_TCK : return "TCK";
|
||||
case PIN_JTAG_TDI : return "TDI";
|
||||
case PIN_JTAG_TDO : return "TDO";
|
||||
case PIN_JTAG_TMS : return "TMS";
|
||||
case PIN_LED_ERR : return "ERRLED";
|
||||
case PIN_LED_RDY : return "RDYLED";
|
||||
case PIN_LED_PGM : return "PGMLED";
|
||||
@@ -400,6 +412,10 @@ const char * avr_pin_lcname(int pinname) {
|
||||
case PIN_AVR_SCK : return "sck";
|
||||
case PIN_AVR_SDO : return "sdo";
|
||||
case PIN_AVR_SDI : return "sdi";
|
||||
case PIN_JTAG_TCK : return "tck";
|
||||
case PIN_JTAG_TDI : return "tdi";
|
||||
case PIN_JTAG_TDO : return "tdo";
|
||||
case PIN_JTAG_TMS : return "tms";
|
||||
case PIN_LED_ERR : return "errled";
|
||||
case PIN_LED_RDY : return "rdyled";
|
||||
case PIN_LED_PGM : return "pgmled";
|
||||
|
||||
Reference in New Issue
Block a user