openFPGALoader icon indicating copy to clipboard operation
openFPGALoader copied to clipboard

Issues flashing Tang Primer 25k with JTAG interfaces other than the usb jtag programmer on the dock board

Open josephpvincent opened this issue 7 months ago • 7 comments

Sorry for the repost - I posted with an incorrect github account originally and wanted to do this on the relevant account so I closed it and opened this one.

Hello!

I've been designing a board using the Tang Primer 25k module and have stumbled into some similar issues with flashing bitstreams:

Case 1: I have gpio pins coming from a Raspberry Pi 4 to use as JTAG using openfpgaloader and the libgpiod interface. I can identify the FPGA and "seemingly" flash the FPGA SRAM, but I always fail to flash to the external flash chip. Furthermore, it seems that flashing the SRAM is also not successful with this approach.

Case 2: I have then flashed a Pi pico with the dirty JTAG image to flash on my board disconnected from the Raspberry Pi 4. In this case, I can identify and seemingly both flash the SRAM and the external flash chip, but upon plugging into the Raspberry Pi 4, it's apparent that the image did not flash successfully to the external flash.

Case 3: As a total sanity check, I checked that I could successfully flash using the usb jtag programmer on the Tang Primer 25k dock board.

Case 4: I then tried to flash using the dirty JTAG implementation on the Pi Pico again, but this time through the Tang Primer 25k dock board, again this failed as it did in the case before. This implies to me that it's not an issue with the board itself, but possibly something with how Gowin flashing is implemented in OpenFPGALoader, does anyone have any tips or experience with this? The verify option fails and the DONE signal is never asserted when a successful flash is reported.

Output from Case 4:

sudo openFPGALoader -c dirtyJtag -f SipeedTang_AudioDSP.fs empty write to flash Jtag frequency : requested 6000000Hz -> real 6000000Hz Parse file Parse SipeedTang_AudioDSP.fs: Done DONE Jtag frequency : requested 2500000Hz -> real 2500000Hz after program flash: displayReadReg 70026020 [ 5] Memory Erase [13] Done Final [14] Security Final [17] sspi_mode [24:23] CPU Bus Width: no BWD pattern is detected [26:25] Retry time sync pattern detect: no retry [28] OTP Reading Done [29] Init Done [30] Wakeup Done Erase SRAM DONE Jtag frequency : requested 10000000Hz -> real 10000000Hz Detail: Jedec ID : 0b memory type : 40 memory capacity : 17 Detail: Jedec ID : 0b memory type : 40 memory capacity : 17 RDSR : 0x00 WIP : 0 WEL : 0 BP : 0 TB : 0 SRWD : 0 flash chip unknown: use basic protection detection start addr: 00000000, end_addr: 000c0000 Erasing: [==================================================] 100.00% Done Writing: [==================================================] 100.00% Done

And here's with verbose output:

sudo openFPGALoader -c dirtyJtag --verbose-level=2 --freq 1000000 -b tangprimer25k -f SipeedTang_AudioDSP.fs empty write to flash Board default cable overridden with dirtyJtag Jtag frequency : requested 1000000Hz -> real 1000000Hz Raw IDCODE:

  • 0 -> 0x0001281b
  • 1 -> 0xffffffff Fetched TDI, end-of-chain found 1 devices index 0: idcode 0x1281b manufacturer Gowin family GW5A model GW5A-25 irlength 8 File type : fs Parse file Parse SipeedTang_AudioDSP.fs: checksum 0x6570 Done DONE bitstream header infos CRCCheck: ON Compress: OFF ConfDataLength: 11072 LoadingRate: 6944444 ProgramDoneBypass: OFF SPIAddr: 00000000 SecurityBit: ON idcode: 0001281b Jtag frequency : requested 2500000Hz -> real 2500000Hz Before disable SPI mode: displayReadReg 30004460 [ 5] Memory Erase [ 6] Preamble [10] Non-JTAG configuration is active [14] Security Final [24:23] CPU Bus Width: no BWD pattern is detected [26:25] Retry time sync pattern detect: no retry [28] OTP Reading Done [29] Init Done pollFlag: 30004460 (0) after program flash: displayReadReg 30004460 [ 5] Memory Erase [ 6] Preamble [10] Non-JTAG configuration is active [14] Security Final [24:23] CPU Bus Width: no BWD pattern is detected [26:25] Retry time sync pattern detect: no retry [28] OTP Reading Done [29] Init Done Erase SRAM before erase sram: displayReadReg 30004460 [ 5] Memory Erase [ 6] Preamble [10] Non-JTAG configuration is active [14] Security Final [24:23] CPU Bus Width: no BWD pattern is detected [26:25] Retry time sync pattern detect: no retry [28] OTP Reading Done [29] Init Done pollFlag: 300040a0 (80) pollFlag: 30004080 (0) pollFlag: 30004080 (0) pollFlag: 30004080 (0) pollFlag: 300000a0 (20) after erase sram: displayReadReg 300000a0 [ 5] Memory Erase [ 7] System Edit Mode [24:23] CPU Bus Width: no BWD pattern is detected [26:25] Retry time sync pattern detect: no retry [28] OTP Reading Done [29] Init Done pollFlag: 30000020 (0) pollFlag: 300000a0 (80) pollFlag: 30000080 (0) pollFlag: 30000080 (0) pollFlag: 30000080 (0) pollFlag: 300000a0 (20) after erase sram: displayReadReg 300000a0 [ 5] Memory Erase [ 7] System Edit Mode [24:23] CPU Bus Width: no BWD pattern is detected [26:25] Retry time sync pattern detect: no retry [28] OTP Reading Done [29] Init Done pollFlag: 30000020 (0) after erase sram: displayReadReg 30000020 [ 5] Memory Erase [24:23] CPU Bus Width: no BWD pattern is detected [26:25] Retry time sync pattern detect: no retry [28] OTP Reading Done [29] Init Done DONE pollFlag: 320040a0 (80) pollFlag: 92004000 (0) toto: displayReadReg 92004000 [14] Security Final [24:23] CPU Bus Width: no BWD pattern is detected [26:25] Retry time sync pattern detect: retry one time [28] OTP Reading Done [31] Auto Erase Jtag frequency : requested 10000000Hz -> real 10000000Hz b 40 17 8 read b401708 Detail: Jedec ID : 0b memory type : 40 memory capacity : 17 b 40 17 f read b40170f Detail: Jedec ID : 0b memory type : 40 memory capacity : 17 RDSR : 0x00 WIP : 0 WEL : 0 BP : 0 TB : 0 SRWD : 0 RDSR : 0x00 WIP : 0 WEL : 0 BP : 0 TB : 0 SRWD : 0 flash chip unknown: use basic protection detection start addr: 00000000, end_addr: 000c0000 Erasing: [==================================================] 100.00% Done Writing: [==================================================] 100.00% Done

