blob: 883566390f3770d9a6b4eed1df3307c025ed95b8 [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
14system, and onlining them back int. The ``devlib`` module exposes a simple
15interface 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
40 ``cpufreq`` state on one core on a cluter will affect all cores on
41 that cluster. Because of this, some devices only expose cpufreq sysfs
42 interface (which is what is used by the ``devlib`` module) on the
43 first cpu in a cluster. So to keep your scripts proable, always use
44 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"``).
75 :param governor: The name of the governor. This must be one of the governors
76 supported by the CPU (as retrunted by ``list_governors()``.
77
78 Keyword arguments may be used to specify governor tunable values.
79
80
81.. method:: target.cpufreq.get_governor_tunables(cpu)
82
83 Return a dict with the values of the specfied CPU's current governor.
84
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
97.. method:: target.cpufreq.list_frequencie(cpu)
98
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
109 Get and set min and max frequencies on the specfied CPU. "set" functions are
110 avialable with all governors other than ``userspace``.
111
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
129``cpufreq`` is the kernel subsystem for managing CPU low power (idle) states.
130
131.. method:: taget.cpuidle.get_driver()
132
133 Return the name current cpuidle driver.
134
135.. method:: taget.cpuidle.get_governor()
136
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
158You can also call ``enable()`` or ``disable()`` on :class:`CpuidleState` objects
159returned 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
185 names and must be a valid Python identifier, but is otherwise free-from.
186: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
214 .. note:: If the moudule ``stage`` is ``"early"``, this method cannot assume
215 that a connection has been established (i.e. it can only access
216 attrubutes of the Target that do not rely on a connection).
217
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.
274
275 Implements hard reset for a target devices. The equivalent of physically
276 power cycling the device. This may be used by client code in situatians
277 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
292 Implements a boot proceedure. This takes the device from (hard or soft)
293 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
300 Update the boot settings. Some boot sequencies allow specifying settings
301 that will be utilized during boot (e.g. linux kernel boot command line). The
302 default implmentation will set each setting in ``kwargs`` as an attribute of
303 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
321 particular implmentation.
322 :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
342 enumarated. There is no need to explicitly register it in that case.
343
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):
358 # Assuming Acme board comes with a "reset-acme-board" utility
359 os.system('reset-acme-board {}'.format(self.target.name))
360
361 register_module(AcmeHardReset)
362