kernel/component.rs
1// Licensed under the Apache License, Version 2.0 or the MIT License.
2// SPDX-License-Identifier: Apache-2.0 OR MIT
3// Copyright Tock Contributors 2022.
4
5//! Components extend the functionality of the Tock kernel through a simple
6//! factory method interface.
7
8/// A component encapsulates peripheral-specific and capsule-specific
9/// initialization for the Tock kernel in a factory method, which reduces
10/// repeated code and simplifies the boot sequence.
11///
12/// The [`Component`] trait encapsulates all of the initialization and
13/// configuration of a kernel extension inside the [`Component::finalize()`]
14/// function call. The [`Component::Output`] type defines what type this
15/// component generates. Note that instantiating a component does not
16/// instantiate the underlying [`Component::Output`] type; instead, the memory
17/// is statically allocated and provided as an argument to the
18/// [`Component::finalize()`] method, which correctly initializes the memory to
19/// instantiate the [`Component::Output`] object. If instantiating and
20/// initializing the [`Component::Output`] type requires parameters, these
21/// should be passed in the component's `new()` function.
22///
23/// Using a component is as follows:
24///
25/// ```rust,ignore
26/// let obj = CapsuleComponent::new(configuration, required_hw)
27/// .finalize(capsule_component_static!());
28/// ```
29///
30/// All required resources and configuration is passed via the constructor, and
31/// all required static memory is defined by the `[name]_component_static!()`
32/// macro and passed to the `finalize()` method.
33pub trait Component {
34 /// An optional type to specify the chip or board specific static memory
35 /// that a component needs to setup the output object(s). This is the memory
36 /// that [`crate::static_buf!()`] would normally setup, but generic
37 /// components cannot setup static buffers for types which are
38 /// chip-dependent, so those buffers have to be passed in manually, and the
39 /// [`Component::StaticInput`] type makes this possible.
40 type StaticInput;
41
42 /// The type (e.g., capsule, peripheral) that this implementation of
43 /// [`Component`] produces via [`Component::finalize()`]. This is typically
44 /// a static reference (`&'static`).
45 type Output;
46
47 /// A factory method that returns an instance of the Output type of this
48 /// [`Component`] implementation. This is used in the boot sequence to
49 /// instantiate and initialize part of the Tock kernel. This factory method
50 /// may only be called once per Component instance.
51 ///
52 /// To enable reusable (i.e. can be used on multiple boards with different
53 /// microcontrollers) and repeatable (i.e. can be instantiated multiple
54 /// times on the same board) components, all components must follow this
55 /// convention:
56 ///
57 /// - All statically allocated memory MUST be passed to
58 /// [`Component::finalize()`] via the `static_memory` argument. The
59 /// [`Component::finalize()`] method **MUST NOT** use
60 /// [`crate::static_init!()`] or [`crate::static_buf!()`] directly. This
61 /// restriction ensures that memory is not aliased if the component is
62 /// used multiple times.
63 fn finalize(self, static_memory: Self::StaticInput) -> Self::Output;
64}