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}