Oddly in this last case I do notice that the requested JTAG frequency is not respected as programming goes on, so maybe this is a hint.

josephpvincent avatar Jun 03 '25 22:06 josephpvincent

I've started to dig into the gowin.cpp file to follow along. Everything looks like it should and I'm not sure why this would be different using dirty jtag versus the FTDI emulation they have on their microcontroller. I wonder if it would be worth looking to see if inserting any delays makes a difference. I do notice some interesting behavior where the FPGA will quickly flash DONE before turning setting it low, so I wonder if it's just a general timing issue when not using a FTDI device.

josephpvincent avatar Jun 04 '25 01:06 josephpvincent

Here's also a verbose output using the usb to jtag on the primer 25k dock during a successful flash:

sudo openFPGALoader --verbose-level 2 -b tangprimer25k -f SipeedTang_AudioDSP.fs empty write to flash Jtag frequency : requested 6.00MHz -> real 6.00MHz
Raw IDCODE:

  • 0 -> 0x0001281b
  • 1 -> 0xffffffff Fetched TDI, end-of-chain found 1 devices index 0: idcode 0x1281b manufacturer Gowin family GW5A model GW5A-25 irlength 8 File type : fs Parse file Parse SipeedTang_AudioDSP.fs: checksum 0x6570 Done DONE bitstream header infos CRCCheck: ON Compress: OFF ConfDataLength: 11072 LoadingRate: 6944444 ProgramDoneBypass: OFF SPIAddr: 00000000 SecurityBit: ON idcode: 0001281b Jtag frequency : requested 2.50MHz -> real 2.50MHz
    Before disable SPI mode: displayReadReg 16020238 [ 3] Timeout [ 4] auto_boot_2nd_fail [ 5] Memory Erase [ 9] auto_boot_1st_fail [17] sspi_mode [24:23] CPU Bus Width: no BWD pattern is detected [26:25] Retry time sync pattern detect: no "sync pattern" is found after three times detection [28] OTP Reading Done pollFlag: 16020238 (0) after program flash: displayReadReg 16020238 [ 3] Timeout [ 4] auto_boot_2nd_fail [ 5] Memory Erase [ 9] auto_boot_1st_fail [17] sspi_mode [24:23] CPU Bus Width: no BWD pattern is detected [26:25] Retry time sync pattern detect: no "sync pattern" is found after three times detection [28] OTP Reading Done Erase SRAM before erase sram: displayReadReg 16020238 [ 3] Timeout [ 4] auto_boot_2nd_fail [ 5] Memory Erase [ 9] auto_boot_1st_fail [17] sspi_mode [24:23] CPU Bus Width: no BWD pattern is detected [26:25] Retry time sync pattern detect: no "sync pattern" is found after three times detection [28] OTP Reading Done pollFlag: 96000298 (80) pollFlag: 96000298 (0) pollFlag: 96000298 (0) pollFlag: 96000298 (0) pollFlag: 360002b8 (20) after erase sram: displayReadReg 360002b8 [ 3] Timeout [ 4] auto_boot_2nd_fail [ 5] Memory Erase [ 7] System Edit Mode [ 9] auto_boot_1st_fail [24:23] CPU Bus Width: no BWD pattern is detected [26:25] Retry time sync pattern detect: no "sync pattern" is found after three times detection [28] OTP Reading Done [29] Init Done pollFlag: 36020238 (0) pollFlag: 360002b8 (80) pollFlag: 36000298 (0) pollFlag: 36000298 (0) pollFlag: 36000298 (0) pollFlag: 36000298 (0) pollFlag: 36000298 (0) pollFlag: 36000298 (0) pollFlag: 36000298 (0) pollFlag: 36000298 (0) pollFlag: 36000298 (0) pollFlag: 36000298 (0) pollFlag: 360002b8 (20) after erase sram: displayReadReg 360002b8 [ 3] Timeout [ 4] auto_boot_2nd_fail [ 5] Memory Erase [ 7] System Edit Mode [ 9] auto_boot_1st_fail [24:23] CPU Bus Width: no BWD pattern is detected [26:25] Retry time sync pattern detect: no "sync pattern" is found after three times detection [28] OTP Reading Done [29] Init Done pollFlag: 36020238 (0) after erase sram: displayReadReg 36020238 [ 3] Timeout [ 4] auto_boot_2nd_fail [ 5] Memory Erase [ 9] auto_boot_1st_fail [17] sspi_mode [24:23] CPU Bus Width: no BWD pattern is detected [26:25] Retry time sync pattern detect: no "sync pattern" is found after three times detection [28] OTP Reading Done [29] Init Done DONE pollFlag: 360002b8 (80) pollFlag: 96020218 (0) toto: displayReadReg 96020218 [ 3] Timeout [ 4] auto_boot_2nd_fail [ 9] auto_boot_1st_fail [17] sspi_mode [24:23] CPU Bus Width: no BWD pattern is detected [26:25] Retry time sync pattern detect: no "sync pattern" is found after three times detection [28] OTP Reading Done [31] Auto Erase Jtag frequency : requested 10.00MHz -> real 10.00MHz
    b 40 17 b read b40170b Detail: Jedec ID : 0b memory type : 40 memory capacity : 17 b 40 17 b read b40170b Detail: Jedec ID : 0b memory type : 40 memory capacity : 17 RDSR : 0x00 WIP : 0 WEL : 0 BP : 0 TB : 0 SRWD : 0 RDSR : 0x00 WIP : 0 WEL : 0 BP : 0 TB : 0 SRWD : 0 flash chip unknown: use basic protection detection start addr: 00000000, end_addr: 000c0000 Erasing: [==================================================] 100.00% Done Writing: [==================================================] 100.00% Done

