Compare commits

...

2 Commits

Author SHA1 Message Date
Gwenhael Goavec-Merou 3cf558ebe2 colognechip: added a workaround to drive reset pin with DirtyJTAG cable
(requires a recent DirtyJTAG firmware)
2025-03-07 07:19:39 +01:00
Gwenhael Goavec-Merou 3c7324d14d dirtyJtag: added SRST/TRST values. Added method to read/set GPIOs level 2025-03-07 07:19:14 +01:00
4 changed files with 119 additions and 39 deletions

View File

@ -46,6 +46,12 @@ CologneChip::CologneChip(Jtag* jtag, const std::string &filename,
ftdi_board_name = std::regex_replace(board_name, std::regex("jtag"), "spi");
} else if (cable_name == "gatemate_pgm") {
ftdi_board_name = "gatemate_pgm_spi";
} else if (cable_name == "dirtyJtag") {
_dirtyjtag = reinterpret_cast<DirtyJtag *>(_jtag->_jtag);
_rstn_pin = (1 << 6);
_done_pin = 0;
_fail_pin = 0;
_oen_pin = 0;
}
if (ftdi_board_name != "") {
@ -84,6 +90,10 @@ void CologneChip::reset()
_ftdi_jtag->gpio_clear(_rstn_pin | _oen_pin);
usleep(SLEEP_US);
_ftdi_jtag->gpio_set(_rstn_pin);
} else if (_dirtyjtag) {
_dirtyjtag->gpio_clear(_rstn_pin);
_dirtyjtag->gpio_set(_rstn_pin);
usleep(SLEEP_US);
}
}
@ -123,10 +133,7 @@ void CologneChip::waitCfgDone()
}
}
/**
* Dump flash contents to file. Works in both SPI and JTAG-SPI-bypass mode.
*/
bool CologneChip::detect_flash()
bool CologneChip::prepare_flash_access()
{
if (_spi) {
/* enable output and hold reset */
@ -135,22 +142,17 @@ bool CologneChip::detect_flash()
/* enable output and disable reset */
_ftdi_jtag->gpio_clear(_oen_pin);
_ftdi_jtag->gpio_set(_rstn_pin);
} else if (_dirtyjtag) {
_dirtyjtag->gpio_clear(_rstn_pin);
_dirtyjtag->gpio_set(_rstn_pin);
usleep(SLEEP_US);
}
/* prepare SPI access */
printInfo("Read Flash ", false);
try {
std::unique_ptr<SPIFlash> flash(_spi ?
new SPIFlash(reinterpret_cast<SPIInterface *>(_spi), false, _verbose):
new SPIFlash(this, false, _verbose));
flash->read_id();
flash->display_status_reg();
} catch (std::exception &e) {
printError("Fail");
printError(std::string(e.what()));
return false;
}
return true;
}
bool CologneChip::post_flash_access()
{
if (_spi) {
/* disable output and release reset */
_spi->gpio_set(_rstn_pin | _oen_pin);
@ -166,18 +168,35 @@ bool CologneChip::detect_flash()
/**
* Dump flash contents to file. Works in both SPI and JTAG-SPI-bypass mode.
*/
bool CologneChip::dumpFlash(uint32_t base_addr, uint32_t len)
bool CologneChip::detect_flash()
{
if (_spi) {
/* enable output and hold reset */
_spi->gpio_clear(_rstn_pin | _oen_pin);
} else if (_ftdi_jtag) {
/* enable output and disable reset */
_ftdi_jtag->gpio_clear(_oen_pin);
_ftdi_jtag->gpio_set(_rstn_pin);
/* prepare SPI access */
prepare_flash_access();
printInfo("Read Flash ", false);
try {
std::unique_ptr<SPIFlash> flash(_spi ?
new SPIFlash(reinterpret_cast<SPIInterface *>(_spi), false, _verbose):
new SPIFlash(this, false, _verbose));
flash->read_id();
flash->display_status_reg();
} catch (std::exception &e) {
printError("Fail");
printError(std::string(e.what()));
return false;
}
return post_flash_access();
}
/**
* Dump flash contents to file. Works in both SPI and JTAG-SPI-bypass mode.
*/
bool CologneChip::dumpFlash(uint32_t base_addr, uint32_t len)
{
/* prepare SPI access */
prepare_flash_access();
printInfo("Read Flash ", false);
try {
std::unique_ptr<SPIFlash> flash(_spi ?
@ -190,16 +209,7 @@ bool CologneChip::dumpFlash(uint32_t base_addr, uint32_t len)
return false;
}
if (_spi) {
/* disable output and release reset */
_spi->gpio_set(_rstn_pin | _oen_pin);
} else if (_ftdi_jtag) {
/* disable output */
_ftdi_jtag->gpio_set(_oen_pin);
}
usleep(SLEEP_US);
return true;
return post_flash_access();
}
/**

View File

@ -12,6 +12,7 @@
#include <string>
#include "device.hpp"
#include "dirtyJtag.hpp"
#include "jtag.hpp"
#include "ftdispi.hpp"
#include "ftdiJtagMPSSE.hpp"
@ -48,6 +49,10 @@ class CologneChip: public Device, SPIInterface {
uint32_t idCode() override {return 0;}
void reset() override;
protected:
bool prepare_flash_access() override;
bool post_flash_access() override;
private:
void programSPI_sram(const uint8_t *data, int length);
void programSPI_flash(unsigned int offset, const uint8_t *data, int length,
@ -65,6 +70,7 @@ class CologneChip: public Device, SPIInterface {
FtdiSpi *_spi = NULL;
FtdiJtagMPSSE *_ftdi_jtag = NULL;
DirtyJtag *_dirtyjtag = NULL;
uint16_t _rstn_pin;
uint16_t _done_pin;
uint16_t _fail_pin;

View File

@ -54,10 +54,12 @@ static version_specific v_options[4] ={{0, 240}, {0, 240}, {NO_READ, 496},
enum dirtyJtagSig {
SIG_TCK = (1 << 1),
SIG_TDI = (1 << 2),
SIG_TDO = (1 << 3),
SIG_TMS = (1 << 4)
SIG_TCK = (1 << 1),
SIG_TDI = (1 << 2),
SIG_TDO = (1 << 3),
SIG_TMS = (1 << 4),
SIG_TRST = (1 << 5),
SIG_SRST = (1 << 6)
};
DirtyJtag::DirtyJtag(uint32_t clkHZ, int8_t verbose):
@ -384,3 +386,56 @@ int DirtyJtag::writeTDI(const uint8_t *tx, uint8_t *rx, uint32_t len, bool end)
}
return EXIT_SUCCESS;
}
/* GPIOs */
/* Read GPIOs */
uint8_t DirtyJtag::gpio_get()
{
int actual_length;
uint8_t sig;
uint8_t buf[] = {CMD_GETSIG, CMD_STOP};
if (libusb_bulk_transfer(dev_handle, DIRTYJTAG_WRITE_EP, buf, sizeof(buf),
&actual_length, DIRTYJTAG_TIMEOUT) < 0) {
printError("writeTDI: last bit error: usb bulk write failed 1");
return -EXIT_FAILURE;
}
do {
if (libusb_bulk_transfer(dev_handle, DIRTYJTAG_READ_EP, &sig, 1,
&actual_length, DIRTYJTAG_TIMEOUT) < 0) {
printError("writeTDI: last bit error: usb bulk read failed");
return -EXIT_FAILURE;
}
} while (actual_length == 0);
return sig;
}
bool DirtyJtag::_set_gpio_level(uint8_t gpio, uint8_t val)
{
int actual_length;
uint8_t buf[] = {
CMD_SETSIG,
static_cast<uint8_t>(gpio), // mask
static_cast<uint8_t>(val), // bit set
CMD_STOP,
};
if (libusb_bulk_transfer(dev_handle, DIRTYJTAG_WRITE_EP, buf, 4,
&actual_length, DIRTYJTAG_TIMEOUT) < 0) {
printError("GPIO set: usb bulk write failed 1");
return false;
}
return true;
}
/* update selected gpio */
bool DirtyJtag::gpio_set(uint8_t gpio)
{
return _set_gpio_level(gpio, gpio);
}
bool DirtyJtag::gpio_clear(uint8_t gpio)
{
return _set_gpio_level(gpio, 0);
}

View File

@ -42,12 +42,21 @@ class DirtyJtag : public JtagInterface {
int flush() override;
/* access gpio */
/* read gpio */
uint8_t gpio_get();
/* update selected gpio */
bool gpio_set(uint8_t gpio);
bool gpio_clear(uint8_t gpio);
private:
int8_t _verbose;
int sendBitBang(uint8_t mask, uint8_t val, uint8_t *read, bool last);
bool getVersion();
bool _set_gpio_level(uint8_t gpio, uint8_t val);
libusb_device_handle *dev_handle;
libusb_context *usb_ctx;
uint8_t _tdi;