blob: b89b488026c766db469aad877f88341e2d1a1f5a [file] [log] [blame]
Sergei Trofimov1ba7fbd2016-12-09 15:06:35 +00001.. _modules:
2
Sergei Trofimov4e6afe92015-10-09 09:30:04 +01003Modules
4=======
5
6Modules add additional functionality to the core :class:`Target` interface.
7Usually, it is support for specific subsystems on the target. Modules are
8instantiated as attributes of the :class:`Target` instance.
9
10hotplug
11-------
12
13Kernel ``hotplug`` subsystem allows offlining ("removing") cores from the
Marc Bonnici8733b9c2017-02-28 17:40:44 +000014system, and onlining them back in. The ``devlib`` module exposes a simple
Sergei Trofimov4e6afe92015-10-09 09:30:04 +010015interface to this subsystem
16
17.. code:: python
18
19 from devlib import LocalLinuxTarget
20 target = LocalLinuxTarget()
21
22 # offline cpus 2 and 3, "removing" them from the system
23 target.hotplug.offline(2, 3)
24
25 # bring CPU 2 back in
26 target.hotplug.online(2)
27
28 # Make sure all cpus are online
29 target.hotplug.online_all()
30
31cpufreq
32-------
33
34``cpufreq`` is the kernel subsystem for managing DVFS (Dynamic Voltage and
35Frequency Scaling). It allows controlling frequency ranges and switching
36policies (governors). The ``devlib`` module exposes the following interface
37
38.. note:: On ARM big.LITTLE systems, all cores on a cluster (usually all cores
39 of the same type) are in the same frequency domain, so setting
Marc Bonnici8733b9c2017-02-28 17:40:44 +000040 ``cpufreq`` state on one core on a cluster will affect all cores on
Sergei Trofimov4e6afe92015-10-09 09:30:04 +010041 that cluster. Because of this, some devices only expose cpufreq sysfs
42 interface (which is what is used by the ``devlib`` module) on the
Marc Bonnici8733b9c2017-02-28 17:40:44 +000043 first cpu in a cluster. So to keep your scripts portable, always use
Sergei Trofimov4e6afe92015-10-09 09:30:04 +010044 the fist (online) CPU in a cluster to set ``cpufreq`` state.
45
46.. method:: target.cpufreq.list_governors(cpu)
47
48 List cpufreq governors available for the specified cpu. Returns a list of
49 strings.
50
51 :param cpu: The cpu; could be a numeric or the corresponding string (e.g.
52 ``1`` or ``"cpu1"``).
53
54.. method:: target.cpufreq.list_governor_tunables(cpu)
55
56 List the tunables for the specified cpu's current governor.
57
58 :param cpu: The cpu; could be a numeric or the corresponding string (e.g.
59 ``1`` or ``"cpu1"``).
60
61
62.. method:: target.cpufreq.get_governor(cpu)
63
64 Returns the name of the currently set governor for the specified cpu.
65
66 :param cpu: The cpu; could be a numeric or the corresponding string (e.g.
67 ``1`` or ``"cpu1"``).
68
Sergei Trofimov1ba7fbd2016-12-09 15:06:35 +000069.. method:: target.cpufreq.set_governor(cpu, governor, \*\*kwargs)
Sergei Trofimov4e6afe92015-10-09 09:30:04 +010070
71 Sets the governor for the specified cpu.
72
73 :param cpu: The cpu; could be a numeric or the corresponding string (e.g.
74 ``1`` or ``"cpu1"``).
Marc Bonnici1fd56362017-01-10 15:35:21 +000075 :param governor: The name of the governor. This must be one of the governors
Marc Bonnici8733b9c2017-02-28 17:40:44 +000076 supported by the CPU (as returned by ``list_governors()``.
Sergei Trofimov4e6afe92015-10-09 09:30:04 +010077
78 Keyword arguments may be used to specify governor tunable values.
79
80
81.. method:: target.cpufreq.get_governor_tunables(cpu)
82
Marc Bonnici8733b9c2017-02-28 17:40:44 +000083 Return a dict with the values of the specified CPU's current governor.
Sergei Trofimov4e6afe92015-10-09 09:30:04 +010084
85 :param cpu: The cpu; could be a numeric or the corresponding string (e.g.
86 ``1`` or ``"cpu1"``).
87
Sergei Trofimov1ba7fbd2016-12-09 15:06:35 +000088.. method:: target.cpufreq.set_governor_tunables(cpu, \*\*kwargs)
Sergei Trofimov4e6afe92015-10-09 09:30:04 +010089
90 Set the tunables for the current governor on the specified CPU.
91
92 :param cpu: The cpu; could be a numeric or the corresponding string (e.g.
93 ``1`` or ``"cpu1"``).
94
95 Keyword arguments should be used to specify tunable values.
96
Marc Bonnici8733b9c2017-02-28 17:40:44 +000097.. method:: target.cpufreq.list_frequencies(cpu)
Sergei Trofimov4e6afe92015-10-09 09:30:04 +010098
99 List DVFS frequencies supported by the specified CPU. Returns a list of ints.
100
101 :param cpu: The cpu; could be a numeric or the corresponding string (e.g.
102 ``1`` or ``"cpu1"``).
103
104.. method:: target.cpufreq.get_min_frequency(cpu)
105 target.cpufreq.get_max_frequency(cpu)
106 target.cpufreq.set_min_frequency(cpu, frequency[, exact=True])
107 target.cpufreq.set_max_frequency(cpu, frequency[, exact=True])
108
Marc Bonnici8733b9c2017-02-28 17:40:44 +0000109 Get and set min and max frequencies on the specified CPU. "set" functions are
110 available with all governors other than ``userspace``.
Sergei Trofimov4e6afe92015-10-09 09:30:04 +0100111
112 :param cpu: The cpu; could be a numeric or the corresponding string (e.g.
113 ``1`` or ``"cpu1"``).
114 :param frequency: Frequency to set.
115
116.. method:: target.cpufreq.get_frequency(cpu)
117 target.cpufreq.set_frequency(cpu, frequency[, exact=True])
118
119 Get and set current frequency on the specified CPU. ``set_frequency`` is only
120 available if the current governor is ``userspace``.
121
122 :param cpu: The cpu; could be a numeric or the corresponding string (e.g.
123 ``1`` or ``"cpu1"``).
124 :param frequency: Frequency to set.
125
126cpuidle
127-------
128
Marc Bonnici1fd56362017-01-10 15:35:21 +0000129``cpuidle`` is the kernel subsystem for managing CPU low power (idle) states.
Sergei Trofimov4e6afe92015-10-09 09:30:04 +0100130
Marc Bonnici8733b9c2017-02-28 17:40:44 +0000131.. method:: target.cpuidle.get_driver()
Sergei Trofimov4e6afe92015-10-09 09:30:04 +0100132
133 Return the name current cpuidle driver.
134
Marc Bonnici8733b9c2017-02-28 17:40:44 +0000135.. method:: target.cpuidle.get_governor()
Sergei Trofimov4e6afe92015-10-09 09:30:04 +0100136
137 Return the name current cpuidle governor (policy).
138
139.. method:: target.cpuidle.get_states([cpu=0])
140
141 Return idle states (optionally, for the specified CPU). Returns a list of
142 :class:`CpuidleState` instances.
143
144.. method:: target.cpuidle.get_state(state[, cpu=0])
145
146 Return :class:`CpuidleState` instance (optionally, for the specified CPU)
147 representing the specified idle state. ``state`` can be either an integer
148 index of the state or a string with the states ``name`` or ``desc``.
149
150.. method:: target.cpuidle.enable(state[, cpu=0])
151 target.cpuidle.disable(state[, cpu=0])
152 target.cpuidle.enable_all([cpu=0])
153 target.cpuidle.disable_all([cpu=0])
154
155 Enable or disable the specified or all states (optionally on the specified
156 CPU.
157
Marc Bonnici1fd56362017-01-10 15:35:21 +0000158You can also call ``enable()`` or ``disable()`` on :class:`CpuidleState` objects
Sergei Trofimov4e6afe92015-10-09 09:30:04 +0100159returned by get_state(s).
160
161cgroups
162-------
163
164TODO
165
166hwmon
167-----
168
169TODO
170
171API
172---
173
Sergei Trofimov1ba7fbd2016-12-09 15:06:35 +0000174Generic Module API Description
175~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
176
177Modules implement discrete, optional pieces of functionality ("optional" in the
178sense that the functionality may or may not be present on the target device, or
179that it may or may not be necessary for a particular application).
180
181Every module (ultimately) derives from :class:`Module` class. A module must
182define the following class attributes:
183
184:name: A unique name for the module. This cannot clash with any of the existing
Marc Bonnici1fd56362017-01-10 15:35:21 +0000185 names and must be a valid Python identifier, but is otherwise free-form.
Sergei Trofimov1ba7fbd2016-12-09 15:06:35 +0000186:kind: This identifies the type of functionality a module implements, which in
187 turn determines the interface implemented by the module (all modules of
188 the same kind must expose a consistent interface). This must be a valid
189 Python identifier, but is otherwise free-form, though, where possible,
190 one should try to stick to an already-defined kind/interface, lest we end
191 up with a bunch of modules implementing similar functionality but
192 exposing slightly different interfaces.
193
194 .. note:: It is possible to omit ``kind`` when defining a module, in
195 which case the module's ``name`` will be treated as its
196 ``kind`` as well.
197
198:stage: This defines when the module will be installed into a :class:`Target`.
199 Currently, the following values are allowed:
200
201 :connected: The module is installed after a connection to the target has
202 been established. This is the default.
203 :early: The module will be installed when a :class:`Target` is first
204 created. This should be used for modules that do not rely on a
205 live connection to the target.
206
207Additionally, a module must implement a static (or class) method :func:`probe`:
208
209.. method:: Module.probe(target)
210
211 This method takes a :class:`Target` instance and returns ``True`` if this
212 module is supported by that target, or ``False`` otherwise.
213
Marc Bonnici8733b9c2017-02-28 17:40:44 +0000214 .. note:: If the module ``stage`` is ``"early"``, this method cannot assume
Sergei Trofimov1ba7fbd2016-12-09 15:06:35 +0000215 that a connection has been established (i.e. it can only access
Marc Bonnici8733b9c2017-02-28 17:40:44 +0000216 attributes of the Target that do not rely on a connection).
Sergei Trofimov1ba7fbd2016-12-09 15:06:35 +0000217
218Installation and invocation
219***************************
220
221The default installation method will create an instance of a module (the
222:class:`Target` instance being the sole argument) and assign it to the target
223instance attribute named after the module's ``kind`` (or ``name`` if ``kind`` is
224``None``).
225
226It is possible to change the installation procedure for a module by overriding
227the default :func:`install` method. The method must have the following
228signature:
229
230.. method:: Module.install(cls, target, **kwargs)
231
232 Install the module into the target instance.
233
234
235Implementation and Usage Patterns
236*********************************
237
238There are two common ways to implement the above API, corresponding to the two
239common uses for modules:
240
241- If a module provides an interface to a particular set of functionality (e.g.
242 an OS subsystem), that module would typically derive directly form
243 :class:`Module` and would leave ``kind`` unassigned, so that it is accessed
244 by it name. Its instance's methods and attributes provide the interface for
245 interacting with its functionality. For examples of this type of module, see
246 the subsystem modules listed above (e.g. ``cpufreq``).
247- If a module provides a platform- or infrastructure-specific implementation of
248 a common function, the module would derive from one of :class:`Module`
249 subclasses that define the interface for that function. In that case the
250 module would be accessible via the common ``kind`` defined its super. The
251 module would typically implement :func:`__call__` and be invoked directly. For
252 examples of this type of module, see common function interface definitions
253 below.
254
255
256Common Function Interfaces
257~~~~~~~~~~~~~~~~~~~~~~~~~~
258
259This section documents :class:`Module` classes defining interface for common
260functions. Classes derived from them provide concrete implementations for
261specific platforms.
262
263
264HardResetModule
265***************
266
267.. attribute:: HardResetModule.kind
268
269 "hard_reset"
270
271.. method:: HardResetModule.__call__()
272
273 Must be implemented by derived classes.
Marc Bonnici1fd56362017-01-10 15:35:21 +0000274
Sergei Trofimov1ba7fbd2016-12-09 15:06:35 +0000275 Implements hard reset for a target devices. The equivalent of physically
Marc Bonnici8733b9c2017-02-28 17:40:44 +0000276 power cycling the device. This may be used by client code in situations
Sergei Trofimov1ba7fbd2016-12-09 15:06:35 +0000277 where the target becomes unresponsive and/or a regular reboot is not
278 possible.
279
280
281BootModule
282**********
283
284.. attribute:: BootModule.kind
285
286 "hard_reset"
287
288.. method:: BootModule.__call__()
289
290 Must be implemented by derived classes.
291
Marc Bonnici8733b9c2017-02-28 17:40:44 +0000292 Implements a boot procedure. This takes the device from (hard or soft)
Sergei Trofimov1ba7fbd2016-12-09 15:06:35 +0000293 reset to a booted state where the device is ready to accept connections. For
294 a lot of commercial devices the process is entirely automatic, however some
295 devices (e.g. development boards), my require additional steps, such as
296 interactions with the bootloader, in order to boot into the OS.
297
298.. method:: Bootmodule.update(\*\*kwargs)
299
Marc Bonnici8733b9c2017-02-28 17:40:44 +0000300 Update the boot settings. Some boot sequences allow specifying settings
Sergei Trofimov1ba7fbd2016-12-09 15:06:35 +0000301 that will be utilized during boot (e.g. linux kernel boot command line). The
Marc Bonnici8733b9c2017-02-28 17:40:44 +0000302 default implementation will set each setting in ``kwargs`` as an attribute of
Sergei Trofimov1ba7fbd2016-12-09 15:06:35 +0000303 the boot module (or update the existing attribute).
304
305
306FlashModule
307***********
308
309.. attribute:: FlashModule.kind
310
311 "flash"
312
313.. method:: __call__(image_bundle=None, images=None, boot_config=None)
314
315 Must be implemented by derived classes.
316
317 Flash the target platform with the specified images.
318
319 :param image_bundle: A compressed bundle of image files with any associated
320 metadata. The format of the bundle is specific to a
Marc Bonnici8733b9c2017-02-28 17:40:44 +0000321 particular implementation.
Sergei Trofimov1ba7fbd2016-12-09 15:06:35 +0000322 :param images: A dict mapping image names/identifiers to the path on the
323 host file system of the corresponding image file. If both
324 this and ``image_bundle`` are specified, individual images
325 will override those in the bundle.
326 :param boot_config: Some platforms require specifying boot arguments at the
327 time of flashing the images, rather than during each
328 reboot. For other platforms, this will be ignored.
329
330
331Module Registration
332~~~~~~~~~~~~~~~~~~~
333
334Modules are specified on :class:`Target` or :class:`Platform` creation by name.
335In order to find the class associated with the name, the module needs to be
336registered with ``devlib``. This is accomplished by passing the module class
337into :func:`register_module` method once it is defined.
338
339.. note:: If you're wiring a module to be included as part of ``devlib`` code
340 base, you can place the file with the module class under
341 ``devlib/modules/`` in the source and it will be automatically
Marc Bonnici8733b9c2017-02-28 17:40:44 +0000342 enumerated. There is no need to explicitly register it in that case.
Sergei Trofimov1ba7fbd2016-12-09 15:06:35 +0000343
344The code snippet below illustrates an implementation of a hard reset function
345for an "Acme" device.
346
347.. code:: python
348
349 import os
350 from devlib import HardResetModule, register_module
351
352
353 class AcmeHardReset(HardResetModule):
354
355 name = 'acme_hard_reset'
356
357 def __call__(self):
Marc Bonnici1fd56362017-01-10 15:35:21 +0000358 # Assuming Acme board comes with a "reset-acme-board" utility
Sergei Trofimov1ba7fbd2016-12-09 15:06:35 +0000359 os.system('reset-acme-board {}'.format(self.target.name))
360
361 register_module(AcmeHardReset)
362