From 0581803def5d647386918ca9557d9974522ffcf9 Mon Sep 17 00:00:00 2001 From: balika011 Date: Wed, 20 Jul 2022 23:25:53 +0200 Subject: [PATCH 1/5] Add MCU Firmware flashing support for GW1NSR-4C --- src/gowin.cpp | 125 ++++++++++++++++++++++++++++++++++++-------------- src/gowin.hpp | 5 +- src/main.cpp | 5 +- 3 files changed, 97 insertions(+), 38 deletions(-) diff --git a/src/gowin.cpp b/src/gowin.cpp index 604ff7d..5b84762 100644 --- a/src/gowin.cpp +++ b/src/gowin.cpp @@ -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; } diff --git a/src/gowin.hpp b/src/gowin.hpp index d26889e..2ad9b32 100644 --- a/src/gowin.hpp +++ b/src/gowin.hpp @@ -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_ diff --git a/src/main.cpp b/src/main.cpp index 65f7d49..b4922a9 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -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(args->port)) + ("mcufw", "Microcontroller firmware", + cxxopts::value(args->mcufw)) ("V,Version", "Print program version"); options.parse_positional({"bitstream"}); From e847c3a7b09d623f08124ababe9572ae9580c509 Mon Sep 17 00:00:00 2001 From: balika011 Date: Wed, 20 Jul 2022 23:27:32 +0200 Subject: [PATCH 2/5] Add connecting MCU to JTAG support for GW1NSR-4C --- src/device.hpp | 2 ++ src/gowin.cpp | 7 +++++++ src/gowin.hpp | 1 + src/main.cpp | 13 ++++++++++++- 4 files changed, 22 insertions(+), 1 deletion(-) diff --git a/src/device.hpp b/src/device.hpp index 7295772..c913402 100644 --- a/src/device.hpp +++ b/src/device.hpp @@ -52,6 +52,8 @@ class Device { virtual int idCode() = 0; virtual void reset(); + virtual bool connectJtagToMCU() {return false;} + protected: Jtag *_jtag; std::string _filename; diff --git a/src/gowin.cpp b/src/gowin.cpp index 5b84762..f49f187 100644 --- a/src/gowin.cpp +++ b/src/gowin.cpp @@ -58,6 +58,7 @@ using namespace std; # define STATUS_FLASH_LOCK (1 << 17) #define EF_PROGRAM 0x71 #define EFLASH_ERASE 0x75 +#define SWITCH_TO_MCU_JTAG 0x7a /* BSCAN spi (external flash) (see below for details) */ /* most common pins def */ @@ -576,6 +577,12 @@ bool Gowin::flashFLASH(uint32_t page, uint8_t *data, int length) return true; } +bool Gowin::connectJtagToMCU() +{ + wr_rd(SWITCH_TO_MCU_JTAG, NULL, 0, NULL, 0); + return true; +} + /* TN653 p. 9 */ bool Gowin::flashSRAM(uint8_t *data, int length) { diff --git a/src/gowin.hpp b/src/gowin.hpp index 2ad9b32..707a081 100644 --- a/src/gowin.hpp +++ b/src/gowin.hpp @@ -26,6 +26,7 @@ class Gowin: public Device, SPIInterface { void reset() override; void program(unsigned int offset, bool unprotect_flash) override; void programFlash(); + bool connectJtagToMCU() override; /* spi interface */ virtual bool protect_flash(uint32_t len) override { diff --git a/src/main.cpp b/src/main.cpp index b4922a9..6b8fa6b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -79,6 +79,7 @@ struct arguments { int port; string interface; string mcufw; + bool conmcu; }; int run_xvc_server(const struct arguments &args, const cable_t &cable, @@ -538,6 +539,13 @@ int main(int argc, char **argv) } } + if (args.conmcu == true) { + fpga->connectJtagToMCU(); + delete(fpga); + delete(jtag); + return EXIT_SUCCESS; + } + /* unprotect SPI flash */ if (args.unprotect_flash && args.bit_file.empty()) { fpga->unprotect_flash(); @@ -716,6 +724,8 @@ int parse_opt(int argc, char **argv, struct arguments *args, jtag_pins_conf_t *p cxxopts::value(args->port)) ("mcufw", "Microcontroller firmware", cxxopts::value(args->mcufw)) + ("conmcu", "Connect JTAG to MCU", + cxxopts::value(args->conmcu)) ("V,Version", "Print program version"); options.parse_positional({"bitstream"}); @@ -846,7 +856,8 @@ int parse_opt(int argc, char **argv, struct arguments *args, jtag_pins_conf_t *p !args->protect_flash && !args->unprotect_flash && !args->xvc && - !args->reset) { + !args->reset && + !args->conmcu) { printError("Error: bitfile not specified"); cout << options.help() << endl; throw std::exception(); From c3d13e8b758c50ad3355b515cc808ea57851f6d3 Mon Sep 17 00:00:00 2001 From: balika011 Date: Sun, 24 Jul 2022 17:30:59 +0200 Subject: [PATCH 3/5] remove unneeded code --- src/main.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 6b8fa6b..4f8eb03 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -541,9 +541,6 @@ int main(int argc, char **argv) if (args.conmcu == true) { fpga->connectJtagToMCU(); - delete(fpga); - delete(jtag); - return EXIT_SUCCESS; } /* unprotect SPI flash */ From e44af8077630581be404a5250e30005a8e7e37fc Mon Sep 17 00:00:00 2001 From: balika011 Date: Sun, 24 Jul 2022 17:31:36 +0200 Subject: [PATCH 4/5] use RawParser for gowin mcu flashing --- src/gowin.cpp | 49 +++++++++++++++++++++---------------------------- src/gowin.hpp | 2 +- 2 files changed, 22 insertions(+), 29 deletions(-) diff --git a/src/gowin.cpp b/src/gowin.cpp index f49f187..1677dd6 100644 --- a/src/gowin.cpp +++ b/src/gowin.cpp @@ -83,7 +83,9 @@ Gowin::Gowin(Jtag *jtag, const string filename, const string &file_type, std::st _spi_msk(BSCAN_SPI_MSK) { _fs = NULL; - uint32_t idcode = _jtag->get_target_device_id();; + _mcufw = NULL; + + uint32_t idcode = _jtag->get_target_device_id(); if (prg_type == Device::WR_FLASH) _mode = Device::FLASH_MODE; @@ -159,23 +161,16 @@ Gowin::Gowin(Jtag *jtag, const string filename, const string &file_type, std::st 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); + _mcufw = new RawParser(mcufw, false); - mcufwdata.resize(file_size); + if (_mcufw->parse() == EXIT_FAILURE) { + printError("FAIL"); + delete _mcufw; + throw std::runtime_error("can't parse file"); + } else { + printSuccess("DONE"); + } - 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; } } @@ -184,6 +179,8 @@ Gowin::~Gowin() { if (_fs) delete _fs; + if (_mcufw) + delete _mcufw; } void Gowin::reset() @@ -195,20 +192,16 @@ void Gowin::reset() void Gowin::programFlash() { int status; - uint8_t *data; - int length; - uint8_t *mcu_data; - int mcu_length; - data = _fs->getData(); - length = _fs->getLength(); + uint8_t *data = _fs->getData(); + int 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; + uint8_t *mcu_data = nullptr; + int mcu_length = 0; + + if (_mcufw) { + mcu_data = _mcufw->getData(); + mcu_length = _mcufw->getLength(); } /* erase SRAM */ diff --git a/src/gowin.hpp b/src/gowin.hpp index 707a081..c628505 100644 --- a/src/gowin.hpp +++ b/src/gowin.hpp @@ -62,6 +62,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; + ConfigBitstreamParser *_mcufw; }; #endif // GOWIN_HPP_ From 421eefc605ef96a66fcfe7a4286f3e13822100aa Mon Sep 17 00:00:00 2001 From: balika011 Date: Sun, 24 Jul 2022 17:51:24 +0200 Subject: [PATCH 5/5] MCU firmware isn't added to the checksum --- src/gowin.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/gowin.cpp b/src/gowin.cpp index 1677dd6..1637146 100644 --- a/src/gowin.cpp +++ b/src/gowin.cpp @@ -170,8 +170,6 @@ Gowin::Gowin(Jtag *jtag, const string filename, const string &file_type, std::st } else { printSuccess("DONE"); } - - skip_checksum = true; } }