components/
l3gd20.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 the L3GD20 sensor.
6//!
7//! Uses a SPI Interface.
8//!
9//! Usage
10//! -----
11//! ```rust
12//! let l3gd20 = components::l3gd20::L3gd20Component::new(spi_mux, stm32f429zi::gpio::PinId::PE03).finalize(
13//!     components::l3gd20_component_static!(stm32f429zi::spi::Spi));
14//! ```
15
16use capsules_core::virtualizers::virtual_spi::{MuxSpiMaster, VirtualSpiMasterDevice};
17use capsules_extra::l3gd20::L3gd20Spi;
18use core::mem::MaybeUninit;
19use kernel::capabilities;
20use kernel::component::Component;
21use kernel::create_capability;
22use kernel::hil::spi;
23use kernel::hil::spi::SpiMasterDevice;
24
25// Setup static space for the objects.
26#[macro_export]
27macro_rules! l3gd20_component_static {
28    ($S:ty $(,)?) => {{
29        let txbuffer = kernel::static_buf!([u8; capsules_extra::l3gd20::TX_BUF_LEN]);
30        let rxbuffer = kernel::static_buf!([u8; capsules_extra::l3gd20::RX_BUF_LEN]);
31
32        let spi = kernel::static_buf!(
33            capsules_core::virtualizers::virtual_spi::VirtualSpiMasterDevice<'static, $S>
34        );
35        let l3gd20spi = kernel::static_buf!(
36            capsules_extra::l3gd20::L3gd20Spi<
37                'static,
38                capsules_core::virtualizers::virtual_spi::VirtualSpiMasterDevice<'static, $S>,
39            >
40        );
41
42        (spi, l3gd20spi, txbuffer, rxbuffer)
43    };};
44}
45
46pub type L3gd20ComponentType<S> = capsules_extra::l3gd20::L3gd20Spi<'static, S>;
47
48pub struct L3gd20Component<
49    S: 'static + spi::SpiMaster<'static>,
50    CS: spi::cs::IntoChipSelect<S::ChipSelect, spi::cs::ActiveLow>,
51> {
52    spi_mux: &'static MuxSpiMaster<'static, S>,
53    chip_select: CS,
54    board_kernel: &'static kernel::Kernel,
55    driver_num: usize,
56}
57
58impl<
59        S: 'static + spi::SpiMaster<'static>,
60        CS: spi::cs::IntoChipSelect<S::ChipSelect, spi::cs::ActiveLow>,
61    > L3gd20Component<S, CS>
62{
63    pub fn new(
64        spi_mux: &'static MuxSpiMaster<'static, S>,
65        chip_select: CS,
66        board_kernel: &'static kernel::Kernel,
67        driver_num: usize,
68    ) -> Self {
69        Self {
70            spi_mux,
71            chip_select,
72            board_kernel,
73            driver_num,
74        }
75    }
76}
77
78impl<
79        S: 'static + spi::SpiMaster<'static>,
80        CS: spi::cs::IntoChipSelect<S::ChipSelect, spi::cs::ActiveLow>,
81    > Component for L3gd20Component<S, CS>
82{
83    type StaticInput = (
84        &'static mut MaybeUninit<VirtualSpiMasterDevice<'static, S>>,
85        &'static mut MaybeUninit<L3gd20Spi<'static, VirtualSpiMasterDevice<'static, S>>>,
86        &'static mut MaybeUninit<[u8; capsules_extra::l3gd20::TX_BUF_LEN]>,
87        &'static mut MaybeUninit<[u8; capsules_extra::l3gd20::RX_BUF_LEN]>,
88    );
89    type Output = &'static L3gd20Spi<'static, VirtualSpiMasterDevice<'static, S>>;
90
91    fn finalize(self, static_buffer: Self::StaticInput) -> Self::Output {
92        let grant_cap = create_capability!(capabilities::MemoryAllocationCapability);
93        let grant = self.board_kernel.create_grant(self.driver_num, &grant_cap);
94
95        let spi_device = static_buffer.0.write(VirtualSpiMasterDevice::new(
96            self.spi_mux,
97            self.chip_select.into_cs(),
98        ));
99        spi_device.setup();
100
101        let txbuffer = static_buffer
102            .2
103            .write([0; capsules_extra::l3gd20::TX_BUF_LEN]);
104        let rxbuffer = static_buffer
105            .3
106            .write([0; capsules_extra::l3gd20::RX_BUF_LEN]);
107
108        let l3gd20 = static_buffer
109            .1
110            .write(L3gd20Spi::new(spi_device, txbuffer, rxbuffer, grant));
111        spi_device.set_client(l3gd20);
112
113        // TODO verify SPI return value
114        let _ = l3gd20.configure();
115
116        l3gd20
117    }
118}