initial commit
This commit is contained in:
commit
2f16907c9e
256
BLFlashCommand.py
Normal file
256
BLFlashCommand.py
Normal file
|
@ -0,0 +1,256 @@
|
|||
# uncompyle6 version 3.9.0
|
||||
# Python bytecode version base 3.7.0 (3394)
|
||||
# Decompiled from: Python 3.7.16 (default, Mar 30 2023, 01:25:49)
|
||||
# [GCC 12.2.1 20220924]
|
||||
# Embedded file name: BLFlashCommand.py
|
||||
"""
|
||||
Created on 20221216
|
||||
|
||||
@author: Dillon
|
||||
"""
|
||||
import os, re, sys, argparse, binascii, threading, configparser
|
||||
from libs import bflb_utils
|
||||
from libs.bflb_utils import get_serial_ports
|
||||
from libs.bflb_interface_eflash_loader import InterfaceEflashLoader
|
||||
|
||||
def hex_to_dec(value):
|
||||
try:
|
||||
value = value.replace('0x', '')
|
||||
int(value, 16)
|
||||
return True
|
||||
except ValueError:
|
||||
return False
|
||||
|
||||
|
||||
class ThreadIot(threading.Thread):
|
||||
|
||||
def __init__(self, config, act='download', callback=None):
|
||||
threading.Thread.__init__(self)
|
||||
self.obj = InterfaceEflashLoader()
|
||||
self.config = config
|
||||
self.callback = callback
|
||||
self.act = act
|
||||
|
||||
def stop(self):
|
||||
pass
|
||||
|
||||
def run(self):
|
||||
self.obj.run(self.act, self.config, self.callback)
|
||||
|
||||
|
||||
class MainClass:
|
||||
|
||||
def __init__(self):
|
||||
self.dict_chip = {
|
||||
'BL602': ('bl602', 'bl602'),
|
||||
'BL702': ('bl702', 'bl702'),
|
||||
'BL702L': ('bl702l', 'bl702l'),
|
||||
'BL808': ('bl808', 'bl808'),
|
||||
'BL606P': ('bl606p', 'bl808'),
|
||||
'BL616': ('bl616', 'bl616')}
|
||||
|
||||
def get_addr_from_partition_by_name(self, name, parition_file, index):
|
||||
try:
|
||||
with open(parition_file, 'rb') as (fp):
|
||||
data = bytearray(fp.read())
|
||||
fp.close()
|
||||
start = data.find(name.encode('utf-8'))
|
||||
if start != -1:
|
||||
addr = data[start + 9 + index * 4:start + 9 + 4 + index * 4]
|
||||
addr.reverse()
|
||||
addr = hex(int(binascii.hexlify(addr), 16))
|
||||
return (True, addr)
|
||||
print(data)
|
||||
print(name.encode('utf-8'))
|
||||
return (False, '0')
|
||||
except Exception as e:
|
||||
try:
|
||||
bflb_utils.printf(e)
|
||||
return (False, '0')
|
||||
finally:
|
||||
e = None
|
||||
del e
|
||||
|
||||
def get_value(self, args):
|
||||
self.config = dict()
|
||||
self.config['param'] = dict()
|
||||
self.config['check_box'] = dict()
|
||||
self.config['input_path'] = dict()
|
||||
self.config['param']['interface_type'] = args.interface
|
||||
self.config['param']['comport_uart'] = args.port
|
||||
self.config['param']['chip'] = args.chipname.lower()
|
||||
if args.chipname.upper() not in self.dict_chip:
|
||||
bflb_utils.printf('Error: chipname ' + args.chipname + ' is error!')
|
||||
return
|
||||
chip = self.dict_chip[args.chipname.upper()]
|
||||
self.config['param']['chip_name'] = chip[0]
|
||||
self.config['param']['chip_type'] = chip[1]
|
||||
if args.interface.lower() == 'uart':
|
||||
self.config['param']['speed_uart'] = str(args.baudrate)
|
||||
self.config['param']['speed_jlink'] = '1000'
|
||||
else:
|
||||
self.config['param']['speed_uart'] = '2000000'
|
||||
if str(args.baudrate) == '2000000':
|
||||
self.config['param']['speed_jlink'] = '1000'
|
||||
else:
|
||||
self.config['param']['speed_jlink'] = str(args.baudrate)
|
||||
if args.efuse:
|
||||
self.config['check_box']['efuse'] = True
|
||||
self.config['input_path']['efuse'] = os.path.abspath(args.efuse)
|
||||
else:
|
||||
self.config['check_box']['efuse'] = False
|
||||
self.config['input_path']['efuse'] = ''
|
||||
self.config['input_path']['config'] = args.config
|
||||
try:
|
||||
try:
|
||||
self.erase = 1
|
||||
self.skip_mode = '0x0, 0x0'
|
||||
self.boot2_isp_mode = 0
|
||||
config = configparser.ConfigParser()
|
||||
if not os.path.exists(os.path.abspath(args.config)):
|
||||
bflb_utils.printf('Error: Config File Not Found!')
|
||||
return
|
||||
config.read((os.path.abspath(args.config)), encoding='utf-8')
|
||||
if config:
|
||||
for item in config.sections():
|
||||
if item == 'cfg':
|
||||
self.erase = config.get('cfg', 'erase', fallback=1)
|
||||
self.skip_mode = config.get('cfg', 'skip_mode', fallback='0x0, 0x0')
|
||||
self.boot2_isp_mode = config.get('cfg', 'boot2_isp_mode', fallback=0)
|
||||
|
||||
except Exception as e:
|
||||
try:
|
||||
config = None
|
||||
print('ConfigParser Error: ' + str(e))
|
||||
finally:
|
||||
e = None
|
||||
del e
|
||||
|
||||
finally:
|
||||
self.config['param']['erase'] = self.erase
|
||||
self.config['param']['skip_mode'] = self.skip_mode
|
||||
self.config['param']['boot2_isp_mode'] = self.boot2_isp_mode
|
||||
|
||||
if args.key:
|
||||
self.config['check_box']['encrypt'] = True
|
||||
self.config['param']['aes_key'] = args.key
|
||||
self.config['param']['aes_iv'] = args.iv
|
||||
else:
|
||||
self.config['check_box']['encrypt'] = False
|
||||
self.config['param']['aes_key'] = ''
|
||||
self.config['param']['aes_iv'] = ''
|
||||
if args.pk:
|
||||
self.config['check_box']['sign'] = True
|
||||
self.config['input_path']['publickey'] = args.pk
|
||||
self.config['input_path']['privatekey'] = args.sk
|
||||
else:
|
||||
self.config['check_box']['sign'] = False
|
||||
self.config['input_path']['publickey'] = ''
|
||||
self.config['input_path']['privatekey'] = ''
|
||||
return self.config
|
||||
|
||||
def get_value_file(self, name, path, addr, cpu_id=None):
|
||||
name = str(name)
|
||||
if os.path.isabs(path):
|
||||
path = os.path.abspath(path)
|
||||
else:
|
||||
config_dir = os.path.dirname(os.path.abspath(self.config['input_path']['config']))
|
||||
path = os.path.join(config_dir, path)
|
||||
if cpu_id:
|
||||
path = path.replace('$(CHIPNAME)', self.config['param']['chip_name'] + '_' + cpu_id)
|
||||
else:
|
||||
path = path.replace('$(CHIPNAME)', self.config['param']['chip_name'])
|
||||
addr = str(addr)
|
||||
self.config[name] = {}
|
||||
self.config[name]['addr'] = addr
|
||||
self.config[name]['path'] = path
|
||||
if not os.path.exists(path):
|
||||
dir_path = os.path.dirname(path)
|
||||
file_name = os.path.basename(path)
|
||||
try:
|
||||
all_file_list = os.listdir(dir_path)
|
||||
except Exception as e:
|
||||
try:
|
||||
bflb_utils.printf(e)
|
||||
return False
|
||||
finally:
|
||||
e = None
|
||||
del e
|
||||
|
||||
result = []
|
||||
if '*' in file_name:
|
||||
file_name = file_name.replace('.', '\\.').replace('*', '.*[一-龥]*')
|
||||
for one_name in all_file_list:
|
||||
pattern = re.compile(file_name)
|
||||
temp_list = pattern.findall(one_name)
|
||||
if one_name in temp_list:
|
||||
result += temp_list
|
||||
|
||||
if len(result) > 1:
|
||||
bflb_utils.printf('Error: ' + name + ' multiple files were matched! ')
|
||||
return False
|
||||
if len(result) == 0:
|
||||
error = 'Error: ' + name + ':' + path + ' image file is not existed'
|
||||
bflb_utils.printf(error)
|
||||
return False
|
||||
self.config[name]['path'] = os.path.join(dir_path, result[0])
|
||||
if addr.find('@partition') != -1:
|
||||
bflb_utils.printf('{0} get address from partiton file {1}'.format(name, self.config['partition']['path']))
|
||||
success, addr_pt = self.get_addr_from_partition_by_name(name, self.config['partition']['path'], 0)
|
||||
if not success:
|
||||
bflb_utils.printf('Fail, not find ', name, ' in partition')
|
||||
return False
|
||||
self.config[name]['addr'] = addr_pt
|
||||
bflb_utils.printf('Address=', addr_pt)
|
||||
addr = addr_pt
|
||||
if not hex_to_dec(addr):
|
||||
error = 'Error: ' + addr + ' is invalid hexadecimal value'
|
||||
bflb_utils.printf(error)
|
||||
return False
|
||||
return True
|
||||
|
||||
def main(self, argv):
|
||||
port = None
|
||||
ports = []
|
||||
for item in get_serial_ports():
|
||||
ports.append(item['port'])
|
||||
|
||||
if ports:
|
||||
try:
|
||||
port = sorted(ports, key=(lambda x: int(re.match('COM(\\d+)', x).group(1))))[0]
|
||||
except Exception:
|
||||
port = sorted(ports)[0]
|
||||
|
||||
else:
|
||||
parser = argparse.ArgumentParser(description='flash-command')
|
||||
parser.add_argument('--interface', dest='interface', default='uart', help='interface to use')
|
||||
parser.add_argument('--port', dest='port', default=port, help='serial port to use')
|
||||
parser.add_argument('--chipname', dest='chipname', default='BL602', help='chip name')
|
||||
parser.add_argument('--baudrate', dest='baudrate', default=2000000, type=int, help='the speed at which to communicate')
|
||||
parser.add_argument('--config', dest='config', default='', help='run config')
|
||||
parser.add_argument('--cpu_id', dest='cpu_id', default='', help='cpu id')
|
||||
parser.add_argument('--efuse', dest='efuse', default='', help='efuse options')
|
||||
parser.add_argument('--key', dest='key', default='', help='aes key')
|
||||
parser.add_argument('--iv', dest='iv', default='', help='aes iv')
|
||||
parser.add_argument('--pk', dest='pk', help='ecc public key')
|
||||
parser.add_argument('--sk', dest='sk', default='', help='ecc private key')
|
||||
args = parser.parse_args(argv)
|
||||
if args.port:
|
||||
bflb_utils.printf('Serial port is ' + args.port)
|
||||
else:
|
||||
if port:
|
||||
bflb_utils.printf('Serial port is ' + port)
|
||||
else:
|
||||
bflb_utils.printf('Serial port is not found')
|
||||
bflb_utils.printf('==================================================')
|
||||
config = self.get_value(args)
|
||||
if config:
|
||||
self.obj = InterfaceEflashLoader()
|
||||
self.obj.run('download', config, None)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
print(sys.argv)
|
||||
app = MainClass()
|
||||
app.main(sys.argv[1:])
|
||||
# okay decompiling BLFlashCommand.pyc
|
60
libs/__init__.py
Normal file
60
libs/__init__.py
Normal file
|
@ -0,0 +1,60 @@
|
|||
# decompyle3 version 3.9.0
|
||||
# Python bytecode version base 3.7.0 (3394)
|
||||
# Decompiled from: Python 3.7.16 (default, Mar 30 2023, 01:25:49)
|
||||
# [GCC 12.2.1 20220924]
|
||||
# Embedded file name: libs/__init__.py
|
||||
from . import bflb_utils
|
||||
from . import bflb_interface_eflash_loader
|
||||
from . import bflb_eflash_loader
|
||||
from . import bflb_configobj
|
||||
from . import bflb_interface_jlink
|
||||
from . import bflb_interface_cklink
|
||||
from . import bflb_interface_openocd
|
||||
from .base import bflb_flash_select
|
||||
from .base import bflb_efuse_boothd_create
|
||||
from .base import bflb_base_eflash_loader
|
||||
from .base import bflb_img_create
|
||||
from .base import bflb_serial
|
||||
from .base import bflb_img_loader
|
||||
from base.bl602 import flash_select_do
|
||||
from base.bl602 import bootheader_cfg_keys
|
||||
from base.bl602 import jlink_load_cfg
|
||||
from base.bl602 import cklink_load_cfg
|
||||
from base.bl602 import openocd_load_cfg
|
||||
from base.bl602 import img_create_do
|
||||
from base.bl702 import chiptype_patch
|
||||
from base.bl702 import flash_select_do
|
||||
from base.bl702 import bootheader_cfg_keys
|
||||
from base.bl702 import jlink_load_cfg
|
||||
from base.bl702 import cklink_load_cfg
|
||||
from base.bl702 import openocd_load_cfg
|
||||
from base.bl702 import img_create_do
|
||||
from base.bl808 import chiptype_patch
|
||||
from base.bl808 import flash_select_do
|
||||
from base.bl808 import bootheader_cfg_keys
|
||||
from base.bl808 import jlink_load_cfg
|
||||
from base.bl808 import cklink_load_cfg
|
||||
from base.bl808 import openocd_load_cfg
|
||||
from base.bl808 import img_create_do
|
||||
from base.bl616 import chiptype_patch
|
||||
from base.bl616 import flash_select_do
|
||||
from base.bl616 import bootheader_cfg_keys
|
||||
from base.bl616 import jlink_load_cfg
|
||||
from base.bl616 import cklink_load_cfg
|
||||
from base.bl616 import openocd_load_cfg
|
||||
from base.bl616 import img_create_do
|
||||
from base.wb03 import chiptype_patch
|
||||
from base.wb03 import flash_select_do
|
||||
from base.wb03 import bootheader_cfg_keys
|
||||
from base.wb03 import jlink_load_cfg
|
||||
from base.wb03 import cklink_load_cfg
|
||||
from base.wb03 import openocd_load_cfg
|
||||
from base.wb03 import img_create_do
|
||||
from base.bl702l import chiptype_patch
|
||||
from base.bl702l import flash_select_do
|
||||
from base.bl702l import bootheader_cfg_keys
|
||||
from base.bl702l import jlink_load_cfg
|
||||
from base.bl702l import cklink_load_cfg
|
||||
from base.bl702l import openocd_load_cfg
|
||||
from base.bl702l import img_create_do
|
||||
# okay decompiling ./libs/__init__.pyc
|
7
libs/base.py
Normal file
7
libs/base.py
Normal file
|
@ -0,0 +1,7 @@
|
|||
# decompyle3 version 3.9.0
|
||||
# Python bytecode version base 3.7.0 (3394)
|
||||
# Decompiled from: Python 3.7.16 (default, Mar 30 2023, 01:25:49)
|
||||
# [GCC 12.2.1 20220924]
|
||||
# Embedded file name: -
|
||||
pass
|
||||
# okay decompiling ./libs/base.pyc
|
2030
libs/bflb_configobj.py
Normal file
2030
libs/bflb_configobj.py
Normal file
File diff suppressed because it is too large
Load Diff
32
libs/bflb_ecdh.py
Normal file
32
libs/bflb_ecdh.py
Normal file
|
@ -0,0 +1,32 @@
|
|||
# decompyle3 version 3.9.0
|
||||
# Python bytecode version base 3.7.0 (3394)
|
||||
# Decompiled from: Python 3.7.16 (default, Mar 30 2023, 01:25:49)
|
||||
# [GCC 12.2.1 20220924]
|
||||
# Embedded file name: libs/bflb_ecdh.py
|
||||
import binascii
|
||||
from ecdsa import ECDH, NIST256p
|
||||
from libs.bflb_utils import *
|
||||
|
||||
class BflbEcdh(object):
|
||||
|
||||
def __init__(self, curve=NIST256p):
|
||||
self.ecdh = ECDH(curve)
|
||||
self.local_public_key = None
|
||||
self.sharedsecret = ''
|
||||
|
||||
def create_public_key(self):
|
||||
self.ecdh.generate_private_key()
|
||||
self.local_public_key = self.ecdh.get_public_key()
|
||||
ret = binascii.hexlify(self.local_public_key.to_string()).decode('utf-8')
|
||||
printf('local public key:')
|
||||
printf(ret)
|
||||
return ret
|
||||
|
||||
def create_shared_key(self, peer_pk):
|
||||
self.ecdh.load_received_public_key_bytes(binascii.unhexlify(peer_pk))
|
||||
self.sharedsecret = self.ecdh.generate_sharedsecret_bytes()
|
||||
ret = binascii.hexlify(self.sharedsecret).decode('utf-8')
|
||||
printf('secret key:')
|
||||
printf(ret)
|
||||
return ret
|
||||
# okay decompiling ./libs/bflb_ecdh.pyc
|
523
libs/bflb_eflash_loader.py
Normal file
523
libs/bflb_eflash_loader.py
Normal file
|
@ -0,0 +1,523 @@
|
|||
# decompyle3 version 3.9.0
|
||||
# Python bytecode version base 3.7.0 (3394)
|
||||
# Decompiled from: Python 3.7.16 (default, Mar 30 2023, 01:25:49)
|
||||
# [GCC 12.2.1 20220924]
|
||||
# Embedded file name: libs/bflb_eflash_loader.py
|
||||
from libs.bflb_utils import *
|
||||
from libs.bflb_configobj import BFConfigParser
|
||||
from libs.base.bflb_base_eflash_loader import BaseEflashLoader
|
||||
FLASH_ERASE_SHAKE_HAND = 'Flash erase shake hand'
|
||||
FLASH_LOAD_SHAKE_HAND = 'Flash load shake hand'
|
||||
|
||||
class BL602EflashLoader(BaseEflashLoader):
|
||||
__doc__ = '\n When chip is bl602, eflash Loader\n '
|
||||
|
||||
def __init__(self, chip_type, args, config, callback=None, macaddr_callback=None, create_simple_callback=None, create_img_callback=None, task_num=None):
|
||||
super().__init__(chip_type, args, config, callback, macaddr_callback, create_simple_callback, create_img_callback, task_num)
|
||||
self.chip_type = chip_type
|
||||
|
||||
def set_load_function(self):
|
||||
self.load_function = 1
|
||||
|
||||
def get_flash_pin(self):
|
||||
return 255
|
||||
|
||||
def show_identify_fail(self):
|
||||
printf('eflash loader identify flash fail!')
|
||||
self.error_code_print('0043')
|
||||
return False
|
||||
|
||||
def set_temp_timeout(self):
|
||||
self.bflb_serial_object.set_timeout(self._default_time_out)
|
||||
|
||||
def run_step(self):
|
||||
result, content = self.first_run_step_load_parameter()
|
||||
if not result or content != 'continue':
|
||||
return (result, content)
|
||||
result, content = self.second_run_step_shake_hand()
|
||||
if not result or content != 'continue':
|
||||
return (result, content)
|
||||
result, content = self.third_run_step_read_mac_address()
|
||||
if not result or content != 'continue':
|
||||
return (result, content)
|
||||
result, content = self.fourth_run_step_interact_chip()
|
||||
if not result or content != 'continue':
|
||||
return (result, content)
|
||||
result, content = self.fifth_run_step_write_flash_and_check()
|
||||
if not result or content != 'continue':
|
||||
return (result, content)
|
||||
result, content = self.sixth_run_step_write_efuse()
|
||||
if not result or content != 'continue':
|
||||
return (result, content)
|
||||
result, content = self.seventh_run_step_erase()
|
||||
if not result or content != 'continue':
|
||||
return (result, content)
|
||||
result, content = self.eighth_run_step_read()
|
||||
if not result or content != 'continue':
|
||||
return (result, content)
|
||||
result, content = self.ninth_run_step_end()
|
||||
return (
|
||||
result, content)
|
||||
|
||||
|
||||
class BL616EflashLoader(BaseEflashLoader):
|
||||
__doc__ = '\n When chip is bl616, eflash Loader\n '
|
||||
|
||||
def __init__(self, chip_type, args, config, callback=None, macaddr_callback=None, create_simple_callback=None, create_img_callback=None, task_num=None):
|
||||
super().__init__(chip_type, args, config, callback, macaddr_callback, create_simple_callback, create_img_callback, task_num)
|
||||
self.chip_type = chip_type
|
||||
|
||||
def run_flash2(self):
|
||||
"""
|
||||
If chip is bl616 or wb03, it will run this function.
|
||||
"""
|
||||
if self.cfg.has_option('FLASH2_CFG', 'flash2_en'):
|
||||
self._flash2_en = self.cfg.get('FLASH2_CFG', 'flash2_en') == 'true'
|
||||
if self._flash2_en is True:
|
||||
self._flash1_size = int(self.cfg.get('FLASH2_CFG', 'flash1_size')) * 1024 * 1024
|
||||
self._flash2_size = int(self.cfg.get('FLASH2_CFG', 'flash2_size')) * 1024 * 1024
|
||||
printf('flash2 set para')
|
||||
flash2_pin = 0
|
||||
flash2_clock_cfg = 0
|
||||
flash2_io_mode = 0
|
||||
flash2_clk_delay = 0
|
||||
if self.cfg.get('FLASH2_CFG', 'flash2_pin'):
|
||||
flash_pin_cfg = self.cfg.get('FLASH2_CFG', 'flash2_pin')
|
||||
if flash_pin_cfg.startswith('0x'):
|
||||
flash2_pin = int(flash_pin_cfg, 16)
|
||||
else:
|
||||
flash2_pin = int(flash_pin_cfg, 10)
|
||||
if self.cfg.has_option('FLASH2_CFG', 'flash2_clock_cfg'):
|
||||
clock_div_cfg = self.cfg.get('FLASH2_CFG', 'flash2_clock_cfg')
|
||||
if clock_div_cfg.startswith('0x'):
|
||||
flash2_clock_cfg = int(clock_div_cfg, 16)
|
||||
else:
|
||||
flash2_clock_cfg = int(clock_div_cfg, 10)
|
||||
if self.cfg.has_option('FLASH2_CFG', 'flash2_io_mode'):
|
||||
io_mode_cfg = self.cfg.get('FLASH2_CFG', 'flash2_io_mode')
|
||||
if io_mode_cfg.startswith('0x'):
|
||||
flash2_io_mode = int(io_mode_cfg, 16)
|
||||
else:
|
||||
flash2_io_mode = int(io_mode_cfg, 10)
|
||||
if self.cfg.has_option('FLASH2_CFG', 'flash2_clock_delay'):
|
||||
clk_delay_cfg = self.cfg.get('FLASH2_CFG', 'flash2_clock_delay')
|
||||
if clk_delay_cfg.startswith('0x'):
|
||||
flash2_clk_delay = int(clk_delay_cfg, 16)
|
||||
else:
|
||||
flash2_clk_delay = int(clk_delay_cfg, 10)
|
||||
self.flash2_set = (flash2_pin << 0) + (flash2_clock_cfg << 8) + (flash2_io_mode << 16) + (flash2_clk_delay << 24)
|
||||
if self.load_function == 2:
|
||||
printf('set flash2 cfg: %X' % self.flash2_set)
|
||||
ret = self.flash_set_para_main_process(self.flash2_set, bytearray(0))
|
||||
self._need_shake_hand = False
|
||||
if ret is False:
|
||||
return (False, self.flash_burn_retry)
|
||||
ret = self.flash_switch_bank_process(1)
|
||||
self._need_shake_hand = False
|
||||
if ret is False:
|
||||
return (False, self.flash_burn_retry)
|
||||
ret, data = self.flash_read_jedec_id_process()
|
||||
if ret:
|
||||
self._need_shake_hand = False
|
||||
data = binascii.hexlify(data).decode('utf-8')
|
||||
self.id2_valid_flag = data[6:]
|
||||
read_id2 = data[0:6]
|
||||
self.read_flash2_id = read_id2
|
||||
if self.cfg.has_option('FLASH2_CFG', 'flash2_para'):
|
||||
flash2_para_file = os.path.join(app_path, self.cfg.get('FLASH2_CFG', 'flash2_para'))
|
||||
self.flash_para_update(flash2_para_file, read_id2)
|
||||
fp = open_file(flash2_para_file, 'rb')
|
||||
para_data = bytearray(fp.read())
|
||||
fp.close()
|
||||
para_data[0:1] = b'\x11'
|
||||
fp = open_file(flash2_para_file, 'wb+')
|
||||
fp.write(para_data)
|
||||
fp.close()
|
||||
else:
|
||||
self.error_code_print('0030')
|
||||
return (
|
||||
False, self.flash_burn_retry)
|
||||
ret = self.flash_switch_bank_process(0)
|
||||
self._need_shake_hand = False
|
||||
if ret is False:
|
||||
return (False, self.flash_burn_retry)
|
||||
return (True, 'continue')
|
||||
|
||||
def get_flash1_and_flash2(self, flash_file, address, size_current, i):
|
||||
if self._flash1_size != 0:
|
||||
if self._flash1_size < int(address[i], 16) + size_current:
|
||||
if self._flash1_size > int(address[i], 16):
|
||||
if self._flash2_select is False:
|
||||
printf('%s file is overflow with flash1' % flash_file[i])
|
||||
flash1_bin, flash1_bin_len, flash2_bin, flash2_bin_len = self.flash_loader_cut_flash_bin(flash_file[i], int(address[i], 16), self._flash1_size)
|
||||
return (
|
||||
flash1_bin, flash1_bin_len, flash2_bin, flash2_bin_len)
|
||||
return ('', 0, '', 0)
|
||||
|
||||
def set_clear_boot_status(self, shakehand=0):
|
||||
self.clear_boot_status(shakehand)
|
||||
|
||||
def get_new_bh_data(self, section, bh_data, fp):
|
||||
if section == 'BOOTHEADER_GROUP0_CFG':
|
||||
fp.write(bh_data[100:120])
|
||||
|
||||
def write_flash_data(self, file, start_addr, callback):
|
||||
pass
|
||||
|
||||
def get_flash_pin_from_bootinfo(self, chiptype, bootinfo):
|
||||
sw_usage_data = bootinfo[22:24] + bootinfo[20:22] + bootinfo[18:20] + bootinfo[16:18]
|
||||
sw_usage_data = int(sw_usage_data, 16)
|
||||
return sw_usage_data >> 14 & 63
|
||||
|
||||
def run_step(self):
|
||||
result, content = self.first_run_step_load_parameter()
|
||||
if not result or content != 'continue':
|
||||
return (result, content)
|
||||
result, content = self.second_run_step_shake_hand()
|
||||
if not result or content != 'continue':
|
||||
return (result, content)
|
||||
result, content = self.third_run_step_read_mac_address()
|
||||
if not result or content != 'continue':
|
||||
return (result, content)
|
||||
result, content = self.fourth_run_step_interact_chip()
|
||||
if not result or content != 'continue':
|
||||
return (result, content)
|
||||
result, content = self.fifth_run_step_write_flash_and_check()
|
||||
if not result or content != 'continue':
|
||||
return (result, content)
|
||||
result, content = self.sixth_run_step_write_efuse()
|
||||
if not result or content != 'continue':
|
||||
return (result, content)
|
||||
result, content = self.seventh_run_step_erase()
|
||||
if not result or content != 'continue':
|
||||
return (result, content)
|
||||
result, content = self.eighth_run_step_read()
|
||||
if not result or content != 'continue':
|
||||
return (result, content)
|
||||
result, content = self.ninth_run_step_end()
|
||||
return (
|
||||
result, content)
|
||||
|
||||
|
||||
class BL628EflashLoader(BaseEflashLoader):
|
||||
__doc__ = '\n When chip is bl628, eflash Loader\n '
|
||||
|
||||
def __init__(self, chip_type, args, config, callback=None, macaddr_callback=None, create_simple_callback=None, create_img_callback=None, task_num=None):
|
||||
super().__init__(chip_type, args, config, callback, macaddr_callback, create_simple_callback, create_img_callback, task_num)
|
||||
self.chip_type = chip_type
|
||||
|
||||
def set_clear_boot_status(self, shakehand=0):
|
||||
self.clear_boot_status(shakehand)
|
||||
|
||||
def get_new_bh_data(self, section, bh_data, fp):
|
||||
if section == 'BOOTHEADER_GROUP0_CFG':
|
||||
fp.write(bh_data[100:124])
|
||||
|
||||
def write_flash_data(self, file, start_addr, callback):
|
||||
pass
|
||||
|
||||
def run_step(self):
|
||||
result, content = self.first_run_step_load_parameter()
|
||||
if not result or content != 'continue':
|
||||
return (result, content)
|
||||
result, content = self.second_run_step_shake_hand()
|
||||
if not result or content != 'continue':
|
||||
return (result, content)
|
||||
result, content = self.third_run_step_read_mac_address()
|
||||
if not result or content != 'continue':
|
||||
return (result, content)
|
||||
result, content = self.fourth_run_step_interact_chip()
|
||||
if not result or content != 'continue':
|
||||
return (result, content)
|
||||
result, content = self.fifth_run_step_write_flash_and_check()
|
||||
if not result or content != 'continue':
|
||||
return (result, content)
|
||||
result, content = self.sixth_run_step_write_efuse()
|
||||
if not result or content != 'continue':
|
||||
return (result, content)
|
||||
result, content = self.seventh_run_step_erase()
|
||||
if not result or content != 'continue':
|
||||
return (result, content)
|
||||
result, content = self.eighth_run_step_read()
|
||||
if not result or content != 'continue':
|
||||
return (result, content)
|
||||
result, content = self.ninth_run_step_end()
|
||||
return (
|
||||
result, content)
|
||||
|
||||
|
||||
class BL702EflashLoader(BaseEflashLoader):
|
||||
__doc__ = '\n When chip is bl702, eflash Loader\n '
|
||||
|
||||
def __init__(self, chip_type, args, config, callback=None, macaddr_callback=None, create_simple_callback=None, create_img_callback=None, task_num=None):
|
||||
super().__init__(chip_type, args, config, callback, macaddr_callback, create_simple_callback, create_img_callback, task_num)
|
||||
self.chip_type = chip_type
|
||||
|
||||
def set_load_function(self):
|
||||
if self.chip_type == 'bl702':
|
||||
self.load_function = 0
|
||||
|
||||
def set_decompress_write(self):
|
||||
self.decompress_write = False
|
||||
|
||||
def get_flash_pin(self):
|
||||
return 255
|
||||
|
||||
def show_identify_fail(self):
|
||||
printf('eflash loader identify flash fail!')
|
||||
self.error_code_print('0043')
|
||||
return False
|
||||
|
||||
def reset_cpu(self, shakehand=0):
|
||||
printf('CPU Reset')
|
||||
if shakehand != 0:
|
||||
printf(FLASH_ERASE_SHAKE_HAND)
|
||||
if self.img_load_shake_hand() is False:
|
||||
return False
|
||||
cmd_id = hexstr_to_bytearray(self._com_cmds.get('reset')['cmd_id'])
|
||||
ret, dmy = self.com_process_one_cmd('reset', cmd_id, bytearray(0))
|
||||
if ret.startswith('OK'):
|
||||
return True
|
||||
self.error_code_print('0004')
|
||||
return False
|
||||
|
||||
def run_reset_cpu(self):
|
||||
if self.isp_mode_sign is True:
|
||||
self.reset_cpu()
|
||||
|
||||
def get_chip_id(self, bootinfo):
|
||||
chip_id = bootinfo[32:34] + bootinfo[34:36] + bootinfo[36:38] + bootinfo[38:40] + bootinfo[40:42] + bootinfo[42:44] + bootinfo[44:46] + bootinfo[46:48]
|
||||
return chip_id
|
||||
|
||||
def get_mac_len(self):
|
||||
return 8
|
||||
|
||||
def set_temp_timeout(self):
|
||||
self.bflb_serial_object.set_timeout(self._default_time_out)
|
||||
|
||||
def get_isp_sh_time(self):
|
||||
return self._isp_shakehand_timeout
|
||||
|
||||
def run_step(self):
|
||||
result, content = self.first_run_step_load_parameter()
|
||||
if not result or content != 'continue':
|
||||
return (result, content)
|
||||
result, content = self.second_run_step_shake_hand()
|
||||
if not result or content != 'continue':
|
||||
return (result, content)
|
||||
result, content = self.third_run_step_read_mac_address()
|
||||
if not result or content != 'continue':
|
||||
return (result, content)
|
||||
result, content = self.fourth_run_step_interact_chip()
|
||||
if not result or content != 'continue':
|
||||
return (result, content)
|
||||
result, content = self.fifth_run_step_write_flash_and_check()
|
||||
if not result or content != 'continue':
|
||||
return (result, content)
|
||||
result, content = self.sixth_run_step_write_efuse()
|
||||
if not result or content != 'continue':
|
||||
return (result, content)
|
||||
result, content = self.seventh_run_step_erase()
|
||||
if not result or content != 'continue':
|
||||
return (result, content)
|
||||
result, content = self.eighth_run_step_read()
|
||||
if not result or content != 'continue':
|
||||
return (result, content)
|
||||
result, content = self.ninth_run_step_end()
|
||||
return (
|
||||
result, content)
|
||||
|
||||
|
||||
class BL702LEflashLoader(BaseEflashLoader):
|
||||
__doc__ = '\n When chip is bl702l, eflash Loader\n '
|
||||
|
||||
def __init__(self, chip_type, args, config, callback=None, macaddr_callback=None, create_simple_callback=None, create_img_callback=None, task_num=None):
|
||||
super().__init__(chip_type, args, config, callback, macaddr_callback, create_simple_callback, create_img_callback, task_num)
|
||||
self.chip_type = chip_type
|
||||
|
||||
def reset_cpu(self, shakehand=0):
|
||||
printf('CPU Reset')
|
||||
if shakehand != 0:
|
||||
printf(FLASH_ERASE_SHAKE_HAND)
|
||||
if self.img_load_shake_hand() is False:
|
||||
return False
|
||||
cmd_id = hexstr_to_bytearray(self._com_cmds.get('reset')['cmd_id'])
|
||||
ret, dmy = self.com_process_one_cmd('reset', cmd_id, bytearray(0))
|
||||
if ret.startswith('OK'):
|
||||
return True
|
||||
self.error_code_print('0004')
|
||||
return False
|
||||
|
||||
def run_reset_cpu(self):
|
||||
if self.isp_mode_sign is True:
|
||||
self.reset_cpu()
|
||||
|
||||
def get_chip_id(self, bootinfo):
|
||||
chip_id = bootinfo[32:34] + bootinfo[34:36] + bootinfo[36:38] + bootinfo[38:40] + bootinfo[40:42] + bootinfo[42:44] + bootinfo[44:46] + bootinfo[46:48]
|
||||
return chip_id
|
||||
|
||||
def get_new_bh_data(self, section, bh_data, fp):
|
||||
if section == 'BOOTHEADER_CFG':
|
||||
fp.write(bh_data[100:116])
|
||||
|
||||
def get_mac_len(self):
|
||||
return 8
|
||||
|
||||
def set_temp_timeout(self):
|
||||
self.bflb_serial_object.set_timeout(self._default_time_out)
|
||||
|
||||
def get_isp_sh_time(self):
|
||||
return self._isp_shakehand_timeout
|
||||
|
||||
def get_flash_pin_from_bootinfo(self, chiptype, bootinfo):
|
||||
dev_info_data = bootinfo[30:32] + bootinfo[28:30] + bootinfo[26:28] + bootinfo[24:26]
|
||||
dev_info_data = int(dev_info_data, 16)
|
||||
flash_cfg = dev_info_data >> 26 & 7
|
||||
sf_reverse = dev_info_data >> 29 & 1
|
||||
sf_swap_cfg = dev_info_data >> 22 & 3
|
||||
if flash_cfg == 0:
|
||||
return 0
|
||||
if sf_reverse == 0:
|
||||
return sf_swap_cfg + 1
|
||||
return sf_swap_cfg + 5
|
||||
|
||||
def run_step(self):
|
||||
result, content = self.first_run_step_load_parameter()
|
||||
if not result or content != 'continue':
|
||||
return (result, content)
|
||||
result, content = self.second_run_step_shake_hand()
|
||||
if not result or content != 'continue':
|
||||
return (result, content)
|
||||
result, content = self.third_run_step_read_mac_address()
|
||||
if not result or content != 'continue':
|
||||
return (result, content)
|
||||
result, content = self.fourth_run_step_interact_chip()
|
||||
if not result or content != 'continue':
|
||||
return (result, content)
|
||||
result, content = self.fifth_run_step_write_flash_and_check()
|
||||
if not result or content != 'continue':
|
||||
return (result, content)
|
||||
result, content = self.sixth_run_step_write_efuse()
|
||||
if not result or content != 'continue':
|
||||
return (result, content)
|
||||
result, content = self.seventh_run_step_erase()
|
||||
if not result or content != 'continue':
|
||||
return (result, content)
|
||||
result, content = self.eighth_run_step_read()
|
||||
if not result or content != 'continue':
|
||||
return (result, content)
|
||||
result, content = self.ninth_run_step_end()
|
||||
return (
|
||||
result, content)
|
||||
|
||||
|
||||
class BL808EflashLoader(BaseEflashLoader):
|
||||
__doc__ = '\n When chip is bl808, eflash Loader\n '
|
||||
|
||||
def __init__(self, chip_type, args, config, callback=None, macaddr_callback=None, create_simple_callback=None, create_img_callback=None, task_num=None):
|
||||
super().__init__(chip_type, args, config, callback, macaddr_callback, create_simple_callback, create_img_callback, task_num)
|
||||
self.chip_type = chip_type
|
||||
|
||||
def set_clear_boot_status(self, shakehand=0):
|
||||
self.clear_boot_status(shakehand)
|
||||
|
||||
def get_new_bh_data(self, section, bh_data, fp):
|
||||
if section == 'BOOTHEADER_GROUP0_CFG':
|
||||
fp.write(bh_data[100:128])
|
||||
|
||||
def write_flash_data(self, file, start_addr, callback):
|
||||
fp = open_file(file, 'rb')
|
||||
flash_data = bytearray(fp.read())
|
||||
fp.close()
|
||||
flash_data_len = len(flash_data)
|
||||
end_addr = start_addr + flash_data_len - 1
|
||||
if start_addr <= 4096:
|
||||
if end_addr > 4096:
|
||||
ret, flash_read_data = self.flash_read_main_process(4096, 4096, 0, None, callback)
|
||||
if flash_read_data[0:4] == int_to_4bytearray_b(1112298054):
|
||||
printf('RF para already write at flash 0x1000 addr, replace it.')
|
||||
flash_data[4096:8192] = flash_read_data[0:4096]
|
||||
fp = open_file(file, 'wb')
|
||||
fp.write(flash_data)
|
||||
fp.close()
|
||||
|
||||
def is_conf_exist(self, flash_id):
|
||||
cfg_dir = app_path + '/utils/flash/bl808/'
|
||||
conf_name = self.get_suitable_conf_name(cfg_dir, flash_id)
|
||||
if os.path.isfile(cfg_dir + conf_name) is False:
|
||||
return False
|
||||
return True
|
||||
|
||||
def get_flash_pin_from_bootinfo(self, chiptype, bootinfo):
|
||||
sw_usage_data = bootinfo[22:24] + bootinfo[20:22] + bootinfo[18:20] + bootinfo[16:18]
|
||||
sw_usage_data = int(sw_usage_data, 16)
|
||||
return sw_usage_data >> 14 & 31
|
||||
|
||||
def run_step(self):
|
||||
result, content = self.first_run_step_load_parameter()
|
||||
if not result or content != 'continue':
|
||||
return (result, content)
|
||||
result, content = self.second_run_step_shake_hand()
|
||||
if not result or content != 'continue':
|
||||
return (result, content)
|
||||
result, content = self.third_run_step_read_mac_address()
|
||||
if not result or content != 'continue':
|
||||
return (result, content)
|
||||
result, content = self.fourth_run_step_interact_chip()
|
||||
if not result or content != 'continue':
|
||||
return (result, content)
|
||||
result, content = self.fifth_run_step_write_flash_and_check()
|
||||
if not result or content != 'continue':
|
||||
return (result, content)
|
||||
result, content = self.sixth_run_step_write_efuse()
|
||||
if not result or content != 'continue':
|
||||
return (result, content)
|
||||
result, content = self.seventh_run_step_erase()
|
||||
if not result or content != 'continue':
|
||||
return (result, content)
|
||||
result, content = self.eighth_run_step_read()
|
||||
if not result or content != 'continue':
|
||||
return (result, content)
|
||||
result, content = self.ninth_run_step_end()
|
||||
return (
|
||||
result, content)
|
||||
|
||||
|
||||
class OtherEflashLoader(BaseEflashLoader):
|
||||
__doc__ = '\n When chip is not bl602,bl702,bl702l,bl808,bl616.wb03, eflash Loader\n '
|
||||
|
||||
def __init__(self, chip_type, args, config, callback=None, macaddr_callback=None, create_simple_callback=None, create_img_callback=None, task_num=None):
|
||||
super().__init__(chip_type, args, config, callback, macaddr_callback, create_simple_callback, create_img_callback, task_num)
|
||||
self.chip_type = chip_type
|
||||
|
||||
def run_step(self):
|
||||
result, content = self.first_run_step_load_parameter()
|
||||
if not result or content != 'continue':
|
||||
return (result, content)
|
||||
if self.isp_mode_sign is True:
|
||||
self.load_function = 1
|
||||
result, content = self.second_run_step_shake_hand()
|
||||
if not result or content != 'continue':
|
||||
return (result, content)
|
||||
result, content = self.third_run_step_read_mac_address()
|
||||
if not result or content != 'continue':
|
||||
return (result, content)
|
||||
result, content = self.fourth_run_step_interact_chip()
|
||||
if not result or content != 'continue':
|
||||
return (result, content)
|
||||
result, content = self.fifth_run_step_write_flash_and_check()
|
||||
if not result or content != 'continue':
|
||||
return (result, content)
|
||||
result, content = self.sixth_run_step_write_efuse()
|
||||
if not result or content != 'continue':
|
||||
return (result, content)
|
||||
result, content = self.seventh_run_step_erase()
|
||||
if not result or content != 'continue':
|
||||
return (result, content)
|
||||
result, content = self.eighth_run_step_read()
|
||||
if not result or content != 'continue':
|
||||
return (result, content)
|
||||
result, content = self.ninth_run_step_end()
|
||||
return (
|
||||
result, content)
|
||||
# okay decompiling ./libs/bflb_eflash_loader.pyc
|
337
libs/bflb_interface_cklink.py
Normal file
337
libs/bflb_interface_cklink.py
Normal file
|
@ -0,0 +1,337 @@
|
|||
# decompyle3 version 3.9.0
|
||||
# Python bytecode version base 3.7.0 (3394)
|
||||
# Decompiled from: Python 3.7.16 (default, Mar 30 2023, 01:25:49)
|
||||
# [GCC 12.2.1 20220924]
|
||||
# Embedded file name: libs/bflb_interface_cklink.py
|
||||
import os, time, binascii, subprocess, config as gol, cklink
|
||||
from libs import bflb_utils
|
||||
from libs.bflb_utils import app_path
|
||||
dir_dll = os.path.join(app_path, 'utils/cklink')
|
||||
|
||||
class BflbCKLinkPort(object):
|
||||
|
||||
def __init__(self, vid=0, pid=0):
|
||||
self._speed = 5000
|
||||
self._rx_timeout = 10000
|
||||
self._cklink_shake_hand_addr = '20000000'
|
||||
self._cklink_data_addr = '20000004'
|
||||
self._cklink_run_addr = '22010000'
|
||||
self._cklink_reg_pc = 32
|
||||
self._inited = False
|
||||
self._chiptype = 'bl808'
|
||||
self._chipname = 'bl808'
|
||||
self.vid = vid
|
||||
self.pid = pid
|
||||
self.link = gol.obj_cklink
|
||||
|
||||
def if_init(self, device, sn, rate, chiptype='bl808', chipname='bl808'):
|
||||
if self._inited is False:
|
||||
dev = device.split('|')
|
||||
vid = int(dev[0].replace('0x', ''), 16)
|
||||
pid = int(dev[1].replace('0x', ''), 16)
|
||||
serial = str(sn)
|
||||
bflb_utils.printf('SN is ' + serial)
|
||||
sub_module = __import__(('libs.base.' + chiptype), fromlist=[chiptype])
|
||||
self._cklink_shake_hand_addr = sub_module.cklink_load_cfg.cklink_shake_hand_addr
|
||||
self._cklink_data_addr = sub_module.cklink_load_cfg.cklink_data_addr
|
||||
self._cklink_run_addr = sub_module.cklink_load_cfg.cklink_run_addr
|
||||
self._cklink_vid = vid
|
||||
self._cklink_pid = pid
|
||||
self._speed = rate
|
||||
self._inited = True
|
||||
self._chiptype = chiptype
|
||||
self._chipname = chipname
|
||||
if not self.link:
|
||||
self.link = cklink.CKLink(dlldir=dir_dll, vid=(self._cklink_vid), pid=(self._cklink_pid), sn=serial, arch=2, cdi=0)
|
||||
gol.obj_cklink = self.link
|
||||
self.link.open()
|
||||
if self.link.connected():
|
||||
self.link.reset(1)
|
||||
return False
|
||||
|
||||
def repeat_init(self, device, sn, rate, chiptype='bl808', chipname='bl808'):
|
||||
if self._inited is False:
|
||||
dev = device.split('|')
|
||||
vid = int(dev[0].replace('0x', ''), 16)
|
||||
pid = int(dev[1].replace('0x', ''), 16)
|
||||
serial = str(sn)
|
||||
bflb_utils.printf('SN is ' + serial)
|
||||
sub_module = __import__(('libs.base.' + chiptype), fromlist=[chiptype])
|
||||
self._cklink_shake_hand_addr = sub_module.cklink_load_cfg.cklink_shake_hand_addr
|
||||
self._cklink_data_addr = sub_module.cklink_load_cfg.cklink_data_addr
|
||||
self._cklink_run_addr = sub_module.cklink_load_cfg.cklink_run_addr
|
||||
self._cklink_vid = vid
|
||||
self._cklink_pid = pid
|
||||
self._speed = rate
|
||||
self._inited = True
|
||||
self._chiptype = chiptype
|
||||
self._chipname = chipname
|
||||
if not self.link:
|
||||
self.link = cklink.CKLink(dlldir=dir_dll, vid=(self._cklink_vid), pid=(self._cklink_pid), sn=serial, arch=2, cdi=0)
|
||||
gol.obj_cklink = self.link
|
||||
self.link.open()
|
||||
if self.link.connected():
|
||||
self.link.reset(1)
|
||||
return False
|
||||
|
||||
def if_close(self):
|
||||
if self.link:
|
||||
try:
|
||||
try:
|
||||
self.link.close()
|
||||
except Exception as e:
|
||||
try:
|
||||
print(e)
|
||||
finally:
|
||||
e = None
|
||||
del e
|
||||
|
||||
finally:
|
||||
self._inited = False
|
||||
|
||||
def close(self):
|
||||
if self.link:
|
||||
try:
|
||||
try:
|
||||
self.link.close()
|
||||
except Exception as e:
|
||||
try:
|
||||
print(e)
|
||||
finally:
|
||||
e = None
|
||||
del e
|
||||
|
||||
finally:
|
||||
self._inited = False
|
||||
|
||||
def if_clear_buf(self):
|
||||
pass
|
||||
|
||||
def clear_buf(self):
|
||||
pass
|
||||
|
||||
def if_set_rx_timeout(self, val):
|
||||
self._rx_timeout = val * 1000
|
||||
|
||||
def set_timeout(self, val):
|
||||
self._rx_timeout = val * 1000
|
||||
|
||||
def if_get_rate(self):
|
||||
return self._speed
|
||||
|
||||
def halt_cpu(self):
|
||||
return self.link.halt()
|
||||
|
||||
def resume_cpu(self):
|
||||
return self.link.resume()
|
||||
|
||||
def reset_cpu(self):
|
||||
return self.link.reset(1)
|
||||
|
||||
def set_pc_msp(self, pc, msp):
|
||||
self.halt_cpu()
|
||||
if self._chiptype == 'bl602' or self._chiptype == 'bl702' or self._chiptype == 'bl702l':
|
||||
addr = int(self._cklink_run_addr, 16)
|
||||
self.link.write_cpu_reg(self._cklink_reg_pc, addr)
|
||||
|
||||
def if_raw_write(self, addr, data_send):
|
||||
self.halt_cpu()
|
||||
addr_int = int(addr, 16)
|
||||
data_send = bytes(data_send)
|
||||
self.link.write_memory(addr_int, data_send)
|
||||
self.resume_cpu()
|
||||
|
||||
def if_write(self, data_send):
|
||||
self.if_raw_write(self._cklink_data_addr, data_send)
|
||||
self.if_raw_write(self._cklink_shake_hand_addr, binascii.unhexlify('48524459'))
|
||||
|
||||
def write(self, data_send):
|
||||
self.if_raw_write(self._cklink_data_addr, data_send)
|
||||
self.if_raw_write(self._cklink_shake_hand_addr, binascii.unhexlify('48524459'))
|
||||
|
||||
def if_read(self, data_len):
|
||||
start_time = time.time() * 1000
|
||||
while True:
|
||||
self.halt_cpu()
|
||||
ready = self.link.read_memory(int(self._cklink_shake_hand_addr, 16), 4)
|
||||
if len(ready) >= 1:
|
||||
ready = binascii.hexlify(ready).decode()
|
||||
if ready == '5341434b':
|
||||
self.resume_cpu()
|
||||
break
|
||||
elapsed = time.time() * 1000 - start_time
|
||||
if elapsed >= self._rx_timeout:
|
||||
return (0, 'waiting response time out'.encode('utf-8'))
|
||||
else:
|
||||
self.resume_cpu()
|
||||
time.sleep(0.001)
|
||||
|
||||
data = self.if_raw_read(self._cklink_data_addr, data_len)
|
||||
if len(data) != data_len:
|
||||
return (0, data)
|
||||
return (1, data)
|
||||
|
||||
def read(self, data_len):
|
||||
start_time = time.time() * 1000
|
||||
while True:
|
||||
self.halt_cpu()
|
||||
ready = self.link.read_memory(int(self._cklink_shake_hand_addr, 16), 4)
|
||||
if len(ready) >= 1:
|
||||
ready = binascii.hexlify(ready).decode()
|
||||
if ready == '5341434b':
|
||||
self.resume_cpu()
|
||||
break
|
||||
elapsed = time.time() * 1000 - start_time
|
||||
if elapsed >= self._rx_timeout:
|
||||
return (0, 'waiting response time out'.encode('utf-8'))
|
||||
else:
|
||||
self.resume_cpu()
|
||||
time.sleep(0.001)
|
||||
|
||||
data = self.if_raw_read(self._cklink_data_addr, data_len)
|
||||
if len(data) != data_len:
|
||||
return (0, data)
|
||||
return (1, data)
|
||||
|
||||
def if_raw_read(self, addr, data_len):
|
||||
return self.if_raw_read8(addr, data_len)
|
||||
|
||||
def if_raw_read8(self, addr, data_len):
|
||||
self.halt_cpu()
|
||||
data = self.link.read_memory(int(addr, 16), data_len)
|
||||
self.resume_cpu()
|
||||
return bytearray(data)
|
||||
|
||||
def if_shakehand(self, do_reset=False, reset_hold_time=100, shake_hand_delay=100, reset_revert=True, cutoff_time=0, shake_hand_retry=2, isp_timeout=0, boot_load=False):
|
||||
self.if_write(bytearray(1))
|
||||
success, ack = self.if_read(2)
|
||||
bflb_utils.printf(binascii.hexlify(ack))
|
||||
if ack.find(b'O') != -1 or ack.find(b'K') != -1:
|
||||
time.sleep(0.03)
|
||||
return 'OK'
|
||||
return 'FL'
|
||||
|
||||
def if_deal_ack(self):
|
||||
success, ack = self.if_read(2)
|
||||
if success == 0:
|
||||
bflb_utils.printf('ack:' + str(binascii.hexlify(ack)))
|
||||
return ack.decode('utf-8')
|
||||
if ack.find(b'O') != -1 or ack.find(b'K') != -1:
|
||||
return 'OK'
|
||||
if ack.find(b'P') != -1 or ack.find(b'D') != -1:
|
||||
return 'PD'
|
||||
success, err_code = self.if_read(4)
|
||||
if success == 0:
|
||||
bflb_utils.printf('err_code:' + str(binascii.hexlify(err_code)))
|
||||
return 'FL'
|
||||
err_code_str = str(binascii.hexlify(err_code[3:4] + err_code[2:3]).decode('utf-8'))
|
||||
ack = 'FL'
|
||||
try:
|
||||
ret = ack + err_code_str + '(' + bflb_utils.get_bflb_error_code(err_code_str) + ')'
|
||||
except Exception:
|
||||
ret = ack + err_code_str + ' unknown'
|
||||
|
||||
bflb_utils.printf(ret)
|
||||
return ret
|
||||
|
||||
def deal_ack(self):
|
||||
success, ack = self.if_read(2)
|
||||
if success == 0:
|
||||
bflb_utils.printf('ack:' + str(binascii.hexlify(ack)))
|
||||
return ack.decode('utf-8')
|
||||
if ack.find(b'O') != -1 or ack.find(b'K') != -1:
|
||||
return 'OK'
|
||||
if ack.find(b'P') != -1 or ack.find(b'D') != -1:
|
||||
return 'PD'
|
||||
success, err_code = self.if_read(4)
|
||||
if success == 0:
|
||||
bflb_utils.printf('err_code:' + str(binascii.hexlify(err_code)))
|
||||
return 'FL'
|
||||
err_code_str = str(binascii.hexlify(err_code[3:4] + err_code[2:3]).decode('utf-8'))
|
||||
ack = 'FL'
|
||||
try:
|
||||
ret = ack + err_code_str + '(' + bflb_utils.get_bflb_error_code(err_code_str) + ')'
|
||||
except Exception:
|
||||
ret = ack + err_code_str + ' unknown'
|
||||
|
||||
bflb_utils.printf(ret)
|
||||
return ret
|
||||
|
||||
def if_deal_response(self):
|
||||
ack = self.if_deal_ack()
|
||||
if ack == 'OK':
|
||||
success, len_bytes = self.if_read(16)
|
||||
if success == 0:
|
||||
bflb_utils.printf('Get length error')
|
||||
bflb_utils.printf(binascii.hexlify(len_bytes))
|
||||
return (
|
||||
'Get length error', len_bytes)
|
||||
tmp = bflb_utils.bytearray_reverse(len_bytes[2:4])
|
||||
data_len = bflb_utils.bytearray_to_int(tmp)
|
||||
success, data_bytes = self.if_read(data_len + 4)
|
||||
if success == 0:
|
||||
bflb_utils.printf('Read data error')
|
||||
return (
|
||||
'Read data error', data_bytes)
|
||||
data_bytes = data_bytes[4:]
|
||||
if len(data_bytes) != data_len:
|
||||
bflb_utils.printf('Not get excepted length')
|
||||
return (
|
||||
'Not get excepted length', data_bytes)
|
||||
return (ack, data_bytes)
|
||||
bflb_utils.printf('Not ack OK')
|
||||
bflb_utils.printf(ack)
|
||||
return (
|
||||
ack, None)
|
||||
|
||||
def deal_response(self):
|
||||
ack = self.if_deal_ack()
|
||||
if ack == 'OK':
|
||||
success, len_bytes = self.if_read(16)
|
||||
if success == 0:
|
||||
bflb_utils.printf('Get length error')
|
||||
bflb_utils.printf(binascii.hexlify(len_bytes))
|
||||
return (
|
||||
'Get length error', len_bytes)
|
||||
tmp = bflb_utils.bytearray_reverse(len_bytes[2:4])
|
||||
data_len = bflb_utils.bytearray_to_int(tmp)
|
||||
success, data_bytes = self.if_read(data_len + 4)
|
||||
if success == 0:
|
||||
bflb_utils.printf('Read data error')
|
||||
return (
|
||||
'Read data error', data_bytes)
|
||||
data_bytes = data_bytes[4:]
|
||||
if len(data_bytes) != data_len:
|
||||
bflb_utils.printf('Not get excepted length')
|
||||
return (
|
||||
'Not get excepted length', data_bytes)
|
||||
return (ack, data_bytes)
|
||||
bflb_utils.printf('Not ack OK')
|
||||
bflb_utils.printf(ack)
|
||||
return (
|
||||
ack, None)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
eflash_loader_t = BflbCKLinkPort()
|
||||
eflash_loader_t.if_init('', 100, 'bl702')
|
||||
bflb_utils.printf('read test')
|
||||
bflb_utils.printf(eflash_loader_t.if_raw_read('21000000', 2))
|
||||
bflb_utils.printf(eflash_loader_t.if_raw_read('21000000', 4))
|
||||
bflb_utils.printf(eflash_loader_t.if_raw_read('21000000', 10))
|
||||
bflb_utils.printf(eflash_loader_t.if_raw_read('21000000', 16))
|
||||
bflb_utils.printf(eflash_loader_t.if_raw_read('21000001', 2))
|
||||
bflb_utils.printf(eflash_loader_t.if_raw_read('21000001', 4))
|
||||
bflb_utils.printf(eflash_loader_t.if_raw_read('21000001', 10))
|
||||
bflb_utils.printf(eflash_loader_t.if_raw_read('21000001', 16))
|
||||
bflb_utils.printf(eflash_loader_t.if_raw_read('21000002', 2))
|
||||
bflb_utils.printf(eflash_loader_t.if_raw_read('21000002', 4))
|
||||
bflb_utils.printf(eflash_loader_t.if_raw_read('21000002', 10))
|
||||
bflb_utils.printf(eflash_loader_t.if_raw_read('21000002', 16))
|
||||
bflb_utils.printf('write test')
|
||||
data = bytearray([
|
||||
1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,
|
||||
4])
|
||||
eflash_loader_t.if_raw_write('42020000', data)
|
||||
bflb_utils.printf(eflash_loader_t.if_raw_read('42020000', 62))
|
||||
# okay decompiling ./libs/bflb_interface_cklink.pyc
|
631
libs/bflb_interface_eflash_loader.py
Normal file
631
libs/bflb_interface_eflash_loader.py
Normal file
|
@ -0,0 +1,631 @@
|
|||
# decompyle3 version 3.9.0
|
||||
# Python bytecode version base 3.7.0 (3394)
|
||||
# Decompiled from: Python 3.7.16 (default, Mar 30 2023, 01:25:49)
|
||||
# [GCC 12.2.1 20220924]
|
||||
# Embedded file name: libs/bflb_interface_eflash_loader.py
|
||||
__doc__ = '\nCreated on 20220909\n\n@author: Dillon\n'
|
||||
import os, sys, time, traceback, binascii
|
||||
from libs.base import bflb_img_loader
|
||||
from libs.bflb_utils import *
|
||||
from libs.bflb_eflash_loader import *
|
||||
|
||||
class InterfaceEflashLoader(object):
|
||||
|
||||
def __init__(self):
|
||||
self._temp_task_num = None
|
||||
|
||||
def error_code_print(self, code):
|
||||
set_error_code(code, self._temp_task_num)
|
||||
printf('{"ErrorCode": "' + code + '","ErrorMsg":"' + eflash_loader_error_code[code] + '"}')
|
||||
|
||||
def get_chip_type(self, interface, device, chip_type, callback):
|
||||
if interface.lower() == 'uart' or interface == 'sdio':
|
||||
boot_speed = 500000
|
||||
else:
|
||||
if chip_type == 'bl606p':
|
||||
return 'bl808'
|
||||
return chip_type
|
||||
_bflb_com_img_loader = bflb_img_loader.BflbImgLoader(device, boot_speed, boot_speed, (interface.lower()), callback=callback)
|
||||
bflb_serial_object = _bflb_com_img_loader.bflb_serial_object
|
||||
try:
|
||||
ret, bootinfo = _bflb_com_img_loader.img_get_bootinfo(boot_speed, boot_speed,
|
||||
callback=callback,
|
||||
do_reset=True,
|
||||
reset_hold_time=5,
|
||||
shake_hand_delay=100,
|
||||
reset_revert=False,
|
||||
cutoff_time=100,
|
||||
shake_hand_retry=2,
|
||||
isp_mode_sign=False,
|
||||
isp_timeout=0,
|
||||
boot_load=True)
|
||||
bootinfo = bootinfo.decode('utf-8')
|
||||
bflb_serial_object.close()
|
||||
if ret is False:
|
||||
_bflb_com_img_loader = bflb_img_loader.BflbImgLoader(device, boot_speed, boot_speed, (interface.lower()), 'bl808', callback=callback)
|
||||
bflb_serial_object = _bflb_com_img_loader.bflb_serial_object
|
||||
ret, bootinfo = _bflb_com_img_loader.img_get_bootinfo(boot_speed, boot_speed,
|
||||
callback=callback,
|
||||
do_reset=True,
|
||||
reset_hold_time=5,
|
||||
shake_hand_delay=100,
|
||||
reset_revert=False,
|
||||
cutoff_time=100,
|
||||
shake_hand_retry=2,
|
||||
isp_mode_sign=False,
|
||||
isp_timeout=0,
|
||||
boot_load=True)
|
||||
bootinfo = bootinfo.decode('utf-8')
|
||||
bflb_serial_object.close()
|
||||
if ret is False:
|
||||
self.error_code_print('0003')
|
||||
return 'Error: Can not get chip type!!'
|
||||
if '01000000' in bootinfo:
|
||||
return 'bl602'
|
||||
if '01000207' in bootinfo:
|
||||
return 'bl702'
|
||||
if '01001606' in bootinfo:
|
||||
return 'bl616'
|
||||
if '01000808' in bootinfo:
|
||||
return 'bl808'
|
||||
return 'Error: Can not get chip type!!'
|
||||
except Exception as e:
|
||||
try:
|
||||
self.error_code_print('0003')
|
||||
return 'Error: Can not get chip type!!'
|
||||
finally:
|
||||
e = None
|
||||
del e
|
||||
|
||||
def judge_result(self, temp_eflash_obj, result, args, start_time):
|
||||
do_reset = True
|
||||
reset_hold_time = 100
|
||||
shake_hand_delay = 100
|
||||
reset_revert = True
|
||||
cutoff_time = 0
|
||||
shake_hand_retry = 2
|
||||
if result == 'repeat_burn':
|
||||
temp_eflash_obj.close_serial()
|
||||
return 'repeat_burn'
|
||||
if temp_eflash_obj.cpu_reset is True:
|
||||
printf('Reset cpu')
|
||||
temp_eflash_obj.base_reset_cpu()
|
||||
if temp_eflash_obj.retry_delay_after_cpu_reset > 0:
|
||||
printf('delay for uart timeout: ', temp_eflash_obj.retry_delay_after_cpu_reset)
|
||||
time.sleep(temp_eflash_obj.retry_delay_after_cpu_reset)
|
||||
if result is True:
|
||||
printf('All time cost(ms): ', time.time() * 1000 - start_time)
|
||||
time.sleep(0.1)
|
||||
if not args.none:
|
||||
if temp_eflash_obj.bflb_serial_object is not None:
|
||||
temp_eflash_obj.close_serial()
|
||||
printf('close interface')
|
||||
printf('[All Success]')
|
||||
local_log_save('log', temp_eflash_obj.input_macaddr)
|
||||
if temp_eflash_obj.bflb_serial_object is not None:
|
||||
temp_eflash_obj.close_serial()
|
||||
return True
|
||||
if temp_eflash_obj.bflb_serial_object is not None:
|
||||
temp_eflash_obj.close_serial()
|
||||
return False
|
||||
|
||||
def run(self, act, config, callback=None):
|
||||
interface = config['param']['interface_type'].lower()
|
||||
error = None
|
||||
flash_burn_retry = 1
|
||||
clear_global()
|
||||
try:
|
||||
try:
|
||||
device = config['param']['comport_uart']
|
||||
if interface.lower() == 'uart':
|
||||
speed = config['param']['speed_uart']
|
||||
else:
|
||||
speed = config['param']['speed_jlink']
|
||||
if not speed.isdigit():
|
||||
error = '{"ErrorCode":"FFFF","ErrorMsg":"BAUDRATE MUST BE DIGIT"}'
|
||||
printf(error)
|
||||
return error
|
||||
chip_type = config['param']['chip_type']
|
||||
if act == 'download':
|
||||
options = [
|
||||
'--write', '--flash']
|
||||
try:
|
||||
if config['check_box']['efuse']:
|
||||
options.extend(['--efuse'])
|
||||
except:
|
||||
pass
|
||||
|
||||
parser = eflash_loader_parser_init()
|
||||
args = parser.parse_args(options)
|
||||
start_time = time.time() * 1000
|
||||
if 'Error' in chip_type:
|
||||
error = '{"ErrorCode":"FFFF","ErrorMsg":"BFLB CAN NOT GET CHIP TYPE"}'
|
||||
printf(error)
|
||||
return error
|
||||
config['param']['chip_xtal'] = 'auto'
|
||||
if chip_type == 'bl602':
|
||||
config['param']['chip_xtal'] = '40m'
|
||||
temp_eflash_obj = BL602EflashLoader(chip_type, args, config, callback)
|
||||
else:
|
||||
if chip_type == 'bl702':
|
||||
config['param']['chip_xtal'] = '32m'
|
||||
temp_eflash_obj = BL702EflashLoader(chip_type, args, config, callback)
|
||||
else:
|
||||
if chip_type == 'bl702l':
|
||||
config['param']['chip_xtal'] = '32m'
|
||||
temp_eflash_obj = BL702LEflashLoader(chip_type, args, config, callback)
|
||||
else:
|
||||
if chip_type == 'bl808' or chip_type == 'bl606p':
|
||||
temp_eflash_obj = BL808EflashLoader(chip_type, args, config, callback)
|
||||
else:
|
||||
if chip_type == 'bl616' or chip_type == 'wb03':
|
||||
temp_eflash_obj = BL616EflashLoader(chip_type, args, config, callback)
|
||||
else:
|
||||
if chip_type == 'bl628':
|
||||
temp_eflash_obj = BL628EflashLoader(chip_type, args, config, callback)
|
||||
else:
|
||||
temp_eflash_obj = OtherEflashLoader(chip_type, args, config, callback)
|
||||
while flash_burn_retry:
|
||||
retry = -1
|
||||
if temp_eflash_obj.bflb_serial_object is not None:
|
||||
temp_eflash_obj.close_serial()
|
||||
else:
|
||||
printf('Program Start')
|
||||
result, content = temp_eflash_obj.run_step()
|
||||
self._temp_task_num = temp_eflash_obj.task_num
|
||||
temp_result = self.judge_result(temp_eflash_obj, result, args, start_time)
|
||||
if temp_result:
|
||||
return True
|
||||
printf('Burn Retry')
|
||||
flash_burn_retry -= 1
|
||||
|
||||
printf('Burn return with retry fail')
|
||||
local_log_save('log', temp_eflash_obj.input_macaddr)
|
||||
error = errorcode_msg(self._temp_task_num)
|
||||
except Exception as e:
|
||||
try:
|
||||
traceback.print_exc(limit=10, file=(sys.stdout))
|
||||
error = str(e)
|
||||
finally:
|
||||
e = None
|
||||
del e
|
||||
|
||||
finally:
|
||||
return error
|
||||
|
||||
def program_read_id(self, config, callback=None):
|
||||
flash_burn_retry = 1
|
||||
interface = config['param']['interface_type']
|
||||
device = config['param']['comport_uart']
|
||||
if interface.lower() == 'uart':
|
||||
speed = config['param']['speed_uart']
|
||||
else:
|
||||
speed = config['param']['speed_jlink']
|
||||
chip_type = config['param']['chip_type']
|
||||
try:
|
||||
if not (config['param']['speed_uart'].isdigit() and config['param']['speed_jlink'].isdigit()):
|
||||
ret = '{"ErrorCode":"FFFF","ErrorMsg":"BAUDRATE MUST BE DIGIT"}'
|
||||
printf(ret)
|
||||
return (
|
||||
False, ret)
|
||||
set_error_code('FFFF')
|
||||
start_time = time.time() * 1000
|
||||
eflash_loader_cfg_tmp = os.path.join(chip_path, chip_type, 'eflash_loader/eflash_loader_cfg.ini')
|
||||
options = ['--none', '--flash', '-c', eflash_loader_cfg_tmp]
|
||||
parser_eflash = eflash_loader_parser_init()
|
||||
args = parser_eflash.parse_args(options)
|
||||
config['param']['chip_xtal'] = 'auto'
|
||||
if chip_type == 'bl602':
|
||||
config['param']['chip_xtal'] = '40m'
|
||||
temp_eflash_obj = BL602EflashLoader(chip_type, args, config, callback)
|
||||
else:
|
||||
if chip_type == 'bl702':
|
||||
config['param']['chip_xtal'] = '32m'
|
||||
temp_eflash_obj = BL702EflashLoader(chip_type, args, config, callback)
|
||||
else:
|
||||
if chip_type == 'bl702l':
|
||||
config['param']['chip_xtal'] = '32m'
|
||||
temp_eflash_obj = BL702LEflashLoader(chip_type, args, config, callback)
|
||||
else:
|
||||
if chip_type == 'bl808' or chip_type == 'bl606p':
|
||||
temp_eflash_obj = BL808EflashLoader(chip_type, args, config, callback)
|
||||
else:
|
||||
if chip_type == 'bl616' or chip_type == 'wb03':
|
||||
temp_eflash_obj = BL616EflashLoader(chip_type, args, config, callback)
|
||||
else:
|
||||
if chip_type == 'bl628':
|
||||
temp_eflash_obj = BL628EflashLoader(chip_type, args, config, callback)
|
||||
else:
|
||||
temp_eflash_obj = OtherEflashLoader(chip_type, args, config, callback)
|
||||
result, content = temp_eflash_obj.run_step()
|
||||
ret, data = temp_eflash_obj.flash_read_jedec_id_process()
|
||||
temp_eflash_obj.object_status_clear()
|
||||
self._temp_task_num = temp_eflash_obj.task_num
|
||||
if ret:
|
||||
data = binascii.hexlify(data).decode('utf-8')
|
||||
if temp_eflash_obj.bflb_serial_object is not None:
|
||||
temp_eflash_obj.close_serial()
|
||||
return (ret, data)
|
||||
except Exception as e:
|
||||
try:
|
||||
ret = str(e)
|
||||
printf('error:' + ret)
|
||||
return (
|
||||
False, ret)
|
||||
finally:
|
||||
e = None
|
||||
del e
|
||||
|
||||
def program_read_reg(self, config, callback=None):
|
||||
flash_burn_retry = 1
|
||||
interface = config['param']['interface_type']
|
||||
device = config['param']['comport_uart']
|
||||
if interface.lower() == 'uart':
|
||||
speed = config['param']['speed_uart']
|
||||
else:
|
||||
speed = config['param']['speed_jlink']
|
||||
chip_type = config['param']['chip_type']
|
||||
try:
|
||||
if not (config['param']['speed_uart'].isdigit() and config['param']['speed_jlink'].isdigit()):
|
||||
ret = '{"ErrorCode":"FFFF","ErrorMsg":"BAUDRATE MUST BE DIGIT"}'
|
||||
printf(ret)
|
||||
return (
|
||||
False, ret)
|
||||
set_error_code('FFFF')
|
||||
start_time = time.time() * 1000
|
||||
eflash_loader_cfg_tmp = os.path.join(chip_path, chip_type, 'eflash_loader/eflash_loader_cfg.ini')
|
||||
options = ['--none', '--flash', '-c', eflash_loader_cfg_tmp]
|
||||
parser_eflash = eflash_loader_parser_init()
|
||||
args = parser_eflash.parse_args(options)
|
||||
config['param']['chip_xtal'] = 'auto'
|
||||
if chip_type == 'bl602':
|
||||
config['param']['chip_xtal'] = '40m'
|
||||
temp_eflash_obj = BL602EflashLoader(chip_type, args, config, callback)
|
||||
else:
|
||||
if chip_type == 'bl702':
|
||||
config['param']['chip_xtal'] = '32m'
|
||||
temp_eflash_obj = BL702EflashLoader(chip_type, args, config, callback)
|
||||
else:
|
||||
if chip_type == 'bl702l':
|
||||
config['param']['chip_xtal'] = '32m'
|
||||
temp_eflash_obj = BL702LEflashLoader(chip_type, args, config, callback)
|
||||
else:
|
||||
if chip_type == 'bl808' or chip_type == 'bl606p':
|
||||
temp_eflash_obj = BL808EflashLoader(chip_type, args, config, callback)
|
||||
else:
|
||||
if chip_type == 'bl616' or chip_type == 'wb03':
|
||||
temp_eflash_obj = BL616EflashLoader(chip_type, args, config, callback)
|
||||
else:
|
||||
if chip_type == 'bl628':
|
||||
temp_eflash_obj = BL628EflashLoader(chip_type, args, config, callback)
|
||||
else:
|
||||
temp_eflash_obj = OtherEflashLoader(chip_type, args, config, callback)
|
||||
result, content = temp_eflash_obj.run_step()
|
||||
temp_eflash_obj.object_status_clear()
|
||||
cmd = config['cmd']
|
||||
length = int(config['len'])
|
||||
cmd_value = int(cmd, 16)
|
||||
if cmd_value != 5:
|
||||
if cmd_value != 53:
|
||||
if cmd_value != 21:
|
||||
temp_eflash_obj.close_serial()
|
||||
ret = 'read register command value not recognize'
|
||||
printf(ret)
|
||||
return (
|
||||
False, ret)
|
||||
if length > 3:
|
||||
temp_eflash_obj.close_serial()
|
||||
ret = 'read register len is too long'
|
||||
printf(ret)
|
||||
return (
|
||||
False, ret)
|
||||
ret, data = temp_eflash_obj.flash_read_status_reg_process(cmd, length)
|
||||
if ret:
|
||||
data = binascii.hexlify(data).decode('utf-8')
|
||||
if temp_eflash_obj.bflb_serial_object is not None:
|
||||
temp_eflash_obj.close_serial()
|
||||
self._temp_task_num = temp_eflash_obj.task_num
|
||||
return (
|
||||
ret, data)
|
||||
except Exception as e:
|
||||
try:
|
||||
ret = str(e)
|
||||
printf('error:' + ret)
|
||||
return (
|
||||
False, ret)
|
||||
finally:
|
||||
e = None
|
||||
del e
|
||||
|
||||
def program_write_reg(self, config, callback=None):
|
||||
ret = None
|
||||
flash_burn_retry = 1
|
||||
interface = config['param']['interface_type']
|
||||
device = config['param']['comport_uart']
|
||||
if interface.lower() == 'uart':
|
||||
speed = config['param']['speed_uart']
|
||||
else:
|
||||
speed = config['param']['speed_jlink']
|
||||
chip_type = config['param']['chip_type']
|
||||
try:
|
||||
if not device:
|
||||
if interface.lower() == 'uart':
|
||||
ret = '{"ErrorCode":"FFFF","ErrorMsg":"BFLB INTERFACE HAS NO COM PORT"}'
|
||||
printf(ret)
|
||||
return (
|
||||
False, ret)
|
||||
if not (config['param']['speed_uart'].isdigit() and config['param']['speed_jlink'].isdigit()):
|
||||
ret = '{"ErrorCode":"FFFF","ErrorMsg":"BAUDRATE MUST BE DIGIT"}'
|
||||
printf(ret)
|
||||
return (
|
||||
False, ret)
|
||||
set_error_code('FFFF')
|
||||
start_time = time.time() * 1000
|
||||
eflash_loader_cfg_tmp = os.path.join(chip_path, chip_type, 'eflash_loader/eflash_loader_cfg.ini')
|
||||
options = ['--none', '--flash', '-c', eflash_loader_cfg_tmp]
|
||||
parser_eflash = eflash_loader_parser_init()
|
||||
args = parser_eflash.parse_args(options)
|
||||
config['param']['chip_xtal'] = 'auto'
|
||||
if chip_type == 'bl602':
|
||||
config['param']['chip_xtal'] = '40m'
|
||||
temp_eflash_obj = BL602EflashLoader(chip_type, args, config, callback)
|
||||
else:
|
||||
if chip_type == 'bl702':
|
||||
config['param']['chip_xtal'] = '32m'
|
||||
temp_eflash_obj = BL702EflashLoader(chip_type, args, config, callback)
|
||||
else:
|
||||
if chip_type == 'bl702l':
|
||||
config['param']['chip_xtal'] = '32m'
|
||||
temp_eflash_obj = BL702LEflashLoader(chip_type, args, config, callback)
|
||||
else:
|
||||
if chip_type == 'bl808' or chip_type == 'bl606p':
|
||||
temp_eflash_obj = BL808EflashLoader(chip_type, args, config, callback)
|
||||
else:
|
||||
if chip_type == 'bl616' or chip_type == 'wb03':
|
||||
temp_eflash_obj = BL616EflashLoader(chip_type, args, config, callback)
|
||||
else:
|
||||
if chip_type == 'bl628':
|
||||
temp_eflash_obj = BL628EflashLoader(chip_type, args, config, callback)
|
||||
else:
|
||||
temp_eflash_obj = OtherEflashLoader(chip_type, args, config, callback)
|
||||
result, content = temp_eflash_obj.run_step()
|
||||
temp_eflash_obj.object_status_clear()
|
||||
cmd = config['cmd']
|
||||
length = int(config['len'])
|
||||
val = config['val']
|
||||
cmd_value = int(cmd, 16)
|
||||
if cmd_value != 1:
|
||||
if cmd_value != 49:
|
||||
if cmd_value != 17:
|
||||
temp_eflash_obj.close_serial()
|
||||
ret = 'write register command value not recognize'
|
||||
printf(ret)
|
||||
return (
|
||||
False, ret)
|
||||
if length > 3:
|
||||
temp_eflash_obj.close_serial()
|
||||
ret = 'write register len is too long'
|
||||
printf(ret)
|
||||
return (
|
||||
False, ret)
|
||||
ret, data = temp_eflash_obj.flash_write_status_reg_process(cmd, length, val)
|
||||
temp_eflash_obj.close_serial()
|
||||
self._temp_task_num = temp_eflash_obj.task_num
|
||||
return (
|
||||
ret, data)
|
||||
except Exception as e:
|
||||
try:
|
||||
ret = str(e)
|
||||
printf('error:' + ret)
|
||||
return (
|
||||
False, ret)
|
||||
finally:
|
||||
e = None
|
||||
del e
|
||||
|
||||
def read_flash_thread(self, config, callback=None):
|
||||
ret = None
|
||||
flash_burn_retry = 1
|
||||
interface = config['param']['interface_type']
|
||||
device = config['param']['comport_uart']
|
||||
if interface.lower() == 'uart':
|
||||
speed = config['param']['speed_uart']
|
||||
else:
|
||||
speed = config['param']['speed_jlink']
|
||||
chip_type = config['param']['chip_type']
|
||||
try:
|
||||
try:
|
||||
if not device:
|
||||
if interface.lower() == 'uart':
|
||||
ret = '{"ErrorCode":"FFFF","ErrorMsg":"BFLB INTERFACE HAS NO COM PORT"}'
|
||||
printf(ret)
|
||||
return (
|
||||
False, ret)
|
||||
if not (config['param']['speed_uart'].isdigit() and config['param']['speed_jlink'].isdigit()):
|
||||
ret = '{"ErrorCode":"FFFF","ErrorMsg":"BAUDRATE MUST BE DIGIT"}'
|
||||
printf(ret)
|
||||
return (
|
||||
False, ret)
|
||||
set_error_code('FFFF')
|
||||
start_time = time.time() * 1000
|
||||
eflash_loader_cfg_tmp = os.path.join(chip_path, chip_type, 'eflash_loader/eflash_loader_cfg.ini')
|
||||
if verify_hex_num(config['start_addr'][2:]) is True:
|
||||
if config['start_addr'][0:2] == '0x':
|
||||
start = config['start_addr'][2:]
|
||||
else:
|
||||
printf('Error, start_addr is HEX data, must begin with 0x')
|
||||
ret = 'start_addr is HEX data, must begin with 0x'
|
||||
else:
|
||||
printf('Error, Please check start_addr hex data')
|
||||
ret = 'Please check start_addr hex data'
|
||||
if verify_hex_num(config['end_addr'][2:]) is True:
|
||||
if config['end_addr'][0:2] == '0x':
|
||||
end = config['end_addr'][2:]
|
||||
else:
|
||||
printf('Error, end_addr is HEX data, must begin with 0x')
|
||||
ret = 'end_addr is HEX data, must begin with 0x'
|
||||
else:
|
||||
printf('Error, Please check end_addr hex data')
|
||||
ret = 'Please check end_addr hex data'
|
||||
if int(start, 16) >= int(end, 16):
|
||||
printf('Error, Start addr must less than end addr')
|
||||
ret = 'Start addr must less than end addr'
|
||||
if ret is not None:
|
||||
return ret
|
||||
printf('Save as flash.bin')
|
||||
options = ['--read', '--flash', '--start=' + start, '--end=' + end, '--file=flash.bin', '-c', eflash_loader_cfg_tmp]
|
||||
parser_eflash = eflash_loader_parser_init()
|
||||
args = parser_eflash.parse_args(options)
|
||||
config['param']['chip_xtal'] = 'auto'
|
||||
if chip_type == 'bl602':
|
||||
config['param']['chip_xtal'] = '40m'
|
||||
temp_eflash_obj = BL602EflashLoader(chip_type, args, config, callback)
|
||||
else:
|
||||
if chip_type == 'bl702':
|
||||
config['param']['chip_xtal'] = '32m'
|
||||
temp_eflash_obj = BL702EflashLoader(chip_type, args, config, callback)
|
||||
else:
|
||||
if chip_type == 'bl702l':
|
||||
config['param']['chip_xtal'] = '32m'
|
||||
temp_eflash_obj = BL702LEflashLoader(chip_type, args, config, callback)
|
||||
else:
|
||||
if chip_type == 'bl808' or chip_type == 'bl606p':
|
||||
temp_eflash_obj = BL808EflashLoader(chip_type, args, config, callback)
|
||||
else:
|
||||
if chip_type == 'bl616' or chip_type == 'wb03':
|
||||
temp_eflash_obj = BL616EflashLoader(chip_type, args, config, callback)
|
||||
else:
|
||||
if chip_type == 'bl628':
|
||||
temp_eflash_obj = BL628EflashLoader(chip_type, args, config, callback)
|
||||
else:
|
||||
temp_eflash_obj = OtherEflashLoader(chip_type, args, config, callback)
|
||||
result, content = temp_eflash_obj.run_step()
|
||||
temp_eflash_obj.object_status_clear()
|
||||
self._temp_task_num = temp_eflash_obj.task_num
|
||||
temp_result = self.judge_result(temp_eflash_obj, result, args, start_time)
|
||||
if temp_result:
|
||||
return True
|
||||
printf('Burn Retry')
|
||||
flash_burn_retry -= 1
|
||||
printf('Burn return with retry fail')
|
||||
local_log_save('log', temp_eflash_obj.input_macaddr)
|
||||
ret = errorcode_msg(self._temp_task_num)
|
||||
except Exception as e:
|
||||
try:
|
||||
ret = str(e)
|
||||
finally:
|
||||
e = None
|
||||
del e
|
||||
|
||||
finally:
|
||||
return ret
|
||||
|
||||
def erase_flash_thread(self, config, callback=None):
|
||||
options = ''
|
||||
start = ''
|
||||
end = ''
|
||||
ret = None
|
||||
flash_burn_retry = 1
|
||||
interface = config['param']['interface_type']
|
||||
device = config['param']['comport_uart']
|
||||
if interface.lower() == 'uart':
|
||||
speed = config['param']['speed_uart']
|
||||
else:
|
||||
speed = config['param']['speed_jlink']
|
||||
chip_type = config['param']['chip_type']
|
||||
start_time = time.time() * 1000
|
||||
try:
|
||||
try:
|
||||
if verify_hex_num(config['start_addr'][2:]) is True:
|
||||
if config['start_addr'][0:2] == '0x':
|
||||
start = config['start_addr'][2:]
|
||||
else:
|
||||
printf('Error, start_addr is HEX data, must begin with 0x')
|
||||
ret = 'start_addr is HEX data, must begin with 0x'
|
||||
else:
|
||||
if config['whole_chip'] is False:
|
||||
printf('Error, Please check start_addr hex data')
|
||||
ret = 'Please check start_addr hex data'
|
||||
if verify_hex_num(config['end_addr'][2:]) is True:
|
||||
if config['end_addr'][0:2] == '0x':
|
||||
end = config['end_addr'][2:]
|
||||
else:
|
||||
printf('Error, end_addr is HEX data, must begin with 0x')
|
||||
ret = 'end_addr is HEX data, must begin with 0x'
|
||||
else:
|
||||
if config['whole_chip'] is False:
|
||||
printf('Error, Please check end_addr hex data')
|
||||
ret = 'Please check end_addr hex data'
|
||||
if config['whole_chip'] is False:
|
||||
if int(start, 16) >= int(end, 16):
|
||||
printf('Error, Start addr must less than end addr')
|
||||
ret = 'Start addr must less than end addr'
|
||||
if ret is not None:
|
||||
return ret
|
||||
eflash_loader_cfg_tmp = os.path.join(chip_path, chip_type, 'eflash_loader/eflash_loader_cfg.ini')
|
||||
if config['whole_chip'] is True:
|
||||
options = [
|
||||
'--erase','--flash','--end=0','-c',eflash_loader_cfg_tmp]
|
||||
else:
|
||||
options = [
|
||||
'--erase', '--flash', '--start=' + start, '--end=' + end, '-c', eflash_loader_cfg_tmp]
|
||||
parser_eflash = eflash_loader_parser_init()
|
||||
args = parser_eflash.parse_args(options)
|
||||
config['param']['chip_xtal'] = 'auto'
|
||||
if chip_type == 'bl602':
|
||||
config['param']['chip_xtal'] = '40m'
|
||||
temp_eflash_obj = BL602EflashLoader(chip_type, args, config, callback)
|
||||
else:
|
||||
if chip_type == 'bl702':
|
||||
config['param']['chip_xtal'] = '32m'
|
||||
temp_eflash_obj = BL702EflashLoader(chip_type, args, config, callback)
|
||||
else:
|
||||
if chip_type == 'bl702l':
|
||||
config['param']['chip_xtal'] = '32m'
|
||||
temp_eflash_obj = BL702LEflashLoader(chip_type, args, config, callback)
|
||||
else:
|
||||
if chip_type == 'bl808' or chip_type == 'bl606p':
|
||||
temp_eflash_obj = BL808EflashLoader(chip_type, args, config, callback)
|
||||
else:
|
||||
if chip_type == 'bl616' or chip_type == 'wb03':
|
||||
temp_eflash_obj = BL616EflashLoader(chip_type, args, config, callback)
|
||||
else:
|
||||
if chip_type == 'bl628':
|
||||
temp_eflash_obj = BL628EflashLoader(chip_type, args, config, callback)
|
||||
else:
|
||||
temp_eflash_obj = OtherEflashLoader(chip_type, args, config, callback)
|
||||
result, content = temp_eflash_obj.run_step()
|
||||
temp_eflash_obj.object_status_clear()
|
||||
self._temp_task_num = temp_eflash_obj.task_num
|
||||
temp_result = self.judge_result(temp_eflash_obj, result, args, start_time)
|
||||
if temp_result:
|
||||
return True
|
||||
printf('Burn Retry')
|
||||
flash_burn_retry -= 1
|
||||
printf('Burn return with retry fail')
|
||||
local_log_save('log', temp_eflash_obj.input_macaddr)
|
||||
ret = errorcode_msg(self._temp_task_num)
|
||||
except Exception as e:
|
||||
try:
|
||||
ret = str(e)
|
||||
finally:
|
||||
e = None
|
||||
del e
|
||||
|
||||
finally:
|
||||
return ret
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
act = 'download'
|
||||
config_value_dict = {
|
||||
'interface_type': 'uart',
|
||||
'comport_uart': 'COM28',
|
||||
'speed_uart': '2000000',
|
||||
'chip_xtal': '40M',
|
||||
'verify': 'False',
|
||||
'ckb_erase_all': 'False'}
|
||||
config = {'param': config_value_dict}
|
||||
iel = InterfaceEflashLoader()
|
||||
iel.run(act, config)
|
||||
# okay decompiling ./libs/bflb_interface_eflash_loader.pyc
|
401
libs/bflb_interface_jlink.py
Normal file
401
libs/bflb_interface_jlink.py
Normal file
|
@ -0,0 +1,401 @@
|
|||
# decompyle3 version 3.9.0
|
||||
# Python bytecode version base 3.7.0 (3394)
|
||||
# Decompiled from: Python 3.7.16 (default, Mar 30 2023, 01:25:49)
|
||||
# [GCC 12.2.1 20220924]
|
||||
# Embedded file name: libs/bflb_interface_jlink.py
|
||||
import re, os, sys, time, binascii, traceback, struct, subprocess, pylink
|
||||
from libs import bflb_utils
|
||||
from libs.bflb_utils import app_path
|
||||
python_version = struct.calcsize('P') * 8
|
||||
if python_version == 64:
|
||||
path_dll = os.path.join(app_path, 'utils/jlink', 'JLink_x64.dll')
|
||||
else:
|
||||
path_dll = os.path.join(app_path, 'utils/jlink', 'JLinkARM.dll')
|
||||
|
||||
class BflbJLinkPort(object):
|
||||
|
||||
def __init__(self):
|
||||
self._speed = 5000
|
||||
self._rx_timeout = 10000
|
||||
self._jlink_shake_hand_addr = '20000000'
|
||||
self._jlink_data_addr = '20000004'
|
||||
self._inited = False
|
||||
self._chiptype = 'bl60x'
|
||||
self._chipname = 'bl60x'
|
||||
self._jlink_run_addr = '22010000'
|
||||
|
||||
def if_init(self, device, rate, chiptype='bl60x', chipname='bl60x'):
|
||||
if self._inited is False:
|
||||
sub_module = __import__(('libs.base.' + chiptype), fromlist=[chiptype])
|
||||
self._jlink_shake_hand_addr = sub_module.jlink_load_cfg.jlink_shake_hand_addr
|
||||
self._jlink_data_addr = sub_module.jlink_load_cfg.jlink_data_addr
|
||||
if sys.platform == 'win32':
|
||||
obj_dll = pylink.Library(dllpath=path_dll)
|
||||
self._jlink = pylink.JLink(lib=obj_dll)
|
||||
self.jlink_path = os.path.join(app_path, 'utils/jlink', 'JLink.exe')
|
||||
else:
|
||||
self._jlink = pylink.JLink()
|
||||
self.jlink_path = 'JLinkExe'
|
||||
match = re.search('\\d{8,10}', device, re.I)
|
||||
if match is not None:
|
||||
bflb_utils.printf(device)
|
||||
self._jlink.open(serial_no=(int(device)))
|
||||
else:
|
||||
self._jlink.open()
|
||||
tif_set = sub_module.jlink_load_cfg.jlink_set_tif
|
||||
self._jlink.set_tif(tif_set)
|
||||
self._speed = rate
|
||||
core_type = sub_module.jlink_load_cfg.jlink_core_type
|
||||
self._jlink.connect(core_type, rate)
|
||||
self._inited = True
|
||||
self._chiptype = chiptype
|
||||
self._chipname = chipname
|
||||
self._jlink_run_addr = sub_module.jlink_load_cfg.jlink_run_addr
|
||||
self._device = device
|
||||
|
||||
def repeat_init(self, device, rate, chiptype='bl60x', chipname='bl60x'):
|
||||
if self._inited is False:
|
||||
sub_module = __import__(('libs.base.' + chiptype), fromlist=[chiptype])
|
||||
self._jlink_shake_hand_addr = sub_module.jlink_load_cfg.jlink_shake_hand_addr
|
||||
self._jlink_data_addr = sub_module.jlink_load_cfg.jlink_data_addr
|
||||
if sys.platform == 'win32':
|
||||
obj_dll = pylink.Library(dllpath=path_dll)
|
||||
self._jlink = pylink.JLink(lib=obj_dll)
|
||||
self.jlink_path = os.path.join(app_path, 'utils/jlink', 'JLink.exe')
|
||||
else:
|
||||
self._jlink = pylink.JLink()
|
||||
self.jlink_path = 'JLinkExe'
|
||||
match = re.search('\\d{8,10}', device, re.I)
|
||||
if match is not None:
|
||||
bflb_utils.printf(device)
|
||||
self._jlink.open(serial_no=(int(device)))
|
||||
else:
|
||||
self._jlink.open()
|
||||
tif_set = sub_module.jlink_load_cfg.jlink_set_tif
|
||||
self._jlink.set_tif(tif_set)
|
||||
self._speed = rate
|
||||
core_type = sub_module.jlink_load_cfg.jlink_core_type
|
||||
self._jlink.connect(core_type, rate)
|
||||
self._inited = True
|
||||
self._chiptype = chiptype
|
||||
self._chipname = chipname
|
||||
self._jlink_run_addr = sub_module.jlink_load_cfg.jlink_run_addr
|
||||
self._device = device
|
||||
|
||||
def if_clear_buf(self):
|
||||
pass
|
||||
|
||||
def clear_buf(self):
|
||||
pass
|
||||
|
||||
def if_set_rx_timeout(self, val):
|
||||
self._rx_timeout = val * 1000
|
||||
|
||||
def set_timeout(self, val):
|
||||
self._rx_timeout = val * 1000
|
||||
|
||||
def if_get_rate(self):
|
||||
return self._speed
|
||||
|
||||
def halt_cpu(self):
|
||||
if self._jlink.halted() is False:
|
||||
self._jlink.halt()
|
||||
if self._jlink.halted():
|
||||
return True
|
||||
bflb_utils.printf("couldn't halt cpu")
|
||||
return False
|
||||
|
||||
def reset_cpu(self, ms=0, halt=True):
|
||||
if self._chiptype != 'bl60x':
|
||||
self._jlink.set_reset_pin_low()
|
||||
self._jlink.set_reset_pin_high()
|
||||
return self._jlink.reset(ms, False)
|
||||
|
||||
def set_pc_msp(self, pc, msp):
|
||||
if self._jlink.halted() is False:
|
||||
self._jlink.halt()
|
||||
if self._jlink.halted():
|
||||
if self._chiptype == 'bl602' or self._chiptype == 'bl702' or self._chiptype == 'bl702l':
|
||||
jlink_script = 'jlink.cmd'
|
||||
fp = open(jlink_script, 'w+')
|
||||
cmd = 'h\r\nSetPC ' + str(self._jlink_run_addr) + '\r\nexit'
|
||||
bflb_utils.printf(cmd)
|
||||
fp.write(cmd)
|
||||
fp.close()
|
||||
if self._device:
|
||||
jlink_cmd = self.jlink_path + ' -device RISC-V -Speed {0} -SelectEmuBySN {1} -IF JTAG -jtagconf -1,-1 -autoconnect 1 -CommanderScript jlink.cmd'.format(str(self._speed), str(self._device))
|
||||
else:
|
||||
jlink_cmd = self.jlink_path + ' -device RISC-V -Speed {0} -IF JTAG -jtagconf -1,-1 -autoconnect 1 -CommanderScript jlink.cmd'.format(str(self._speed))
|
||||
bflb_utils.printf(jlink_cmd)
|
||||
p = subprocess.Popen(jlink_cmd, shell=True, stdin=(subprocess.PIPE), stdout=(subprocess.PIPE), stderr=(subprocess.PIPE))
|
||||
out, err = p.communicate()
|
||||
bflb_utils.printf(out, err)
|
||||
os.remove(jlink_script)
|
||||
else:
|
||||
self._jlink.register_write(15, int(pc, 16))
|
||||
self._jlink.register_write(13, int(msp, 16))
|
||||
self._jlink.restart()
|
||||
else:
|
||||
bflb_utils.printf("couldn't halt cpu")
|
||||
|
||||
def if_write(self, data_send):
|
||||
self.if_raw_write(self._jlink_data_addr, data_send)
|
||||
data_list = []
|
||||
data_list.append(int('59445248', 16))
|
||||
self._jlink.memory_write((int(self._jlink_shake_hand_addr, 16)), data_list, nbits=32)
|
||||
|
||||
def write(self, data_send):
|
||||
self.if_raw_write(self._jlink_data_addr, data_send)
|
||||
data_list = []
|
||||
data_list.append(int('59445248', 16))
|
||||
self._jlink.memory_write((int(self._jlink_shake_hand_addr, 16)), data_list, nbits=32)
|
||||
|
||||
def if_raw_write(self, addr, data_send):
|
||||
addr_int = int(addr, 16)
|
||||
len2 = len(data_send) % 4
|
||||
len1 = len(data_send) - len2
|
||||
if len1 != 0:
|
||||
data_list = []
|
||||
for i in range(int(len1 / 4)):
|
||||
data_list.append(data_send[4 * i] + (data_send[4 * i + 1] << 8) + (data_send[4 * i + 2] << 16) + (data_send[4 * i + 3] << 24))
|
||||
|
||||
self._jlink.memory_write(addr_int, data_list, nbits=32)
|
||||
if len2 != 0:
|
||||
data_list = []
|
||||
for i in range(len2):
|
||||
data_list.append(data_send[len1 + i])
|
||||
|
||||
self._jlink.memory_write((addr_int + len1), data_list, nbits=8)
|
||||
|
||||
def if_raw_write8(self, addr, data_send):
|
||||
data_list = []
|
||||
for data in data_send:
|
||||
data_list.append(data)
|
||||
|
||||
self._jlink.memory_write((int(addr, 16)), data_list, nbits=8)
|
||||
|
||||
def if_raw_write16(self, addr, data_send):
|
||||
data_list = []
|
||||
for i in range(int(len(data_send) / 2)):
|
||||
data_list.append(data_send[2 * i] + (data_send[2 * i + 1] << 8))
|
||||
|
||||
self._jlink.memory_write((int(addr, 16)), data_list, nbits=16)
|
||||
|
||||
def if_raw_write32(self, addr, data_send):
|
||||
data_list = []
|
||||
for i in range(int(len(data_send) / 4)):
|
||||
data_list.append(data_send[4 * i] + (data_send[4 * i + 1] << 8) + (data_send[4 * i + 2] << 16) + (data_send[4 * i + 3] << 24))
|
||||
|
||||
self._jlink.memory_write((int(addr, 16)), data_list, nbits=32)
|
||||
|
||||
def if_read(self, data_len):
|
||||
start_time = time.time() * 1000
|
||||
while True:
|
||||
ready = self._jlink.memory_read((int(self._jlink_shake_hand_addr, 16)), 1, nbits=32)
|
||||
if len(ready) >= 1:
|
||||
if ready[0] == int('4B434153', 16):
|
||||
break
|
||||
elapsed = time.time() * 1000 - start_time
|
||||
if elapsed >= self._rx_timeout:
|
||||
return (0, 'waiting response time out'.encode('utf-8'))
|
||||
else:
|
||||
time.sleep(0.001)
|
||||
|
||||
data = self.if_raw_read(self._jlink_data_addr, data_len)
|
||||
if len(data) != data_len:
|
||||
return (0, data)
|
||||
return (1, data)
|
||||
|
||||
def read(self, data_len):
|
||||
start_time = time.time() * 1000
|
||||
while True:
|
||||
ready = self._jlink.memory_read((int(self._jlink_shake_hand_addr, 16)), 1, nbits=32)
|
||||
if len(ready) >= 1:
|
||||
if ready[0] == int('4B434153', 16):
|
||||
break
|
||||
elapsed = time.time() * 1000 - start_time
|
||||
if elapsed >= self._rx_timeout:
|
||||
return (0, 'waiting response time out'.encode('utf-8'))
|
||||
else:
|
||||
time.sleep(0.001)
|
||||
|
||||
data = self.if_raw_read(self._jlink_data_addr, data_len)
|
||||
if len(data) != data_len:
|
||||
return (0, data)
|
||||
return (1, data)
|
||||
|
||||
def if_raw_read(self, addr, data_len):
|
||||
addr_int = int(addr, 16)
|
||||
if addr_int % 4 == 0:
|
||||
len2 = data_len % 4
|
||||
len1 = data_len - len2
|
||||
data1 = bytearray(0)
|
||||
data2 = bytearray(0)
|
||||
if len1 != 0:
|
||||
data1 = self._jlink.memory_read(addr_int, (int(len1 / 4)), nbits=32)
|
||||
if len2 != 0:
|
||||
data2 = self._jlink.memory_read((addr_int + len1), len2, nbits=8)
|
||||
data = bytearray(0)
|
||||
for tmp in data1:
|
||||
data += bflb_utils.int_to_4bytearray_l(tmp)
|
||||
|
||||
data += bytearray(data2)
|
||||
return data
|
||||
return self.if_raw_read8(addr, data_len)
|
||||
|
||||
def if_raw_read8(self, addr, data_len):
|
||||
data = self._jlink.memory_read((int(addr, 16)), data_len, nbits=8)
|
||||
return bytearray(data)
|
||||
|
||||
def if_raw_read16(self, addr, data_len):
|
||||
raw_data = self._jlink.memory_read((int(addr, 16)), (data_len / 2), nbits=16)
|
||||
data = bytearray(0)
|
||||
for tmp in raw_data:
|
||||
data += bflb_utils.int_to_2bytearray_l(tmp)
|
||||
|
||||
return bytearray(data)
|
||||
|
||||
def if_raw_read32(self, addr, data_len):
|
||||
raw_data = self._jlink.memory_read((int(addr, 16)), (data_len / 4), nbits=32)
|
||||
data = bytearray(0)
|
||||
for tmp in raw_data:
|
||||
data += bflb_utils.int_to_4bytearray_l(tmp)
|
||||
|
||||
return bytearray(data)
|
||||
|
||||
def if_shakehand(self, do_reset=False, reset_hold_time=100, shake_hand_delay=100, reset_revert=True, cutoff_time=0, shake_hand_retry=2, isp_timeout=0, boot_load=False):
|
||||
self.if_write(bytearray(1))
|
||||
success, ack = self.if_read(2)
|
||||
bflb_utils.printf(binascii.hexlify(ack))
|
||||
if ack.find(b'O') != -1 or ack.find(b'K') != -1:
|
||||
time.sleep(0.03)
|
||||
return 'OK'
|
||||
return 'FL'
|
||||
|
||||
def if_close(self):
|
||||
if self._jlink:
|
||||
self._jlink.close()
|
||||
self._inited = False
|
||||
|
||||
def close(self):
|
||||
if self._jlink:
|
||||
self._jlink.close()
|
||||
self._inited = False
|
||||
|
||||
def if_deal_ack(self):
|
||||
success, ack = self.if_read(2)
|
||||
if success == 0:
|
||||
bflb_utils.printf('ack:' + str(binascii.hexlify(ack)))
|
||||
return ack.decode('utf-8')
|
||||
if ack.find(b'O') != -1 or ack.find(b'K') != -1:
|
||||
return 'OK'
|
||||
if ack.find(b'P') != -1 or ack.find(b'D') != -1:
|
||||
return 'PD'
|
||||
success, err_code = self.if_read(4)
|
||||
if success == 0:
|
||||
bflb_utils.printf('err_code:' + str(binascii.hexlify(err_code)))
|
||||
return 'FL'
|
||||
err_code_str = str(binascii.hexlify(err_code[3:4] + err_code[2:3]).decode('utf-8'))
|
||||
ack = 'FL'
|
||||
try:
|
||||
ret = ack + err_code_str + '(' + bflb_utils.get_bflb_error_code(err_code_str) + ')'
|
||||
except Exception:
|
||||
ret = ack + err_code_str + ' unknown'
|
||||
|
||||
bflb_utils.printf(ret)
|
||||
return ret
|
||||
|
||||
def deal_ack(self):
|
||||
success, ack = self.if_read(2)
|
||||
if success == 0:
|
||||
bflb_utils.printf('ack:' + str(binascii.hexlify(ack)))
|
||||
return ack.decode('utf-8')
|
||||
if ack.find(b'O') != -1 or ack.find(b'K') != -1:
|
||||
return 'OK'
|
||||
if ack.find(b'P') != -1 or ack.find(b'D') != -1:
|
||||
return 'PD'
|
||||
success, err_code = self.if_read(4)
|
||||
if success == 0:
|
||||
bflb_utils.printf('err_code:' + str(binascii.hexlify(err_code)))
|
||||
return 'FL'
|
||||
err_code_str = str(binascii.hexlify(err_code[3:4] + err_code[2:3]).decode('utf-8'))
|
||||
ack = 'FL'
|
||||
try:
|
||||
ret = ack + err_code_str + '(' + bflb_utils.get_bflb_error_code(err_code_str) + ')'
|
||||
except Exception:
|
||||
ret = ack + err_code_str + ' unknown'
|
||||
|
||||
bflb_utils.printf(ret)
|
||||
return ret
|
||||
|
||||
def if_deal_response(self):
|
||||
ack = self.if_deal_ack()
|
||||
if ack == 'OK':
|
||||
success, len_bytes = self.if_read(4)
|
||||
if success == 0:
|
||||
bflb_utils.printf('Get length error')
|
||||
bflb_utils.printf(binascii.hexlify(len_bytes))
|
||||
return (
|
||||
'Get length error', len_bytes)
|
||||
tmp = bflb_utils.bytearray_reverse(len_bytes[2:4])
|
||||
data_len = bflb_utils.bytearray_to_int(tmp)
|
||||
success, data_bytes = self.if_read(data_len + 4)
|
||||
if success == 0:
|
||||
bflb_utils.printf('Read data error')
|
||||
return (
|
||||
'Read data error', data_bytes)
|
||||
data_bytes = data_bytes[4:]
|
||||
if len(data_bytes) != data_len:
|
||||
bflb_utils.printf('Not get excepted length')
|
||||
return (
|
||||
'Not get excepted length', data_bytes)
|
||||
return (ack, data_bytes)
|
||||
bflb_utils.printf('Not ack OK')
|
||||
bflb_utils.printf(ack)
|
||||
return (
|
||||
ack, None)
|
||||
|
||||
def deal_response(self):
|
||||
ack = self.if_deal_ack()
|
||||
if ack == 'OK':
|
||||
success, len_bytes = self.if_read(4)
|
||||
if success == 0:
|
||||
bflb_utils.printf('Get length error')
|
||||
bflb_utils.printf(binascii.hexlify(len_bytes))
|
||||
return (
|
||||
'Get length error', len_bytes)
|
||||
tmp = bflb_utils.bytearray_reverse(len_bytes[2:4])
|
||||
data_len = bflb_utils.bytearray_to_int(tmp)
|
||||
success, data_bytes = self.if_read(data_len + 4)
|
||||
if success == 0:
|
||||
bflb_utils.printf('Read data error')
|
||||
return (
|
||||
'Read data error', data_bytes)
|
||||
data_bytes = data_bytes[4:]
|
||||
if len(data_bytes) != data_len:
|
||||
bflb_utils.printf('Not get excepted length')
|
||||
return (
|
||||
'Not get excepted length', data_bytes)
|
||||
return (ack, data_bytes)
|
||||
bflb_utils.printf('Not ack OK')
|
||||
bflb_utils.printf(ack)
|
||||
return (
|
||||
ack, None)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
try:
|
||||
eflash_loader_t = BflbJLinkPort()
|
||||
eflash_loader_t.if_init('', 1000, 'bl602')
|
||||
bflb_utils.printf('reset test')
|
||||
res = eflash_loader_t.reset_cpu(0, False)
|
||||
bflb_utils.printf(res)
|
||||
except Exception as e:
|
||||
try:
|
||||
NUM_ERR = 5
|
||||
bflb_utils.printf(e)
|
||||
traceback.print_exc(limit=NUM_ERR, file=(sys.stdout))
|
||||
finally:
|
||||
e = None
|
||||
del e
|
||||
# okay decompiling ./libs/bflb_interface_jlink.pyc
|
425
libs/bflb_interface_openocd.py
Normal file
425
libs/bflb_interface_openocd.py
Normal file
|
@ -0,0 +1,425 @@
|
|||
# decompyle3 version 3.9.0
|
||||
# Python bytecode version base 3.7.0 (3394)
|
||||
# Decompiled from: Python 3.7.16 (default, Mar 30 2023, 01:25:49)
|
||||
# [GCC 12.2.1 20220924]
|
||||
# Embedded file name: libs/bflb_interface_openocd.py
|
||||
import os, time, binascii, subprocess, threading, telnetlib, serial
|
||||
from libs import bflb_utils
|
||||
from libs.bflb_utils import app_path
|
||||
openocd_path = os.path.join(app_path, 'utils/openocd', 'openocd.exe')
|
||||
|
||||
class ThreadOpenocdServer(threading.Thread):
|
||||
|
||||
def __init__(self, chiptype='bl602', device='rv_dbg_plus', serial=None):
|
||||
threading.Thread.__init__(self)
|
||||
self.timeToQuit = threading.Event()
|
||||
self.timeToQuit.clear()
|
||||
self._chiptype = chiptype
|
||||
self._device = device
|
||||
self._serial = serial
|
||||
bflb_utils.printf('SN is ' + str(self._serial))
|
||||
|
||||
def stop(self):
|
||||
self.timeToQuit.set()
|
||||
|
||||
def run(self):
|
||||
cmd = ''
|
||||
if self._serial:
|
||||
cmd_ftdi_serial = ' -c "ftdi_serial \\"' + self._serial + '\\""'
|
||||
else:
|
||||
cmd_ftdi_serial = ''
|
||||
if self._device == 'rv_dbg_plus':
|
||||
if self._chiptype == 'bl602':
|
||||
cmd = openocd_path + ' -f ' + app_path + '/utils/openocd/if_rv_dbg_plus.cfg ' + cmd_ftdi_serial + ' -f ' + app_path + '/utils/openocd/tgt_602.cfg'
|
||||
else:
|
||||
cmd = openocd_path + ' -f ' + app_path + '/utils/openocd/if_rv_dbg_plus.cfg' + cmd_ftdi_serial + ' -f ' + app_path + '/utils/openocd/tgt_702.cfg'
|
||||
else:
|
||||
if self._device == 'ft2232hl':
|
||||
if self._chiptype == 'bl602':
|
||||
cmd = openocd_path + ' -f ' + app_path + '/utils/openocd/if_bflb_dbg.cfg' + cmd_ftdi_serial + ' -f ' + app_path + '/utils/openocd/tgt_602.cfg'
|
||||
else:
|
||||
cmd = openocd_path + ' -f ' + app_path + '/utils/openocd/if_bflb_dbg.cfg' + cmd_ftdi_serial + ' -f ' + app_path + '/utils/openocd/tgt_702.cfg'
|
||||
else:
|
||||
cmd = openocd_path + ' -f ' + app_path + '/utils/openocd/openocd-usb-sipeed.cfg ' + cmd_ftdi_serial
|
||||
bflb_utils.printf(cmd)
|
||||
p = subprocess.Popen(cmd, shell=True, stdin=(subprocess.PIPE), stdout=(subprocess.PIPE), stderr=(subprocess.PIPE))
|
||||
out, err = p.communicate()
|
||||
bflb_utils.printf(out)
|
||||
|
||||
|
||||
class BflbOpenocdPort(object):
|
||||
|
||||
def __init__(self):
|
||||
self._speed = 5000
|
||||
self._rx_timeout = 10000
|
||||
self._openocd_shake_hand_addr = '20000000'
|
||||
self._openocd_data_addr = '20000004'
|
||||
self._inited = False
|
||||
self._chiptype = 'bl60x'
|
||||
self._chipname = 'bl60x'
|
||||
self._openocd_run_addr = '22010000'
|
||||
self.tn = telnetlib.Telnet()
|
||||
|
||||
def if_init(self, device, sn, rate, chiptype='bl60x', chipname='bl60x'):
|
||||
if self._inited is False:
|
||||
sub_module = __import__(('libs.base.' + chiptype), fromlist=[chiptype])
|
||||
self._openocd_shake_hand_addr = sub_module.openocd_load_cfg.openocd_shake_hand_addr
|
||||
self._openocd_data_addr = sub_module.openocd_load_cfg.openocd_data_addr
|
||||
self._openocd_run_addr = sub_module.openocd_load_cfg.openocd_run_addr
|
||||
self._speed = rate
|
||||
self._inited = True
|
||||
self._chiptype = chiptype
|
||||
self._chipname = chipname
|
||||
if sn:
|
||||
serial = 'FactoryAIOT Prog ' + str(sn)
|
||||
else:
|
||||
serial = None
|
||||
self._openocd_th = None
|
||||
self._openocd_th = ThreadOpenocdServer(chiptype, device, serial)
|
||||
self._openocd_th.setDaemon(True)
|
||||
self._openocd_th.start()
|
||||
try:
|
||||
self.tn.open('127.0.0.1', port=4444, timeout=10)
|
||||
self.tn.write(('adapter speed ' + str(rate)).encode('ascii') + b'\n')
|
||||
self.tn.write('WaitCmd\n'.encode('ascii'))
|
||||
self.tn.read_until(('"WaitCmd"'.encode('ascii')), timeout=10)
|
||||
except Exception:
|
||||
bflb_utils.printf('Failed to connect openocd server')
|
||||
bflb_utils.set_error_code('0009')
|
||||
self.if_close()
|
||||
|
||||
return False
|
||||
|
||||
def repeat_init(self, device, sn, rate, chiptype='bl60x', chipname='bl60x'):
|
||||
if self._inited is False:
|
||||
sub_module = __import__(('libs.base.' + chiptype), fromlist=[chiptype])
|
||||
self._openocd_shake_hand_addr = sub_module.openocd_load_cfg.openocd_shake_hand_addr
|
||||
self._openocd_data_addr = sub_module.openocd_load_cfg.openocd_data_addr
|
||||
self._openocd_run_addr = sub_module.openocd_load_cfg.openocd_run_addr
|
||||
self._speed = rate
|
||||
self._inited = True
|
||||
self._chiptype = chiptype
|
||||
self._chipname = chipname
|
||||
if sn:
|
||||
serial = 'FactoryAIOT Prog ' + str(sn)
|
||||
else:
|
||||
serial = None
|
||||
self._openocd_th = None
|
||||
self._openocd_th = ThreadOpenocdServer(chiptype, device, serial)
|
||||
self._openocd_th.setDaemon(True)
|
||||
self._openocd_th.start()
|
||||
try:
|
||||
self.tn.open('127.0.0.1', port=4444, timeout=10)
|
||||
self.tn.write(('adapter speed ' + str(rate)).encode('ascii') + b'\n')
|
||||
self.tn.write('WaitCmd\n'.encode('ascii'))
|
||||
self.tn.read_until(('"WaitCmd"'.encode('ascii')), timeout=10)
|
||||
except Exception:
|
||||
bflb_utils.printf('Failed to connect openocd server')
|
||||
bflb_utils.set_error_code('0009')
|
||||
self.if_close()
|
||||
|
||||
return False
|
||||
|
||||
def if_clear_buf(self):
|
||||
pass
|
||||
|
||||
def clear_buf(self):
|
||||
pass
|
||||
|
||||
def if_set_rx_timeout(self, val):
|
||||
self._rx_timeout = val * 1000
|
||||
|
||||
def set_timeout(self, val):
|
||||
self._rx_timeout = val * 1000
|
||||
|
||||
def if_get_rate(self):
|
||||
return self._speed
|
||||
|
||||
def halt_cpu(self):
|
||||
self.tn.write('halt'.encode('ascii') + b'\n')
|
||||
return True
|
||||
|
||||
def reset_cpu(self, ms=0, halt=True):
|
||||
if halt:
|
||||
self.halt_cpu()
|
||||
self.tn.write('reset'.encode('ascii') + b'\n')
|
||||
|
||||
def set_pc_msp(self, pc, msp):
|
||||
self.halt_cpu()
|
||||
if self._chiptype == 'bl602' or self._chiptype == 'bl702' or self._chiptype == 'bl702l':
|
||||
self.tn.write(('reg pc 0x' + self._openocd_run_addr).encode('ascii') + b'\n')
|
||||
self.tn.write('resume'.encode('ascii') + b'\n')
|
||||
|
||||
def if_raw_write(self, addr, data_send):
|
||||
addr_int = int(addr, 16)
|
||||
if len(data_send) > 32:
|
||||
fp = open('openocd_load_data.bin', 'wb+')
|
||||
fp.write(data_send)
|
||||
fp.close()
|
||||
self.tn.write(('load_image openocd_load_data.bin ' + hex(addr_int)).encode('ascii') + b'\n')
|
||||
else:
|
||||
for data in data_send:
|
||||
self.tn.write(('mwb ' + hex(addr_int) + ' ' + hex(data)).encode('ascii') + b'\n')
|
||||
addr_int += 1
|
||||
|
||||
def if_write(self, data_send):
|
||||
self.if_raw_write(self._openocd_data_addr, data_send)
|
||||
self.if_raw_write(self._openocd_shake_hand_addr, bytearray.fromhex('48524459'))
|
||||
|
||||
def write(self, data_send):
|
||||
self.if_raw_write(self._openocd_data_addr, data_send)
|
||||
self.if_raw_write(self._openocd_shake_hand_addr, bytearray.fromhex('48524459'))
|
||||
|
||||
def read_data_parse(self, buff, aligned):
|
||||
strdata = buff.decode().strip()
|
||||
data = bytearray(0)
|
||||
index = strdata.find(': ')
|
||||
if aligned is True:
|
||||
lstr = strdata[index + 2:strdata.find('WaitCmd') - 6].split('0x')
|
||||
for l in lstr:
|
||||
ldata = []
|
||||
if l.find(': ') != -1:
|
||||
ldata = l[9:].split(' ')
|
||||
else:
|
||||
ldata = l.split(' ')
|
||||
for d in ldata:
|
||||
if len(d) != 8:
|
||||
continue
|
||||
else:
|
||||
hexstr = d[6:8] + d[4:6] + d[2:4] + d[0:2]
|
||||
data += bflb_utils.hexstr_to_bytearray(hexstr)
|
||||
|
||||
else:
|
||||
data += bflb_utils.hexstr_to_bytearray(strdata[index + 2:strdata.find('WaitCmd') - 6].replace(' ', ''))
|
||||
return data
|
||||
|
||||
def if_addr_unaligned_read(self, addr, data_len):
|
||||
addr_int = int(addr, 16)
|
||||
data = bytearray(0)
|
||||
dummy = self.tn.read_very_eager().decode('utf-8')
|
||||
self.tn.write(('mdb ' + hex(addr_int) + ' ' + hex(data_len) + '\n').encode('ascii'))
|
||||
self.tn.write('WaitCmd\n'.encode('ascii'))
|
||||
ret = self.tn.read_until(('"WaitCmd"'.encode('ascii')), timeout=10)
|
||||
data += self.read_data_parse(ret, False)
|
||||
return data
|
||||
|
||||
def if_addr_aligned_read(self, addr, data_len):
|
||||
addr_int = int(addr, 16)
|
||||
leftlen = data_len
|
||||
data = bytearray(0)
|
||||
dummy = self.tn.read_very_eager().decode('utf-8')
|
||||
self.tn.write(('mdw ' + hex(addr_int) + ' ' + hex(data_len // 4) + '\n').encode('ascii'))
|
||||
self.tn.write('WaitCmd\n'.encode('ascii'))
|
||||
ret = self.tn.read_until(('"WaitCmd"'.encode('ascii')), timeout=10)
|
||||
data += self.read_data_parse(ret, True)
|
||||
addr_int = addr_int + data_len // 4 * 4
|
||||
leftlen = data_len - data_len // 4 * 4
|
||||
if leftlen != 0:
|
||||
data += self.if_addr_unaligned_read(hex(addr_int)[2:], leftlen)
|
||||
return data
|
||||
|
||||
def if_raw_read(self, addr, data_len):
|
||||
data = bytearray(0)
|
||||
if data_len <= 4:
|
||||
return self.if_addr_unaligned_read(addr, data_len)
|
||||
addr_int = int(addr, 16)
|
||||
pre_read_len = 4 - addr_int % 4
|
||||
if pre_read_len != 0:
|
||||
data += self.if_addr_unaligned_read(addr, pre_read_len)
|
||||
data += self.if_addr_aligned_read(hex(addr_int + pre_read_len), data_len - pre_read_len)
|
||||
return data[:data_len]
|
||||
|
||||
def if_read(self, data_len):
|
||||
start_time = time.time() * 1000
|
||||
while True:
|
||||
ready = self.if_raw_read(self._openocd_shake_hand_addr, 16)
|
||||
if ready[0:4] == bytearray([83, 65, 67, 75]):
|
||||
break
|
||||
else:
|
||||
elapsed = time.time() * 1000 - start_time
|
||||
if elapsed >= self._rx_timeout:
|
||||
return (0, 'waiting response time out'.encode('utf-8'))
|
||||
time.sleep(0.001)
|
||||
|
||||
data = self.if_raw_read(self._openocd_data_addr, data_len)
|
||||
if len(data) != data_len:
|
||||
return (0, data)
|
||||
return (1, data)
|
||||
|
||||
def read(self, data_len):
|
||||
start_time = time.time() * 1000
|
||||
while True:
|
||||
ready = self.if_raw_read(self._openocd_shake_hand_addr, 16)
|
||||
if ready[0:4] == bytearray([83, 65, 67, 75]):
|
||||
break
|
||||
else:
|
||||
elapsed = time.time() * 1000 - start_time
|
||||
if elapsed >= self._rx_timeout:
|
||||
return (0, 'waiting response time out'.encode('utf-8'))
|
||||
time.sleep(0.001)
|
||||
|
||||
data = self.if_raw_read(self._openocd_data_addr, data_len)
|
||||
if len(data) != data_len:
|
||||
return (0, data)
|
||||
return (1, data)
|
||||
|
||||
def if_clear_buff(self):
|
||||
self.tn.write('WaitCmd\n'.encode('ascii'))
|
||||
self.tn.read_until(('"WaitCmd"'.encode('ascii')), timeout=10)
|
||||
|
||||
def clear_buff(self):
|
||||
self.tn.write('WaitCmd\n'.encode('ascii'))
|
||||
self.tn.read_until(('"WaitCmd"'.encode('ascii')), timeout=10)
|
||||
|
||||
def if_shakehand(self, do_reset=False, reset_hold_time=100, shake_hand_delay=100, reset_revert=True, cutoff_time=0, shake_hand_retry=2, isp_timeout=0, boot_load=False):
|
||||
self.if_clear_buff()
|
||||
self.if_write(bytearray(1))
|
||||
success, ack = self.if_read(2)
|
||||
bflb_utils.printf(binascii.hexlify(ack))
|
||||
if ack.find(b'O') != -1 or ack.find(b'K') != -1:
|
||||
time.sleep(0.03)
|
||||
return 'OK'
|
||||
return 'FL'
|
||||
|
||||
def if_close(self):
|
||||
if self.tn.get_socket():
|
||||
self.tn.write('shutdown\n'.encode('ascii'))
|
||||
time.sleep(0.05)
|
||||
self.tn.close()
|
||||
if self._openocd_th:
|
||||
self._openocd_th.stop()
|
||||
self._inited = False
|
||||
|
||||
def close(self):
|
||||
if self.tn.get_socket():
|
||||
self.tn.write('shutdown\n'.encode('ascii'))
|
||||
time.sleep(0.05)
|
||||
self.tn.close()
|
||||
if self._openocd_th:
|
||||
self._openocd_th.stop()
|
||||
self._inited = False
|
||||
|
||||
def if_deal_ack(self):
|
||||
success, ack = self.if_read(2)
|
||||
if success == 0:
|
||||
bflb_utils.printf('ack:' + str(binascii.hexlify(ack)))
|
||||
return ack.decode('utf-8')
|
||||
if ack.find(b'O') != -1 or ack.find(b'K') != -1:
|
||||
return 'OK'
|
||||
if ack.find(b'P') != -1 or ack.find(b'D') != -1:
|
||||
return 'PD'
|
||||
success, err_code = self.if_read(4)
|
||||
if success == 0:
|
||||
bflb_utils.printf('err_code:' + str(binascii.hexlify(err_code)))
|
||||
return 'FL'
|
||||
err_code_str = str(binascii.hexlify(err_code[3:4] + err_code[2:3]).decode('utf-8'))
|
||||
ack = 'FL'
|
||||
try:
|
||||
ret = ack + err_code_str + '(' + bflb_utils.get_bflb_error_code(err_code_str) + ')'
|
||||
except Exception:
|
||||
ret = ack + err_code_str + ' unknown'
|
||||
|
||||
bflb_utils.printf(ret)
|
||||
return ret
|
||||
|
||||
def deal_ack(self):
|
||||
success, ack = self.if_read(2)
|
||||
if success == 0:
|
||||
bflb_utils.printf('ack:' + str(binascii.hexlify(ack)))
|
||||
return ack.decode('utf-8')
|
||||
if ack.find(b'O') != -1 or ack.find(b'K') != -1:
|
||||
return 'OK'
|
||||
if ack.find(b'P') != -1 or ack.find(b'D') != -1:
|
||||
return 'PD'
|
||||
success, err_code = self.if_read(4)
|
||||
if success == 0:
|
||||
bflb_utils.printf('err_code:' + str(binascii.hexlify(err_code)))
|
||||
return 'FL'
|
||||
err_code_str = str(binascii.hexlify(err_code[3:4] + err_code[2:3]).decode('utf-8'))
|
||||
ack = 'FL'
|
||||
try:
|
||||
ret = ack + err_code_str + '(' + bflb_utils.get_bflb_error_code(err_code_str) + ')'
|
||||
except Exception:
|
||||
ret = ack + err_code_str + ' unknown'
|
||||
|
||||
bflb_utils.printf(ret)
|
||||
return ret
|
||||
|
||||
def if_deal_response(self):
|
||||
ack = self.if_deal_ack()
|
||||
if ack == 'OK':
|
||||
success, len_bytes = self.if_read(4)
|
||||
if success == 0:
|
||||
bflb_utils.printf('Get length error')
|
||||
bflb_utils.printf(binascii.hexlify(len_bytes))
|
||||
return (
|
||||
'Get length error', len_bytes)
|
||||
tmp = bflb_utils.bytearray_reverse(len_bytes[2:4])
|
||||
data_len = bflb_utils.bytearray_to_int(tmp)
|
||||
success, data_bytes = self.if_read(data_len + 4)
|
||||
if success == 0:
|
||||
bflb_utils.printf('Read data error')
|
||||
return (
|
||||
'Read data error', data_bytes)
|
||||
data_bytes = data_bytes[4:]
|
||||
if len(data_bytes) != data_len:
|
||||
bflb_utils.printf('Not get excepted length')
|
||||
return (
|
||||
'Not get excepted length', data_bytes)
|
||||
return (ack, data_bytes)
|
||||
bflb_utils.printf('Not ack OK')
|
||||
bflb_utils.printf(ack)
|
||||
return (
|
||||
ack, None)
|
||||
|
||||
def deal_response(self):
|
||||
ack = self.if_deal_ack()
|
||||
if ack == 'OK':
|
||||
success, len_bytes = self.if_read(4)
|
||||
if success == 0:
|
||||
bflb_utils.printf('Get length error')
|
||||
bflb_utils.printf(binascii.hexlify(len_bytes))
|
||||
return (
|
||||
'Get length error', len_bytes)
|
||||
tmp = bflb_utils.bytearray_reverse(len_bytes[2:4])
|
||||
data_len = bflb_utils.bytearray_to_int(tmp)
|
||||
success, data_bytes = self.if_read(data_len + 4)
|
||||
if success == 0:
|
||||
bflb_utils.printf('Read data error')
|
||||
return (
|
||||
'Read data error', data_bytes)
|
||||
data_bytes = data_bytes[4:]
|
||||
if len(data_bytes) != data_len:
|
||||
bflb_utils.printf('Not get excepted length')
|
||||
return (
|
||||
'Not get excepted length', data_bytes)
|
||||
return (ack, data_bytes)
|
||||
bflb_utils.printf('Not ack OK')
|
||||
bflb_utils.printf(ack)
|
||||
return (
|
||||
ack, None)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
eflash_loader_t = BflbOpenocdPort()
|
||||
eflash_loader_t.if_init('', 100, 'bl60x')
|
||||
bflb_utils.printf('read test')
|
||||
bflb_utils.printf(eflash_loader_t.if_raw_read('21000000', 2))
|
||||
bflb_utils.printf(eflash_loader_t.if_raw_read('21000000', 4))
|
||||
bflb_utils.printf(eflash_loader_t.if_raw_read('21000000', 10))
|
||||
bflb_utils.printf(eflash_loader_t.if_raw_read('21000000', 16))
|
||||
bflb_utils.printf(eflash_loader_t.if_raw_read('21000001', 2))
|
||||
bflb_utils.printf(eflash_loader_t.if_raw_read('21000001', 4))
|
||||
bflb_utils.printf(eflash_loader_t.if_raw_read('21000001', 10))
|
||||
bflb_utils.printf(eflash_loader_t.if_raw_read('21000001', 16))
|
||||
bflb_utils.printf(eflash_loader_t.if_raw_read('21000002', 2))
|
||||
bflb_utils.printf(eflash_loader_t.if_raw_read('21000002', 4))
|
||||
bflb_utils.printf(eflash_loader_t.if_raw_read('21000002', 10))
|
||||
bflb_utils.printf(eflash_loader_t.if_raw_read('21000002', 16))
|
||||
bflb_utils.printf('write test')
|
||||
data = bytearray([
|
||||
1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,
|
||||
4])
|
||||
eflash_loader_t.if_raw_write('42020000', data)
|
||||
bflb_utils.printf(eflash_loader_t.if_raw_read('42020000', 62))
|
||||
# okay decompiling ./libs/bflb_interface_openocd.pyc
|
476
libs/bflb_utils.py
Normal file
476
libs/bflb_utils.py
Normal file
|
@ -0,0 +1,476 @@
|
|||
import os
|
||||
import sys
|
||||
import re
|
||||
import time
|
||||
import shutil
|
||||
import binascii
|
||||
import struct
|
||||
import random
|
||||
import socket
|
||||
import threading
|
||||
import datetime
|
||||
import hashlib
|
||||
import argparse
|
||||
import traceback
|
||||
import platform
|
||||
import codecs
|
||||
from glob import glob
|
||||
import pylink
|
||||
from serial import Serial
|
||||
from Crypto.Util import Counter
|
||||
from Crypto.Cipher import AES
|
||||
try:
|
||||
from PySide2 import QtCore
|
||||
qt_sign = True
|
||||
except ImportError:
|
||||
qt_sign = False
|
||||
try:
|
||||
from serial.tools.list_ports import comports
|
||||
except ImportError:
|
||||
pass
|
||||
if getattr(sys, 'frozen', False):
|
||||
app_path = os.path.dirname(sys.executable)
|
||||
else:
|
||||
app_path = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||
chip_path = os.path.join(app_path, 'chips')
|
||||
python_version = struct.calcsize('P')*8
|
||||
if python_version == 64:
|
||||
path_dll = os.path.join(app_path, 'utils/jlink', 'JLink_x64.dll')
|
||||
else:
|
||||
path_dll = os.path.join(app_path, 'utils/jlink', 'JLinkARM.dll')
|
||||
try:
|
||||
import changeconf as cgc
|
||||
conf_sign = True
|
||||
except ImportError:
|
||||
cgc = None
|
||||
conf_sign = False
|
||||
PY2 = sys.version_info[0] == 2
|
||||
udp_clinet_dict = {}
|
||||
udp_send_log = False
|
||||
udp_log_local_echo = False
|
||||
udp_socket_server = None
|
||||
error_code_num = 'FFFF'
|
||||
error_code_num_task = ['FFFF', 'FFFF', 'FFFF', 'FFFF', 'FFFF', 'FFFF', 'FFFF', 'FFFF', 'FFFF', 'FFFF', 'FFFF', 'FFFF', 'FFFF', 'FFFF', 'FFFF', 'FFFF', 'FFFF', 'FFFF', 'FFFF', 'FFFF', 'FFFF', 'FFFF', 'FFFF', 'FFFF', 'FFFF', 'FFFF', 'FFFF', 'FFFF', 'FFFF', 'FFFF', 'FFFF', 'FFFF', 'FFFF', 'FFFF', 'FFFF', 'FFFF', 'FFFF', 'FFFF', 'FFFF', 'FFFF', 'FFFF', 'FFFF', 'FFFF', 'FFFF', 'FFFF', 'FFFF', 'FFFF', 'FFFF', 'FFFF', 'FFFF', 'FFFF', 'FFFF', 'FFFF', 'FFFF', 'FFFF', 'FFFF', 'FFFF', 'FFFF', 'FFFF', 'FFFF', 'FFFF', 'FFFF', 'FFFF', 'FFFF', 'FFFF', 'FFFF']
|
||||
local_log_en = True
|
||||
local_log_data = ''
|
||||
if conf_sign:
|
||||
bflb_error_code = {'0000': 'SUCCESS', '0001': 'FLASH_INIT_ERROR', '0002': 'FLASH_ERASE_PARA_ERROR', '0003': 'FLASH_ERASE_ERROR', '0004': 'FLASH_WRITE_PARA_ERROR', '0005': 'FLASH_WRITE_ADDR_ERROR', '0006': 'FLASH_WRITE_ERROR', '0007': 'FLASH_BOOT_PARA_ERROR', '0008': 'FLASH_SET_PARA_ERROR', '0009': 'FLASH_READ_STATUS_REG_ERROR', '000a': 'FLASH_WRITE_STATUS_REG_ERROR', '000b': 'FLASH_DECOMPRESS_WRITE_ERROR', '000c': 'FLASH_WRITE_XZ_ERROR', '000d': 'FLASH_SWITCH_BANK_ERROR', '0101': 'CMD_ID_ERROR', '0102': 'CMD_LEN_ERROR', '0103': 'CMD_CRC_ERROR', '0104': 'CMD_SEQ_ERROR', '0201': 'IMG_BOOTHEADER_LEN_ERROR', '0202': 'IMG_BOOTHEADER_NOT_LOAD_ERROR', '0203': 'IMG_BOOTHEADER_MAGIC_ERROR', '0204': 'IMG_BOOTHEADER_CRC_ERROR', '0205': 'IMG_BOOTHEADER_ENCRYPT_NOTFIT', '0206': 'IMG_BOOTHEADER_SIGN_NOTFIT', '0207': 'IMG_SEGMENT_CNT_ERROR', '0208': 'IMG_AES_IV_LEN_ERROR', '0209': 'IMG_AES_IV_CRC_ERROR', '020a': 'IMG_PK_LEN_ERROR', '020b': 'IMG_PK_CRC_ERROR', '020c': 'IMG_PK_HASH_ERROR', '020d': 'IMG_SIGNATURE_LEN_ERROR', '020e': 'IMG_SIGNATURE_CRC_ERROR', '020f': 'IMG_SECTIONHEADER_LEN_ERROR', '0210': 'IMG_SECTIONHEADER_CRC_ERROR', '0211': 'IMG_SECTIONHEADER_DST_ERROR', '0212': 'IMG_SECTIONDATA_LEN_ERROR', '0213': 'IMG_SECTIONDATA_DEC_ERROR', '0214': 'IMG_SECTIONDATA_TLEN_ERROR', '0215': 'IMG_SECTIONDATA_CRC_ERROR', '0216': 'IMG_HALFBAKED_ERROR', '0217': 'IMG_HASH_ERROR', '0218': 'IMG_SIGN_PARSE_ERROR', '0219': 'IMG_SIGN_ERROR', '021a': 'IMG_DEC_ERROR', '021b': 'IMG_ALL_INVALID_ERROR', '0301': 'IF_RATE_LEN_ERROR', '0302': 'IF_RATE_PARA_ERROR', '0303': 'IF_PASSWORDERROR', '0304': 'IF_PASSWORDCLOSE', '0401': 'EFUSE_WRITE_PARA_ERROR', '0402': 'EFUSE_WRITE_ADDR_ERROR', '0403': 'EFUSE_WRITE_ERROR', '0404': 'EFUSE_READ_PARA_ERROR', '0405': 'EFUSE_READ_ADDR_ERROR', '0406': 'EFUSE_READ_ERROR', '0407': 'EFUSE_READ_MAC_ERROR', '0408': 'EFUSE_WRITE_MAC_ERROR', '0501': 'MEMORY_WRITE_PARA_ERROR', '0502': 'MEMORY_WRITE_ADDR_ERROR', '0503': 'MEMORY_WRITE_ERROR', '0504': 'MEMORY_READ_PARA_ERROR', '0505': 'MEMORY_READ_ADDR_ERROR', '0506': 'MEMORY_READ_ERROR', '0508': 'REG_WRITE_PARA_ERROR', '0509': 'REG_WRITE_ADDR_ERROR', '050a': 'REG_WRITE_ERROR', '050b': 'REG_READ_PARA_ERROR', '050c': 'REG_READ_ADDR_ERROR', '050d': 'REG_READ_ERROR', '0601': 'ECDH_PARA_ERROR', '0602': 'ECDH_PRIVATE_KEY_ERROR', '0603': 'ECDH_SHARED_KEY_ERROR', '0604': 'ECDH_RANDOM_VAL_ERROR', '0605': 'ECDH_DECRYPT_ERROR', '0606': 'ECDH_ENCRYPT_ERROR', 'fffc': 'PLL_ERROR', 'fffd': 'INVASION_ERROR', 'fffe': 'POLLING', 'ffff': 'FAIL'}
|
||||
eflash_loader_error_code = {'0000': 'SUCCESS', '0001': 'EFLASH LOADER SHAKEHAND FAIL', '0002': 'OPTION SET UNSUPPORTED', '0003': 'LOAD HELP BIN FAIL', '0004': 'RESET CPU FAIL', '0005': 'BURN RETRY FAIL', '0006': 'LOG READ FAIL', '0009': 'CONNECT OPENOCD SERVER FAIL', '000A': 'REPEAT BURN', '000B': 'CONFIG FILE NOT FOUND', '000C': 'SET CLOCK PLL FAIL', '000D': 'SET OPT FINISH FAIL', '000E': 'IMPORT PACKET FAIL', '0020': 'EFUSE READ FAIL', '0021': 'EFUSE WRITE FAIL', '0022': 'EFUSE COMPARE FAIL', '0023': 'EFUSE READ MAC ADDR FAIL', '0024': 'EFUSE WRITE MAC ADDR FAIL', '0025': 'EFUSE MAC ADDR CRC FAIL', '0030': 'READ FLASH JEDEC ID FAIL', '0031': 'READ FLASH STATUS REGISTER FAIL', '0032': 'WRITE FLASH STATUS REGISTER FAIL', '0033': 'FLASH CHIP ERASE FAIL', '0034': 'FLASH ERASE FAIL', '0035': 'FLASH READ FAIL', '0036': 'FLASH WRITE FAIL', '0037': 'FLASH WRITE CHECK FAIL', '0038': 'FLASH READ SHA FAIL', '0039': 'FLASH XIP MODE ENTER FAIL', '003A': 'FLASH XIP MODE EXIT FAIL', '003B': 'FLASH SET PARA FAIL', '003C': 'FLASH LOAD FIRMWARE BIN FAIL', '003D': 'FLASH MATCH TYPE FAIL', '003E': 'FLASH LOAD VERIFY FAIL', '003F': 'FLASH BOOT FAIL', '0040': 'FLASH CFG NOT FIT WITH BOOTHEADER', '0041': 'FLASH LOAD ROMFS FAIL', '0042': 'FLASH SWITCH BANK FAIL', '0043': 'FLASH IDENTIFY FAIL', '0044': 'FLASH CHIPERASE CONFLICT WITH SKIP MODE', '0050': 'IMG LOAD SHAKEHAND FAIL', '0051': 'IMG LOAD BOOT CHECK FAIL', '0060': 'IMG CREATE FAIL', '0061': 'IMG FILE NOT SET', '0062': 'IMG ADDR NOT SET', '0063': 'BOOTINFO ADDR NOT SET', '0064': 'AES KEY NOT SET', '0065': 'AES IV NOT SET', '0066': 'PUBLIC KEY NOT SET', '0067': 'PRIVATE KEY NOT SET', '0068': 'RAW DATA NOT NEED CREATE', '0069': 'FLASH ID NOT SUPPORT', '0070': 'FLASH ID NOT FOUND', '0071': 'ENCRYPT KEY LEN ERROR', '0072': 'AES IV LEN ERROR', '0073': 'AES IV SHOULD END WITH 00000000', '0074': 'IMG TYPE NOT FIT', '0075': 'IMG CREATE ENTER EXCEPT', '0076': 'PT NOT SET', '0077': 'AES KEY DATA OR LEN ERROR', '0078': 'AES IV DATA OR LEN ERROR', '0079': 'FACTORY IMG NOT FOUND', '007A': 'GENERATE ROMFS FAIL', '007B': 'PT PARCEL IS NULL', '007C': 'PT TABLE NOT SET', '007D': 'BOOT2 BIN NOT SET', '007E': 'FW BIN NOT SET', '007F': 'MEDIA NOT SET', '0080': 'ROMFS NOT SET', '0081': 'MFG BIN NOT SET', '0082': 'PT CHECK FAIL', '0083': 'D0 FW BIN NOT SET', '0084': 'IMTB BIN NOT SET', '0085': 'IMG LOADER BIN NOT SET', '0086': 'SBI BIN NOT SET', '0087': 'KERNEL BIN NOT SET', '0088': 'ROOTFS BIN NOT SET', '0089': 'KV BIN NOT SET', '0090': 'YOCBOOT BIN NOT SET', '0091': 'DTB BIN NOT SET', 'FFFF': 'BURN RETRY FAIL'}
|
||||
else:
|
||||
bflb_error_code = {'0000': 'BFLB_SUCCESS', '0001': 'BFLB_FLASH_INIT_ERROR', '0002': 'BFLB_FLASH_ERASE_PARA_ERROR', '0003': 'BFLB_FLASH_ERASE_ERROR', '0004': 'BFLB_FLASH_WRITE_PARA_ERROR', '0005': 'BFLB_FLASH_WRITE_ADDR_ERROR', '0006': 'BFLB_FLASH_WRITE_ERROR', '0007': 'BFLB_FLASH_BOOT_PARA_ERROR', '0008': 'BFLB_FLASH_SET_PARA_ERROR', '0009': 'BFLB_FLASH_READ_STATUS_REG_ERROR', '000a': 'BFLB_FLASH_WRITE_STATUS_REG_ERROR', '000b': 'BFLB_FLASH_DECOMPRESS_WRITE_ERROR', '000c': 'BFLB_FLASH_WRITE_XZ_ERROR', '000d': 'BFLB_FLASH_SWITCH_BANK_ERROR', '0101': 'BFLB_CMD_ID_ERROR', '0102': 'BFLB_CMD_LEN_ERROR', '0103': 'BFLB_CMD_CRC_ERROR', '0104': 'BFLB_CMD_SEQ_ERROR', '0201': 'BFLB_IMG_BOOTHEADER_LEN_ERROR', '0202': 'BFLB_IMG_BOOTHEADER_NOT_LOAD_ERROR', '0203': 'BFLB_IMG_BOOTHEADER_MAGIC_ERROR', '0204': 'BFLB_IMG_BOOTHEADER_CRC_ERROR', '0205': 'BFLB_IMG_BOOTHEADER_ENCRYPT_NOTFIT', '0206': 'BFLB_IMG_BOOTHEADER_SIGN_NOTFIT', '0207': 'BFLB_IMG_SEGMENT_CNT_ERROR', '0208': 'BFLB_IMG_AES_IV_LEN_ERROR', '0209': 'BFLB_IMG_AES_IV_CRC_ERROR', '020a': 'BFLB_IMG_PK_LEN_ERROR', '020b': 'BFLB_IMG_PK_CRC_ERROR', '020c': 'BFLB_IMG_PK_HASH_ERROR', '020d': 'BFLB_IMG_SIGNATURE_LEN_ERROR', '020e': 'BFLB_IMG_SIGNATURE_CRC_ERROR', '020f': 'BFLB_IMG_SECTIONHEADER_LEN_ERROR', '0210': 'BFLB_IMG_SECTIONHEADER_CRC_ERROR', '0211': 'BFLB_IMG_SECTIONHEADER_DST_ERROR', '0212': 'BFLB_IMG_SECTIONDATA_LEN_ERROR', '0213': 'BFLB_IMG_SECTIONDATA_DEC_ERROR', '0214': 'BFLB_IMG_SECTIONDATA_TLEN_ERROR', '0215': 'BFLB_IMG_SECTIONDATA_CRC_ERROR', '0216': 'BFLB_IMG_HALFBAKED_ERROR', '0217': 'BFLB_IMG_HASH_ERROR', '0218': 'BFLB_IMG_SIGN_PARSE_ERROR', '0219': 'BFLB_IMG_SIGN_ERROR', '021a': 'BFLB_IMG_DEC_ERROR', '021b': 'BFLB_IMG_ALL_INVALID_ERROR', '0301': 'BFLB_IF_RATE_LEN_ERROR', '0302': 'BFLB_IF_RATE_PARA_ERROR', '0303': 'BFLB_IF_PASSWORDERROR', '0304': 'BFLB_IF_PASSWORDCLOSE', '0401': 'BFLB_EFUSE_WRITE_PARA_ERROR', '0402': 'BFLB_EFUSE_WRITE_ADDR_ERROR', '0403': 'BFLB_EFUSE_WRITE_ERROR', '0404': 'BFLB_EFUSE_READ_PARA_ERROR', '0405': 'BFLB_EFUSE_READ_ADDR_ERROR', '0406': 'BFLB_EFUSE_READ_ERROR', '0407': 'BFLB_EFUSE_READ_MAC_ERROR', '0408': 'BFLB_EFUSE_WRITE_MAC_ERROR', '0501': 'BFLB_MEMORY_WRITE_PARA_ERROR', '0502': 'BFLB_MEMORY_WRITE_ADDR_ERROR', '0503': 'BFLB_MEMORY_WRITE_ERROR', '0504': 'BFLB_MEMORY_READ_PARA_ERROR', '0505': 'BFLB_MEMORY_READ_ADDR_ERROR', '0506': 'BFLB_MEMORY_READ_ERROR', '0508': 'BFLB_REG_WRITE_PARA_ERROR', '0509': 'BFLB_REG_WRITE_ADDR_ERROR', '050a': 'BFLB_REG_WRITE_ERROR', '050b': 'BFLB_REG_READ_PARA_ERROR', '050c': 'BFLB_REG_READ_ADDR_ERROR', '050d': 'BFLB_REG_READ_ERROR', '0601': 'BFLB_ECDH_PARA_ERROR', '0602': 'BFLB_ECDH_PRIVATE_KEY_ERROR', '0603': 'BFLB_ECDH_SHARED_KEY_ERROR', '0604': 'BFLB_ECDH_RANDOM_VAL_ERROR', '0605': 'BFLB_ECDH_DECRYPT_ERROR', '0606': 'BFLB_ECDH_ENCRYPT_ERROR', 'fffc': 'BFLB_PLL_ERROR', 'fffd': 'BFLB_INVASION_ERROR', 'fffe': 'BFLB_POLLING', 'ffff': 'BFLB_FAIL'}
|
||||
eflash_loader_error_code = {'0000': 'BFLB SUCCESS', '0001': 'BFLB EFLASH LOADER SHAKEHAND FAIL', '0002': 'BFLB OPTION SET UNSUPPORTED', '0003': 'BFLB LOAD HELP BIN FAIL', '0004': 'BFLB RESET CPU FAIL', '0005': 'BFLB BURN RETRY FAIL', '0006': 'BFLB LOG READ FAIL', '0009': 'BFLB CONNECT OPENOCD SERVER FAIL', '000A': 'BFLB REPEAT BURN', '000B': 'BFLB CONFIG FILE NOT FOUND', '000C': 'BFLB SET CLOCK PLL FAIL', '000D': 'BFLB SET OPT FINISH FAIL', '000E': 'BFLB IMPORT PACKET FAIL', '0020': 'BFLB EFUSE READ FAIL', '0021': 'BFLB EFUSE WRITE FAIL', '0022': 'BFLB EFUSE COMPARE FAIL', '0023': 'BFLB EFUSE READ MAC ADDR FAIL', '0024': 'BFLB EFUSE WRITE MAC ADDR FAIL', '0025': 'BFLB EFUSE MAC ADDR CRC FAIL', '0030': 'BFLB READ FLASH JEDEC ID FAIL', '0031': 'BFLB READ FLASH STATUS REGISTER FAIL', '0032': 'BFLB WRITE FLASH STATUS REGISTER FAIL', '0033': 'BFLB FLASH CHIP ERASE FAIL', '0034': 'BFLB FLASH ERASE FAIL', '0035': 'BFLB FLASH READ FAIL', '0036': 'BFLB FLASH WRITE FAIL', '0037': 'BFLB FLASH WRITE CHECK FAIL', '0038': 'BFLB FLASH READ SHA FAIL', '0039': 'BFLB FLASH XIP MODE ENTER FAIL', '003A': 'BFLB FLASH XIP MODE EXIT FAIL', '003B': 'BFLB FLASH SET PARA FAIL', '003C': 'BFLB FLASH LOAD FIRMWARE BIN FAIL', '003D': 'BFLB FLASH MATCH TYPE FAIL', '003E': 'BFLB FLASH LOAD VERIFY FAIL', '003F': 'BFLB FLASH BOOT FAIL', '0040': 'BFLB FLASH CFG NOT FIT WITH BOOTHEADER', '0041': 'BFLB FLASH LOAD ROMFS FAIL', '0042': 'BFLB FLASH SWITCH BANK FAIL', '0043': 'BFLB FLASH IDENTIFY FAIL', '0044': 'BFLB FLASH CHIPERASE CONFLICT WITH SKIP MODE', '0050': 'BFLB IMG LOAD SHAKEHAND FAIL', '0051': 'BFLB IMG LOAD BOOT CHECK FAIL', '0060': 'BFLB IMG CREATE FAIL', '0061': 'BFLB IMG FILE NOT SET', '0062': 'BFLB IMG ADDR NOT SET', '0063': 'BFLB BOOTINFO ADDR NOT SET', '0064': 'BFLB AES KEY NOT SET', '0065': 'BFLB AES IV NOT SET', '0066': 'BFLB PUBLIC KEY NOT SET', '0067': 'BFLB PRIVATE KEY NOT SET', '0068': 'BFLB RAW DATA NOT NEED CREATE', '0069': 'BFLB FLASH ID NOT SUPPORT', '0070': 'BFLB FLASH ID NOT FOUND', '0071': 'BFLB ENCRYPT KEY LEN ERROR', '0072': 'BFLB AES IV LEN ERROR', '0073': 'BFLB AES IV SHOULD END WITH 00000000', '0074': 'BFLB IMG TYPE NOT FIT', '0075': 'BFLB IMG CREATE ENTER EXCEPT', '0076': 'BFLB PT NOT SET', '0077': 'BFLB AES KEY DATA OR LEN ERROR', '0078': 'BFLB AES IV DATA OR LEN ERROR', '0079': 'BFLB FACTORY IMG NOT FOUND', '007A': 'BFLB GENERATE ROMFS FAIL', '007B': 'BFLB PT PARCEL IS NULL', '007C': 'BFLB PT TABLE NOT SET', '007D': 'BFLB BOOT2 BIN NOT SET', '007E': 'BFLB FW BIN NOT SET', '007F': 'BFLB MEDIA NOT SET', '0080': 'BFLB ROMFS NOT SET', '0081': 'BFLB MFG BIN NOT SET', '0082': 'BFLB PT CHECK FAIL', '0083': 'D0 FW BIN NOT SET', '0084': 'IMTB BIN NOT SET', '0085': 'IMG LOADER BIN NOT SET', '0086': 'SBI BIN NOT SET', '0087': 'KERNEL BIN NOT SET', '0088': 'ROOTFS BIN NOT SET', '0089': 'KV BIN NOT SET', '0090': 'YOCBOOT BIN NOT SET', 'FFFF': 'BFLB BURN RETRY FAIL'}
|
||||
|
||||
def convert_path(path:str) -> str:
|
||||
return path.replace('\\/'.replace(os.sep, ''), os.sep)
|
||||
|
||||
def printf(*args):
|
||||
global local_log_data
|
||||
data = ''
|
||||
for arg in args:
|
||||
data += str(arg)
|
||||
if data:
|
||||
if conf_sign:
|
||||
for (key, value) in cgc.replace_name_list.items():
|
||||
data = data.replace(key, value)
|
||||
now_time = datetime.datetime.now().strftime('[%H:%M:%S.%f')[:-3] + '] - '
|
||||
data = now_time + data
|
||||
if local_log_en is True:
|
||||
local_log_data += data + '\n'
|
||||
else:
|
||||
local_log_data = ''
|
||||
if udp_send_log:
|
||||
tid = str(threading.get_ident())
|
||||
if udp_log_local_echo:
|
||||
print('[' + tid + ':]' + data.strip())
|
||||
try:
|
||||
udp_socket_server.sendto((data.strip() + '\r\n').encode('utf-8'), udp_clinet_dict[tid])
|
||||
except Exception as e:
|
||||
print(e)
|
||||
elif qt_sign and QtCore.QThread.currentThread().objectName():
|
||||
print('[Task%s]' % str(QtCore.QThread.currentThread().objectName()) + data.strip())
|
||||
else:
|
||||
print(data.strip())
|
||||
sys.stdout.flush()
|
||||
|
||||
def local_log_enable(en=False):
|
||||
global local_log_en
|
||||
if en is True:
|
||||
local_log_en = True
|
||||
else:
|
||||
local_log_en = False
|
||||
|
||||
def local_log_save(local_path='log', key_word=''):
|
||||
global local_log_data
|
||||
log_dir = os.path.join(app_path, local_path)
|
||||
if not os.path.exists(log_dir):
|
||||
os.makedirs(log_dir)
|
||||
if local_log_en is True:
|
||||
try:
|
||||
rq = time.strftime('%Y%m%d%H%M%S', time.localtime(time.time()))
|
||||
log_name = rq + '_' + key_word + '.log'
|
||||
log_path = os.path.join(log_dir, log_name)
|
||||
with codecs.open(log_path, 'w', encoding='utf-8') as fp:
|
||||
fp.write(local_log_data)
|
||||
except Exception as e:
|
||||
printf(e)
|
||||
traceback.print_exc(limit=5, file=sys.stdout)
|
||||
local_log_data = ''
|
||||
|
||||
def get_bflb_error_code(code):
|
||||
return bflb_error_code[code]
|
||||
|
||||
def clear_global():
|
||||
global error_code_num, error_code_num_task
|
||||
error_code_num = 'FFFF'
|
||||
error_code_num_task = []
|
||||
|
||||
def set_error_code(num_str, task=None):
|
||||
global error_code_num
|
||||
if task != None:
|
||||
if len(error_code_num_task) == 0:
|
||||
for i in range(66):
|
||||
error_code_num_task.append('FFFF')
|
||||
if error_code_num_task[task] == 'FFFF':
|
||||
error_code_num_task[task] = num_str
|
||||
if num_str == 'FFFF':
|
||||
error_code_num_task[task] = num_str
|
||||
else:
|
||||
if error_code_num == 'FFFF':
|
||||
error_code_num = num_str
|
||||
if num_str == 'FFFF':
|
||||
error_code_num = num_str
|
||||
|
||||
def get_error_code(task=None):
|
||||
if task != None:
|
||||
return error_code_num_task[task]
|
||||
return error_code_num
|
||||
|
||||
def errorcode_msg(task=None):
|
||||
if task != None:
|
||||
return '{"ErrorCode": "' + error_code_num_task[task] + '", "ErrorMsg":"' + eflash_loader_error_code[error_code_num_task[task]] + '"}'
|
||||
return '{"ErrorCode": "' + error_code_num + '", "ErrorMsg":"' + eflash_loader_error_code[error_code_num] + '"}'
|
||||
|
||||
def get_security_key():
|
||||
return (hexstr_to_bytearray('424F554646414C4F4C41424B45594956'), hexstr_to_bytearray('424F554646414C4F4C41424B00000000'))
|
||||
|
||||
def hexstr_to_bytearray_b(hexstring):
|
||||
return bytearray.fromhex(hexstring)
|
||||
|
||||
def hexstr_to_bytearray(hexstring):
|
||||
return bytearray.fromhex(hexstring)
|
||||
|
||||
def hexstr_to_bytearray_l(hexstring):
|
||||
b = bytearray.fromhex(hexstring)
|
||||
b.reverse()
|
||||
return b
|
||||
|
||||
def int_to_2bytearray_l(intvalue):
|
||||
return struct.pack('<H', intvalue)
|
||||
|
||||
def int_to_2bytearray_b(intvalue):
|
||||
return struct.pack('>H', intvalue)
|
||||
|
||||
def int_to_4bytearray_l(intvalue):
|
||||
src = bytearray(4)
|
||||
src[3] = intvalue >> 24 & 255
|
||||
src[2] = intvalue >> 16 & 255
|
||||
src[1] = intvalue >> 8 & 255
|
||||
src[0] = intvalue >> 0 & 255
|
||||
return src
|
||||
|
||||
def int_to_4bytearray_b(intvalue):
|
||||
val = int_to_4bytearray_l(intvalue)
|
||||
val.reverse()
|
||||
return val
|
||||
|
||||
def bytearray_reverse(a):
|
||||
length = len(a)
|
||||
b = bytearray(length)
|
||||
i = 0
|
||||
while i < length:
|
||||
b[i] = a[length - i - 1]
|
||||
i = i + 1
|
||||
return b
|
||||
|
||||
def bytearray_to_int(b):
|
||||
return int(binascii.hexlify(b), 16)
|
||||
|
||||
def string_to_bytearray(string):
|
||||
return bytes(string, encoding='utf8')
|
||||
|
||||
def bytearray_to_str(bytesarray):
|
||||
return str(bytesarray)
|
||||
|
||||
def get_random_hexstr(n_bytes):
|
||||
hextring = ''
|
||||
i = 0
|
||||
while i < n_bytes:
|
||||
hextring = hextring + str(binascii.hexlify(random.randint(0, 255)))
|
||||
i = i + 1
|
||||
return hextring
|
||||
|
||||
def get_crc32_bytearray(data):
|
||||
crc = binascii.crc32(data)
|
||||
return int_to_4bytearray_l(crc)
|
||||
|
||||
def add_to_16(par):
|
||||
while len(par) % 16 != 0:
|
||||
par += b'\x00'
|
||||
return par
|
||||
|
||||
def enable_udp_send_log(local_echo):
|
||||
global udp_send_log, udp_log_local_echo, udp_socket_server
|
||||
udp_send_log = True
|
||||
udp_log_local_echo = local_echo
|
||||
udp_socket_server = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||
|
||||
def add_udp_client(tid, upd_client):
|
||||
udp_clinet_dict[tid] = upd_client
|
||||
|
||||
def remove_udp_client(tid):
|
||||
del udp_clinet_dict[tid]
|
||||
|
||||
def update_cfg(cfg, section, key, value):
|
||||
if cfg.has_option(section, key):
|
||||
cfg.set(section, key, str(value))
|
||||
|
||||
def get_byte_array(string):
|
||||
return string.encode('utf-8')
|
||||
|
||||
def verify_hex_num(string):
|
||||
length = len(string)
|
||||
i = 0
|
||||
while True:
|
||||
if re.match('\\A[0-9a-fA-F]+\\Z', string[i:i + 1]) is None:
|
||||
return False
|
||||
i += 1
|
||||
if i >= length:
|
||||
break
|
||||
return True
|
||||
|
||||
def get_eflash_loader(xtal):
|
||||
xtal_suffix = str(xtal).lower().replace('.', 'p').replace('M', 'm').replace('RC', 'rc')
|
||||
return 'eflash_loader_' + xtal_suffix + '.bin'
|
||||
|
||||
def str_endian_switch(string):
|
||||
s = string[6:8] + string[4:6] + string[2:4] + string[0:2]
|
||||
return s
|
||||
|
||||
def img_create_sha256_data(data_bytearray):
|
||||
hashfun = hashlib.sha256()
|
||||
hashfun.update(data_bytearray)
|
||||
return hexstr_to_bytearray(hashfun.hexdigest())
|
||||
|
||||
def img_create_encrypt_data(data_bytearray, key_bytearray, iv_bytearray, flash_img):
|
||||
if flash_img == 0:
|
||||
cryptor = AES.new(key_bytearray, AES.MODE_CBC, iv_bytearray)
|
||||
ciphertext = cryptor.encrypt(data_bytearray)
|
||||
else:
|
||||
iv = Counter.new(128, initial_value=int(binascii.hexlify(iv_bytearray), 16))
|
||||
cryptor = AES.new(key_bytearray, AES.MODE_CTR, counter=iv)
|
||||
ciphertext = cryptor.encrypt(data_bytearray)
|
||||
return ciphertext
|
||||
|
||||
def aes_decrypt_data(data, key_bytearray, iv_bytearray, flash_img):
|
||||
if flash_img == 0:
|
||||
cryptor = AES.new(key_bytearray, AES.MODE_CBC, iv_bytearray)
|
||||
plaintext = cryptor.decrypt(data)
|
||||
else:
|
||||
iv = Counter.new(128, initial_value=int(binascii.hexlify(iv_bytearray), 16))
|
||||
cryptor = AES.new(key_bytearray, AES.MODE_CTR, counter=iv)
|
||||
plaintext = cryptor.decrypt(data)
|
||||
return plaintext
|
||||
|
||||
def open_file(file, mode='rb'):
|
||||
fp = open(os.path.join(app_path, file), mode)
|
||||
return fp
|
||||
|
||||
def copyfile(srcfile, dstfile):
|
||||
if os.path.isfile(srcfile):
|
||||
(fpath, fname) = os.path.split(dstfile)
|
||||
if not os.path.exists(fpath):
|
||||
os.makedirs(fpath)
|
||||
shutil.copyfile(srcfile, dstfile)
|
||||
else:
|
||||
printf('Src file not exists')
|
||||
|
||||
def get_systype():
|
||||
type_ = platform.system().lower()
|
||||
arch = platform.machine().lower()
|
||||
if type_ == 'windows':
|
||||
arch = 'amd64' if platform.architecture()[0] == '64bit' else 'x86'
|
||||
if arch:
|
||||
return '%s_%s' % (type_, arch)
|
||||
return type_
|
||||
|
||||
def get_serial_ports():
|
||||
try:
|
||||
from serial.tools.list_ports import comports
|
||||
except ImportError:
|
||||
return
|
||||
WINDOWS = sys.platform.startswith('win')
|
||||
result = []
|
||||
for (p, d, h) in comports():
|
||||
if not p:
|
||||
continue
|
||||
if WINDOWS and PY2:
|
||||
try:
|
||||
d = unicode(d, errors='ignore')
|
||||
except TypeError:
|
||||
pass
|
||||
if 'VID:PID' in h:
|
||||
result.append({'port': p, 'description': d, 'hwid': h})
|
||||
if not result:
|
||||
if 'darwin' in get_systype():
|
||||
for p in glob('/dev/tty.*'):
|
||||
result.append({'port': p, 'description': 'n/a', 'hwid': 'n/a'})
|
||||
return result
|
||||
|
||||
def serial_enumerate():
|
||||
prog_ports = []
|
||||
sdio_ports = []
|
||||
sdio_file_ser_dict = {}
|
||||
uart_ports = []
|
||||
file_dict = {}
|
||||
ports = []
|
||||
if sys.platform.startswith('win'):
|
||||
for (p, d, h) in comports():
|
||||
if not ('Virtual' in d or not p) and 'STM' not in d:
|
||||
continue
|
||||
if 'PID=1D6B' in h.upper():
|
||||
ser_value = h.split(' ')[2][4:]
|
||||
if ser_value not in sdio_file_ser_dict:
|
||||
sdio_file_ser_dict[ser_value] = p
|
||||
elif 'LOCATION' in h.upper():
|
||||
file_dict[sdio_file_ser_dict[ser_value]] = p
|
||||
sdio_ports.append(sdio_file_ser_dict[ser_value] + ' (SDIO)')
|
||||
else:
|
||||
file_dict[p] = sdio_file_ser_dict[ser_value]
|
||||
sdio_ports.append(p + ' (SDIO)')
|
||||
if 'FACTORYAIOT_PROG' in h.upper() or 'PID=42BF:B210' in h.upper():
|
||||
prog_ports.append(p + ' (PROG)')
|
||||
else:
|
||||
uart_ports.append(p)
|
||||
elif 'FACTORYAIOT_PROG' in h.upper() or 'PID=42BF:B210' in h.upper():
|
||||
prog_ports.append(p + ' (PROG)')
|
||||
else:
|
||||
uart_ports.append(p)
|
||||
try:
|
||||
uart_ports = sorted(uart_ports, key=lambda x: int(re.match('COM(\\d+)', x).group(1)))
|
||||
except Exception:
|
||||
uart_ports = sorted(uart_ports)
|
||||
ports = sorted(prog_ports) + sorted(sdio_ports) + uart_ports
|
||||
elif sys.platform.startswith('linux'):
|
||||
for (p, d, h) in comports():
|
||||
if not p:
|
||||
continue
|
||||
if 'PID=1D6B' in h.upper():
|
||||
ser_value = h.split(' ')[2][4:]
|
||||
if ser_value not in sdio_file_ser_dict:
|
||||
sdio_file_ser_dict[ser_value] = p
|
||||
elif sdio_file_ser_dict[ser_value] > p:
|
||||
file_dict[p] = sdio_file_ser_dict[ser_value]
|
||||
sdio_ports.append(p + ' (SDIO)')
|
||||
else:
|
||||
file_dict[sdio_file_ser_dict[ser_value]] = p
|
||||
sdio_ports.append(sdio_file_ser_dict[ser_value] + ' (SDIO)')
|
||||
elif 'FACTORYAIOT PROG' in h.upper():
|
||||
prog_ports.append(p + ' (PROG)')
|
||||
else:
|
||||
uart_ports.append(p)
|
||||
ports = sorted(prog_ports) + sorted(sdio_ports) + sorted(uart_ports)
|
||||
elif sys.platform.startswith('darwin'):
|
||||
for dev in glob('/dev/tty.usb*'):
|
||||
ports.append(dev)
|
||||
return ports
|
||||
|
||||
def pylink_enumerate():
|
||||
try:
|
||||
if sys.platform == 'win32':
|
||||
obj_dll = pylink.Library(dllpath=path_dll)
|
||||
obj = pylink.JLink(lib=obj_dll)
|
||||
else:
|
||||
obj = pylink.JLink()
|
||||
except Exception:
|
||||
return []
|
||||
else:
|
||||
return obj.connected_emulators()
|
||||
|
||||
def cklink_openocd_enumerate():
|
||||
ports_cklink = []
|
||||
ports_openocd = []
|
||||
if sys.platform.startswith('win'):
|
||||
for (p, d, h) in comports():
|
||||
if not p:
|
||||
continue
|
||||
if 'FACTORYAIOT_PROG' in h.upper():
|
||||
match1 = re.search('FACTORYAIOT_PROG_([a-zA-Z0-9]{6}) LOCATION', h.upper(), re.I)
|
||||
match2 = re.search('FACTORYAIOT_PROG_([a-zA-Z0-9]{6})$', h.upper(), re.I)
|
||||
if match1 is not None:
|
||||
ports_cklink.append(match1.group(1))
|
||||
if match2 is not None:
|
||||
ports_openocd.append(match2.group(1))
|
||||
elif sys.platform.startswith('linux'):
|
||||
for (p, d, h) in comports():
|
||||
if not p:
|
||||
continue
|
||||
if 'FactoryAIOT Prog' in h:
|
||||
match1 = re.search('FactoryAIOT Prog ([a-zA-Z0-9]{6}) LOCATION', h, re.I)
|
||||
if match1 is not None:
|
||||
ports_cklink.append(match1.group(1))
|
||||
return (ports_cklink, ports_openocd)
|
||||
|
||||
def image_create_parser_init():
|
||||
parser = argparse.ArgumentParser(description='bouffalolab image create command')
|
||||
parser.add_argument('--chipname', dest='chipname', help='chip name')
|
||||
parser.add_argument('--imgfile', dest='imgfile', help='image file')
|
||||
parser.add_argument('--security', dest='security', help='security save efusedata')
|
||||
parser.add_argument('-i', '--image', dest='image', help='image type: media or if')
|
||||
parser.add_argument('-c', '--cpu', dest='cpu', help='cpu type: cpu0 cpu1 or all')
|
||||
parser.add_argument('-g', '--group', dest='group', help='group type')
|
||||
parser.add_argument('-s', '--signer', dest='signer', help='signer')
|
||||
return parser
|
||||
|
||||
def eflash_loader_parser_init():
|
||||
parser = argparse.ArgumentParser(description='bouffalolab eflash loader command')
|
||||
parser.add_argument('--chipname', dest='chipname', help='chip name')
|
||||
parser.add_argument('--chipid', dest='chipid', action='store_true', help='chip id')
|
||||
parser.add_argument('--usage', dest='usage', action='store_true', help='display usage')
|
||||
parser.add_argument('--flash', dest='flash', action='store_true', help='target is flash')
|
||||
parser.add_argument('--efuse', dest='efuse', action='store_true', help='target is efuse')
|
||||
parser.add_argument('--ram', dest='ram', action='store_true', help='target is ram')
|
||||
parser.add_argument('-w', '--write', dest='write', action='store_true', help='write to flash/efuse')
|
||||
parser.add_argument('-e', '--erase', dest='erase', action='store_true', help='erase flash')
|
||||
parser.add_argument('-r', '--read', dest='read', action='store_true', help='read from flash/efuse')
|
||||
parser.add_argument('-n', '--none', dest='none', action='store_true', help='eflash loader environment init')
|
||||
parser.add_argument('-p', '--port', dest='port', help='serial port to use')
|
||||
parser.add_argument('-b', '--baudrate', dest='baudrate', type=int, help='the speed at which to communicate')
|
||||
parser.add_argument('-c', '--config', dest='config', help='eflash loader config file')
|
||||
parser.add_argument('-i', '--interface', dest='interface', help='interface type: uart/jlink/openocd')
|
||||
parser.add_argument('--xtal', dest='xtal', help='xtal type')
|
||||
parser.add_argument('--start', dest='start', help='start address')
|
||||
parser.add_argument('--end', dest='end', help='end address')
|
||||
parser.add_argument('--addr', dest='addr', help='address to write')
|
||||
parser.add_argument('--mac', dest='mac', help='mac address to write')
|
||||
parser.add_argument('--file', dest='file', help='file to store read data or file to write')
|
||||
parser.add_argument('--skip', dest='skip', help='skip write file to flash')
|
||||
parser.add_argument('--packet', dest='packet', help=' import packet to replace burn file')
|
||||
parser.add_argument('--efusefile', dest='efusefile', help='efuse file to write efuse')
|
||||
parser.add_argument('--data', dest='data', help='data to write')
|
||||
parser.add_argument('--mass', dest='mass', help='load mass bin')
|
||||
parser.add_argument('--loadstr', dest='loadstr', help='')
|
||||
parser.add_argument('--loadfile', dest='loadfile', help='')
|
||||
parser.add_argument('--userarea', dest='userarea', help='user area')
|
||||
parser.add_argument('--romfs', dest='romfs', help='romfs data to write')
|
||||
parser.add_argument('--csvfile', dest='csvfile', help='csv file contains 3/5 tuples')
|
||||
parser.add_argument('--csvaddr', dest='csvaddr', help='address to write for csv file')
|
||||
parser.add_argument('--para', dest='para', help='efuse para')
|
||||
parser.add_argument('--isp', dest='isp', action='store_true', help='isp config')
|
||||
parser.add_argument('--createcfg', dest='createcfg', help='img create cfg file')
|
||||
parser.add_argument('--key', dest='key', help='aes key for socket')
|
||||
parser.add_argument('--ecdh', dest='ecdh', action='store_true', help='open ecdh function')
|
||||
parser.add_argument('--echo', dest='echo', action='store_true', help='open local log echo')
|
||||
parser.add_argument('-a', '--auto', dest='auto', action='store_true', help='auto flash')
|
||||
parser.add_argument('-v', '--version', dest='version', action='store_true', help='display version')
|
||||
return parser
|
||||
|
21
pylink/__init__.py
Normal file
21
pylink/__init__.py
Normal file
|
@ -0,0 +1,21 @@
|
|||
# decompyle3 version 3.9.0
|
||||
# Python bytecode version base 3.7.0 (3394)
|
||||
# Decompiled from: Python 3.7.16 (default, Mar 30 2023, 01:25:49)
|
||||
# [GCC 12.2.1 20220924]
|
||||
# Embedded file name: pylink/__init__.py
|
||||
__version__ = '0.5.0'
|
||||
__title__ = 'pylink'
|
||||
__author__ = 'Square Embedded Software Team'
|
||||
__author_email__ = 'esw-team@squareup.com'
|
||||
__copyright__ = 'Copyright 2017 Square, Inc.'
|
||||
__license__ = 'Apache 2.0'
|
||||
__url__ = 'http://www.github.com/Square/pylink'
|
||||
__description__ = 'Python interface for SEGGER J-Link.'
|
||||
__long_description__ = "This module provides a Python implementation of the\nJ-Link SDK by leveraging the SDK's DLL.\n"
|
||||
from .enums import *
|
||||
from .errors import *
|
||||
from .jlink import *
|
||||
from .library import *
|
||||
from .structs import *
|
||||
from .unlockers import *
|
||||
# okay decompiling ./pylink/__init__.pyc
|
57
pylink/binpacker.py
Normal file
57
pylink/binpacker.py
Normal file
|
@ -0,0 +1,57 @@
|
|||
# decompyle3 version 3.9.0
|
||||
# Python bytecode version base 3.7.0 (3394)
|
||||
# Decompiled from: Python 3.7.16 (default, Mar 30 2023, 01:25:49)
|
||||
# [GCC 12.2.1 20220924]
|
||||
# Embedded file name: pylink/binpacker.py
|
||||
import ctypes, math
|
||||
BITS_PER_BYTE = 8
|
||||
|
||||
def pack_size(value):
|
||||
"""Returns the number of bytes required to represent a given value.
|
||||
|
||||
Args:
|
||||
value (int): the natural number whose size to get
|
||||
|
||||
Returns:
|
||||
The minimal number of bytes required to represent the given integer.
|
||||
|
||||
Raises:
|
||||
ValueError: if ``value < 0``.
|
||||
TypeError: if ``value`` is not a number.
|
||||
"""
|
||||
if value == 0:
|
||||
return 1
|
||||
if value < 0:
|
||||
raise ValueError('Expected non-negative integer.')
|
||||
return int(math.log(value, 256)) + 1
|
||||
|
||||
|
||||
def pack(value, nbits=None):
|
||||
"""Packs a given value into an array of 8-bit unsigned integers.
|
||||
|
||||
If ``nbits`` is not present, calculates the minimal number of bits required
|
||||
to represent the given ``value``. The result is little endian.
|
||||
|
||||
Args:
|
||||
value (int): the integer value to pack
|
||||
nbits (int): optional number of bits to use to represent the value
|
||||
|
||||
Returns:
|
||||
An array of ``ctypes.c_uint8`` representing the packed ``value``.
|
||||
|
||||
Raises:
|
||||
ValueError: if ``value < 0`` and ``nbits`` is ``None`` or ``nbits <= 0``.
|
||||
TypeError: if ``nbits`` or ``value`` are not numbers.
|
||||
"""
|
||||
if nbits is None:
|
||||
nbits = pack_size(value) * BITS_PER_BYTE
|
||||
else:
|
||||
if nbits <= 0:
|
||||
raise ValueError('Given number of bits must be greater than 0.')
|
||||
buf_size = int(math.ceil(nbits / float(BITS_PER_BYTE)))
|
||||
buf = (ctypes.c_uint8 * buf_size)()
|
||||
for idx, _ in enumerate(buf):
|
||||
buf[idx] = value >> idx * BITS_PER_BYTE & 255
|
||||
|
||||
return buf
|
||||
# okay decompiling ./pylink/binpacker.pyc
|
52
pylink/decorators.py
Normal file
52
pylink/decorators.py
Normal file
|
@ -0,0 +1,52 @@
|
|||
# decompyle3 version 3.9.0
|
||||
# Python bytecode version base 3.7.0 (3394)
|
||||
# Decompiled from: Python 3.7.16 (default, Mar 30 2023, 01:25:49)
|
||||
# [GCC 12.2.1 20220924]
|
||||
# Embedded file name: pylink/decorators.py
|
||||
from . import threads
|
||||
import functools
|
||||
|
||||
def async_decorator(func):
|
||||
"""Asynchronous function decorator. Interprets the function as being
|
||||
asynchronous, so returns a function that will handle calling the
|
||||
Function asynchronously.
|
||||
|
||||
Args:
|
||||
func (function): function to be called asynchronously
|
||||
|
||||
Returns:
|
||||
The wrapped function.
|
||||
|
||||
Raises:
|
||||
AttributeError: if ``func`` is not callable
|
||||
"""
|
||||
|
||||
@functools.wraps(func)
|
||||
def async_wrapper(*args, **kwargs):
|
||||
if not ('callback' not in kwargs or kwargs['callback']):
|
||||
return func(*args, **kwargs)
|
||||
callback = kwargs.pop('callback')
|
||||
if not callable(callback):
|
||||
raise TypeError("Expected 'callback' is not callable.")
|
||||
|
||||
def thread_func(*args, **kwargs):
|
||||
exception, res = (None, None)
|
||||
try:
|
||||
res = func(*args, **kwargs)
|
||||
except Exception as e:
|
||||
try:
|
||||
exception = e
|
||||
finally:
|
||||
e = None
|
||||
del e
|
||||
|
||||
return callback(exception, res)
|
||||
|
||||
thread = threads.ThreadReturn(target=thread_func, args=args,
|
||||
kwargs=kwargs)
|
||||
thread.daemon = True
|
||||
thread.start()
|
||||
return thread
|
||||
|
||||
return async_wrapper
|
||||
# okay decompiling ./pylink/decorators.pyc
|
528
pylink/enums.py
Normal file
528
pylink/enums.py
Normal file
|
@ -0,0 +1,528 @@
|
|||
# decompyle3 version 3.9.0
|
||||
# Python bytecode version base 3.7.0 (3394)
|
||||
# Decompiled from: Python 3.7.16 (default, Mar 30 2023, 01:25:49)
|
||||
# [GCC 12.2.1 20220924]
|
||||
# Embedded file name: pylink/enums.py
|
||||
import ctypes
|
||||
|
||||
class JLinkGlobalErrors(object):
|
||||
__doc__ = 'Enumeration for the error codes which any J-Link SDK DLL API-function\n can have as a return value.'
|
||||
UNSPECIFIED_ERROR = -1
|
||||
EMU_NO_CONNECTION = -256
|
||||
EMU_COMM_ERROR = -257
|
||||
DLL_NOT_OPEN = -258
|
||||
VCC_FAILURE = -259
|
||||
INVALID_HANDLE = -260
|
||||
NO_CPU_FOUND = -261
|
||||
EMU_FEATURE_UNSUPPORTED = -262
|
||||
EMU_NO_MEMORY = -263
|
||||
TIF_STATUS_ERROR = -264
|
||||
FLASH_PROG_COMPARE_FAILED = -265
|
||||
FLASH_PROG_PROGRAM_FAILED = -266
|
||||
FLASH_PROG_VERIFY_FAILED = -267
|
||||
OPEN_FILE_FAILED = -268
|
||||
UNKNOWN_FILE_FORMAT = -269
|
||||
WRITE_TARGET_MEMORY_FAILED = -270
|
||||
DEVICE_FEATURE_NOT_SUPPORTED = -271
|
||||
WRONG_USER_CONFIG = -272
|
||||
NO_TARGET_DEVICE_SELECTED = -273
|
||||
CPU_IN_LOW_POWER_MODE = -274
|
||||
|
||||
@classmethod
|
||||
def to_string(cls, error_code):
|
||||
"""Returns the string message for the given ``error_code``.
|
||||
|
||||
Args:
|
||||
cls (JlinkGlobalErrors): the ``JLinkGlobalErrors`` class
|
||||
error_code (int): error code to convert
|
||||
|
||||
Returns:
|
||||
An error string corresponding to the error code.
|
||||
|
||||
Raises:
|
||||
ValueError: if the error code is invalid.
|
||||
"""
|
||||
if error_code == cls.EMU_NO_CONNECTION:
|
||||
return 'No connection to emulator.'
|
||||
if error_code == cls.EMU_COMM_ERROR:
|
||||
return 'Emulator connection error.'
|
||||
if error_code == cls.DLL_NOT_OPEN:
|
||||
return "DLL has not been opened. Did you call '.connect()'?"
|
||||
if error_code == cls.VCC_FAILURE:
|
||||
return 'Target system has no power.'
|
||||
if error_code == cls.INVALID_HANDLE:
|
||||
return 'Given file / memory handle is invalid.'
|
||||
if error_code == cls.NO_CPU_FOUND:
|
||||
return 'Could not find supported CPU.'
|
||||
if error_code == cls.EMU_FEATURE_UNSUPPORTED:
|
||||
return 'Emulator does not support the selected feature.'
|
||||
if error_code == cls.EMU_NO_MEMORY:
|
||||
return 'Emulator out of memory.'
|
||||
if error_code == cls.TIF_STATUS_ERROR:
|
||||
return 'Target interface error.'
|
||||
if error_code == cls.FLASH_PROG_COMPARE_FAILED:
|
||||
return 'Programmed data differs from source data.'
|
||||
if error_code == cls.FLASH_PROG_PROGRAM_FAILED:
|
||||
return 'Programming error occured.'
|
||||
if error_code == cls.FLASH_PROG_VERIFY_FAILED:
|
||||
return 'Error while verifying programmed data.'
|
||||
if error_code == cls.OPEN_FILE_FAILED:
|
||||
return 'Specified file could not be opened.'
|
||||
if error_code == cls.UNKNOWN_FILE_FORMAT:
|
||||
return 'File format of selected file is not supported.'
|
||||
if error_code == cls.WRITE_TARGET_MEMORY_FAILED:
|
||||
return 'Could not write target memory.'
|
||||
if error_code == cls.DEVICE_FEATURE_NOT_SUPPORTED:
|
||||
return 'Feature not supported by connected device.'
|
||||
if error_code == cls.WRONG_USER_CONFIG:
|
||||
return 'User configured DLL parameters incorrectly.'
|
||||
if error_code == cls.NO_TARGET_DEVICE_SELECTED:
|
||||
return 'User did not specify core to connect to.'
|
||||
if error_code == cls.CPU_IN_LOW_POWER_MODE:
|
||||
return 'Target CPU is in low power mode.'
|
||||
if error_code == cls.UNSPECIFIED_ERROR:
|
||||
return 'Unspecified error.'
|
||||
raise ValueError('Invalid error code: %d' % error_code)
|
||||
|
||||
|
||||
class JLinkEraseErrors(JLinkGlobalErrors):
|
||||
__doc__ = 'Enumeration for the error codes generated during an erase operation.'
|
||||
ILLEGAL_COMMAND = -5
|
||||
|
||||
@classmethod
|
||||
def to_string(cls, error_code):
|
||||
if error_code == cls.ILLEGAL_COMMAND:
|
||||
return 'Failed to erase sector.'
|
||||
return super(JLinkEraseErrors, cls).to_string(error_code)
|
||||
|
||||
|
||||
class JLinkFlashErrors(JLinkGlobalErrors):
|
||||
__doc__ = 'Enumeration for the error codes generated during a flash operation.'
|
||||
COMPARE_ERROR = -2
|
||||
PROGRAM_ERASE_ERROR = -3
|
||||
VERIFICATION_ERROR = -4
|
||||
|
||||
@classmethod
|
||||
def to_string(cls, error_code):
|
||||
if error_code == cls.COMPARE_ERROR:
|
||||
return 'Error comparing flash content to programming data.'
|
||||
if error_code == cls.PROGRAM_ERASE_ERROR:
|
||||
return 'Error during program/erase phase.'
|
||||
if error_code == cls.VERIFICATION_ERROR:
|
||||
return 'Error verifying programmed data.'
|
||||
return super(JLinkFlashErrors, cls).to_string(error_code)
|
||||
|
||||
|
||||
class JLinkWriteErrors(JLinkGlobalErrors):
|
||||
__doc__ = 'Enumeration for the error codes generated during a write.'
|
||||
ZONE_NOT_FOUND_ERROR = -5
|
||||
|
||||
@classmethod
|
||||
def to_string(cls, error_code):
|
||||
if error_code == cls.ZONE_NOT_FOUND_ERROR:
|
||||
return 'Zone not found'
|
||||
return super(JLinkWriteErrors, cls).to_string(error_code)
|
||||
|
||||
|
||||
class JLinkReadErrors(JLinkGlobalErrors):
|
||||
__doc__ = 'Enumeration for the error codes generated during a read.'
|
||||
ZONE_NOT_FOUND_ERROR = -5
|
||||
|
||||
@classmethod
|
||||
def to_string(cls, error_code):
|
||||
if error_code == cls.ZONE_NOT_FOUND_ERROR:
|
||||
return 'Zone not found'
|
||||
return super(JLinkReadErrors, cls).to_string(error_code)
|
||||
|
||||
|
||||
class JLinkDataErrors(JLinkGlobalErrors):
|
||||
__doc__ = 'Enumeration for the error codes generated when setting a data event.'
|
||||
ERROR_UNKNOWN = 2147483648
|
||||
ERROR_NO_MORE_EVENTS = 2147483649
|
||||
ERROR_NO_MORE_ADDR_COMP = 2147483650
|
||||
ERROR_NO_MORE_DATA_COMP = 2147483652
|
||||
ERROR_INVALID_ADDR_MASK = 2147483680
|
||||
ERROR_INVALID_DATA_MASK = 2147483712
|
||||
ERROR_INVALID_ACCESS_MASK = 2147483776
|
||||
|
||||
@classmethod
|
||||
def to_string(cls, error_code):
|
||||
if error_code == cls.ERROR_UNKNOWN:
|
||||
return 'Unknown error.'
|
||||
if error_code == cls.ERROR_NO_MORE_EVENTS:
|
||||
return 'There are no more available watchpoint units.'
|
||||
if error_code == cls.ERROR_NO_MORE_ADDR_COMP:
|
||||
return 'No more address comparisons can be set.'
|
||||
if error_code == cls.ERROR_NO_MORE_DATA_COMP:
|
||||
return 'No more data comparisons can be set.'
|
||||
if error_code == cls.ERROR_INVALID_ADDR_MASK:
|
||||
return 'Invalid flags passed for the address mask.'
|
||||
if error_code == cls.ERROR_INVALID_DATA_MASK:
|
||||
return 'Invalid flags passed for the data mask.'
|
||||
if error_code == cls.ERROR_INVALID_ACCESS_MASK:
|
||||
return 'Invalid flags passed for the access mask.'
|
||||
return super(JLinkDataErrors, cls).to_string(error_code)
|
||||
|
||||
|
||||
class JLinkRTTErrors(JLinkGlobalErrors):
|
||||
__doc__ = 'Enumeration for error codes from RTT.'
|
||||
RTT_ERROR_CONTROL_BLOCK_NOT_FOUND = -2
|
||||
|
||||
@classmethod
|
||||
def to_string(cls, error_code):
|
||||
if error_code == cls.RTT_ERROR_CONTROL_BLOCK_NOT_FOUND:
|
||||
return 'The RTT Control Block has not yet been found (wait?)'
|
||||
return super(JLinkRTTErrors, cls).to_string(error_code)
|
||||
|
||||
|
||||
class JLinkHost(object):
|
||||
__doc__ = 'Enumeration for the different JLink hosts: currently only IP and USB.'
|
||||
USB = 1
|
||||
IP = 2
|
||||
USB_OR_IP = USB | IP
|
||||
|
||||
|
||||
class JLinkInterfaces(object):
|
||||
__doc__ = 'Target interfaces for the J-Link.'
|
||||
JTAG = 0
|
||||
SWD = 1
|
||||
FINE = 3
|
||||
ICSP = 4
|
||||
SPI = 5
|
||||
C2 = 6
|
||||
|
||||
|
||||
class JLinkResetStrategyCortexM3(object):
|
||||
__doc__ = 'Target reset strategies for the J-Link.\n\n Attributes:\n NORMAL: default reset strategy, does whatever is best to reset.\n CORE: only the core is reset via the ``VECTRESET`` bit.\n RESETPIN: pulls the reset pin low to reset the core and peripherals.\n CONNECT_UNDER_RESET: J-Link connects to target while keeping reset\n active. This is recommented for STM32 devices.\n HALT_AFTER_BTL: halt the core after the bootloader is executed.\n HALT_BEFORE_BTL: halt the core before the bootloader is executed.\n KINETIS: performs a normal reset, but also disables the watchdog.\n ADI_HALT_AFTER_KERNEL: sets the ``SYSRESETREQ`` bit in the ``AIRCR`` in\n order to reset the device.\n CORE_AND_PERIPHERALS: sets the ``SYSRESETREQ`` bit in the ``AIRCR``, and\n the ``VC_CORERESET`` bit in the ``DEMCR`` to make sure that the CPU is\n halted immediately after reset.\n LPC1200: reset for LPC1200 devices.\n S3FN60D: reset for Samsung S3FN60D devices.\n\n Note:\n Please see the J-Link SEGGER Documentation, UM8001, for full information\n about the different reset strategies.\n '
|
||||
NORMAL = 0
|
||||
CORE = 1
|
||||
RESETPIN = 2
|
||||
CONNECT_UNDER_RESET = 3
|
||||
HALT_AFTER_BTL = 4
|
||||
HALT_BEFORE_BTL = 5
|
||||
KINETIS = 6
|
||||
ADI_HALT_AFTER_KERNEL = 7
|
||||
CORE_AND_PERIPHERALS = 8
|
||||
LPC1200 = 9
|
||||
S3FN60D = 10
|
||||
|
||||
|
||||
class JLinkFunctions(object):
|
||||
__doc__ = 'Collection of function prototype and type builders for the J-Link SDK\n API calls.'
|
||||
LOG_PROTOTYPE = ctypes.CFUNCTYPE(None, ctypes.c_char_p)
|
||||
UNSECURE_HOOK_PROTOTYPE = ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_char_p, ctypes.c_char_p, ctypes.c_uint32)
|
||||
FLASH_PROGRESS_PROTOTYPE = ctypes.CFUNCTYPE(None, ctypes.c_char_p, ctypes.c_char_p, ctypes.c_int)
|
||||
|
||||
|
||||
class JLinkCore(object):
|
||||
__doc__ = 'Enumeration for the different CPU core identifiers.\n\n These are the possible cores for targets the J-Link is connected to.\n Note that these are bitfields.'
|
||||
NONE = 0
|
||||
ANY = 4294967295
|
||||
CORTEX_M1 = 16777471
|
||||
COLDFIRE = 50331647
|
||||
CORTEX_M3 = 50331903
|
||||
CORTEX_M3_R1P0 = 50331664
|
||||
CORTEX_M3_R1P1 = 50331665
|
||||
CORTEX_M3_R2P0 = 50331680
|
||||
SIM = 83886079
|
||||
XSCALE = 100663295
|
||||
CORTEX_M0 = 100663551
|
||||
CORTEX_M_V8BASEL = 100729087
|
||||
ARM7 = 134217727
|
||||
ARM7TDMI = 117440767
|
||||
ARM7TDMI_R3 = 117440575
|
||||
ARM7TDMI_R4 = 117440591
|
||||
ARM7TDMI_S = 117441023
|
||||
ARM7TDMI_S_R3 = 117440831
|
||||
ARM7TDMI_S_R4 = 117440847
|
||||
CORTEX_A8 = 134217983
|
||||
CORTEX_A7 = 134742271
|
||||
CORTEX_A9 = 134807807
|
||||
CORTEX_A12 = 134873343
|
||||
CORTEX_A15 = 134938879
|
||||
CORTEX_A17 = 135004415
|
||||
ARM9 = 167772159
|
||||
ARM9TDMI_S = 150995455
|
||||
ARM920T = 153092351
|
||||
ARM922T = 153223423
|
||||
ARM926EJ_S = 153485823
|
||||
ARM946E_S = 155582975
|
||||
ARM966E_S = 157680127
|
||||
ARM968E_S = 157811199
|
||||
ARM11 = 201326591
|
||||
ARM1136 = 188153855
|
||||
ARM1136J = 188089087
|
||||
ARM1136J_S = 188089343
|
||||
ARM1136JF = 188090111
|
||||
ARM1136JF_S = 188090367
|
||||
ARM1156 = 190251007
|
||||
ARM1176 = 192348159
|
||||
ARM1176J = 192283391
|
||||
ARM1176J_S = 192283647
|
||||
ARM1176JF = 192284415
|
||||
ARM1176JF_S = 192284671
|
||||
CORTEX_R4 = 201326847
|
||||
CORTEX_R5 = 201392383
|
||||
RX = 234881023
|
||||
RX610 = 218169343
|
||||
RX62N = 218234879
|
||||
RX62T = 218300415
|
||||
RX63N = 218365951
|
||||
RX630 = 218431487
|
||||
RX63T = 218497023
|
||||
RX621 = 218562559
|
||||
RX62G = 218628095
|
||||
RX631 = 218693631
|
||||
RX210 = 219217919
|
||||
RX21A = 219283455
|
||||
RX220 = 219348991
|
||||
RX230 = 219414527
|
||||
RX231 = 219480063
|
||||
RX23T = 219545599
|
||||
RX111 = 220266495
|
||||
RX110 = 220332031
|
||||
RX113 = 220397567
|
||||
RX64M = 221315071
|
||||
RX71M = 221380607
|
||||
CORTEX_M4 = 234881279
|
||||
CORTEX_M7 = 234946815
|
||||
CORTEX_M_V8MAINL = 235012351
|
||||
CORTEX_A5 = 251658495
|
||||
POWER_PC = 285212671
|
||||
POWER_PC_N1 = 285147391
|
||||
POWER_PC_N2 = 285147647
|
||||
MIPS = 301989887
|
||||
MIPS_M4K = 285278207
|
||||
MIPS_MICROAPTIV = 285343743
|
||||
EFM8_UNSPEC = 318767103
|
||||
CIP51 = 302055423
|
||||
|
||||
|
||||
class JLinkDeviceFamily(object):
|
||||
__doc__ = 'Enumeration for the difference device families.\n\n These are the possible device families for targets that the J-Link is\n connected to.'
|
||||
AUTO = 0
|
||||
CORTEX_M1 = 1
|
||||
COLDFIRE = 2
|
||||
CORTEX_M3 = 3
|
||||
SIMULATOR = 4
|
||||
XSCALE = 5
|
||||
CORTEX_M0 = 6
|
||||
ARM7 = 7
|
||||
CORTEX_A8 = 8
|
||||
CORTEX_A9 = 8
|
||||
ARM9 = 9
|
||||
ARM10 = 10
|
||||
ARM11 = 11
|
||||
CORTEX_R4 = 12
|
||||
RX = 13
|
||||
CORTEX_M4 = 14
|
||||
CORTEX_A5 = 15
|
||||
POWERPC = 16
|
||||
MIPS = 17
|
||||
EFM8 = 18
|
||||
ANY = 255
|
||||
|
||||
|
||||
class JLinkFlags(object):
|
||||
__doc__ = 'Enumeration for the different flags that are passed to the J-Link C SDK\n API methods.'
|
||||
GO_OVERSTEP_BP = 1
|
||||
DLG_BUTTON_YES = 1
|
||||
DLG_BUTTON_NO = 2
|
||||
DLG_BUTTON_OK = 4
|
||||
DLG_BUTTON_CANCEL = 8
|
||||
HW_PIN_STATUS_LOW = 0
|
||||
HW_PIN_STATUS_HIGH = 1
|
||||
HW_PIN_STATUS_UNKNOWN = 255
|
||||
|
||||
|
||||
class JLinkSWOInterfaces(object):
|
||||
__doc__ = 'Serial Wire Output (SWO) interfaces.'
|
||||
UART = 0
|
||||
MANCHESTER = 1
|
||||
|
||||
|
||||
class JLinkSWOCommands(object):
|
||||
__doc__ = 'Serial Wire Output (SWO) commands.'
|
||||
START = 0
|
||||
STOP = 1
|
||||
FLUSH = 2
|
||||
GET_SPEED_INFO = 3
|
||||
GET_NUM_BYTES = 10
|
||||
SET_BUFFERSIZE_HOST = 20
|
||||
SET_BUFFERSIZE_EMU = 21
|
||||
|
||||
|
||||
class JLinkCPUCapabilities(object):
|
||||
__doc__ = 'Target CPU Cabilities.'
|
||||
READ_MEMORY = 2
|
||||
WRITE_MEMORY = 4
|
||||
READ_REGISTERS = 8
|
||||
WRITE_REGISTERS = 16
|
||||
GO = 32
|
||||
STEP = 64
|
||||
HALT = 128
|
||||
IS_HALTED = 256
|
||||
RESET = 512
|
||||
RUN_STOP = 1024
|
||||
TERMINAL = 2048
|
||||
DCC = 16384
|
||||
HSS = 32768
|
||||
|
||||
|
||||
class JLinkHaltReasons(object):
|
||||
__doc__ = 'Halt reasons for the CPU.\n\n Attributes:\n DBGRQ: CPU has been halted because DBGRQ signal asserted.\n CODE_BREAKPOINT: CPU has been halted because of code breakpoint match.\n DATA_BREAKPOINT: CPU has been halted because of data breakpoint match.\n VECTOR_CATCH: CPU has been halted because of vector catch.\n '
|
||||
DBGRQ = 0
|
||||
CODE_BREAKPOINT = 1
|
||||
DATA_BREAKPOINT = 2
|
||||
VECTOR_CATCH = 3
|
||||
|
||||
|
||||
class JLinkVectorCatchCortexM3(object):
|
||||
__doc__ = 'Vector catch types for the ARM Cortex M3.\n\n Attributes:\n CORE_RESET: The CPU core reset.\n MEM_ERROR: A memory management error occurred.\n COPROCESSOR_ERROR: Usage fault error accessing the Coprocessor.\n CHECK_ERROR: Usage fault error on enabled check.\n STATE_ERROR: Usage fault state error.\n BUS_ERROR: Normal bus error.\n INT_ERROR: Interrupt or exception service error.\n HARD_ERROR: Hard fault error.\n '
|
||||
CORE_RESET = 1
|
||||
MEM_ERROR = 16
|
||||
COPROCESSOR_ERROR = 32
|
||||
CHECK_ERROR = 64
|
||||
STATE_ERROR = 128
|
||||
BUS_ERROR = 256
|
||||
INT_ERROR = 512
|
||||
HARD_ERROR = 1024
|
||||
|
||||
|
||||
class JLinkBreakpoint(object):
|
||||
__doc__ = 'J-Link breakpoint types.\n\n Attributes:\n SW_RAM: Software breakpont located in RAM.\n SW_FLASH: Software breakpoint located in flash.\n SW: Software breakpoint located in RAM or flash.\n HW: Hardware breakpoint.\n ANY: Allows specifying any time of breakpoint.\n ARM: Breakpoint in ARM mode (only available on ARM 7/9 cores).\n THUMB: Breakpoint in THUMB mode (only available on ARM 7/9 cores).\n '
|
||||
SW_RAM = 16
|
||||
SW_FLASH = 32
|
||||
SW = 240
|
||||
HW = 4294967040
|
||||
ANY = 4294967280
|
||||
ARM = 1
|
||||
THUMB = 2
|
||||
|
||||
|
||||
class JLinkBreakpointImplementation(object):
|
||||
__doc__ = 'J-Link breakpoint implementation types.\n\n Attributes:\n HARD: Hardware breakpoint using a breakpoint unit.\n SOFT: Software breakpoint using a breakpoint instruction.\n PENDING: Breakpoint has not been set yet.\n FLASH: Breakpoint set in flash.\n '
|
||||
HARD = 1
|
||||
SOFT = 2
|
||||
PENDING = 4
|
||||
FLASH = 16
|
||||
|
||||
|
||||
class JLinkEventTypes(object):
|
||||
__doc__ = 'J-Link data event types.\n\n Attributes:\n BREAKPOINT: breakpoint data event.\n '
|
||||
BREAKPOINT = 1
|
||||
|
||||
|
||||
class JLinkAccessFlags(object):
|
||||
__doc__ = 'J-Link access types for data events.\n\n These access types allow specifying the different types of access events\n that should be monitored.\n\n Attributes:\n READ: specifies to monitor read accesses.\n WRITE: specifies to monitor write accesses.\n PRIVILEGED: specifies to monitor privileged accesses.\n SIZE_8BIT: specifies to monitor an 8-bit access width.\n SIZE_16BIT: specifies to monitor an 16-bit access width.\n SIZE_32BIT: specifies to monitor an 32-bit access width.\n '
|
||||
READ = 0
|
||||
WRITE = 1
|
||||
PRIV = 16
|
||||
SIZE_8BIT = 0
|
||||
SIZE_16BIT = 2
|
||||
SIZE_32BIT = 4
|
||||
|
||||
|
||||
class JLinkAccessMaskFlags(object):
|
||||
__doc__ = 'J-Link access mask flags.\n\n Attributes:\n SIZE: specifies to not care about the access size of the event.\n DIR: specifies to not care about the access direction of the event.\n PRIV: specifies to not care about the access privilege of the event.\n '
|
||||
SIZE = 6
|
||||
DIR = 1
|
||||
PRIV = 16
|
||||
|
||||
|
||||
class JLinkStraceCommand(object):
|
||||
__doc__ = 'STRACE commmands.'
|
||||
TRACE_EVENT_SET = 0
|
||||
TRACE_EVENT_CLR = 1
|
||||
TRACE_EVENT_CLR_ALL = 2
|
||||
SET_BUFFER_SIZE = 3
|
||||
|
||||
|
||||
class JLinkStraceEvent(object):
|
||||
__doc__ = 'STRACE events.'
|
||||
CODE_FETCH = 0
|
||||
DATA_ACCESS = 1
|
||||
DATA_LOAD = 2
|
||||
DATA_STORE = 3
|
||||
|
||||
|
||||
class JLinkStraceOperation(object):
|
||||
__doc__ = 'STRACE operation specifiers.'
|
||||
TRACE_START = 0
|
||||
TRACE_STOP = 1
|
||||
TRACE_INCLUDE_RANGE = 2
|
||||
TRACE_EXCLUDE_RANGE = 3
|
||||
|
||||
|
||||
class JLinkTraceSource(object):
|
||||
__doc__ = 'Sources for tracing.'
|
||||
ETB = 0
|
||||
ETM = 1
|
||||
MTB = 2
|
||||
|
||||
|
||||
class JLinkTraceCommand(object):
|
||||
__doc__ = 'J-Link trace commands.'
|
||||
START = 0
|
||||
STOP = 1
|
||||
FLUSH = 2
|
||||
GET_NUM_SAMPLES = 16
|
||||
GET_CONF_CAPACITY = 17
|
||||
SET_CAPACITY = 18
|
||||
GET_MIN_CAPACITY = 19
|
||||
GET_MAX_CAPACITY = 20
|
||||
SET_FORMAT = 32
|
||||
GET_FORMAT = 33
|
||||
GET_NUM_REGIONS = 48
|
||||
GET_REGION_PROPS = 49
|
||||
GET_REGION_PROPS_EX = 50
|
||||
|
||||
|
||||
class JLinkTraceFormat(object):
|
||||
__doc__ = 'J-Link trace formats.\n\n Attributes:\n FORMAT_4BIT: 4-bit data.\n FORMAT_8BIT: 8-bit data.\n FORMAT_16BIT: 16-bit data.\n FORMAT_MULTIPLEXED: multiplexing on ETM / buffer link.\n FORMAT_DEMULTIPLEXED: de-multiplexing on ETM / buffer link.\n FORMAT_DOUBLE_EDGE: clock data on both ETM / buffer link edges.\n FORMAT_ETM7_9: ETM7/ETM9 protocol.\n FORMAT_ETM10: ETM10 protocol.\n FORMAT_1BIT: 1-bit data.\n FORMAT_2BIT: 2-bit data.\n '
|
||||
FORMAT_4BIT = 1
|
||||
FORMAT_8BIT = 2
|
||||
FORMAT_16BIT = 4
|
||||
FORMAT_MULTIPLEXED = 8
|
||||
FORMAT_DEMULTIPLEXED = 16
|
||||
FORMAT_DOUBLE_EDGE = 32
|
||||
FORMAT_ETM7_9 = 64
|
||||
FORMAT_ETM10 = 128
|
||||
FORMAT_1BIT = 256
|
||||
FORMAT_2BIT = 512
|
||||
|
||||
|
||||
class JLinkROMTable(object):
|
||||
__doc__ = 'The J-Link ROM tables.'
|
||||
NONE = 256
|
||||
ETM = 257
|
||||
MTB = 258
|
||||
TPIU = 259
|
||||
ITM = 260
|
||||
DWT = 261
|
||||
FPB = 262
|
||||
NVIC = 263
|
||||
TMC = 264
|
||||
TF = 265
|
||||
PTM = 266
|
||||
ETB = 267
|
||||
DBG = 268
|
||||
APBAP = 269
|
||||
AHBAP = 270
|
||||
SECURE = 271
|
||||
|
||||
|
||||
class JLinkRTTCommand(object):
|
||||
__doc__ = 'RTT commands.'
|
||||
START = 0
|
||||
STOP = 1
|
||||
GETDESC = 2
|
||||
GETNUMBUF = 3
|
||||
GETSTAT = 4
|
||||
|
||||
|
||||
class JLinkRTTDirection(object):
|
||||
__doc__ = 'RTT Direction.'
|
||||
UP = 0
|
||||
DOWN = 1
|
||||
# okay decompiling ./pylink/enums.pyc
|
44
pylink/errors.py
Normal file
44
pylink/errors.py
Normal file
|
@ -0,0 +1,44 @@
|
|||
# decompyle3 version 3.9.0
|
||||
# Python bytecode version base 3.7.0 (3394)
|
||||
# Decompiled from: Python 3.7.16 (default, Mar 30 2023, 01:25:49)
|
||||
# [GCC 12.2.1 20220924]
|
||||
# Embedded file name: pylink/errors.py
|
||||
from . import enums
|
||||
from . import util
|
||||
|
||||
class JLinkException(enums.JLinkGlobalErrors, Exception):
|
||||
__doc__ = 'Generic J-Link exception.'
|
||||
|
||||
def __init__(self, code):
|
||||
message = code
|
||||
self.code = None
|
||||
if util.is_integer(code):
|
||||
message = self.to_string(code)
|
||||
self.code = code
|
||||
super(JLinkException, self).__init__(message)
|
||||
self.message = message
|
||||
|
||||
|
||||
class JLinkEraseException(enums.JLinkEraseErrors, JLinkException):
|
||||
__doc__ = 'J-Link erase exception.'
|
||||
|
||||
|
||||
class JLinkFlashException(enums.JLinkFlashErrors, JLinkException):
|
||||
__doc__ = 'J-Link flash exception.'
|
||||
|
||||
|
||||
class JLinkWriteException(enums.JLinkWriteErrors, JLinkException):
|
||||
__doc__ = 'J-Link write exception.'
|
||||
|
||||
|
||||
class JLinkReadException(enums.JLinkReadErrors, JLinkException):
|
||||
__doc__ = 'J-Link read exception.'
|
||||
|
||||
|
||||
class JLinkDataException(enums.JLinkDataErrors, JLinkException):
|
||||
__doc__ = 'J-Link data event exception.'
|
||||
|
||||
|
||||
class JLinkRTTException(enums.JLinkRTTErrors, JLinkException):
|
||||
__doc__ = 'J-Link RTT exception.'
|
||||
# okay decompiling ./pylink/errors.pyc
|
4629
pylink/jlink.py
Normal file
4629
pylink/jlink.py
Normal file
File diff suppressed because it is too large
Load Diff
114
pylink/jlock.py
Normal file
114
pylink/jlock.py
Normal file
|
@ -0,0 +1,114 @@
|
|||
# decompyle3 version 3.9.0
|
||||
# Python bytecode version base 3.7.0 (3394)
|
||||
# Decompiled from: Python 3.7.16 (default, Mar 30 2023, 01:25:49)
|
||||
# [GCC 12.2.1 20220924]
|
||||
# Embedded file name: pylink/jlock.py
|
||||
import psutil, errno, tempfile, os
|
||||
|
||||
class JLock(object):
|
||||
__doc__ = 'Lockfile for accessing a particular J-Link.\n\n The J-Link SDK does not prevent accessing the same J-Link multiple times\n from the same process or multiple processes. As a result, a user can\n have the same J-Link being accessed by multiple processes. This class\n provides an interface to a lock-file like structure for the physical\n J-Links to ensure that any instance of a ``JLink`` with an open emulator\n connection will be the only one accessing that emulator.\n\n This class uses a PID-style lockfile to allow acquiring of the lockfile in\n the instances where the lockfile exists, but the process which created it\n is no longer running.\n\n To share the same emulator connection between multiple threads, processes,\n or functions, a single instance of a ``JLink`` should be created and passed\n between the threads and processes.\n\n Attributes:\n name: the name of the lockfile.\n path: full path to the lockfile.\n fd: file description of the lockfile.\n acquired: boolean indicating if the lockfile lock has been acquired.\n '
|
||||
SERIAL_NAME_FMT = '.pylink-usb-{}.lck'
|
||||
IPADDR_NAME_FMT = '.pylink-ip-{}.lck'
|
||||
|
||||
def __init__(self, serial_no):
|
||||
"""Creates an instance of a ``JLock`` and populates the name.
|
||||
|
||||
Note:
|
||||
This method may fail if there is no temporary directory in which to
|
||||
have the lockfile placed.
|
||||
|
||||
Args:
|
||||
self (JLock): the ``JLock`` instance
|
||||
serial_no (int): the serial number of the J-Link
|
||||
|
||||
Returns:
|
||||
``None``
|
||||
"""
|
||||
self.name = self.SERIAL_NAME_FMT.format(serial_no)
|
||||
self.acquired = False
|
||||
self.fd = None
|
||||
self.path = None
|
||||
self.path = os.path.join(tempfile.tempdir, self.name)
|
||||
|
||||
def __del__(self):
|
||||
"""Cleans up the lockfile instance if it was acquired.
|
||||
|
||||
Args:
|
||||
self (JLock): the ``JLock`` instance
|
||||
|
||||
Returns:
|
||||
``None``
|
||||
"""
|
||||
self.release()
|
||||
|
||||
def acquire(self):
|
||||
"""Attempts to acquire a lock for the J-Link lockfile.
|
||||
|
||||
If the lockfile exists but does not correspond to an active process,
|
||||
the lockfile is first removed, before an attempt is made to acquire it.
|
||||
|
||||
Args:
|
||||
self (Jlock): the ``JLock`` instance
|
||||
|
||||
Returns:
|
||||
``True`` if the lock was acquired, otherwise ``False``.
|
||||
|
||||
Raises:
|
||||
OSError: on file errors.
|
||||
"""
|
||||
if os.path.exists(self.path):
|
||||
try:
|
||||
pid = None
|
||||
with open(self.path, 'r') as f:
|
||||
line = f.readline().strip()
|
||||
pid = int(line)
|
||||
if not psutil.pid_exists(pid):
|
||||
os.remove(self.path)
|
||||
except ValueError as e:
|
||||
try:
|
||||
os.remove(self.path)
|
||||
finally:
|
||||
e = None
|
||||
del e
|
||||
|
||||
except IOError as e:
|
||||
try:
|
||||
pass
|
||||
finally:
|
||||
e = None
|
||||
del e
|
||||
|
||||
try:
|
||||
self.fd = os.open(self.path, os.O_CREAT | os.O_EXCL | os.O_RDWR)
|
||||
to_write = '%s%s' % (os.getpid(), os.linesep)
|
||||
os.write(self.fd, to_write.encode())
|
||||
except OSError as e:
|
||||
try:
|
||||
if not os.path.exists(self.path):
|
||||
raise
|
||||
return False
|
||||
finally:
|
||||
e = None
|
||||
del e
|
||||
|
||||
self.acquired = True
|
||||
return True
|
||||
|
||||
def release(self):
|
||||
"""Cleans up the lockfile if it was acquired.
|
||||
|
||||
Args:
|
||||
self (JLock): the ``JLock`` instance
|
||||
|
||||
Returns:
|
||||
``False`` if the lock was not released or the lock is not acquired,
|
||||
otherwise ``True``.
|
||||
"""
|
||||
if not self.acquired:
|
||||
return False
|
||||
os.close(self.fd)
|
||||
if os.path.exists(self.path):
|
||||
os.remove(self.path)
|
||||
self.acquired = False
|
||||
return True
|
||||
# okay decompiling ./pylink/jlock.pyc
|
346
pylink/library.py
Normal file
346
pylink/library.py
Normal file
|
@ -0,0 +1,346 @@
|
|||
# decompyle3 version 3.9.0
|
||||
# Python bytecode version base 3.7.0 (3394)
|
||||
# Decompiled from: Python 3.7.16 (default, Mar 30 2023, 01:25:49)
|
||||
# [GCC 12.2.1 20220924]
|
||||
# Embedded file name: pylink/library.py
|
||||
from . import util
|
||||
import ctypes
|
||||
import ctypes.util as ctypes_util
|
||||
import os, sys, tempfile
|
||||
|
||||
class Library(object):
|
||||
__doc__ = 'Wrapper to provide easy access to loading the J-Link SDK DLL.\n\n This class provides a convenience for finding and loading the J-Link DLL\n across multiple platforms, and accounting for the inconsistencies between\n Windows and nix-based platforms.\n\n Attributes:\n _standard_calls_: list of names of the methods for the API calls that\n must be converted to standard calling convention on the Windows\n platform.\n JLINK_SDK_NAME: name of the J-Link DLL on nix-based platforms.\n WINDOWS_JLINK_SDK_NAME: name of the J-Link DLL on Windows platforms.\n '
|
||||
_standard_calls_ = [
|
||||
'JLINK_Configure',
|
||||
'JLINK_DownloadFile',
|
||||
'JLINK_GetAvailableLicense',
|
||||
'JLINK_GetPCode',
|
||||
'JLINK_PrintConfig',
|
||||
'JLINK_EraseChip',
|
||||
'JLINK_SPI_Transfer',
|
||||
'JLINK_GetpFunc',
|
||||
'JLINK_GetMemZones',
|
||||
'JLINK_ReadMemZonedEx',
|
||||
'JLINK_SetHookUnsecureDialog',
|
||||
'JLINK_WriteMemZonedEx',
|
||||
'JLINK_DIALOG_Configure',
|
||||
'JLINK_DIALOG_ConfigureEx',
|
||||
'JLINK_EMU_GPIO_GetProps',
|
||||
'JLINK_EMU_GPIO_GetState',
|
||||
'JLINK_EMU_GPIO_SetState',
|
||||
'JLINK_EMU_AddLicense',
|
||||
'JLINK_EMU_EraseLicenses',
|
||||
'JLINK_EMU_GetLicenses',
|
||||
'JLINK_HSS_GetCaps',
|
||||
'JLINK_HSS_Start',
|
||||
'JLINK_HSS_Stop',
|
||||
'JLINK_HSS_Read',
|
||||
'JLINK_POWERTRACE_Control',
|
||||
'JLINK_POWERTRACE_Read',
|
||||
'JLINK_RTTERMINAL_Control',
|
||||
'JLINK_RTTERMINAL_Read',
|
||||
'JLINK_RTTERMINAL_Write',
|
||||
'JLINK_STRACE_Config',
|
||||
'JLINK_STRACE_Control',
|
||||
'JLINK_STRACE_Read',
|
||||
'JLINK_STRACE_Start',
|
||||
'JLINK_STRACE_Stop',
|
||||
'JLINK_SWD_GetData',
|
||||
'JLINK_SWD_GetU8',
|
||||
'JLINK_SWD_GetU16',
|
||||
'JLINK_SWD_GetU32',
|
||||
'JLINK_SWD_StoreGetRaw',
|
||||
'JLINK_SWD_StoreRaw',
|
||||
'JLINK_SWD_SyncBits',
|
||||
'JLINK_SWD_SyncBytes',
|
||||
'JLINK_SetFlashProgProgressCallback']
|
||||
JLINK_SDK_NAME = 'libjlinkarm'
|
||||
WINDOWS_32_JLINK_SDK_NAME = 'JLinkARM'
|
||||
WINDOWS_64_JLINK_SDK_NAME = 'JLink_x64'
|
||||
|
||||
@classmethod
|
||||
def get_appropriate_windows_sdk_name(cls):
|
||||
"""Returns the appropriate JLink SDK library name on Windows depending
|
||||
on 32bit or 64bit Python variant.
|
||||
|
||||
SEGGER delivers two variants of their dynamic library on Windows:
|
||||
- ``JLinkARM.dll`` for 32-bit platform
|
||||
- ``JLink_x64.dll`` for 64-bit platform
|
||||
|
||||
Args:
|
||||
cls (Library): the ``Library`` class
|
||||
|
||||
Returns:
|
||||
The name of the library depending on the platform this module is run on.
|
||||
|
||||
"""
|
||||
if sys.maxsize == 9223372036854775807:
|
||||
return Library.WINDOWS_64_JLINK_SDK_NAME
|
||||
return Library.WINDOWS_32_JLINK_SDK_NAME
|
||||
|
||||
@classmethod
|
||||
def find_library_windows(cls):
|
||||
r"""Loads the SEGGER DLL from the windows installation directory.
|
||||
|
||||
On Windows, these are found either under:
|
||||
- ``C:\Program Files\SEGGER\JLink``
|
||||
- ``C:\Program Files (x86)\SEGGER\JLink``.
|
||||
|
||||
Args:
|
||||
cls (Library): the ``Library`` class
|
||||
|
||||
Returns:
|
||||
The paths to the J-Link library files in the order that they are
|
||||
found.
|
||||
"""
|
||||
dll = cls.get_appropriate_windows_sdk_name() + '.dll'
|
||||
root = 'C:\\'
|
||||
for d in os.listdir(root):
|
||||
dir_path = os.path.join(root, d)
|
||||
if d.startswith('Program Files'):
|
||||
if os.path.isdir(dir_path):
|
||||
dir_path = os.path.join(dir_path, 'SEGGER')
|
||||
if not os.path.isdir(dir_path):
|
||||
continue
|
||||
else:
|
||||
ds = filter(lambda x: x.startswith('JLink')
|
||||
, os.listdir(dir_path))
|
||||
for jlink_dir in ds:
|
||||
lib_path = os.path.join(dir_path, jlink_dir, dll)
|
||||
if os.path.isfile(lib_path):
|
||||
yield lib_path
|
||||
|
||||
@classmethod
|
||||
def find_library_linux(cls):
|
||||
"""Loads the SEGGER DLL from the root directory.
|
||||
|
||||
On Linux, the SEGGER tools are installed under the ``/opt/SEGGER``
|
||||
directory with versioned directories having the suffix ``_VERSION``.
|
||||
|
||||
Args:
|
||||
cls (Library): the ``Library`` class
|
||||
|
||||
Returns:
|
||||
The paths to the J-Link library files in the order that they are
|
||||
found.
|
||||
"""
|
||||
dll = Library.JLINK_SDK_NAME
|
||||
root = os.path.join('/', 'opt', 'SEGGER')
|
||||
for directory_name, subdirs, files in os.walk(root):
|
||||
fnames = []
|
||||
x86_found = False
|
||||
for f in files:
|
||||
path = os.path.join(directory_name, f)
|
||||
if os.path.isfile(path):
|
||||
if f.startswith(dll):
|
||||
fnames.append(f)
|
||||
if '_x86' in path:
|
||||
x86_found = True
|
||||
|
||||
for fname in fnames:
|
||||
fpath = os.path.join(directory_name, fname)
|
||||
if util.is_os_64bit():
|
||||
if '_x86' not in fname:
|
||||
yield fpath
|
||||
else:
|
||||
if x86_found:
|
||||
if '_x86' in fname:
|
||||
yield fpath
|
||||
else:
|
||||
yield fpath
|
||||
|
||||
@classmethod
|
||||
def find_library_darwin(cls):
|
||||
r"""Loads the SEGGER DLL from the installed applications.
|
||||
|
||||
This method accounts for the all the different ways in which the DLL
|
||||
may be installed depending on the version of the DLL. Always uses
|
||||
the first directory found.
|
||||
|
||||
SEGGER's DLL is installed in one of three ways dependent on which
|
||||
which version of the SEGGER tools are installed:
|
||||
|
||||
======== ============================================================
|
||||
Versions Directory
|
||||
======== ============================================================
|
||||
< 5.0.0 ``/Applications/SEGGER/JLink\ NUMBER``
|
||||
< 6.0.0 ``/Applications/SEGGER/JLink/libjlinkarm.major.minor.dylib``
|
||||
>= 6.0.0 ``/Applications/SEGGER/JLink/libjlinkarm``
|
||||
======== ============================================================
|
||||
|
||||
Args:
|
||||
cls (Library): the ``Library`` class
|
||||
|
||||
Returns:
|
||||
The path to the J-Link library files in the order they are found.
|
||||
"""
|
||||
dll = Library.JLINK_SDK_NAME
|
||||
root = os.path.join('/', 'Applications', 'SEGGER')
|
||||
if not os.path.isdir(root):
|
||||
return
|
||||
for d in os.listdir(root):
|
||||
dir_path = os.path.join(root, d)
|
||||
if os.path.isdir(dir_path):
|
||||
if d.startswith('JLink'):
|
||||
files = list((f for f in os.listdir(dir_path) if os.path.isfile(os.path.join(dir_path, f))))
|
||||
if dll + '.dylib' in files:
|
||||
yield os.path.join(dir_path, dll + '.dylib')
|
||||
else:
|
||||
for f in files:
|
||||
if f.startswith(dll):
|
||||
yield os.path.join(dir_path, f)
|
||||
|
||||
def __init__(self, dllpath=None):
|
||||
"""Initializes an instance of a ``Library``.
|
||||
|
||||
Loads the default J-Link DLL if ``dllpath`` is ``None``, otherwise
|
||||
loads the DLL specified by the given ``dllpath``.
|
||||
|
||||
Args:
|
||||
self (Library): the ``Library`` instance
|
||||
dllpath (str): the DLL to load into the library
|
||||
|
||||
Returns:
|
||||
``None``
|
||||
"""
|
||||
self._lib = None
|
||||
self._winlib = None
|
||||
self._path = None
|
||||
self._windows = sys.platform.startswith('win')
|
||||
self._cygwin = sys.platform.startswith('cygwin')
|
||||
self._temp = None
|
||||
if self._windows or self._cygwin:
|
||||
self._sdk = self.get_appropriate_windows_sdk_name()
|
||||
else:
|
||||
self._sdk = self.JLINK_SDK_NAME
|
||||
if dllpath is not None:
|
||||
self.load(dllpath)
|
||||
else:
|
||||
self.load_default()
|
||||
|
||||
def __del__(self):
|
||||
"""Cleans up the temporary DLL file created when the lib was loaded.
|
||||
|
||||
Args:
|
||||
self (Library): the ``Library`` instance
|
||||
|
||||
Returns:
|
||||
``None``
|
||||
"""
|
||||
self.unload()
|
||||
|
||||
def load_default(self):
|
||||
"""Loads the default J-Link SDK DLL.
|
||||
|
||||
The default J-Link SDK is determined by first checking if ``ctypes``
|
||||
can find the DLL, then by searching the platform-specific paths.
|
||||
|
||||
Args:
|
||||
self (Library): the ``Library`` instance
|
||||
|
||||
Returns:
|
||||
``True`` if the DLL was loaded, otherwise ``False``.
|
||||
"""
|
||||
path = ctypes_util.find_library(self._sdk)
|
||||
if not path is None or self._windows or self._cygwin:
|
||||
path = next(self.find_library_windows(), None)
|
||||
else:
|
||||
if sys.platform.startswith('linux'):
|
||||
path = next(self.find_library_linux(), None)
|
||||
else:
|
||||
if sys.platform.startswith('darwin'):
|
||||
path = next(self.find_library_darwin(), None)
|
||||
if path is not None:
|
||||
return self.load(path)
|
||||
return False
|
||||
|
||||
def load(self, path=None):
|
||||
"""Loads the specified DLL, if any, otherwise re-loads the current DLL.
|
||||
|
||||
If ``path`` is specified, loads the DLL at the given ``path``,
|
||||
otherwise re-loads the DLL currently specified by this library.
|
||||
|
||||
Note:
|
||||
This creates a temporary DLL file to use for the instance. This is
|
||||
necessary to work around a limitation of the J-Link DLL in which
|
||||
multiple J-Links cannot be accessed from the same process.
|
||||
|
||||
Args:
|
||||
self (Library): the ``Library`` instance
|
||||
path (path): path to the DLL to load
|
||||
|
||||
Returns:
|
||||
``True`` if library was loaded successfully.
|
||||
|
||||
Raises:
|
||||
OSError: if there is no J-LINK SDK DLL present at the path.
|
||||
|
||||
See Also:
|
||||
`J-Link Multi-session <http://forum.segger.com/index.php?page=Thread&threadID=669>`_.
|
||||
"""
|
||||
self.unload()
|
||||
self._path = path or self._path
|
||||
if self._windows or self._cygwin:
|
||||
suffix = '.dll'
|
||||
else:
|
||||
if sys.platform.startswith('darwin'):
|
||||
suffix = '.dylib'
|
||||
else:
|
||||
suffix = '.so'
|
||||
tf = tempfile.NamedTemporaryFile(delete=False, suffix=suffix)
|
||||
with open(tf.name, 'wb') as outputfile:
|
||||
with open(self._path, 'rb') as inputfile:
|
||||
outputfile.write(inputfile.read())
|
||||
tf.close()
|
||||
self._temp = tf
|
||||
self._lib = ctypes.cdll.LoadLibrary(tf.name)
|
||||
if self._windows:
|
||||
self._winlib = ctypes.windll.LoadLibrary(tf.name)
|
||||
for stdcall in self._standard_calls_:
|
||||
if hasattr(self._winlib, stdcall):
|
||||
setattr(self._lib, stdcall, getattr(self._winlib, stdcall))
|
||||
|
||||
return True
|
||||
|
||||
def unload(self):
|
||||
"""Unloads the library's DLL if it has been loaded.
|
||||
|
||||
This additionally cleans up the temporary DLL file that was created
|
||||
when the library was loaded.
|
||||
|
||||
Args:
|
||||
self (Library): the ``Library`` instance
|
||||
|
||||
Returns:
|
||||
``True`` if the DLL was unloaded, otherwise ``False``.
|
||||
"""
|
||||
unloaded = False
|
||||
if self._lib is not None:
|
||||
if self._winlib is not None:
|
||||
ctypes.windll.kernel32.FreeLibrary.argtypes = (
|
||||
ctypes.c_void_p,)
|
||||
ctypes.windll.kernel32.FreeLibrary(self._lib._handle)
|
||||
ctypes.windll.kernel32.FreeLibrary(self._winlib._handle)
|
||||
self._lib = None
|
||||
self._winlib = None
|
||||
unloaded = True
|
||||
else:
|
||||
del self._lib
|
||||
self._lib = None
|
||||
unloaded = True
|
||||
if self._temp is not None:
|
||||
os.remove(self._temp.name)
|
||||
self._temp = None
|
||||
return unloaded
|
||||
|
||||
def dll(self):
|
||||
"""Returns the DLL for the underlying shared library.
|
||||
|
||||
Args:
|
||||
self (Library): the ``Library`` instance
|
||||
|
||||
Returns:
|
||||
A ``ctypes`` DLL instance if one was loaded, otherwise ``None``.
|
||||
"""
|
||||
return self._lib
|
||||
# okay decompiling ./pylink/library.pyc
|
206
pylink/registers.py
Normal file
206
pylink/registers.py
Normal file
|
@ -0,0 +1,206 @@
|
|||
# decompyle3 version 3.9.0
|
||||
# Python bytecode version base 3.7.0 (3394)
|
||||
# Decompiled from: Python 3.7.16 (default, Mar 30 2023, 01:25:49)
|
||||
# [GCC 12.2.1 20220924]
|
||||
# Embedded file name: pylink/registers.py
|
||||
import ctypes
|
||||
|
||||
class IDCodeRegisterBits(ctypes.LittleEndianStructure):
|
||||
__doc__ = 'This class holds the different bit masks for the IDCode register.\n\n Attributes:\n valid: validity bit, should always be ``0``.\n manufactuer: the JEDEC Manufacturer ID.\n part_no: the part number defined by the manufacturer.\n version_code: the version code.\n '
|
||||
_fields_ = [
|
||||
(
|
||||
'valid', ctypes.c_uint32, 1),
|
||||
(
|
||||
'manufacturer', ctypes.c_uint32, 11),
|
||||
(
|
||||
'part_no', ctypes.c_uint32, 16),
|
||||
(
|
||||
'version_code', ctypes.c_uint32, 4)]
|
||||
|
||||
|
||||
class IDCodeRegisterFlags(ctypes.Union):
|
||||
__doc__ = 'Mask for the IDCode register bits.\n\n Attributes:\n value: the value stored in the mask.\n '
|
||||
_anonymous_ = ('bit', )
|
||||
_fields_ = [
|
||||
(
|
||||
'bit', IDCodeRegisterBits),
|
||||
(
|
||||
'value', ctypes.c_uint32)]
|
||||
|
||||
|
||||
class AbortRegisterBits(ctypes.LittleEndianStructure):
|
||||
__doc__ = 'This class holds the different bit mask for the Abort Register.\n\n Attributes:\n DAPABORT: write ``1`` to trigger a DAP abort.\n STKCMPCLR: write ``1`` to clear the ``STICKYCMP`` sticky compare flag\n (only supported on SW-DP).\n STKERRCLR: write ``1`` to clear the ``STICKYERR`` sticky error flag\n (only supported on SW-DP).\n WDERRCLR: write ``1`` to clear the ``WDATAERR`` write data error flag\n (only supported on SW-DP).\n ORUNERRCLR: write ``1`` to clear the ``STICKYORUN`` overrun error flag\n (only supported on SW-DP).\n '
|
||||
_fields_ = [
|
||||
(
|
||||
'DAPABORT', ctypes.c_uint32, 1),
|
||||
(
|
||||
'STKCMPCLR', ctypes.c_uint32, 1),
|
||||
(
|
||||
'STKERRCLR', ctypes.c_uint32, 1),
|
||||
(
|
||||
'WDERRCLR', ctypes.c_uint32, 1),
|
||||
(
|
||||
'ORUNERRCLR', ctypes.c_uint32, 1),
|
||||
(
|
||||
'RESERVED', ctypes.c_uint32, 27)]
|
||||
|
||||
|
||||
class AbortRegisterFlags(ctypes.Union):
|
||||
__doc__ = 'Mask for the abort register bits.\n\n Attributes:\n value: the value stored in the mask.\n '
|
||||
_anonymous_ = ('bit', )
|
||||
_fields_ = [
|
||||
(
|
||||
'bit', AbortRegisterBits),
|
||||
(
|
||||
'value', ctypes.c_uint32)]
|
||||
|
||||
|
||||
class ControlStatusRegisterBits(ctypes.LittleEndianStructure):
|
||||
__doc__ = 'This class holds the different bit masks for the DP Control / Status\n Register bit assignments.\n\n Attributes:\n ORUNDETECT: if set, enables overrun detection.\n STICKYORUN: if overrun is enabled, is set when overrun occurs.\n TRNMODE: transfer mode for acess port operations.\n STICKYCMP: is set when a match occurs on a pushed compare or verify\n operation.\n STICKYERR: is set when an error is returned by an access port\n transaction.\n READOK: is set when the response to a previous access port or ``RDBUFF``\n was ``OK``.\n WDATAERR: set to ``1`` if a Write Data Error occurs.\n MASKLANE: bytes to be masked in pushed compare and verify operations.\n TRNCNT: transaction counter.\n RESERVED: reserved.\n CDBGRSTREQ: debug reset request.\n CDBGRSTACK: debug reset acknowledge.\n CDBGPWRUPREQ: debug power-up request.\n CDBGPWRUPACK: debug power-up acknowledge.\n CSYSPWRUPREQ: system power-up request\n CSYSPWRUPACK: system power-up acknowledge.\n\n See also:\n See the ARM documentation on the significance of these masks\n `here <http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ihi0031c/index.html>`_.\n '
|
||||
_fields_ = [
|
||||
(
|
||||
'ORUNDETECT', ctypes.c_uint32, 1),
|
||||
(
|
||||
'STICKYORUN', ctypes.c_uint32, 1),
|
||||
(
|
||||
'TRNMODE', ctypes.c_uint32, 2),
|
||||
(
|
||||
'STICKYCMP', ctypes.c_uint32, 1),
|
||||
(
|
||||
'STICKYERR', ctypes.c_uint32, 1),
|
||||
(
|
||||
'READOK', ctypes.c_uint32, 1),
|
||||
(
|
||||
'WDATAERR', ctypes.c_uint32, 1),
|
||||
(
|
||||
'MASKLANE', ctypes.c_uint32, 4),
|
||||
(
|
||||
'TRNCNT', ctypes.c_uint32, 12),
|
||||
(
|
||||
'RESERVED', ctypes.c_uint32, 2),
|
||||
(
|
||||
'CDBGRSTREQ', ctypes.c_uint32, 1),
|
||||
(
|
||||
'CDBGRSTACK', ctypes.c_uint32, 1),
|
||||
(
|
||||
'CDBGPWRUPREQ', ctypes.c_uint32, 1),
|
||||
(
|
||||
'CDBGPWRUPACK', ctypes.c_uint32, 1),
|
||||
(
|
||||
'CSYSPWRUPREQ', ctypes.c_uint32, 1),
|
||||
(
|
||||
'CSYSPWRUPACK', ctypes.c_uint32, 1)]
|
||||
|
||||
|
||||
class ControlStatusRegisterFlags(ctypes.Union):
|
||||
__doc__ = 'Mask for the control/status register bits.\n\n Attributes:\n value: the value stored in the mask.\n '
|
||||
_anonymous_ = ('bit', )
|
||||
_fields_ = [
|
||||
(
|
||||
'bit', ControlStatusRegisterBits),
|
||||
(
|
||||
'value', ctypes.c_uint32)]
|
||||
|
||||
|
||||
class SelectRegisterBits(ctypes.LittleEndianStructure):
|
||||
__doc__ = 'This class holds the different bit masks for the AP Select Register.\n\n Attributes:\n CTRLSEL: SW-DP debug port address bank select.\n RESERVED_A: reserved.\n APBANKSEL: selects the active four-word register window on the current\n access port.\n RESERVED_B: reserved.\n APSEL: selects the current access port.\n '
|
||||
_fields_ = [
|
||||
(
|
||||
'CTRLSEL', ctypes.c_uint32, 1),
|
||||
(
|
||||
'RESERVED_A', ctypes.c_uint32, 3),
|
||||
(
|
||||
'APBANKSEL', ctypes.c_uint32, 4),
|
||||
(
|
||||
'RESERVED_B', ctypes.c_uint32, 16),
|
||||
(
|
||||
'APSEL', ctypes.c_uint32, 8)]
|
||||
|
||||
|
||||
class SelectRegisterFlags(ctypes.Union):
|
||||
__doc__ = 'Mask for the select register bits.\n\n Attributes:\n value: the value stored in the mask.\n '
|
||||
_anonymous_ = ('bit', )
|
||||
_fields_ = [
|
||||
(
|
||||
'bit', SelectRegisterBits),
|
||||
(
|
||||
'value', ctypes.c_uint32)]
|
||||
|
||||
|
||||
class MDMAPControlRegisterBits(ctypes.LittleEndianStructure):
|
||||
__doc__ = 'This class holds the different bit masks for the MDM-AP Control\n Register.\n\n Attributes:\n flash_mass_erase: set to cause a mass erase, this is cleared\n automatically when a mass erase finishes.\n debug_disable: set to disable debug, clear to allow debug.\n debug_request: set to force the core to halt.\n sys_reset_request: set to force a system reset.\n core_hold_reset: set to suspend the core in reset at the end of reset\n sequencing.\n VLLDBGREQ: set to hold the system in reset after the next recovery from\n VLLSx (Very Low Leakage Stop).\n VLLDBGACK: set to release a system held in reset following a VLLSx\n (Very Low Leakage Stop) recovery.\n VLLSTATACK: set to acknowledge that the DAP LLS (Low Leakage Stop) and\n VLLS (Very Low Leakage Stop) status bits have read.\n '
|
||||
_fields_ = [
|
||||
(
|
||||
'flash_mass_erase', ctypes.c_uint8, 1),
|
||||
(
|
||||
'debug_disable', ctypes.c_uint8, 1),
|
||||
(
|
||||
'debug_request', ctypes.c_uint8, 1),
|
||||
(
|
||||
'sys_reset_request', ctypes.c_uint8, 1),
|
||||
(
|
||||
'core_hold_reset', ctypes.c_uint8, 1),
|
||||
(
|
||||
'VLLDBGREQ', ctypes.c_uint8, 1),
|
||||
(
|
||||
'VLLDBGACK', ctypes.c_uint8, 1),
|
||||
(
|
||||
'VLLSTATACK', ctypes.c_uint8, 1)]
|
||||
|
||||
|
||||
class MDMAPControlRegisterFlags(ctypes.Union):
|
||||
__doc__ = 'Mask for the MDM-AP control register bits.\n\n Attributes:\n value: the value stored in the mask.\n '
|
||||
_anonymous_ = ('bit', )
|
||||
_fields_ = [
|
||||
(
|
||||
'bit', MDMAPControlRegisterBits),
|
||||
(
|
||||
'value', ctypes.c_uint8)]
|
||||
|
||||
|
||||
class MDMAPStatusRegisterBits(ctypes.LittleEndianStructure):
|
||||
__doc__ = 'Holds the bit masks for the MDM-AP Status Register.\n\n Attributes:\n flash_mass_erase_ack: cleared after a system reset, indicates that a\n flash mass erase was acknowledged.\n flash_ready: indicates that flash has been initialized and can be\n configured.\n system_security: if set, system is secure and debugger cannot access the\n memory or system bus.\n system_reset: ``1`` if system is in reset, otherwise ``0``.\n mass_erase_enabled: ``1`` if MCU can be mass erased, otherwise ``0``.\n low_power_enabled: ``1`` if low power stop mode is enabled, otherwise ``0``.\n very_low_power_mode: ``1`` if device is in very low power mode.\n LLSMODEEXIT: indicates an exit from LLS mode has occurred.\n VLLSxMODEEXIT: indicates an exit from VLLSx mode has occured.\n core_halted; indicates core has entered debug halt mode.\n core_deep_sleep: indicates core has entered a low power mode.\n core_sleeping: indicates the core has entered a low power mode.\n\n Note:\n if ``core_sleeping & !core_deep_sleep``, then the core is in VLPW (very\n low power wait) mode, otherwise if ``core_sleeping & core_deep_sleep``,\n then it is in VLPS (very low power stop) mode.\n '
|
||||
_fields_ = [
|
||||
(
|
||||
'flash_mass_erase_ack', ctypes.c_uint32, 1),
|
||||
(
|
||||
'flash_ready', ctypes.c_uint32, 1),
|
||||
(
|
||||
'system_security', ctypes.c_uint32, 1),
|
||||
(
|
||||
'system_reset', ctypes.c_uint32, 1),
|
||||
(
|
||||
'RESERVED_A', ctypes.c_uint32, 1),
|
||||
(
|
||||
'mass_erase_enabled', ctypes.c_uint32, 1),
|
||||
(
|
||||
'backdoor_access_enabled', ctypes.c_uint32, 1),
|
||||
(
|
||||
'low_power_enabled', ctypes.c_uint32, 1),
|
||||
(
|
||||
'very_low_power_mode', ctypes.c_uint32, 1),
|
||||
(
|
||||
'LLSMODEEXIT', ctypes.c_uint32, 1),
|
||||
(
|
||||
'VLLSxMODEEXIT', ctypes.c_uint32, 1),
|
||||
(
|
||||
'RESERVED_B', ctypes.c_uint32, 5),
|
||||
(
|
||||
'core_halted', ctypes.c_uint32, 1),
|
||||
(
|
||||
'core_deep_sleep', ctypes.c_uint32, 1),
|
||||
(
|
||||
'core_sleeping', ctypes.c_uint32, 1),
|
||||
(
|
||||
'RESERVED_C', ctypes.c_uint32, 13)]
|
||||
|
||||
|
||||
class MDMAPStatusRegisterFlags(ctypes.Union):
|
||||
__doc__ = 'Mask for the MDM-AP status register bits.\n\n Attributes:\n value: the value stored in the mask.\n '
|
||||
_anonymous_ = ('bit', )
|
||||
_fields_ = [
|
||||
(
|
||||
'bit', MDMAPStatusRegisterBits),
|
||||
(
|
||||
'value', ctypes.c_uint32)]
|
||||
# okay decompiling ./pylink/registers.pyc
|
907
pylink/structs.py
Normal file
907
pylink/structs.py
Normal file
|
@ -0,0 +1,907 @@
|
|||
# decompyle3 version 3.9.0
|
||||
# Python bytecode version base 3.7.0 (3394)
|
||||
# Decompiled from: Python 3.7.16 (default, Mar 30 2023, 01:25:49)
|
||||
# [GCC 12.2.1 20220924]
|
||||
# Embedded file name: pylink/structs.py
|
||||
from . import enums
|
||||
import ctypes
|
||||
|
||||
class JLinkConnectInfo(ctypes.Structure):
|
||||
__doc__ = 'J-Link connection info structure.\n\n Attributes:\n SerialNumber: J-Link serial number.\n Connection: type of connection (e.g. ``enums.JLinkHost.USB``)\n USBAddr: USB address if connected via USB.\n aIPAddr: IP address if connected via IP.\n Time: Time period (ms) after which UDP discover answer was received.\n Time_us: Time period (uS) after which UDP discover answer was received.\n HWVersion: Hardware version of J-Link, if connected via IP.\n abMACAddr: MAC Address, if connected via IP.\n acProduct: Product name, if connected via IP.\n acNickname: Nickname, if connected via IP.\n acFWString: Firmware string, if connected via IP.\n IsDHCPAssignedIP: Is IP address reception via DHCP.\n IsDHCPAssignedIPIsValid: True if connected via IP.\n NumIPConnections: Number of IP connections currently established.\n NumIPConnectionsIsValid: True if connected via IP.\n aPadding: Bytes reserved for future use.\n '
|
||||
_fields_ = [
|
||||
(
|
||||
'SerialNumber', ctypes.c_uint32),
|
||||
(
|
||||
'Connection', ctypes.c_ubyte),
|
||||
(
|
||||
'USBAddr', ctypes.c_uint32),
|
||||
(
|
||||
'aIPAddr', ctypes.c_uint8 * 16),
|
||||
(
|
||||
'Time', ctypes.c_int),
|
||||
(
|
||||
'Time_us', ctypes.c_uint64),
|
||||
(
|
||||
'HWVersion', ctypes.c_uint32),
|
||||
(
|
||||
'abMACAddr', ctypes.c_uint8 * 6),
|
||||
(
|
||||
'acProduct', ctypes.c_char * 32),
|
||||
(
|
||||
'acNickname', ctypes.c_char * 32),
|
||||
(
|
||||
'acFWString', ctypes.c_char * 112),
|
||||
(
|
||||
'IsDHCPAssignedIP', ctypes.c_char),
|
||||
(
|
||||
'IsDHCPAssignedIPIsValid', ctypes.c_char),
|
||||
(
|
||||
'NumIPConnections', ctypes.c_char),
|
||||
(
|
||||
'NumIPConnectionsIsValid', ctypes.c_char),
|
||||
(
|
||||
'aPadding', ctypes.c_uint8 * 34)]
|
||||
|
||||
def __repr__(self):
|
||||
"""Returns a representation of this class.
|
||||
|
||||
Args:
|
||||
self (JLinkConnectInfo): the ``JlinkConnectInfo`` instance
|
||||
|
||||
Returns:
|
||||
String representation of the class.
|
||||
"""
|
||||
return 'JLinkConnectInfo(%s)' % self.__str__()
|
||||
|
||||
def __str__(self):
|
||||
"""Returns a string representation of the connection info.
|
||||
|
||||
Args:
|
||||
self (JLinkConnectInfo): the ``JLinkConnectInfo`` instance
|
||||
|
||||
Returns:
|
||||
String specifying the product, its serial number, and the type of
|
||||
connection that it has (one of USB or IP).
|
||||
"""
|
||||
conn = 'USB' if self.Connection == 1 else 'IP'
|
||||
return '%s <Serial No. %s, Conn. %s>' % (self.acProduct.decode(), self.SerialNumber, conn)
|
||||
|
||||
|
||||
class JLinkFlashArea(ctypes.Structure):
|
||||
__doc__ = 'Definition for a region of Flash.\n\n Attributes:\n Addr: address where the flash area starts.\n Size: size of the flash area.\n '
|
||||
_fields_ = [
|
||||
(
|
||||
'Addr', ctypes.c_uint32),
|
||||
(
|
||||
'Size', ctypes.c_uint32)]
|
||||
|
||||
def __repr__(self):
|
||||
"""Returns a representation of the instance.
|
||||
|
||||
Args:
|
||||
self (FlashArea): the ``FlashArea`` instance
|
||||
|
||||
Returns:
|
||||
String representation of the Flash Area.
|
||||
"""
|
||||
return '%s(%s)' % (self.__class__.__name__, self.__str__())
|
||||
|
||||
def __str__(self):
|
||||
"""Returns a string representation of the instance.
|
||||
|
||||
Args:
|
||||
self (FlashArea): the ``FlashArea`` instance
|
||||
|
||||
Returns:
|
||||
String specifying address of flash region, and its size.
|
||||
"""
|
||||
return 'Address = 0x%x, Size = %s' % (self.Addr, self.Size)
|
||||
|
||||
|
||||
class JLinkRAMArea(JLinkFlashArea):
|
||||
__doc__ = 'Definition for a region of RAM.\n\n Attributes:\n Addr: address where the flash area starts.\n Size: size of the flash area.\n '
|
||||
|
||||
|
||||
class JLinkDeviceInfo(ctypes.Structure):
|
||||
__doc__ = 'J-Link device information.\n\n This structure is used to represent a device that is supported by the\n J-Link.\n\n Attributes:\n SizeOfStruct: Size of the struct (DO NOT CHANGE).\n sName: name of the device.\n CoreId: core identifier of the device.\n FlashAddr: base address of the internal flash of the device.\n RAMAddr: base address of the internal RAM of the device.\n EndianMode: the endian mode of the device (0 -> only little endian,\n 1 -> only big endian, 2 -> both).\n FlashSize: total flash size in bytes.\n RAMSize: total RAM size in bytes.\n sManu: device manufacturer.\n aFlashArea: a list of ``JLinkFlashArea`` instances.\n aRamArea: a list of ``JLinkRAMArea`` instances.\n Core: CPU core.\n '
|
||||
_fields_ = [
|
||||
(
|
||||
'SizeofStruct', ctypes.c_uint32),
|
||||
(
|
||||
'sName', ctypes.POINTER(ctypes.c_char)),
|
||||
(
|
||||
'CoreId', ctypes.c_uint32),
|
||||
(
|
||||
'FlashAddr', ctypes.c_uint32),
|
||||
(
|
||||
'RAMAddr', ctypes.c_uint32),
|
||||
(
|
||||
'EndianMode', ctypes.c_char),
|
||||
(
|
||||
'FlashSize', ctypes.c_uint32),
|
||||
(
|
||||
'RAMSize', ctypes.c_uint32),
|
||||
(
|
||||
'sManu', ctypes.POINTER(ctypes.c_char)),
|
||||
(
|
||||
'aFlashArea', JLinkFlashArea * 32),
|
||||
(
|
||||
'aRAMArea', JLinkRAMArea * 32),
|
||||
(
|
||||
'Core', ctypes.c_uint32)]
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
(super(JLinkDeviceInfo, self).__init__)(*args, **kwargs)
|
||||
self.SizeofStruct = ctypes.sizeof(self)
|
||||
|
||||
def __repr__(self):
|
||||
"""Returns a representation of this instance.
|
||||
|
||||
Args:
|
||||
self (JLinkDeviceInfo): the ``JLinkDeviceInfo`` instance
|
||||
|
||||
Returns:
|
||||
Returns a string representation of the instance.
|
||||
"""
|
||||
return 'JLinkDeviceInfo(%s)' % self.__str__()
|
||||
|
||||
def __str__(self):
|
||||
"""Returns a string representation of this instance.
|
||||
|
||||
Args:
|
||||
self (JLinkDeviceInfo): the ``JLinkDeviceInfo`` instance
|
||||
|
||||
Returns:
|
||||
Returns a string specifying the device name, core, and manufacturer.
|
||||
"""
|
||||
manu = self.manufacturer
|
||||
return '%s <Core Id. %s, Manu. %s>' % (self.name, self.Core, manu)
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
"""Returns the name of the device.
|
||||
|
||||
Args:
|
||||
self (JLinkDeviceInfo): the ``JLinkDeviceInfo`` instance
|
||||
|
||||
Returns:
|
||||
Device name.
|
||||
"""
|
||||
return ctypes.cast(self.sName, ctypes.c_char_p).value.decode()
|
||||
|
||||
@property
|
||||
def manufacturer(self):
|
||||
"""Returns the name of the manufacturer of the device.
|
||||
|
||||
Args:
|
||||
self (JLinkDeviceInfo): the ``JLinkDeviceInfo`` instance
|
||||
|
||||
Returns:
|
||||
Manufacturer name.
|
||||
"""
|
||||
buf = ctypes.cast(self.sManu, ctypes.c_char_p).value
|
||||
if buf:
|
||||
return buf.decode()
|
||||
|
||||
|
||||
class JLinkHardwareStatus(ctypes.Structure):
|
||||
__doc__ = 'Definition for the hardware status information for a J-Link.\n\n Attributes:\n VTarget: target supply voltage.\n tck: measured state of TCK pin.\n tdi: measured state of TDI pin.\n tdo: measured state of TDO pin.\n tms: measured state of TMS pin.\n tres: measured state of TRES pin.\n trst: measured state of TRST pin.\n '
|
||||
_fields_ = [
|
||||
(
|
||||
'VTarget', ctypes.c_uint16),
|
||||
(
|
||||
'tck', ctypes.c_uint8),
|
||||
(
|
||||
'tdi', ctypes.c_uint8),
|
||||
(
|
||||
'tdo', ctypes.c_uint8),
|
||||
(
|
||||
'tms', ctypes.c_uint8),
|
||||
(
|
||||
'tres', ctypes.c_uint8),
|
||||
(
|
||||
'trst', ctypes.c_uint8)]
|
||||
|
||||
def __repr__(self):
|
||||
"""Returns a string representation of the instance.
|
||||
|
||||
Args:
|
||||
self (JLinkHardwareStatus): the ``JlinkHardwareStatus`` instance
|
||||
|
||||
Returns:
|
||||
String representation of the instance.
|
||||
"""
|
||||
return '%s(VTarget=%dmV)' % (self.__class__.__name__, self.voltage)
|
||||
|
||||
@property
|
||||
def voltage(self):
|
||||
"""Returns the target supply voltage.
|
||||
|
||||
This is an alias for ``.VTarget``.
|
||||
|
||||
Args:
|
||||
self (JLInkHardwareStatus): the ``JLinkHardwareStatus`` instance
|
||||
|
||||
Returns:
|
||||
Target supply voltage as an integer.
|
||||
"""
|
||||
return self.VTarget
|
||||
|
||||
|
||||
class JLinkGPIODescriptor(ctypes.Structure):
|
||||
__doc__ = 'Definition for the structure that details the name and capabilities of a\n user-controllable GPIO.\n\n Attributes:\n acName: name of the GPIO.\n Caps: bitfield of capabilities.\n '
|
||||
_fields_ = [
|
||||
(
|
||||
'acName', ctypes.c_char * 32),
|
||||
(
|
||||
'Caps', ctypes.c_uint32)]
|
||||
|
||||
def __repr__(self):
|
||||
"""Returns a string representation of the instance.
|
||||
|
||||
Args:
|
||||
self (JLinkGPIODescriptor): the ``JLinkGPIODescriptor`` instance
|
||||
|
||||
Returns:
|
||||
String representation of the instance.
|
||||
"""
|
||||
return '%s(%s)' % (self.__class__.__name__, self.__str__())
|
||||
|
||||
def __str__(self):
|
||||
"""Returns the GPIO name.
|
||||
|
||||
Args:
|
||||
self (JLinkGPIODescriptor): the ``JLInkGPIODescriptor`` instance
|
||||
|
||||
Returns:
|
||||
GPIO name.
|
||||
"""
|
||||
return self.acName.decode()
|
||||
|
||||
|
||||
class JLinkMemoryZone(ctypes.Structure):
|
||||
__doc__ = 'Represents a CPU memory zone.\n\n Attributes:\n sName: initials of the memory zone.\n sDesc: name of the memory zone.\n VirtAddr: start address of the virtual address space of the memory zone.\n abDummy: reserved for future use.\n '
|
||||
_fields_ = [
|
||||
(
|
||||
'sName', ctypes.c_char_p),
|
||||
(
|
||||
'sDesc', ctypes.c_char_p),
|
||||
(
|
||||
'VirtAddr', ctypes.c_uint64),
|
||||
(
|
||||
'abDummy', ctypes.c_uint8 * 16)]
|
||||
|
||||
def __repr__(self):
|
||||
"""Returns a string representation of the instance
|
||||
|
||||
Args:
|
||||
self: the ``JLinkMemoryZone`` instance
|
||||
|
||||
Returns:
|
||||
String representation of the instance.
|
||||
"""
|
||||
return '%s(%s)' % (self.__class__.__name__, self.__str__())
|
||||
|
||||
def __str__(self):
|
||||
"""Returns a formatted string describing the memory zone.
|
||||
|
||||
Args:
|
||||
self: the ``JLinkMemoryZone`` instance
|
||||
|
||||
Returns:
|
||||
String representation of the memory zone.
|
||||
"""
|
||||
return '%s <Desc. %s, VirtAddr. 0x%x>' % (self.sName, self.sDesc, self.VirtAddr)
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
"""Alias for the memory zone name.
|
||||
|
||||
Args:
|
||||
self (JLinkMemoryZone): the ``JLinkMemoryZone`` instance
|
||||
|
||||
Returns:
|
||||
The memory zone name.
|
||||
"""
|
||||
return self.sName
|
||||
|
||||
|
||||
class JLinkSpeedInfo(ctypes.Structure):
|
||||
__doc__ = "Represents information about an emulator's supported speeds.\n\n The emulator can support all target interface speeds calculated by dividing\n the base frequency by atleast ``MinDiv``.\n\n Attributes:\n SizeOfStruct: the size of this structure.\n BaseFreq: Base frequency (in HZ) used to calculate supported speeds.\n MinDiv: minimum divider allowed to divide the base frequency.\n SupportAdaptive: ``1`` if emulator supports adaptive clocking, otherwise\n ``0``.\n "
|
||||
_fields_ = [
|
||||
(
|
||||
'SizeOfStruct', ctypes.c_uint32),
|
||||
(
|
||||
'BaseFreq', ctypes.c_uint32),
|
||||
(
|
||||
'MinDiv', ctypes.c_uint16),
|
||||
(
|
||||
'SupportAdaptive', ctypes.c_uint16)]
|
||||
|
||||
def __init__(self):
|
||||
super(JLinkSpeedInfo, self).__init__()
|
||||
self.SizeOfStruct = ctypes.sizeof(self)
|
||||
|
||||
def __repr__(self):
|
||||
"""Returns a string representation of the instance.
|
||||
|
||||
Args:
|
||||
self (JLinkSpeedInfo): the ``JLinkSpeedInfo`` instance
|
||||
|
||||
Returns:
|
||||
String representation of the instance.
|
||||
"""
|
||||
return self.__str__()
|
||||
|
||||
def __str__(self):
|
||||
"""Returns this instance formatted as a string.
|
||||
|
||||
Args:
|
||||
self (JLinkSpeedInfo): the ``JLinkSpeedInfo`` instance
|
||||
|
||||
Returns:
|
||||
String formatted instance.
|
||||
"""
|
||||
return '%s(Freq=%sHz)' % (self.__class__.__name__, self.BaseFreq)
|
||||
|
||||
|
||||
class JLinkSWOStartInfo(ctypes.Structure):
|
||||
__doc__ = 'Represents configuration information for collecting Serial Wire Output\n (SWO) information.\n\n Attributes:\n SizeofStruct: size of the structure.\n Interface: the interface type used for SWO.\n Speed: the frequency used for SWO communication in Hz.\n\n Note:\n You should *never* change ``.SizeofStruct`` or ``.Interface``.\n '
|
||||
_fields_ = [
|
||||
(
|
||||
'SizeofStruct', ctypes.c_uint32),
|
||||
(
|
||||
'Interface', ctypes.c_uint32),
|
||||
(
|
||||
'Speed', ctypes.c_uint32)]
|
||||
|
||||
def __init__(self):
|
||||
super(JLinkSWOStartInfo, self).__init__()
|
||||
self.SizeofStruct = ctypes.sizeof(self)
|
||||
self.Interface = enums.JLinkSWOInterfaces.UART
|
||||
|
||||
def __repr__(self):
|
||||
"""Returns a representation of this instance.
|
||||
|
||||
Args:
|
||||
self (JLinkSWOStartInfo): the ``JLinkSWOStartInfo`` instance
|
||||
|
||||
Returns:
|
||||
The string representation of this instance.
|
||||
"""
|
||||
return self.__str__()
|
||||
|
||||
def __str__(self):
|
||||
"""Returns a string representation of this instance.
|
||||
|
||||
Args:
|
||||
self (JLinkSWOStartInfo): the ``JLinkSWOStartInfo`` instance
|
||||
|
||||
Returns:
|
||||
The string representation of this instance.
|
||||
"""
|
||||
return '%s(Speed=%sHz)' % (self.__class__.__name__, self.Speed)
|
||||
|
||||
|
||||
class JLinkSWOSpeedInfo(ctypes.Structure):
|
||||
__doc__ = "Structure representing information about target's supported SWO speeds.\n\n To calculate the supported SWO speeds, the base frequency is taken and\n divide by a number in the range of ``[ MinDiv, MaxDiv ]``.\n\n Attributes:\n SizeofStruct: size of the structure.\n Interface: interface type for the speed information.\n BaseFreq: base frequency (Hz) used to calculate supported SWO speeds.\n MinDiv: minimum divider allowed to divide the base frequency.\n MaxDiv: maximum divider allowed to divide the base frequency.\n MinPrescale: minimum prescaler allowed to adjust the base frequency.\n MaxPrescale: maximum prescaler allowed to adjust the base frequency.\n\n Note:\n You should *never* change ``.SizeofStruct`` or ``.Interface``.\n "
|
||||
_fields_ = [
|
||||
(
|
||||
'SizeofStruct', ctypes.c_uint32),
|
||||
(
|
||||
'Interface', ctypes.c_uint32),
|
||||
(
|
||||
'BaseFreq', ctypes.c_uint32),
|
||||
(
|
||||
'MinDiv', ctypes.c_uint32),
|
||||
(
|
||||
'MaxDiv', ctypes.c_uint32),
|
||||
(
|
||||
'MinPrescale', ctypes.c_uint32),
|
||||
(
|
||||
'MaxPrescale', ctypes.c_uint32)]
|
||||
|
||||
def __init__(self):
|
||||
super(JLinkSWOSpeedInfo, self).__init__()
|
||||
self.SizeofStruct = ctypes.sizeof(self)
|
||||
self.Interface = enums.JLinkSWOInterfaces.UART
|
||||
|
||||
def __repr__(self):
|
||||
"""Returns a representation of the instance.
|
||||
|
||||
Args:
|
||||
self (JLinkSWOSpeedInfo): the ``JLinkSWOSpeedInfo`` instance
|
||||
|
||||
Returns:
|
||||
``None``
|
||||
"""
|
||||
return self.__str__()
|
||||
|
||||
def __str__(self):
|
||||
"""Returns a string representaton of the instance.
|
||||
|
||||
Args:
|
||||
self (JLinkSWOSpeedInfo): the ``JLinkSWOSpeedInfo`` instance
|
||||
|
||||
Returns:
|
||||
``None``
|
||||
"""
|
||||
return '%s(Interface=UART, Freq=%sHz)' % (self.__class__.__name__, self.BaseFreq)
|
||||
|
||||
|
||||
class JLinkMOEInfo(ctypes.Structure):
|
||||
__doc__ = 'Structure representing the Method of Debug Entry (MOE).\n\n The method of debug entry is a reason for which a CPU has stopped. At any\n given time, there may be multiple methods of debug entry.\n\n Attributes:\n HaltReason: reason why the CPU stopped.\n Index: if cause of CPU stop was a code/data breakpoint, this identifies\n the index of the code/data breakpoint unit which causes the CPU to\n stop, otherwise it is ``-1``.\n '
|
||||
_fields_ = [
|
||||
(
|
||||
'HaltReason', ctypes.c_uint32),
|
||||
(
|
||||
'Index', ctypes.c_int)]
|
||||
|
||||
def __repr__(self):
|
||||
"""Returns a string representation of the instance.
|
||||
|
||||
Args:
|
||||
self (JLinkMOEInfo): the ``JLinkMOEInfo`` instance
|
||||
|
||||
Returns:
|
||||
A string representation of the instance.
|
||||
"""
|
||||
return '%s(%s)' % (self.__class__.__name__, self.__str__())
|
||||
|
||||
def __str__(self):
|
||||
"""Returns a string representation of the instance.
|
||||
|
||||
Args:
|
||||
self (JLinkMOEInfo): the ``JLinkMOEInfo`` instance
|
||||
|
||||
Returns:
|
||||
A string representation of the instance.
|
||||
"""
|
||||
d = enums.JLinkHaltReasons.__dict__
|
||||
s = next((k for k, v in d.items() if v == self.HaltReason))
|
||||
if self.dbgrq():
|
||||
return s
|
||||
return s.replace('_', ' ').title()
|
||||
|
||||
def dbgrq(self):
|
||||
"""Returns whether this a DBGRQ.
|
||||
|
||||
Args:
|
||||
self (JLinkMOEInfo): the ``JLinkMOEInfo`` instance
|
||||
|
||||
Returns:
|
||||
``True`` if this is a DBGRQ, otherwise ``False``.
|
||||
"""
|
||||
return self.HaltReason == enums.JLinkHaltReasons.DBGRQ
|
||||
|
||||
def code_breakpoint(self):
|
||||
"""Returns whether this a code breakpoint.
|
||||
|
||||
Args:
|
||||
self (JLinkMOEInfo): the ``JLinkMOEInfo`` instance
|
||||
|
||||
Returns:
|
||||
``True`` if this is a code breakpoint, otherwise ``False``.
|
||||
"""
|
||||
return self.HaltReason == enums.JLinkHaltReasons.CODE_BREAKPOINT
|
||||
|
||||
def data_breakpoint(self):
|
||||
"""Returns whether this a data breakpoint.
|
||||
|
||||
Args:
|
||||
self (JLinkMOEInfo): the ``JLinkMOEInfo`` instance
|
||||
|
||||
Returns:
|
||||
``True`` if this is a data breakpoint, otherwise ``False``.
|
||||
"""
|
||||
return self.HaltReason == enums.JLinkHaltReasons.DATA_BREAKPOINT
|
||||
|
||||
def vector_catch(self):
|
||||
"""Returns whether this a vector catch.
|
||||
|
||||
Args:
|
||||
self (JLinkMOEInfo): the ``JLinkMOEInfo`` instance
|
||||
|
||||
Returns:
|
||||
``True`` if this is a vector catch, otherwise ``False``.
|
||||
"""
|
||||
return self.HaltReason == enums.JLinkHaltReasons.VECTOR_CATCH
|
||||
|
||||
|
||||
class JLinkBreakpointInfo(ctypes.Structure):
|
||||
__doc__ = 'Class representing information about a breakpoint.\n\n Attributes:\n SizeOfStruct: the size of the structure (this should not be modified).\n Handle: breakpoint handle.\n Addr: address of where the breakpoint has been set.\n Type: type flags which were specified when the breakpoint was created.\n ImpFlags: describes the current state of the breakpoint.\n UseCnt: describes how often the breakpoint is set at the same address.\n '
|
||||
_fields_ = [
|
||||
(
|
||||
'SizeOfStruct', ctypes.c_uint32),
|
||||
(
|
||||
'Handle', ctypes.c_uint32),
|
||||
(
|
||||
'Addr', ctypes.c_uint32),
|
||||
(
|
||||
'Type', ctypes.c_uint32),
|
||||
(
|
||||
'ImpFlags', ctypes.c_uint32),
|
||||
(
|
||||
'UseCnt', ctypes.c_uint32)]
|
||||
|
||||
def __init__(self):
|
||||
super(JLinkBreakpointInfo, self).__init__()
|
||||
self.SizeOfStruct = ctypes.sizeof(self)
|
||||
|
||||
def __repr__(self):
|
||||
"""Returns a formatted string describing the breakpoint.
|
||||
|
||||
Args:
|
||||
self (JLinkBreakpointInfo): the ``JLinkBreakpointInfo`` instance
|
||||
|
||||
Returns:
|
||||
Stirng representation of the breakpoint.
|
||||
"""
|
||||
return self.__str__()
|
||||
|
||||
def __str__(self):
|
||||
"""Returns a formatted string describing the breakpoint.
|
||||
|
||||
Args:
|
||||
self (JLinkBreakpointInfo): the ``JLinkBreakpointInfo`` instance
|
||||
|
||||
Returns:
|
||||
Stirng representation of the breakpoint.
|
||||
"""
|
||||
name = self.__class__.__name__
|
||||
return '%s(Handle %d, Address %d)' % (name, self.Handle, self.Addr)
|
||||
|
||||
def software_breakpoint(self):
|
||||
"""Returns whether this is a software breakpoint.
|
||||
|
||||
Args:
|
||||
self (JLinkBreakpointInfo): the ``JLinkBreakpointInfo`` instance
|
||||
|
||||
Returns:
|
||||
``True`` if the breakpoint is a software breakpoint, otherwise
|
||||
``False``.
|
||||
"""
|
||||
software_types = [
|
||||
enums.JLinkBreakpoint.SW_RAM,
|
||||
enums.JLinkBreakpoint.SW_FLASH,
|
||||
enums.JLinkBreakpoint.SW]
|
||||
return any((self.Type & stype for stype in software_types))
|
||||
|
||||
def hardware_breakpoint(self):
|
||||
"""Returns whether this is a hardware breakpoint.
|
||||
|
||||
Args:
|
||||
self (JLinkBreakpointInfo): the ``JLinkBreakpointInfo`` instance
|
||||
|
||||
Returns:
|
||||
``True`` if the breakpoint is a hardware breakpoint, otherwise
|
||||
``False``.
|
||||
"""
|
||||
return self.Type & enums.JLinkBreakpoint.HW
|
||||
|
||||
def pending(self):
|
||||
"""Returns if this breakpoint is pending.
|
||||
|
||||
Args:
|
||||
self (JLinkBreakpointInfo): the ``JLinkBreakpointInfo`` instance
|
||||
|
||||
Returns:
|
||||
``True`` if the breakpoint is still pending, otherwise ``False``.
|
||||
"""
|
||||
return self.ImpFlags & enums.JLinkBreakpointImplementation.PENDING
|
||||
|
||||
|
||||
class JLinkDataEvent(ctypes.Structure):
|
||||
__doc__ = 'Class representing a data event.\n\n A data may halt the CPU, trigger SWO output, or trigger trace output.\n\n Attributes:\n SizeOfStruct: the size of the structure (this should not be modified).\n Type: the type of the data event (this should not be modified).\n Addr: the address on which the watchpoint was set\n AddrMask: the address mask used for comparision.\n Data: the data on which the watchpoint has been set.\n DataMask: the data mask used for comparision.\n Access: the control data on which the event has been set.\n AccessMask: the control mask used for comparison.\n '
|
||||
_fields_ = [
|
||||
(
|
||||
'SizeOfStruct', ctypes.c_int),
|
||||
(
|
||||
'Type', ctypes.c_int),
|
||||
(
|
||||
'Addr', ctypes.c_uint32),
|
||||
(
|
||||
'AddrMask', ctypes.c_uint32),
|
||||
(
|
||||
'Data', ctypes.c_uint32),
|
||||
(
|
||||
'DataMask', ctypes.c_uint32),
|
||||
(
|
||||
'Access', ctypes.c_uint8),
|
||||
(
|
||||
'AccessMask', ctypes.c_uint8)]
|
||||
|
||||
def __init__(self):
|
||||
super(JLinkDataEvent, self).__init__()
|
||||
self.SizeOfStruct = ctypes.sizeof(self)
|
||||
self.Type = enums.JLinkEventTypes.BREAKPOINT
|
||||
|
||||
def __repr__(self):
|
||||
"""Returns a string representation of the data event.
|
||||
|
||||
Args:
|
||||
self (JLinkDataEvent): the ``JLinkDataEvent`` instance
|
||||
|
||||
Returns:
|
||||
A string representation of the data event.
|
||||
"""
|
||||
return self.__str__()
|
||||
|
||||
def __str__(self):
|
||||
"""Returns a string representation of the data event.
|
||||
|
||||
Args:
|
||||
self (JLinkDataEvent): the ``JLinkDataEvent`` instance
|
||||
|
||||
Returns:
|
||||
A string representation of the data event.
|
||||
"""
|
||||
name = self.__class__.__name__
|
||||
return '%s(Type %d, Address %d)' % (name, self.Type, self.Addr)
|
||||
|
||||
|
||||
class JLinkWatchpointInfo(ctypes.Structure):
|
||||
__doc__ = 'Class representing information about a watchpoint.\n\n Attributes:\n SizeOfStruct: the size of the structure (this should not be modified).\n Handle: the watchpoint handle.\n Addr: the address the watchpoint was set at.\n AddrMask: the address mask used for comparison.\n Data: the data on which the watchpoint was set.\n DataMask: the data mask used for comparision.\n Ctrl: the control data on which the breakpoint was set.\n CtrlMask: the control mask used for comparison.\n WPUnit: the index of the watchpoint unit.\n '
|
||||
_fields_ = [
|
||||
(
|
||||
'SizeOfStruct', ctypes.c_uint32),
|
||||
(
|
||||
'Handle', ctypes.c_uint32),
|
||||
(
|
||||
'Addr', ctypes.c_uint32),
|
||||
(
|
||||
'AddrMask', ctypes.c_uint32),
|
||||
(
|
||||
'Data', ctypes.c_uint32),
|
||||
(
|
||||
'DataMask', ctypes.c_uint32),
|
||||
(
|
||||
'Ctrl', ctypes.c_uint32),
|
||||
(
|
||||
'CtrlMask', ctypes.c_uint32),
|
||||
(
|
||||
'WPUnit', ctypes.c_uint8)]
|
||||
|
||||
def __init__(self):
|
||||
super(JLinkWatchpointInfo, self).__init__()
|
||||
self.SizeOfStruct = ctypes.sizeof(self)
|
||||
|
||||
def __repr__(self):
|
||||
"""Returns a formatted string describing the watchpoint.
|
||||
|
||||
Args:
|
||||
self (JLinkWatchpointInfo): the ``JLinkWatchpointInfo`` instance
|
||||
|
||||
Returns:
|
||||
String representation of the watchpoint.
|
||||
"""
|
||||
return self.__str__()
|
||||
|
||||
def __str__(self):
|
||||
"""Returns a formatted string describing the watchpoint.
|
||||
|
||||
Args:
|
||||
self (JLinkWatchpointInfo): the ``JLinkWatchpointInfo`` instance
|
||||
|
||||
Returns:
|
||||
String representation of the watchpoint.
|
||||
"""
|
||||
name = self.__class__.__name__
|
||||
return '%s(Handle %d, Address %d)' % (name, self.Handle, self.Addr)
|
||||
|
||||
|
||||
class JLinkStraceEventInfo(ctypes.Structure):
|
||||
__doc__ = 'Class representing the STRACE event information.\n\n Attributes:\n SizeOfStruct: size of the structure.\n Type: type of event.\n Op: the STRACE operation to perform.\n AccessSize: access width for trace events.\n Reserved0: reserved.\n Addr: specifies the load/store address for data.\n Data: the data to be compared for the operation for data access events.\n DataMask: bitmask for bits of data to omit in comparision for data access\n events.\n AddrRangeSize: address range for range events.\n '
|
||||
_fields_ = [
|
||||
(
|
||||
'SizeOfStruct', ctypes.c_uint32),
|
||||
(
|
||||
'Type', ctypes.c_uint8),
|
||||
(
|
||||
'Op', ctypes.c_uint8),
|
||||
(
|
||||
'AccessSize', ctypes.c_uint8),
|
||||
(
|
||||
'Reserved0', ctypes.c_uint8),
|
||||
(
|
||||
'Addr', ctypes.c_uint64),
|
||||
(
|
||||
'Data', ctypes.c_uint64),
|
||||
(
|
||||
'DataMask', ctypes.c_uint64),
|
||||
(
|
||||
'AddrRangeSize', ctypes.c_uint32)]
|
||||
|
||||
def __init__(self):
|
||||
super(JLinkStraceEventInfo, self).__init__()
|
||||
self.SizeOfStruct = ctypes.sizeof(self)
|
||||
|
||||
def __repr__(self):
|
||||
"""Returns a formatted string describing the event info.
|
||||
|
||||
Args:
|
||||
self (JLinkStraceEventInfo): the ``JLinkStraceEventInfo`` instance
|
||||
|
||||
Returns:
|
||||
String representation of the event info.
|
||||
"""
|
||||
return self.__str__()
|
||||
|
||||
def __str__(self):
|
||||
"""Returns a formatted string describing the event info.
|
||||
|
||||
Args:
|
||||
self (JLinkStraceEventInfo): the ``JLinkStraceEventInfo`` instance
|
||||
|
||||
Returns:
|
||||
String representation of the event information.
|
||||
"""
|
||||
name = self.__class__.__name__
|
||||
return '%s(Type=%d, Op=%d)' % (name, self.Type, self.Op)
|
||||
|
||||
|
||||
class JLinkTraceData(ctypes.Structure):
|
||||
__doc__ = 'Structure representing trace data returned by the trace buffer.\n\n Attributes:\n PipeStat: type of trace data.\n Sync: sync point in buffer.\n Packet: trace data packet.\n '
|
||||
_fields_ = [
|
||||
(
|
||||
'PipeStat', ctypes.c_uint8),
|
||||
(
|
||||
'Sync', ctypes.c_uint8),
|
||||
(
|
||||
'Packet', ctypes.c_uint16)]
|
||||
|
||||
def __repr__(self):
|
||||
"""Returns a string representation of the trace data instance.
|
||||
|
||||
Args:
|
||||
self (JLinkTraceData): the ``JLinkTraceData`` instance.
|
||||
|
||||
Returns:
|
||||
A string representation of the instance.
|
||||
"""
|
||||
return self.__str__()
|
||||
|
||||
def __str__(self):
|
||||
"""Returns a string representation of the trace data instance.
|
||||
|
||||
Args:
|
||||
self (JLinkTraceData): the ``JLinkTraceData`` instance.
|
||||
|
||||
Returns:
|
||||
A string representation of the instance.
|
||||
"""
|
||||
return '%s(%d)' % (self.__class__.__name__, self.Packet)
|
||||
|
||||
def instruction(self):
|
||||
"""Returns whether the data corresponds to an executed instruction.
|
||||
|
||||
Args:
|
||||
self (JLinkTraceData): the ``JLinkTraceData`` instance.
|
||||
|
||||
Returns:
|
||||
``True`` if this is trace data for an executed instruction.
|
||||
"""
|
||||
return self.PipeStat == 0
|
||||
|
||||
def data_instruction(self):
|
||||
"""Returns whether the data corresponds to an data instruction.
|
||||
|
||||
Args:
|
||||
self (JLinkTraceData): the ``JLinkTraceData`` instance.
|
||||
|
||||
Returns:
|
||||
``True`` if this is trace data for an data instruction.
|
||||
"""
|
||||
return self.PipeStat == 1
|
||||
|
||||
def non_instruction(self):
|
||||
"""Returns whether the data corresponds to an un-executed instruction.
|
||||
|
||||
Args:
|
||||
self (JLinkTraceData): the ``JLinkTraceData`` instance.
|
||||
|
||||
Returns:
|
||||
``True`` if this is trace data for an un-executed instruction.
|
||||
"""
|
||||
return self.PipeStat == 2
|
||||
|
||||
def wait(self):
|
||||
"""Returns whether the data corresponds to a wait.
|
||||
|
||||
Args:
|
||||
self (JLinkTraceData): the ``JLinkTraceData`` instance.
|
||||
|
||||
Returns:
|
||||
``True`` if this is trace data for a wait.
|
||||
"""
|
||||
return self.PipeStat == 3
|
||||
|
||||
def branch(self):
|
||||
"""Returns whether the data corresponds to a branch execution.
|
||||
|
||||
Args:
|
||||
self (JLinkTraceData): the ``JLinkTraceData`` instance.
|
||||
|
||||
Returns:
|
||||
``True`` if this is trace data for a branch execution.
|
||||
"""
|
||||
return self.PipeStat == 4
|
||||
|
||||
def data_branch(self):
|
||||
"""Returns whether the data corresponds to a branch with data.
|
||||
|
||||
Args:
|
||||
self (JLinkTraceData): the ``JLinkTraceData`` instance.
|
||||
|
||||
Returns:
|
||||
``True`` if this is trace data for a branch with data.
|
||||
"""
|
||||
return self.PipeStat == 5
|
||||
|
||||
def trigger(self):
|
||||
"""Returns whether the data corresponds to a trigger event.
|
||||
|
||||
Args:
|
||||
self (JLinkTraceData): the ``JLinkTraceData`` instance.
|
||||
|
||||
Returns:
|
||||
``True`` if this is trace data for a trigger event.
|
||||
"""
|
||||
return self.PipeStat == 6
|
||||
|
||||
def trace_disabled(self):
|
||||
"""Returns whether the data corresponds to trace being disabled.
|
||||
|
||||
Args:
|
||||
self (JLinkTraceData): the ``JLinkTraceData`` instance.
|
||||
|
||||
Returns:
|
||||
``True`` if this is trace data for the trace disabled event.
|
||||
"""
|
||||
return self.PipeStat == 7
|
||||
|
||||
|
||||
class JLinkTraceRegion(ctypes.Structure):
|
||||
__doc__ = 'Structure describing a trace region.\n\n Attributes:\n SizeOfStruct: size of the structure.\n RegionIndex: index of the region.\n NumSamples: number of samples in the region.\n Off: offset in the trace buffer.\n RegionCnt: number of trace regions.\n Dummy: unused.\n Timestamp: timestamp of last event written to buffer.\n '
|
||||
_fields_ = [
|
||||
(
|
||||
'SizeOfStruct', ctypes.c_uint32),
|
||||
(
|
||||
'RegionIndex', ctypes.c_uint32),
|
||||
(
|
||||
'NumSamples', ctypes.c_uint32),
|
||||
(
|
||||
'Off', ctypes.c_uint32),
|
||||
(
|
||||
'RegionCnt', ctypes.c_uint32),
|
||||
(
|
||||
'Dummy', ctypes.c_uint32),
|
||||
(
|
||||
'Timestamp', ctypes.c_uint64)]
|
||||
|
||||
def __init__(self):
|
||||
super(JLinkTraceRegion, self).__init__()
|
||||
self.SizeOfStruct = ctypes.sizeof(self)
|
||||
|
||||
def __repr__(self):
|
||||
"""Returns a string representation of the instance.
|
||||
|
||||
Args:
|
||||
self (JLinkTraceRegion): the ``JLinkTraceRegion`` instance.
|
||||
|
||||
Returns:
|
||||
String representation of the trace region.
|
||||
"""
|
||||
return self.__str__()
|
||||
|
||||
def __str__(self):
|
||||
"""Returns a string representation of the instance.
|
||||
|
||||
Args:
|
||||
self (JLinkTraceRegion): the ``JLinkTraceRegion`` instance.
|
||||
|
||||
Returns:
|
||||
String representation of the trace region.
|
||||
"""
|
||||
return '%s(Index=%d)' % (self.__class__.__name__, self.RegionIndex)
|
||||
# okay decompiling ./pylink/structs.pyc
|
45
pylink/threads.py
Normal file
45
pylink/threads.py
Normal file
|
@ -0,0 +1,45 @@
|
|||
# decompyle3 version 3.9.0
|
||||
# Python bytecode version base 3.7.0 (3394)
|
||||
# Decompiled from: Python 3.7.16 (default, Mar 30 2023, 01:25:49)
|
||||
# [GCC 12.2.1 20220924]
|
||||
# Embedded file name: pylink/threads.py
|
||||
import threading
|
||||
|
||||
class ThreadReturn(threading.Thread):
|
||||
__doc__ = 'Implementation of a thread with a return value.\n\n See also:\n `StackOverflow <http://stackoverflow.com/questions/6893968/>`__.\n '
|
||||
|
||||
def __init__(self, daemon=False, *args, **kwargs):
|
||||
"""Initializes the thread.
|
||||
|
||||
Args:
|
||||
self (ThreadReturn): the ``ThreadReturn`` instance
|
||||
daemon (bool): if the thread should be spawned as a daemon
|
||||
args: optional list of arguments
|
||||
kwargs: optional key-word arguments
|
||||
|
||||
Returns:
|
||||
``None``
|
||||
"""
|
||||
(super(ThreadReturn, self).__init__)(*args, **kwargs)
|
||||
self.daemon = daemon
|
||||
self._return = None
|
||||
|
||||
def run(self):
|
||||
"""Runs the thread.
|
||||
|
||||
Args:
|
||||
self (ThreadReturn): the ``ThreadReturn`` instance
|
||||
|
||||
Returns:
|
||||
``None``
|
||||
"""
|
||||
target = getattr(self, '_Thread__target', getattr(self, '_target', None))
|
||||
args = getattr(self, '_Thread__args', getattr(self, '_args', None))
|
||||
kwargs = getattr(self, '_Thread__kwargs', getattr(self, '_kwargs', None))
|
||||
if target is not None:
|
||||
self._return = target(*args, **kwargs)
|
||||
|
||||
def join(self, *args, **kwargs):
|
||||
(super(ThreadReturn, self).join)(*args, **kwargs)
|
||||
return self._return
|
||||
# okay decompiling ./pylink/threads.pyc
|
157
pylink/util.py
Normal file
157
pylink/util.py
Normal file
|
@ -0,0 +1,157 @@
|
|||
# decompyle3 version 3.9.0
|
||||
# Python bytecode version base 3.7.0 (3394)
|
||||
# Decompiled from: Python 3.7.16 (default, Mar 30 2023, 01:25:49)
|
||||
# [GCC 12.2.1 20220924]
|
||||
# Embedded file name: pylink/util.py
|
||||
from . import enums
|
||||
import platform, sys
|
||||
|
||||
def is_integer(val):
|
||||
"""Returns whether the given value is an integer.
|
||||
|
||||
Args:
|
||||
val (object): value to check
|
||||
|
||||
Returns:
|
||||
``True`` if the given value is an integer, otherwise ``False``.
|
||||
"""
|
||||
try:
|
||||
val += 1
|
||||
except TypeError:
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
|
||||
|
||||
def is_natural(val):
|
||||
"""Returns whether the given value is a natrual number.
|
||||
|
||||
Args:
|
||||
val (object): value to check
|
||||
|
||||
Returns:
|
||||
``True`` if the given value is a natural number, otherwise ``False``.
|
||||
"""
|
||||
return is_integer(val) and val >= 0
|
||||
|
||||
|
||||
def is_os_64bit():
|
||||
"""Returns whether the current running platform is 64bit.
|
||||
|
||||
Returns:
|
||||
``True`` if the platform is 64bit, otherwise ``False``.
|
||||
"""
|
||||
return platform.machine().endswith('64')
|
||||
|
||||
|
||||
def noop(*args, **kwargs):
|
||||
"""No-op. Does nothing.
|
||||
|
||||
Args:
|
||||
args: list of arguments
|
||||
kwargs: keyword arguments dictionary
|
||||
|
||||
Returns:
|
||||
``None``
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
def unsecure_hook_dialog(title, msg, flags):
|
||||
"""No-op that ignores the dialog.
|
||||
|
||||
Args:
|
||||
title (str): title of the unsecure dialog
|
||||
msg (str): text of the unsecure dialog
|
||||
flags (int): flags specifying which values can be returned
|
||||
|
||||
Returns:
|
||||
``enums.JLinkFlags.DLG_BUTTON_NO``
|
||||
"""
|
||||
return enums.JLinkFlags.DLG_BUTTON_NO
|
||||
|
||||
|
||||
def progress_bar(iteration, total, prefix=None, suffix=None, decs=1, length=100):
|
||||
"""Creates a console progress bar.
|
||||
|
||||
This should be called in a loop to create a progress bar.
|
||||
|
||||
See `StackOverflow <http://stackoverflow.com/questions/3173320/>`__.
|
||||
|
||||
Args:
|
||||
iteration (int): current iteration
|
||||
total (int): total iterations
|
||||
prefix (str): prefix string
|
||||
suffix (str): suffix string
|
||||
decs (int): positive number of decimals in percent complete
|
||||
length (int): character length of the bar
|
||||
|
||||
Returns:
|
||||
``None``
|
||||
|
||||
Note:
|
||||
This function assumes that nothing else is printed to the console in the
|
||||
interim.
|
||||
"""
|
||||
if prefix is None:
|
||||
prefix = ''
|
||||
if suffix is None:
|
||||
suffix = ''
|
||||
format_str = '{0:.' + str(decs) + 'f}'
|
||||
percents = format_str.format(100 * (iteration / float(total)))
|
||||
filled_length = int(round(length * iteration / float(total)))
|
||||
bar = '█' * filled_length + '-' * (length - filled_length)
|
||||
prefix, suffix = prefix.strip(), suffix.strip()
|
||||
sys.stdout.write('\r%s |%s| %s%s %s' % (prefix, bar, percents, '%', suffix))
|
||||
sys.stdout.flush()
|
||||
if iteration == total:
|
||||
sys.stdout.write('\n')
|
||||
sys.stdout.flush()
|
||||
|
||||
|
||||
def flash_progress_callback(action, progress_string, percentage):
|
||||
"""Callback that can be used with ``JLink.flash()``.
|
||||
|
||||
This callback generates a progress bar in the console to show the progress
|
||||
of each of the steps of the flash.
|
||||
|
||||
Args:
|
||||
action (str): the current action being invoked
|
||||
progress_string (str): the current step in the progress
|
||||
percentage (int): the percent to which the current step has been done
|
||||
|
||||
Returns:
|
||||
``None``
|
||||
|
||||
Note:
|
||||
This function ignores the compare action.
|
||||
"""
|
||||
if action.lower() != 'compare':
|
||||
return progress_bar((min(100, percentage)), 100, prefix=action)
|
||||
|
||||
|
||||
def calculate_parity(n):
|
||||
"""Calculates and returns the parity of a number.
|
||||
|
||||
The parity of a number is ``1`` if the number has an odd number of ones
|
||||
in its binary representation, otherwise ``0``.
|
||||
|
||||
Args:
|
||||
n (int): the number whose parity to calculate
|
||||
|
||||
Returns:
|
||||
``1`` if the number has an odd number of ones, otherwise ``0``.
|
||||
|
||||
Raises:
|
||||
ValueError: if ``n`` is less than ``0``.
|
||||
"""
|
||||
if not is_natural(n):
|
||||
raise ValueError('Expected n to be a positive integer.')
|
||||
y = 0
|
||||
n = abs(n)
|
||||
while n:
|
||||
y += n & 1
|
||||
n = n >> 1
|
||||
|
||||
return y & 1
|
||||
# okay decompiling ./pylink/util.pyc
|
1
requirements.txt
Normal file
1
requirements.txt
Normal file
|
@ -0,0 +1 @@
|
|||
psutil==5.9.5
|
Loading…
Reference in New Issue
Block a user