mirror of
https://github.com/DarkFlippers/unleashed-firmware.git
synced 2024-12-24 22:07:14 +03:00
c3ececcf96
* ufbt: added "dolphin_ext" target (expects "external" subfolder in cwd with dolphin assets); cleaned up unused code * ufbt: codestyle fixes * scripts: fixed style according to ruff linter * scripts: additional cleanup & codestyle fixes * github: pass target hw code when installing local SDK with ufbt * ufbt: added error message for missing folder in dolphin builder * scripts: more linter fixes * sdk: added flipper_format_stream; ufbt: support for --extra-define * fbt: reduced amount of global defines * scripts, fbt: rearranged imports Co-authored-by: Aleksandr Kutuzov <alleteam@gmail.com>
104 lines
3.0 KiB
Python
104 lines
3.0 KiB
Python
import logging
|
|
import subprocess
|
|
|
|
|
|
class CubeProgrammer:
|
|
"""STM32 Cube Programmer cli wrapper"""
|
|
|
|
def __init__(self, config={}):
|
|
assert isinstance(config, dict)
|
|
# Params base
|
|
self.params = []
|
|
# Connect params
|
|
connect = []
|
|
if "port" in config and config["port"]:
|
|
connect.append(f"port={config['port']}")
|
|
else:
|
|
connect.append("port=swd")
|
|
if "serial" in config and config["serial"]:
|
|
connect.append(f"sn={config['serial']}")
|
|
self.params.append("-c " + " ".join(connect))
|
|
# Other params
|
|
if "params" in config:
|
|
self.params += config["params"]
|
|
# logging
|
|
self.logger = logging.getLogger()
|
|
|
|
def _execute(self, args):
|
|
try:
|
|
params = [
|
|
"STM32_Programmer_CLI",
|
|
"-q",
|
|
*self.params,
|
|
*args,
|
|
]
|
|
self.logger.debug(f"_execute: {params}")
|
|
output = subprocess.check_output(params)
|
|
except subprocess.CalledProcessError as e:
|
|
if e.output:
|
|
print("Process output:\n", e.output.decode())
|
|
print("Process return code:", e.returncode)
|
|
raise e
|
|
assert output
|
|
return output.decode()
|
|
|
|
def getVersion(self):
|
|
self._execute(["--version"])
|
|
|
|
def checkOptionBytes(self, option_bytes):
|
|
output = self._execute(["-ob displ"])
|
|
ob_correct = True
|
|
for line in output.split("\n"):
|
|
line = line.strip()
|
|
if ":" not in line:
|
|
self.logger.debug(f"Skipping line: {line}")
|
|
continue
|
|
key, data = line.split(":", 1)
|
|
key = key.strip()
|
|
data = data.strip()
|
|
if key not in option_bytes.keys():
|
|
self.logger.debug(f"Skipping key: {key}")
|
|
continue
|
|
self.logger.debug(f"Processing key: {key} {data}")
|
|
value, comment = data.split(" ", 1)
|
|
value = value.strip()
|
|
comment = comment.strip()
|
|
if option_bytes[key][0] != value:
|
|
self.logger.error(
|
|
f"Invalid OB: {key} {value}, expected: {option_bytes[key][0]}"
|
|
)
|
|
ob_correct = False
|
|
return ob_correct
|
|
|
|
def setOptionBytes(self, option_bytes):
|
|
options = []
|
|
for key, (value, attr) in option_bytes.items():
|
|
if "w" in attr:
|
|
options.append(f"{key}={value}")
|
|
self._execute(["-ob", *options])
|
|
return True
|
|
|
|
def flashBin(self, address, filename):
|
|
self._execute(
|
|
[
|
|
"-d",
|
|
filename,
|
|
f"{address}",
|
|
]
|
|
)
|
|
|
|
def flashCore2(self, address, filename):
|
|
self._execute(
|
|
[
|
|
"-fwupgrade",
|
|
filename,
|
|
f"{address}",
|
|
]
|
|
)
|
|
|
|
def deleteCore2RadioStack(self):
|
|
self._execute(["-fwdelete"])
|
|
|
|
def resetTarget(self):
|
|
self._execute([])
|