From e960af1cb1b0593784fbaf4de9b5f26fa2ab8216 Mon Sep 17 00:00:00 2001 From: Yangbo Lu Date: Fri, 9 May 2025 13:57:16 +0800 Subject: [PATCH] scripts: west_commands: runners: add nxp spsdk Added nxp spsdk as west runner. Secure Provisioning SDK (SPSDK) is a unified, reliable, and easy to use Python SDK library working across the NXP MCU portfolio providing a strong foundation from quick customer prototyping up to production deployment. Docs: https://spsdk.readthedocs.io Signed-off-by: Yangbo Lu Signed-off-by: Jiafei Pan --- scripts/west_commands/runners/__init__.py | 1 + scripts/west_commands/runners/spsdk.py | 131 ++++++++++++++++++++ scripts/west_commands/tests/test_imports.py | 1 + 3 files changed, 133 insertions(+) create mode 100644 scripts/west_commands/runners/spsdk.py diff --git a/scripts/west_commands/runners/__init__.py b/scripts/west_commands/runners/__init__.py index 2cb6073f51a..4c0d7c90ed8 100644 --- a/scripts/west_commands/runners/__init__.py +++ b/scripts/west_commands/runners/__init__.py @@ -58,6 +58,7 @@ _names = [ 'rfp', 'silabs_commander', 'spi_burn', + 'spsdk', 'stm32cubeprogrammer', 'stm32flash', 'sy1xx', diff --git a/scripts/west_commands/runners/spsdk.py b/scripts/west_commands/runners/spsdk.py new file mode 100644 index 00000000000..53a5b313839 --- /dev/null +++ b/scripts/west_commands/runners/spsdk.py @@ -0,0 +1,131 @@ +# Copyright 2025 NXP +# +# SPDX-License-Identifier: Apache-2.0 + +'''Runner for flashing with SPSDK.''' + +import logging +import os +import subprocess +from pathlib import Path + +from runners.core import RunnerCaps, ZephyrBinaryRunner + + +class SPSDKBinaryRunner(ZephyrBinaryRunner): + '''Runner front-end for SPSDK.''' + + def __init__( + self, + cfg, + dev_id, + bootdevice=None, + family=None, + bootloader=None, + flashbin=None, + containers=None, + commander=None, + ): + super().__init__(cfg) + self.dev_id = dev_id + self.file = cfg.file + self.file_type = cfg.file_type + self.hex_name = cfg.hex_file + self.bin_name = cfg.bin_file + self.elf_name = cfg.elf_file + + self.bootdevice = bootdevice + self.family = family + self.bootloader = bootloader + self.flashbin = flashbin + self.containers = containers + self.commander = commander + + @classmethod + def name(cls): + return 'spsdk' + + @classmethod + def capabilities(cls): + return RunnerCaps(commands={'flash'}, dev_id=True) + + @classmethod + def dev_id_help(cls) -> str: + return 'SPSDK serial number for the board.' + + @classmethod + def do_add_parser(cls, parser): + parser.add_argument('--bootdevice', default='spl', help='boot device') + parser.add_argument('--family', required=True, help='family') + parser.add_argument('--bootloader', required=True, help='bootloader') + parser.add_argument('--flashbin', required=True, help='nxp container image flash.bin') + parser.add_argument( + '--containers', required=True, help='container count in flash.bin: one or two' + ) + parser.add_argument( + '--commander', + default='nxpuuu', + help="SPSDK Commander, default is nxpuuu", + ) + + @classmethod + def do_create(cls, cfg, args): + return SPSDKBinaryRunner( + cfg, + bootdevice=args.bootdevice, + family=args.family, + bootloader=args.bootloader, + flashbin=args.flashbin, + containers=args.containers, + commander=args.commander, + dev_id=args.dev_id, + ) + + def do_run(self, command, **kwargs): + self.commander = os.fspath(Path(self.require(self.commander)).resolve()) + + if command == 'flash': + self.flash(**kwargs) + + def flash(self, **kwargs): + self.logger.info(f"Flashing file: {self.flashbin}") + + kwargs = {} + if not self.logger.isEnabledFor(logging.DEBUG): + kwargs['stdout'] = subprocess.DEVNULL + + if self.dev_id: + cmd_with_id = [self.commander] + [(f'-us={self.dev_id}' if self.dev_id else '')] + else: + cmd_with_id = [self.commander] + if self.bootdevice == 'spl': + if self.containers == 'one': + cmd = cmd_with_id + ['run'] + [f"SDPS[-t 10000]: boot -f {self.flashbin}"] + self.logger.info(f"Command: {cmd}") + self.check_call(cmd, **kwargs) + elif self.containers == 'two': + cmd = cmd_with_id + ['run'] + [f"SDPS[-t 10000]: boot -f {self.flashbin}"] + self.logger.info(f"Command: {cmd}") + self.check_call(cmd, **kwargs) + cmd = cmd_with_id + ['run'] + ["SDPV: delay 1000"] + self.logger.info(f"Command: {cmd}") + self.check_call(cmd, **kwargs) + cmd = cmd_with_id + ['run'] + [f"SDPV: write -f {self.flashbin} -skipspl"] + self.logger.info(f"Command: {cmd}") + self.check_call(cmd, **kwargs) + cmd = cmd_with_id + ['run'] + ["SDPV: jump"] + self.logger.info(f"Command: {cmd}") + self.check_call(cmd, **kwargs) + else: + raise ValueError(f"Invalid containers count: {self.containers}") + else: + cmd = ( + [self.commander] + + ['write'] + + ['-b', f'{self.bootdevice}'] + + ['-f', f'{self.family}'] + + [f'{self.bootloader}'] + + [f'{self.flashbin}'] + ) + self.logger.info(f"Command: {cmd}") + self.check_call(cmd, **kwargs) diff --git a/scripts/west_commands/tests/test_imports.py b/scripts/west_commands/tests/test_imports.py index 6def98afa04..3be15e8d7b9 100644 --- a/scripts/west_commands/tests/test_imports.py +++ b/scripts/west_commands/tests/test_imports.py @@ -49,6 +49,7 @@ def test_runner_imports(): 'rfp', 'silabs_commander', 'spi_burn', + 'spsdk', 'stm32cubeprogrammer', 'stm32flash', 'sy1xx',