Skip to content

Commit 6de6c0f

Browse files
committed
patch #9327: ft245r.c: add TPI support (patches 1-4)
Submitted by David Mosberger-Tang: * ft245r.c: add TPI support * avrdude.conf.in (tc2030): New programmer git-svn-id: svn://svn.savannah.nongnu.org/avrdude/trunk/avrdude@1483 81a1dc3b-b13d-400b-aceb-764788c761c2
1 parent d947e58 commit 6de6c0f

File tree

3 files changed

+218
-10
lines changed

3 files changed

+218
-10
lines changed

ChangeLog

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
2021-11-24 Joerg Wunsch <[email protected]>
2+
3+
Submitted by David Mosberger-Tang:
4+
patch #9327: ft245r.c: add TPI support (patches 1-4)
5+
* ft245r.c: add TPI support
6+
* avrdude.conf.in (tc2030): New programmer
7+
18
2021-11-24 Joerg Wunsch <[email protected]>
29

310
* ft245r.c (ft245r_open): allow for picking a default

avrdude.conf.in

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -780,6 +780,18 @@ programmer
780780
reset = 7; # RI X3(4)
781781
;
782782

783+
programmer
784+
id = "tc2030";
785+
desc = "Tag-Connect TC2030";
786+
type = "ftdi_syncbb";
787+
connection_type = usb;
788+
# FOR TPI devices:
789+
mosi = 0; # TxD = D0 (wire to TPIDATA via 1k resistor)
790+
miso = 1; # RxD = D1 (wire to TPIDATA directly)
791+
sck = 2; # RTS = D2 (wire to SCK)
792+
reset = 3; # CTS = D3 (wire to ~RESET)
793+
;
794+
783795
# website mentioned above uses this id
784796
programmer parent "arduino-ft232r"
785797
id = "diecimila";

ft245r.c

Lines changed: 199 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,11 @@
6767
#include "ft245r.h"
6868
#include "usbdevs.h"
6969

