1# Copyright (c) 2024 Google LLC.
2#
3# SPDX-License-Identifier: Apache-2.0
4
5"""WCH CH32V00x specific runner."""
6
7import argparse
8
9from runners.core import RunnerCaps, RunnerConfig, ZephyrBinaryRunner
10
11
12class MiniChLinkBinaryRunner(ZephyrBinaryRunner):
13    """Runner for CH32V00x based devices using minichlink."""
14
15    def __init__(
16        self,
17        cfg: RunnerConfig,
18        minichlink: str,
19        erase: bool,
20        reset: bool,
21        dt_flash: bool,
22        terminal: bool,
23    ):
24        super().__init__(cfg)
25
26        self.minichlink = minichlink
27        self.erase = erase
28        self.reset = reset
29        self.dt_flash = dt_flash
30        self.terminal = terminal
31
32    @classmethod
33    def name(cls):
34        return "minichlink"
35
36    @classmethod
37    def capabilities(cls) -> RunnerCaps:
38        return RunnerCaps(commands={"flash"}, flash_addr=True, erase=True, reset=True)
39
40    @classmethod
41    def do_add_parser(cls, parser: argparse.ArgumentParser):
42        parser.add_argument(
43            "--minichlink", default="minichlink", help="path to the minichlink binary"
44        )
45        parser.add_argument(
46            "--terminal",
47            default=False,
48            action=argparse.BooleanOptionalAction,
49            help="open the terminal after flashing. Implies --reset.",
50        )
51        parser.set_defaults(reset=True)
52
53    @classmethod
54    def do_create(cls, cfg: RunnerConfig, args: argparse.Namespace):
55        return MiniChLinkBinaryRunner(
56            cfg,
57            minichlink=args.minichlink,
58            erase=args.erase,
59            reset=args.reset,
60            dt_flash=(args.dt_flash == "y"),
61            terminal=args.terminal,
62        )
63
64    def do_run(self, command: str, **kwargs):
65        self.require(self.minichlink)
66
67        if command == "flash":
68            self.flash()
69        else:
70            raise ValueError("BUG: unhandled command f{command}")
71
72    def flash(self):
73        self.ensure_output("bin")
74
75        cmd = [self.minichlink, "-a"]
76
77        if self.erase:
78            cmd.append("-E")
79
80        flash_addr = 0
81        if self.dt_flash:
82            flash_addr = self.flash_address_from_build_conf(self.build_conf)
83
84        cmd.extend(["-w", self.cfg.bin_file or "", f"0x{flash_addr:x}"])
85
86        if self.reset or self.terminal:
87            cmd.append("-b")
88
89        if self.terminal:
90            cmd.append("-T")
91
92        if self.terminal:
93            self.check_call(cmd)
94        else:
95            self.check_output(cmd)
96