diff --git a/boards/common/sp_artemis.board.cmake b/boards/common/sp_artemis.board.cmake new file mode 100644 index 0000000000000..7708e4815870e --- /dev/null +++ b/boards/common/sp_artemis.board.cmake @@ -0,0 +1,2 @@ +board_set_flasher_ifnset(sp_artemis) +board_finalize_runner_args(sp_artemis) diff --git a/boards/sparkfun/artemis_nano.dtsi b/boards/sparkfun/artemis_nano.dtsi new file mode 100644 index 0000000000000..e74b40068d073 --- /dev/null +++ b/boards/sparkfun/artemis_nano.dtsi @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2023 Ambiq Micro Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + #include + #include "apollo3_evb_connector.dtsi" + + &pinctrl { + uart0_default: uart0_default { + group1 { + pinmux = ; + }; + group2 { + pinmux = ; + input-enable; + }; + }; + i2c0_default: i2c0_default { + group1 { + pinmux = , ; + drive-open-drain; + drive-strength = "0.5"; + bias-pull-up; + }; + }; + i2c1_default: i2c1_default { + group1 { + pinmux = , ; + drive-open-drain; + drive-strength = "0.5"; + bias-pull-up; + }; + }; + i2c2_default: i2c2_default { + group1 { + pinmux = , ; + drive-open-drain; + drive-strength = "0.5"; + bias-pull-up; + }; + }; + i2c3_default: i2c3_default { + group1 { + pinmux = , ; + drive-open-drain; + drive-strength = "0.5"; + bias-pull-up; + }; + }; + i2c4_default: i2c4_default { + group1 { + pinmux = , ; + drive-open-drain; + drive-strength = "0.5"; + bias-pull-up; + }; + }; + i2c5_default: i2c5_default { + group1 { + pinmux = , ; + drive-open-drain; + drive-strength = "0.5"; + bias-pull-up; + }; + }; + + spi0_default: spi0_default { + group1 { + pinmux = , , ; + }; + }; + spi1_default: spi1_default { + group1 { + pinmux = , , ; + }; + }; + spi2_default: spi2_default { + group1 { + pinmux = , , ; + }; + }; + spi3_default: spi3_default { + group1 { + pinmux = , , ; + }; + }; + spi4_default: spi4_default { + group1 { + pinmux = , , ; + }; + }; + spi5_default: spi5_default { + group1 { + pinmux = , , ; + }; + }; + + adc0_default: adc0_default{ + group1 { + pinmux = , ; + drive-strength = "0.1"; + }; + }; + + mspi0_default: mspi0_default{ + group1 { + pinmux = , + , + , + , + ; + }; + group2 { + pinmux = ; + drive-push-pull; + drive-strength = "0.5"; + ambiq,iom-nce-module = <0>; + ambiq,iom-num = <6>; + }; + }; + + bleif_default: bleif_default{ + group1 { + pinmux = , + , + , + , + , + ; + }; + }; + }; diff --git a/boards/sparkfun/artemis_nano/Kconfig.artemis_nano b/boards/sparkfun/artemis_nano/Kconfig.artemis_nano new file mode 100644 index 0000000000000..c21cb3ed7c27c --- /dev/null +++ b/boards/sparkfun/artemis_nano/Kconfig.artemis_nano @@ -0,0 +1,13 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright (c) 2024 Ali Sarlak + + +if BOARD_ARTEMIS_NANO + +config BOARD_ARTEMIS_NANO + select SOC_APOLLO3_BLUE + +config SYS_CLOCK_HW_CYCLES_PER_SEC + default 32768 if AMBIQ_STIMER_TIMER + +endif # BOARD_ARTEMIS_NANO diff --git a/boards/sparkfun/artemis_nano/Kconfig.defconfig b/boards/sparkfun/artemis_nano/Kconfig.defconfig new file mode 100644 index 0000000000000..04caf23509b2f --- /dev/null +++ b/boards/sparkfun/artemis_nano/Kconfig.defconfig @@ -0,0 +1,11 @@ +# Sparkfun artemis_nano board configuration + +# Copyright (c) 2024 Ali Sarlak +# SPDX-License-Identifier: Apache-2.0 + +if BOARD_ARTEMIS_NANO + +config FLASH_BASE_ADDRESS + default 0x10000 + +endif diff --git a/boards/sparkfun/artemis_nano/artemis_nano-pinctrl.dtsi b/boards/sparkfun/artemis_nano/artemis_nano-pinctrl.dtsi new file mode 100644 index 0000000000000..6aca8895451a5 --- /dev/null +++ b/boards/sparkfun/artemis_nano/artemis_nano-pinctrl.dtsi @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2024 Ali Sarlak + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "artemis_nano_connector.dtsi" + +&pinctrl { + uart1_default: uart1_default { + group1 { + pinmux = ; + }; + group2 { + pinmux = ; + input-enable; + }; + }; + itm_default: itm_default { + group1 { + pinmux = ; + }; + }; + i2c0_default: i2c0_default { + group1 { + pinmux = , ; + drive-open-drain; + drive-strength = "0.5"; + bias-pull-up; + }; + }; + i2c1_default: i2c1_default { + group1 { + pinmux = , ; + drive-open-drain; + drive-strength = "0.5"; + bias-pull-up; + }; + }; + i2c2_default: i2c2_default { + group1 { + pinmux = , ; + drive-open-drain; + drive-strength = "0.5"; + bias-pull-up; + }; + }; + i2c3_default: i2c3_default { + group1 { + pinmux = , ; + drive-open-drain; + drive-strength = "0.5"; + bias-pull-up; + }; + }; + i2c4_default: i2c4_default { + group1 { + pinmux = , ; + drive-open-drain; + drive-strength = "0.5"; + bias-pull-up; + }; + }; + i2c5_default: i2c5_default { + group1 { + pinmux = , ; + drive-open-drain; + drive-strength = "0.5"; + bias-pull-up; + }; + }; + spid0_default: spid0_default { + group1 { + pinmux = , , , ; + }; + }; + spi0_default: spi0_default { + group1 { + pinmux = , , ; + }; + }; + spi1_default: spi1_default { + group1 { + pinmux = , , ; + }; + }; + + spi3_default: spi3_default { + group1 { + pinmux = , , ; + }; + }; + + spi5_default: spi5_default { + group1 { + pinmux = , , ; + }; + }; + + adc0_default: adc0_default{ + group1 { + pinmux = , ; + drive-strength = "0.1"; + }; + }; + + mspi0_default: mspi0_default{ + group1 { + pinmux = , + , + , + , + ; + }; + group2 { + pinmux = ; + drive-push-pull; + drive-strength = "0.5"; + ambiq,iom-nce-module = <0>; + ambiq,iom-num = <6>; + }; + }; + + bleif_default: bleif_default{ + group1 { + pinmux = , + , + , + , + , + ; + }; + }; +}; diff --git a/boards/sparkfun/artemis_nano/artemis_nano.dts b/boards/sparkfun/artemis_nano/artemis_nano.dts new file mode 100644 index 0000000000000..d4342b82e4788 --- /dev/null +++ b/boards/sparkfun/artemis_nano/artemis_nano.dts @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2024 Ali Sarlak + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; + +#include + +#include "artemis_nano-pinctrl.dtsi" + +/ { + model = "Sparkfun Artemis Nano"; + compatible = "ambiq,artemis_nano"; + + chosen { + zephyr,itcm = &tcm; + zephyr,sram = &sram0; + zephyr,flash = &flash0; + zephyr,console = &uart1; + zephyr,shell-uart = &uart1; + zephyr,uart-pipe = &uart1; + zephyr,flash-controller = &flash; + }; + + aliases { + watchdog0 = &wdt0; + led0 = &led0; + }; + + leds{ + compatible = "gpio-leds"; + led0: led_0 { + gpios = <&gpio0_31 19 GPIO_ACTIVE_HIGH>; + label = "USER LED"; + }; + }; +}; + +&flash0 { + erase-block-size = <8192>; + write-block-size = <4>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + /* Set 16KB of storage at the end of the 976KB of flash */ + storage_partition: partition@f0000 { + label = "storage"; + reg = <0x000f0000 0x4000>; + }; + }; +}; + +&uart1 { + current-speed = <115200>; + pinctrl-0 = <&uart1_default>; + pinctrl-names = "default"; + status = "okay"; +}; + +&stimer0 { + clk-source = <3>; +}; + +&gpio0_31 { + status = "okay"; +}; + +&i2c2 { + status = "disabled"; +}; diff --git a/boards/sparkfun/artemis_nano/artemis_nano.yaml b/boards/sparkfun/artemis_nano/artemis_nano.yaml new file mode 100644 index 0000000000000..800b3d1dde44f --- /dev/null +++ b/boards/sparkfun/artemis_nano/artemis_nano.yaml @@ -0,0 +1,17 @@ +# Artemis Nano Board Definition +identifier: artemis_nano +name: Artemis Nano +type: mcu +arch: arm +ram: 384 +flash: 976 +toolchain: + - zephyr + - gnuarmemb +supported: + - uart + - gpio +testing: + ignore_tags: + - net +vendor: sparkfun diff --git a/boards/sparkfun/artemis_nano/artemis_nano_connector.dtsi b/boards/sparkfun/artemis_nano/artemis_nano_connector.dtsi new file mode 100644 index 0000000000000..01d0631a68dc9 --- /dev/null +++ b/boards/sparkfun/artemis_nano/artemis_nano_connector.dtsi @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2024 Ali Sarlak + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + artemis_nano: connector { + compatible = "artemis_nano-header"; + #gpio-cells = <2>; + gpio-map-mask = <0xffffffff 0xffffff80>; + gpio-map-pass-thru = <0 0x7f>; + gpio-map = <0 0 &gpio0_31 0 0>, /* IOS_SPI_SCK, IOS_I2C_SCL */ + <1 0 &gpio0_31 1 0>, /* IOS_SPI_MOSI, IOS_I2C_SDA */ + <2 0 &gpio0_31 2 0>, /* IOS_SPI_MISO */ + <3 0 &gpio0_31 3 0>, /* IOS_CE */ + <4 0 &gpio0_31 4 0>, /* IOS_INT */ + <5 0 &gpio0_31 5 0>, /* SCL0/SCK0 [~11]*/ + <6 0 &gpio0_31 6 0>, /* SDA0/MISO0/I2SDAT [~13]*/ + <7 0 &gpio0_31 7 0>, /* MOSI0/CLKOUT [~12]*/ + <8 0 &gpio0_31 8 0>, /* IOM1_SPI_SCK, IOM1_I2C_SCL */ + <9 0 &gpio0_31 9 0>, /* IOM1_SPI_MISO, IOM1_I2C_SDA */ + <10 0 &gpio0_31 10 0>, /* LED0, IOM1_SPI_MOSI */ + <11 0 &gpio0_31 11 0>, /* PDMDATA [~A2] */ + <12 0 &gpio0_31 12 0>, /* PDMCLK/TX1 [~A16] */ + <13 0 &gpio0_31 13 0>, /* I2SBCLK/RX1 [~A0]*/ + <14 0 &gpio0_31 14 0>, /* LED3 */ + <15 0 &gpio0_31 15 0>, /* LED2 */ + <16 0 &gpio0_31 16 0>, /* BUTTON0 */ + <17 0 &gpio0_31 17 0>, /* x */ + <18 0 &gpio0_31 18 0>, /* CMPIN1/SCCIO [~4]*/ + <19 0 &gpio0_31 19 0>, /* ~D19/LED/1 */ + <20 0 &gpio0_31 20 0>, /* SWDCK */ + <21 0 &gpio0_31 21 0>, /* SWDIO */ + <22 0 &gpio0_31 22 0>, /* MSPI0_D0, UART0_TX */ + <23 0 &gpio0_31 23 0>, /* MSPI0_D3, UART0_RX */ + <24 0 &gpio0_31 24 0>, /* MSPI0_SCK */ + <25 0 &gpio0_31 25 0>, /* SDA2/MISO2/RX1 [~D25/SDA2/2] */ + <26 0 &gpio0_31 26 0>, /* MSPI0_D1 */ + <27 0 &gpio0_31 27 0>, /* SCL2/SCK2 [~D27/SCL2/2]*/ + <28 0 &gpio0_31 28 0>, /* MSPI0_CE0 */ + <29 0 &gpio0_31 29 0>, /* PDMDATA [~A3] */ + <30 0 &gpio0_31 30 0>, /* x */ + <31 0 &gpio0_31 31 0>, /* [~A5] */ + <32 0 &gpio32_63 0 0>, /* BLEIF_MOSI */ + <33 0 &gpio32_63 1 0>, /* BLEIF_CSN */ + <34 0 &gpio32_63 2 0>, /* IOM1_CS */ + <35 0 &gpio32_63 3 0>, /* BLEIF_STATUS [~A14]*/ + <36 0 &gpio32_63 4 0>, /* PDM_DATA [PDMDATA/2]*/ + <37 0 &gpio32_63 5 0>, /* PDM_CLK [PDMCLK/2]*/ + <38 0 &gpio32_63 6 0>, /* DISP_TE [8]*/ + <39 0 &gpio32_63 7 0>, /* DISP_PWR_EN [~9]*/ + <40 0 &gpio32_63 8 0>, /* IOM4_SPI_MISO, IOM4_I2C_SDA [10]*/ + <41 0 &gpio32_63 9 0>, /* SWO */ + <42 0 &gpio32_63 10 0>, /* IOM3_I2C_SCL [~7]*/ + <43 0 &gpio32_63 11 0>, /* IOM3_I2C_SDA [~6]*/ + <44 0 &gpio32_63 12 0>, /* IOM4_SPI_MOSI */ + <45 0 &gpio32_63 13 0>, /* DISP_2V8_EN */ + <46 0 &gpio32_63 14 0>, /* ACC_INT */ + <47 0 &gpio32_63 15 0>, /* IOM5_SPI_MOSI */ + <48 0 &gpio32_63 16 0>, /* IOM5_I2C_SCL */ + <49 0 &gpio32_63 17 0>; /* IOM5_I2C_SDA */ + }; +}; diff --git a/boards/sparkfun/artemis_nano/artemis_nano_defconfig b/boards/sparkfun/artemis_nano/artemis_nano_defconfig new file mode 100644 index 0000000000000..6a1d39db5d1ca --- /dev/null +++ b/boards/sparkfun/artemis_nano/artemis_nano_defconfig @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: Apache-2.0 +# Artemis Nano Kernel Configuration + +# Enable Console and UART +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y +CONFIG_SERIAL=y +CONFIG_UART_INTERRUPT_DRIVEN=y diff --git a/boards/sparkfun/artemis_nano/board.cmake b/boards/sparkfun/artemis_nano/board.cmake new file mode 100644 index 0000000000000..9e2525a15877c --- /dev/null +++ b/boards/sparkfun/artemis_nano/board.cmake @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: Apache-2.0 +if(BOARD STREQUAL "artemis_nano") +board_runner_args(sp_artemis "--baud-rate=115200" "--serial-port=/dev/ttyUSB0") +include(${ZEPHYR_BASE}/boards/common/sp_artemis.board.cmake) +endif() diff --git a/boards/sparkfun/artemis_nano/board.yml b/boards/sparkfun/artemis_nano/board.yml new file mode 100644 index 0000000000000..a3731ee44c041 --- /dev/null +++ b/boards/sparkfun/artemis_nano/board.yml @@ -0,0 +1,5 @@ +board: + name: artemis_nano + vendor: sparkfun + socs: + - name: apollo3_blue diff --git a/boards/sparkfun/artemis_nano/docs/index.rst b/boards/sparkfun/artemis_nano/docs/index.rst new file mode 100644 index 0000000000000..de096647ac7f3 --- /dev/null +++ b/boards/sparkfun/artemis_nano/docs/index.rst @@ -0,0 +1,88 @@ +.. _artemis_nano: + +Sparkfun Artemis Nano +###################### + +The SparkFun Artemis Nano is a versatile and user-friendly development board that utilizes + Ambiq's ultra-low power Apollo3 Blue SoC. + +.. image:: ./sparkfun_artemis_nano.webp + :align: center + :alt: Artemis Nano + +Hardware +******** + +- Apollo3 Blue SoC with up to 96 MHz operating frequency +- ARM® Cortex® M4F core +- 16 kB 2-way Associative/Direct-Mapped Cache per core +- Up to 1 MB of flash memory for code/data +- Up to 384 KB of low leakage / low power RAM for code/data +- Integrated Bluetooth 5 Low-energy controller + +For more information about the SparkFun RedBoard Artemis Nano: + +- `SparkFun RedBoard Artemis Nano`_ + +Supported Features +================== + +The Sparkfun Redboard Artemis Nano board target supports the following hardware features: + ++-----------+------------+-------------------------------------+ +| Interface | Controller | Driver/Component | ++===========+============+=====================================+ +| MPU | on-chip | memory protection unit | ++-----------+------------+-------------------------------------+ +| NVIC | on-chip | nested vector interrupt controller | ++-----------+------------+-------------------------------------+ +| SYSTICK | on-chip | systick | ++-----------+------------+-------------------------------------+ +| STIMER | on-chip | stimer | ++-----------+------------+-------------------------------------+ +| GPIO | on-chip | gpio | ++-----------+------------+-------------------------------------+ +| UART | on-chip | serial | ++-----------+------------+-------------------------------------+ +| WDT | on-chip | watchdog | ++-----------+------------+-------------------------------------+ +| RADIO | on-chip | bluetooth | ++-----------+------------+-------------------------------------+ + +The default configuration can be found in the defconfig file: +``boards/sparkfun/artemis_nano/artemis_nano_defconfig``. + +Programming and Debugging +========================= + +Flashing an application +----------------------- + +Connect your device to your host computer using the USB-C port. +The sample application `blinky` is used for this example. +Build the Zephyr kernel and application, then flash it to the device: + +.. zephyr-app-commands:: + :zephyr-app: samples/basic/blinky + :board: artemis_nano + :goals: flash + +.. note:: + The `west flash -b artemis_nano` command requires the `SparkFun SVL bootloader`_ and a custom flash program that has been implemented for this board. To use west flash you have to add Artemis-Firmware-Upload-GUI-3.0.0/artemis_uploader to your PATH. + +After flashing the board you should see the blue LED (USER LED D19) is blinking. + +.. _SparkFun RedBoard Artemis Nano: + https://www.sparkfun.com/products/15443 + +.. _Apollo3 Blue Datasheet: + https://contentportal.ambiq.com/documents/20123/388390/Apollo3-Blue-SoC-Datasheet.pdf + +.. _SEGGER J-Link software: + https://www.segger.com/downloads/jlink + +.. _pylink: + https://github.com/Square/pylink + +.. _SparkFun SVL bootloader: + https://github.com/sparkfun/SparkFun_Artemis/tree/master diff --git a/boards/sparkfun/artemis_nano/docs/sparkfun_artemis_nano.webp b/boards/sparkfun/artemis_nano/docs/sparkfun_artemis_nano.webp new file mode 100644 index 0000000000000..a1b0bb326ffa7 Binary files /dev/null and b/boards/sparkfun/artemis_nano/docs/sparkfun_artemis_nano.webp differ diff --git a/scripts/west_commands/runners/__init__.py b/scripts/west_commands/runners/__init__.py index 5fd582fc9527e..543ec4b56625f 100644 --- a/scripts/west_commands/runners/__init__.py +++ b/scripts/west_commands/runners/__init__.py @@ -55,6 +55,7 @@ def _import_runner_module(runner_name): 'renode', 'renode-robot', 'silabs_commander', + 'sp_artemis', 'spi_burn', 'stm32cubeprogrammer', 'stm32flash', diff --git a/scripts/west_commands/runners/sp_artemis.py b/scripts/west_commands/runners/sp_artemis.py new file mode 100644 index 0000000000000..c3121558aac9f --- /dev/null +++ b/scripts/west_commands/runners/sp_artemis.py @@ -0,0 +1,135 @@ +# Copyright (c) 2017 Linaro Limited. +# +# SPDX-License-Identifier: Apache-2.0 + +"""Runner for flashing with svl""" + +import subprocess +import os +import glob +from runners.core import ZephyrBinaryRunner, RunnerCaps + + +class PortNotFoundError(Exception): + """Exception raised when no serial ports are found.""" + +class ArtemisBinaryRunner(ZephyrBinaryRunner): + """Runner for Artemis Nano.""" + + def __init__(self, cfg, serial_port, baud_rate): + super().__init__(cfg) + self.bin_file = cfg.bin_file + self.serial_port = serial_port + self.baud_rate = baud_rate + + self.svl_script = self._find_in_path("artemis_svl.py") + if self.svl_script is None: + raise FileNotFoundError("Script artemis_svl.py not found in PATH") + + @classmethod + def do_create(cls, cfg, args): + return ArtemisBinaryRunner( + cfg=cfg, serial_port=args.serial_port, baud_rate=args.baud_rate + ) + + @classmethod + def name(cls): + return "sp_artemis" + + @classmethod + def capabilities(cls): + return RunnerCaps(commands={"flash"}) + + @classmethod + def do_add_parser(cls, parser): + parser.add_argument( + "--serial-port", required=True, help="Serial port for flashing" + ) + parser.add_argument( + "--baud-rate", + type=int, + default=115200, + help="Specify the communication speed in baud (default is 115200)", + ) + + def do_run(self, command, **kwargs): + if command == "flash": + self.do_flash(**kwargs) + + def do_flash(self, **kwargs): + print("Flashing ...") + print(f"serial port is {self.serial_port}") + print(f"baud rate is {self.baud_rate}") + + if not self._does_serial_port_exist(): + print(f"{self.serial_port} not found!!!") + return + + if self.bin_file is not None: + # Check if bin file actually exists + if not os.path.isfile(self.bin_file): + err = "Cannot flash; file ({}) not found" + raise ValueError(err.format(self.bin_file)) + + # Pad the binary file to make its size divisible by 4 + self._pad_binary_file() + + # Check if artemis_svl.py exists + if not os.path.isfile(self.svl_script): + raise FileNotFoundError(f"Script {self.svl_script} not found") + + cmd = [ + "python3", + self.svl_script, + "-f", + self.bin_file, + "-b", + str(self.baud_rate), + self.serial_port, + ] + + else: + err = "Cannot flash; no bin ({}) files found." + raise ValueError(err.format(self.bin_name)) + + try: + # Run the command + result = subprocess.run(cmd, check=True, capture_output=True, text=True) + print(result.stdout) + print("Flashing successful!") + except subprocess.CalledProcessError as e: + print(f"Flashing failed with error: {e.stderr}") + + def _pad_binary_file(self): + """Padding the binary file""" + with open(self.bin_file, "rb") as f: + bin_data = f.read() + + # Pad the binary file to make its size divisible by 4 + padding = (4 - (len(bin_data) % 4)) % 4 + if padding != 0: + bin_data += b"\x00" * padding + with open(self.bin_file, "wb") as f: + f.write(bin_data) + + def _find_in_path(self, filename): + """Search for a file in all directories listed in PATH.""" + for path in os.environ["PATH"].split(os.pathsep): + full_path = os.path.join(path, filename) + if os.path.isfile(full_path) and os.access(full_path, os.X_OK): + return full_path + return None + + def _does_serial_port_exist(self): + possible_ports = glob.glob("/dev/tty[A-Za-z]*") + # Filter out the actual serial ports + serial_ports = [ + port + for port in possible_ports + if "ttyS" in port or "ttyUSB" in port or "ttyACM" in port + ] + if serial_ports: + return self.serial_port in serial_ports + else: + print("No serial ports found in /dev/ ") + return False diff --git a/scripts/west_commands/tests/test_imports.py b/scripts/west_commands/tests/test_imports.py index d47470c5a6646..ea99c476bdff8 100644 --- a/scripts/west_commands/tests/test_imports.py +++ b/scripts/west_commands/tests/test_imports.py @@ -14,46 +14,47 @@ def test_runner_imports(): # test suites. runner_names = set(r.name() for r in ZephyrBinaryRunner.get_runners()) - expected = set(( - # zephyr-keep-sorted-start - 'arc-nsim', - 'blackmagicprobe', - 'bossac', - 'canopen', - 'dediprog', - 'dfu-util', - 'esp32', - 'ezflashcli', - 'gd32isp', - 'hifive1', - 'intel_adsp', - 'intel_cyclonev', - 'jlink', - 'linkserver', - 'mdb-hw', - 'mdb-nsim', - 'minichlink', - 'misc-flasher', - 'native', - 'nios2', - 'nrfjprog', - 'nrfutil', - 'nxp_s32dbg', - 'openocd', - 'probe-rs', - 'pyocd', - 'qemu', - 'renode', - 'renode-robot', - 'silabs_commander', - 'spi_burn', - 'stm32cubeprogrammer', - 'stm32flash', - 'teensy', - 'trace32', - 'uf2', - 'xsdb', - 'xtensa', - # zephyr-keep-sorted-stop - )) + expected = set( + ( + # zephyr-keep-sorted-start + "arc-nsim", + "blackmagicprobe", + "bossac", + "canopen", + "dediprog", + "dfu-util", + "esp32", + "ezflashcli", + "gd32isp", + "hifive1", + "intel_adsp", + "intel_cyclonev", + "jlink", + "linkserver", + "mdb-hw", + "mdb-nsim", + "misc-flasher", + "native", + "nios2", + "nrfjprog", + "nrfutil", + "nxp_s32dbg", + "openocd", + "probe-rs", + "pyocd", + "qemu", + "renode", + "renode-robot", + "silabs_commander", + "sp_artemis", + "spi_burn", + "stm32cubeprogrammer", + "stm32flash", + "teensy", + "trace32", + "uf2", + "xtensa", + # zephyr-keep-sorted-stop + ) + ) assert runner_names == expected