Some notes - 16020238 status is read before disable SPI mode which is different than what's read above.

Looking at the poll flag prints, we also have different values: pollFlag: 36020238 (0) pollFlag: 360002b8 (80) pollFlag: 36000298 (0) pollFlag: 36000298 (0) pollFlag: 36000298 (0) pollFlag: 36000298 (0) pollFlag: 36000298 (0) pollFlag: 36000298 (0) pollFlag: 36000298 (0) pollFlag: 36000298 (0) pollFlag: 36000298 (0) pollFlag: 36000298 (0) pollFlag: 360002b8 (20)

It also seems that there are more pollflag prints here which is interesting, not sure why that would be but it indicates to me that a different routine is being called potentially.

The Toto displayreadreg line also is different: toto: displayReadReg 96020218

Seems like some valid points to consider. I don't have much time at the moment to break this down and look at the status register reads line per line, but this is probably indicating what is/isn't working here.

I'll look into this more later and give any insight found, but would be very happy if somebody with experience either implementing or debugging this could chime in.

josephpvincent avatar Jun 04 '25 21:06 josephpvincent

The strange thing is with all cables the Flash is correctly detected and updated. Yes maybe timings are wrong due to static/fixed frequencies but with libgpiod frequency are slower than ftdi. I have a tang Primer 25K and will try to disable onboard interface to uses a dirtyJTAG to see why this is not working.

Thanks!

trabucayre avatar Jun 08 '25 05:06 trabucayre

The strange thing is with all cables the Flash is correctly detected and updated. Yes maybe timings are wrong due to static/fixed frequencies but with libgpiod frequency are slower than ftdi. I have a tang Primer 25K and will try to disable onboard interface to uses a dirtyJTAG to see why this is not working.

Thanks!

Thank you! It is very strange.

Note that with the libgpiod flash it’s not able to use the SPI flash on board. I did not post a log of that up.

josephpvincent avatar Jun 08 '25 21:06 josephpvincent

Adding that I just tried the Gowin gwu2x JTAG with success. Also tried an FT232H board which could identify the FPGA but failed to flash and hanged.

josephpvincent avatar Jun 08 '25 22:06 josephpvincent

Strange: I have tested with an esp32s3 (see #501) without any issues. Another weird thing: I observes some errors at libftdi level with digilent_hs2.

trabucayre avatar Jun 10 '25 13:06 trabucayre

I'm running into a similar issue. I have a custom board that I designed myself that has an RP2350A with dirtypicojtag ported to it. I'm able to write to the SRAM of the FPGA using openfpgaloader.

However, openfpgaloader refuses to write to the SPI flash saying it's write protected which is not the case at all. The chip is a GW5A-EV25PG256CC1/I0.

cyo-the-vile avatar Nov 20 '25 22:11 cyo-the-vile