gowin: add flash GW1N1 support

- eraseFlash need 65 x 32bits for GW1N1, 1 x 32bits for others
- improve flashFlash with delay according to the model
This commit is contained in:
Gwenhael Goavec-Merou 2020-05-23 14:51:48 +02:00
parent aa752856c3
commit 50fa17b62f
2 changed files with 60 additions and 12 deletions

View File

@ -64,7 +64,7 @@ using namespace std;
#define EFLASH_ERASE 0x75 #define EFLASH_ERASE 0x75
Gowin::Gowin(Jtag *jtag, const string filename, bool flash_wr, bool sram_wr, Gowin::Gowin(Jtag *jtag, const string filename, bool flash_wr, bool sram_wr,
bool verbose): Device(jtag, filename, verbose) bool verbose): Device(jtag, filename, verbose), is_gw1n1(false)
{ {
_fs = NULL; _fs = NULL;
if (_filename != "") { if (_filename != "") {
@ -82,6 +82,10 @@ Gowin::Gowin(Jtag *jtag, const string filename, bool flash_wr, bool sram_wr,
} }
} }
_jtag->setClkFreq(2500000, 0); _jtag->setClkFreq(2500000, 0);
/* erase and program flash differ for GW1N1 */
if (idCode() == 0x0900281B)
is_gw1n1 = true;
} }
Gowin::~Gowin() Gowin::~Gowin()
@ -98,6 +102,7 @@ void Gowin::reset()
void Gowin::programFlash() void Gowin::programFlash()
{ {
int status;
uint8_t *data; uint8_t *data;
int length; int length;
@ -126,8 +131,20 @@ void Gowin::programFlash()
return; return;
wr_rd(RELOAD, NULL, 0, NULL, 0); wr_rd(RELOAD, NULL, 0, NULL, 0);
wr_rd(NOOP, NULL, 0, NULL, 0); wr_rd(NOOP, NULL, 0, NULL, 0);
/* wait for reload */
usleep(150*1000);
/* check if file checksum == checksum in FPGA */
status = readUserCode();
if (_fs->checksum() != status) {
printError("SRAM Flash: FAIL");
printf("%04x %04x\n", _fs->checksum(), status);
} else
printSuccess("SRAM Flash: Success");
if (_verbose) if (_verbose)
printInfo("%08x\n", readUserCode()); displayReadReg(readStatusReg());
} }
void Gowin::program(unsigned int offset) void Gowin::program(unsigned int offset)
@ -320,7 +337,6 @@ bool Gowin::flashFLASH(uint8_t *data, int length)
uint8_t tt[39]; uint8_t tt[39];
bzero(tt, 39); bzero(tt, 39);
ProgressBar progress("Flash SRAM", byte_length, 50);
_jtag->go_test_logic_reset(); _jtag->go_test_logic_reset();
/* we have to send /* we have to send
@ -329,7 +345,6 @@ bool Gowin::flashFLASH(uint8_t *data, int length)
* full bitstream * full bitstream
*/ */
int buffer_length = byte_length+(6*4); int buffer_length = byte_length+(6*4);
unsigned char buffer[byte_length+(6*4)];
unsigned char bufvalues[]={ unsigned char bufvalues[]={
0x47, 0x57, 0x31, 0x4E, 0x47, 0x57, 0x31, 0x4E,
0xff, 0xff , 0xff, 0xff, 0xff, 0xff , 0xff, 0xff,
@ -337,16 +352,28 @@ bool Gowin::flashFLASH(uint8_t *data, int length)
0xff, 0xff , 0xff, 0xff, 0xff, 0xff , 0xff, 0xff,
0xff, 0xff , 0xff, 0xff, 0xff, 0xff , 0xff, 0xff,
0xff, 0xff , 0xff, 0xff}; 0xff, 0xff , 0xff, 0xff};
memcpy(buffer, bufvalues, sizeof bufvalues);
memcpy(buffer+6*4, data, byte_length);
int nb_xpage = buffer_length/256; int nb_xpage = buffer_length/256;
if (nb_xpage * 256 != buffer_length) if (nb_xpage * 256 != buffer_length) {
nb_xpage++; nb_xpage++;
buffer_length = nb_xpage * 256;
}
unsigned char buffer[buffer_length];
/* fill theorical size with 0xff */
memset(buffer, 0xff, buffer_length);
/* fill first page with code */
memcpy(buffer, bufvalues, 6*4);
/* bitstream just after opcode */
memcpy(buffer+6*4, data, byte_length);
ProgressBar progress("Flash SRAM", buffer_length, 50);
for (int i=0, xpage=0; xpage < nb_xpage; i+=(nb_iter*4), xpage++) { for (int i=0, xpage=0; xpage < nb_xpage; i+=(nb_iter*4), xpage++) {
wr_rd(CONFIG_ENABLE, NULL, 0, NULL, 0); wr_rd(CONFIG_ENABLE, NULL, 0, NULL, 0);
wr_rd(EF_PROGRAM, NULL, 0, NULL, 0); wr_rd(EF_PROGRAM, NULL, 0, NULL, 0);
if (xpage != 0)
_jtag->read_write(tt, NULL, 312, 0); _jtag->read_write(tt, NULL, 312, 0);
addr = xpage << 6; addr = xpage << 6;
tmp[3] = 0xff&(addr >> 24); tmp[3] = 0xff&(addr >> 24);
@ -367,8 +394,16 @@ bool Gowin::flashFLASH(uint8_t *data, int length)
for (int x=0; x < 4; x++) for (int x=0; x < 4; x++)
tx[3-x] = t[x]; tx[3-x] = t[x];
_jtag->shiftDR(tx, NULL, 32); _jtag->shiftDR(tx, NULL, 32);
if (!is_gw1n1)
_jtag->read_write(tt, NULL, 40, 0); _jtag->read_write(tt, NULL, 40, 0);
} }
if (is_gw1n1) {
//usleep(10*2400*2);
uint8_t tt2[6008/8];
memset(tt2, 0, 6008/8);
_jtag->read_write(tt2, tt2, 6008, 0);
}
progress.display(i); progress.display(i);
} }
/* 2.2.6.6 */ /* 2.2.6.6 */
@ -426,16 +461,28 @@ bool Gowin::flashSRAM(uint8_t *data, int length)
*/ */
bool Gowin::eraseFLASH() bool Gowin::eraseFLASH()
{ {
uint8_t tt[37500];
unsigned char tx[4] = {0, 0, 0, 0}; unsigned char tx[4] = {0, 0, 0, 0};
printInfo("erase Flash ", false); printInfo("erase Flash ", false);
wr_rd(EFLASH_ERASE, NULL, 0, NULL, 0); wr_rd(EFLASH_ERASE, NULL, 0, NULL, 0);
_jtag->set_state(Jtag::RUN_TEST_IDLE); _jtag->set_state(Jtag::RUN_TEST_IDLE);
//_jtag->read_write(tt, tt, 37500*8, 0);
/* GW1N1 need 65 x 32bits
* others 1 x 32bits
*/
int nb_iter = (is_gw1n1)?65:1;
for (int i = 0; i < nb_iter; i++) {
_jtag->shiftDR(tx, NULL, 32); _jtag->shiftDR(tx, NULL, 32);
/* TN653 specifies to wait for 120ms with _jtag->toggleClk(6);
}
/* TN653 specifies to wait for 160ms with
* there are no bit in status register to specify * there are no bit in status register to specify
* when this operation is done so we need to wait * when this operation is done so we need to wait
*/ */
usleep(120000); //usleep(2*120000);
//uint8_t tt[37500];
_jtag->read_write(tt, tt, 37500*8, 0);
printSuccess("Done"); printSuccess("Done");
return true; return true;
} }

View File

@ -52,5 +52,6 @@ class Gowin: public Device {
uint32_t readStatusReg(); uint32_t readStatusReg();
uint32_t readUserCode(); uint32_t readUserCode();
FsParser *_fs; FsParser *_fs;
bool is_gw1n1;
}; };
#endif // GOWIN_HPP_ #endif // GOWIN_HPP_