build/gowin/programmer: refactor for enhanced functionality

- Supports exflash
- Use devname info for embflash or exflash
- Allow customize operation mode via pmode
This commit is contained in:
Andelf 2024-12-21 03:53:06 +08:00
parent 8254a349f8
commit 3b19bcd583
1 changed files with 52 additions and 29 deletions

View File

@ -9,13 +9,19 @@ import sys
from shutil import which from shutil import which
from litex.build.generic_programmer import GenericProgrammer from litex.build.generic_programmer import GenericProgrammer
from litex.build import tools
# GowinProgrammer ---------------------------------------------------------------------------------- # GowinProgrammer ----------------------------------------------------------------------------------
GOWIN_PMODE_SRAM = 4 # SRAM Program
GOWIN_PMODE_SRAM = 2
# SRAM Program JTAG 1149
GOWIN_PMODE_SRAM_JTAG = 16
# embFlash Erase,Program
GOWIN_PMODE_EMBFLASH = 5 GOWIN_PMODE_EMBFLASH = 5
GOWIN_PMODE_EXTFLASH = 31 # for bin # exFlash C Bin Erase,Program thru GAO-Bridge
GOWIN_PMODE_EXFLASH_BIN = 38
# exFlash Erase,Program thru GAO-Bridge
GOWIN_PMODE_EXFLASH = 36
GOWIN_CABLE_GWU2X = 0 GOWIN_CABLE_GWU2X = 0
GOWIN_CABLE_FT2CH = 1 GOWIN_CABLE_FT2CH = 1
@ -26,8 +32,12 @@ GOWIN_CABLE_FT2CH = 1
class GowinProgrammer(GenericProgrammer): class GowinProgrammer(GenericProgrammer):
needs_bitreverse = False needs_bitreverse = False
def __init__(self, devname): def __init__(self, devname, cable = GOWIN_CABLE_FT2CH):
self.device = str(devname) self.device = str(devname)
self.cable = cable
# Ref: Gowin Programmer User Guide https://cdn.gowinsemi.com.cn/SUG502E.pdf
self.has_embflash = self.device.startswith("GN1N")
# windows/powershell or msys2 # windows/powershell or msys2
self.is_win32 = True if sys.platform == "win32" else False self.is_win32 = True if sys.platform == "win32" else False
@ -50,42 +60,55 @@ class GowinProgrammer(GenericProgrammer):
# follow the help information: # follow the help information:
# 1. Gowin programmer does not support start address for embflash! # 1. Gowin programmer does not support start address for embflash!
# 2. External SPI FLASH programming is also not detailed (for programmer_cli) # 2. Verify usually got stuck, so we disable it by now. patch is welcome!
# 3. Verify usually got stuck, so we disable it by now. patch is welcome! def flash(self, address = 0, bitstream_file = None, external = False, fifile = None, mcufile = None, pmode = None):
def flash(self, address = 0, data_file = None, external = False, fifile = None, verify = False, cable = GOWIN_CABLE_FT2CH):
pmode = (GOWIN_PMODE_EMBFLASH + 1) if verify else GOWIN_PMODE_EMBFLASH
if external is True: if pmode is None:
pmode = (GOWIN_PMODE_EXTFLASH + 1) if verify else GOWIN_PMODE_EXTFLASH if external:
pmode = GOWIN_PMODE_EXFLASH
elif self.has_embflash:
pmode = GOWIN_PMODE_EMBFLASH
else:
pmode = GOWIN_PMODE_EXFLASH
external = True
if data_file is None and fifile is None: if bitstream_file is None and fifile is None and mcufile is None:
print("GowinProgrammer: fsFile or fiFile should be given!"); print("GowinProgrammer: fsFile, fiFile or mcuFile should be given!")
exit(1) exit(1)
if self.is_wsl is True and data_file is not None: if self.is_wsl is True and bitstream_file is not None:
data_file = os.popen("wslpath -w {}".format(data_file)).read().strip("\n") bitstream_file = os.popen("wslpath -w {}".format(bitstream_file)).read().strip("\n")
if self.is_wsl is True and fifile is not None: if self.is_wsl is True and fifile is not None:
fifile = os.popen("wslpath -w {}".format(fifile)).read().strip("\n") fifile = os.popen("wslpath -w {}".format(fifile)).read().strip("\n")
cmd_line = [self.programmer, if self.is_wsl is True and mcufile is not None:
"--spiaddr", str(address), mcufile = os.popen("wslpath -w {}".format(mcufile)).read().strip("\n")
cmd_line = [
self.programmer,
"--device", str(self.device)] "--device", str(self.device)]
if data_file is not None: if external:
if external is True: # accepts 0xXXX, at least 3 hex digits. Here we use 6 digits.
cmd_line += ["--mcuFile", str(data_file)] spiaddr = "0x{:05X}".format(address)
else: cmd_line += ["--spiaddr", spiaddr]
cmd_line += ["--fsFile", str(data_file)]
if bitstream_file is not None:
cmd_line += ["--fsFile", str(bitstream_file)]
if fifile is not None: if fifile is not None:
cmd_line += ["--fiFile", str(fifile)] cmd_line += ["--fiFile", str(fifile)]
cmd_line += ["--cable-index", str(cable), "--operation_index", str(pmode)] if mcufile is not None:
cmd_line += ["--mcuFile", str(mcufile)]
cmd_line += ["--cable-index", str(self.cable), "--operation_index", str(pmode)]
print(' '.join(cmd_line))
self.call(cmd_line) self.call(cmd_line)
def load_bitstream(self, bitstream_file, verify = False, cable = GOWIN_CABLE_FT2CH): def load_bitstream(self, bitstream_file):
pmode = 4 if verify else 2 pmode = GOWIN_PMODE_SRAM
bitfile = bitstream_file bitfile = bitstream_file
if self.is_wsl is True: if self.is_wsl is True:
bitfile = os.popen("wslpath -w {}".format(bitstream_file)).read().strip("\n") bitfile = os.popen("wslpath -w {}".format(bitstream_file)).read().strip("\n")
@ -93,6 +116,6 @@ class GowinProgrammer(GenericProgrammer):
cmd_line = [self.programmer, cmd_line = [self.programmer,
"--device", str(self.device), "--device", str(self.device),
"--fsFile", str(bitfile), "--fsFile", str(bitfile),
"--cable-index", str(cable), "--cable-index", str(self.cable),
"--operation_index", str(pmode)] "--operation_index", str(pmode)]
self.call(cmd_line) self.call(cmd_line)