gowin: try again to fix gw5ast flash write
This commit is contained in:
parent
cd40de37cb
commit
a58f946ed5
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in New Issue