capsules_extra/
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//! Syscall driver capsule for CAN communication.
9//!
10//! This module has a CAN syscall driver capsule implementation.
11//!
12//! This capsule sends commands from the userspace to a driver that
13//! implements the Can trait.
14//!
15//! The capsule shares 2 buffers with the userspace: one RO that is used
16//! for transmitting messages and one RW that is used for receiving
17//! messages.
18//!
19//! The RO buffer uses the first 4 bytes as a counter of how many messages
20//! the userspace must read, at the time the upcall was sent. If the
21//! userspace is slower and in the meantime there were other messages
22//! that were received, the userspace reads them all and sends to the
23//! capsule a new buffer that has the counter on the first 4 bytes 0.
24//! Because of that, when receiving a callback from the driver regarding
25//! a received message, the capsule checks the counter:
26//! - if it's 0, the message will be copied to the RW buffer, the counter
27//!   will be incremented and an upcall will be sent
28//! - if it's greater the 0, the message will be copied to the RW buffer
29//!   but no upcall will be done
30//!
31//! Usage
32//! -----
33//!
34//! You need a driver that implements the Can trait.
35//! ```rust,ignore
36//! let grant_cap = create_capability!(capabilities::MemoryAllocationCapability);
37//! let grant_can = self.board_kernel.create_grant(
38//!     capsules::can::CanCapsule::DRIVER_NUM, &grant_cap);
39//! let can = capsules::can::CanCapsule::new(
40//!    can_peripheral,
41//!    grant_can,
42//!    tx_buffer,
43//!    rx_buffer,
44//! );
45//!
46//! kernel::hil::can::Controller::set_client(can_peripheral, Some(can));
47//! kernel::hil::can::Transmit::set_client(can_peripheral, Some(can));
48//! kernel::hil::can::Receive::set_client(can_peripheral, Some(can));
49//! ```
50//!
51
52use core::mem::size_of;
53
54use kernel::grant::{AllowRoCount, AllowRwCount, Grant, UpcallCount};
55use kernel::hil::can;
56use kernel::processbuffer::{ReadableProcessBuffer, WriteableProcessBuffer};
57use kernel::syscall::{CommandReturn, SyscallDriver};
58use kernel::utilities::cells::{OptionalCell, TakeCell};
59use kernel::utilities::streaming_process_slice::StreamingProcessSlice;
60use kernel::ErrorCode;
61use kernel::ProcessId;
62
63use capsules_core::driver;
64pub const DRIVER_NUM: usize = driver::NUM::Can as usize;
65pub const BYTE4_MASK: usize = 0xff000000;
66pub const BYTE3_MASK: usize = 0xff0000;
67pub const BYTE2_MASK: usize = 0xff00;
68pub const BYTE1_MASK: usize = 0xff;
69
70mod error_upcalls {
71    pub const ERROR_TX: usize = 100;
72    pub const ERROR_RX: usize = 101;
73}
74
75mod up_calls {
76    pub const UPCALL_ENABLE: usize = 0;
77    pub const UPCALL_DISABLE: usize = 1;
78    pub const UPCALL_MESSAGE_SENT: usize = 2;
79    pub const UPCALL_MESSAGE_RECEIVED: usize = 3;
80    pub const UPCALL_RECEIVED_STOPPED: usize = 4;
81    pub const UPCALL_TRANSMISSION_ERROR: usize = 5;
82    pub const COUNT: u8 = 6;
83}
84
85mod ro_allow {
86    pub const RO_ALLOW_BUFFER: usize = 0;
87    pub const COUNT: u8 = 1;
88}
89
90mod rw_allow {
91    pub const RW_ALLOW_BUFFER: usize = 0;
92    pub const COUNT: u8 = 1;
93}
94
95pub struct CanCapsule<'a, Can: can::Can> {
96    // CAN driver
97    can: &'a Can,
98
99    // CAN buffers
100    can_tx: TakeCell<'static, [u8; can::STANDARD_CAN_PACKET_SIZE]>,
101    can_rx: TakeCell<'static, [u8; can::STANDARD_CAN_PACKET_SIZE]>,
102
103    // Process
104    processes: Grant<
105        App,
106        UpcallCount<{ up_calls::COUNT }>,
107        AllowRoCount<{ ro_allow::COUNT }>,
108        AllowRwCount<{ rw_allow::COUNT }>,
109    >,
110    processid: OptionalCell<ProcessId>,
111
112    // Variable used to store the current state of the CAN peripheral
113    // during an `enable` or `disable` command.
114    peripheral_state: OptionalCell<can::State>,
115}
116
117#[derive(Default)]
118pub struct App {
119    lost_messages: u32,
120}
121
122impl<'a, Can: can::Can> CanCapsule<'a, Can> {
123    pub fn new(
124        can: &'a Can,
125        grant: Grant<
126            App,
127            UpcallCount<{ up_calls::COUNT }>,
128            AllowRoCount<{ ro_allow::COUNT }>,
129            AllowRwCount<{ rw_allow::COUNT }>,
130        >,
131        can_tx: &'static mut [u8; can::STANDARD_CAN_PACKET_SIZE],
132        can_rx: &'static mut [u8; can::STANDARD_CAN_PACKET_SIZE],
133    ) -> CanCapsule<'a, Can> {
134        CanCapsule {
135            can,
136            can_tx: TakeCell::new(can_tx),
137            can_rx: TakeCell::new(can_rx),
138            processes: grant,
139            peripheral_state: OptionalCell::empty(),
140            processid: OptionalCell::empty(),
141        }
142    }
143
144    fn schedule_callback(&self, callback_number: usize, data: (usize, usize, usize)) {
145        self.processid.map(|processid| {
146            let _ = self.processes.enter(processid, |_app, kernel_data| {
147                kernel_data
148                    .schedule_upcall(callback_number, (data.0, data.1, data.2))
149                    .ok();
150            });
151        });
152    }
153
154    /// This function makes a copy of the buffer in the grant and sends it
155    /// to the low-level hardware, in order for it to be sent on the bus.
156    pub fn process_send_command(
157        &self,
158        processid: ProcessId,
159        id: can::Id,
160        length: usize,
161    ) -> Result<(), ErrorCode> {
162        self.processes
163            .enter(processid, |_, kernel_data| {
164                kernel_data
165                    .get_readonly_processbuffer(ro_allow::RO_ALLOW_BUFFER)
166                    .map_or_else(
167                        |err| err.into(),
168                        |buffer_ref| {
169                            buffer_ref
170                                .enter(|buffer| {
171                                    self.can_tx.take().map_or(
172                                        Err(ErrorCode::NOMEM),
173                                        |dest_buffer| {
174                                            for i in 0..length {
175                                                dest_buffer[i] = buffer[i].get();
176                                            }
177                                            match self.can.send(id, dest_buffer, length) {
178                                                Ok(()) => Ok(()),
179                                                Err((err, buf)) => {
180                                                    self.can_tx.replace(buf);
181                                                    Err(err)
182                                                }
183                                            }
184                                        },
185                                    )
186                                })
187                                .unwrap_or_else(|err| err.into())
188                        },
189                    )
190            })
191            .unwrap_or_else(|err| err.into())
192    }
193
194    pub fn is_valid_process(&self, processid: ProcessId) -> bool {
195        self.processid.map_or(true, |owning_process| {
196            self.processes
197                .enter(owning_process, |_, _| owning_process == processid)
198                .unwrap_or(true)
199        })
200    }
201}
202
203impl<Can: can::Can> SyscallDriver for CanCapsule<'_, Can> {
204    fn command(
205        &self,
206        command_num: usize,
207        arg1: usize,
208        arg2: usize,
209        processid: ProcessId,
210    ) -> CommandReturn {
211        // This driver exists.
212        if command_num == 0 {
213            return CommandReturn::success();
214        }
215
216        // Check to see if the process or no process at all
217        // owns the capsule. Only one application can use the
218        // capsule at a time.
219        if !self.is_valid_process(processid) {
220            return CommandReturn::failure(ErrorCode::RESERVE);
221        } else {
222            self.processid.set(processid);
223        }
224
225        match command_num {
226            // Set the bitrate
227            1 => match self.can.set_bitrate(arg1 as u32) {
228                Ok(()) => CommandReturn::success(),
229                Err(err) => CommandReturn::failure(err),
230            },
231
232            // Set the operation mode (Loopback, Monitoring, etc)
233            2 => {
234                match self.can.set_operation_mode(match arg1 {
235                    0 => can::OperationMode::Loopback,
236                    1 => can::OperationMode::Monitoring,
237                    2 => can::OperationMode::Freeze,
238                    _ => can::OperationMode::Normal,
239                }) {
240                    Ok(()) => CommandReturn::success(),
241                    Err(err) => CommandReturn::failure(err),
242                }
243            }
244
245            // Enable the peripheral
246            3 => match self.can.enable() {
247                Ok(()) => CommandReturn::success(),
248                Err(err) => CommandReturn::failure(err),
249            },
250
251            // Disable the peripheral
252            4 => match self.can.disable() {
253                Ok(()) => CommandReturn::success(),
254                Err(err) => CommandReturn::failure(err),
255            },
256
257            // Send a message with a 16-bit identifier
258            5 => {
259                let id = can::Id::Standard(arg1 as u16);
260                self.processid
261                    .map_or(
262                        CommandReturn::failure(ErrorCode::BUSY),
263                        |processid| match self.process_send_command(processid, id, arg2) {
264                            Ok(()) => CommandReturn::success(),
265                            Err(err) => CommandReturn::failure(err),
266                        },
267                    )
268            }
269
270            // Send a message with a 32-bit identifier
271            6 => {
272                let id = can::Id::Extended(arg1 as u32);
273                self.processid
274                    .map_or(
275                        CommandReturn::failure(ErrorCode::BUSY),
276                        |processid| match self.process_send_command(processid, id, arg2) {
277                            Ok(()) => CommandReturn::success(),
278                            Err(err) => CommandReturn::failure(err),
279                        },
280                    )
281            }
282
283            // Start receiving messages
284            7 => {
285                self.can_rx
286                    .take()
287                    .map_or(CommandReturn::failure(ErrorCode::NOMEM), |dest_buffer| {
288                        self.processes
289                            .enter(processid, |_, kernel| {
290                                match kernel.get_readwrite_processbuffer(0).map_or_else(
291                                    |err| err.into(),
292                                    |buffer_ref| {
293                                        buffer_ref
294                                            .enter(|buffer| {
295                                                // make sure that the receiving buffer can have at least
296                                                // 2 messages of 8 bytes each and 4 another bytes for the counter
297                                                if buffer.len()
298                                                    >= 2 * can::STANDARD_CAN_PACKET_SIZE
299                                                        + size_of::<u32>()
300                                                {
301                                                    Ok(())
302                                                } else {
303                                                    Err(ErrorCode::SIZE)
304                                                }
305                                            })
306                                            .unwrap_or_else(|err| err.into())
307                                    },
308                                ) {
309                                    Ok(()) => match self.can.start_receive_process(dest_buffer) {
310                                        Ok(()) => CommandReturn::success(),
311                                        Err((err, _)) => CommandReturn::failure(err),
312                                    },
313                                    Err(err) => CommandReturn::failure(err),
314                                }
315                            })
316                            .unwrap_or_else(|err| err.into())
317                    })
318            }
319
320            // Stop receiving messages
321            8 => match self.can.stop_receive() {
322                Ok(()) => CommandReturn::success(),
323                Err(err) => CommandReturn::failure(err),
324            },
325
326            // Set the timing parameters
327            9 => {
328                match self.can.set_bit_timing(can::BitTiming {
329                    segment1: ((arg1 & BYTE4_MASK) >> 24) as u8,
330                    segment2: ((arg1 & BYTE3_MASK) >> 16) as u8,
331                    propagation: arg2 as u8,
332                    sync_jump_width: ((arg1 & BYTE2_MASK) >> 8) as u32,
333                    baud_rate_prescaler: (arg1 & BYTE1_MASK) as u32,
334                }) {
335                    Ok(()) => CommandReturn::success(),
336                    Err(err) => CommandReturn::failure(err),
337                }
338            }
339
340            _ => CommandReturn::failure(ErrorCode::NOSUPPORT),
341        }
342    }
343
344    fn allocate_grant(&self, process_id: ProcessId) -> Result<(), kernel::process::Error> {
345        self.processes.enter(process_id, |_, _| {})
346    }
347}
348
349impl<Can: can::Can> can::ControllerClient for CanCapsule<'_, Can> {
350    // This callback must be called after an `enable` or `disable` command was sent.
351    // It stores the new state of the peripheral.
352    fn state_changed(&self, state: can::State) {
353        self.peripheral_state.replace(state);
354    }
355
356    // This callback must be called after an `enable` command was sent and after a
357    // `state_changed` callback was called. If there is no error and the state of
358    // the peripheral is Running, send to the userspace a success callback.
359    // If the state is different or the status is an error, send to the userspace an
360    // error callback.
361    fn enabled(&self, status: Result<(), ErrorCode>) {
362        match status {
363            Ok(()) => match self.peripheral_state.take() {
364                Some(can::State::Running) => {
365                    self.schedule_callback(up_calls::UPCALL_ENABLE, (0, 0, 0));
366                }
367                Some(can::State::Error(err)) => {
368                    self.schedule_callback(up_calls::UPCALL_ENABLE, (err as usize, 0, 0));
369                }
370                Some(can::State::Disabled) | None => {
371                    self.schedule_callback(
372                        up_calls::UPCALL_ENABLE,
373                        (ErrorCode::OFF as usize, 0, 0),
374                    );
375                }
376            },
377            Err(err) => {
378                self.peripheral_state.take();
379                self.schedule_callback(up_calls::UPCALL_ENABLE, (err as usize, 0, 0));
380            }
381        }
382    }
383
384    // This callback must be called after an `disable` command was sent and after a
385    // `state_changed` callback was called. If there is no error and  the state of
386    // the peripheral is Disabled, send to the userspace a success callback.
387    // If the state is different or the status is an error, send to the userspace an
388    // error callback.
389    fn disabled(&self, status: Result<(), ErrorCode>) {
390        match status {
391            Ok(()) => match self.peripheral_state.take() {
392                Some(can::State::Disabled) => {
393                    self.schedule_callback(up_calls::UPCALL_DISABLE, (0, 0, 0));
394                }
395                Some(can::State::Error(err)) => {
396                    self.schedule_callback(up_calls::UPCALL_DISABLE, (err as usize, 0, 0));
397                }
398                Some(can::State::Running) | None => {
399                    self.schedule_callback(
400                        up_calls::UPCALL_DISABLE,
401                        (ErrorCode::FAIL as usize, 0, 0),
402                    );
403                }
404            },
405            Err(err) => {
406                self.peripheral_state.take();
407                self.schedule_callback(up_calls::UPCALL_ENABLE, (err as usize, 0, 0));
408            }
409        }
410        self.processid.clear();
411    }
412}
413
414impl<Can: can::Can> can::TransmitClient<{ can::STANDARD_CAN_PACKET_SIZE }> for CanCapsule<'_, Can> {
415    // This callback is called when the hardware acknowledges that a message
416    // was sent. This callback also makes an upcall to the userspace.
417    fn transmit_complete(
418        &self,
419        status: Result<(), can::Error>,
420        buffer: &'static mut [u8; can::STANDARD_CAN_PACKET_SIZE],
421    ) {
422        self.can_tx.replace(buffer);
423        match status {
424            Ok(()) => self.schedule_callback(up_calls::UPCALL_MESSAGE_SENT, (0, 0, 0)),
425            Err(err) => {
426                self.schedule_callback(
427                    up_calls::UPCALL_TRANSMISSION_ERROR,
428                    (error_upcalls::ERROR_TX, err as usize, 0),
429                );
430            }
431        }
432    }
433}
434
435impl<Can: can::Can> can::ReceiveClient<{ can::STANDARD_CAN_PACKET_SIZE }> for CanCapsule<'_, Can> {
436    // This callback is called when a new message is received on any receiving
437    // fifo.
438    fn message_received(
439        &self,
440        id: can::Id,
441        buffer: &mut [u8; can::STANDARD_CAN_PACKET_SIZE],
442        _len: usize,
443        status: Result<(), can::Error>,
444    ) {
445        match status {
446            Ok(()) => {
447                let res: Result<(bool, u32), ErrorCode> =
448                    self.processid.map_or(Err(ErrorCode::NOMEM), |processid| {
449                        self.processes
450                            .enter(processid, |app_data, kernel_data| {
451                                kernel_data
452                                    .get_readwrite_processbuffer(rw_allow::RW_ALLOW_BUFFER)
453                                    .map_or_else(
454                                        |err| Err(err.into()),
455                                        |buffer_ref| {
456                                            buffer_ref
457                                                .mut_enter(|user_slice| {
458                                                    StreamingProcessSlice::new(user_slice)
459                                                        .append_chunk(buffer)
460                                                        .inspect_err(|_err| {
461                                                            app_data.lost_messages += 1;
462                                                        })
463                                                })
464                                                .unwrap_or_else(|err| Err(err.into()))
465                                        },
466                                    )
467                            })
468                            .unwrap_or_else(|err| Err(err.into()))
469                    });
470
471                match res {
472                    Err(err) => self.schedule_callback(
473                        up_calls::UPCALL_TRANSMISSION_ERROR,
474                        (error_upcalls::ERROR_RX, err as usize, 0),
475                    ),
476                    Ok((_first_chunk, new_offset)) => self.schedule_callback(
477                        up_calls::UPCALL_MESSAGE_RECEIVED,
478                        (
479                            0,
480                            new_offset as usize,
481                            match id {
482                                can::Id::Standard(u16) => u16 as usize,
483                                can::Id::Extended(u32) => u32 as usize,
484                            },
485                        ),
486                    ),
487                }
488            }
489            Err(err) => {
490                let kernel_err: ErrorCode = err.into();
491                self.schedule_callback(
492                    up_calls::UPCALL_TRANSMISSION_ERROR,
493                    (error_upcalls::ERROR_RX, kernel_err.into(), 0),
494                )
495            }
496        }
497    }
498
499    fn stopped(&self, buffer: &'static mut [u8; can::STANDARD_CAN_PACKET_SIZE]) {
500        self.can_rx.replace(buffer);
501        self.schedule_callback(up_calls::UPCALL_RECEIVED_STOPPED, (0, 0, 0));
502    }
503}