Add MCU Firmware flashing support for GW1NSR-4C

This commit is contained in:
balika011 2022-07-20 23:25:53 +02:00
parent 057ce931f8
commit 0581803def
3 changed files with 97 additions and 38 deletions

View File

@ -73,7 +73,7 @@ using namespace std;
#define BSCAN_GW1NSR_4C_SPI_DO (1 << 1)
#define BSCAN_GW1NSR_4C_SPI_MSK ((0x01 << 0))
Gowin::Gowin(Jtag *jtag, const string filename, const string &file_type,
Gowin::Gowin(Jtag *jtag, const string filename, const string &file_type, std::string mcufw,
Device::prog_type_t prg_type, bool external_flash,
bool verify, int8_t verbose): Device(jtag, filename, file_type,
verify, verbose), is_gw1n1(false), _external_flash(external_flash),
@ -153,6 +153,30 @@ Gowin::Gowin(Jtag *jtag, const string filename, const string &file_type,
/* FIXME: implement GW2 checksum calculation */
skip_checksum = true;
};
if (mcufw.size() > 0) {
if (idcode != 0x0100981b)
throw std::runtime_error("Microcontroller firmware flashing only supported on GW1NSR-4C");
FILE *fd = fopen(mcufw.c_str(), "rb");
if (!fd)
throw std::runtime_error("Error: fail to open " + filename);
fseek(fd, 0, SEEK_END);
int file_size = ftell(fd);
fseek(fd, 0, SEEK_SET);
mcufwdata.resize(file_size);
int ret = fread((char *) mcufwdata.data(), sizeof(char), file_size, fd);
fclose(fd);
if (ret != file_size)
throw std::runtime_error("Error: fail to read " + mcufw);
/* FIXME: implement checksum calculation */
skip_checksum = true;
}
}
Gowin::~Gowin()
@ -172,9 +196,19 @@ void Gowin::programFlash()
int status;
uint8_t *data;
int length;
uint8_t *mcu_data;
int mcu_length;
data = _fs->getData();
length = _fs->getLength();
if (mcufwdata.size() == 0) {
mcu_data = nullptr;
mcu_length = 0;
} else {
mcu_data = (uint8_t *) mcufwdata.data();
mcu_length = mcufwdata.size() * 8;
}
/* erase SRAM */
if (!EnableCfg())
@ -192,8 +226,12 @@ void Gowin::programFlash()
if (!DisableCfg())
return;
/* test status a faire */
if (!flashFLASH(data, length))
if (!flashFLASH(0, data, length))
return;
if (mcu_data) {
if (!flashFLASH(0x380, mcu_data, mcu_length))
return;
}
if (_verify)
printWarn("writing verification not supported");
if (!DisableCfg())
@ -222,8 +260,6 @@ void Gowin::programFlash()
void Gowin::program(unsigned int offset, bool unprotect_flash)
{
(void) offset;
uint8_t *data;
uint32_t status;
int length;
@ -435,55 +471,69 @@ bool Gowin::pollFlag(uint32_t mask, uint32_t value)
}
/* TN653 p. 17-21 */
bool Gowin::flashFLASH(uint8_t *data, int length)
bool Gowin::flashFLASH(uint32_t page, uint8_t *data, int length)
{
uint8_t tx[4] = {0x4E, 0x31, 0x57, 0x47};
uint8_t tmp[4];
uint32_t addr;
int nb_iter;
int byte_length = length / 8;
int buffer_length;
uint8_t *buffer;
int nb_xpage;
uint8_t tt[39];
memset(tt, 0, 39);
_jtag->go_test_logic_reset();
/* we have to send
* bootcode a X=0, Y=0 (4Bytes)
* 5 x 32 dummy bits
* full bitstream
*/
int buffer_length = byte_length+(6*4);
unsigned char bufvalues[]={
0x47, 0x57, 0x31, 0x4E,
0xff, 0xff , 0xff, 0xff,
0xff, 0xff , 0xff, 0xff,
0xff, 0xff , 0xff, 0xff,
0xff, 0xff , 0xff, 0xff,
0xff, 0xff , 0xff, 0xff};
if (page == 0) {
/* we have to send
* bootcode a X=0, Y=0 (4Bytes)
* 5 x 32 dummy bits
* full bitstream
*/
buffer_length = byte_length+(6*4);
unsigned char bufvalues[]={
0x47, 0x57, 0x31, 0x4E,
0xff, 0xff , 0xff, 0xff,
0xff, 0xff , 0xff, 0xff,
0xff, 0xff , 0xff, 0xff,
0xff, 0xff , 0xff, 0xff,
0xff, 0xff , 0xff, 0xff};
nb_xpage = buffer_length/256;
if (nb_xpage * 256 != buffer_length) {
nb_xpage++;
buffer_length = nb_xpage * 256;
}
int nb_xpage = buffer_length/256;
if (nb_xpage * 256 != buffer_length) {
nb_xpage++;
buffer_length = nb_xpage * 256;
buffer = new uint8_t[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);
} else {
buffer_length = byte_length;
nb_xpage = buffer_length/256;
if (nb_xpage * 256 != buffer_length) {
nb_xpage++;
buffer_length = nb_xpage * 256;
}
buffer = new uint8_t[buffer_length];
memset(buffer, 0xff, buffer_length);
memcpy(buffer, data, byte_length);
}
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("write Flash", buffer_length, 50, _quiet);
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(EF_PROGRAM, NULL, 0, NULL, 0);
if (xpage != 0)
if ((page + xpage) != 0)
_jtag->toggleClk(312);
addr = xpage << 6;
addr = (page + xpage) << 6;
tmp[3] = 0xff&(addr >> 24);
tmp[2] = 0xff&(addr >> 16);
tmp[1] = 0xff&(addr >> 8);
@ -499,8 +549,12 @@ bool Gowin::flashFLASH(uint8_t *data, int length)
for (int ypage = 0; ypage < nb_iter; ypage++) {
unsigned char *t = buffer+xoffset + 4*ypage;
for (int x=0; x < 4; x++)
tx[3-x] = t[x];
for (int x=0; x < 4; x++) {
if (page == 0)
tx[3-x] = t[x];
else
tx[x] = t[x];
}
_jtag->shiftDR(tx, NULL, 32);
if (!is_gw1n1)
@ -518,6 +572,7 @@ bool Gowin::flashFLASH(uint8_t *data, int length)
_jtag->set_state(Jtag::RUN_TEST_IDLE);
progress.done();
delete[] buffer;
return true;
}

View File

@ -18,7 +18,7 @@
class Gowin: public Device, SPIInterface {
public:
Gowin(Jtag *jtag, std::string filename, const std::string &file_type,
Gowin(Jtag *jtag, std::string filename, const std::string &file_type, std::string mcufw,
Device::prog_type_t prg_type, bool external_flash,
bool verify, int8_t verbose);
~Gowin();
@ -48,7 +48,7 @@ class Gowin: public Device, SPIInterface {
bool eraseSRAM();
bool eraseFLASH();
bool flashSRAM(uint8_t *data, int length);
bool flashFLASH(uint8_t *data, int length);
bool flashFLASH(uint32_t page, uint8_t *data, int length);
void displayReadReg(uint32_t dev);
uint32_t readStatusReg();
uint32_t readUserCode();
@ -61,5 +61,6 @@ class Gowin: public Device, SPIInterface {
uint8_t _spi_di; /**< di signal (mosi) 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 */
std::string mcufwdata;
};
#endif // GOWIN_HPP_

View File

@ -78,6 +78,7 @@ struct arguments {
bool xvc;
int port;
string interface;
string mcufw;
};
int run_xvc_server(const struct arguments &args, const cable_t &cable,
@ -506,7 +507,7 @@ int main(int argc, char **argv)
fpga = new Efinix(jtag, args.bit_file, args.file_type,
/*DBUS4 | DBUS7, DBUS5*/args.board, args.verify, args.verbose);
} else if (fab == "Gowin") {
fpga = new Gowin(jtag, args.bit_file, args.file_type,
fpga = new Gowin(jtag, args.bit_file, args.file_type, args.mcufw,
args.prg_type, args.external_flash, args.verify, args.verbose);
} else if (fab == "lattice") {
fpga = new Lattice(jtag, args.bit_file, args.file_type,
@ -713,6 +714,8 @@ int parse_opt(int argc, char **argv, struct arguments *args, jtag_pins_conf_t *p
#endif
("port", "Xilinx Virtual Cable Port (default 3721)",
cxxopts::value<int>(args->port))
("mcufw", "Microcontroller firmware",
cxxopts::value<std::string>(args->mcufw))
("V,Version", "Print program version");
options.parse_positional({"bitstream"});