diff --git a/src/gowin.cpp b/src/gowin.cpp index 3d064d6f1e..0582ba290f 100644 --- a/src/gowin.cpp +++ b/src/gowin.cpp @@ -160,10 +160,12 @@ Gowin::Gowin(Jtag *jtag, const string filename, const string &file_type, std::st _jtag->set_state(Jtag::TEST_LOGIC_RESET); if (_verbose) displayReadReg("Before disable SPI mode", readStatusReg()); - disableCfg(); + //disableCfg(); + send_command(CONFIG_DISABLE); // BYPASS ? send_command(0); // BYPASS ? _jtag->set_state(Jtag::TEST_LOGIC_RESET); gw5a_disable_spi(); + idCode(); } } @@ -224,6 +226,7 @@ bool Gowin::send_command(uint8_t cmd) { _jtag->shiftIR(&cmd, nullptr, 8); _jtag->toggleClk(6); + _jtag->flush(); return true; } @@ -249,6 +252,7 @@ uint32_t Gowin::readReg32(uint8_t cmd) uint32_t reg = 0, tmp = 0xffffffffU; send_command(cmd); _jtag->shiftDR((uint8_t *)&tmp, (uint8_t *)®, 32); + _jtag->toggleClk(1); return le32toh(reg); } @@ -769,6 +773,7 @@ bool Gowin::writeSRAM(const uint8_t *data, int length) int remains = length; const uint8_t *ptr = data; static const unsigned pstep = 524288; // 0x80000, about 0.2 sec of bitstream at 2.5MHz + printf("length : %d\n", length); while (remains) { int chunk = pstep; /* 2.2.6.5 */ @@ -876,9 +881,18 @@ bool Gowin::eraseFLASH() void Gowin::sendClkUs(unsigned us) { uint64_t clocks = _jtag->getClkFreq(); + printf("%d %d ", clocks, us); clocks *= us; + printf("%lu ", clocks); clocks /= 1000000; - _jtag->toggleClk(clocks); + uint32_t kLen = (clocks + 7 ) / 8; + uint8_t dummy[kLen]; + printf("%d %d\n", clocks, kLen); + memset(dummy, 0, kLen); + _jtag->read_write(dummy, NULL, clocks & 0xffffffff, 0); + if ((clocks > 0xffffffff)) + _jtag->read_write(dummy, NULL, clocks - 0xffffffff, 0); + //_jtag->toggleClk(clocks); } /* Erase SRAM: @@ -890,10 +904,12 @@ bool Gowin::eraseSRAM() if (_verbose) displayReadReg("before erase sram", readStatusReg()); - if (!enableCfg()) { + /*if (!enableCfg()) { printError("FAIL"); return false; - } + }*/ + send_command(0x11); + send_command(CONFIG_ENABLE); send_command(ERASE_SRAM); send_command(NOOP); @@ -904,23 +920,27 @@ bool Gowin::eraseSRAM() * this check seems enough */ if (_idcode == 0x0001081b) // seems required for GW5AST... - sendClkUs(10000); - if (pollFlag(STATUS_MEMORY_ERASE, STATUS_MEMORY_ERASE)) { - if (_verbose) - displayReadReg("after erase sram", readStatusReg()); - } else { - printError("FAIL"); - return false; + sendClkUs(750*9); + else { + if (pollFlag(STATUS_MEMORY_ERASE, STATUS_MEMORY_ERASE)) { + if (_verbose) + displayReadReg("after erase sram", readStatusReg()); + } else { + printError("FAIL"); + return false; + } } send_command(XFER_DONE); send_command(NOOP); - if (!disableCfg()) { + send_command(CONFIG_DISABLE); + send_command(NOOP); + /*if (!disableCfg()) { printError("FAIL"); return false; - } + }*/ - if (_mode == Device::FLASH_MODE) { + /*if (_mode == Device::FLASH_MODE) { uint32_t status_reg = readStatusReg(); if (_verbose) displayReadReg("after erase sram", status_reg); @@ -930,7 +950,7 @@ bool Gowin::eraseSRAM() } else { printSuccess("DONE"); } - } + }*/ return true; } @@ -1149,6 +1169,7 @@ bool Gowin::dumpFlash(uint32_t base_addr, uint32_t len) bool Gowin::prepare_flash_access() { _jtag->setClkFreq(10000000); + //_jtag->setClkFreq(2500000); if (!eraseSRAM()) { printError("Error: fail to erase SRAM"); @@ -1156,6 +1177,11 @@ bool Gowin::prepare_flash_access() } if (is_gw5a) { + if (!eraseSRAM()) { + printError("Error: fail to erase SRAM"); + return false; + } + displayReadReg("toto", readStatusReg()); if (!gw5a_enable_spi()) { printError("Error: fail to switch GW5A to SPI mode"); return false; @@ -1229,9 +1255,14 @@ int Gowin::spi_put_gw5a(const uint8_t cmd, const uint8_t *tx, uint8_t *rx, 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); + //_jtag->set_state(Jtag::TEST_LOGIC_RESET, 0/*curr_tdi*/); + _jtag->set_state(Jtag::SELECT_DR_SCAN, 0/*curr_tdi*/); + _jtag->flush(); + _jtag->set_state(Jtag::TEST_LOGIC_RESET, 0/*curr_tdi*/); + const uint8_t dummy = 0; + _jtag->read_write(&dummy, NULL, 5, 0); + //_jtag->toggleClk(5); // Required ? + //_jtag->flush(); if (rx) { // Reconstruct read sequence and drop first 3bits. for (uint32_t i = 0; i < len; i++) rx[i] = FsParser::reverseByte((jrx[i] >> 3) | @@ -1255,6 +1286,7 @@ int Gowin::spi_wait_gw5a(uint8_t cmd, uint8_t mask, uint8_t cond, } count++; + //printf("%x %x %x %u\n", tmp, mask, cond, count); if (count == timeout) { printf("timeout: %x\n", tmp); break; @@ -1269,21 +1301,31 @@ int Gowin::spi_wait_gw5a(uint8_t cmd, uint8_t mask, uint8_t cond, bool Gowin::gw5a_enable_spi() { - enableCfg(); + uint8_t dummy[625]; + memset(dummy, 0, 625); + //enableCfg(); + send_command(0x15); send_command(0x3F); - disableCfg(); + send_command(0x3A); + //disableCfg(); if (_verbose) displayReadReg("toto", readStatusReg()); /* UG704 3.4.3 'ExtFlash Programming -> Program External Flash via JTAG-SPI' */ send_command(NOOP); + send_command(0x11); + send_command(0x02); _jtag->set_state(Jtag::RUN_TEST_IDLE); - _jtag->toggleClk(126*8); + //_jtag->toggleClk(126*8); + _jtag->read_write(dummy, NULL, 126 * 8, 0); + //sendClkUs(51); _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->toggleClk(625*8); + //_jtag->read_write(dummy, NULL, 625 * 8, 0); + sendClkUs(250*9); _jtag->set_state(Jtag::TEST_LOGIC_RESET); /* save current read/write edge cfg before switching to SPI mode0 * (rising edge: read / falling edge: write) @@ -1327,5 +1369,6 @@ bool Gowin::gw5a_disable_spi() // 2. 8 TCK clock cycle with TMS=1 _jtag->set_state(Jtag::TEST_LOGIC_RESET); // 5 cycles _jtag->toggleClk(5); + idCode(); return true; } diff --git a/src/jtag.cpp b/src/jtag.cpp index 5eece8624b..f47cf4b0c6 100644 --- a/src/jtag.cpp +++ b/src/jtag.cpp @@ -84,7 +84,7 @@ Jtag::Jtag(const cable_t &cable, const jtag_pins_conf_t *pin_conf, _tms_buffer_size(128), _num_tms(0), _board_name("nope"), _user_misc_devs(user_misc_devs), device_index(0), _dr_bits_before(0), _dr_bits_after(0), - _ir_bits_before(0), _ir_bits_after(0), _curr_tdi(1) + _ir_bits_before(0), _ir_bits_after(0), _curr_tdi(0) { switch (cable.type) { case MODE_ANLOGICCABLE: @@ -347,7 +347,7 @@ void Jtag::go_test_logic_reset() _state = TEST_LOGIC_RESET; } -int Jtag::read_write(const uint8_t *tdi, unsigned char *tdo, int len, char last) +int Jtag::read_write(const uint8_t *tdi, unsigned char *tdo, uint32_t len, char last) { flushTMS(false); _jtag->writeTDI(tdi, tdo, len, last); diff --git a/src/jtag.hpp b/src/jtag.hpp index 3d9140950a..c921118672 100644 --- a/src/jtag.hpp +++ b/src/jtag.hpp @@ -117,11 +117,11 @@ class Jtag { tapState_t end_state = RUN_TEST_IDLE); int shiftDR(const uint8_t *tdi, unsigned char *tdo, int drlen, tapState_t end_state = RUN_TEST_IDLE); - int read_write(const uint8_t *tdi, unsigned char *tdo, int len, char last); + int read_write(const uint8_t *tdi, unsigned char *tdo, uint32_t len, char last); void toggleClk(int nb); void go_test_logic_reset(); - void set_state(tapState_t newState, const uint8_t tdi = 1); + void set_state(tapState_t newState, const uint8_t tdi = 0); int flushTMS(bool flush_buffer = false); void flush() {flushTMS(); _jtag->flush();} void setTMS(unsigned char tms); diff --git a/src/spiFlash.cpp b/src/spiFlash.cpp index 2ebed49be4..cac9cfee39 100644 --- a/src/spiFlash.cpp +++ b/src/spiFlash.cpp @@ -457,6 +457,57 @@ int SPIFlash::erase_and_prog(int base_addr, const uint8_t *data, int len) return 0; } +int SPIFlash::erase_and_prog2(int base_addr, const uint8_t *data, int len) +{ + printf("len: %d base_addr %08x\n", len, base_addr); + /* Now we can erase sector and write new data */ + ProgressBar progress("Writing", len, 50, _verbose < 0); + const uint8_t *ptr = data; + int size = 0; + uint8_t buffer[0x100]; + for (int sect_addr = 0; sect_addr < len; sect_addr += 0x1000) { + bool must_erase = true; + bool must_write = true; + bool all_same = true; + size = (sect_addr + 0x1000 > len)?(len-sect_addr) : 0x1000; + uint8_t first_c = ptr[0]; + for (int p = 1; p < size; p++) { + if (first_c != ptr[p]) { + all_same = false; + break; + } + } + if (all_same) { + must_erase = first_c == 0xff; + must_write = first_c == 0x00; + } + if (must_erase) { + /* erase 4K (ie 256B * 16 pages) */ + sector_erase(sect_addr); // erase 4K + } + for (int page_addr = 0; page_addr < 0x1000; page_addr += 0x100) { + + uint32_t addr = sect_addr + page_addr; + size = (addr + 256 > len)?(len-addr) : 256; + memset(buffer, 0xff, 0x100); + if (addr > len) { + memcpy(buffer, ptr, size); + ptr += size; + } + + printf("sect_addr %08x page_addr %08x addr %08x\n", sect_addr, page_addr, addr+base_addr); + if (must_write) { + if (write_page(addr + base_addr, buffer, 0x100) == -1) + return -1; + } + } + progress.display(sect_addr); + } + progress.done(); + + return 0; +} + bool SPIFlash::verify(const int &base_addr, const uint8_t *data, const int &len, int rd_burst) { diff --git a/src/spiFlash.hpp b/src/spiFlash.hpp index 2ef040b311..210ab6e608 100644 --- a/src/spiFlash.hpp +++ b/src/spiFlash.hpp @@ -80,6 +80,7 @@ class SPIFlash { const int &len, int rd_burst = 0); /* combo flash + erase */ int erase_and_prog(int base_addr, const uint8_t *data, int len); + int erase_and_prog2(int base_addr, const uint8_t *data, int len); /*! * \brief check if area base_addr to base_addr + len match * data content