Merge pull request #243 from balika011/master

Gowin GW1NSR-4C MCU support
This commit is contained in:
Gwenhael Goavec-Merou 2022-07-25 19:09:01 +02:00 committed by GitHub
commit e77b8fb022
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 112 additions and 44 deletions

View File

@ -52,6 +52,8 @@ class Device {
virtual int idCode() = 0;
virtual void reset();
virtual bool connectJtagToMCU() {return false;}
protected:
Jtag *_jtag;
std::string _filename;

View File

@ -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 */
@ -73,7 +74,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),
@ -82,7 +83,9 @@ Gowin::Gowin(Jtag *jtag, const string filename, const string &file_type,
_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;
@ -153,12 +156,29 @@ 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");
_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()
{
if (_fs)
delete _fs;
if (_mcufw)
delete _mcufw;
}
void Gowin::reset()
@ -170,11 +190,17 @@ void Gowin::reset()
void Gowin::programFlash()
{
int status;
uint8_t *data;
int length;
data = _fs->getData();
length = _fs->getLength();
uint8_t *data = _fs->getData();
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 */
if (!EnableCfg())
@ -192,8 +218,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 +252,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 +463,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 +541,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 +564,13 @@ bool Gowin::flashFLASH(uint8_t *data, int length)
_jtag->set_state(Jtag::RUN_TEST_IDLE);
progress.done();
delete[] buffer;
return true;
}
bool Gowin::connectJtagToMCU()
{
wr_rd(SWITCH_TO_MCU_JTAG, NULL, 0, NULL, 0);
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();
@ -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 {
@ -48,7 +49,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 +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 */
ConfigBitstreamParser *_mcufw;
};
#endif // GOWIN_HPP_

View File

@ -78,6 +78,8 @@ struct arguments {
bool xvc;
int port;
string interface;
string mcufw;
bool conmcu;
};
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,
/*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,
@ -537,6 +539,10 @@ int main(int argc, char **argv)
}
}
if (args.conmcu == true) {
fpga->connectJtagToMCU();
}
/* unprotect SPI flash */
if (args.unprotect_flash && args.bit_file.empty()) {
fpga->unprotect_flash();
@ -721,6 +727,10 @@ 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))
("conmcu", "Connect JTAG to MCU",
cxxopts::value<bool>(args->conmcu))
("V,Version", "Print program version");
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->unprotect_flash &&
!args->xvc &&
!args->reset) {
!args->reset &&
!args->conmcu) {
printError("Error: bitfile not specified");
cout << options.help() << endl;
throw std::exception();