import argparse
import subprocess
import sys
import os
from intelhex import IntelHex
HELP = 'prerequisite: Add sections below to jlink database file (C:\\Program Files (x86)\\SEGGER\\JLink_V640b\\JLinkDevices.xml)\n'
DATABASE_PATCH = """
"""
FLM_PATH = 'Put *.flm files under the following path (C:\\Program Files (x86)\\SEGGER\\JLink_V640b\\Devices\\GigaDevice\\)'
JLINK_PATH = r'C:\Program Files (x86)\SEGGER\JLink\JLink.exe'
JLINK_SCRIPT = 'download_script.jlink'
VENV = 'scripts\\venv'
def download_firmware_jlink(files, algo):
if not files:
print('Can\'t find any hex or axf images')
return
loadfile_cmd = [f'loadfile {f}' for f in files]
#cmds = ['r', 'exec EnableEraseAllFlashBanks', 'erase', *loadfile_cmd, 'qc']
#cmds = ['r', *loadfile_cmd, 'qc']
if algo == 'GD32W51x_S':
# Set all flash area as secure world if FMCOB = 1 (SECWM3 = 0x03FF0000)
flashwm_change = ['w4 50022004 0x45670123', 'w4 50022004 0xCDEF89AB', 'w4 50022008 0x45670123', 'w4 50022008 0xCDEF89AB', 'w4 50022060 0x03FF0000', 'w4 50022010 0x00000080']
flashwm_revert = ['w4 50022004 0x45670123', 'w4 50022004 0xCDEF89AB', 'w4 50022008 0x45670123', 'w4 50022008 0xCDEF89AB', 'w4 50022060 0x000003FF', 'w4 50022010 0x00000080']
else:
flashwm_change = []
flashwm_revert = []
nocompare = ['exec SetCompareMode = 0']
cmds = ['r'] + nocompare + flashwm_change + [*loadfile_cmd] + flashwm_revert + ['qc']
script_contents = '\n'.join(cmds) + '\n'
with open(JLINK_SCRIPT, 'w') as f:
f.write(script_contents)
cmd = [JLINK_PATH, '-device', algo, '-if', 'SWD', '-speed', '3000', '-autoconnect', '1', '-JTAGConf', '-1,-1', '-CommanderScript', JLINK_SCRIPT]
subprocess.run(cmd, check=True)
def download_firmware_daplink(files, algo):
if not files:
print('Can\'t find any hex or axf images')
return
if algo == 'GD32W51x' or algo == 'GD32W51x_S':
target = 'gd32w51x'
elif algo == 'GD32W51x_Q' or algo == 'GD32W51x_Q_S':
target = 'gd32w51x_qspi'
p = subprocess.Popen(VENV + '\\Scripts\\activate.bat && pyocd cmd ' + f' --target {target}', shell=True, stdin=subprocess.PIPE)
p.communicate(input=b'ww 0xE000EDD0 2\nexit\n')
if target == 'gd32w51x':
subprocess.run(VENV + '\\Scripts\\activate.bat && pyocd flash --disable-keep-unwritten ' + ' '.join(files) + f' --target {target}', shell=True, check=True)
else:
subprocess.run(VENV + '\\Scripts\\activate.bat && pyocd flash --disable-keep-unwritten --disable-smart-flash ' + ' '.join(files) + f' --target {target}', shell=True, check=True)
def verify_firmware_jlink(files, algo):
if not files:
print('Can\'t find any hex or axf images')
return
savefile_cmd = []
verifybin_cmd = []
for hex, bin in files:
ih = IntelHex()
ih.loadhex(hex)
savefile_cmd.append(' '.join(['savebin', bin + '.read', f'{ih.minaddr():x}', f'{ih.maxaddr() - ih.minaddr() + 1:x}']))
verifybin_cmd.append(' '.join(['verifybin', bin, f'{ih.minaddr():x}']))
cmds = ['r', *savefile_cmd, 'qc']
script_contents = '\n'.join(cmds) + '\n'
with open(JLINK_SCRIPT, 'w') as f:
f.write(script_contents)
cmd = [JLINK_PATH, '-device', algo, '-if', 'SWD', '-speed', '4000', '-autoconnect', '1', '-JTAGConf', '-1,-1', '-CommanderScript', JLINK_SCRIPT]
subprocess.run(cmd, check=True)
cmds = ['r', *verifybin_cmd, 'qc']
script_contents = '\n'.join(cmds) + '\n'
with open(JLINK_SCRIPT, 'w') as f:
f.write(script_contents)
cmd = [JLINK_PATH, '-device', algo, '-if', 'SWD', '-speed', '4000', '-autoconnect', '1', '-JTAGConf', '-1,-1', '-CommanderScript', JLINK_SCRIPT]
subprocess.run(cmd, check=True)
if __name__ == '__main__':
parser = argparse.ArgumentParser(formatter_class=argparse.RawDescriptionHelpFormatter, description=HELP + DATABASE_PATCH + FLM_PATH)
parser.add_argument('--dir', '-d', help='specify the folder of images')
parser.add_argument('--file', '-f', action='append', help='specify the path of images')
parser.add_argument('--verify', '-v', help='verify the binary contents programmed to the target')
parser.add_argument('--algo', '-a', help='flash download algorithm', default="GD32101")
parser.add_argument('--debugger', help='specify the debugger to perform flash programming', default="JLINK")
args = parser.parse_args()
if not args.dir and not args.file:
print('Either parameter --dir or --file is required')
sys.exit(1)
if args.dir:
files = [os.path.join(args.dir, f) for f in os.listdir(args.dir)]
if args.verify:
hex_files = [f for f in files if os.path.splitext(f)[1] == '.hex']
bin_files = [f for f in files if os.path.splitext(f)[1] == '.bin']
if len(hex_files) != len(bin_files):
print('Error: missing matched binary files or hex files')
sys.exit(1)
file_tuples = [(hex, bin) for hex in hex_files for bin in bin_files if os.path.splitext(hex)[0] == os.path.splitext(bin)[0]]
if args.debugger == 'JLINK':
verify_firmware_jlink(file_tuples, args.algo)
else:
files = [f for f in files if os.path.splitext(f)[1] == '.hex' or os.path.splitext(f)[1] == '.axf']
if args.debugger == 'JLINK':
download_firmware_jlink(files, args.algo)
elif args.debugger == 'DAPLINK':
download_firmware_daplink(files, args.algo)
else:
if args.verify:
if args.debugger == 'JLINK':
verify_firmware_jlink(args.file, args.algo)
else:
if args.debugger == 'JLINK':
download_firmware_jlink(args.file, args.algo)
elif args.debugger == 'DAPLINK':
download_firmware_daplink(args.file, args.algo)