Add workaround for slow JTAG on Sipeed Console

Signed-off-by: gatecat <gatecat@ds0.me>
This commit is contained in:
gatecat 2026-02-08 10:55:22 +01:00 committed by Gwenhael Goavec-Merou
parent 3cfa6afcab
commit a300f9d36a
2 changed files with 25 additions and 2 deletions

View File

@ -80,6 +80,13 @@ void FtdiJtagMPSSE::init_internal(const mpsse_bit_config &cable)
_cmd8EWA = true;
}
// This Sipeed firmware is incredibly slow in LSB first mode
if ( (!strncmp((const char *)_imanufacturer, "SIPEED", 6))
&& (!strncmp((const char *)_iserialnumber, "2025041420", 10)) ) {
_msb_first = true;
}
display("%x\n", cable.bit_low_val);
display("%x\n", cable.bit_low_dir);
display("%x\n", cable.bit_high_val);
@ -219,6 +226,13 @@ int FtdiJtagMPSSE::flush()
return mpsse_write();
}
static unsigned char bit_reverse(unsigned char b) {
b = (b & 0xF0) >> 4 | (b & 0x0F) << 4;
b = (b & 0xCC) >> 2 | (b & 0x33) << 2;
b = (b & 0xAA) >> 1 | (b & 0x55) << 1;
return b;
}
int FtdiJtagMPSSE::writeTDI(const uint8_t *tdi, uint8_t *tdo, uint32_t len, bool last)
{
/* 3 possible case :
@ -233,9 +247,11 @@ int FtdiJtagMPSSE::writeTDI(const uint8_t *tdi, uint8_t *tdo, uint32_t len, bool
int nb_bit = (real_len & 0x07); // residual bits
int xfer = tx_buff_size - 3;
unsigned char c[xfer];
unsigned char rev[xfer];
unsigned char *rx_ptr = (unsigned char *)tdo;
unsigned char *tx_ptr = (unsigned char *)tdi;
unsigned char tx_buf[3] = {(unsigned char)(MPSSE_LSB |
bool use_msb_first = _msb_first && !tdo;
unsigned char tx_buf[3] = {(unsigned char)(((use_msb_first) ? 0 : MPSSE_LSB) |
((tdi) ? (MPSSE_DO_WRITE | _write_mode) : 0) |
((tdo) ? (MPSSE_DO_READ | _read_mode) : 0)),
static_cast<unsigned char>((xfer - 1) & 0xff), // low
@ -266,7 +282,12 @@ int FtdiJtagMPSSE::writeTDI(const uint8_t *tdi, uint8_t *tdo, uint32_t len, bool
tx_buf[2] = (((xfer_len - 1) >> 8) & 0xff); // high
mpsse_store(tx_buf, 3);
if (tdi) {
mpsse_store(tx_ptr, xfer_len);
if (use_msb_first) {
for (int i = 0; i < xfer_len; i++) {
rev[i] = bit_reverse(tx_ptr[i]);
}
}
mpsse_store(use_msb_first ? rev : tx_ptr, xfer_len);
tx_ptr += xfer_len;
}
if (tdo) {
@ -288,6 +309,7 @@ int FtdiJtagMPSSE::writeTDI(const uint8_t *tdi, uint8_t *tdo, uint32_t len, bool
if (nb_bit != 0) {
display("%s read/write %d bit\n", __func__, nb_bit);
tx_buf[0] |= MPSSE_BITMODE;
tx_buf[0] |= MPSSE_LSB;
tx_buf[1] = nb_bit - 1;
mpsse_store(tx_buf, 2);
if (tdi) {

View File

@ -113,6 +113,7 @@ class FtdiJtagMPSSE : public JtagInterface, public FTDIpp_MPSSE {
uint8_t _write_mode; /**< write edge configuration */
uint8_t _read_mode; /**< read edge configuration */
bool _invert_read_edge; /**< read edge selection (false: pos, true: neg) */
bool _msb_first; /**< use MSB first, workaround for sipeed console */
/* writeTMSTDI specifics */
uint32_t _tdo_pos;
uint8_t _curr_tdi;