components/
analog_comparator.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
// Licensed under the Apache License, Version 2.0 or the MIT License.
// SPDX-License-Identifier: Apache-2.0 OR MIT
// Copyright Tock Contributors 2022.

//! Component for initializing an Analog Comparator.
//!
//! This provides one Component, AcComponent, which implements a userspace
//! syscall interface to a passed analog comparator driver.
//!
//! Usage
//! -----
//! ```rust
//! let analog_comparator = components::analog_comparator::AnalogComparatorComponent::new(
//!     &sam4l::acifc::ACIFC,
//!     components::analog_comparator_component_helper!(
//!         <sam4l::acifc::Acifc as kernel::hil::analog_comparator::AnalogComparator>::Channel,
//!         &sam4l::acifc::CHANNEL_AC0,
//!         &sam4l::acifc::CHANNEL_AC1,
//!         &sam4l::acifc::CHANNEL_AC2,
//!         &sam4l::acifc::CHANNEL_AC3
//!     ),
//! )
//! .finalize(components::analog_comparator_component_static!(sam4l::acifc::Acifc));
//! ```

use capsules_extra::analog_comparator::AnalogComparator;
use core::mem::MaybeUninit;
use kernel::capabilities;
use kernel::component::Component;
use kernel::create_capability;

#[macro_export]
macro_rules! analog_comparator_component_helper {
    ($Channel:ty, $($P:expr),+ $(,)?) => {{
        use kernel::count_expressions;
        use kernel::static_init;
        const NUM_CHANNELS: usize = count_expressions!($($P),+);

        static_init!(
            [&'static $Channel; NUM_CHANNELS],
            [
                $($P,)*
            ]
        )
    };};
}

#[macro_export]
macro_rules! analog_comparator_component_static {
    ($AC:ty $(,)?) => {{
        kernel::static_buf!(capsules_extra::analog_comparator::AnalogComparator<'static, $AC>)
    };};
}

pub struct AnalogComparatorComponent<
    AC: 'static + kernel::hil::analog_comparator::AnalogComparator<'static>,
> {
    comp: &'static AC,
    ac_channels: &'static [&'static AC::Channel],
    board_kernel: &'static kernel::Kernel,
    driver_num: usize,
}

impl<AC: 'static + kernel::hil::analog_comparator::AnalogComparator<'static>>
    AnalogComparatorComponent<AC>
{
    pub fn new(
        comp: &'static AC,
        ac_channels: &'static [&'static AC::Channel],
        board_kernel: &'static kernel::Kernel,
        driver_num: usize,
    ) -> Self {
        Self {
            comp,
            ac_channels,
            board_kernel,
            driver_num,
        }
    }
}

impl<AC: 'static + kernel::hil::analog_comparator::AnalogComparator<'static>> Component
    for AnalogComparatorComponent<AC>
{
    type StaticInput = &'static mut MaybeUninit<AnalogComparator<'static, AC>>;
    type Output = &'static AnalogComparator<'static, AC>;

    fn finalize(self, static_buffer: Self::StaticInput) -> Self::Output {
        let grant_cap = create_capability!(capabilities::MemoryAllocationCapability);
        let grant_ac = self.board_kernel.create_grant(self.driver_num, &grant_cap);

        let analog_comparator =
            static_buffer.write(AnalogComparator::new(self.comp, self.ac_channels, grant_ac));
        self.comp.set_client(analog_comparator);

        analog_comparator
    }
}