From 275ba38207a331dd3dea0ba9c44101cc4307ae2c Mon Sep 17 00:00:00 2001 From: Gwenhael Goavec-Merou Date: Sun, 31 May 2020 15:57:21 +0200 Subject: [PATCH] restructure hierarchy/abstraction: - jtagInterface as now only two method: one for tms or for tdi, in all case full buffer is provided and specific code deal with them to write - jtag: drop read_write logic to jtag probe abstraction --- src/ftdiJtagBitbang.cpp | 173 +++++++++++++++++---------- src/ftdiJtagBitbang.hpp | 16 ++- src/ftdiJtagMPSSE.cpp | 254 ++++++++++++++++++++++++++-------------- src/ftdiJtagMPSSE.hpp | 13 +- src/jtag.cpp | 125 +++----------------- src/jtag.hpp | 2 +- src/jtagInterface.hpp | 51 ++++---- 7 files changed, 331 insertions(+), 303 deletions(-) diff --git a/src/ftdiJtagBitbang.cpp b/src/ftdiJtagBitbang.cpp index e99d101..8cd54af 100644 --- a/src/ftdiJtagBitbang.cpp +++ b/src/ftdiJtagBitbang.cpp @@ -42,7 +42,8 @@ using namespace std; FtdiJtagBitBang::FtdiJtagBitBang(const FTDIpp_MPSSE::mpsse_bit_config &cable, const jtag_pins_conf_t *pin_conf, string dev, uint32_t clkHZ, bool verbose): - FTDIpp_MPSSE(cable, dev, clkHZ, verbose), _bitmode(0), _nb_bit(0) + FTDIpp_MPSSE(cable, dev, clkHZ, verbose), _bitmode(0), _nb_bit(0), + _curr_tms(0) { init_internal(cable, pin_conf); } @@ -68,14 +69,24 @@ void FtdiJtagBitBang::init_internal(const FTDIpp_MPSSE::mpsse_bit_config &cable, _tdi_pin = (1 << pin_conf->tdi_pin); _tdo_pin = (1 << pin_conf->tdo_pin); - _buffer_size = 128; // TX Fifo size + _buffer_size = 512; // TX Fifo size + + setClkFreq(_clkHZ); _in_buf = (unsigned char *)malloc(sizeof(unsigned char) * _buffer_size); bzero(_in_buf, _buffer_size); init(1, _tck_pin | _tms_pin | _tdi_pin, BITMODE_BITBANG, (FTDIpp_MPSSE::mpsse_bit_config &)cable); setBitmode(BITMODE_BITBANG); +} +int FtdiJtagBitBang::setClkFreq(uint32_t clkHZ) +{ + if (clkHZ > 3000000) + clkHZ = 3000000; + int ret = ftdi_set_baudrate(_ftdi, clkHZ); + printf("ret %d\n", ret); + return ret; } int FtdiJtagBitBang::setBitmode(uint8_t mode) @@ -90,77 +101,111 @@ int FtdiJtagBitBang::setBitmode(uint8_t mode) return ret; } -/** - * store tms in - * internal buffer - */ -int FtdiJtagBitBang::storeTMS(uint8_t *tms, int nb_bit, uint8_t tdi, bool read) +int FtdiJtagBitBang::writeTMS(uint8_t *tms, int len, bool flush_buffer) { - (void) read; - int xfer_len = nb_bit; - /* need to check for available space in buffer */ - if (nb_bit == 0) - return 0; + int ret; - while (xfer_len > 0) { - int xfer = xfer_len; - if ((_nb_bit + 2*xfer) > _buffer_size) - xfer = (_buffer_size - _nb_bit) >> 1; - - for (int i = 0; i < xfer; i++, _nb_bit += 2) { - _in_buf[_nb_bit] = ((tdi)?_tdi_pin:0) | - (((tms[i >> 3] >> (i & 0x7)) & 0x01)? _tms_pin:0); - _in_buf[_nb_bit + 1] = _in_buf[_nb_bit] | _tck_pin; + /* nothing to send + * but maybe need to flush internal buffer + */ + if (len == 0) { + if (flush_buffer) { + ret = flush(); + return ret; } - - xfer_len -= xfer; - if (xfer_len != 0) - write(NULL, 0); + return 0; } - return nb_bit; -} -int FtdiJtagBitBang::writeTMS(uint8_t *tdo, int len) -{ - return write(tdo, len); -} - -/** - * store tdi in - * internal buffer with tms - * size must be <= 8 - */ -int FtdiJtagBitBang::storeTDI(uint8_t tdi, int nb_bit, bool read) -{ - for (int i = 0; i < nb_bit; i++, _nb_bit += 2) { - _in_buf[_nb_bit] = - ((tdi & (1 << (i & 0x7)))?_tdi_pin:0); - _in_buf[_nb_bit + 1] = _in_buf[_nb_bit] | _tck_pin; + /* check for at least one bit space in buffer */ + if (_nb_bit+2 > _buffer_size) { + ret = flush(); + if (ret < 0) + return ret; } - return nb_bit; -} -/** - * store tdi in - * internal buffer - * since TDI is used in shiftDR and shiftIR, tms is always set to 0 - */ -int FtdiJtagBitBang::storeTDI(uint8_t *tdi, int nb_byte, bool read) -{ - /* need to check for available space in buffer */ - for (int i = 0; i < nb_byte * 8; i++, _nb_bit += 2) { - _in_buf[_nb_bit] = - ((tdi[i >> 3] & (1 << (i & 0x7)))?_tdi_pin:0); - _in_buf[_nb_bit + 1] = _in_buf[_nb_bit] | _tck_pin; + /* fill buffer to reduce USB transaction */ + for (int i = 0; i < len; i++) { + _curr_tms = ((tms[i >> 3] & (1 << (i & 0x07)))? _tms_pin : 0); + uint8_t val = _tdi_pin | _curr_tms; + _in_buf[_nb_bit++] = val; + _in_buf[_nb_bit++] = val | _tck_pin; + + if (_nb_bit + 2 > _buffer_size) { + ret = write(NULL, 0); + if (ret < 0) + return ret; + } } - return nb_byte; + + /* security check: try to flush buffer */ + if (flush_buffer) { + ret = write(NULL, 0); + if (ret < 0) + return ret; + } + + return len; } -int FtdiJtagBitBang::writeTDI(uint8_t *tdo, int nb_bit) +int FtdiJtagBitBang::writeTDI(uint8_t *tx, uint8_t *rx, uint32_t len, bool end) { - return write(tdo, nb_bit); + uint32_t iter; + if (len * 2 + 1 < (uint32_t)_buffer_size) { + iter = len; + } else { + iter = _buffer_size >> 1; // two tx / bit + iter = (iter / 8) * 8; + } + + uint8_t *rx_ptr = rx; + + if (len == 0) + return 0; + if (rx) + bzero(rx, len/8); + + for (uint32_t i = 0, pos = 0; i < len; i++) { + /* keep tms or + * set tms high if it's last bit and end true */ + if (end && (i == len -1)) + _curr_tms = _tms_pin; + uint8_t val = _curr_tms; + + if (tx) + val |= ((tx[i >> 3] & (1 << (i & 0x07)))? _tdi_pin : 0); + _in_buf[_nb_bit ] = val; + _in_buf[_nb_bit + 1] = val | _tck_pin; + + _nb_bit += 2; + + pos++; + /* flush buffer */ + if (pos == iter) { + pos = 0; + write((rx) ? rx_ptr : NULL, iter); + if (rx) + rx_ptr += (iter/8); + } + } + + /* security check: try to flush buffer */ + if (_nb_bit != 0) { + write((rx && _nb_bit > 1) ? rx_ptr : NULL, _nb_bit / 2); + } + + return len; } +int FtdiJtagBitBang::toggleClk(uint8_t tms, uint8_t tdo, uint32_t clk_len) +{ + (void) tms; (void) tdo; (void) clk_len; + return -1; +} + +int FtdiJtagBitBang::flush() +{ + return write(NULL, 0); +} int FtdiJtagBitBang::write(uint8_t *tdo, int nb_bit) { @@ -171,13 +216,17 @@ int FtdiJtagBitBang::write(uint8_t *tdo, int nb_bit) setBitmode((tdo) ? BITMODE_SYNCBB : BITMODE_BITBANG); ret = ftdi_write_data(_ftdi, _in_buf, _nb_bit); - if (ret != _nb_bit) + if (ret != _nb_bit) { printf("problem %d written\n", ret); + return ret; + } if (tdo) { ret = ftdi_read_data(_ftdi, _in_buf, _nb_bit); - if (ret != _nb_bit) + if (ret != _nb_bit) { printf("problem %d read\n", ret); + return ret; + } /* need to reconstruct received word * even bit are discarded since JTAG read in rising edge * since jtag is LSB first we need to shift right content by 1 diff --git a/src/ftdiJtagBitbang.hpp b/src/ftdiJtagBitbang.hpp index 1350e2e..8167f41 100644 --- a/src/ftdiJtagBitbang.hpp +++ b/src/ftdiJtagBitbang.hpp @@ -42,21 +42,16 @@ class FtdiJtagBitBang : public JtagInterface, private FTDIpp_MPSSE { const jtag_pins_conf_t *pin_conf, uint32_t clkHZ, bool verbose); virtual ~FtdiJtagBitBang(); - int setClkFreq(uint32_t clkHZ) override { - return FTDIpp_MPSSE::setClkFreq(clkHZ); - } + int setClkFreq(uint32_t clkHZ) override; int setClkFreq(uint32_t clkHZ, char use_divide_by_5) override { return FTDIpp_MPSSE::setClkFreq(clkHZ, use_divide_by_5);} /* TMS */ - int storeTMS(uint8_t *tms, int _bit_len, uint8_t tdi = 1, - bool read = false) override; - int writeTMS(uint8_t *tdo, int len = 0) override; + int writeTMS(uint8_t *tms, int len, bool flush_buffer) override; /* TDI */ - int storeTDI(uint8_t tdi, int nb_bit, bool read) override; - int storeTDI(uint8_t *tdi, int nb_byte, bool read) override; - int writeTDI(uint8_t *tdo, int nb_bit) override; + int writeTDI(uint8_t *tx, uint8_t *rx, uint32_t len, bool end) override; + int toggleClk(uint8_t tms, uint8_t tdo, uint32_t clk_len) override; /*! * \brief return internal buffer size (in byte). @@ -67,6 +62,8 @@ class FtdiJtagBitBang : public JtagInterface, private FTDIpp_MPSSE { bool isFull() override { return _nb_bit == 8*get_buffer_size();} + int flush() override; + private: void init_internal(const FTDIpp_MPSSE::mpsse_bit_config &cable, const jtag_pins_conf_t *pin_conf); @@ -80,5 +77,6 @@ class FtdiJtagBitBang : public JtagInterface, private FTDIpp_MPSSE { uint8_t _tdo_pin; /*!< tdo pin: 1 << pin id */ uint8_t _tdi_pin; /*!< tdi pin: 1 << pin id */ int _nb_bit; + uint8_t _curr_tms; }; #endif diff --git a/src/ftdiJtagMPSSE.cpp b/src/ftdiJtagMPSSE.cpp index b2e0427..888e6c2 100644 --- a/src/ftdiJtagMPSSE.cpp +++ b/src/ftdiJtagMPSSE.cpp @@ -49,8 +49,7 @@ FtdiJtagMPSSE::FtdiJtagMPSSE(const FTDIpp_MPSSE::mpsse_bit_config &cable, FtdiJtagMPSSE::FtdiJtagMPSSE(const FTDIpp_MPSSE::mpsse_bit_config &cable, uint32_t clkHZ, bool verbose): - FTDIpp_MPSSE(cable, clkHZ, verbose), - _ch552WA(false) + FTDIpp_MPSSE(cable, clkHZ, verbose), _ch552WA(false) { init_internal(cable); } @@ -76,8 +75,6 @@ FtdiJtagMPSSE::~FtdiJtagMPSSE() if (read != 5) fprintf(stderr, "Loopback failed, expect problems on later runs %d\n", read); - - free(_in_buf); } void FtdiJtagMPSSE::init_internal(const FTDIpp_MPSSE::mpsse_bit_config &cable) @@ -104,109 +101,194 @@ void FtdiJtagMPSSE::init_internal(const FTDIpp_MPSSE::mpsse_bit_config &cable) display("%x\n", cable.bit_high_val); display("%x\n", cable.bit_high_dir); - _in_buf = (unsigned char *)malloc(sizeof(unsigned char) * _buffer_size); - bzero(_in_buf, _buffer_size); init(5, 0xfb, BITMODE_MPSSE, (FTDIpp_MPSSE::mpsse_bit_config &)cable); } -/** - * store tms in - * internal buffer - * size must be <= 8 - */ -int FtdiJtagMPSSE::storeTMS(uint8_t *tms, int nb_bit, uint8_t tdi, bool read) +int FtdiJtagMPSSE::writeTMS(uint8_t *tms, int len, bool flush_buffer) { - int xfer, pos = 0, tx = nb_bit; - unsigned char buf[3]= {static_cast(MPSSE_WRITE_TMS | MPSSE_LSB | - MPSSE_BITMODE | MPSSE_WRITE_NEG | ((read) ? MPSSE_DO_READ : 0)), - static_cast(0), - static_cast(0)}; + (void) flush_buffer; + display("%s %d %d\n", __func__, len, (len/8)+1); - if (nb_bit == 0) + if (len == 0) return 0; - display("%s: %d %s %d %d %x\n", __func__, tdi, (read) ? "true" : "false", - nb_bit, (nb_bit / 6) * 3, tms[0]); - int plop = 0; + int xfer = len; + int iter = _buffer_size / 3; + int offset = 0, pos = 0; - while (nb_bit != 0) { - xfer = (nb_bit > 6) ? 6 : nb_bit; - buf[1] = xfer - 1; - buf[2] = (tdi)?0x80 : 0x00; - for (int i = 0; i < xfer; i++, pos++) { + uint8_t buf[3]= {static_cast(MPSSE_WRITE_TMS | MPSSE_LSB | + MPSSE_BITMODE | MPSSE_WRITE_NEG), + 0, 0}; + while (xfer > 0) { + int bit_to_send = (xfer > 6) ? 6 : xfer; + buf[1] = bit_to_send-1; + buf[2] = 0x80; + + for (int i = 0; i < bit_to_send; i++, offset++) { buf[2] |= - (((tms[pos >> 3] & (1 << (pos & 0x07))) ? 1 : 0) << i); + (((tms[offset >> 3] & (1 << (offset & 0x07))) ? 1 : 0) << i); } - nb_bit -= xfer; + pos+=3; + mpsse_store(buf, 3); - plop += 3; - } + if (pos == iter * 3) { + pos = 0; + if (mpsse_write() < 0) + printf("writeTMS: error\n"); - return tx; -} - -int FtdiJtagMPSSE::writeTMS(uint8_t *tdo, int len) -{ - display("%s %s %d %d\n", __func__, (tdo)?"true":"false", len, (len/8)+1); - - if (tdo) { - return mpsse_read(tdo, (len/8)+1); - } else { - int ret = mpsse_write(); - if (_ch552WA) { - uint8_t c[len/8+1]; - ftdi_read_data(_ftdi, c, len/8+1); + if (_ch552WA) { + uint8_t c[len/8+1]; + int ret = ftdi_read_data(_ftdi, c, len/8+1); + if (ret != 0) { + printf("ret : %d\n", ret); + } + } } - return ret; + xfer -= bit_to_send; } + mpsse_write(); + if (_ch552WA) { + uint8_t c[len/8+1]; + ftdi_read_data(_ftdi, c, len/8+1); + } + + return len; } -/** - * store tdi in internal buffer - * size must be <= 8 - */ -int FtdiJtagMPSSE::storeTDI(uint8_t tdi, int nb_bit, bool read) +/* need a WA for ch552 */ +int FtdiJtagMPSSE::toggleClk(uint8_t tms, uint8_t tdi, uint32_t clk_len) { + (void) tms; + (void) tdi; + + uint8_t buf[] = {static_cast(0x8e), + 0, 0}; + int xfer_len = clk_len; + while (xfer_len > 0) { + int xfer = (xfer_len > 8) ? 8 : xfer_len; + buf[1] = xfer -1; + mpsse_store(buf, 2); + mpsse_write(); + xfer_len -= xfer; + } + return 0; +} + +int FtdiJtagMPSSE::flush() +{ + return mpsse_write(); +} + +int FtdiJtagMPSSE::writeTDI(uint8_t *tdi, uint8_t *tdo, uint32_t len, bool last) +{ + /* 3 possible case : + * - n * 8bits to send -> use byte command + * - less than 8bits -> use bit command + * - last bit to send -> sent in conjunction with TMS + */ + int tx_buff_size = mpsse_get_buffer_size(); + int real_len = (last) ? len - 1 : len; // if its a buffer in a big send send len + // else supress last bit -> with TMS + int nb_byte = real_len >> 3; // number of byte to send + int nb_bit = (real_len & 0x07); // residual bits + int xfer = tx_buff_size - 3; + unsigned char c[len]; + unsigned char *rx_ptr = (unsigned char *)tdo; + unsigned char *tx_ptr = (unsigned char *)tdi; unsigned char tx_buf[3] = {(unsigned char)(MPSSE_LSB | MPSSE_WRITE_NEG | - MPSSE_DO_WRITE | MPSSE_BITMODE | ((read) ? MPSSE_DO_READ : 0)), - static_cast(nb_bit - 1), - tdi}; - mpsse_store(tx_buf, 3); + ((tdi) ? MPSSE_DO_WRITE : 0) | + ((tdo) ? MPSSE_DO_READ : 0)), + static_cast((xfer - 1) & 0xff), // low + static_cast((((xfer - 1) >> 8) & 0xff))}; // high - return nb_bit; -} + display("%s len : %d %d %d %d\n", __func__, len, real_len, nb_byte, + nb_bit); -/** - * store tdi in internal buffer - */ -int FtdiJtagMPSSE::storeTDI(uint8_t *tdi, int nb_byte, bool read) -{ - unsigned char tx_buf[3] = {(unsigned char)(MPSSE_LSB | MPSSE_WRITE_NEG | - MPSSE_DO_WRITE | - ((read) ? MPSSE_DO_READ : 0)), - static_cast((nb_byte - 1) & 0xff), - static_cast(((nb_byte - 1) >> 8) & 0xff)}; - mpsse_store(tx_buf, 3); - mpsse_store(tdi, nb_byte); + if ((nb_byte * 8) + nb_bit != real_len) { + printf("pas cool\n"); + throw std::exception(); + } - return nb_byte; -} - -/* flush buffer - * if tdo is not null read nb_bit - */ -int FtdiJtagMPSSE::writeTDI(uint8_t *tdo, int nb_bit) -{ - int nb_byte = (nb_bit < 8)? 1: (nb_bit >> 3); - - if (tdo) { - return mpsse_read(tdo, nb_byte); - } else { - int ret = mpsse_write(); - if (_ch552WA) { - uint8_t c[nb_byte]; - ftdi_read_data(_ftdi, c, nb_byte); + while (nb_byte != 0) { + int xfer_len = (nb_byte > xfer) ? xfer : nb_byte; + tx_buf[1] = (((xfer_len - 1) ) & 0xff); // low + tx_buf[2] = (((xfer_len - 1) >> 8) & 0xff); // high + mpsse_store(tx_buf, 3); + if (tdi) { + mpsse_store(tx_ptr, xfer_len); + tx_ptr += xfer_len; } - return ret; + if (tdo) { + mpsse_read(rx_ptr, xfer_len); + rx_ptr += xfer_len; + } else if (_ch552WA) { + mpsse_write(); + ftdi_read_data(_ftdi, c, xfer_len); + } else { + mpsse_write(); + } + nb_byte -= xfer_len; } + + unsigned char last_bit = (tdi) ? *tx_ptr : 0; + + if (nb_bit != 0) { + display("%s read/write %d bit\n", __func__, nb_bit); + tx_buf[0] |= MPSSE_BITMODE; + tx_buf[1] = nb_bit - 1; + mpsse_store(tx_buf, 2); + if (tdi) { + display("%s last_bit %x size %d\n", __func__, last_bit, nb_bit-1); + mpsse_store(last_bit); + } + if (tdo) { + mpsse_read(rx_ptr, 1); + /* realign we have read nb_bit + * since LSB add bit by the left and shift + * we need to complete shift + */ + *rx_ptr >>= (8 - nb_bit); + display("%s %x\n", __func__, *rx_ptr); + } else if (_ch552WA) { + mpsse_write(); + ftdi_read_data(_ftdi, c, nb_bit); + } else { + mpsse_write(); + } + } + + /* display : must be dropped */ + if (_verbose && tdo) { + display("\n"); + for (int i = (len / 8) - 1; i >= 0; i--) + display("%x ", (unsigned char)tdo[i]); + display("\n"); + } + + if (last == 1) { + last_bit = (tdi)? (*tx_ptr & (1 << nb_bit)) : 0; + + display("%s move to EXIT1_xx and send last bit %x\n", __func__, (last_bit?0x81:0x01)); + /* write the last bit in conjunction with TMS */ + tx_buf[0] = MPSSE_WRITE_TMS | MPSSE_LSB | MPSSE_BITMODE | MPSSE_WRITE_NEG | + ((tdo) ? MPSSE_DO_READ : 0); + tx_buf[1] = 0x0; // send 1bit + tx_buf[2] = ((last_bit) ? 0x81 : 0x01); // we know in TMS tdi is bit 7 + // and to move to EXIT_XR TMS = 1 + mpsse_store(tx_buf, 3); + if (tdo) { + unsigned char c; + mpsse_read(&c, 1); + /* in this case for 1 one it's always bit 7 */ + *rx_ptr |= ((c & 0x80) << (7 - nb_bit)); + display("%s %x\n", __func__, c); + } else if (_ch552WA) { + mpsse_write(); + ftdi_read_data(_ftdi, c, 1); + } else { + mpsse_write(); + } + } + + return 0; } diff --git a/src/ftdiJtagMPSSE.hpp b/src/ftdiJtagMPSSE.hpp index 3b03721..80d64a7 100644 --- a/src/ftdiJtagMPSSE.hpp +++ b/src/ftdiJtagMPSSE.hpp @@ -47,13 +47,11 @@ class FtdiJtagMPSSE : public JtagInterface, private FTDIpp_MPSSE { return FTDIpp_MPSSE::setClkFreq(clkHZ, use_divide_by_5);} /* TMS */ - int storeTMS(uint8_t *tms, int nb_bit, uint8_t tdi = 1, - bool read = false) override; - int writeTMS(uint8_t *tdo, int len = 0) override; + int writeTMS(uint8_t *tms, int len, bool flush_buffer) override; + /* clock */ + int toggleClk(uint8_t tms, uint8_t tdi, uint32_t clk_len) override; /* TDI */ - int storeTDI(uint8_t tdi, int nb_bit, bool read) override; - int storeTDI(uint8_t *tdi, int nb_byte, bool read) override; - int writeTDI(uint8_t *tdo, int nb_bit) override; + int writeTDI(uint8_t *tx, uint8_t *rx, uint32_t len, bool end) override; /*! * \brief return internal buffer size (in byte). @@ -63,9 +61,10 @@ class FtdiJtagMPSSE : public JtagInterface, private FTDIpp_MPSSE { bool isFull() override { return false;} + int flush() override; + private: void init_internal(const FTDIpp_MPSSE::mpsse_bit_config &cable); - uint8_t *_in_buf; bool _ch552WA; /* avoid errors with SiPeed tangNano */ }; #endif diff --git a/src/jtag.cpp b/src/jtag.cpp index 68239b7..35959b6 100644 --- a/src/jtag.cpp +++ b/src/jtag.cpp @@ -147,20 +147,19 @@ void Jtag::setTMS(unsigned char tms) int Jtag::flushTMS(bool flush_buffer) { - int xfer = _num_tms; + int ret = 0; if (_num_tms != 0) { display("%s: %d %x\n", __func__, _num_tms, _tms_buffer[0]); - _jtag->storeTMS(_tms_buffer, _num_tms); + ret = _jtag->writeTMS(_tms_buffer, _num_tms, flush_buffer); /* reset buffer and number of bits */ bzero(_tms_buffer, _tms_buffer_size); _num_tms = 0; - if (flush_buffer) { - return _jtag->writeTMS(NULL, xfer); - } + } else if (flush_buffer) { + _jtag->flush(); } - return 0; + return ret; } void Jtag::go_test_logic_reset() @@ -172,123 +171,29 @@ void Jtag::go_test_logic_reset() _state = TEST_LOGIC_RESET; } -/* GGM: faut tenir plus compte de la taille de la fifo interne - * du FT2232 pour maximiser l'envoi au lieu de faire de petits envoies - */ int Jtag::read_write(unsigned char *tdi, unsigned char *tdo, int len, char last) { - /* 3 possible case : - * - n * 8bits to send -> use byte command - * - less than 8bits -> use bit command - * - last bit to send -> sent in conjunction with TMS - */ - int tx_buff_size = _jtag->get_buffer_size(); - int real_len = (last) ? len - 1 : len; // if its a buffer in a big send send len - // else supress last bit -> with TMS - int nb_byte = real_len >> 3; // number of byte to send - int nb_bit = (real_len & 0x07); // residual bits - int xfer = tx_buff_size; - - unsigned char *rx_ptr = (unsigned char *)tdo; - unsigned char *tx_ptr = (unsigned char *)tdi; - flushTMS(true); - - display("%s len : %d %d %d %d %d\n", __func__, len, real_len, nb_byte, - nb_bit, tx_buff_size); - while (nb_byte > xfer) { - display("%s %d %d\n", __func__, nb_byte, xfer); - - if (xfer != _jtag->storeTDI(tx_ptr, xfer, tdo != NULL)) { - printError("%s: Fail to store tdi\n", __func__); - return -1; - } - if (0 > _jtag->writeTDI(rx_ptr, xfer * 8)) { - printError("%s: Write errror\n", __func__); - return -1; - } - if (tdi) - tx_ptr += xfer; - if (tdo) - rx_ptr += xfer; - nb_byte -= xfer; - } - - - /* 1/ send serie of byte */ - if (nb_byte > 0) { - display("%s read/write %d byte\n", __func__, nb_byte); - if (nb_byte != _jtag->storeTDI(tx_ptr, nb_byte, tdo != NULL)) { - printError("%s: Fail to store tdi\n", __func__); - return -1; - } - if (0 > _jtag->writeTDI(((tdo)?rx_ptr:NULL), nb_byte * 8)) { - printError("%s: Write errror\n", __func__); - return -1; - } - if (tdi) - tx_ptr += nb_byte; - if (tdo) - rx_ptr += nb_byte; - } - - unsigned char last_bit = (tdi) ? *tx_ptr : 0; - - if (nb_bit != 0) { - display("%s read/write %d bit\n", __func__, nb_bit); - if (nb_bit != _jtag->storeTDI(last_bit, nb_bit, tdo != NULL)) { - printError("%s: Fail to store tdi\n", __func__); - return -1; - } - if (0 > _jtag->writeTDI((tdo)?rx_ptr:NULL, nb_bit)) { - printError("%s: Write errror\n", __func__); - return -1; - } - - if (tdo) { - /* realign we have read nb_bit - * since LSB add bit by the left and shift - * we need to complete shift - */ - *rx_ptr >>= (8 - nb_bit); - display("%s %x\n", __func__, *rx_ptr); - } - } - - /* display : must be dropped */ - if (_verbose && tdo) { - display("\n"); - for (int i = (len / 8) - 1; i >= 0; i--) - display("%x ", (unsigned char)tdo[i]); - display("\n"); - } - - if (last == 1) { - uint8_t c; - last_bit = (tdi)? (*tx_ptr & (1 << nb_bit)) : 0; - - display("%s move to EXIT1_xx and send last bit %x\n", __func__, (last_bit?0x81:0x01)); - - c=1; - _jtag->storeTMS(&c, 1, (last_bit)?1:0, tdo != NULL); - _jtag->writeTMS((tdo)?&c:NULL, 1); - if (tdo) { - /* in this case for 1 one it's always bit 7 */ - *rx_ptr |= ((c & 0x80) << (7 - nb_bit)); - display("%s %x\n", __func__, c); - } + _jtag->writeTDI(tdi, tdo, len, last); + if (last == 1) _state = (_state == SHIFT_DR) ? EXIT1_DR : EXIT1_IR; - } - return 0; } void Jtag::toggleClk(int nb) { unsigned char c = (TEST_LOGIC_RESET == _state) ? 1 : 0; +#if 0 + flushTMS(true); + if (_jtag->toggleClk(c, 0, nb) >= 0) + return; + throw std::exception(); + return; +#else for (int i = 0; i < nb; i++) setTMS(c); flushTMS(true); +#endif } int Jtag::shiftDR(unsigned char *tdi, unsigned char *tdo, int drlen, int end_state) diff --git a/src/jtag.hpp b/src/jtag.hpp index 8469d49..ec3ffc0 100644 --- a/src/jtag.hpp +++ b/src/jtag.hpp @@ -54,7 +54,7 @@ class Jtag { void go_test_logic_reset(); void set_state(int newState); int flushTMS(bool flush_buffer = false); - void flush() {_jtag->writeTMS(NULL, 0); _jtag->writeTDI(NULL, 0);} + void flush() {flushTMS(); _jtag->flush();} void setTMS(unsigned char tms); enum tapState_t { diff --git a/src/jtagInterface.hpp b/src/jtagInterface.hpp index 6438528..d9ec6a1 100644 --- a/src/jtagInterface.hpp +++ b/src/jtagInterface.hpp @@ -35,44 +35,33 @@ class JtagInterface { virtual int setClkFreq(uint32_t clkHZ) = 0; virtual int setClkFreq(uint32_t clkHZ, char use_divide_by_5) = 0; - /*! - * \brief store TMS states in internal buffer. Not limited to 8 states - * \param tms: array of TMS values - * \param nb_bit: number of TMS states to store - * \param tdi: state of TDI for all TMS to store - * \return number of states stored - */ - virtual int storeTMS(uint8_t *tms, int nb_bit, uint8_t tdi = 1, - bool read = false) = 0; /*! * \brief flush TMS internal buffer (ie. transmit to converter) * \param tdo: pointer for read operation. May be NULL * \param len: number of bit to send * \return number of bit send/received */ - virtual int writeTMS(uint8_t *tdo, int len = 0) = 0; + virtual int writeTMS(uint8_t *tms, int len, bool flush_buffer) = 0; + /*! - * \brief store up to 8 TDI state(s) in internal buffer - * \param tdi: TDI value(s) - * \param tms: state of TMS for all TDI to store - * \param nb_bit: number of TMS states to store - * \return number of states stored + * \brief send TDI bits (mainly in shift DR/IR state) + * \param tdi: array of TDI values (used to write) + * \param tdo: array of TDO values (used when read) + * \param len: number of bit to send/receive + * \param end: in JTAG state machine last bit and tms are set in same time + * but only in shift[i|d]r, if end is false tms remain the same. + * \return number of bit written and/or read */ - virtual int storeTDI(uint8_t tdi, int nb_bit, bool read) = 0; + virtual int writeTDI(uint8_t *tx, uint8_t *rx, uint32_t len, bool end) = 0; + /*! - * \brief store TDI multiple of 8 states in internal buffer. - * \param tdi: array of TDI values - * \param tms: state of TMS for all TDI to store - * \param nb_byte: number of TDI states to store - * \return number of states stored + * \brief toggle clk without touch of TDI/TMS + * \param tms: state of tms signal + * \param tdi: state of tdi signal + * \param clk_len: number of clock cycle + * \return number of clock cycle send */ - virtual int storeTDI(uint8_t *tdi, int nb_byte, bool read) = 0; - /*! - * \brief flush TDI internal buffer (ie. transmit to converter) - * \param tdo: pointer for read operation. May be NULL - * \return number of bit send/received - */ - virtual int writeTDI(uint8_t *tdo, int nb_bit) = 0; + virtual int toggleClk(uint8_t tms, uint8_t tdi, uint32_t clk_len) = 0; /*! * \brief return internal buffer size (in byte) @@ -85,5 +74,11 @@ class JtagInterface { * \return true when internal buffer is full */ virtual bool isFull() = 0; + + /*! + * \brief force internal flush buffer + * \return 1 if success, 0 if nothing to write, -1 is something wrong + */ + virtual int flush() = 0; }; #endif // _JTAGINTERFACE_H_