scripts: runner: generalize commands to "capabilities"
Some configuration options or device tree nodes affect the way that runners ought to behave, but there's no good way for them to report whether they can handle them. One motivating example is CONFIG_FLASH_LOAD_OFFSET, as influenced by the zephyr,code-partition chosen node in the DT for architectures where CONFIG_HAS_FLASH_LOAD_OFFSET=y. If CONFIG_FLASH_LOAD_OFFSET is nonzero, the 'flash' command ought to place the kernel at that address offset from the device flash's start address. Runners don't support this right now, which should be fixed. However, we don't want to mandate support for this feature, since not all targets need it. We need to let runners declare what their capabilities are. Make it so by adding a RunnerCaps class to the runner core. This currently just states which commands a runner can handle, but can be generalized to implement the above use case. Signed-off-by: Marti Bolivar <marti@opensourcefoundries.com>
This commit is contained in:
parent
e33ec242fd
commit
cd8d43b1c9
7 changed files with 42 additions and 27 deletions
|
@ -8,7 +8,7 @@ from os import path
|
||||||
import os
|
import os
|
||||||
import platform
|
import platform
|
||||||
|
|
||||||
from .core import ZephyrBinaryRunner, get_env_or_bail
|
from .core import ZephyrBinaryRunner, RunnerCaps, get_env_or_bail
|
||||||
|
|
||||||
DEFAULT_BOSSAC_PORT = '/dev/ttyACM0'
|
DEFAULT_BOSSAC_PORT = '/dev/ttyACM0'
|
||||||
|
|
||||||
|
@ -28,8 +28,8 @@ class BossacBinaryRunner(ZephyrBinaryRunner):
|
||||||
return 'bossac'
|
return 'bossac'
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def handles_command(cls, command):
|
def capabilities(cls):
|
||||||
return command == 'flash'
|
return RunnerCaps(commands={'flash'})
|
||||||
|
|
||||||
def create_from_env(command, debug):
|
def create_from_env(command, debug):
|
||||||
'''Create flasher from environment.
|
'''Create flasher from environment.
|
||||||
|
|
|
@ -143,6 +143,17 @@ class NetworkPortHelper:
|
||||||
return {int(b) for b in used_bytes}
|
return {int(b) for b in used_bytes}
|
||||||
|
|
||||||
|
|
||||||
|
class RunnerCaps:
|
||||||
|
'''This class represents a runner class's capabilities.
|
||||||
|
|
||||||
|
The most basic capability is the set of supported commands,
|
||||||
|
available in the commands field. This defaults to all three
|
||||||
|
commands.'''
|
||||||
|
|
||||||
|
def __init__(self, commands={'flash', 'debug', 'debugserver'}):
|
||||||
|
self.commands = commands
|
||||||
|
|
||||||
|
|
||||||
class ZephyrBinaryRunner(abc.ABC):
|
class ZephyrBinaryRunner(abc.ABC):
|
||||||
'''Abstract superclass for binary runners (flashers, debuggers).
|
'''Abstract superclass for binary runners (flashers, debuggers).
|
||||||
|
|
||||||
|
@ -184,7 +195,7 @@ class ZephyrBinaryRunner(abc.ABC):
|
||||||
|
|
||||||
1. Define a ZephyrBinaryRunner subclass, and implement its
|
1. Define a ZephyrBinaryRunner subclass, and implement its
|
||||||
abstract methods. Override any methods you need to, especially
|
abstract methods. Override any methods you need to, especially
|
||||||
handles_command().
|
capabilities().
|
||||||
|
|
||||||
2. Make sure the Python module defining your runner class is
|
2. Make sure the Python module defining your runner class is
|
||||||
imported by this package's __init__.py (otherwise,
|
imported by this package's __init__.py (otherwise,
|
||||||
|
@ -229,7 +240,8 @@ class ZephyrBinaryRunner(abc.ABC):
|
||||||
else:
|
else:
|
||||||
raise ValueError('no runner named {} is known'.format(runner_name))
|
raise ValueError('no runner named {} is known'.format(runner_name))
|
||||||
|
|
||||||
if not cls.handles_command(command):
|
caps = cls.capabilities()
|
||||||
|
if command not in caps.commands:
|
||||||
raise ValueError('runner {} does not implement command {}'.format(
|
raise ValueError('runner {} does not implement command {}'.format(
|
||||||
runner_name, command))
|
runner_name, command))
|
||||||
|
|
||||||
|
@ -246,13 +258,15 @@ class ZephyrBinaryRunner(abc.ABC):
|
||||||
etc.).'''
|
etc.).'''
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def handles_command(cls, command):
|
def capabilities(cls):
|
||||||
'''Return True iff this class can run the given command.
|
'''Returns a RunnerCaps representing this runner's capabilities.
|
||||||
|
|
||||||
The default implementation returns True if the command is
|
This implementation returns the default capabilities, which
|
||||||
valid (i.e. is one of "flash", "debug", and "debugserver").
|
includes support for all three commands, but no other special
|
||||||
Subclasses should override if they only provide a subset.'''
|
powers.
|
||||||
return command in {'flash', 'debug', 'debugserver'}
|
|
||||||
|
Subclasses should override appropriately if needed.'''
|
||||||
|
return RunnerCaps()
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
@abc.abstractmethod
|
@abc.abstractmethod
|
||||||
|
@ -263,7 +277,8 @@ class ZephyrBinaryRunner(abc.ABC):
|
||||||
'''Runs command ('flash', 'debug', 'debugserver').
|
'''Runs command ('flash', 'debug', 'debugserver').
|
||||||
|
|
||||||
This is the main entry point to this runner.'''
|
This is the main entry point to this runner.'''
|
||||||
if not self.handles_command(command):
|
caps = self.capabilities()
|
||||||
|
if command not in caps.commands:
|
||||||
raise ValueError('runner {} does not implement command {}'.format(
|
raise ValueError('runner {} does not implement command {}'.format(
|
||||||
self.name(), command))
|
self.name(), command))
|
||||||
self.do_run(command, **kwargs)
|
self.do_run(command, **kwargs)
|
||||||
|
|
|
@ -8,7 +8,7 @@ import os
|
||||||
import sys
|
import sys
|
||||||
import time
|
import time
|
||||||
|
|
||||||
from .core import ZephyrBinaryRunner, get_env_or_bail
|
from .core import ZephyrBinaryRunner, RunnerCaps, get_env_or_bail
|
||||||
|
|
||||||
|
|
||||||
class DfuUtilBinaryRunner(ZephyrBinaryRunner):
|
class DfuUtilBinaryRunner(ZephyrBinaryRunner):
|
||||||
|
@ -30,8 +30,8 @@ class DfuUtilBinaryRunner(ZephyrBinaryRunner):
|
||||||
return 'dfu-util'
|
return 'dfu-util'
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def handles_command(cls, command):
|
def capabilities(cls):
|
||||||
return command == 'flash'
|
return RunnerCaps(commands={'flash'})
|
||||||
|
|
||||||
def create_from_env(command, debug):
|
def create_from_env(command, debug):
|
||||||
'''Create flasher from environment.
|
'''Create flasher from environment.
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
from os import path
|
from os import path
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from .core import ZephyrBinaryRunner, get_env_or_bail
|
from .core import ZephyrBinaryRunner, RunnerCaps, get_env_or_bail
|
||||||
|
|
||||||
|
|
||||||
class Esp32BinaryRunner(ZephyrBinaryRunner):
|
class Esp32BinaryRunner(ZephyrBinaryRunner):
|
||||||
|
@ -30,8 +30,8 @@ class Esp32BinaryRunner(ZephyrBinaryRunner):
|
||||||
return 'esp32'
|
return 'esp32'
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def handles_command(cls, command):
|
def capabilities(cls):
|
||||||
return command == 'flash'
|
return RunnerCaps(commands={'flash'})
|
||||||
|
|
||||||
def create_from_env(command, debug):
|
def create_from_env(command, debug):
|
||||||
'''Create flasher from environment.
|
'''Create flasher from environment.
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
from os import path
|
from os import path
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from .core import ZephyrBinaryRunner, get_env_or_bail
|
from .core import ZephyrBinaryRunner, RunnerCaps, get_env_or_bail
|
||||||
|
|
||||||
DEFAULT_JLINK_GDB_PORT = 2331
|
DEFAULT_JLINK_GDB_PORT = 2331
|
||||||
|
|
||||||
|
@ -33,8 +33,8 @@ class JLinkBinaryRunner(ZephyrBinaryRunner):
|
||||||
return 'jlink'
|
return 'jlink'
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def handles_command(cls, command):
|
def capabilities(cls):
|
||||||
return command in {'debug', 'debugserver'}
|
return RunnerCaps(commands={'debug', 'debugserver'})
|
||||||
|
|
||||||
def create_from_env(command, debug):
|
def create_from_env(command, debug):
|
||||||
'''Create runner from environment.
|
'''Create runner from environment.
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
from os import path
|
from os import path
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
from .core import ZephyrBinaryRunner, get_env_or_bail
|
from .core import ZephyrBinaryRunner, RunnerCaps, get_env_or_bail
|
||||||
|
|
||||||
|
|
||||||
class NrfJprogBinaryRunner(ZephyrBinaryRunner):
|
class NrfJprogBinaryRunner(ZephyrBinaryRunner):
|
||||||
|
@ -23,8 +23,8 @@ class NrfJprogBinaryRunner(ZephyrBinaryRunner):
|
||||||
return 'nrfjprog'
|
return 'nrfjprog'
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def handles_command(cls, command):
|
def capabilities(cls):
|
||||||
return command == 'flash'
|
return RunnerCaps(commands={'flash'})
|
||||||
|
|
||||||
def create_from_env(command, debug):
|
def create_from_env(command, debug):
|
||||||
'''Create flasher from environment.
|
'''Create flasher from environment.
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
from os import path
|
from os import path
|
||||||
|
|
||||||
from .core import ZephyrBinaryRunner, get_env_or_bail
|
from .core import ZephyrBinaryRunner, RunnerCaps, get_env_or_bail
|
||||||
|
|
||||||
|
|
||||||
class XtensaBinaryRunner(ZephyrBinaryRunner):
|
class XtensaBinaryRunner(ZephyrBinaryRunner):
|
||||||
|
@ -22,8 +22,8 @@ class XtensaBinaryRunner(ZephyrBinaryRunner):
|
||||||
return 'xtensa'
|
return 'xtensa'
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def handles_command(cls, command):
|
def capabilities(cls):
|
||||||
return command == 'debug'
|
return RunnerCaps(commands={'debug'})
|
||||||
|
|
||||||
def create_from_env(command, debug):
|
def create_from_env(command, debug):
|
||||||
'''Create runner from environment.
|
'''Create runner from environment.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue