components/
pwm.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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
// Licensed under the Apache License, Version 2.0 or the MIT License.
// SPDX-License-Identifier: Apache-2.0 OR MIT
// Copyright Tock Contributors 2022.

//! Components for using PWM.

use capsules_core::virtualizers::virtual_pwm::{MuxPwm, PwmPinUser};
use capsules_extra::pwm::Pwm;
use core::mem::MaybeUninit;
use kernel::capabilities;
use kernel::component::Component;
use kernel::create_capability;
use kernel::hil::pwm;

#[macro_export]
macro_rules! pwm_mux_component_static {
    ($A:ty $(,)?) => {{
        kernel::static_buf!(capsules_core::virtualizers::virtual_pwm::MuxPwm<'static, $A>)
    };};
}

#[macro_export]
macro_rules! pwm_pin_user_component_static {
    ($A:ty $(,)?) => {{
        kernel::static_buf!(capsules_core::virtualizers::virtual_pwm::PwmPinUser<'static, $A>)
    };};
}

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

        let drivers = static_init!(
            [&'static dyn kernel::hil::pwm::PwmPin; NUM_DRIVERS],
            [
                $($P,)*
            ]
        );
        let pwm = kernel::static_buf!(capsules_extra::pwm::Pwm<'static, NUM_DRIVERS>);
        (pwm, drivers)
    };};
}

pub struct PwmMuxComponent<P: 'static + pwm::Pwm> {
    pwm: &'static P,
}

impl<P: 'static + pwm::Pwm> PwmMuxComponent<P> {
    pub fn new(pwm: &'static P) -> Self {
        PwmMuxComponent { pwm }
    }
}

impl<P: 'static + pwm::Pwm> Component for PwmMuxComponent<P> {
    type StaticInput = &'static mut MaybeUninit<MuxPwm<'static, P>>;
    type Output = &'static MuxPwm<'static, P>;

    fn finalize(self, static_buffer: Self::StaticInput) -> Self::Output {
        let pwm_mux = static_buffer.write(MuxPwm::new(self.pwm));

        pwm_mux
    }
}

pub struct PwmPinUserComponent<P: 'static + pwm::Pwm> {
    pwm_mux: &'static MuxPwm<'static, P>,
    channel: P::Pin,
}

impl<P: 'static + pwm::Pwm> PwmPinUserComponent<P> {
    pub fn new(mux: &'static MuxPwm<'static, P>, channel: P::Pin) -> Self {
        PwmPinUserComponent {
            pwm_mux: mux,
            channel,
        }
    }
}

impl<P: 'static + pwm::Pwm> Component for PwmPinUserComponent<P> {
    type StaticInput = &'static mut MaybeUninit<PwmPinUser<'static, P>>;
    type Output = &'static PwmPinUser<'static, P>;

    fn finalize(self, static_buffer: Self::StaticInput) -> Self::Output {
        let pwm_pin = static_buffer.write(PwmPinUser::new(self.pwm_mux, self.channel));

        pwm_pin.add_to_mux();

        pwm_pin
    }
}

pub struct PwmDriverComponent<const NUM_PINS: usize> {
    board_kernel: &'static kernel::Kernel,
    driver_num: usize,
}

impl<const NUM_PINS: usize> PwmDriverComponent<NUM_PINS> {
    pub fn new(
        board_kernel: &'static kernel::Kernel,
        driver_num: usize,
    ) -> PwmDriverComponent<NUM_PINS> {
        PwmDriverComponent {
            board_kernel,
            driver_num,
        }
    }
}

impl<const NUM_PINS: usize> Component for PwmDriverComponent<NUM_PINS> {
    type StaticInput = (
        &'static mut MaybeUninit<Pwm<'static, NUM_PINS>>,
        &'static [&'static dyn kernel::hil::pwm::PwmPin; NUM_PINS],
    );
    type Output = &'static capsules_extra::pwm::Pwm<'static, NUM_PINS>;

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

        let pwm = static_buffer
            .0
            .write(capsules_extra::pwm::Pwm::new(static_buffer.1, grant_adc));

        pwm
    }
}