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
This commit is contained in:
Gwenhael Goavec-Merou 2020-05-31 15:57:21 +02:00
parent 652b3d292e
commit 275ba38207
7 changed files with 331 additions and 303 deletions

View File

@ -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)
int ret;
/* nothing to send
* but maybe need to flush internal buffer
*/
if (len == 0) {
if (flush_buffer) {
ret = flush();
return ret;
}
return 0;
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;
}
xfer_len -= xfer;
if (xfer_len != 0)
write(NULL, 0);
/* 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;
}
int FtdiJtagBitBang::writeTMS(uint8_t *tdo, int len)
{
return write(tdo, len);
}
/* 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;
/**
* 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;
if (_nb_bit + 2 > _buffer_size) {
ret = write(NULL, 0);
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;
}
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

View File

@ -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

View File

@ -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<unsigned char>(MPSSE_WRITE_TMS | MPSSE_LSB |
MPSSE_BITMODE | MPSSE_WRITE_NEG | ((read) ? MPSSE_DO_READ : 0)),
static_cast<unsigned char>(0),
static_cast<unsigned char>(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<unsigned char>(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");
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 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();
}
}
xfer -= bit_to_send;
}
mpsse_write();
if (_ch552WA) {
uint8_t c[len/8+1];
ftdi_read_data(_ftdi, c, len/8+1);
}
return ret;
return len;
}
/* 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<uint8_t>(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;
}
/**
* store tdi in internal buffer
* size must be <= 8
*/
int FtdiJtagMPSSE::storeTDI(uint8_t tdi, int nb_bit, bool read)
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<unsigned char>(nb_bit - 1),
tdi};
((tdi) ? MPSSE_DO_WRITE : 0) |
((tdo) ? MPSSE_DO_READ : 0)),
static_cast<unsigned char>((xfer - 1) & 0xff), // low
static_cast<unsigned char>((((xfer - 1) >> 8) & 0xff))}; // high
display("%s len : %d %d %d %d\n", __func__, len, real_len, nb_byte,
nb_bit);
if ((nb_byte * 8) + nb_bit != real_len) {
printf("pas cool\n");
throw std::exception();
}
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);
return 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<unsigned char>((nb_byte - 1) & 0xff),
static_cast<unsigned char>(((nb_byte - 1) >> 8) & 0xff)};
mpsse_store(tx_buf, 3);
mpsse_store(tdi, nb_byte);
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 (tdi) {
mpsse_store(tx_ptr, xfer_len);
tx_ptr += xfer_len;
}
if (tdo) {
return mpsse_read(tdo, nb_byte);
mpsse_read(rx_ptr, xfer_len);
rx_ptr += xfer_len;
} else if (_ch552WA) {
mpsse_write();
ftdi_read_data(_ftdi, c, xfer_len);
} else {
int ret = mpsse_write();
if (_ch552WA) {
uint8_t c[nb_byte];
ftdi_read_data(_ftdi, c, nb_byte);
mpsse_write();
}
return ret;
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;
}

View File

@ -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

View File

@ -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)

View File

@ -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 {

View File

@ -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_