Skip to content

Commit e960af1

Browse files
yangbolu1991dkalowsk
authored andcommitted
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 <yangbo.lu@nxp.com> Signed-off-by: Jiafei Pan <Jiafei.Pan@nxp.com>
1 parent 497c027 commit e960af1

File tree

3 files changed

+133
-0
lines changed

3 files changed

+133
-0
lines changed

scripts/west_commands/runners/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ def _import_runner_module(runner_name):
5858
'rfp',
5959
'silabs_commander',
6060
'spi_burn',
61+
'spsdk',
6162
'stm32cubeprogrammer',
6263
'stm32flash',
6364
'sy1xx',
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
# Copyright 2025 NXP
2+
#
3+
# SPDX-License-Identifier: Apache-2.0
4+
5+
'''Runner for flashing with SPSDK.'''
6+
7+
import logging
8+
import os
9+
import subprocess
10+
from pathlib import Path
11+
12+
from runners.core import RunnerCaps, ZephyrBinaryRunner
13+
14+
15+
class SPSDKBinaryRunner(ZephyrBinaryRunner):
16+
'''Runner front-end for SPSDK.'''
17+
18+
def __init__(
19+
self,
20+
cfg,
21+
dev_id,
22+
bootdevice=None,
23+
family=None,
24+
bootloader=None,
25+
flashbin=None,
26+
containers=None,
27+
commander=None,
28+
):
29+
super().__init__(cfg)
30+
self.dev_id = dev_id
31+
self.file = cfg.file
32+
self.file_type = cfg.file_type
33+
self.hex_name = cfg.hex_file
34+
self.bin_name = cfg.bin_file
35+
self.elf_name = cfg.elf_file
36+
37+
self.bootdevice = bootdevice
38+
self.family = family
39+
self.bootloader = bootloader
40+
self.flashbin = flashbin
41+
self.containers = containers
42+
self.commander = commander
43+
44+
@classmethod
45+
def name(cls):
46+
return 'spsdk'
47+
48+
@classmethod
49+
def capabilities(cls):
50+
return RunnerCaps(commands={'flash'}, dev_id=True)
51+
52+
@classmethod
53+
def dev_id_help(cls) -> str:
54+
return 'SPSDK serial number for the board.'
55+
56+
@classmethod
57+
def do_add_parser(cls, parser):
58+
parser.add_argument('--bootdevice', default='spl', help='boot device')
59+
parser.add_argument('--family', required=True, help='family')
60+
parser.add_argument('--bootloader', required=True, help='bootloader')
61+
parser.add_argument('--flashbin', required=True, help='nxp container image flash.bin')
62+
parser.add_argument(
63+
'--containers', required=True, help='container count in flash.bin: one or two'
64+
)
65+
parser.add_argument(
66+
'--commander',
67+
default='nxpuuu',
68+
help="SPSDK Commander, default is nxpuuu",
69+
)
70+
71+
@classmethod
72+
def do_create(cls, cfg, args):
73+
return SPSDKBinaryRunner(
74+
cfg,
75+
bootdevice=args.bootdevice,
76+
family=args.family,
77+
bootloader=args.bootloader,
78+
flashbin=args.flashbin,
79+
containers=args.containers,
80+
commander=args.commander,
81+
dev_id=args.dev_id,
82+
)
83+
84+
def do_run(self, command, **kwargs):
85+
self.commander = os.fspath(Path(self.require(self.commander)).resolve())
86+
87+
if command == 'flash':
88+
self.flash(**kwargs)
89+
90+
def flash(self, **kwargs):
91+
self.logger.info(f"Flashing file: {self.flashbin}")
92+
93+
kwargs = {}
94+
if not self.logger.isEnabledFor(logging.DEBUG):
95+
kwargs['stdout'] = subprocess.DEVNULL
96+
97+
if self.dev_id:
98+
cmd_with_id = [self.commander] + [(f'-us={self.dev_id}' if self.dev_id else '')]
99+
else:
100+
cmd_with_id = [self.commander]
101+
if self.bootdevice == 'spl':
102+
if self.containers == 'one':
103+
cmd = cmd_with_id + ['run'] + [f"SDPS[-t 10000]: boot -f {self.flashbin}"]
104+
self.logger.info(f"Command: {cmd}")
105+
self.check_call(cmd, **kwargs)
106+
elif self.containers == 'two':
107+
cmd = cmd_with_id + ['run'] + [f"SDPS[-t 10000]: boot -f {self.flashbin}"]
108+
self.logger.info(f"Command: {cmd}")
109+
self.check_call(cmd, **kwargs)
110+
cmd = cmd_with_id + ['run'] + ["SDPV: delay 1000"]
111+
self.logger.info(f"Command: {cmd}")
112+
self.check_call(cmd, **kwargs)
113+
cmd = cmd_with_id + ['run'] + [f"SDPV: write -f {self.flashbin} -skipspl"]
114+
self.logger.info(f"Command: {cmd}")
115+
self.check_call(cmd, **kwargs)
116+
cmd = cmd_with_id + ['run'] + ["SDPV: jump"]
117+
self.logger.info(f"Command: {cmd}")
118+
self.check_call(cmd, **kwargs)
119+
else:
120+
raise ValueError(f"Invalid containers count: {self.containers}")
121+
else:
122+
cmd = (
123+
[self.commander]
124+
+ ['write']
125+
+ ['-b', f'{self.bootdevice}']
126+
+ ['-f', f'{self.family}']
127+
+ [f'{self.bootloader}']
128+
+ [f'{self.flashbin}']
129+
)
130+
self.logger.info(f"Command: {cmd}")
131+
self.check_call(cmd, **kwargs)

scripts/west_commands/tests/test_imports.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ def test_runner_imports():
4949
'rfp',
5050
'silabs_commander',
5151
'spi_burn',
52+
'spsdk',
5253
'stm32cubeprogrammer',
5354
'stm32flash',
5455
'sy1xx',

0 commit comments

Comments
 (0)