gowin: GW5A SPI flash support
This commit is contained in:
parent
a5f2aa56c8
commit
b119a955a6
282
src/gowin.cpp
282
src/gowin.cpp
|
|
@ -79,6 +79,7 @@ Gowin::Gowin(Jtag *jtag, const string filename, const string &file_type, std::st
|
||||||
Device::prog_type_t prg_type, bool external_flash,
|
Device::prog_type_t prg_type, bool external_flash,
|
||||||
bool verify, int8_t verbose): Device(jtag, filename, file_type,
|
bool verify, int8_t verbose): Device(jtag, filename, file_type,
|
||||||
verify, verbose),
|
verify, verbose),
|
||||||
|
SPIInterface(filename, verbose, 0, verify, false, false),
|
||||||
_fs(NULL), _idcode(0), is_gw1n1(false), is_gw2a(false),
|
_fs(NULL), _idcode(0), is_gw1n1(false), is_gw2a(false),
|
||||||
is_gw1n4(false), is_gw5a(false), _external_flash(external_flash),
|
is_gw1n4(false), is_gw5a(false), _external_flash(external_flash),
|
||||||
_spi_sck(BSCAN_SPI_SCK), _spi_cs(BSCAN_SPI_CS),
|
_spi_sck(BSCAN_SPI_SCK), _spi_cs(BSCAN_SPI_CS),
|
||||||
|
|
@ -88,6 +89,9 @@ Gowin::Gowin(Jtag *jtag, const string filename, const string &file_type, std::st
|
||||||
{
|
{
|
||||||
detectFamily();
|
detectFamily();
|
||||||
|
|
||||||
|
_prev_wr_edge = _jtag->getWriteEdge();
|
||||||
|
_prev_rd_edge = _jtag->getReadEdge();
|
||||||
|
|
||||||
if (prg_type == Device::WR_FLASH)
|
if (prg_type == Device::WR_FLASH)
|
||||||
_mode = Device::FLASH_MODE;
|
_mode = Device::FLASH_MODE;
|
||||||
else
|
else
|
||||||
|
|
@ -150,6 +154,17 @@ Gowin::Gowin(Jtag *jtag, const string filename, const string &file_type, std::st
|
||||||
printSuccess("DONE");
|
printSuccess("DONE");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (is_gw5a && _mode == Device::FLASH_MODE) {
|
||||||
|
_jtag->setClkFreq(2500000);
|
||||||
|
_jtag->set_state(Jtag::TEST_LOGIC_RESET);
|
||||||
|
if (_verbose)
|
||||||
|
displayReadReg("Before disable SPI mode", readStatusReg());
|
||||||
|
disableCfg();
|
||||||
|
send_command(0); // BYPASS ?
|
||||||
|
_jtag->set_state(Jtag::TEST_LOGIC_RESET);
|
||||||
|
gw5a_disable_spi();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Gowin::~Gowin()
|
Gowin::~Gowin()
|
||||||
|
|
@ -283,20 +298,10 @@ void Gowin::programFlash()
|
||||||
|
|
||||||
void Gowin::programExtFlash(unsigned int offset, bool unprotect_flash)
|
void Gowin::programExtFlash(unsigned int offset, bool unprotect_flash)
|
||||||
{
|
{
|
||||||
_jtag->setClkFreq(10000000);
|
displayReadReg("after program flash", readStatusReg());
|
||||||
|
|
||||||
if (!enableCfg())
|
if (!prepare_flash_access()) {
|
||||||
throw std::runtime_error("Error: fail to enable configuration");
|
throw std::runtime_error("Error: fail to prepare flash access");
|
||||||
|
|
||||||
eraseSRAM();
|
|
||||||
send_command(XFER_DONE);
|
|
||||||
send_command(NOOP);
|
|
||||||
|
|
||||||
if (!is_gw2a) {
|
|
||||||
send_command(0x3D);
|
|
||||||
} else {
|
|
||||||
disableCfg();
|
|
||||||
send_command(NOOP);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SPIFlash spiFlash(this, unprotect_flash,
|
SPIFlash spiFlash(this, unprotect_flash,
|
||||||
|
|
@ -307,17 +312,30 @@ void Gowin::programExtFlash(unsigned int offset, bool unprotect_flash)
|
||||||
const uint8_t *data = _fs->getData();
|
const uint8_t *data = _fs->getData();
|
||||||
int length = _fs->getLength();
|
int length = _fs->getLength();
|
||||||
|
|
||||||
if (spiFlash.erase_and_prog(offset, data, length / 8) != 0)
|
char mess[256];
|
||||||
throw std::runtime_error("Error: write to flash failed");
|
bool ret = true;
|
||||||
if (_verify)
|
|
||||||
if (!spiFlash.verify(offset, data, length / 8, 256))
|
if (spiFlash.erase_and_prog(offset, data, length / 8) != 0) {
|
||||||
throw std::runtime_error("Error: flash vefication failed");
|
snprintf(mess, 256, "Error: write to flash failed");
|
||||||
if (!is_gw2a) {
|
printError(mess);
|
||||||
if (!disableCfg())
|
ret = false;
|
||||||
throw std::runtime_error("Error: fail to disable configuration");
|
}
|
||||||
|
if (ret && _verify)
|
||||||
|
if (!spiFlash.verify(offset, data, length / 8, 256)) {
|
||||||
|
snprintf(mess, 256, "Error: flash vefication failed");
|
||||||
|
printError(mess);
|
||||||
|
ret = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!post_flash_access()) {
|
||||||
|
snprintf(mess, 256, "Error: fail to disable flash access");
|
||||||
|
printError(mess);
|
||||||
|
ret = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
reset();
|
if (!ret) {
|
||||||
|
throw std::runtime_error(mess);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Gowin::programSRAM()
|
void Gowin::programSRAM()
|
||||||
|
|
@ -352,8 +370,6 @@ void Gowin::program(unsigned int offset, bool unprotect_flash)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (_mode == FLASH_MODE) {
|
if (_mode == FLASH_MODE) {
|
||||||
if (is_gw5a)
|
|
||||||
throw std::runtime_error("Error: write to flash on GW5A is not yet supported");
|
|
||||||
if (_external_flash)
|
if (_external_flash)
|
||||||
programExtFlash(offset, unprotect_flash);
|
programExtFlash(offset, unprotect_flash);
|
||||||
else
|
else
|
||||||
|
|
@ -787,6 +803,9 @@ inline void Gowin::spi_gowin_write(const uint8_t *wr, uint8_t *rd, unsigned len)
|
||||||
|
|
||||||
int Gowin::spi_put(uint8_t cmd, const uint8_t *tx, uint8_t *rx, uint32_t len)
|
int Gowin::spi_put(uint8_t cmd, const uint8_t *tx, uint8_t *rx, uint32_t len)
|
||||||
{
|
{
|
||||||
|
if (is_gw5a)
|
||||||
|
return spi_put_gw5a(cmd, tx, rx, len);
|
||||||
|
|
||||||
uint8_t jrx[len+1], jtx[len+1];
|
uint8_t jrx[len+1], jtx[len+1];
|
||||||
jtx[0] = cmd;
|
jtx[0] = cmd;
|
||||||
if (tx)
|
if (tx)
|
||||||
|
|
@ -801,6 +820,18 @@ int Gowin::spi_put(uint8_t cmd, const uint8_t *tx, uint8_t *rx, uint32_t len)
|
||||||
|
|
||||||
int Gowin::spi_put(const uint8_t *tx, uint8_t *rx, uint32_t len)
|
int Gowin::spi_put(const uint8_t *tx, uint8_t *rx, uint32_t len)
|
||||||
{
|
{
|
||||||
|
if (is_gw5a) {
|
||||||
|
uint8_t jrx[len];
|
||||||
|
int ret = spi_put_gw5a(tx[0], (len > 1) ? &tx[1] : NULL,
|
||||||
|
(rx) ? jrx : NULL, len - 1);
|
||||||
|
// FIXME: first byte is never read (but in most call it's not an issue
|
||||||
|
if (rx) {
|
||||||
|
rx[0] = 0;
|
||||||
|
memcpy(&rx[1], jrx, len - 1);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
if (is_gw2a) {
|
if (is_gw2a) {
|
||||||
uint8_t jtx[len];
|
uint8_t jtx[len];
|
||||||
uint8_t jrx[len];
|
uint8_t jrx[len];
|
||||||
|
|
@ -858,6 +889,9 @@ int Gowin::spi_put(const uint8_t *tx, uint8_t *rx, uint32_t len)
|
||||||
int Gowin::spi_wait(uint8_t cmd, uint8_t mask, uint8_t cond,
|
int Gowin::spi_wait(uint8_t cmd, uint8_t mask, uint8_t cond,
|
||||||
uint32_t timeout, bool verbose)
|
uint32_t timeout, bool verbose)
|
||||||
{
|
{
|
||||||
|
if (is_gw5a)
|
||||||
|
return spi_wait_gw5a(cmd, mask, cond, timeout, verbose);
|
||||||
|
|
||||||
uint8_t tmp;
|
uint8_t tmp;
|
||||||
uint32_t count = 0;
|
uint32_t count = 0;
|
||||||
|
|
||||||
|
|
@ -940,3 +974,203 @@ int Gowin::spi_wait(uint8_t cmd, uint8_t mask, uint8_t cond,
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Gowin::dumpFlash(uint32_t base_addr, uint32_t len)
|
||||||
|
{
|
||||||
|
bool ret = true;
|
||||||
|
/* enable SPI flash access */
|
||||||
|
if (!prepare_flash_access())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
try {
|
||||||
|
SPIFlash flash(this, false, _verbose);
|
||||||
|
ret = flash.dump(_filename, base_addr, len, 256);
|
||||||
|
} catch (std::exception &e) {
|
||||||
|
printError(e.what());
|
||||||
|
ret = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* reload bitstream */
|
||||||
|
return post_flash_access() && ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Gowin::prepare_flash_access()
|
||||||
|
{
|
||||||
|
_jtag->setClkFreq(10000000);
|
||||||
|
|
||||||
|
if (!eraseSRAM()) {
|
||||||
|
printError("Error: fail to erase SRAM");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_gw5a) {
|
||||||
|
if (!gw5a_enable_spi()) {
|
||||||
|
printError("Error: fail to switch GW5A to SPI mode");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else if (!is_gw2a) {
|
||||||
|
send_command(0x3D);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Gowin::post_flash_access()
|
||||||
|
{
|
||||||
|
bool ret = true;
|
||||||
|
|
||||||
|
if (is_gw5a) {
|
||||||
|
if (!gw5a_disable_spi()) {
|
||||||
|
printError("Error: fail to disable GW5A SPI mode");
|
||||||
|
ret = false;
|
||||||
|
}
|
||||||
|
} else if (!is_gw2a) {
|
||||||
|
if (!disableCfg()) {
|
||||||
|
printError("Error: fail to disable configuration");
|
||||||
|
ret = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
reset();
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Specific implementation for Arora V GW5A FPGAs
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* interface mode is already configured to mimic SPI (mode 0).
|
||||||
|
* JTAG is LSB, SPI is MSB -> all byte must be reversed.
|
||||||
|
*/
|
||||||
|
int Gowin::spi_put_gw5a(const uint8_t cmd, const uint8_t *tx, uint8_t *rx,
|
||||||
|
uint32_t len)
|
||||||
|
{
|
||||||
|
uint32_t kLen = len + (rx ? 1 : 0); // cppcheck/lint happy
|
||||||
|
uint32_t bit_len = len * 8 + (rx ? 3 : 0); // 3bits delay when read
|
||||||
|
uint8_t jtx[kLen], jrx[kLen];
|
||||||
|
uint8_t _cmd = FsParser::reverseByte(cmd); // reverse cmd.
|
||||||
|
uint8_t curr_tdi = cmd & 0x01;
|
||||||
|
|
||||||
|
if (tx != NULL) { // SPI: MSB, JTAG: LSB -> reverse Bytes
|
||||||
|
for (uint32_t i = 0; i < len; i++)
|
||||||
|
jtx[i] = FsParser::reverseByte(tx[i]);
|
||||||
|
curr_tdi = tx[len-1] & 0x01;
|
||||||
|
} else {
|
||||||
|
memset(jtx, curr_tdi, kLen);
|
||||||
|
}
|
||||||
|
|
||||||
|
// set TMS/CS low by moving to a state where TMS == 0,
|
||||||
|
// first cmd bit is also sent here (ie before next TCK rise).
|
||||||
|
_jtag->set_state(Jtag::RUN_TEST_IDLE, _cmd & 0x01);
|
||||||
|
_cmd >>= 1;
|
||||||
|
|
||||||
|
// complete with 7 remaining cmd bits
|
||||||
|
if (0 != _jtag->read_write(&_cmd, NULL, 7, 0))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
// write/read the sequence. Force set to 0 to manage state here
|
||||||
|
// (with jtag last bit is sent with tms rise)
|
||||||
|
if (0 != _jtag->read_write(jtx, (rx) ? jrx : NULL, bit_len, 0))
|
||||||
|
return -1;
|
||||||
|
// set TMS/CS high by moving to a state where TMS == 1
|
||||||
|
_jtag->set_state(Jtag::TEST_LOGIC_RESET, curr_tdi);
|
||||||
|
_jtag->toggleClk(5); // Required ?
|
||||||
|
_jtag->flushTMS(true);
|
||||||
|
if (rx) { // Reconstruct read sequence and drop first 3bits.
|
||||||
|
for (uint32_t i = 0; i < len; i++)
|
||||||
|
rx[i] = FsParser::reverseByte((jrx[i] >> 3) |
|
||||||
|
(((jrx[i+1]) & 0x07) << 5));
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Gowin::spi_wait_gw5a(uint8_t cmd, uint8_t mask, uint8_t cond,
|
||||||
|
uint32_t timeout, bool verbose)
|
||||||
|
{
|
||||||
|
uint8_t tmp;
|
||||||
|
uint32_t count = 0;
|
||||||
|
|
||||||
|
do {
|
||||||
|
// sent command and read flash answer
|
||||||
|
if (0 != spi_put_gw5a(cmd, NULL, &tmp, 1)) {
|
||||||
|
printError("Error: cant write/read status");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
count++;
|
||||||
|
if (count == timeout) {
|
||||||
|
printf("timeout: %x\n", tmp);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (verbose) {
|
||||||
|
printf("%x %x %x %u\n", tmp, mask, cond, count);
|
||||||
|
}
|
||||||
|
} while ((tmp & mask) != cond);
|
||||||
|
|
||||||
|
return (count == timeout) ? -1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Gowin::gw5a_enable_spi()
|
||||||
|
{
|
||||||
|
enableCfg();
|
||||||
|
send_command(0x3F);
|
||||||
|
disableCfg();
|
||||||
|
if (_verbose)
|
||||||
|
displayReadReg("toto", readStatusReg());
|
||||||
|
|
||||||
|
/* UG704 3.4.3 'ExtFlash Programming -> Program External Flash via JTAG-SPI' */
|
||||||
|
send_command(NOOP);
|
||||||
|
_jtag->set_state(Jtag::RUN_TEST_IDLE);
|
||||||
|
_jtag->toggleClk(126*8);
|
||||||
|
_jtag->set_state(Jtag::RUN_TEST_IDLE);
|
||||||
|
send_command(0x16);
|
||||||
|
send_command(0x00);
|
||||||
|
_jtag->set_state(Jtag::RUN_TEST_IDLE);
|
||||||
|
_jtag->toggleClk(625*8);
|
||||||
|
_jtag->set_state(Jtag::TEST_LOGIC_RESET);
|
||||||
|
/* save current read/write edge cfg before switching to SPI mode0
|
||||||
|
* (rising edge: read / falling edge: write)
|
||||||
|
*/
|
||||||
|
_prev_wr_edge = _jtag->getWriteEdge();
|
||||||
|
_prev_rd_edge = _jtag->getReadEdge();
|
||||||
|
_jtag->setWriteEdge(JtagInterface::FALLING_EDGE);
|
||||||
|
_jtag->setReadEdge(JtagInterface::RISING_EDGE);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Gowin::gw5a_disable_spi()
|
||||||
|
{
|
||||||
|
/* reconfigure WR/RD edge and sent sequence to
|
||||||
|
* disable SPI mode
|
||||||
|
*/
|
||||||
|
_jtag->setWriteEdge(_prev_wr_edge);
|
||||||
|
_jtag->setReadEdge(_prev_rd_edge);
|
||||||
|
_jtag->flushTMS(true);
|
||||||
|
_jtag->flush();
|
||||||
|
// 1. sent 15 TMS pulse
|
||||||
|
// TEST_LOGIC_RESET to SELECT_DR_SCAN: 01
|
||||||
|
_jtag->set_state(Jtag::SELECT_DR_SCAN);
|
||||||
|
// SELECT_DR_SCAN to CAPTURE_DR: 0
|
||||||
|
_jtag->set_state(Jtag::CAPTURE_DR);
|
||||||
|
// CAPTURE_DR to EXIT1_DR: 1
|
||||||
|
_jtag->set_state(Jtag::EXIT1_DR);
|
||||||
|
// EXIT1_DR to EXIT2_DR: 01
|
||||||
|
_jtag->set_state(Jtag::EXIT2_DR);
|
||||||
|
// Now we have 3 pulses
|
||||||
|
for (int i = 0; i < 6; i++) { // 2 each loop: 12 pulses + 3 before
|
||||||
|
_jtag->set_state(Jtag::PAUSE_DR); // 010
|
||||||
|
_jtag->set_state(Jtag::EXIT2_DR); // 1
|
||||||
|
}
|
||||||
|
_jtag->set_state(Jtag::EXIT1_DR); // 01 : 16
|
||||||
|
_jtag->set_state(Jtag::PAUSE_DR); // 0
|
||||||
|
|
||||||
|
_jtag->flushTMS(true);
|
||||||
|
_jtag->flush();
|
||||||
|
// 2. 8 TCK clock cycle with TMS=1
|
||||||
|
_jtag->set_state(Jtag::TEST_LOGIC_RESET); // 5 cycles
|
||||||
|
_jtag->toggleClk(5);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@
|
||||||
#include "configBitstreamParser.hpp"
|
#include "configBitstreamParser.hpp"
|
||||||
#include "device.hpp"
|
#include "device.hpp"
|
||||||
#include "jtag.hpp"
|
#include "jtag.hpp"
|
||||||
|
#include "jtagInterface.hpp"
|
||||||
#include "spiInterface.hpp"
|
#include "spiInterface.hpp"
|
||||||
|
|
||||||
class Gowin: public Device, SPIInterface {
|
class Gowin: public Device, SPIInterface {
|
||||||
|
|
@ -32,15 +33,58 @@ class Gowin: public Device, SPIInterface {
|
||||||
(void) len;
|
(void) len;
|
||||||
printError("protect flash not supported"); return false;}
|
printError("protect flash not supported"); return false;}
|
||||||
bool unprotect_flash() override {
|
bool unprotect_flash() override {
|
||||||
|
if (is_gw5a)
|
||||||
|
return SPIInterface::unprotect_flash();
|
||||||
printError("unprotect flash not supported"); return false;}
|
printError("unprotect flash not supported"); return false;}
|
||||||
bool bulk_erase_flash() override {
|
bool bulk_erase_flash() override {
|
||||||
|
if (is_gw5a)
|
||||||
|
return SPIInterface::bulk_erase_flash();
|
||||||
printError("bulk erase flash not supported"); return false;}
|
printError("bulk erase flash not supported"); return false;}
|
||||||
|
bool dumpFlash(uint32_t base_addr, uint32_t len) override;
|
||||||
int spi_put(uint8_t cmd, const uint8_t *tx, uint8_t *rx,
|
int spi_put(uint8_t cmd, const uint8_t *tx, uint8_t *rx,
|
||||||
uint32_t len) override;
|
uint32_t len) override;
|
||||||
int spi_put(const uint8_t *tx, uint8_t *rx, uint32_t len) override;
|
int spi_put(const uint8_t *tx, uint8_t *rx, uint32_t len) override;
|
||||||
int spi_wait(uint8_t cmd, uint8_t mask, uint8_t cond,
|
int spi_wait(uint8_t cmd, uint8_t mask, uint8_t cond,
|
||||||
uint32_t timeout, bool verbose) override;
|
uint32_t timeout, bool verbose) override;
|
||||||
|
|
||||||
|
/* ---------------- */
|
||||||
|
/* Arora V specific */
|
||||||
|
/* ---------------- */
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Send cmd, followed by (optional) tx sequence and fill
|
||||||
|
* rx if not null
|
||||||
|
* \param[in] cmd: SPI command
|
||||||
|
* \param[in] rx: Byte sequence to write (may be null)
|
||||||
|
* \param[out] tx: Byte buffer when read is requested
|
||||||
|
* \param[in] len: number of Byte to read/write (0 when no read/write)
|
||||||
|
* \return 0 on success, -1 otherwise
|
||||||
|
*/
|
||||||
|
int spi_put_gw5a(const uint8_t cmd, const uint8_t *tx, uint8_t *rx,
|
||||||
|
uint32_t len);
|
||||||
|
/*!
|
||||||
|
* \brief poll on cmd register until timeout or SPI reg content match
|
||||||
|
* cond with mask
|
||||||
|
* \param[in] cmd: SPI command
|
||||||
|
* \param[in] mask: mask to apply on SPI rx
|
||||||
|
* \param[in] cond: SPI rx value value
|
||||||
|
* \param[in] timeout: number of try before fail
|
||||||
|
* \param[in] verbose: display try
|
||||||
|
* \return 0 on success, -1 otherwise
|
||||||
|
*/
|
||||||
|
int spi_wait_gw5a(uint8_t cmd, uint8_t mask, uint8_t cond,
|
||||||
|
uint32_t timeout, bool verbose);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/*!
|
||||||
|
* \brief prepare SPI flash access
|
||||||
|
*/
|
||||||
|
bool prepare_flash_access() override;
|
||||||
|
/*!
|
||||||
|
* \brief end of SPI flash access
|
||||||
|
*/
|
||||||
|
bool post_flash_access() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool detectFamily();
|
bool detectFamily();
|
||||||
bool send_command(uint8_t cmd);
|
bool send_command(uint8_t cmd);
|
||||||
|
|
@ -65,6 +109,21 @@ class Gowin: public Device, SPIInterface {
|
||||||
* .fs usercode field
|
* .fs usercode field
|
||||||
*/
|
*/
|
||||||
void checkCRC();
|
void checkCRC();
|
||||||
|
|
||||||
|
/* ---------------- */
|
||||||
|
/* Arora V specific */
|
||||||
|
/* ---------------- */
|
||||||
|
/*!
|
||||||
|
* \brief Send the sequence to pass GW5A to SPI mode.
|
||||||
|
* \return true on success, false otherwise
|
||||||
|
*/
|
||||||
|
bool gw5a_disable_spi();
|
||||||
|
/*!
|
||||||
|
* \brief Send the sequence to disable SPI mode for GW5A.
|
||||||
|
* \return true on success, false otherwise
|
||||||
|
*/
|
||||||
|
bool gw5a_enable_spi();
|
||||||
|
|
||||||
ConfigBitstreamParser *_fs;
|
ConfigBitstreamParser *_fs;
|
||||||
uint32_t _idcode;
|
uint32_t _idcode;
|
||||||
bool is_gw1n1;
|
bool is_gw1n1;
|
||||||
|
|
@ -79,5 +138,7 @@ class Gowin: public Device, SPIInterface {
|
||||||
uint8_t _spi_do; /**< do signal (miso) offset in bscan SPI */
|
uint8_t _spi_do; /**< do signal (miso) offset in bscan SPI */
|
||||||
uint8_t _spi_msk; /** default spi msk with only do out */
|
uint8_t _spi_msk; /** default spi msk with only do out */
|
||||||
ConfigBitstreamParser *_mcufw;
|
ConfigBitstreamParser *_mcufw;
|
||||||
|
JtagInterface::tck_edge_t _prev_rd_edge; /**< default probe rd edge cfg */
|
||||||
|
JtagInterface::tck_edge_t _prev_wr_edge; /**< default probe wr edge cfg */
|
||||||
};
|
};
|
||||||
#endif // SRC_GOWIN_HPP_
|
#endif // SRC_GOWIN_HPP_
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue