diff --git a/src/jtag.cpp b/src/jtag.cpp index 9674ed5..49ee674 100644 --- a/src/jtag.cpp +++ b/src/jtag.cpp @@ -51,9 +51,10 @@ using namespace std; #endif /* + * FT232 JTAG PINS MAPPING: * AD0 -> TCK * AD1 -> TDI - * AD2 -> TD0 + * AD2 -> TDO * AD3 -> TMS */ @@ -170,7 +171,7 @@ int Jtag::detectChain(unsigned max_dev) /* cleanup */ _devices_list.clear(); _irlength_list.clear(); - + _ir_bits_before = _ir_bits_after = _dr_bits_before = _dr_bits_after = 0; go_test_logic_reset(); set_state(SHIFT_DR); @@ -259,11 +260,38 @@ bool Jtag::insert_first(uint32_t device_id, uint16_t irlength) return true; } -uint16_t Jtag::device_select(uint16_t index) +int Jtag::device_select(unsigned index) { - if (index > (uint16_t) _devices_list.size()) + if (index > _devices_list.size()) return -1; device_index = index; + /* get number of devices, in the JTAG chain, + * before the selected one + */ + _dr_bits_before = _devices_list.size() - device_index - 1; + /* get number of devices in the JTAG chain + * after the selected one + */ + _dr_bits_after = device_index; + _dr_bits = vector((std::max(_dr_bits_after, _dr_bits_before) + 7)/8, 0); + + /* when the device is not alone and not + * the first a serie of bypass must be + * send to complete send ir sequence + */ + _ir_bits_after = 0; + for (int i = 0; i < device_index; ++i) + _ir_bits_after += _irlength_list[i]; + + /* send serie of bypass instructions + * final size depends on number of device + * before targeted and irlength of each one + */ + _ir_bits_before = 0; + for (unsigned i = device_index + 1; i < _devices_list.size(); ++i) + _ir_bits_before += _irlength_list[i]; + _ir_bits = vector((std::max(_ir_bits_before, _ir_bits_after) + 7) / 8, 0xff); // BYPASS command is all-ones + return device_index; } @@ -332,11 +360,6 @@ void Jtag::toggleClk(int nb) int Jtag::shiftDR(const uint8_t *tdi, unsigned char *tdo, int drlen, tapState_t end_state) { - /* get number of devices in the JTAG chain - * after the selected one - */ - int bits_after = device_index; - /* if current state not shift DR * move to this state */ @@ -344,19 +367,8 @@ int Jtag::shiftDR(const uint8_t *tdi, unsigned char *tdo, int drlen, tapState_t set_state(SHIFT_DR); flushTMS(false); // force transmit tms state - /* get number of devices, in the JTAG chain, - * before the selected one - */ - int bits_before = _devices_list.size() - device_index - 1; - - /* if not 0 send enough bits - */ - if (bits_before > 0) { - int n = (bits_before + 7) / 8; - uint8_t tx[n]; - memset(tx, 0x00, n); - read_write(tx, NULL, bits_before, 0); - } + if (_dr_bits_before) + read_write(_dr_bits.data(), NULL, _dr_bits_before, false); } /* write tdi (and read tdo) to the selected device @@ -364,18 +376,15 @@ int Jtag::shiftDR(const uint8_t *tdi, unsigned char *tdo, int drlen, tapState_t * is the last of the chain and a state change must * be done */ - read_write(tdi, tdo, drlen, bits_after == 0 && end_state != SHIFT_DR); + read_write(tdi, tdo, drlen, _dr_bits_after == 0 && end_state != SHIFT_DR); /* if it's asked to move in FSM */ if (end_state != SHIFT_DR) { /* if current device is not the last */ - if (bits_after > 0) { - int n = (bits_after + 7) / 8; - uint8_t tx[n]; - memset(tx, 0x00, n); - read_write(tx, NULL, bits_after, 1); // its the last force - // tms high with last bit - } + if (_dr_bits_after) + read_write(_dr_bits.data(), NULL, _dr_bits_after, true); // its the last force + // tms high with last bit + /* move to end_state */ set_state(end_state); @@ -395,37 +404,12 @@ int Jtag::shiftIR(unsigned char tdi, int irlen, tapState_t end_state) int Jtag::shiftIR(unsigned char *tdi, unsigned char *tdo, int irlen, tapState_t end_state) { display("%s: avant shiftIR\n", __func__); - int bypass_after = 0; - if (end_state != SHIFT_IR) { - /* when the device is not alone and not - * the first a serie of bypass must be - * send to complete send ir sequence - */ - for (int i = 0; i < device_index; i++) - bypass_after += _irlength_list[i]; - } /* if not in SHIFT IR move to this state */ if (_state != SHIFT_IR) { set_state(SHIFT_IR); - /* force flush */ - flushTMS(false); - - /* send serie of bypass instructions - * final size depends on number of device - * before targeted and irlength of each one - */ - int bypass_before = 0; - for (unsigned int i = device_index + 1; i < _devices_list.size(); i++) - bypass_before += _irlength_list[i]; - - /* if > 0 send bits */ - if (bypass_before > 0) { - int n = (bypass_before + 7) / 8; - uint8_t tx[n]; - memset(tx, 0xff, n); - read_write(tx, NULL, bypass_before, 0); - } + if (_ir_bits_before) + read_write(_ir_bits.data(), NULL, _ir_bits_before, false); } display("%s: envoi ircode\n", __func__); @@ -435,17 +419,13 @@ int Jtag::shiftIR(unsigned char *tdi, unsigned char *tdo, int irlen, tapState_t * is the last of the chain and a state change must * be done */ - read_write(tdi, tdo, irlen, bypass_after == 0 && end_state != SHIFT_IR); + read_write(tdi, tdo, irlen, _ir_bits_after == 0 && end_state != SHIFT_IR); /* it's asked to move out of SHIFT IR state */ if (end_state != SHIFT_IR) { /* again if devices after fill '1' */ - if (bypass_after > 0) { - int n = (bypass_after + 7) / 8; - uint8_t tx[n]; - memset(tx, 0xff, n); - read_write(tx, NULL, bypass_after, 1); - } + if (_ir_bits_after > 0) + read_write(_ir_bits.data(), NULL, _ir_bits_after, true); /* move to the requested state */ set_state(end_state); } diff --git a/src/jtag.hpp b/src/jtag.hpp index 45eb5c8..bdd3eba 100644 --- a/src/jtag.hpp +++ b/src/jtag.hpp @@ -53,7 +53,7 @@ class Jtag { * \param[in] index: index in the chain * \return -1 if index is out of bound, index otherwise */ - uint16_t device_select(uint16_t index); + int device_select(unsigned index); /*! * \brief inject a device into list at the begin * \param[in] device_id: idcode @@ -127,6 +127,16 @@ class Jtag { std::string _board_name; int device_index; /*!< index for targeted FPGA */ + + // Assume passive devices in JTAG chain are switched to BYPASS mode, + // thus each device requeres 1 bit during SHIFT-DR + unsigned _dr_bits_before, _dr_bits_after; + std::vector _dr_bits; + + // For the above we need for add BYPASS commands for each passive device + unsigned _ir_bits_before, _ir_bits_after; + std::vector _ir_bits; + std::vector _devices_list; /*!< ordered list of devices idcode */ std::vector _irlength_list; /*!< ordered list of irlength */ };