From ee4a62e96827ffd48b27ea1b021d6aa35d8d14f9 Mon Sep 17 00:00:00 2001 From: Gwenhael Goavec-Merou Date: Tue, 21 Apr 2020 09:08:32 +0200 Subject: [PATCH] xilinx: implement spiInterface and pass this instead of jtag to spiFlash class --- src/xilinx.cpp | 103 ++++++++++++++++++++++++++++++++++++++++++++++++- src/xilinx.hpp | 12 +++++- 2 files changed, 113 insertions(+), 2 deletions(-) diff --git a/src/xilinx.cpp b/src/xilinx.cpp index 1ebf45a..ec9fdb8 100644 --- a/src/xilinx.cpp +++ b/src/xilinx.cpp @@ -22,6 +22,7 @@ Xilinx::Xilinx(Jtag *jtag, std::string filename, bool verbose): } Xilinx::~Xilinx() {} +#define USER1 0x02 #define CFG_IN 0x05 #define USERCODE 0x08 #define IDCODE 0x09 @@ -92,7 +93,7 @@ void Xilinx::program_spi(unsigned int offset) /* last: read file and erase/flash spi flash */ McsParser mcs(_filename, _verbose); mcs.parse(); - SPIFlash spiFlash(_jtag, _verbose); + SPIFlash spiFlash(this, _verbose); spiFlash.erase_and_prog(offset, mcs.getData(), mcs.getLength()); } @@ -206,3 +207,103 @@ void Xilinx::program_mem(BitParser &bitfile) */ _jtag->go_test_logic_reset(); } + +/* + * jtag : jtag interface + * cmd : opcode for SPI flash + * tx : buffer to send + * rx : buffer to fill + * len : number of byte to send/receive (cmd not comprise) + * so to send only a cmd set len to 0 (or omit this param) + */ +int Xilinx::spi_put(uint8_t cmd, + uint8_t *tx, uint8_t *rx, uint16_t len) +{ + int xfer_len = len + 1 + ((rx == NULL) ? 0 : 1); + uint8_t jtx[xfer_len]; + jtx[0] = McsParser::reverseByte(cmd); + /* uint8_t jtx[xfer_len] = {McsParser::reverseByte(cmd)}; */ + uint8_t jrx[xfer_len]; + if (tx != NULL) { + for (int i=0; i < len; i++) + jtx[i+1] = McsParser::reverseByte(tx[i]); + } + /* addr BSCAN user1 */ + _jtag->shiftIR(USER1, 6); + /* send first already stored cmd, + * in the same time store each byte + * to next + */ + _jtag->shiftDR(jtx, (rx == NULL)? NULL: jrx, 8*xfer_len); + + if (rx != NULL) { + for (int i=0; i < len; i++) + rx[i] = McsParser::reverseByte(jrx[i+1] >> 1) | (jrx[i+2] & 0x01); + } + return 0; +} + +int Xilinx::spi_put(uint8_t *tx, uint8_t *rx, uint16_t len) +{ + int xfer_len = len + ((rx == NULL) ? 0 : 1); + uint8_t jtx[xfer_len]; + uint8_t jrx[xfer_len]; + if (tx != NULL) { + for (int i=0; i < len; i++) + jtx[i] = McsParser::reverseByte(tx[i]); + } + /* addr BSCAN user1 */ + _jtag->shiftIR(USER1, 6); + /* send first already stored cmd, + * in the same time store each byte + * to next + */ + _jtag->shiftDR(jtx, (rx == NULL)? NULL: jrx, 8*xfer_len); + + if (rx != NULL) { + for (int i=0; i < len; i++) + rx[i] = McsParser::reverseByte(jrx[i] >> 1) | (jrx[i+1] & 0x01); + } + return 0; +} + +int Xilinx::spi_wait(uint8_t cmd, uint8_t mask, uint8_t cond, + uint32_t timeout, bool verbose) +{ + uint8_t rx[2]; + uint8_t dummy[2]; + uint8_t tmp; + uint8_t tx = McsParser::reverseByte(cmd); + uint32_t count = 0; + + _jtag->shiftIR(USER1, 6, Jtag::UPDATE_IR); + _jtag->set_state(Jtag::SHIFT_DR); + _jtag->read_write(&tx, NULL, 8, 0); + + do { + _jtag->read_write(dummy, rx, 8*2, 0); + tmp = (McsParser::reverseByte(rx[0]>>1)) | (0x01 & rx[1]); + count++; + if (count == timeout){ + printf("timeout: %x %x %x\n", tmp, rx[0], rx[1]); + break; + } + if (tmp & ~0x3) { + printf("Error: rx %x %x %x\n", tmp, McsParser::reverseByte(rx[0]), rx[1]); + count = timeout; + break; + } + if (verbose) { + printf("%x %x %x %d\n", tmp, mask, cond, count); + } + } while ((tmp & mask) != cond); + _jtag->go_test_logic_reset(); + + if (count == timeout) { + printf("%x\n", tmp); + std::cout << "wait: Error" << std::endl; + return -ETIME; + } else { + return 0; + } +} diff --git a/src/xilinx.hpp b/src/xilinx.hpp index 1e6b80c..fd6b88c 100644 --- a/src/xilinx.hpp +++ b/src/xilinx.hpp @@ -1,11 +1,14 @@ #ifndef XILINX_HPP #define XILINX_HPP +#include + #include "bitparser.hpp" #include "device.hpp" #include "jtag.hpp" +#include "spiInterface.hpp" -class Xilinx: public Device { +class Xilinx: public Device, SPIInterface { public: Xilinx(Jtag *jtag, std::string filename, bool verbose); ~Xilinx(); @@ -15,6 +18,13 @@ class Xilinx: public Device { void program_mem(BitParser &bitfile); int idCode(); void reset(); + + /* spi interface */ + int spi_put(uint8_t cmd, uint8_t *tx, uint8_t *rx, + uint16_t len) override; + int spi_put(uint8_t *tx, uint8_t *rx, uint16_t len) override; + int spi_wait(uint8_t cmd, uint8_t mask, uint8_t cond, + uint32_t timeout, bool verbose = false) override; }; #endif