mirror of
https://github.com/ARM-software/devlib.git
synced 2025-01-31 02:00:45 +00:00
doc: documenting Platforms and Modules
Adding documentation for Platforms and Modules API.
This commit is contained in:
parent
b3cea0c0d2
commit
1ba7fbdc9a
@ -19,6 +19,7 @@ Contents:
|
||||
target
|
||||
modules
|
||||
instrumentation
|
||||
platform
|
||||
connection
|
||||
|
||||
Indices and tables
|
||||
|
196
doc/modules.rst
196
doc/modules.rst
@ -1,3 +1,5 @@
|
||||
.. _modules:
|
||||
|
||||
Modules
|
||||
=======
|
||||
|
||||
@ -64,7 +66,7 @@ policies (governors). The ``devlib`` module exposes the following interface
|
||||
:param cpu: The cpu; could be a numeric or the corresponding string (e.g.
|
||||
``1`` or ``"cpu1"``).
|
||||
|
||||
.. method:: target.cpufreq.set_governor(cpu, governor, **kwargs)
|
||||
.. method:: target.cpufreq.set_governor(cpu, governor, \*\*kwargs)
|
||||
|
||||
Sets the governor for the specified cpu.
|
||||
|
||||
@ -83,7 +85,7 @@ policies (governors). The ``devlib`` module exposes the following interface
|
||||
:param cpu: The cpu; could be a numeric or the corresponding string (e.g.
|
||||
``1`` or ``"cpu1"``).
|
||||
|
||||
.. method:: target.cpufreq.set_governor_tunables(cpu, **kwargs)
|
||||
.. method:: target.cpufreq.set_governor_tunables(cpu, \*\*kwargs)
|
||||
|
||||
Set the tunables for the current governor on the specified CPU.
|
||||
|
||||
@ -169,4 +171,192 @@ TODO
|
||||
API
|
||||
---
|
||||
|
||||
TODO
|
||||
Generic Module API Description
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Modules implement discrete, optional pieces of functionality ("optional" in the
|
||||
sense that the functionality may or may not be present on the target device, or
|
||||
that it may or may not be necessary for a particular application).
|
||||
|
||||
Every module (ultimately) derives from :class:`Module` class. A module must
|
||||
define the following class attributes:
|
||||
|
||||
:name: A unique name for the module. This cannot clash with any of the existing
|
||||
names and must be a valid Python identifier, but is otherwise free-from.
|
||||
:kind: This identifies the type of functionality a module implements, which in
|
||||
turn determines the interface implemented by the module (all modules of
|
||||
the same kind must expose a consistent interface). This must be a valid
|
||||
Python identifier, but is otherwise free-form, though, where possible,
|
||||
one should try to stick to an already-defined kind/interface, lest we end
|
||||
up with a bunch of modules implementing similar functionality but
|
||||
exposing slightly different interfaces.
|
||||
|
||||
.. note:: It is possible to omit ``kind`` when defining a module, in
|
||||
which case the module's ``name`` will be treated as its
|
||||
``kind`` as well.
|
||||
|
||||
:stage: This defines when the module will be installed into a :class:`Target`.
|
||||
Currently, the following values are allowed:
|
||||
|
||||
:connected: The module is installed after a connection to the target has
|
||||
been established. This is the default.
|
||||
:early: The module will be installed when a :class:`Target` is first
|
||||
created. This should be used for modules that do not rely on a
|
||||
live connection to the target.
|
||||
|
||||
Additionally, a module must implement a static (or class) method :func:`probe`:
|
||||
|
||||
.. method:: Module.probe(target)
|
||||
|
||||
This method takes a :class:`Target` instance and returns ``True`` if this
|
||||
module is supported by that target, or ``False`` otherwise.
|
||||
|
||||
.. note:: If the moudule ``stage`` is ``"early"``, this method cannot assume
|
||||
that a connection has been established (i.e. it can only access
|
||||
attrubutes of the Target that do not rely on a connection).
|
||||
|
||||
Installation and invocation
|
||||
***************************
|
||||
|
||||
The default installation method will create an instance of a module (the
|
||||
:class:`Target` instance being the sole argument) and assign it to the target
|
||||
instance attribute named after the module's ``kind`` (or ``name`` if ``kind`` is
|
||||
``None``).
|
||||
|
||||
It is possible to change the installation procedure for a module by overriding
|
||||
the default :func:`install` method. The method must have the following
|
||||
signature:
|
||||
|
||||
.. method:: Module.install(cls, target, **kwargs)
|
||||
|
||||
Install the module into the target instance.
|
||||
|
||||
|
||||
Implementation and Usage Patterns
|
||||
*********************************
|
||||
|
||||
There are two common ways to implement the above API, corresponding to the two
|
||||
common uses for modules:
|
||||
|
||||
- If a module provides an interface to a particular set of functionality (e.g.
|
||||
an OS subsystem), that module would typically derive directly form
|
||||
:class:`Module` and would leave ``kind`` unassigned, so that it is accessed
|
||||
by it name. Its instance's methods and attributes provide the interface for
|
||||
interacting with its functionality. For examples of this type of module, see
|
||||
the subsystem modules listed above (e.g. ``cpufreq``).
|
||||
- If a module provides a platform- or infrastructure-specific implementation of
|
||||
a common function, the module would derive from one of :class:`Module`
|
||||
subclasses that define the interface for that function. In that case the
|
||||
module would be accessible via the common ``kind`` defined its super. The
|
||||
module would typically implement :func:`__call__` and be invoked directly. For
|
||||
examples of this type of module, see common function interface definitions
|
||||
below.
|
||||
|
||||
|
||||
Common Function Interfaces
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
This section documents :class:`Module` classes defining interface for common
|
||||
functions. Classes derived from them provide concrete implementations for
|
||||
specific platforms.
|
||||
|
||||
|
||||
HardResetModule
|
||||
***************
|
||||
|
||||
.. attribute:: HardResetModule.kind
|
||||
|
||||
"hard_reset"
|
||||
|
||||
.. method:: HardResetModule.__call__()
|
||||
|
||||
Must be implemented by derived classes.
|
||||
|
||||
Implements hard reset for a target devices. The equivalent of physically
|
||||
power cycling the device. This may be used by client code in situatians
|
||||
where the target becomes unresponsive and/or a regular reboot is not
|
||||
possible.
|
||||
|
||||
|
||||
BootModule
|
||||
**********
|
||||
|
||||
.. attribute:: BootModule.kind
|
||||
|
||||
"hard_reset"
|
||||
|
||||
.. method:: BootModule.__call__()
|
||||
|
||||
Must be implemented by derived classes.
|
||||
|
||||
Implements a boot proceedure. This takes the device from (hard or soft)
|
||||
reset to a booted state where the device is ready to accept connections. For
|
||||
a lot of commercial devices the process is entirely automatic, however some
|
||||
devices (e.g. development boards), my require additional steps, such as
|
||||
interactions with the bootloader, in order to boot into the OS.
|
||||
|
||||
.. method:: Bootmodule.update(\*\*kwargs)
|
||||
|
||||
Update the boot settings. Some boot sequencies allow specifying settings
|
||||
that will be utilized during boot (e.g. linux kernel boot command line). The
|
||||
default implmentation will set each setting in ``kwargs`` as an attribute of
|
||||
the boot module (or update the existing attribute).
|
||||
|
||||
|
||||
FlashModule
|
||||
***********
|
||||
|
||||
.. attribute:: FlashModule.kind
|
||||
|
||||
"flash"
|
||||
|
||||
.. method:: __call__(image_bundle=None, images=None, boot_config=None)
|
||||
|
||||
Must be implemented by derived classes.
|
||||
|
||||
Flash the target platform with the specified images.
|
||||
|
||||
:param image_bundle: A compressed bundle of image files with any associated
|
||||
metadata. The format of the bundle is specific to a
|
||||
particular implmentation.
|
||||
:param images: A dict mapping image names/identifiers to the path on the
|
||||
host file system of the corresponding image file. If both
|
||||
this and ``image_bundle`` are specified, individual images
|
||||
will override those in the bundle.
|
||||
:param boot_config: Some platforms require specifying boot arguments at the
|
||||
time of flashing the images, rather than during each
|
||||
reboot. For other platforms, this will be ignored.
|
||||
|
||||
|
||||
Module Registration
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Modules are specified on :class:`Target` or :class:`Platform` creation by name.
|
||||
In order to find the class associated with the name, the module needs to be
|
||||
registered with ``devlib``. This is accomplished by passing the module class
|
||||
into :func:`register_module` method once it is defined.
|
||||
|
||||
.. note:: If you're wiring a module to be included as part of ``devlib`` code
|
||||
base, you can place the file with the module class under
|
||||
``devlib/modules/`` in the source and it will be automatically
|
||||
enumarated. There is no need to explicitly register it in that case.
|
||||
|
||||
The code snippet below illustrates an implementation of a hard reset function
|
||||
for an "Acme" device.
|
||||
|
||||
.. code:: python
|
||||
|
||||
import os
|
||||
from devlib import HardResetModule, register_module
|
||||
|
||||
|
||||
class AcmeHardReset(HardResetModule):
|
||||
|
||||
name = 'acme_hard_reset'
|
||||
|
||||
def __call__(self):
|
||||
# Assuming Acme board comes with a "reset-acme-board" utility
|
||||
os.system('reset-acme-board {}'.format(self.target.name))
|
||||
|
||||
register_module(AcmeHardReset)
|
||||
|
||||
|
112
doc/platform.rst
Normal file
112
doc/platform.rst
Normal file
@ -0,0 +1,112 @@
|
||||
.. _platform:
|
||||
|
||||
Platform
|
||||
========
|
||||
|
||||
:class:`Platform`\ s describe the system underlying the OS. They encapsulate
|
||||
hardware- and firmware-specific details. In most cases, the generic
|
||||
:class:`Platform` class, which gets used if a platform is not explicitly
|
||||
specified on :class:`Target` creation, will be sufficient. It will automatically
|
||||
query as much platform information (such CPU topology, hardware model, etc) if
|
||||
it was not specified explicitly by the user.
|
||||
|
||||
|
||||
.. class:: Platform(name=None, core_names=None, core_clusters=None,\
|
||||
big_core=None, model=None, modules=None)
|
||||
|
||||
:param name: A user-friendly identifier for the platform.
|
||||
:param core_names: A list of CPU core names in the order they appear
|
||||
registered with the OS. If they are not specified,
|
||||
they will be queried at run time.
|
||||
:param core_clusters: Alist with cluster ids of each core (starting with
|
||||
0). If this is not specified, clusters will be
|
||||
inferred from core names (cores with the same name are
|
||||
assumed to be in a cluster).
|
||||
:param big_core: The name of the big core in a big.LITTLE system. If this is
|
||||
not specified it will be inferred (on systems with exactly
|
||||
two clasters).
|
||||
:param model: Model name of the hardware system. If this is not specified it
|
||||
will be queried at run time.
|
||||
:param modules: Modules with additional functionality supported by the
|
||||
platfrom (e.g. for handling flashing, rebooting, etc). These
|
||||
would be added to the Target's modules. (See :ref:`modules`\ ).
|
||||
|
||||
|
||||
Versatile Express
|
||||
-----------------
|
||||
|
||||
The generic platform may be extended to support hardware- or
|
||||
infrastructure-specific functionality. Platforms exist for ARM
|
||||
VersatileExpress-based :class:`Juno` and :class:`TC2` development boards. In
|
||||
addition to the standard :class:`Platform` parameters above, these platfroms
|
||||
support additional configuration:
|
||||
|
||||
|
||||
.. class:: VersatileExpressPlatform
|
||||
|
||||
Normally, this would be instatiated via one of its derived classes
|
||||
(:class:`Juno` or :class:`TC2`) that set appropriate defaults for some of
|
||||
the parameters.
|
||||
|
||||
:param serial_port: Identifies the serial port (usual a /dev node) on which the
|
||||
device is connected.
|
||||
:param baudrate: Baud rate for the serial connection. This defaults to
|
||||
``115200`` for :class:`Juno` and ``38400`` for
|
||||
:class:`TC2`.
|
||||
:param vemsd_mount: Mount point for the VEMSD (Versatile Express MicroSD card
|
||||
that is used for board configuration files and firmware
|
||||
images). This defaults to ``"/media/JUNO"`` for
|
||||
:class:`Juno` and ``"/media/VEMSD"`` for :class:`TC2`,
|
||||
though you would most likely need to change this for
|
||||
your setup as it would depend both on the file system
|
||||
label on the MicroSD card, and on how the card was
|
||||
mounted on the host system.
|
||||
:param hard_reset_method: Specifies the method for hard-resetting the devices
|
||||
(e.g. if it becomes unresponsive and normal reboot
|
||||
method doesn not work). Currently supported methods
|
||||
are:
|
||||
|
||||
:dtr: reboot by toggling DTR line on the serial
|
||||
connection (this is enabled via a DIP switch
|
||||
on the board).
|
||||
:reboottxt: reboot by writing a filed called
|
||||
``reboot.txt`` to the root of the VEMSD
|
||||
mount (this is enabled via board
|
||||
configuration file).
|
||||
|
||||
This defaults to ``dtr`` for :class:`Juno` and
|
||||
``reboottxt`` for :class:`TC2`.
|
||||
:param bootloader: Specifies the bootloader configuration used by the board.
|
||||
The following values are currently supported:
|
||||
|
||||
:uefi: Boot via UEFI menu, by selecting the entry
|
||||
specified by ``uefi_entry`` paramter. If this
|
||||
entry does not exist, it will be automatically
|
||||
created based on values provided for ``image``,
|
||||
``initrd``, ``fdt``, and ``bootargs`` parameters.
|
||||
:uefi-shell: Boot by going via the UEFI shell.
|
||||
:u-boot: Boot using Das U-Boot.
|
||||
:bootmon: Boot directly via Versatile Express Bootmon
|
||||
using the values provided for ``image``,
|
||||
``initrd``, ``fdt``, and ``bootargs``
|
||||
parameters.
|
||||
|
||||
This defaults to ``u-boot`` for :class:`Juno` and
|
||||
``bootmon`` for :class:`TC2`.
|
||||
:param flash_method: Specifies how the device is flashed. Currently, only
|
||||
``"vemsd"`` method is supported, which flashes by
|
||||
writing firmware images to an appropriate location on
|
||||
the VEMSD.
|
||||
:param image: Specfies the kernel image name for ``uefi`` or ``bootmon`` boot.
|
||||
:param fdt: Specifies the device tree blob for ``uefi`` or ``bootmon`` boot.
|
||||
:param initrd: Specifies the ramdisk image for ``uefi`` or ``bootmon`` boot.
|
||||
:param bootargs: Specifies the boot arguments that will be pass to the
|
||||
kernel by the bootloader.
|
||||
:param uefi_entry: Then name of the UEFI entry to be used/created by
|
||||
``uefi`` bootloader.
|
||||
:param ready_timeout: Timeout, in seconds, for the time it takes the
|
||||
platform to become ready to accept connections. Note:
|
||||
this does not mean that the system is fully booted;
|
||||
just that the services needed to establish a
|
||||
connection (e.g. sshd or adbd) are up.
|
||||
|
@ -18,7 +18,7 @@ Target
|
||||
available). If a :class:`Platform` instance is not specified on
|
||||
:class:`Target` creation, one will be created automatically and it will
|
||||
dynamically probe the device to discover as much about the underlying
|
||||
hardware as it can.
|
||||
hardware as it can. See also :ref:`platform`\ .
|
||||
|
||||
:param working_directory: This is primary location for on-target file system
|
||||
interactions performed by ``devlib``. This location *must* be readable and
|
||||
@ -53,7 +53,7 @@ Target
|
||||
:param modules: a list of additional modules to be installed. Some modules will
|
||||
try to install by default (if supported by the underlying target).
|
||||
Current default modules are ``hotplug``, ``cpufreq``, ``cpuidle``,
|
||||
``cgroups``, and ``hwmon``.
|
||||
``cgroups``, and ``hwmon`` (See :ref:`modules`\ ).
|
||||
|
||||
See modules documentation for more detail.
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user