Skip to content

Commit ef1009c

Browse files
author
Gwenhael Goavec-Merou
committed
xilinx: adapted code to support existing spiOverJtag bitstreams (v1) and new bitstreams (v2)
1 parent dfa5cf3 commit ef1009c

File tree

2 files changed

+174
-3
lines changed

2 files changed

+174
-3
lines changed

src/xilinx.cpp

Lines changed: 161 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737

3838
/* Used for xc3s */
3939
#define USER1 0x02
40+
#define USER4 0x23
4041
#define CFG_IN 0x05
4142
#define USERCODE 0x08
4243
#define IDCODE 0x09
@@ -278,7 +279,7 @@ Xilinx::Xilinx(Jtag *jtag, const std::string &filename,
278279
SPIInterface(filename, verbose, 256, verify, skip_load_bridge,
279280
skip_reset),
280281
_device_package(device_package), _spiOverJtagPath(spiOverJtagPath),
281-
_irlen(6), _secondary_filename(secondary_filename)
282+
_irlen(6), _secondary_filename(secondary_filename), _soj_is_v2(false)
282283
{
283284
if (prg_type == Device::RD_FLASH) {
284285
_mode = Device::READ_MODE;
@@ -673,11 +674,20 @@ bool Xilinx::post_flash_access()
673674

674675
bool Xilinx::prepare_flash_access()
675676
{
677+
bool ret = false;
676678
if (_skip_load_bridge) {
677679
printInfo("Skip loading bridge for spiOverjtag");
678-
return true;
680+
ret = true;
681+
} else {
682+
ret = load_bridge();
683+
}
684+
/* check SpiOverJtag version */
685+
if (ret) {
686+
if (get_spiOverJtag_version() == 2.0f)
687+
_soj_is_v2 = true;
688+
printf("SOJ version: %f\n", _soj_is_v2 ? 2.0f : 1.0f);
679689
}
680-
return load_bridge();
690+
return ret;
681691
}
682692

683693
bool Xilinx::load_bridge()
@@ -714,9 +724,31 @@ bool Xilinx::load_bridge()
714724
printError(e.what());
715725
throw std::runtime_error(e.what());
716726
}
727+
717728
return true;
718729
}
719730

731+
float Xilinx::get_spiOverJtag_version()
732+
{
733+
uint8_t jtx[6] = {0x01, 0x00, 0x00, 0x00, 0x00, 0x00};
734+
uint8_t jrx[7];
735+
uint8_t rx[6];
736+
737+
_jtag->shiftIR(USER4, _irlen, Jtag::UPDATE_IR);
738+
if (_jtag->get_chain_len() > 1)
739+
_jtag->shiftDR(jtx, NULL, 1, Jtag::SHIFT_DR);
740+
_jtag->shiftDR(jtx, jrx, 6 * 8);
741+
_jtag->flush();
742+
743+
memcpy(rx, &jrx[1], 5);
744+
rx[5] = '\0';
745+
746+
float version = atof((const char *)rx);
747+
if (version == 0.0f) // not supported => 1.0
748+
return 1.0f;
749+
return version;
750+
}
751+
720752
void Xilinx::program_spi(ConfigBitstreamParser * bit, unsigned int offset,
721753
bool unprotect_flash)
722754
{
@@ -2023,6 +2055,10 @@ bool Xilinx::xc2c_flow_program(JedParser *jed)
20232055
int Xilinx::spi_put(uint8_t cmd,
20242056
const uint8_t *tx, uint8_t *rx, uint32_t len)
20252057
{
2058+
/* SpiOverJtag v2 */
2059+
if (_soj_is_v2)
2060+
return spi_put_v2(cmd, tx, rx, len);
2061+
20262062
int xfer_len = len + 1 + ((rx == NULL) ? 0 : 1);
20272063
uint8_t jtx[xfer_len];
20282064
jtx[0] = McsParser::reverseByte(cmd);
@@ -2074,6 +2110,10 @@ int Xilinx::spi_put(const uint8_t *tx, uint8_t *rx, uint32_t len)
20742110
int Xilinx::spi_wait(uint8_t cmd, uint8_t mask, uint8_t cond,
20752111
uint32_t timeout, bool verbose)
20762112
{
2113+
/* SpiOverJtag v2 */
2114+
if (_soj_is_v2)
2115+
return spi_wait_v2(cmd, mask, cond, timeout, verbose);
2116+
20772117
uint8_t rx[2];
20782118
uint8_t dummy[2];
20792119
memset(dummy, 0xff, sizeof(dummy));
@@ -2108,6 +2148,124 @@ int Xilinx::spi_wait(uint8_t cmd, uint8_t mask, uint8_t cond,
21082148
}
21092149
}
21102150

2151+
int Xilinx::spi_put_v2(uint8_t cmd, const uint8_t *tx, uint8_t *rx,
2152+
uint32_t len)
2153+
{
2154+
const uint32_t real_len = len + 1; // rx/tx length + cmd
2155+
uint32_t kPktLen = real_len + 2 ; // One header and +1 due to the needs of an additional bit/byte
2156+
uint8_t mode = 0x01;
2157+
if (real_len > 32) {
2158+
kPktLen++; // Additional header
2159+
mode = 0x00;
2160+
}
2161+
2162+
uint32_t xfer_bit_len = (kPktLen - 1) * 8 + (rx ? 8 : 1);
2163+
2164+
uint8_t jrx[kPktLen];
2165+
uint8_t pkt[kPktLen];
2166+
uint32_t idx = 0;
2167+
2168+
pkt[idx++] = ((0x1f & real_len) << 3) | ((0x03 & mode) << 1) | 1;
2169+
if (mode == 0x00)
2170+
pkt[idx++] = 0xff & (real_len >> 5);
2171+
2172+
pkt[idx++] = McsParser::reverseByte(cmd);
2173+
if (tx) {
2174+
for (uint32_t i=0; i < len; i++)
2175+
pkt[idx++] = McsParser::reverseByte(tx[i]);
2176+
} else {
2177+
memset(&pkt[idx], 0, len);
2178+
idx += len;
2179+
}
2180+
2181+
/* addr BSCAN user1 */
2182+
_jtag->shiftIR(get_ircode(_ircode_map, _user_instruction), NULL, _irlen);
2183+
_jtag->shiftDR(pkt, (rx == NULL) ? NULL : jrx, xfer_bit_len);
2184+
_jtag->go_test_logic_reset();
2185+
_jtag->flush();
2186+
2187+
if (_verbose) {
2188+
for (uint32_t i = 0; i < kPktLen; i++)
2189+
printf("%02x ", pkt[i]);
2190+
printf("\n");
2191+
}
2192+
2193+
if (rx != NULL) {
2194+
if (_verbose) {
2195+
for (uint32_t i = 0; i < kPktLen; i++)
2196+
printf("%02x ", jrx[i]);
2197+
printf("\n");
2198+
for (uint32_t i = 0; i < kPktLen; i++)
2199+
printf("%02x ", McsParser::reverseByte(jrx[i]));
2200+
printf("\n");
2201+
}
2202+
idx = (mode == 0 ? 3 : 2);
2203+
uint8_t shift = (_jtag->get_chain_len() > 1) ? 2 : 1;
2204+
for (uint32_t i = 0; i < len; i++) {
2205+
rx[i] = McsParser::reverseByte(jrx[i + idx] >> shift);
2206+
if (shift == 1) {
2207+
rx[i] |= (jrx[i + idx + 1] & 0x01);
2208+
} else {
2209+
rx[i] |= ((jrx[i + idx + 1] & 0x01) << 1) |
2210+
((jrx[i + idx + 1] & 0x02) >> 1);
2211+
}
2212+
if (_verbose)
2213+
printf("%02x ", rx[i]);
2214+
}
2215+
if (_verbose)
2216+
printf("\n");
2217+
}
2218+
2219+
return 0;
2220+
}
2221+
2222+
int Xilinx::spi_wait_v2(uint8_t cmd, uint8_t mask, uint8_t cond,
2223+
uint32_t timeout, bool verbose)
2224+
{
2225+
uint8_t rx[2];
2226+
uint8_t tx[2];
2227+
uint8_t tmp;
2228+
uint32_t count = 0;
2229+
uint8_t shift = _jtag->get_chain_len() > 1 ? 2 : 1;
2230+
2231+
tx[0] = (0x2 << 1) | 1;
2232+
tx[1] = McsParser::reverseByte(cmd);
2233+
2234+
_jtag->shiftIR(get_ircode(_ircode_map, _user_instruction), NULL, _irlen, Jtag::UPDATE_IR);
2235+
_jtag->shiftDR(tx, NULL, 16, Jtag::SHIFT_DR);
2236+
2237+
tx[0] = tx[1] = 0;
2238+
2239+
do {
2240+
_jtag->shiftDR(tx, rx, 8*2, Jtag::SHIFT_DR);
2241+
tmp = (McsParser::reverseByte(rx[0] >> shift));
2242+
if (shift == 1) {
2243+
tmp |= (0x01 & rx[1]);
2244+
} else {
2245+
tmp |= ((0x01 & rx[1]) << 1) |
2246+
(0x01 & (rx[1] >> 1));
2247+
}
2248+
count++;
2249+
if (count == timeout){
2250+
printf("timeout: %x %x %x\n", tmp, rx[0], rx[1]);
2251+
break;
2252+
}
2253+
if (verbose) {
2254+
printf("%x %x %x %u %02x %02x\n", tmp, mask, cond, count, rx[0], rx[1]);
2255+
}
2256+
} while ((tmp & mask) != cond);
2257+
2258+
_jtag->shiftDR(tx, rx, 8*2, Jtag::EXIT1_DR);
2259+
_jtag->go_test_logic_reset();
2260+
2261+
if (count == timeout) {
2262+
printf("%x\n", tmp);
2263+
std::cout << "wait: Error" << std::endl;
2264+
return -ETIME;
2265+
}
2266+
return 0;
2267+
}
2268+
21112269
void Xilinx::select_flash_chip(xilinx_flash_chip_t flash_chip) {
21122270
switch (flash_chip) {
21132271
case SECONDARY_FLASH:

src/xilinx.hpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,12 @@ class Xilinx: public Device, SPIInterface {
168168
int spi_wait(uint8_t cmd, uint8_t mask, uint8_t cond,
169169
uint32_t timeout, bool verbose = false) override;
170170

171+
/* SpiOverJtag v2 specifics methods */
172+
int spi_put_v2(uint8_t cmd, const uint8_t *tx, uint8_t *rx,
173+
uint32_t len);
174+
int spi_wait_v2(uint8_t cmd, uint8_t mask, uint8_t cond,
175+
uint32_t timeout, bool verbose = false);
176+
171177
protected:
172178
/*!
173179
* \brief prepare SPI flash access (need to have bridge in RAM)
@@ -215,6 +221,12 @@ class Xilinx: public Device, SPIInterface {
215221
*/
216222
bool load_bridge();
217223

224+
/*!
225+
* \brief read SpiOverJtag version to select between v1 and v2
226+
* \return 2.0 for v2 or 1.0 for v1
227+
*/
228+
float get_spiOverJtag_version();
229+
218230
enum xilinx_flash_chip_t {
219231
PRIMARY_FLASH = 0x1,
220232
SECONDARY_FLASH = 0x2
@@ -249,6 +261,7 @@ class Xilinx: public Device, SPIInterface {
249261
std::string _secondary_file_extension; /* file type for the secondary flash file */
250262
int _flash_chips; /* bitfield to select the target in boards with two flash chips */
251263
std::string _user_instruction; /* which USER bscan instruction to interface with SPI */
264+
bool _soj_is_v2; /* SpiOverJtag version (1.0 or 2.0) */
252265
};
253266

254267
#endif // SRC_XILINX_HPP_

0 commit comments

Comments
 (0)