rename ftdijtag to jtag

- drop everything about ftdi
- use jtagInterface to communicate with hardware
- for all class using jtag: rename FtdiJtag -> Jtag
This commit is contained in:
Gwenhael Goavec-Merou 2020-03-06 09:05:57 +01:00
parent 890fc3c767
commit 9c9348f7d0
18 changed files with 284 additions and 293 deletions

View File

@ -1,5 +1,6 @@
#include <string.h>
#include "altera.hpp" #include "altera.hpp"
#include "ftdijtag.hpp" #include "jtag.hpp"
#include "device.hpp" #include "device.hpp"
#include "epcq.hpp" #include "epcq.hpp"
@ -8,7 +9,7 @@
// DATA_DIR is defined at compile time. // DATA_DIR is defined at compile time.
#define BIT_FOR_FLASH (DATA_DIR "/openFPGALoader/test_sfl.svf") #define BIT_FOR_FLASH (DATA_DIR "/openFPGALoader/test_sfl.svf")
Altera::Altera(FtdiJtag *jtag, std::string filename, bool verbose): Altera::Altera(Jtag *jtag, std::string filename, bool verbose):
Device(jtag, filename, verbose), _svf(_jtag, _verbose) Device(jtag, filename, verbose), _svf(_jtag, _verbose)
{ {
if (_filename != "") { if (_filename != "") {
@ -24,10 +25,10 @@ void Altera::reset()
{ {
/* PULSE_NCONFIG */ /* PULSE_NCONFIG */
unsigned char tx_buff[2] = {0x01, 0x00}; unsigned char tx_buff[2] = {0x01, 0x00};
_jtag->set_state(FtdiJtag::TEST_LOGIC_RESET); _jtag->set_state(Jtag::TEST_LOGIC_RESET);
_jtag->shiftIR(tx_buff, NULL, IRLENGTH); _jtag->shiftIR(tx_buff, NULL, IRLENGTH);
_jtag->toggleClk(1); _jtag->toggleClk(1);
_jtag->set_state(FtdiJtag::TEST_LOGIC_RESET); _jtag->set_state(Jtag::TEST_LOGIC_RESET);
} }
void Altera::program(unsigned int offset) void Altera::program(unsigned int offset)
@ -45,7 +46,7 @@ void Altera::program(unsigned int offset)
_svf.parse(_filename); _svf.parse(_filename);
} else if (_mode == Device::SPI_MODE) { } else if (_mode == Device::SPI_MODE) {
/* GGM: TODO: fix this issue */ /* GGM: TODO: fix this issue */
EPCQ epcq(_jtag->vid(), _jtag->pid(), 2, 6000000); EPCQ epcq(0x403, 0x6010/*_jtag->vid(), _jtag->pid()*/, 2, 6000000);
_svf.parse(BIT_FOR_FLASH); _svf.parse(BIT_FOR_FLASH);
epcq.program(offset, _filename, (_file_extension == "rpd")? true:false); epcq.program(offset, _filename, (_file_extension == "rpd")? true:false);
reset(); reset();
@ -53,11 +54,12 @@ void Altera::program(unsigned int offset)
} }
int Altera::idCode() int Altera::idCode()
{ {
unsigned char tx_data = IDCODE; unsigned char tx_data[4] = {IDCODE};
unsigned char rx_data[4]; unsigned char rx_data[4];
_jtag->go_test_logic_reset(); _jtag->go_test_logic_reset();
_jtag->shiftIR(&tx_data, NULL, IRLENGTH); _jtag->shiftIR(tx_data, NULL, IRLENGTH);
_jtag->shiftDR(NULL, rx_data, 32); bzero(tx_data, 4);
_jtag->shiftDR(tx_data, rx_data, 32);
return ((rx_data[0] & 0x000000ff) | return ((rx_data[0] & 0x000000ff) |
((rx_data[1] << 8) & 0x0000ff00) | ((rx_data[1] << 8) & 0x0000ff00) |
((rx_data[2] << 16) & 0x00ff0000) | ((rx_data[2] << 16) & 0x00ff0000) |

View File

@ -3,12 +3,12 @@
#include "bitparser.hpp" #include "bitparser.hpp"
#include "device.hpp" #include "device.hpp"
#include "ftdijtag.hpp" #include "jtag.hpp"
#include "svf_jtag.hpp" #include "svf_jtag.hpp"
class Altera: public Device { class Altera: public Device {
public: public:
Altera(FtdiJtag *jtag, std::string filename, bool verbose); Altera(Jtag *jtag, std::string filename, bool verbose);
~Altera(); ~Altera();
void program(unsigned int offset = 0); void program(unsigned int offset = 0);

View File

@ -5,7 +5,7 @@
using namespace std; using namespace std;
Device::Device(FtdiJtag *jtag, string filename, bool verbose): Device::Device(Jtag *jtag, string filename, bool verbose):
_filename(filename), _filename(filename),
_file_extension(filename.substr(filename.find_last_of(".") +1)), _file_extension(filename.substr(filename.find_last_of(".") +1)),
_mode(NONE_MODE), _verbose(verbose) _mode(NONE_MODE), _verbose(verbose)

View File

@ -3,7 +3,7 @@
#include <iostream> #include <iostream>
#include "ftdijtag.hpp" #include "jtag.hpp"
/* GGM: TODO: program must have an optional /* GGM: TODO: program must have an optional
* offset * offset
@ -18,13 +18,13 @@ class Device {
FLASH_MODE = 1, FLASH_MODE = 1,
MEM_MODE = 2 MEM_MODE = 2
}; };
Device(FtdiJtag *jtag, std::string filename, bool verbose = false); Device(Jtag *jtag, std::string filename, bool verbose = false);
virtual ~Device(); virtual ~Device();
virtual void program(unsigned int offset = 0) = 0; virtual void program(unsigned int offset = 0) = 0;
virtual int idCode() = 0; virtual int idCode() = 0;
virtual void reset(); virtual void reset();
protected: protected:
FtdiJtag *_jtag; Jtag *_jtag;
std::string _filename; std::string _filename;
std::string _file_extension; std::string _file_extension;
enum prog_mode _mode; enum prog_mode _mode;

View File

@ -1,65 +0,0 @@
#ifndef FTDIJTAG_H
#define FTDIJTAG_H
#include <ftdi.h>
#include <iostream>
#include <vector>
#include "ftdipp_mpsse.hpp"
class FtdiJtag : public FTDIpp_MPSSE {
public:
//FtdiJtag(std::string board_name, int vid, int pid, unsigned char interface, uint32_t clkHZ);
FtdiJtag(FTDIpp_MPSSE::mpsse_bit_config &cable, std::string dev,
unsigned char interface, uint32_t clkHZ, bool verbose = false);
FtdiJtag(FTDIpp_MPSSE::mpsse_bit_config &cable, unsigned char interface, uint32_t clkHZ,
bool verbose);
~FtdiJtag();
int detectChain(std::vector<int> &devices, int max_dev);
int shiftIR(unsigned char *tdi, unsigned char *tdo, int irlen, int end_state = RUN_TEST_IDLE);
int shiftIR(unsigned char tdi, int irlen, int end_state = RUN_TEST_IDLE);
int shiftDR(unsigned char *tdi, unsigned char *tdo, int drlen, int end_state = RUN_TEST_IDLE);
int read_write(unsigned char *tdi, unsigned char *tdo, int len, char last);
void toggleClk(int nb);
void go_test_logic_reset();
void set_state(int newState);
int flushTMS(bool flush_buffer = false);
void flush() {mpsse_write();}
void setTMS(unsigned char tms);
enum tapState_t {
TEST_LOGIC_RESET = 0,
RUN_TEST_IDLE = 1,
SELECT_DR_SCAN = 2,
CAPTURE_DR = 3,
SHIFT_DR = 4,
EXIT1_DR = 5,
PAUSE_DR = 6,
EXIT2_DR = 7,
UPDATE_DR = 8,
SELECT_IR_SCAN = 9,
CAPTURE_IR = 10,
SHIFT_IR = 11,
EXIT1_IR = 12,
PAUSE_IR = 13,
EXIT2_IR = 14,
UPDATE_IR = 15,
UNKNOWN = 999
};
const char *getStateName(tapState_t s);
/* utilities */
void setVerbose(bool verbose){_verbose=verbose;}
private:
void init_internal(FTDIpp_MPSSE::mpsse_bit_config &cable);
int _state;
int _tms_buffer_size;
int _num_tms;
unsigned char *_tms_buffer;
std::string _board_name;
bool _ch552WA;
};
#endif

View File

@ -24,7 +24,7 @@
#include <iostream> #include <iostream>
#include "ftdijtag.hpp" #include "jtag.hpp"
#include "gowin.hpp" #include "gowin.hpp"
#include "progressBar.hpp" #include "progressBar.hpp"
#include "display.hpp" #include "display.hpp"
@ -63,7 +63,7 @@ using namespace std;
#define EF_PROGRAM 0x71 #define EF_PROGRAM 0x71
#define EFLASH_ERASE 0x75 #define EFLASH_ERASE 0x75
Gowin::Gowin(FtdiJtag *jtag, const string filename, bool flash_wr, bool sram_wr, Gowin::Gowin(Jtag *jtag, const string filename, bool flash_wr, bool sram_wr,
bool verbose): Device(jtag, filename, verbose) bool verbose): Device(jtag, filename, verbose)
{ {
_fs = NULL; _fs = NULL;
@ -372,7 +372,7 @@ bool Gowin::flashFLASH(uint8_t *data, int length)
progress.display(i); progress.display(i);
} }
/* 2.2.6.6 */ /* 2.2.6.6 */
_jtag->set_state(FtdiJtag::RUN_TEST_IDLE); _jtag->set_state(Jtag::RUN_TEST_IDLE);
progress.done(); progress.done();
return true; return true;
@ -390,25 +390,28 @@ bool Gowin::flashSRAM(uint8_t *data, int length)
wr_rd(XFER_WRITE, NULL, 0, NULL, 0); wr_rd(XFER_WRITE, NULL, 0, NULL, 0);
/* 2.2.6.5 */ /* 2.2.6.5 */
_jtag->set_state(FtdiJtag::SHIFT_DR); _jtag->set_state(Jtag::SHIFT_DR);
for (int i=0; i < byte_length; i+=256) { int xfer_len = 256;
if (i + 256 > byte_length) { // last packet with some size
for (int i=0; i < byte_length; i+=xfer_len) {
if (i + xfer_len > byte_length) { // last packet with some size
tx_len = (byte_length - i) * 8; tx_len = (byte_length - i) * 8;
tx_end = 1; // to move in EXIT1_DR tx_end = 1; // to move in EXIT1_DR
} else { } else {
tx_len = 256 * 8; tx_len = xfer_len * 8;
tx_end = 0; tx_end = 0;
} }
_jtag->read_write(data+i, NULL, tx_len, tx_end); _jtag->read_write(data+i, NULL, tx_len, tx_end);
_jtag->flush(); //_jtag->flush();
progress.display(i); progress.display(i);
} }
/* 2.2.6.6 */ /* 2.2.6.6 */
_jtag->set_state(FtdiJtag::RUN_TEST_IDLE); _jtag->set_state(Jtag::RUN_TEST_IDLE);
/* p.15 fig 2.11 */ /* p.15 fig 2.11 */
wr_rd(XFER_DONE, NULL, 0, NULL, 0); wr_rd(XFER_DONE, NULL, 0, NULL, 0);
if (pollFlag(STATUS_DONE_FINAL, STATUS_DONE_FINAL)) { if (pollFlag(STATUS_DONE_FINAL, STATUS_DONE_FINAL)) {
progress.done(); progress.done();
return true; return true;
@ -426,7 +429,7 @@ bool Gowin::eraseFLASH()
unsigned char tx[4] = {0, 0, 0, 0}; unsigned char tx[4] = {0, 0, 0, 0};
printInfo("erase Flash ", false); printInfo("erase Flash ", false);
wr_rd(EFLASH_ERASE, NULL, 0, NULL, 0); wr_rd(EFLASH_ERASE, NULL, 0, NULL, 0);
_jtag->set_state(FtdiJtag::RUN_TEST_IDLE); _jtag->set_state(Jtag::RUN_TEST_IDLE);
_jtag->shiftDR(tx, NULL, 32); _jtag->shiftDR(tx, NULL, 32);
/* TN653 specifies to wait for 120ms with /* TN653 specifies to wait for 120ms with
* there are no bit in status register to specify * there are no bit in status register to specify

View File

@ -25,12 +25,12 @@
#include "device.hpp" #include "device.hpp"
#include "fsparser.hpp" #include "fsparser.hpp"
#include "ftdijtag.hpp" #include "jtag.hpp"
#include "jedParser.hpp" #include "jedParser.hpp"
class Gowin: public Device { class Gowin: public Device {
public: public:
Gowin(FtdiJtag *jtag, std::string filename, bool flash_wr, bool sram_wr, Gowin(Jtag *jtag, std::string filename, bool flash_wr, bool sram_wr,
bool verbose); bool verbose);
~Gowin(); ~Gowin();
int idCode() override; int idCode() override;

View File

@ -1,3 +1,20 @@
/*
* Copyright (C) 2020 Gwenhael Goavec-Merou <gwenhael.goavec-merou@trabucayre.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <libusb.h> #include <libusb.h>
#include <iostream> #include <iostream>
@ -7,8 +24,11 @@
#include <string.h> #include <string.h>
#include <string> #include <string>
#include "ftdijtag.hpp" #include "display.hpp"
#include "jtag.hpp"
#include "ftdipp_mpsse.hpp" #include "ftdipp_mpsse.hpp"
#include "ftdiJtagBitbang.hpp"
#include "ftdiJtagMPSSE.hpp"
using namespace std; using namespace std;
@ -43,81 +63,42 @@ using namespace std;
* - envoyer le dernier avec 0x4B ou 0x6B * - envoyer le dernier avec 0x4B ou 0x6B
*/ */
FtdiJtag::FtdiJtag(FTDIpp_MPSSE::mpsse_bit_config &cable, string dev, Jtag::Jtag(FTDIpp_MPSSE::mpsse_bit_config &cable, string dev,
unsigned char interface, uint32_t clkHZ, bool verbose): unsigned char interface, uint32_t clkHZ, bool verbose):
FTDIpp_MPSSE(dev, interface, clkHZ, verbose), _verbose(verbose),
_state(RUN_TEST_IDLE), _state(RUN_TEST_IDLE),
_tms_buffer_size(128), _num_tms(0), _tms_buffer_size(128), _num_tms(0),
_board_name("nope"), _ch552WA(false) _board_name("nope")
{ {
init_internal(cable); init_internal(cable, interface, clkHZ);
} }
FtdiJtag::FtdiJtag(FTDIpp_MPSSE::mpsse_bit_config &cable, Jtag::Jtag(FTDIpp_MPSSE::mpsse_bit_config &cable,
unsigned char interface, uint32_t clkHZ, bool verbose): unsigned char interface, uint32_t clkHZ, bool verbose):
FTDIpp_MPSSE(cable.vid, cable.pid, interface, clkHZ, verbose), _verbose(verbose),
_state(RUN_TEST_IDLE), _state(RUN_TEST_IDLE),
_tms_buffer_size(128), _num_tms(0), _tms_buffer_size(128), _num_tms(0),
_board_name("nope"), _ch552WA(false) _board_name("nope")
{ {
init_internal(cable); init_internal(cable, interface, clkHZ);
} }
FtdiJtag::~FtdiJtag() Jtag::~Jtag()
{ {
int read;
/* Before shutdown, we must wait until everything is shifted out
* Do this by temporary enabling loopback mode, write something
* and wait until we can read it back
* */
static unsigned char tbuf[16] = { SET_BITS_LOW, 0xff, 0x00,
SET_BITS_HIGH, 0xff, 0x00,
LOOPBACK_START,
MPSSE_DO_READ |
MPSSE_DO_WRITE | MPSSE_WRITE_NEG | MPSSE_LSB,
0x04, 0x00,
0xaa, 0x55, 0x00, 0xff, 0xaa,
LOOPBACK_END
};
mpsse_store(tbuf, 16);
read = mpsse_read(tbuf, 5);
if (read != 5)
fprintf(stderr,
"Loopback failed, expect problems on later runs %d\n", read);
free(_tms_buffer); free(_tms_buffer);
delete _jtag;
} }
void FtdiJtag::init_internal(FTDIpp_MPSSE::mpsse_bit_config &cable) void Jtag::init_internal(FTDIpp_MPSSE::mpsse_bit_config &cable,
unsigned char interface, uint32_t clkHZ)
{ {
/* search for iProduct -> need to have _jtag = new FtdiJtagMPSSE(cable, interface, clkHZ, _verbose);
* ftdi->usb_dev (libusb_device_handler) -> libusb_device ->
* libusb_device_descriptor
*/
struct libusb_device * usb_dev = libusb_get_device(_ftdi->usb_dev);
struct libusb_device_descriptor usb_desc;
unsigned char iProduct[200];
libusb_get_device_descriptor(usb_dev, &usb_desc);
libusb_get_string_descriptor_ascii(_ftdi->usb_dev, usb_desc.iProduct,
iProduct, 200);
display("iProduct : %s\n", iProduct);
if (!strncmp((const char *)iProduct, "Sipeed-Debug", 12)) {
_ch552WA = true;
}
display("board_name %s\n", _board_name.c_str());
display("%x\n", cable.bit_low_val);
display("%x\n", cable.bit_low_dir);
display("%x\n", cable.bit_high_val);
display("%x\n", cable.bit_high_dir);
_tms_buffer = (unsigned char *)malloc(sizeof(unsigned char) * _tms_buffer_size); _tms_buffer = (unsigned char *)malloc(sizeof(unsigned char) * _tms_buffer_size);
bzero(_tms_buffer, _tms_buffer_size); bzero(_tms_buffer, _tms_buffer_size);
init(5, 0xfb, cable);
} }
int FtdiJtag::detectChain(vector<int> &devices, int max_dev) int Jtag::detectChain(vector<int> &devices, int max_dev)
{ {
unsigned char rx_buff[4]; unsigned char rx_buff[4];
/* WA for CH552/tangNano: write is always mandatory */ /* WA for CH552/tangNano: write is always mandatory */
@ -140,9 +121,9 @@ int FtdiJtag::detectChain(vector<int> &devices, int max_dev)
return devices.size(); return devices.size();
} }
void FtdiJtag::setTMS(unsigned char tms) void Jtag::setTMS(unsigned char tms)
{ {
display("%s %d %d\n", __func__, _num_tms, (_num_tms >> 3)); display("%s %x %d %d\n", __func__, tms, _num_tms, (_num_tms >> 3));
if (_num_tms+1 == _tms_buffer_size * 8) if (_num_tms+1 == _tms_buffer_size * 8)
flushTMS(); flushTMS();
if (tms != 0) if (tms != 0)
@ -158,38 +139,23 @@ void FtdiJtag::setTMS(unsigned char tms)
* -bit 7 is TDI state for each clk cycles * -bit 7 is TDI state for each clk cycles
*/ */
int FtdiJtag::flushTMS(bool flush_buffer) int Jtag::flushTMS(bool flush_buffer)
{ {
int xfer, pos = 0; if (_num_tms != 0) {
unsigned char buf[3]= {MPSSE_WRITE_TMS | MPSSE_LSB | MPSSE_BITMODE | display("%s: %d %x\n", __func__, _num_tms, _tms_buffer[0]);
MPSSE_WRITE_NEG, 0, 0};
if (_num_tms == 0) _jtag->storeTMS(_tms_buffer, _num_tms);
return 0;
display("%s: %d %x\n", __func__, _num_tms, _tms_buffer[0]); /* reset buffer and number of bits */
bzero(_tms_buffer, _tms_buffer_size);
while (_num_tms != 0) { _num_tms = 0;
xfer = (_num_tms > 6) ? 6 : _num_tms;
buf[1] = xfer - 1;
buf[2] = 0x80;
for (int i = 0; i < xfer; i++, pos++) {
buf[2] |=
(((_tms_buffer[pos >> 3] & (1 << (pos & 0x07))) ? 1 : 0) << i);
}
_num_tms -= xfer;
mpsse_store(buf, 3);
} }
/* reset buffer and number of bits */
bzero(_tms_buffer, _tms_buffer_size);
_num_tms = 0;
if (flush_buffer) if (flush_buffer)
return mpsse_write(); return _jtag->writeTMS(NULL);
return 0; return 0;
} }
void FtdiJtag::go_test_logic_reset() void Jtag::go_test_logic_reset()
{ {
/* idenpendly to current state 5 clk with TMS high is enough */ /* idenpendly to current state 5 clk with TMS high is enough */
for (int i = 0; i < 6; i++) for (int i = 0; i < 6; i++)
@ -201,44 +167,42 @@ void FtdiJtag::go_test_logic_reset()
/* GGM: faut tenir plus compte de la taille de la fifo interne /* 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 * du FT2232 pour maximiser l'envoi au lieu de faire de petits envoies
*/ */
int FtdiJtag::read_write(unsigned char *tdi, unsigned char *tdo, int len, char last) int Jtag::read_write(unsigned char *tdi, unsigned char *tdo, int len, char last)
{ {
/* 3 possible case : /* 3 possible case :
* - n * 8bits to send -> use byte command * - n * 8bits to send -> use byte command
* - less than 8bits -> use bit command * - less than 8bits -> use bit command
* - last bit to send -> sent in conjunction with TMS * - last bit to send -> sent in conjunction with TMS
*/ */
int tx_buff_size = mpsse_get_buffer_size(); 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 int real_len = (last) ? len - 1 : len; // if its a buffer in a big send send len
// else supress last bit -> with TMS // else supress last bit -> with TMS
int nb_byte = real_len >> 3; // number of byte to send int nb_byte = real_len >> 3; // number of byte to send
int nb_bit = (real_len & 0x07); // residual bits int nb_bit = (real_len & 0x07); // residual bits
int xfer = tx_buff_size - 3; int xfer = tx_buff_size;
unsigned char c[len];
unsigned char *rx_ptr = (unsigned char *)tdo; unsigned char *rx_ptr = (unsigned char *)tdo;
unsigned char *tx_ptr = (unsigned char *)tdi; unsigned char *tx_ptr = (unsigned char *)tdi;
unsigned char tx_buf[3] = {(unsigned char)(MPSSE_LSB | MPSSE_WRITE_NEG |
((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
flushTMS(true); flushTMS(true);
display("%s len : %d %d %d %d\n", __func__, len, real_len, nb_byte, display("%s len : %d %d %d %d %d\n", __func__, len, real_len, nb_byte,
nb_bit); nb_bit, tx_buff_size);
while (nb_byte > xfer) { while (nb_byte > xfer) {
mpsse_store(tx_buf, 3); display("%s %d %d\n", __func__, nb_byte, xfer);
if (tdi) {
mpsse_store(tx_ptr, 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; tx_ptr += xfer;
} if (tdo)
if (tdo) {
mpsse_read(rx_ptr, xfer);
rx_ptr += xfer; rx_ptr += xfer;
} else if (_ch552WA) {
ftdi_read_data(_ftdi, c, xfer);
}
nb_byte -= xfer; nb_byte -= xfer;
} }
@ -246,43 +210,40 @@ int FtdiJtag::read_write(unsigned char *tdi, unsigned char *tdo, int len, char l
/* 1/ send serie of byte */ /* 1/ send serie of byte */
if (nb_byte > 0) { if (nb_byte > 0) {
display("%s read/write %d byte\n", __func__, nb_byte); display("%s read/write %d byte\n", __func__, nb_byte);
tx_buf[1] = ((nb_byte - 1) & 0xff); // low if (nb_byte != _jtag->storeTDI(tx_ptr, nb_byte, tdo != NULL)) {
tx_buf[2] = (((nb_byte - 1) >> 8) & 0xff); // high printError("%s: Fail to store tdi\n", __func__);
mpsse_store(tx_buf, 3); return -1;
if (tdi) { }
mpsse_store(tx_ptr, nb_byte); 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; tx_ptr += nb_byte;
} if (tdo)
if (tdo) {
mpsse_read(rx_ptr, nb_byte);
rx_ptr += nb_byte; rx_ptr += nb_byte;
} else if (_ch552WA) {
ftdi_read_data(_ftdi, c, nb_byte);
}
} }
unsigned char last_bit = (tdi) ? *tx_ptr : 0; unsigned char last_bit = (tdi) ? *tx_ptr : 0;
if (nb_bit != 0) { if (nb_bit != 0) {
display("%s read/write %d bit\n", __func__, nb_bit); display("%s read/write %d bit\n", __func__, nb_bit);
tx_buf[0] |= MPSSE_BITMODE; if (nb_bit != _jtag->storeTDI(last_bit, nb_bit, tdo != NULL)) {
tx_buf[1] = nb_bit - 1; printError("%s: Fail to store tdi\n", __func__);
mpsse_store(tx_buf, 2); return -1;
if (tdi) {
display("%s last_bit %x size %d\n", __func__, last_bit, nb_bit-1);
mpsse_store(last_bit);
} }
mpsse_write(); if (0 > _jtag->writeTDI((tdo)?rx_ptr:NULL, nb_bit)) {
printError("%s: Write errror\n", __func__);
return -1;
}
if (tdo) { if (tdo) {
mpsse_read(rx_ptr, 1);
/* realign we have read nb_bit /* realign we have read nb_bit
* since LSB add bit by the left and shift * since LSB add bit by the left and shift
* we need to complete shift * we need to complete shift
*/ */
*rx_ptr >>= (8 - nb_bit); *rx_ptr >>= (8 - nb_bit);
display("%s %x\n", __func__, *rx_ptr); display("%s %x\n", __func__, *rx_ptr);
} else if (_ch552WA) {
ftdi_read_data(_ftdi, c, nb_bit);
} }
} }
@ -295,25 +256,18 @@ int FtdiJtag::read_write(unsigned char *tdi, unsigned char *tdo, int len, char l
} }
if (last == 1) { if (last == 1) {
uint8_t c;
last_bit = (tdi)? (*tx_ptr & (1 << nb_bit)) : 0; 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)); 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 | c=1;
((tdo) ? MPSSE_DO_READ : 0); _jtag->storeTMS(&c, 1, (last_bit)?1:0, tdo != NULL);
tx_buf[1] = 0x0 ; // send 1bit _jtag->writeTMS((tdo)?&c:NULL, 1);
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);
mpsse_write();
if (tdo) { if (tdo) {
unsigned char c;
mpsse_read(&c, 1);
/* in this case for 1 one it's always bit 7 */ /* in this case for 1 one it's always bit 7 */
*rx_ptr |= ((c & 0x80) << (7 - nb_bit)); *rx_ptr |= ((c & 0x80) << (7 - nb_bit));
display("%s %x\n", __func__, c); display("%s %x\n", __func__, c);
} else if (_ch552WA) {
ftdi_read_data(_ftdi, c, 1);
} }
_state = (_state == SHIFT_DR) ? EXIT1_DR : EXIT1_IR; _state = (_state == SHIFT_DR) ? EXIT1_DR : EXIT1_IR;
} }
@ -321,7 +275,7 @@ int FtdiJtag::read_write(unsigned char *tdi, unsigned char *tdo, int len, char l
return 0; return 0;
} }
void FtdiJtag::toggleClk(int nb) void Jtag::toggleClk(int nb)
{ {
unsigned char c = (TEST_LOGIC_RESET == _state) ? 1 : 0; unsigned char c = (TEST_LOGIC_RESET == _state) ? 1 : 0;
for (int i = 0; i < nb; i++) for (int i = 0; i < nb; i++)
@ -329,7 +283,7 @@ void FtdiJtag::toggleClk(int nb)
flushTMS(true); flushTMS(true);
} }
int FtdiJtag::shiftDR(unsigned char *tdi, unsigned char *tdo, int drlen, int end_state) int Jtag::shiftDR(unsigned char *tdi, unsigned char *tdo, int drlen, int end_state)
{ {
set_state(SHIFT_DR); set_state(SHIFT_DR);
// force transmit tms state // force transmit tms state
@ -341,7 +295,7 @@ int FtdiJtag::shiftDR(unsigned char *tdi, unsigned char *tdo, int drlen, int end
return 0; return 0;
} }
int FtdiJtag::shiftIR(unsigned char tdi, int irlen, int end_state) int Jtag::shiftIR(unsigned char tdi, int irlen, int end_state)
{ {
if (irlen > 8) { if (irlen > 8) {
cerr << "Error: this method this direct char don't support more than 1 byte" << endl; cerr << "Error: this method this direct char don't support more than 1 byte" << endl;
@ -350,7 +304,7 @@ int FtdiJtag::shiftIR(unsigned char tdi, int irlen, int end_state)
return shiftIR(&tdi, NULL, irlen, end_state); return shiftIR(&tdi, NULL, irlen, end_state);
} }
int FtdiJtag::shiftIR(unsigned char *tdi, unsigned char *tdo, int irlen, int end_state) int Jtag::shiftIR(unsigned char *tdi, unsigned char *tdo, int irlen, int end_state)
{ {
display("%s: avant shiftIR\n", __func__); display("%s: avant shiftIR\n", __func__);
set_state(SHIFT_IR); set_state(SHIFT_IR);
@ -358,13 +312,13 @@ int FtdiJtag::shiftIR(unsigned char *tdi, unsigned char *tdo, int irlen, int end
// currently don't care about multiple device in the chain // currently don't care about multiple device in the chain
display("%s: envoi ircode\n", __func__); display("%s: envoi ircode\n", __func__);
read_write(tdi, tdo, irlen, 1);// 1 since only one device read_write(tdi, tdo, irlen, 1); // 1 since only one device
set_state(end_state); set_state(end_state);
return 0; return 0;
} }
void FtdiJtag::set_state(int newState) void Jtag::set_state(int newState)
{ {
unsigned char tms; unsigned char tms;
while (newState != _state) { while (newState != _state) {
@ -548,13 +502,14 @@ void FtdiJtag::set_state(int newState)
} }
setTMS(tms); setTMS(tms);
display("%d %d %d %x\n", tms, _num_tms-1, _state, _tms_buffer[(_num_tms-1) / 8]); display("%d %d %d %x\n", tms, _num_tms-1, _state,
_tms_buffer[(_num_tms-1) / 8]);
} }
/* force write buffer */ /* force write buffer */
flushTMS(); flushTMS();
} }
const char *FtdiJtag::getStateName(tapState_t s) const char *Jtag::getStateName(tapState_t s)
{ {
switch (s) { switch (s) {
case TEST_LOGIC_RESET: case TEST_LOGIC_RESET:

93
src/jtag.hpp Normal file
View File

@ -0,0 +1,93 @@
/*
* Copyright (C) 2020 Gwenhael Goavec-Merou <gwenhael.goavec-merou@trabucayre.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef JTAG_H
#define JTAG_H
#include <ftdi.h>
#include <iostream>
#include <string>
#include <vector>
#include "ftdipp_mpsse.hpp"
#include "jtagInterface.hpp"
class Jtag {
public:
Jtag(FTDIpp_MPSSE::mpsse_bit_config &cable, std::string dev,
unsigned char interface, uint32_t clkHZ, bool verbose = false);
Jtag(FTDIpp_MPSSE::mpsse_bit_config &cable, unsigned char interface,
uint32_t clkHZ, bool verbose);
~Jtag();
/* maybe to update */
int setClkFreq(uint32_t clkHZ) { return _jtag->setClkFreq(clkHZ);}
int setClkFreq(uint32_t clkHZ, char use_divide_by_5) {
return _jtag->setClkFreq(clkHZ, use_divide_by_5);}
int detectChain(std::vector<int> &devices, int max_dev);
int shiftIR(unsigned char *tdi, unsigned char *tdo, int irlen,
int end_state = RUN_TEST_IDLE);
int shiftIR(unsigned char tdi, int irlen,
int end_state = RUN_TEST_IDLE);
int shiftDR(unsigned char *tdi, unsigned char *tdo, int drlen,
int end_state = RUN_TEST_IDLE);
int read_write(unsigned char *tdi, unsigned char *tdo, int len, char last);
void toggleClk(int nb);
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 setTMS(unsigned char tms);
enum tapState_t {
TEST_LOGIC_RESET = 0,
RUN_TEST_IDLE = 1,
SELECT_DR_SCAN = 2,
CAPTURE_DR = 3,
SHIFT_DR = 4,
EXIT1_DR = 5,
PAUSE_DR = 6,
EXIT2_DR = 7,
UPDATE_DR = 8,
SELECT_IR_SCAN = 9,
CAPTURE_IR = 10,
SHIFT_IR = 11,
EXIT1_IR = 12,
PAUSE_IR = 13,
EXIT2_IR = 14,
UPDATE_IR = 15,
UNKNOWN = 999
};
const char *getStateName(tapState_t s);
/* utilities */
void setVerbose(bool verbose){_verbose = verbose;}
private:
void init_internal(FTDIpp_MPSSE::mpsse_bit_config &cable,
unsigned char interface, uint32_t clkHZ);
bool _verbose;
int _state;
int _tms_buffer_size;
int _num_tms;
unsigned char *_tms_buffer;
std::string _board_name;
JtagInterface *_jtag;
};
#endif

View File

@ -24,7 +24,7 @@
#include <iostream> #include <iostream>
#include "ftdijtag.hpp" #include "jtag.hpp"
#include "lattice.hpp" #include "lattice.hpp"
#include "progressBar.hpp" #include "progressBar.hpp"
#include "display.hpp" #include "display.hpp"
@ -61,7 +61,7 @@ using namespace std;
# define REG_STATUS_CNF_CHK_MASK (0x7 << 23) # define REG_STATUS_CNF_CHK_MASK (0x7 << 23)
# define REG_STATUS_EXEC_ERR (1 << 26) # define REG_STATUS_EXEC_ERR (1 << 26)
Lattice::Lattice(FtdiJtag *jtag, const string filename, bool verbose): Lattice::Lattice(Jtag *jtag, const string filename, bool verbose):
Device(jtag, filename, verbose) Device(jtag, filename, verbose)
{ {
if (_filename != "") { if (_filename != "") {
@ -182,13 +182,13 @@ bool Lattice::program_mem()
/* LSC_INIT_ADDRESS */ /* LSC_INIT_ADDRESS */
wr_rd(0x46, NULL, 0, NULL, 0); wr_rd(0x46, NULL, 0, NULL, 0);
_jtag->set_state(FtdiJtag::RUN_TEST_IDLE); _jtag->set_state(Jtag::RUN_TEST_IDLE);
_jtag->toggleClk(1000); _jtag->toggleClk(1000);
uint8_t *data = _bit.getData(); uint8_t *data = _bit.getData();
int length = _bit.getLength()/8; int length = _bit.getLength()/8;
wr_rd(0x7A, NULL, 0, NULL, 0); wr_rd(0x7A, NULL, 0, NULL, 0);
_jtag->set_state(FtdiJtag::RUN_TEST_IDLE); _jtag->set_state(Jtag::RUN_TEST_IDLE);
_jtag->toggleClk(2); _jtag->toggleClk(2);
uint8_t tmp[1024]; uint8_t tmp[1024];
@ -205,10 +205,10 @@ bool Lattice::program_mem()
for (int ii = 0; ii < size; ii++) for (int ii = 0; ii < size; ii++)
tmp[ii] = ConfigBitstreamParser::reverseByte(data[i+ii]); tmp[ii] = ConfigBitstreamParser::reverseByte(data[i+ii]);
_jtag->shiftDR(tmp, NULL, size*8, FtdiJtag::SHIFT_DR); _jtag->shiftDR(tmp, NULL, size*8, Jtag::SHIFT_DR);
} }
_jtag->set_state(FtdiJtag::RUN_TEST_IDLE); _jtag->set_state(Jtag::RUN_TEST_IDLE);
if (checkStatus(0, REG_STATUS_CNF_CHK_MASK)) if (checkStatus(0, REG_STATUS_CNF_CHK_MASK))
progress.done(); progress.done();
@ -341,7 +341,7 @@ bool Lattice::program_flash()
/* LSC_INIT_ADDRESS */ /* LSC_INIT_ADDRESS */
wr_rd(0x46, NULL, 0, NULL, 0); wr_rd(0x46, NULL, 0, NULL, 0);
_jtag->set_state(FtdiJtag::RUN_TEST_IDLE); _jtag->set_state(Jtag::RUN_TEST_IDLE);
_jtag->toggleClk(1000); _jtag->toggleClk(1000);
/* flash UFM */ /* flash UFM */
@ -354,7 +354,7 @@ bool Lattice::program_flash()
/* LSC_INIT_ADDRESS */ /* LSC_INIT_ADDRESS */
wr_rd(0x46, NULL, 0, NULL, 0); wr_rd(0x46, NULL, 0, NULL, 0);
_jtag->set_state(FtdiJtag::RUN_TEST_IDLE); _jtag->set_state(Jtag::RUN_TEST_IDLE);
_jtag->toggleClk(1000); _jtag->toggleClk(1000);
if ((eraseMode & FLASH_ERASE_FEATURE) != 0) { if ((eraseMode & FLASH_ERASE_FEATURE) != 0) {
@ -425,7 +425,7 @@ bool Lattice::EnableISC(uint8_t flash_mode)
{ {
wr_rd(ISC_ENABLE, &flash_mode, 1, NULL, 0); wr_rd(ISC_ENABLE, &flash_mode, 1, NULL, 0);
_jtag->set_state(FtdiJtag::RUN_TEST_IDLE); _jtag->set_state(Jtag::RUN_TEST_IDLE);
_jtag->toggleClk(1000); _jtag->toggleClk(1000);
if (!pollBusyFlag()) if (!pollBusyFlag())
return false; return false;
@ -437,7 +437,7 @@ bool Lattice::EnableISC(uint8_t flash_mode)
bool Lattice::DisableISC() bool Lattice::DisableISC()
{ {
wr_rd(ISC_DISABLE, NULL, 0, NULL, 0); wr_rd(ISC_DISABLE, NULL, 0, NULL, 0);
_jtag->set_state(FtdiJtag::RUN_TEST_IDLE); _jtag->set_state(Jtag::RUN_TEST_IDLE);
_jtag->toggleClk(1000); _jtag->toggleClk(1000);
if (!pollBusyFlag()) if (!pollBusyFlag())
return false; return false;
@ -450,7 +450,7 @@ bool Lattice::EnableCfgIf()
{ {
uint8_t tx_buf = 0x08; uint8_t tx_buf = 0x08;
wr_rd(0x74, &tx_buf, 1, NULL, 0); wr_rd(0x74, &tx_buf, 1, NULL, 0);
_jtag->set_state(FtdiJtag::RUN_TEST_IDLE); _jtag->set_state(Jtag::RUN_TEST_IDLE);
_jtag->toggleClk(1000); _jtag->toggleClk(1000);
return pollBusyFlag(); return pollBusyFlag();
} }
@ -459,7 +459,7 @@ bool Lattice::DisableCfg()
{ {
uint8_t tx_buf, rx_buf; uint8_t tx_buf, rx_buf;
wr_rd(0x26, &tx_buf, 1, &rx_buf, 1); wr_rd(0x26, &tx_buf, 1, &rx_buf, 1);
_jtag->set_state(FtdiJtag::RUN_TEST_IDLE); _jtag->set_state(Jtag::RUN_TEST_IDLE);
_jtag->toggleClk(1000); _jtag->toggleClk(1000);
return true; return true;
} }
@ -490,7 +490,7 @@ bool Lattice::checkID()
printf("check ID\n"); printf("check ID\n");
uint8_t tx[4]; uint8_t tx[4];
wr_rd(0xE2, tx, 4, NULL, 0); wr_rd(0xE2, tx, 4, NULL, 0);
_jtag->set_state(FtdiJtag::RUN_TEST_IDLE); _jtag->set_state(Jtag::RUN_TEST_IDLE);
_jtag->toggleClk(1000); _jtag->toggleClk(1000);
uint32_t reg = readStatusReg(); uint32_t reg = readStatusReg();
@ -501,7 +501,7 @@ bool Lattice::checkID()
tx[1] = 0xd0; tx[1] = 0xd0;
tx[0] = 0x43; tx[0] = 0x43;
wr_rd(0xE2, tx, 4, NULL, 0); wr_rd(0xE2, tx, 4, NULL, 0);
_jtag->set_state(FtdiJtag::RUN_TEST_IDLE); _jtag->set_state(Jtag::RUN_TEST_IDLE);
_jtag->toggleClk(1000); _jtag->toggleClk(1000);
reg = readStatusReg(); reg = readStatusReg();
displayReadReg(reg); displayReadReg(reg);
@ -519,7 +519,7 @@ uint32_t Lattice::readStatusReg()
uint32_t reg; uint32_t reg;
uint8_t rx[4], tx[4]; uint8_t rx[4], tx[4];
wr_rd(0x3C, tx, 4, rx, 4); wr_rd(0x3C, tx, 4, rx, 4);
_jtag->set_state(FtdiJtag::RUN_TEST_IDLE); _jtag->set_state(Jtag::RUN_TEST_IDLE);
_jtag->toggleClk(1000); _jtag->toggleClk(1000);
reg = rx[3] << 24 | rx[2] << 16 | rx[1] << 8 | rx[0]; reg = rx[3] << 24 | rx[2] << 16 | rx[1] << 8 | rx[0];
return reg; return reg;
@ -543,10 +543,10 @@ bool Lattice::wr_rd(uint8_t cmd,
xfer_tx[i] = tx[i]; xfer_tx[i] = tx[i];
} }
_jtag->shiftIR(&cmd, NULL, 8, FtdiJtag::PAUSE_IR); _jtag->shiftIR(&cmd, NULL, 8, Jtag::PAUSE_IR);
if (rx || tx) { if (rx || tx) {
_jtag->shiftDR(xfer_tx, (rx) ? xfer_rx : NULL, 8 * xfer_len, _jtag->shiftDR(xfer_tx, (rx) ? xfer_rx : NULL, 8 * xfer_len,
FtdiJtag::PAUSE_DR); Jtag::PAUSE_DR);
} }
if (rx) { if (rx) {
if (verbose) { if (verbose) {
@ -652,7 +652,7 @@ bool Lattice::pollBusyFlag(bool verbose)
int timeout = 0; int timeout = 0;
do { do {
wr_rd(CHECK_BUSY_FLAG, NULL, 0, &rx, 1); wr_rd(CHECK_BUSY_FLAG, NULL, 0, &rx, 1);
_jtag->set_state(FtdiJtag::RUN_TEST_IDLE); _jtag->set_state(Jtag::RUN_TEST_IDLE);
_jtag->toggleClk(1000); _jtag->toggleClk(1000);
if (verbose) if (verbose)
printf("pollBusyFlag :%02x\n", rx); printf("pollBusyFlag :%02x\n", rx);
@ -676,7 +676,7 @@ bool Lattice::flashErase(uint8_t mask)
{ {
uint8_t tx[1] = {mask}; uint8_t tx[1] = {mask};
wr_rd(FLASH_ERASE, tx, 1, NULL, 0); wr_rd(FLASH_ERASE, tx, 1, NULL, 0);
_jtag->set_state(FtdiJtag::RUN_TEST_IDLE); _jtag->set_state(Jtag::RUN_TEST_IDLE);
_jtag->toggleClk(1000); _jtag->toggleClk(1000);
if (!pollBusyFlag()) if (!pollBusyFlag())
return false; return false;
@ -692,7 +692,7 @@ bool Lattice::flashProg(uint32_t start_addr, std::vector<std::string> data)
for (uint32_t line = 0; line < data.size(); line++) { for (uint32_t line = 0; line < data.size(); line++) {
wr_rd(PROG_CFG_FLASH, (uint8_t *)data[line].c_str(), wr_rd(PROG_CFG_FLASH, (uint8_t *)data[line].c_str(),
16, NULL, 0); 16, NULL, 0);
_jtag->set_state(FtdiJtag::RUN_TEST_IDLE); _jtag->set_state(Jtag::RUN_TEST_IDLE);
_jtag->toggleClk(1000); _jtag->toggleClk(1000);
progress.display(line); progress.display(line);
if (pollBusyFlag() == false) if (pollBusyFlag() == false)
@ -709,20 +709,20 @@ bool Lattice::Verify(JedParser &_jed, bool unlock)
EnableISC(0x08); EnableISC(0x08);
wr_rd(0x46, NULL, 0, NULL, 0); wr_rd(0x46, NULL, 0, NULL, 0);
_jtag->set_state(FtdiJtag::RUN_TEST_IDLE); _jtag->set_state(Jtag::RUN_TEST_IDLE);
_jtag->toggleClk(1000); _jtag->toggleClk(1000);
tx_buf[0] = 0x73; tx_buf[0] = 0x73;
_jtag->shiftIR(tx_buf, NULL, 8, FtdiJtag::PAUSE_IR); _jtag->shiftIR(tx_buf, NULL, 8, Jtag::PAUSE_IR);
bzero(tx_buf, 16); bzero(tx_buf, 16);
bool failure = false; bool failure = false;
vector<string> data = _jed.data_for_section(0); vector<string> data = _jed.data_for_section(0);
ProgressBar progress("Verifying", data.size(), 50); ProgressBar progress("Verifying", data.size(), 50);
for (size_t line = 0; line< data.size(); line++) { for (size_t line = 0; line< data.size(); line++) {
_jtag->set_state(FtdiJtag::RUN_TEST_IDLE); _jtag->set_state(Jtag::RUN_TEST_IDLE);
_jtag->toggleClk(2); _jtag->toggleClk(2);
_jtag->shiftDR(tx_buf, rx_buf, 16*8, FtdiJtag::PAUSE_DR); _jtag->shiftDR(tx_buf, rx_buf, 16*8, Jtag::PAUSE_DR);
for (size_t i = 0; i < data[i].size(); i++) { for (size_t i = 0; i < data[i].size(); i++) {
if (rx_buf[i] != (unsigned char)data[line][i]) { if (rx_buf[i] != (unsigned char)data[line][i]) {
printf("%3ld %3ld %02x -> %02x\n", line, i, printf("%3ld %3ld %02x -> %02x\n", line, i,
@ -760,7 +760,7 @@ uint16_t Lattice::readFeabits()
{ {
uint8_t rx_buf[2]; uint8_t rx_buf[2];
wr_rd(READ_FEABITS, NULL, 0, rx_buf, 2); wr_rd(READ_FEABITS, NULL, 0, rx_buf, 2);
_jtag->set_state(FtdiJtag::RUN_TEST_IDLE); _jtag->set_state(Jtag::RUN_TEST_IDLE);
_jtag->toggleClk(1000); _jtag->toggleClk(1000);
return rx_buf[0] | (((uint16_t)rx_buf[1]) << 8); return rx_buf[0] | (((uint16_t)rx_buf[1]) << 8);
@ -772,7 +772,7 @@ bool Lattice::writeFeaturesRow(uint64_t features, bool verify)
for (int i=0; i < 8; i++) for (int i=0; i < 8; i++)
tx_buf[i] = ((features >> (i*8)) & 0x00ff); tx_buf[i] = ((features >> (i*8)) & 0x00ff);
wr_rd(PROG_FEATURE_ROW, tx_buf, 8, NULL, 0); wr_rd(PROG_FEATURE_ROW, tx_buf, 8, NULL, 0);
_jtag->set_state(FtdiJtag::RUN_TEST_IDLE); _jtag->set_state(Jtag::RUN_TEST_IDLE);
_jtag->toggleClk(1000); _jtag->toggleClk(1000);
if (!pollBusyFlag()) if (!pollBusyFlag())
return false; return false;
@ -787,7 +787,7 @@ bool Lattice::writeFeabits(uint16_t feabits, bool verify)
(uint8_t)(0x00ff & (feabits>>8))}; (uint8_t)(0x00ff & (feabits>>8))};
wr_rd(PROG_FEABITS, tx_buf, 2, NULL, 0); wr_rd(PROG_FEABITS, tx_buf, 2, NULL, 0);
_jtag->set_state(FtdiJtag::RUN_TEST_IDLE); _jtag->set_state(Jtag::RUN_TEST_IDLE);
_jtag->toggleClk(1000); _jtag->toggleClk(1000);
if (!pollBusyFlag()) if (!pollBusyFlag())
return false; return false;
@ -799,7 +799,7 @@ bool Lattice::writeFeabits(uint16_t feabits, bool verify)
bool Lattice::writeProgramDone() bool Lattice::writeProgramDone()
{ {
wr_rd(PROG_DONE, NULL, 0, NULL, 0); wr_rd(PROG_DONE, NULL, 0, NULL, 0);
_jtag->set_state(FtdiJtag::RUN_TEST_IDLE); _jtag->set_state(Jtag::RUN_TEST_IDLE);
_jtag->toggleClk(1000); _jtag->toggleClk(1000);
if (!pollBusyFlag()) if (!pollBusyFlag())
return false; return false;
@ -811,7 +811,7 @@ bool Lattice::writeProgramDone()
bool Lattice::loadConfiguration() bool Lattice::loadConfiguration()
{ {
wr_rd(REFRESH, NULL, 0, NULL, 0); wr_rd(REFRESH, NULL, 0, NULL, 0);
_jtag->set_state(FtdiJtag::RUN_TEST_IDLE); _jtag->set_state(Jtag::RUN_TEST_IDLE);
_jtag->toggleClk(1000); _jtag->toggleClk(1000);
if (!pollBusyFlag()) if (!pollBusyFlag())
return false; return false;

View File

@ -23,14 +23,14 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include "ftdijtag.hpp" #include "jtag.hpp"
#include "device.hpp" #include "device.hpp"
#include "jedParser.hpp" #include "jedParser.hpp"
#include "latticeBitParser.hpp" #include "latticeBitParser.hpp"
class Lattice: public Device { class Lattice: public Device {
public: public:
Lattice(FtdiJtag *jtag, std::string filename, bool verbose); Lattice(Jtag *jtag, std::string filename, bool verbose);
int idCode() override; int idCode() override;
int userCode(); int userCode();
void reset() override {} void reset() override {}

View File

@ -31,7 +31,7 @@
#include "display.hpp" #include "display.hpp"
#include "gowin.hpp" #include "gowin.hpp"
#include "lattice.hpp" #include "lattice.hpp"
#include "ftdijtag.hpp" #include "jtag.hpp"
#include "part.hpp" #include "part.hpp"
#include "xilinx.hpp" #include "xilinx.hpp"
@ -122,11 +122,11 @@ int main(int argc, char **argv)
cable = select_cable->second; cable = select_cable->second;
/* jtag base */ /* jtag base */
FtdiJtag *jtag; Jtag *jtag;
if (args.device == "-") if (args.device == "-")
jtag = new FtdiJtag(cable, 1, 6000000, false); jtag = new Jtag(cable, 1, 6000000, false);
else else
jtag = new FtdiJtag(cable, args.device, 1, 6000000, false); jtag = new Jtag(cable, args.device, 1, 6000000, false);
/* chain detection */ /* chain detection */
vector<int> listDev; vector<int> listDev;

View File

@ -20,7 +20,7 @@
#include <unistd.h> #include <unistd.h>
#include <iostream> #include <iostream>
#include "ftdijtag.hpp" #include "jtag.hpp"
#include "ftdipp_mpsse.hpp" #include "ftdipp_mpsse.hpp"
#include "progressBar.hpp" #include "progressBar.hpp"
#include "spiFlash.hpp" #include "spiFlash.hpp"
@ -72,7 +72,7 @@ static uint8_t reverseByte(uint8_t src)
#define FLASH_WRVECR 0x61 #define FLASH_WRVECR 0x61
#define FLASH_RDVECR 0x65 #define FLASH_RDVECR 0x65
SPIFlash::SPIFlash(FtdiJtag *jtag, bool verbose):_jtag(jtag), _verbose(verbose) SPIFlash::SPIFlash(Jtag *jtag, bool verbose):_jtag(jtag), _verbose(verbose)
{ {
} }
@ -116,8 +116,8 @@ int SPIFlash::wait(uint8_t mask, uint8_t cond, uint32_t timeout, bool verbose)
uint8_t tx = reverseByte(FLASH_RDSR); uint8_t tx = reverseByte(FLASH_RDSR);
uint32_t count = 0; uint32_t count = 0;
_jtag->shiftIR(USER1, 6, FtdiJtag::UPDATE_IR); _jtag->shiftIR(USER1, 6, Jtag::UPDATE_IR);
_jtag->set_state(FtdiJtag::SHIFT_DR); _jtag->set_state(Jtag::SHIFT_DR);
_jtag->read_write(&tx, NULL, 8, 0); _jtag->read_write(&tx, NULL, 8, 0);
do { do {

View File

@ -18,11 +18,11 @@
#ifndef SPIFLASH_HPP #ifndef SPIFLASH_HPP
#define SPIFLASH_HPP #define SPIFLASH_HPP
#include "ftdijtag.hpp" #include "jtag.hpp"
class SPIFlash { class SPIFlash {
public: public:
SPIFlash(FtdiJtag *jtag, bool verbose); SPIFlash(Jtag *jtag, bool verbose);
/* power */ /* power */
void power_up(); void power_up();
void power_down(); void power_down();
@ -46,7 +46,7 @@ class SPIFlash {
void jtag_write_read(uint8_t cmd, uint8_t *tx, uint8_t *rx, uint16_t len = 0); void jtag_write_read(uint8_t cmd, uint8_t *tx, uint8_t *rx, uint16_t len = 0);
int wait(uint8_t mask, uint8_t cond, uint32_t timeout, bool verbose=false); int wait(uint8_t mask, uint8_t cond, uint32_t timeout, bool verbose=false);
FtdiJtag *_jtag; Jtag *_jtag;
bool _verbose; bool _verbose;
}; };

View File

@ -4,7 +4,7 @@
#include <map> #include <map>
#include <vector> #include <vector>
#include "ftdijtag.hpp" #include "jtag.hpp"
#include "svf_jtag.hpp" #include "svf_jtag.hpp"
@ -231,7 +231,7 @@ void SVF_jtag::handle_instruction(vector<string> const &vstr)
} }
} }
SVF_jtag::SVF_jtag(FtdiJtag *jtag, bool verbose):_verbose(verbose), _freq_hz(0), SVF_jtag::SVF_jtag(Jtag *jtag, bool verbose):_verbose(verbose), _freq_hz(0),
_enddr(fsm_state["IDLE"]), _endir(fsm_state["IDLE"]), _enddr(fsm_state["IDLE"]), _endir(fsm_state["IDLE"]),
_run_state(fsm_state["IDLE"]), _end_state(fsm_state["IDLE"]) _run_state(fsm_state["IDLE"]), _end_state(fsm_state["IDLE"])

View File

@ -3,11 +3,13 @@
#include <iostream> #include <iostream>
#include <vector> #include <vector>
#include <map> #include <map>
#include "jtag.hpp"
using namespace std; using namespace std;
class SVF_jtag { class SVF_jtag {
public: public:
SVF_jtag(FtdiJtag *jtag, bool verbose); SVF_jtag(Jtag *jtag, bool verbose);
~SVF_jtag(); ~SVF_jtag();
void parse(string filename); void parse(string filename);
void setVerbose(bool verbose) {_verbose = verbose;} void setVerbose(bool verbose) {_verbose = verbose;}
@ -46,7 +48,7 @@ class SVF_jtag {
{"IRUPDATE", 15} {"IRUPDATE", 15}
}; };
FtdiJtag *_jtag; Jtag *_jtag;
bool _verbose; bool _verbose;
uint32_t _freq_hz; uint32_t _freq_hz;

View File

@ -1,7 +1,7 @@
#include <iostream> #include <iostream>
#include <stdexcept> #include <stdexcept>
#include "ftdijtag.hpp" #include "jtag.hpp"
#include "bitparser.hpp" #include "bitparser.hpp"
#include "mcsParser.hpp" #include "mcsParser.hpp"
#include "spiFlash.hpp" #include "spiFlash.hpp"
@ -10,7 +10,7 @@
#include "part.hpp" #include "part.hpp"
#include "progressBar.hpp" #include "progressBar.hpp"
Xilinx::Xilinx(FtdiJtag *jtag, std::string filename, bool verbose): Xilinx::Xilinx(Jtag *jtag, std::string filename, bool verbose):
Device(jtag, filename, verbose) Device(jtag, filename, verbose)
{ {
if (_filename != ""){ if (_filename != ""){
@ -36,23 +36,24 @@ void Xilinx::reset()
{ {
_jtag->shiftIR(JSHUTDOWN, 6); _jtag->shiftIR(JSHUTDOWN, 6);
_jtag->shiftIR(JPROGRAM, 6); _jtag->shiftIR(JPROGRAM, 6);
_jtag->set_state(FtdiJtag::RUN_TEST_IDLE); _jtag->set_state(Jtag::RUN_TEST_IDLE);
_jtag->toggleClk(10000*12); _jtag->toggleClk(10000*12);
_jtag->set_state(FtdiJtag::RUN_TEST_IDLE); _jtag->set_state(Jtag::RUN_TEST_IDLE);
_jtag->toggleClk(2000); _jtag->toggleClk(2000);
_jtag->shiftIR(BYPASS, 6); _jtag->shiftIR(BYPASS, 6);
_jtag->set_state(FtdiJtag::RUN_TEST_IDLE); _jtag->set_state(Jtag::RUN_TEST_IDLE);
_jtag->toggleClk(2000); _jtag->toggleClk(2000);
} }
int Xilinx::idCode() int Xilinx::idCode()
{ {
unsigned char tx_data[4]= {0x00, 0x00, 0x00, 0x00};
unsigned char rx_data[4]; unsigned char rx_data[4];
_jtag->go_test_logic_reset(); _jtag->go_test_logic_reset();
_jtag->shiftIR(IDCODE, 6); _jtag->shiftIR(IDCODE, 6);
_jtag->shiftDR(NULL, rx_data, 32); _jtag->shiftDR(tx_data, rx_data, 32);
return ((rx_data[0] & 0x000000ff) | return ((rx_data[0] & 0x000000ff) |
((rx_data[1] << 8) & 0x0000ff00) | ((rx_data[1] << 8) & 0x0000ff00) |
((rx_data[2] << 16) & 0x00ff0000) | ((rx_data[2] << 16) & 0x00ff0000) |
@ -128,7 +129,7 @@ void Xilinx::program_mem(BitParser &bitfile)
/* /*
* 8: Move into the RTI state. X 0 10,000(1) * 8: Move into the RTI state. X 0 10,000(1)
*/ */
_jtag->set_state(FtdiJtag::RUN_TEST_IDLE); _jtag->set_state(Jtag::RUN_TEST_IDLE);
_jtag->toggleClk(10000*12); _jtag->toggleClk(10000*12);
/* /*
* 9: Start loading the CFG_IN instruction, * 9: Start loading the CFG_IN instruction,
@ -141,11 +142,11 @@ void Xilinx::program_mem(BitParser &bitfile)
/* /*
* 11: Enter the SELECT-DR state. X 1 2 * 11: Enter the SELECT-DR state. X 1 2
*/ */
_jtag->set_state(FtdiJtag::SELECT_DR_SCAN); _jtag->set_state(Jtag::SELECT_DR_SCAN);
/* /*
* 12: Enter the SHIFT-DR state. X 0 2 * 12: Enter the SHIFT-DR state. X 0 2
*/ */
_jtag->set_state(FtdiJtag::SHIFT_DR); _jtag->set_state(Jtag::SHIFT_DR);
/* /*
* 13: Shift in the FPGA bitstream. Bitn (MSB) * 13: Shift in the FPGA bitstream. Bitn (MSB)
* is the first bit in the bitstream(2). bit1...bitn 0 (bits in bitstream)-1 * is the first bit in the bitstream(2). bit1...bitn 0 (bits in bitstream)-1
@ -177,11 +178,11 @@ void Xilinx::program_mem(BitParser &bitfile)
/* /*
* 15: Enter UPDATE-DR state. X 1 1 * 15: Enter UPDATE-DR state. X 1 1
*/ */
_jtag->set_state(FtdiJtag::UPDATE_DR); _jtag->set_state(Jtag::UPDATE_DR);
/* /*
* 16: Move into RTI state. X 0 1 * 16: Move into RTI state. X 0 1
*/ */
_jtag->set_state(FtdiJtag::RUN_TEST_IDLE); _jtag->set_state(Jtag::RUN_TEST_IDLE);
/* /*
* 17: Enter the SELECT-IR state. X 1 2 * 17: Enter the SELECT-IR state. X 1 2
* 18: Move to the SHIFT-IR state. X 0 2 * 18: Move to the SHIFT-IR state. X 0 2
@ -191,13 +192,13 @@ void Xilinx::program_mem(BitParser &bitfile)
* 20: Load the last bit of the JSTART instruction. 0 1 1 * 20: Load the last bit of the JSTART instruction. 0 1 1
* 21: Move to the UPDATE-IR state. X 1 1 * 21: Move to the UPDATE-IR state. X 1 1
*/ */
_jtag->shiftIR(JSTART, 6, FtdiJtag::UPDATE_IR); _jtag->shiftIR(JSTART, 6, Jtag::UPDATE_IR);
/* /*
* 22: Move to the RTI state and clock the * 22: Move to the RTI state and clock the
* startup sequence by applying a minimum X 0 2000 * startup sequence by applying a minimum X 0 2000
* of 2000 clock cycles to the TCK. * of 2000 clock cycles to the TCK.
*/ */
_jtag->set_state(FtdiJtag::RUN_TEST_IDLE); _jtag->set_state(Jtag::RUN_TEST_IDLE);
_jtag->toggleClk(2000); _jtag->toggleClk(2000);
/* /*
* 23: Move to the TLR state. The device is * 23: Move to the TLR state. The device is

View File

@ -3,11 +3,11 @@
#include "bitparser.hpp" #include "bitparser.hpp"
#include "device.hpp" #include "device.hpp"
#include "ftdijtag.hpp" #include "jtag.hpp"
class Xilinx: public Device { class Xilinx: public Device {
public: public:
Xilinx(FtdiJtag *jtag, std::string filename, bool verbose); Xilinx(Jtag *jtag, std::string filename, bool verbose);
~Xilinx(); ~Xilinx();
void program(unsigned int offset = 0) override; void program(unsigned int offset = 0) override;