xvc_server: fix comm when Vivado acts as client
This commit is contained in:
parent
a481c1e699
commit
a0180f0bc6
|
|
@ -26,7 +26,7 @@ XVC_server::XVC_server(int port, const cable_t & cable,
|
||||||
const string & firmware_path):_verbose(verbose > 1),
|
const string & firmware_path):_verbose(verbose > 1),
|
||||||
_jtag(NULL), _port(port), _sock(-1),
|
_jtag(NULL), _port(port), _sock(-1),
|
||||||
_is_stopped(false), _must_stop(false),
|
_is_stopped(false), _must_stop(false),
|
||||||
_buffer_size(2048)
|
_buffer_size(2048), _state(Jtag::RUN_TEST_IDLE)
|
||||||
{
|
{
|
||||||
(void)pin_conf;
|
(void)pin_conf;
|
||||||
(void)ip_adr;
|
(void)ip_adr;
|
||||||
|
|
@ -226,9 +226,9 @@ int XVC_server::sread(int fd, void *target, int len)
|
||||||
unsigned char *t = (unsigned char *)target;
|
unsigned char *t = (unsigned char *)target;
|
||||||
while (len) {
|
while (len) {
|
||||||
int r = read(fd, t, len);
|
int r = read(fd, t, len);
|
||||||
if (r == 0) // connection closed
|
if (r == 0){ // connection closed
|
||||||
return 2;
|
return 2;
|
||||||
else if (r < 0) {
|
} else if (r < 0) {
|
||||||
char err[256];
|
char err[256];
|
||||||
snprintf(err, 256, "Read error (%d) %d %s\n", r,
|
snprintf(err, 256, "Read error (%d) %d %s\n", r,
|
||||||
errno, strerror(errno));
|
errno, strerror(errno));
|
||||||
|
|
@ -337,12 +337,11 @@ int XVC_server::handle_data(int fd)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 3. receive 2 x nr_bytes (TMS + TDI) */
|
/* 3. receive 2 x nr_bytes (TMS + TDI) */
|
||||||
memset(_tmstdi, 0, _buffer_size);
|
|
||||||
if ((ret = sread(fd, _tmstdi, nr_bytes * 2)) != 1) {
|
if ((ret = sread(fd, _tmstdi, nr_bytes * 2)) != 1) {
|
||||||
printError("reading data failed");
|
printError("reading data failed");
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
memset(_result, 0, _buffer_size/2);
|
memset(_result, 0, nr_bytes);
|
||||||
|
|
||||||
if (_verbose) {
|
if (_verbose) {
|
||||||
printInfo("\tNumber of Bits : " + std::to_string(len));
|
printInfo("\tNumber of Bits : " + std::to_string(len));
|
||||||
|
|
@ -350,8 +349,17 @@ int XVC_server::handle_data(int fd)
|
||||||
printInfo("\n");
|
printInfo("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_jtag)
|
// Due to a weird bug(??) xilinx impacts goes through another
|
||||||
|
// "capture_ir"/"capture_dr" cycle after reading IR/DR which
|
||||||
|
// unfortunately sets IR to the read-out IR value.
|
||||||
|
// Just ignore these transactions.
|
||||||
|
// ref: https://github.com/tmbinc/xvcd/blob/ftdi/src/xvcd.c#L265
|
||||||
|
if (!((_state == Jtag::EXIT1_IR && len == 5 && _tmstdi[0] == 0x17) ||
|
||||||
|
(_state == Jtag::EXIT1_DR && len == 4 && _tmstdi[0] == 0x6b))) {
|
||||||
|
// update state using tms sequence
|
||||||
|
set_state(_tmstdi, len);
|
||||||
_jtag->writeTMSTDI(_tmstdi, _tmstdi + nr_bytes, _result, len);
|
_jtag->writeTMSTDI(_tmstdi, _tmstdi + nr_bytes, _result, len);
|
||||||
|
}
|
||||||
|
|
||||||
/* send received TDO sequence */
|
/* send received TDO sequence */
|
||||||
if (send(fd, _result, nr_bytes, 0) != nr_bytes) {
|
if (send(fd, _result, nr_bytes, 0) != nr_bytes) {
|
||||||
|
|
@ -361,3 +369,69 @@ int XVC_server::handle_data(int fd)
|
||||||
} while (1);
|
} while (1);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* loops over tms_seq, extracts bit by bit values and update
|
||||||
|
* jtag "virtual" state accordingly.
|
||||||
|
*/
|
||||||
|
Jtag::tapState_t XVC_server::set_state(const uint8_t *tms_seq, uint32_t len)
|
||||||
|
{
|
||||||
|
for (uint32_t i = 0; i < len; i++) {
|
||||||
|
uint8_t tms = !!(tms_seq[i >> 3] & (1 << (i & 0x07)));
|
||||||
|
switch (_state) {
|
||||||
|
case Jtag::TEST_LOGIC_RESET:
|
||||||
|
_state = (tms) ? Jtag::TEST_LOGIC_RESET : Jtag::RUN_TEST_IDLE;
|
||||||
|
break;
|
||||||
|
case Jtag::RUN_TEST_IDLE:
|
||||||
|
_state = (tms) ? Jtag::SELECT_DR_SCAN : Jtag::RUN_TEST_IDLE;
|
||||||
|
break;
|
||||||
|
case Jtag::SELECT_DR_SCAN:
|
||||||
|
_state = (tms) ? Jtag::SELECT_IR_SCAN: Jtag::CAPTURE_DR;
|
||||||
|
break;
|
||||||
|
case Jtag::CAPTURE_DR:
|
||||||
|
_state = (tms) ? Jtag::EXIT1_DR : Jtag::SHIFT_DR;
|
||||||
|
break;
|
||||||
|
case Jtag::SHIFT_DR:
|
||||||
|
_state = (tms) ? Jtag::EXIT1_DR : Jtag::CAPTURE_DR;
|
||||||
|
break;
|
||||||
|
case Jtag::EXIT1_DR:
|
||||||
|
_state = (tms) ? Jtag::UPDATE_DR : Jtag::PAUSE_DR;
|
||||||
|
break;
|
||||||
|
case Jtag::PAUSE_DR:
|
||||||
|
_state = (tms) ? Jtag::EXIT2_DR : Jtag::PAUSE_DR;
|
||||||
|
break;
|
||||||
|
case Jtag::EXIT2_DR:
|
||||||
|
_state = (tms) ? Jtag::UPDATE_DR : Jtag::SHIFT_DR;
|
||||||
|
break;
|
||||||
|
case Jtag::UPDATE_DR:
|
||||||
|
_state = (tms) ? Jtag::SELECT_DR_SCAN : Jtag::RUN_TEST_IDLE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Jtag::SELECT_IR_SCAN:
|
||||||
|
_state = (tms) ? Jtag::TEST_LOGIC_RESET : Jtag::CAPTURE_IR;
|
||||||
|
break;
|
||||||
|
case Jtag::CAPTURE_IR:
|
||||||
|
_state = (tms) ? Jtag::EXIT1_IR : Jtag::SHIFT_IR;
|
||||||
|
break;
|
||||||
|
case Jtag::SHIFT_IR:
|
||||||
|
_state = (tms) ? Jtag::EXIT1_IR : Jtag::CAPTURE_IR;
|
||||||
|
break;
|
||||||
|
case Jtag::EXIT1_IR:
|
||||||
|
_state = (tms) ? Jtag::UPDATE_IR : Jtag::PAUSE_IR;
|
||||||
|
break;
|
||||||
|
case Jtag::PAUSE_IR:
|
||||||
|
_state = (tms) ? Jtag::EXIT2_IR : Jtag::PAUSE_IR;
|
||||||
|
break;
|
||||||
|
case Jtag::EXIT2_IR:
|
||||||
|
_state = (tms) ? Jtag::UPDATE_IR : Jtag::SHIFT_IR;
|
||||||
|
break;
|
||||||
|
case Jtag::UPDATE_IR:
|
||||||
|
_state = (tms) ? Jtag::SELECT_DR_SCAN : Jtag::RUN_TEST_IDLE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* pass */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return _state;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,19 @@ class XVC_server {
|
||||||
*/
|
*/
|
||||||
bool listen_loop();
|
bool listen_loop();
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief update jtag virtual state by following the tms sequence
|
||||||
|
* \param tms_seq: tms sequence lsb first
|
||||||
|
* \param len: number of tms bit to apply
|
||||||
|
* \return jtag state after applying sequence
|
||||||
|
*/
|
||||||
|
Jtag::tapState_t set_state(const uint8_t *tms_seq, uint32_t len);
|
||||||
|
/*!
|
||||||
|
* \brief return actual jtag state
|
||||||
|
* \return jtag state
|
||||||
|
*/
|
||||||
|
Jtag::tapState_t get_state() { return _state;}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/*!
|
/*!
|
||||||
* \brief thread dedicated for wait for incoming connection
|
* \brief thread dedicated for wait for incoming connection
|
||||||
|
|
@ -62,6 +75,7 @@ class XVC_server {
|
||||||
* \return 3 when failure, 2 when connection closed, 1 otherwise
|
* \return 3 when failure, 2 when connection closed, 1 otherwise
|
||||||
*/
|
*/
|
||||||
int sread(int fd, void *target, int len);
|
int sread(int fd, void *target, int len);
|
||||||
|
|
||||||
int _verbose; /*!< verbose level */
|
int _verbose; /*!< verbose level */
|
||||||
JtagInterface *_jtag; /*!< jtag interface */
|
JtagInterface *_jtag; /*!< jtag interface */
|
||||||
int _port; /*!< network port */
|
int _port; /*!< network port */
|
||||||
|
|
@ -73,6 +87,7 @@ class XVC_server {
|
||||||
uint32_t _buffer_size; /*!< buffer max capacity TDI+TMS */
|
uint32_t _buffer_size; /*!< buffer max capacity TDI+TMS */
|
||||||
uint8_t *_tmstdi; /*!< TDI/TMS from client */
|
uint8_t *_tmstdi; /*!< TDI/TMS from client */
|
||||||
uint8_t *_result; /*!< buffer for server -> client */
|
uint8_t *_result; /*!< buffer for server -> client */
|
||||||
|
Jtag::tapState_t _state; /*!< actual jtag state */
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // SRC_XVC_SERVER_HPP_
|
#endif // SRC_XVC_SERVER_HPP_
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue