Merge pull request #243 from balika011/master
Gowin GW1NSR-4C MCU support
This commit is contained in:
commit
e77b8fb022
|
|
@ -52,6 +52,8 @@ class Device {
|
||||||
virtual int idCode() = 0;
|
virtual int idCode() = 0;
|
||||||
virtual void reset();
|
virtual void reset();
|
||||||
|
|
||||||
|
virtual bool connectJtagToMCU() {return false;}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Jtag *_jtag;
|
Jtag *_jtag;
|
||||||
std::string _filename;
|
std::string _filename;
|
||||||
|
|
|
||||||
133
src/gowin.cpp
133
src/gowin.cpp
|
|
@ -58,6 +58,7 @@ using namespace std;
|
||||||
# define STATUS_FLASH_LOCK (1 << 17)
|
# define STATUS_FLASH_LOCK (1 << 17)
|
||||||
#define EF_PROGRAM 0x71
|
#define EF_PROGRAM 0x71
|
||||||
#define EFLASH_ERASE 0x75
|
#define EFLASH_ERASE 0x75
|
||||||
|
#define SWITCH_TO_MCU_JTAG 0x7a
|
||||||
|
|
||||||
/* BSCAN spi (external flash) (see below for details) */
|
/* BSCAN spi (external flash) (see below for details) */
|
||||||
/* most common pins def */
|
/* most common pins def */
|
||||||
|
|
@ -73,7 +74,7 @@ using namespace std;
|
||||||
#define BSCAN_GW1NSR_4C_SPI_DO (1 << 1)
|
#define BSCAN_GW1NSR_4C_SPI_DO (1 << 1)
|
||||||
#define BSCAN_GW1NSR_4C_SPI_MSK ((0x01 << 0))
|
#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,
|
Device::prog_type_t prg_type, bool external_flash,
|
||||||
bool verify, int8_t verbose): Device(jtag, filename, file_type,
|
bool verify, int8_t verbose): Device(jtag, filename, file_type,
|
||||||
verify, verbose), is_gw1n1(false), _external_flash(external_flash),
|
verify, verbose), is_gw1n1(false), _external_flash(external_flash),
|
||||||
|
|
@ -82,7 +83,9 @@ Gowin::Gowin(Jtag *jtag, const string filename, const string &file_type,
|
||||||
_spi_msk(BSCAN_SPI_MSK)
|
_spi_msk(BSCAN_SPI_MSK)
|
||||||
{
|
{
|
||||||
_fs = NULL;
|
_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)
|
if (prg_type == Device::WR_FLASH)
|
||||||
_mode = Device::FLASH_MODE;
|
_mode = Device::FLASH_MODE;
|
||||||
|
|
@ -153,12 +156,29 @@ Gowin::Gowin(Jtag *jtag, const string filename, const string &file_type,
|
||||||
/* FIXME: implement GW2 checksum calculation */
|
/* FIXME: implement GW2 checksum calculation */
|
||||||
skip_checksum = true;
|
skip_checksum = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (mcufw.size() > 0) {
|
||||||
|
if (idcode != 0x0100981b)
|
||||||
|
throw std::runtime_error("Microcontroller firmware flashing only supported on GW1NSR-4C");
|
||||||
|
|
||||||
|
_mcufw = new RawParser(mcufw, false);
|
||||||
|
|
||||||
|
if (_mcufw->parse() == EXIT_FAILURE) {
|
||||||
|
printError("FAIL");
|
||||||
|
delete _mcufw;
|
||||||
|
throw std::runtime_error("can't parse file");
|
||||||
|
} else {
|
||||||
|
printSuccess("DONE");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Gowin::~Gowin()
|
Gowin::~Gowin()
|
||||||
{
|
{
|
||||||
if (_fs)
|
if (_fs)
|
||||||
delete _fs;
|
delete _fs;
|
||||||
|
if (_mcufw)
|
||||||
|
delete _mcufw;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Gowin::reset()
|
void Gowin::reset()
|
||||||
|
|
@ -170,11 +190,17 @@ void Gowin::reset()
|
||||||
void Gowin::programFlash()
|
void Gowin::programFlash()
|
||||||
{
|
{
|
||||||
int status;
|
int status;
|
||||||
uint8_t *data;
|
|
||||||
int length;
|
|
||||||
|
|
||||||
data = _fs->getData();
|
uint8_t *data = _fs->getData();
|
||||||
length = _fs->getLength();
|
int length = _fs->getLength();
|
||||||
|
|
||||||
|
uint8_t *mcu_data = nullptr;
|
||||||
|
int mcu_length = 0;
|
||||||
|
|
||||||
|
if (_mcufw) {
|
||||||
|
mcu_data = _mcufw->getData();
|
||||||
|
mcu_length = _mcufw->getLength();
|
||||||
|
}
|
||||||
|
|
||||||
/* erase SRAM */
|
/* erase SRAM */
|
||||||
if (!EnableCfg())
|
if (!EnableCfg())
|
||||||
|
|
@ -192,8 +218,12 @@ void Gowin::programFlash()
|
||||||
if (!DisableCfg())
|
if (!DisableCfg())
|
||||||
return;
|
return;
|
||||||
/* test status a faire */
|
/* test status a faire */
|
||||||
if (!flashFLASH(data, length))
|
if (!flashFLASH(0, data, length))
|
||||||
return;
|
return;
|
||||||
|
if (mcu_data) {
|
||||||
|
if (!flashFLASH(0x380, mcu_data, mcu_length))
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (_verify)
|
if (_verify)
|
||||||
printWarn("writing verification not supported");
|
printWarn("writing verification not supported");
|
||||||
if (!DisableCfg())
|
if (!DisableCfg())
|
||||||
|
|
@ -222,8 +252,6 @@ void Gowin::programFlash()
|
||||||
|
|
||||||
void Gowin::program(unsigned int offset, bool unprotect_flash)
|
void Gowin::program(unsigned int offset, bool unprotect_flash)
|
||||||
{
|
{
|
||||||
(void) offset;
|
|
||||||
|
|
||||||
uint8_t *data;
|
uint8_t *data;
|
||||||
uint32_t status;
|
uint32_t status;
|
||||||
int length;
|
int length;
|
||||||
|
|
@ -435,55 +463,69 @@ bool Gowin::pollFlag(uint32_t mask, uint32_t value)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TN653 p. 17-21 */
|
/* 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 tx[4] = {0x4E, 0x31, 0x57, 0x47};
|
||||||
uint8_t tmp[4];
|
uint8_t tmp[4];
|
||||||
uint32_t addr;
|
uint32_t addr;
|
||||||
int nb_iter;
|
int nb_iter;
|
||||||
int byte_length = length / 8;
|
int byte_length = length / 8;
|
||||||
|
int buffer_length;
|
||||||
|
uint8_t *buffer;
|
||||||
|
int nb_xpage;
|
||||||
uint8_t tt[39];
|
uint8_t tt[39];
|
||||||
memset(tt, 0, 39);
|
memset(tt, 0, 39);
|
||||||
|
|
||||||
_jtag->go_test_logic_reset();
|
_jtag->go_test_logic_reset();
|
||||||
|
|
||||||
/* we have to send
|
if (page == 0) {
|
||||||
* bootcode a X=0, Y=0 (4Bytes)
|
/* we have to send
|
||||||
* 5 x 32 dummy bits
|
* bootcode a X=0, Y=0 (4Bytes)
|
||||||
* full bitstream
|
* 5 x 32 dummy bits
|
||||||
*/
|
* full bitstream
|
||||||
int buffer_length = byte_length+(6*4);
|
*/
|
||||||
unsigned char bufvalues[]={
|
buffer_length = byte_length+(6*4);
|
||||||
0x47, 0x57, 0x31, 0x4E,
|
unsigned char bufvalues[]={
|
||||||
0xff, 0xff , 0xff, 0xff,
|
0x47, 0x57, 0x31, 0x4E,
|
||||||
0xff, 0xff , 0xff, 0xff,
|
0xff, 0xff , 0xff, 0xff,
|
||||||
0xff, 0xff , 0xff, 0xff,
|
0xff, 0xff , 0xff, 0xff,
|
||||||
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;
|
buffer = new uint8_t[buffer_length];
|
||||||
if (nb_xpage * 256 != buffer_length) {
|
/* fill theorical size with 0xff */
|
||||||
nb_xpage++;
|
memset(buffer, 0xff, buffer_length);
|
||||||
buffer_length = nb_xpage * 256;
|
/* 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);
|
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(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)
|
if ((page + xpage) != 0)
|
||||||
_jtag->toggleClk(312);
|
_jtag->toggleClk(312);
|
||||||
addr = xpage << 6;
|
addr = (page + xpage) << 6;
|
||||||
tmp[3] = 0xff&(addr >> 24);
|
tmp[3] = 0xff&(addr >> 24);
|
||||||
tmp[2] = 0xff&(addr >> 16);
|
tmp[2] = 0xff&(addr >> 16);
|
||||||
tmp[1] = 0xff&(addr >> 8);
|
tmp[1] = 0xff&(addr >> 8);
|
||||||
|
|
@ -499,8 +541,12 @@ bool Gowin::flashFLASH(uint8_t *data, int length)
|
||||||
|
|
||||||
for (int ypage = 0; ypage < nb_iter; ypage++) {
|
for (int ypage = 0; ypage < nb_iter; ypage++) {
|
||||||
unsigned char *t = buffer+xoffset + 4*ypage;
|
unsigned char *t = buffer+xoffset + 4*ypage;
|
||||||
for (int x=0; x < 4; x++)
|
for (int x=0; x < 4; x++) {
|
||||||
tx[3-x] = t[x];
|
if (page == 0)
|
||||||
|
tx[3-x] = t[x];
|
||||||
|
else
|
||||||
|
tx[x] = t[x];
|
||||||
|
}
|
||||||
_jtag->shiftDR(tx, NULL, 32);
|
_jtag->shiftDR(tx, NULL, 32);
|
||||||
|
|
||||||
if (!is_gw1n1)
|
if (!is_gw1n1)
|
||||||
|
|
@ -518,6 +564,13 @@ bool Gowin::flashFLASH(uint8_t *data, int length)
|
||||||
_jtag->set_state(Jtag::RUN_TEST_IDLE);
|
_jtag->set_state(Jtag::RUN_TEST_IDLE);
|
||||||
|
|
||||||
progress.done();
|
progress.done();
|
||||||
|
delete[] buffer;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Gowin::connectJtagToMCU()
|
||||||
|
{
|
||||||
|
wr_rd(SWITCH_TO_MCU_JTAG, NULL, 0, NULL, 0);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@
|
||||||
|
|
||||||
class Gowin: public Device, SPIInterface {
|
class Gowin: public Device, SPIInterface {
|
||||||
public:
|
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,
|
Device::prog_type_t prg_type, bool external_flash,
|
||||||
bool verify, int8_t verbose);
|
bool verify, int8_t verbose);
|
||||||
~Gowin();
|
~Gowin();
|
||||||
|
|
@ -26,6 +26,7 @@ class Gowin: public Device, SPIInterface {
|
||||||
void reset() override;
|
void reset() override;
|
||||||
void program(unsigned int offset, bool unprotect_flash) override;
|
void program(unsigned int offset, bool unprotect_flash) override;
|
||||||
void programFlash();
|
void programFlash();
|
||||||
|
bool connectJtagToMCU() override;
|
||||||
|
|
||||||
/* spi interface */
|
/* spi interface */
|
||||||
virtual bool protect_flash(uint32_t len) override {
|
virtual bool protect_flash(uint32_t len) override {
|
||||||
|
|
@ -48,7 +49,7 @@ class Gowin: public Device, SPIInterface {
|
||||||
bool eraseSRAM();
|
bool eraseSRAM();
|
||||||
bool eraseFLASH();
|
bool eraseFLASH();
|
||||||
bool flashSRAM(uint8_t *data, int length);
|
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);
|
void displayReadReg(uint32_t dev);
|
||||||
uint32_t readStatusReg();
|
uint32_t readStatusReg();
|
||||||
uint32_t readUserCode();
|
uint32_t readUserCode();
|
||||||
|
|
@ -61,5 +62,6 @@ class Gowin: public Device, SPIInterface {
|
||||||
uint8_t _spi_di; /**< di signal (mosi) offset in bscan SPI */
|
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_do; /**< do signal (miso) offset in bscan SPI */
|
||||||
uint8_t _spi_msk; /** default spi msk with only do out */
|
uint8_t _spi_msk; /** default spi msk with only do out */
|
||||||
|
ConfigBitstreamParser *_mcufw;
|
||||||
};
|
};
|
||||||
#endif // GOWIN_HPP_
|
#endif // GOWIN_HPP_
|
||||||
|
|
|
||||||
15
src/main.cpp
15
src/main.cpp
|
|
@ -78,6 +78,8 @@ struct arguments {
|
||||||
bool xvc;
|
bool xvc;
|
||||||
int port;
|
int port;
|
||||||
string interface;
|
string interface;
|
||||||
|
string mcufw;
|
||||||
|
bool conmcu;
|
||||||
};
|
};
|
||||||
|
|
||||||
int run_xvc_server(const struct arguments &args, const cable_t &cable,
|
int run_xvc_server(const struct arguments &args, const cable_t &cable,
|
||||||
|
|
@ -506,7 +508,7 @@ int main(int argc, char **argv)
|
||||||
fpga = new Efinix(jtag, args.bit_file, args.file_type,
|
fpga = new Efinix(jtag, args.bit_file, args.file_type,
|
||||||
/*DBUS4 | DBUS7, DBUS5*/args.board, args.verify, args.verbose);
|
/*DBUS4 | DBUS7, DBUS5*/args.board, args.verify, args.verbose);
|
||||||
} else if (fab == "Gowin") {
|
} 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);
|
args.prg_type, args.external_flash, args.verify, args.verbose);
|
||||||
} else if (fab == "lattice") {
|
} else if (fab == "lattice") {
|
||||||
fpga = new Lattice(jtag, args.bit_file, args.file_type,
|
fpga = new Lattice(jtag, args.bit_file, args.file_type,
|
||||||
|
|
@ -537,6 +539,10 @@ int main(int argc, char **argv)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (args.conmcu == true) {
|
||||||
|
fpga->connectJtagToMCU();
|
||||||
|
}
|
||||||
|
|
||||||
/* unprotect SPI flash */
|
/* unprotect SPI flash */
|
||||||
if (args.unprotect_flash && args.bit_file.empty()) {
|
if (args.unprotect_flash && args.bit_file.empty()) {
|
||||||
fpga->unprotect_flash();
|
fpga->unprotect_flash();
|
||||||
|
|
@ -721,6 +727,10 @@ int parse_opt(int argc, char **argv, struct arguments *args, jtag_pins_conf_t *p
|
||||||
#endif
|
#endif
|
||||||
("port", "Xilinx Virtual Cable Port (default 3721)",
|
("port", "Xilinx Virtual Cable Port (default 3721)",
|
||||||
cxxopts::value<int>(args->port))
|
cxxopts::value<int>(args->port))
|
||||||
|
("mcufw", "Microcontroller firmware",
|
||||||
|
cxxopts::value<std::string>(args->mcufw))
|
||||||
|
("conmcu", "Connect JTAG to MCU",
|
||||||
|
cxxopts::value<bool>(args->conmcu))
|
||||||
("V,Version", "Print program version");
|
("V,Version", "Print program version");
|
||||||
|
|
||||||
options.parse_positional({"bitstream"});
|
options.parse_positional({"bitstream"});
|
||||||
|
|
@ -845,7 +855,8 @@ int parse_opt(int argc, char **argv, struct arguments *args, jtag_pins_conf_t *p
|
||||||
!args->protect_flash &&
|
!args->protect_flash &&
|
||||||
!args->unprotect_flash &&
|
!args->unprotect_flash &&
|
||||||
!args->xvc &&
|
!args->xvc &&
|
||||||
!args->reset) {
|
!args->reset &&
|
||||||
|
!args->conmcu) {
|
||||||
printError("Error: bitfile not specified");
|
printError("Error: bitfile not specified");
|
||||||
cout << options.help() << endl;
|
cout << options.help() << endl;
|
||||||
throw std::exception();
|
throw std::exception();
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue