kernel/hil/
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//! Interface for CAN peripherals.
9//!
10//! Defines multiple traits for different purposes.
11//!
12//! The `Configure` trait is used to configure the communication
13//! mode and bit timing parameters of the CAN peripheral. The
14//! `ConfigureFd` trait is an advanced feature that can be implemented
15//! for peripherals that support flexible data messages. These
16//! 2 traits represent synchronous actions and do not need a client
17//! in order to confirm to the capsule that the action is finished.
18//!
19//! The `Controller` trait is used to enable and disable the device.
20//! In order to be able to enable the device, the bit timing parameters
21//! and the communication mode must be previously set, and in order
22//! to disable the device, it must be enabled. This trait defines
23//! asynchronous behaviours and because of that, the `ControllerClient`
24//! trait is used to confirm to the capsule that the action is finished.
25//!
26//! The `Filter` trait is used to configure filter banks for receiving
27//! messages. The action is synchronous.
28//!
29//! The `Transmit` trait is used to asynchronously send a message on
30//! the CAN bus. The device must be previously enabled. The
31//! `TransmitClient` trait is used to notify the capsule when the
32//! transmission is done or when there was en error captured during
33//! the transmission.
34//!
35//! The `Receive` trait is used to asynchronously receive messages on
36//! the CAN bus. The `ReceiveClient` trait is used to notify the capsule
37//! when a message was received, when the receiving process was aborted
38//! and anytime an error occurs.
39//!
40
41use crate::ErrorCode;
42use core::cmp;
43
44pub const STANDARD_CAN_PACKET_SIZE: usize = 8;
45pub const FD_CAN_PACKET_SIZE: usize = 64;
46
47/// Defines the possible states of the peripheral
48#[derive(Debug, Copy, Clone, PartialEq, Eq)]
49pub enum State {
50    /// The peripheral is enabled and functions normally
51    Running,
52
53    /// The peripheral is disabled
54    Disabled,
55
56    /// There was an error while executing a request (sending
57    /// or receiving)
58    Error(Error),
59}
60
61/// Defines the error codes received from the CAN peripheral
62#[derive(Debug, Copy, Clone, PartialEq, Eq)]
63pub enum Error {
64    /// The previous transmission failed due to an arbitration
65    /// lost
66    ArbitrationLost,
67
68    /// The previous transmission failed
69    Transmission,
70
71    /// The internal Transmit Error Counter or the internal
72    /// Receive Error Counter is greater than 96 and the
73    /// passive error state is entered.
74    Warning,
75
76    /// The internal Transmit Error Counter or the internal
77    /// Receive Error Counter is greater than 127 and the
78    /// passive error state is entered.
79    Passive,
80
81    /// The internal Transmit Error Counter is greater than 255
82    /// and the bus-off state is entered.
83    BusOff,
84
85    /// 6 consecutive bits of equal value are detected on the bus.
86    /// (When transmitting device detects 5 consecutive bits of
87    /// equal value on the bus, it inserts a complemented one).
88    Stuff,
89
90    /// The form of the received or the transmitted frame is
91    /// different than the standard format.
92    Form,
93
94    /// There are no receivers on the bus or the sender caused an
95    /// error.
96    Ack,
97
98    /// While transmitting a recessive bit, the receiver sensed a
99    /// dominant bit.
100    BitRecessive,
101
102    /// While transmitting a dominant bit, the receiver sensed a
103    /// recessive bit.
104    BitDominant,
105
106    /// The frame has been corrupted on the CAN bus
107    Crc,
108
109    /// Set by software to force the hardware to indicate the
110    /// current communication status.
111    SetBySoftware,
112}
113
114impl From<Error> for ErrorCode {
115    fn from(val: Error) -> Self {
116        match val {
117            Error::ArbitrationLost => ErrorCode::RESERVE,
118            Error::BusOff => ErrorCode::OFF,
119            Error::Form => ErrorCode::INVAL,
120            Error::BitRecessive | Error::BitDominant => ErrorCode::BUSY,
121            Error::Ack | Error::Transmission => ErrorCode::NOACK,
122            Error::Crc | Error::SetBySoftware | Error::Warning | Error::Passive | Error::Stuff => {
123                ErrorCode::FAIL
124            }
125        }
126    }
127}
128
129/// The Scale Bits structure defines the 2 possible widths
130/// of the filter bank
131#[derive(Debug, Copy, Clone)]
132pub enum ScaleBits {
133    Bits16,
134    Bits32,
135}
136
137/// The filter can be configured to filter the messages by matching
138/// an identifier or by bitwise matching multiple identifiers.
139#[derive(Debug, Copy, Clone)]
140pub enum IdentifierMode {
141    /// A mask is used to filter the messages
142    List,
143    /// The value of the identifier is used to filter the messages
144    Mask,
145}
146
147/// The identifier can be standard (11 bits) or extended (29 bits)
148#[derive(Debug, Copy, Clone)]
149pub enum Id {
150    Standard(u16),
151    Extended(u32),
152}
153
154/// This structure defines the parameters to configure a filter bank
155#[derive(Copy, Clone)]
156pub struct FilterParameters {
157    /// The filter Id
158    ///
159    /// This value is dependent on the peripheral used and identifies
160    /// the filter bank that will be used
161    pub number: u32,
162
163    /// The width of the filter bank
164    pub scale_bits: ScaleBits,
165
166    /// The way in which the message Ids will be filtered.
167    pub identifier_mode: IdentifierMode,
168
169    /// The receive FIFO Id that the filter will be applied to
170    pub fifo_number: usize,
171}
172
173/// This structure defines the parameters for the timing mode
174#[derive(Debug, Copy, Clone)]
175pub struct BitTiming {
176    /// A value that defines the location of the sample
177    /// point (between 1 and 16 time quanta)
178    pub segment1: u8,
179
180    /// A value that defines the location of the transmit
181    /// point (between 1 and 8 time quanta)
182    pub segment2: u8,
183
184    /// A value used for compensating the delay on the bus
185    /// lines
186    pub propagation: u8,
187
188    /// A value that represents the maximum time by which
189    /// the bit sampling period may lengthen or shorten
190    /// each cycle to perform the resynchronization. It is
191    /// measured in time quanta.
192    pub sync_jump_width: u32,
193
194    /// A value that represents the sampling clock period.
195    /// A period is reffered to as a time quanta.
196    pub baud_rate_prescaler: u32,
197}
198
199/// The peripheral can be configured to work in the following modes:
200#[derive(Debug, Copy, Clone)]
201pub enum OperationMode {
202    /// Loopback mode means that each message is transmitted on the
203    /// TX channel and immediately received on the RX channel
204    Loopback,
205
206    /// Monitoring mode means that the CAN peripheral sends only the recessive
207    /// bits on the bus and cannot start a transmission, but can receive
208    /// valid data frames and valid remote frames
209    Monitoring,
210
211    /// Freeze mode means that no transmission or reception of frames is
212    /// done
213    Freeze,
214
215    /// Normal mode means that the transmission and reception of frames
216    /// are available
217    Normal,
218}
219
220/// The `StandardBitTiming` trait is used to calculate the optimum timing parameters
221/// for a given bitrate and the clock's frequency.
222pub trait StandardBitTiming {
223    fn bit_timing_for_bitrate(clock_rate: u32, bitrate: u32) -> Result<BitTiming, ErrorCode>;
224}
225
226/// The default implementation for the `bit_timing_for_bitrate` method. This algorithm
227/// is inspired by the Zephyr CAN driver available at
228/// `<https://github.com/zephyrproject-rtos/zephyr/tree/main/drivers/can>`
229impl<T: Configure> StandardBitTiming for T {
230    fn bit_timing_for_bitrate(clock_rate: u32, bitrate: u32) -> Result<BitTiming, ErrorCode> {
231        if bitrate > 8_000_000 {
232            return Err(ErrorCode::INVAL);
233        }
234
235        let mut res_timing: BitTiming = Self::MIN_BIT_TIMINGS;
236        let sp: u32 = if bitrate > 800_000 {
237            750
238        } else if bitrate > 500_000 {
239            800
240        } else {
241            875
242        };
243        let mut sample_point_err;
244        let mut sample_point_err_min = u16::MAX;
245        let mut ts: u32 = (Self::MAX_BIT_TIMINGS.propagation
246            + Self::MAX_BIT_TIMINGS.segment1
247            + Self::MAX_BIT_TIMINGS.segment2
248            + Self::SYNC_SEG) as u32;
249
250        for prescaler in
251            cmp::max(clock_rate / (ts * bitrate), 1)..Self::MAX_BIT_TIMINGS.baud_rate_prescaler
252        {
253            if clock_rate % (prescaler * bitrate) != 0 {
254                continue;
255            }
256            ts = clock_rate / (prescaler * bitrate);
257
258            sample_point_err = {
259                let ts1_max = Self::MAX_BIT_TIMINGS.propagation + Self::MAX_BIT_TIMINGS.segment1;
260                let ts1_min = Self::MIN_BIT_TIMINGS.propagation + Self::MIN_BIT_TIMINGS.segment1;
261                let mut ts1;
262                let mut ts2;
263                let mut res: i32 = 0;
264
265                ts2 = ts - (ts * sp) / 1000;
266                ts2 = if ts2 < Self::MIN_BIT_TIMINGS.segment2 as u32 {
267                    Self::MIN_BIT_TIMINGS.segment2 as u32
268                } else if ts2 > Self::MAX_BIT_TIMINGS.segment2 as u32 {
269                    Self::MAX_BIT_TIMINGS.segment2 as u32
270                } else {
271                    ts2
272                };
273                ts1 = ts - Self::SYNC_SEG as u32 - ts2;
274
275                if ts1 > ts1_max as u32 {
276                    ts1 = ts1_max as u32;
277                    ts2 = ts - Self::SYNC_SEG as u32 - ts1;
278                    if ts2 > Self::MAX_BIT_TIMINGS.segment2 as u32 {
279                        res = -1;
280                    }
281                } else if ts1 < ts1_min as u32 {
282                    ts1 = ts1_min as u32;
283                    ts2 = ts - ts1;
284                    if ts2 < Self::MIN_BIT_TIMINGS.segment2 as u32 {
285                        res = -1;
286                    }
287                }
288
289                if res != -1 {
290                    res_timing.propagation = if ts1 / 2 < Self::MIN_BIT_TIMINGS.propagation as u32 {
291                        Self::MIN_BIT_TIMINGS.propagation
292                    } else if ts1 / 2 > Self::MAX_BIT_TIMINGS.propagation as u32 {
293                        Self::MAX_BIT_TIMINGS.propagation
294                    } else {
295                        (ts1 / 2) as u8
296                    };
297
298                    res_timing.segment1 = ts1 as u8 - res_timing.propagation;
299                    res_timing.segment2 = ts2 as u8;
300
301                    res = ((Self::SYNC_SEG as u32 + ts1) * 1000 / ts) as i32;
302                    if res > sp as i32 {
303                        res - sp as i32
304                    } else {
305                        sp as i32 - res
306                    }
307                } else {
308                    res
309                }
310            };
311
312            if sample_point_err < 0 {
313                continue;
314            }
315
316            if sample_point_err < sample_point_err_min as i32 {
317                sample_point_err_min = sample_point_err as u16;
318                res_timing.baud_rate_prescaler = prescaler;
319                if sample_point_err == 0 {
320                    break;
321                }
322            }
323        }
324
325        if sample_point_err_min != 0 {
326            return Err(ErrorCode::INVAL);
327        }
328
329        Ok(BitTiming {
330            segment1: res_timing.segment1 - 1,
331            segment2: res_timing.segment2 - 1,
332            propagation: res_timing.propagation,
333            sync_jump_width: if res_timing.sync_jump_width == 0 {
334                0
335            } else {
336                res_timing.sync_jump_width - 1
337            },
338            baud_rate_prescaler: res_timing.baud_rate_prescaler - 1,
339        })
340    }
341}
342
343/// The `Configure` trait is used to configure the CAN peripheral and to prepare it for
344/// transmission and reception of data.
345///
346/// The peripheral cannot transmit or receive frames if it is not
347/// previously configured and enabled.
348///
349/// In order to configure the peripheral, the following steps are required:
350///
351/// - Call `set_bitrate` or `set_bit_timing` to configure the timing settings
352/// - Call `set_operation_mode` to configure the testing mode
353/// - (Optional) Call `set_automatic_retransmission` and/or
354///   `set_wake_up` to configure the behaviour of the peripheral
355/// - To apply the settings and be able to use the peripheral, call `enable`
356///   (from the `Controller` trait)
357pub trait Configure {
358    /// Constants that define the minimum and maximum values that the timing
359    /// parameters can take. They are used when calculating the optimum timing
360    /// parameters for a given bitrate.
361    const MIN_BIT_TIMINGS: BitTiming;
362    const MAX_BIT_TIMINGS: BitTiming;
363
364    /// This constant represents the synchronization segment.
365    /// Most CAN devices seems to have define this in hardware to 1 quantum long.
366    /// 1 quantum long. It is used for the synchronization of the clocks.
367    const SYNC_SEG: u8 = 1;
368
369    /// Configures the CAN peripheral at the given bitrate. This function is
370    /// supposed to be called before the `enable` function. This function is
371    /// synchronous as the driver should only calculate the timing parameters
372    /// based on the bitrate and the frequency of the board and store them.
373    /// This function does not configure the hardware.
374    ///
375    /// # Arguments:
376    ///
377    /// * `bitrate` - A value that represents the bitrate for the CAN communication.
378    ///
379    /// # Return values:
380    ///
381    /// * `Ok()` - The timing parameters were calculated and stored.
382    /// * `Err(ErrorCode)` - Indicates the error because of which the request
383    ///   cannot be completed
384    fn set_bitrate(&self, bitrate: u32) -> Result<(), ErrorCode>;
385
386    /// Configures the CAN peripheral with the given arguments. This function is
387    /// supposed to be called before the `enable` function. This function is
388    /// synchronous as the driver should only store the arguments, and should not
389    /// configure the hardware.
390    ///
391    /// # Arguments:
392    ///
393    /// * `bit_timing` - A BitTiming structure to define the bit timing settings
394    ///   for the peripheral
395    ///
396    /// # Return values:
397    ///
398    /// * `Ok()` - The parameters were stored.
399    /// * `Err(ErrorCode)` - Indicates the error because of which the request
400    ///   cannot be completed
401    fn set_bit_timing(&self, bit_timing: BitTiming) -> Result<(), ErrorCode>;
402
403    /// Configures the CAN peripheral with the given arguments. This function is
404    /// supposed to be called before the `enable` function. This function is
405    /// synchronous as the driver should only store the arguments, and should not
406    /// configure the hardware.
407    ///
408    /// # Arguments:
409    ///
410    /// * `mode` - An OperationMode structure to define the running mode of the
411    ///   peripheral
412    ///
413    /// # Return values:
414    ///
415    /// * `Ok()` - The parameters were stored.
416    /// * `Err(ErrorCode)` - Indicates the error because of which the request
417    ///   cannot be completed
418    fn set_operation_mode(&self, mode: OperationMode) -> Result<(), ErrorCode>;
419
420    /// Returns the current timing parameters for the CAN peripheral.
421    ///
422    /// # Return values:
423    ///
424    /// * `Ok(BitTiming)` - The current timing parameters given to the
425    ///   peripheral
426    /// * `Err(ErrorCode)` - Indicates the error because of which the request
427    ///   cannot be completed
428    fn get_bit_timing(&self) -> Result<BitTiming, ErrorCode>;
429
430    /// Returns the current operating mode for the CAN peripheral.
431    ///
432    /// # Return values:
433    ///
434    /// * `Ok(OperationMode)` - The current operating mode parameter given to
435    ///   the peripheral
436    /// * `Err(ErrorCode)` - Indicates the error because of which the request
437    ///   cannot be completed
438    fn get_operation_mode(&self) -> Result<OperationMode, ErrorCode>;
439
440    /// Configures the CAN peripheral with the automatic retransmission setting.
441    /// This function is optional, but if used, must be called before the
442    /// `enable` function. This function is synchronous as the driver should
443    /// only store the arguments, and should not configure the hardware.
444    ///
445    /// # Arguments:
446    ///
447    /// * `automatic` - Value to configure the automatic retransmission setting
448    ///
449    /// # Return values:
450    ///
451    /// * `Ok()` - The setting was stored.
452    /// * `Err(ErrorCode)` - Indicates the error because of which the request
453    ///   cannot be completed
454    fn set_automatic_retransmission(&self, automatic: bool) -> Result<(), ErrorCode>;
455
456    /// Configures the CAN peripheral with the automatic wake up setting.
457    /// This function is optional, but if used, must be called before the
458    /// `enable` function. This function is synchronous as the driver should
459    /// only store the arguments, and should not configure the hardware.
460    ///
461    /// # Arguments:
462    ///
463    /// * `wake_up` - Value to configure the automatic wake up setting
464    ///
465    /// # Return values:
466    ///
467    /// * `Ok()` - The setting was stored.
468    /// * `Err(ErrorCode)` - Indicates the error because of which the request
469    ///   cannot be completed
470    fn set_wake_up(&self, wake_up: bool) -> Result<(), ErrorCode>;
471
472    /// Returns the current automatic retransmission setting of the peripheral.
473    ///
474    /// # Return values:
475    ///
476    /// * `Ok(bool)` - The current automatic retransmission setting
477    /// * `Err(ErrorCode)` - Indicates the error because of which the request
478    ///   cannot be completed
479    fn get_automatic_retransmission(&self) -> Result<bool, ErrorCode>;
480
481    /// Returns the current automatic wake up setting of the peripheral.
482    ///
483    /// # Return values:
484    ///
485    /// * `Ok(bool)` - The current automatic wake up setting
486    /// * `Err(ErrorCode)` - Indicates the error because of which the request
487    ///   cannot be completed
488    fn get_wake_up(&self) -> Result<bool, ErrorCode>;
489
490    /// Returns the number of receive FIFOs the peripheral provides
491    fn receive_fifo_count(&self) -> usize;
492}
493
494/// The `ConfigureFd` trait is used to configure the CAN peripheral
495/// for CanFD and to prepare it for transmission and reception of
496/// data.
497///
498/// The peripheral cannot transmit or receive frames if it is not
499/// previously configured and enabled.
500///
501/// In order to configure the peripheral, the following steps are required:
502///
503/// - Call `set_bit_timing` to configure the timing settings
504/// - Call `set_operation_mode` to configure the testing mode
505/// - (Optional) Call `set_automatic_retransmission` and/or
506///   `set_wake_up` to configure the behaviour of the peripheral
507/// - To apply the settings and be able to use the peripheral, call `enable`
508///   (from the `Controller` trait)
509pub trait ConfigureFd: Configure {
510    /// Configures the CAN FD peripheral with the given arguments. This function is
511    /// supposed to be called before the `enable` function. This function is
512    /// synchronous as the driver should only store the arguments, and should not
513    /// configure the hardware.
514    ///
515    /// # Arguments:
516    ///
517    /// * `payload_bit_timing` - A BitTiming structure to define the bit timing
518    ///   settings for the frame payload
519    ///
520    /// # Return values:
521    ///
522    /// * `Ok()` - The parameters were stored.
523    /// * `Err(ErrorCode)` - Indicates the error because of which the request
524    ///   cannot be completed
525    ///   - `ErrorCode::NOSUPPORT` indicates that payload timing is not
526    ///     supported
527    fn set_payload_bit_timing(&self, payload_bit_timing: BitTiming) -> Result<(), ErrorCode>;
528
529    /// Returns the current timing parameters for the CAN peripheral.
530    ///
531    /// # Return values:
532    ///
533    /// * `Ok(BitTiming)` - The current timing for the frame payload given to
534    ///   the peripheral
535    /// * `Err(ErrorCode)` - Indicates the error because of which the request
536    ///   cannot be completed
537    ///   - `ErrorCode::NOSUPPORT` indicates that payload timing is not
538    ///     supported
539    fn get_payload_bit_timing(&self) -> Result<BitTiming, ErrorCode>;
540
541    /// Returns the maximum accepted frame size in bytes.
542    ///
543    /// - for CanFD BRS this should be 8 bytes
544    /// - for CanFD Full this should be 64 bytes
545    fn get_frame_size() -> usize;
546}
547
548/// The `Filter` trait is used to enable and disable a filter bank.
549///
550/// When the receiving process starts by calling the `start_receiving_process`
551/// in the `Receive` trait, there MUST be no filter enabled.
552pub trait Filter {
553    /// Enables a filter for message reception.
554    ///
555    /// # Arguments:
556    ///
557    /// * `filter` - A FilterParameters structure to define the filter
558    ///   configuration
559    ///
560    /// # Return values:
561    ///
562    /// * `Ok()` - The filter was successfully configured.
563    /// * `Err(ErrorCode)` - indicates the error because of which the request
564    ///   cannot be completed
565    fn enable_filter(&self, filter: FilterParameters) -> Result<(), ErrorCode>;
566
567    /// Disables a filter.
568    ///
569    /// # Arguments:
570    ///
571    /// * `number` - The filter Id to identify the filter bank to disable
572    ///
573    /// # Return values:
574    ///
575    /// * `Ok()` - The filter was successfully disabled.
576    /// * `Err(ErrorCode)` - indicates the error because of which the request
577    ///   cannot be completed
578    fn disable_filter(&self, number: u32) -> Result<(), ErrorCode>;
579
580    /// Returns the number of filters the peripheral provides
581    fn filter_count(&self) -> usize;
582}
583
584/// The `Controller` trait is used to enable and disable the CAN peripheral.
585/// The enable process applies the settings that were previously provided
586/// to the driver using the `Configure` trait.
587pub trait Controller {
588    /// Set the client to be used for callbacks of the `Controller` implementation.
589    fn set_client(&self, client: Option<&'static dyn ControllerClient>);
590
591    /// This function enables the CAN peripheral with the Timing, Operation and Mode
592    /// arguments that are provided to the driver before calling the
593    /// `enable` function.
594    ///
595    /// # Return values:
596    ///
597    /// * `Ok()` - The parameters were provided and the process can begin. The
598    ///   driver will call the `state_changed` and `enabled` callbacks after the
599    ///   process ends. Both of the callbacks must be called and the capsule
600    ///   should wait for the `enable` callback before transmitting or receiving
601    ///   frames, as enabling might fail with an error. While `state_changed`
602    ///   will report the device as being in `State::Disabled`, it does not
603    ///   report the error. A client cannot otherwise differentiate between a
604    ///   callback issued due to failed `enable` or a peripheral's decision to
605    ///   enter a disabled state.
606    /// * `Err(ErrorCode)` - Indicates the error because of which the request
607    ///   cannot be completed.
608    ///     * `ErrorCode::BUSY` - the peripheral was already enabled
609    ///     * `ErrorCode::INVAL` - no arguments were previously provided
610    fn enable(&self) -> Result<(), ErrorCode>;
611
612    /// This function disables the CAN peripheral and puts it in Sleep Mode. The
613    /// peripheral must be previously enabled.
614    ///
615    /// # Return values:
616    ///
617    /// * `Ok()` - The peripheral was already enabled and the process can begin.
618    ///   The driver will call the `state_changed` and `disabled` callbacks
619    ///   after the process ends. Both of the callbacks must be called and the
620    ///   capsule should wait for the `disabled` callback before considering the
621    ///   peripheral disabled, as disabling might fail with an erro . While
622    ///   `state_changed` will report the device as being in `State::Enabled`,
623    ///   it does not report the error. A client cannot otherwise differentiate
624    ///   between a callback issued due to failed `disable` or a peripheral's
625    ///   decision to enter the enable state.
626    /// * `Err(ErrorCode)` - Indicates the error because of which the request
627    ///   cannot be completed.
628    ///     * `ErrorCode::OFF` - the peripheral was not previously enabled
629    fn disable(&self) -> Result<(), ErrorCode>;
630
631    /// This function returns the current state of the CAN peripheral.
632    ///
633    /// # Return values:
634    ///
635    /// * `Ok(State)` - The state of the CAN peripheral if it is functional
636    /// * `Err(ErrorCode)` - The driver cannot report the state of the
637    ///   peripheral if it is not functional.
638    fn get_state(&self) -> Result<State, ErrorCode>;
639}
640
641/// The `Transmit` trait is used to interact with the CAN driver through transmission
642/// requests only.
643///
644/// The CAN peripheral must be configured first, in order to be able to send data.
645pub trait Transmit<const PACKET_SIZE: usize> {
646    const PACKET_SIZE: usize = PACKET_SIZE;
647    /// Set the client to be used for callbacks of the `Transmit` implementation.
648    fn set_client(&self, client: Option<&'static dyn TransmitClient<PACKET_SIZE>>);
649
650    /// Sends a buffer using the CAN bus.
651    ///
652    /// In most cases, this function should be called after the peripheral was
653    /// previously configures and at least one filter has been enabled.
654    ///
655    /// # Arguments:
656    ///
657    /// * `id` - The identifier of the message (standard or extended)
658    /// * `buffer` - Data to be written on the bus
659    /// * `len` - Length of the current message
660    ///
661    /// # Return values:
662    /// * `Ok()` - The transmission request was successful and the caller will
663    ///   receive a for the `transmit_complete` callback function call
664    /// * `Err(ErrorCode, &'static mut [u8])` - a tuple with the error that
665    ///   occurred during the transmission request and the buffer that was
666    ///   provided as an argument to the function
667    fn send(
668        &self,
669        id: Id,
670        buffer: &'static mut [u8; PACKET_SIZE],
671        len: usize,
672    ) -> Result<(), (ErrorCode, &'static mut [u8; PACKET_SIZE])>;
673}
674
675/// The `Receive` trait is used to interact with the CAN driver through receive
676/// requests only.
677///
678/// The CAN peripheral must be configured first, in order to be able to send data.
679pub trait Receive<const PACKET_SIZE: usize> {
680    const PACKET_SIZE: usize = PACKET_SIZE;
681    /// Set the client to be used for callbacks of the `Receive` implementation.
682    fn set_client(&self, client: Option<&'static dyn ReceiveClient<PACKET_SIZE>>);
683
684    /// Start receiving messaged on the CAN bus.
685    ///
686    /// In most cases, this function should be called after the peripheral was
687    /// previously configured. When calling this function, there MUST be
688    /// no filters enabled by the user. The implementation of this function
689    /// MUST permit receiving frames on all available receiving FIFOs.
690    ///
691    /// # Arguments:
692    ///
693    /// * `buffer` - A buffer to store the data
694    ///
695    /// # Return values:
696    ///
697    /// * `Ok()` - The receive request was successful and the caller waits for
698    ///   the `message_received` callback function to receive data
699    /// * `Err(ErrorCode, &'static mut [u8])` - tuple with the error that
700    ///   occurred during the reception request and the buffer that was received
701    ///   as an argument to the function
702    fn start_receive_process(
703        &self,
704        buffer: &'static mut [u8; PACKET_SIZE],
705    ) -> Result<(), (ErrorCode, &'static mut [u8; PACKET_SIZE])>;
706
707    /// Asks the driver to stop receiving messages. This function should
708    /// be called only after a call to the `start_receive_process` function.
709    ///
710    /// # Return values:
711    ///
712    /// * `Ok()` - The request was successful an the caller waits for the
713    ///   `stopped` callback function after this command
714    /// * `Err(ErrorCode)` - Indicates the error because of which the request
715    ///   cannot be completed
716    fn stop_receive(&self) -> Result<(), ErrorCode>;
717}
718
719/// Client interface for capsules that implement the `Controller` trait.
720pub trait ControllerClient {
721    /// The driver calls this function when the state of the CAN peripheral is
722    /// changed.
723    ///
724    /// # Arguments:
725    ///
726    /// * `state` - The current state of the peripheral
727    fn state_changed(&self, state: State);
728
729    /// The driver calls this function when the peripheral has been successfully
730    /// enabled. The driver must call this function and `state_changed` also,
731    /// but must wait for this function to be called. If an error occurs, the
732    /// `state_changed` callback might not be able to report it.
733    ///
734    /// # Arguments:
735    ///
736    /// * `status`
737    ///     * `Ok()` - The peripheral has been successfully enabled; the actual
738    ///       state is transmitted via `state_changed` callback
739    ///     * `Err(ErrorCode)` - The error that occurred during the enable process
740    fn enabled(&self, status: Result<(), ErrorCode>);
741
742    /// The driver calls this function when the peripheral has been successfully
743    /// disabled. The driver must call this function and `state_changed` also,
744    /// but must wait for this function to be called. If an error occurs, the
745    /// `state_changed` callback might not be able to report it.
746    ///
747    /// # Arguments:
748    ///
749    /// * `status`
750    ///     * `Ok()` - The peripheral has been successfully disabled; the actual
751    ///       state is transmitted via `state_changed` callback
752    ///     * `Err(ErrorCode)` - The error that occurred during the disable process
753    fn disabled(&self, status: Result<(), ErrorCode>);
754}
755
756/// Client interface for capsules that implement the `Transmit` trait.
757pub trait TransmitClient<const PACKET_SIZE: usize> {
758    /// The driver calls this function when there is an update of the last
759    /// message that was transmitted
760    ///
761    /// # Arguments:
762    ///
763    /// * `status` - The status for the request
764    ///     * `Ok()` - There was no error during the transmission process
765    ///     * `Err(Error)` - The error that occurred during the transmission process
766    /// * `buffer` - The buffer received as an argument for the `send` function
767    fn transmit_complete(&self, status: Result<(), Error>, buffer: &'static mut [u8; PACKET_SIZE]);
768}
769
770/// Client interface for capsules that implement the `Receive` trait.
771pub trait ReceiveClient<const PACKET_SIZE: usize> {
772    /// The driver calls this function when a new message has been received on the given
773    /// FIFO.
774    ///
775    /// # Arguments:
776    ///
777    /// * `id` - The identifier of the received message
778    /// * `buffer` - A reference to the buffer where the data is stored. This
779    ///   data must be stored. This buffer is usually a slice to the original
780    ///   buffer that was supplied to the `start_receive_process`. It must be
781    ///   used within this function call. In most cases the data is copied to a
782    ///   driver or application buffer.
783    /// * `len` - The length of the buffer
784    /// * `status` - The status for the request
785    ///     * `Ok()` - There was no error during the reception process
786    ///     * `Err(Error)` - The error that occurred during the reception process
787    fn message_received(
788        &self,
789        id: Id,
790        buffer: &mut [u8; PACKET_SIZE],
791        len: usize,
792        status: Result<(), Error>,
793    );
794
795    /// The driver calls this function when the reception of messages has been stopped.
796    ///
797    /// # Arguments:
798    ///
799    /// * `buffer` - The buffer that was given as an argument to the
800    ///   `start_receive_process` function
801    fn stopped(&self, buffer: &'static mut [u8; PACKET_SIZE]);
802}
803
804/// Convenience type for capsules that configure, send
805/// and receive data using the CAN peripheral
806pub trait Can:
807    Transmit<STANDARD_CAN_PACKET_SIZE> + Configure + Controller + Receive<STANDARD_CAN_PACKET_SIZE>
808{
809}
810
811pub trait CanFd:
812    Transmit<FD_CAN_PACKET_SIZE> + Configure + ConfigureFd + Receive<FD_CAN_PACKET_SIZE>
813{
814}
815
816/// Provide blanket implementation for Can trait group
817impl<
818        T: Transmit<STANDARD_CAN_PACKET_SIZE>
819            + Configure
820            + Controller
821            + Receive<STANDARD_CAN_PACKET_SIZE>,
822    > Can for T
823{
824}
825
826/// Provide blanket implementation for CanFd trait group
827impl<T: Transmit<FD_CAN_PACKET_SIZE> + Configure + ConfigureFd + Receive<FD_CAN_PACKET_SIZE>> CanFd
828    for T
829{
830}