components/
rf233.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//! Component for communicating with an RF233 chip (802.15.4) connected via SPI.
6//!
7//! This provides one Component, RF233Component, which provides basic
8//! packet-level interfaces for communicating with 802.15.4.
9//!
10//! Usage
11//! -----
12//! ```rust
13//! let rf233 = components::rf233::RF233Component::new(
14//!     rf233_spi,
15//!     &peripherals.pa[09], // reset
16//!     &peripherals.pa[10], // sleep
17//!     &peripherals.pa[08], // irq
18//!     &peripherals.pa[08],
19//!     RADIO_CHANNEL,
20//! )
21//! .finalize(components::rf233_component_static!(sam4l::spi::SpiHw));
22//! ```
23
24use capsules_core::virtualizers::virtual_spi::VirtualSpiMasterDevice;
25use capsules_extra::rf233::RF233;
26use core::mem::MaybeUninit;
27use kernel::component::Component;
28use kernel::hil::radio::RadioConfig;
29use kernel::hil::spi::{SpiMaster, SpiMasterDevice};
30use kernel::hil::{self, radio};
31
32// Setup static space for the objects.
33#[macro_export]
34macro_rules! rf233_component_static {
35    ($S:ty $(,)?) => {{
36        let spi_device = kernel::static_buf!(
37            capsules_extra::rf233::RF233<
38                'static,
39                capsules_core::virtualizers::virtual_spi::VirtualSpiMasterDevice<'static, $S>,
40            >
41        );
42        // The RF233 radio stack requires four buffers for its SPI operations:
43        //
44        //   1. buf: a packet-sized buffer for SPI operations, which is
45        //      used as the read buffer when it writes a packet passed to it and the write
46        //      buffer when it reads a packet into a buffer passed to it.
47        //   2. rx_buf: buffer to receive packets into
48        //   3 + 4: two small buffers for performing registers
49        //      operations (one read, one write).
50        let rf233_buf = kernel::static_buf!([u8; kernel::hil::radio::MAX_BUF_SIZE]);
51        let rf233_reg_write =
52            kernel::static_buf!([u8; capsules_extra::rf233::SPI_REGISTER_TRANSACTION_LENGTH]);
53        let rf233_reg_read =
54            kernel::static_buf!([u8; capsules_extra::rf233::SPI_REGISTER_TRANSACTION_LENGTH]);
55
56        (spi_device, rf233_buf, rf233_reg_write, rf233_reg_read)
57    };};
58}
59
60pub struct RF233Component<S: SpiMaster<'static> + 'static> {
61    spi: &'static VirtualSpiMasterDevice<'static, S>,
62    reset: &'static dyn hil::gpio::Pin,
63    sleep: &'static dyn hil::gpio::Pin,
64    irq: &'static dyn hil::gpio::InterruptPin<'static>,
65    ctl: &'static dyn hil::gpio::InterruptPin<'static>,
66    channel: radio::RadioChannel,
67}
68
69impl<S: SpiMaster<'static> + 'static> RF233Component<S> {
70    pub fn new(
71        spi: &'static VirtualSpiMasterDevice<'static, S>,
72        reset: &'static dyn hil::gpio::Pin,
73        sleep: &'static dyn hil::gpio::Pin,
74        irq: &'static dyn hil::gpio::InterruptPin<'static>,
75        ctl: &'static dyn hil::gpio::InterruptPin<'static>,
76        channel: radio::RadioChannel,
77    ) -> Self {
78        Self {
79            spi,
80            reset,
81            sleep,
82            irq,
83            ctl,
84            channel,
85        }
86    }
87}
88
89impl<S: SpiMaster<'static> + 'static> Component for RF233Component<S> {
90    type StaticInput = (
91        &'static mut MaybeUninit<RF233<'static, VirtualSpiMasterDevice<'static, S>>>,
92        &'static mut MaybeUninit<[u8; hil::radio::MAX_BUF_SIZE]>,
93        &'static mut MaybeUninit<[u8; capsules_extra::rf233::SPI_REGISTER_TRANSACTION_LENGTH]>,
94        &'static mut MaybeUninit<[u8; capsules_extra::rf233::SPI_REGISTER_TRANSACTION_LENGTH]>,
95    );
96    type Output = &'static RF233<'static, VirtualSpiMasterDevice<'static, S>>;
97
98    fn finalize(self, s: Self::StaticInput) -> Self::Output {
99        let rf233_buf = s.1.write([0; hil::radio::MAX_BUF_SIZE]);
100        let rf233_reg_write =
101            s.2.write([0; capsules_extra::rf233::SPI_REGISTER_TRANSACTION_LENGTH]);
102        let rf233_reg_read =
103            s.3.write([0; capsules_extra::rf233::SPI_REGISTER_TRANSACTION_LENGTH]);
104        let rf233 = s.0.write(RF233::new(
105            self.spi,
106            rf233_buf,
107            rf233_reg_write,
108            rf233_reg_read,
109            self.reset,
110            self.sleep,
111            self.irq,
112            self.channel,
113        ));
114        self.ctl.set_client(rf233);
115        self.spi.set_client(rf233);
116        let _ = rf233.initialize();
117        rf233
118    }
119}