components/
pwm.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 for using PWM.
6
7use capsules_core::virtualizers::virtual_pwm::{MuxPwm, PwmPinUser};
8use capsules_extra::pwm::Pwm;
9use core::mem::MaybeUninit;
10use kernel::capabilities;
11use kernel::component::Component;
12use kernel::create_capability;
13use kernel::hil::pwm;
14
15#[macro_export]
16macro_rules! pwm_mux_component_static {
17    ($A:ty $(,)?) => {{
18        kernel::static_buf!(capsules_core::virtualizers::virtual_pwm::MuxPwm<'static, $A>)
19    };};
20}
21
22#[macro_export]
23macro_rules! pwm_pin_user_component_static {
24    ($A:ty $(,)?) => {{
25        kernel::static_buf!(capsules_core::virtualizers::virtual_pwm::PwmPinUser<'static, $A>)
26    };};
27}
28
29#[macro_export]
30macro_rules! pwm_driver_component_helper {
31    ($($P:expr),+ $(,)?) => {{
32        use kernel::count_expressions;
33        use kernel::static_init;
34        const NUM_DRIVERS: usize = count_expressions!($($P),+);
35
36        let drivers = static_init!(
37            [&'static dyn kernel::hil::pwm::PwmPin; NUM_DRIVERS],
38            [
39                $($P,)*
40            ]
41        );
42        let pwm = kernel::static_buf!(capsules_extra::pwm::Pwm<'static, NUM_DRIVERS>);
43        (pwm, drivers)
44    };};
45}
46
47pub struct PwmMuxComponent<P: 'static + pwm::Pwm> {
48    pwm: &'static P,
49}
50
51impl<P: 'static + pwm::Pwm> PwmMuxComponent<P> {
52    pub fn new(pwm: &'static P) -> Self {
53        PwmMuxComponent { pwm }
54    }
55}
56
57impl<P: 'static + pwm::Pwm> Component for PwmMuxComponent<P> {
58    type StaticInput = &'static mut MaybeUninit<MuxPwm<'static, P>>;
59    type Output = &'static MuxPwm<'static, P>;
60
61    fn finalize(self, static_buffer: Self::StaticInput) -> Self::Output {
62        let pwm_mux = static_buffer.write(MuxPwm::new(self.pwm));
63
64        pwm_mux
65    }
66}
67
68pub struct PwmPinUserComponent<P: 'static + pwm::Pwm> {
69    pwm_mux: &'static MuxPwm<'static, P>,
70    channel: P::Pin,
71}
72
73impl<P: 'static + pwm::Pwm> PwmPinUserComponent<P> {
74    pub fn new(mux: &'static MuxPwm<'static, P>, channel: P::Pin) -> Self {
75        PwmPinUserComponent {
76            pwm_mux: mux,
77            channel,
78        }
79    }
80}
81
82impl<P: 'static + pwm::Pwm> Component for PwmPinUserComponent<P> {
83    type StaticInput = &'static mut MaybeUninit<PwmPinUser<'static, P>>;
84    type Output = &'static PwmPinUser<'static, P>;
85
86    fn finalize(self, static_buffer: Self::StaticInput) -> Self::Output {
87        let pwm_pin = static_buffer.write(PwmPinUser::new(self.pwm_mux, self.channel));
88
89        pwm_pin.add_to_mux();
90
91        pwm_pin
92    }
93}
94
95pub struct PwmDriverComponent<const NUM_PINS: usize> {
96    board_kernel: &'static kernel::Kernel,
97    driver_num: usize,
98}
99
100impl<const NUM_PINS: usize> PwmDriverComponent<NUM_PINS> {
101    pub fn new(
102        board_kernel: &'static kernel::Kernel,
103        driver_num: usize,
104    ) -> PwmDriverComponent<NUM_PINS> {
105        PwmDriverComponent {
106            board_kernel,
107            driver_num,
108        }
109    }
110}
111
112impl<const NUM_PINS: usize> Component for PwmDriverComponent<NUM_PINS> {
113    type StaticInput = (
114        &'static mut MaybeUninit<Pwm<'static, NUM_PINS>>,
115        &'static [&'static dyn kernel::hil::pwm::PwmPin; NUM_PINS],
116    );
117    type Output = &'static capsules_extra::pwm::Pwm<'static, NUM_PINS>;
118
119    fn finalize(self, static_buffer: Self::StaticInput) -> Self::Output {
120        let grant_cap = create_capability!(capabilities::MemoryAllocationCapability);
121        let grant_adc = self.board_kernel.create_grant(self.driver_num, &grant_cap);
122
123        let pwm = static_buffer
124            .0
125            .write(capsules_extra::pwm::Pwm::new(static_buffer.1, grant_adc));
126
127        pwm
128    }
129}