70+
#include "tpi.h"
71+
72+
#define TPIPCR_GT_0b 0x07
73+
#define TPI_STOP_BITS 0x03
74+
7075
#if defined(_WIN32)
7176
#include <windows.h>
7277
#endif
@@ -241,6 +246,9 @@ static int ft245r_chip_erase(PROGRAMMER * pgm, AVRPART * p) {
241246
unsigned char cmd[4] = {0,0,0,0};
242247
unsigned char res[4];
243248

249+
if (p->flags & AVRPART_HAS_TPI)
250+
return avr_tpi_chip_erase(pgm, p);
251+
244252
if (p->op[AVR_OP_CHIP_ERASE] == NULL) {
245253
avrdude_message(MSG_INFO, "chip erase instruction not defined for part \"%s\"\n",
246254
p->desc);
@@ -280,6 +288,16 @@ static int ft245r_set_bitclock(PROGRAMMER * pgm) {
280288
return 0;
281289
}
282290

291+
static int get_pin(PROGRAMMER *pgm, int pinname) {
292+
uint8_t byte;
293+
294+
if (ftdi_read_pins(handle, &byte) != 0)
295+
return -1;
296+
if (FT245R_DEBUG)
297+
avrdude_message(MSG_INFO, "%s: in 0x%02x\n", __func__, byte);
298+
return GET_BITS_0(byte, pgm, pinname) != 0;
299+
}
300+
283301
static int set_pin(PROGRAMMER * pgm, int pinname, int val) {
284302
unsigned char buf[1];
285303

@@ -375,6 +393,8 @@ static void ft245r_enable(PROGRAMMER * pgm) {
375393

376394
static int ft245r_cmd(PROGRAMMER * pgm, const unsigned char *cmd,
377395
unsigned char *res);
396+
static int ft245r_tpi_tx(PROGRAMMER * pgm, uint8_t byte);
397+
static int ft245r_tpi_rx(PROGRAMMER * pgm, uint8_t *bytep);
378398
/*
379399
* issue the 'program enable' command to the AVR device
380400
*/
@@ -383,6 +403,9 @@ static int ft245r_program_enable(PROGRAMMER * pgm, AVRPART * p) {
383403
unsigned char res[4];
384404
int i;
385405

406+
if (p->flags & AVRPART_HAS_TPI)
407+
return avr_tpi_program_enable(pgm, p, TPIPCR_GT_0b);
408+
386409
if (p->op[AVR_OP_PGM_ENABLE] == NULL) {
387410
avrdude_message(MSG_INFO, "%s: AVR_OP_PGM_ENABLE command not defined for %s\n",
388411
progname, p->desc);
@@ -443,25 +466,73 @@ static int ft245r_initialize(PROGRAMMER * pgm, AVRPART * p) {
443466
*/
444467
usleep(20000); // 20ms
445468

469+
if (p->flags & AVRPART_HAS_TPI) {
470+
bool io_link_ok = true;
471+
uint8_t byte;
472+
int i;
473+
474+
/* Since there is a single TPIDATA line, MOSI and MISO must be
475+
linked together through a 1kOhm resistor. Verify that
476+
everything we send on MOSI gets mirrored back on MISO. */
477+
set_pin(pgm, PIN_AVR_MOSI, 0);
478+
if (get_pin(pgm, PIN_AVR_MISO) != 0) {
479+
io_link_ok = false;
480+
avrdude_message(MSG_INFO, "MOSI->MISO 0 failed\n");
481+
if (!ovsigck)
482+
return -1;
483+
}
484+
set_pin(pgm, PIN_AVR_MOSI, 1);
485+
if (get_pin(pgm, PIN_AVR_MISO) != 1) {
486+
io_link_ok = false;
487+
avrdude_message(MSG_INFO, "MOSI->MISO 1 failed\n");
488+
if (!ovsigck)
489+
return -1;
490+
}
491+
492+
if (io_link_ok)
493+
avrdude_message(MSG_NOTICE2, "MOSI-MISO link present\n");
494+
495+
/* keep TPIDATA high for 16 clock cycles */
496+
set_pin(pgm, PIN_AVR_MOSI, 1);
497+
for (i = 0; i < 16; i++) {
498+
set_sck(pgm, 1);
499+
set_sck(pgm, 0);
500+
}
501+
502+
/* remove extra guard timing bits */
503+
ft245r_tpi_tx(pgm, TPI_CMD_SSTCS | TPI_REG_TPIPCR);
504+
ft245r_tpi_tx(pgm, 0x7);
505+
506+
/* read TPI ident reg */
507+
ft245r_tpi_tx(pgm, TPI_CMD_SLDCS | TPI_REG_TPIIR);
508+
ft245r_tpi_rx(pgm, &byte);
509+
if (byte != 0x80) {
510+
avrdude_message(MSG_INFO, "TPIIR 0x%02x not correct\n", byte);
511+
return -1;
512+
}
513+
}
446514
return ft245r_program_enable(pgm, p);
447515
}
448516

517+
static inline void add_bit(PROGRAMMER * pgm, unsigned char *buf, int *buf_pos,
518+
uint8_t bit) {
519+
ft245r_out = SET_BITS_0(ft245r_out,pgm,PIN_AVR_MOSI, bit);
520+
ft245r_out = SET_BITS_0(ft245r_out,pgm,PIN_AVR_SCK,0);
521+
buf[*buf_pos] = ft245r_out;
522+
(*buf_pos)++;
523+
524+
ft245r_out = SET_BITS_0(ft245r_out,pgm,PIN_AVR_SCK,1);
525+
buf[*buf_pos] = ft245r_out;
526+
(*buf_pos)++;
527+
}
528+
449529
static inline int set_data(PROGRAMMER * pgm, unsigned char *buf, unsigned char data) {
450530
int j;
451531
int buf_pos = 0;
452532
unsigned char bit = 0x80;
453533

454534
for (j=0; j<8; j++) {
455-
ft245r_out = SET_BITS_0(ft245r_out,pgm,PIN_AVR_MOSI,data & bit);
456-
457-
ft245r_out = SET_BITS_0(ft245r_out,pgm,PIN_AVR_SCK,0);
458-
buf[buf_pos] = ft245r_out;
459-
buf_pos++;
460-
461-
ft245r_out = SET_BITS_0(ft245r_out,pgm,PIN_AVR_SCK,1);
462-
buf[buf_pos] = ft245r_out;
463-
buf_pos++;
464-
535+
add_bit(pgm, buf, &buf_pos, (data & bit) != 0);
465536
bit >>= 1;
466537
}
467538
return buf_pos;
@@ -532,6 +603,123 @@ static int ft245r_cmd(PROGRAMMER * pgm, const unsigned char *cmd,
532603
return 0;
533604
}
534605

606+
static inline uint8_t extract_tpi_data(PROGRAMMER * pgm, unsigned char *buf,
607+
int *buf_pos) {
608+
uint8_t bit = 0x1, byte = 0;
609+
int j;
610+
611+
for (j = 0; j < 8; j++) {
612+
(*buf_pos)++; // skip over falling clock edge
613+
if (GET_BITS_0(buf[(*buf_pos)++], pgm, PIN_AVR_MISO))
614+
byte |= bit;
615+
bit <<= 1;
616+
}
617+
return byte;
618+
}
619+
620+
static inline int set_tpi_data(PROGRAMMER * pgm, unsigned char *buf,
621+
uint8_t byte) {
622+
uint8_t bit = 0x1, parity = 0;
623+
int j, buf_pos = 0;
624+
625+
// start bit:
626+
add_bit(pgm, buf, &buf_pos, 0);
627+
628+
// 8 data bits:
629+
for (j = 0; j < 8; j++) {
630+
add_bit(pgm, buf, &buf_pos, (byte & bit) != 0);
631+
parity ^= (byte & bit) != 0;
632+
bit <<= 1;
633+
}
634+
635+
// parity bit:
636+
add_bit(pgm, buf, &buf_pos, parity);
637+
// stop bits:
638+
add_bit(pgm, buf, &buf_pos, 1);
639+
add_bit(pgm, buf, &buf_pos, 1);
640+
return buf_pos;
641+
}
642+
643+
static int ft245r_tpi_tx(PROGRAMMER * pgm, uint8_t byte) {
644+
uint8_t buf[128];
645+
int len;
646+
647+
len = set_tpi_data(pgm, buf, byte);
648+
ft245r_send(pgm, buf, len);
649+
ft245r_recv(pgm, buf, len);
650+
return 0;
651+
}
652+
653+
static int ft245r_tpi_rx(PROGRAMMER * pgm, uint8_t *bytep) {
654+
uint8_t buf[128], bit, parity;
655+
int i, buf_pos = 0, len = 0;
656+
uint32_t res, m, byte;
657+
658+
/* Allow for up to 4 bits before we must see start bit; during
659+
that time, we must keep the MOSI line high. */
660+
for (i = 0; i < 2; ++i)
661+
len += set_data(pgm, &buf[len], 0xff);
662+
663+
ft245r_send(pgm, buf, len);
664+
ft245r_recv(pgm, buf, len);
665+
666+
res = (extract_tpi_data(pgm, buf, &buf_pos)
667+
| ((uint32_t) extract_tpi_data(pgm, buf, &buf_pos) << 8));
668+
669+
/* Look for start bit: */
670+
m = 0x1;
671+
while (m & res)
672+
m <<= 1;
673+
if (m >= 0x10) {
674+
avrdude_message(MSG_INFO, "%s: start bit missing (res=0x%04x)\n",
675+
__func__, res);
676+
return -1;
677+
}
678+
byte = parity = 0;
679+
for (i = 0; i < 8; ++i) {
680+
m <<= 1;
681+
bit = (res & m) != 0;
682+
parity ^= bit;
683+
byte |= bit << i;
684+
}
685+
m <<= 1;
686+
if (((res & m) != 0) != parity) {
687+
avrdude_message(MSG_INFO, "%s: parity bit wrong\n", __func__);
688+
return -1;
689+
}
690+
if (((res & (m << 1)) == 0) || ((res & (m << 2))) == 0) {
691+
avrdude_message(MSG_INFO, "%s: stop bits wrong\n", __func__);
692+
return -1;
693+
}
694+
*bytep = (uint8_t) byte;
695+
return 0;
696+
}
697+
698+
static int ft245r_cmd_tpi(PROGRAMMER * pgm, const unsigned char *cmd,
699+
int cmd_len, unsigned char *res, int res_len) {
700+
int i, ret = 0;
701+
702+
pgm->pgm_led(pgm, ON);
703+
704+
for (i = 0; i < cmd_len; ++i)
705+
ft245r_tpi_tx(pgm, cmd[i]);
706+
for (i = 0; i < res_len; ++i)
707+
if ((ret = ft245r_tpi_rx(pgm, &res[i])) < 0)
708+
break;
709+
if (verbose >= 2) {
710+
avrdude_message(MSG_NOTICE2, "%s: [ ", __func__);
711+
for (i = 0; i < cmd_len; i++)
712+
avrdude_message(MSG_NOTICE2, "%02X ", cmd[i]);
713+
avrdude_message(MSG_NOTICE2, "] [ ");
714+
for(i = 0; i < res_len; i++)
715+
avrdude_message(MSG_NOTICE2, "%02X ", res[i]);
716+
avrdude_message(MSG_NOTICE2, "]\n");
717+
}
718+
719+
pgm->pgm_led(pgm, OFF);
720+
return ret;
721+
}
722+
535723
/* lower 8 pins are accepted, they might be also inverted */
536724
static const struct pindef_t valid_pins = {{0xff},{0xff}} ;
537725

@@ -985,6 +1173,7 @@ void ft245r_initpgm(PROGRAMMER * pgm) {
9851173
pgm->program_enable = ft245r_program_enable;
9861174
pgm->chip_erase = ft245r_chip_erase;
9871175
pgm->cmd = ft245r_cmd;
1176+
pgm->cmd_tpi = ft245r_cmd_tpi;
9881177
pgm->open = ft245r_open;
9891178
pgm->close = ft245r_close;
9901179
pgm->read_byte = avr_read_byte_default;

0 commit comments

Comments
 (0)