components/
can.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// Copyright OxidOS Automotive SRL 2022
5//
6// Author: Teona Severin <teona.severin@oxidos.io>
7
8//! Component for CAN syscall interface.
9//!
10//! This provides one Component, `CanComponent`, which implements a
11//! userspace syscall interface to the Can peripheral.
12//!
13//! Usage
14//! -----
15//! ```rust
16//! let can = components::can::CanComponent::new(
17//!     board_kernel,
18//!     capsules_extra::can::DRIVER_NUM,
19//!     &peripherals.can1
20//! ).finalize(components::can_component_static!(
21//!     stm32f429zi::can::Can<'static>
22//! ));
23//! ```
24//!
25
26use capsules_extra::can::CanCapsule;
27use core::mem::MaybeUninit;
28use kernel::component::Component;
29use kernel::hil::can;
30use kernel::{capabilities, create_capability};
31
32#[macro_export]
33macro_rules! can_component_static {
34    ($C:ty $(,)?) => {{
35        use capsules_extra::can::CanCapsule;
36        use core::mem::MaybeUninit;
37        use kernel::hil::can;
38        use kernel::static_buf;
39
40        let CAN_TX_BUF = static_buf!([u8; can::STANDARD_CAN_PACKET_SIZE]);
41        let CAN_RX_BUF = static_buf!([u8; can::STANDARD_CAN_PACKET_SIZE]);
42        let can = static_buf!(capsules_extra::can::CanCapsule<'static, $C>);
43        (can, CAN_TX_BUF, CAN_RX_BUF)
44    };};
45}
46
47pub struct CanComponent<A: 'static + can::Can> {
48    board_kernel: &'static kernel::Kernel,
49    driver_num: usize,
50    can: &'static A,
51}
52
53impl<A: 'static + can::Can> CanComponent<A> {
54    pub fn new(
55        board_kernel: &'static kernel::Kernel,
56        driver_num: usize,
57        can: &'static A,
58    ) -> CanComponent<A> {
59        CanComponent {
60            board_kernel,
61            driver_num,
62            can,
63        }
64    }
65}
66
67impl<A: 'static + can::Can> Component for CanComponent<A> {
68    type StaticInput = (
69        &'static mut MaybeUninit<CanCapsule<'static, A>>,
70        &'static mut MaybeUninit<[u8; can::STANDARD_CAN_PACKET_SIZE]>,
71        &'static mut MaybeUninit<[u8; can::STANDARD_CAN_PACKET_SIZE]>,
72    );
73    type Output = &'static CanCapsule<'static, A>;
74
75    fn finalize(self, static_buffer: Self::StaticInput) -> Self::Output {
76        let grant_cap = create_capability!(capabilities::MemoryAllocationCapability);
77        let grant_can = self.board_kernel.create_grant(self.driver_num, &grant_cap);
78
79        let can = static_buffer.0.write(capsules_extra::can::CanCapsule::new(
80            self.can,
81            grant_can,
82            static_buffer.1.write([0; can::STANDARD_CAN_PACKET_SIZE]),
83            static_buffer.2.write([0; can::STANDARD_CAN_PACKET_SIZE]),
84        ));
85        can::Controller::set_client(self.can, Some(can));
86        can::Transmit::set_client(self.can, Some(can));
87        can::Receive::set_client(self.can, Some(can));
88
89        can
90    }
91}