Skip to main content

esp_idf_hal/
can.rs

1//! CAN bus peripheral control.
2//!
3//! It is called Two-Wire Automotive Interface (TWAI) in ESP32 documentation.
4//!
5//! # Example
6//!
7//! Create a CAN peripheral and then transmit and receive a message.
8//! ```
9//! use embedded_can::nb::Can;
10//! use embedded_can::Frame;
11//! use embedded_can::StandardId;
12//! use esp_idf_hal::prelude::*;
13//! use esp_idf_hal::can;
14//!
15//! let peripherals = Peripherals::take().unwrap();
16//! let pins = peripherals.pins;
17//!
18//! // filter to accept only CAN ID 881
19//! let filter = can::config::Filter::Standard {filter: 881, mask: 0x7FF };
20//! // filter that accepts all CAN IDs
21//! // let filter = can::config::Filter::standard_allow_all();
22//!
23//! let timing = can::config::Timing::B500K;
24//! let config = can::config::Config::new().filter(filter).timing(timing);
25//! let mut can = can::CanDriver::new(peripherals.can, pins.gpio5, pins.gpio4, &config).unwrap();
26//!
27//! let tx_frame = can::Frame::new(StandardId::new(0x042).unwrap(), &[0, 1, 2, 3, 4, 5, 6, 7]).unwrap();
28//! nb::block!(can.transmit(&tx_frame)).unwrap();
29//!
30//! if let Ok(rx_frame) = nb::block!(can.receive()) {
31//!    info!("rx {:}:", rx_frame);
32//! }
33//! ```
34
35use core::borrow::BorrowMut;
36use core::ffi::CStr;
37use core::marker::PhantomData;
38use core::num::NonZeroU32;
39
40use enumset::{EnumSet, EnumSetType};
41
42use esp_idf_sys::*;
43
44use crate::cpu::Core;
45use crate::delay::{self, BLOCK, NON_BLOCK};
46use crate::interrupt::InterruptType;
47use crate::task::asynch::Notification;
48use crate::{gpio::*, task};
49
50crate::embedded_hal_error!(CanError, embedded_can::Error, embedded_can::ErrorKind);
51
52crate::embedded_hal_error!(
53    Can02Error,
54    embedded_hal_0_2::can::Error,
55    embedded_hal_0_2::can::ErrorKind
56);
57
58pub type CanConfig = config::Config;
59
60pub mod config {
61    use enumset::EnumSet;
62    use esp_idf_sys::*;
63
64    use crate::interrupt::InterruptType;
65
66    use super::Alert;
67
68    /// CAN timing
69    #[derive(Default, Debug, Copy, Clone, Eq, PartialEq, Hash)]
70    pub enum Timing {
71        B25K,
72        B50K,
73        B100K,
74        B125K,
75        B250K,
76        #[default]
77        B500K,
78        B800K,
79        B1M,
80        Custom {
81            baudrate_prescaler: u32,
82            timing_segment_1: u8,
83            timing_segment_2: u8,
84            synchronization_jump_width: u8,
85            triple_sampling: bool,
86        },
87    }
88
89    impl From<Timing> for twai_timing_config_t {
90        #[allow(clippy::needless_update)]
91        fn from(resolution: Timing) -> Self {
92            match resolution {
93                Timing::B25K => twai_timing_config_t {
94                    brp: 128,
95                    tseg_1: 16,
96                    tseg_2: 8,
97                    sjw: 3,
98                    ..Default::default()
99                },
100                Timing::B50K => twai_timing_config_t {
101                    brp: 80,
102                    tseg_1: 15,
103                    tseg_2: 4,
104                    sjw: 3,
105                    ..Default::default()
106                },
107                Timing::B100K => twai_timing_config_t {
108                    brp: 40,
109                    tseg_1: 15,
110                    tseg_2: 4,
111                    sjw: 3,
112                    ..Default::default()
113                },
114                Timing::B125K => twai_timing_config_t {
115                    brp: 32,
116                    tseg_1: 15,
117                    tseg_2: 4,
118                    sjw: 3,
119                    ..Default::default()
120                },
121                Timing::B250K => twai_timing_config_t {
122                    brp: 16,
123                    tseg_1: 15,
124                    tseg_2: 4,
125                    sjw: 3,
126                    ..Default::default()
127                },
128                Timing::B500K => twai_timing_config_t {
129                    brp: 8,
130                    tseg_1: 15,
131                    tseg_2: 4,
132                    sjw: 3,
133                    ..Default::default()
134                },
135                Timing::B800K => twai_timing_config_t {
136                    brp: 4,
137                    tseg_1: 16,
138                    tseg_2: 8,
139                    sjw: 3,
140                    ..Default::default()
141                },
142                Timing::B1M => twai_timing_config_t {
143                    brp: 4,
144                    tseg_1: 15,
145                    tseg_2: 4,
146                    sjw: 3,
147                    ..Default::default()
148                },
149                Timing::Custom {
150                    baudrate_prescaler,
151                    timing_segment_1,
152                    timing_segment_2,
153                    synchronization_jump_width,
154                    triple_sampling,
155                } => twai_timing_config_t {
156                    brp: baudrate_prescaler,
157                    tseg_1: timing_segment_1,
158                    tseg_2: timing_segment_2,
159                    sjw: synchronization_jump_width,
160                    triple_sampling,
161                    ..Default::default()
162                },
163            }
164        }
165    }
166
167    /// Is used to filter out unwanted CAN IDs (messages).
168    ///
169    /// Notice that Espressif TWAI (CAN in rest of the world) acceptance filtering
170    /// works differently than common CAN filtering (for example mask bits are inversed).
171    /// However here those differences are hidden away from the user and common CAN filtering is used.
172    ///
173    /// `mask` is used to determine which bits in the incoming CAN ID are compared with the `filter` value.
174    /// Bits in `mask` mean:
175    /// `0`: do not care - the bit is not used for the comparison
176    /// `1`: must match - the bit of the incoming CAN ID must have the same state as in `filter`
177    ///
178    /// Notice that if `mask` is `0`, all CAN IDs are accepted regardless of `filter` value.
179    ///
180    /// ## Examples
181    ///
182    /// This shows how 11 bit CAN ID `0x3AA` goes through filtering engine and is finally accepted:
183    /// ```
184    /// // incoming id [ 0 1 1 1 0 1 0 1 0 1 0 ]
185    /// // mask        [ 1 0 1 0 0 1 1 1 0 0 0 ]
186    /// //               1 = compare
187    /// //               0 = do not care
188    /// // masked id   [ 0 _ 1 _ _ 1 0 1 _ _ _ ]
189    /// // filter      [ 0 0 1 1 1 1 0 1 0 1 1 ]
190    ///
191    /// // incoming id [ 0 1 1 1 0 1 0 1 0 1 0 ]
192    /// // accepted
193    /// ```
194    ///
195    /// Notice that for example `0x7AA` would not be accepted because its MSB bit is `1`,
196    /// but `filter` only accepts `0` in this bit position and `mask` says that this bit must be compared.
197    ///
198    /// Accept only CAN ID `0x567`
199    /// ```
200    /// let filter = 0x567;
201    /// // every bit must match filter
202    /// let mask   = 0x7FF;
203    /// let f = Filter::Standard { filter, mask };
204    /// ```
205    ///
206    /// Accept CAN IDs `0x560 - 0x56F`
207    /// ```
208    /// let filter = 0x560;
209    /// // do not care about 4 LSB bits
210    /// let mask   = 0x7F0;
211    /// let f = Filter::Standard { filter, mask };
212    /// ```
213    #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
214    pub enum Filter {
215        /// Filter for 11 bit standard CAN IDs
216        Standard { filter: u16, mask: u16 },
217        /// Filter for two 11 bit standard CAN IDs
218        Dual {
219            filter1: u16,
220            mask1: u16,
221            filter2: u16,
222            mask2: u16,
223        },
224        /// Filter for 29 bit extended CAN IDs
225        Extended { filter: u32, mask: u32 },
226    }
227
228    impl Filter {
229        /// Filter that allows all standard CAN IDs.
230        pub const fn standard_allow_all() -> Self {
231            Self::Standard { filter: 0, mask: 0 }
232        }
233
234        /// Filter that accepts all extended CAN IDs.
235        pub const fn extended_allow_all() -> Self {
236            Self::Extended { filter: 0, mask: 0 }
237        }
238    }
239
240    impl Default for Filter {
241        fn default() -> Self {
242            Filter::standard_allow_all()
243        }
244    }
245
246    #[derive(Debug, Copy, Clone, Default, Eq, PartialEq, Hash)]
247    pub enum Mode {
248        #[default]
249        Normal,
250        NoAck,
251        ListenOnly,
252    }
253
254    impl From<Mode> for twai_mode_t {
255        fn from(val: Mode) -> Self {
256            match val {
257                Mode::Normal => twai_mode_t_TWAI_MODE_NORMAL,
258                Mode::NoAck => twai_mode_t_TWAI_MODE_NO_ACK,
259                Mode::ListenOnly => twai_mode_t_TWAI_MODE_LISTEN_ONLY,
260            }
261        }
262    }
263
264    #[derive(Debug, Clone)]
265    pub struct Config {
266        pub timing: Timing,
267        pub filter: Filter,
268        pub tx_queue_len: u32,
269        pub rx_queue_len: u32,
270        pub mode: Mode,
271        pub alerts: EnumSet<Alert>,
272        pub intr_flags: EnumSet<InterruptType>,
273    }
274
275    impl Config {
276        pub fn new() -> Self {
277            Self {
278                timing: Default::default(),
279                filter: Default::default(),
280                tx_queue_len: 5,
281                rx_queue_len: 5,
282                mode: Default::default(),
283                alerts: Default::default(),
284                intr_flags: EnumSet::<InterruptType>::empty(),
285            }
286        }
287
288        #[must_use]
289        pub fn timing(mut self, timing: Timing) -> Self {
290            self.timing = timing;
291            self
292        }
293
294        #[must_use]
295        pub fn filter(mut self, filter: Filter) -> Self {
296            self.filter = filter;
297            self
298        }
299
300        #[must_use]
301        pub fn tx_queue_len(mut self, tx_queue_len: u32) -> Self {
302            self.tx_queue_len = tx_queue_len;
303            self
304        }
305
306        #[must_use]
307        pub fn rx_queue_len(mut self, rx_queue_len: u32) -> Self {
308            self.rx_queue_len = rx_queue_len;
309            self
310        }
311
312        #[must_use]
313        pub fn mode(mut self, mode: Mode) -> Self {
314            self.mode = mode;
315            self
316        }
317
318        #[must_use]
319        pub fn alerts(mut self, alerts: EnumSet<Alert>) -> Self {
320            self.alerts = alerts;
321            self
322        }
323
324        #[must_use]
325        pub fn intr_flags(mut self, flags: EnumSet<InterruptType>) -> Self {
326            self.intr_flags = flags;
327            self
328        }
329    }
330
331    impl Default for Config {
332        fn default() -> Self {
333            Self::new()
334        }
335    }
336}
337
338#[derive(Debug, EnumSetType)]
339#[enumset(repr = "u32")]
340#[repr(u32)]
341pub enum Alert {
342    /// No more messages to transmit
343    TransmitIdle = 0,
344    /// The previous transmission was successful
345    Success = 1,
346    /// A frame has been received and added to the RX queue
347    Received = 2,
348    /// Both error counters have dropped below error warning limit
349    BelowErrorWarning = 3,
350    /// TWAI controller has become error active
351    ActiveError = 4,
352    /// TWAI controller is undergoing bus recovery
353    RecoveryInProgress = 5,
354    /// TWAI controller has successfully completed bus recovery
355    BusRecovered = 6,
356    /// The previous transmission lost arbitration
357    ArbLost = 7,
358    /// One of the error counters have exceeded the error warning limit
359    AboveErrorWarning = 8,
360    /// A (Bit, Stuff, CRC, Form, ACK) error has occurred on the bus
361    BusError = 9,
362    /// The previous transmission has failed (for single shot transmission)
363    TransmitFailed = 10,
364    /// The RX queue is full causing a frame to be lost
365    ReceiveQueueFull = 11,
366    /// TWAI controller has become error passive
367    ErrorPass = 12,
368    /// Bus-off condition occurred. TWAI controller can no longer influence bus
369    BusOffline = 13,
370    /// An RX FIFO overrun has occurred
371    ReceiveFifoOverflow = 14,
372    /// An message transmission was cancelled and retried due to an errata workaround
373    TransmitRetried = 15,
374    /// The TWAI controller was reset
375    PeripheralReset = 16,
376    /// In addition to alerting also Logs the event
377    AlertAndLog = 17,
378}
379
380/// CAN abstraction
381pub struct CanDriver<'d>(PhantomData<&'d mut ()>, EnumSet<Alert>, bool);
382
383impl<'d> CanDriver<'d> {
384    pub fn new(
385        _can: CAN<'d>,
386        tx: impl OutputPin + 'd,
387        rx: impl InputPin + 'd,
388        config: &config::Config,
389    ) -> Result<Self, EspError> {
390        #[allow(clippy::needless_update)]
391        let general_config = twai_general_config_t {
392            mode: config.mode.into(),
393            tx_io: tx.pin() as _,
394            rx_io: rx.pin() as _,
395            clkout_io: -1,
396            bus_off_io: -1,
397            tx_queue_len: config.tx_queue_len,
398            rx_queue_len: config.rx_queue_len,
399            alerts_enabled: config.alerts.as_repr(),
400            clkout_divider: 0,
401            intr_flags: InterruptType::to_native(config.intr_flags) as _,
402            ..Default::default()
403        };
404
405        let timing_config = config.timing.into();
406
407        // modify filter and mask to be compatible with TWAI acceptance filter
408        let (filter, mask, single_filter) = match config.filter {
409            config::Filter::Standard { filter, mask } => {
410                ((filter as u32) << 21, !((mask as u32) << 21), true)
411            }
412            config::Filter::Extended { filter, mask } => (filter << 3, !(mask << 3), true),
413            config::Filter::Dual {
414                filter1,
415                mask1,
416                filter2,
417                mask2,
418            } => (
419                ((filter1 as u32) << 21) | ((filter2 as u32) << 5),
420                !(((mask1 as u32) << 21) | ((mask2 as u32) << 5)),
421                false,
422            ),
423        };
424
425        let filter_config = twai_filter_config_t {
426            acceptance_code: filter,
427            acceptance_mask: mask,
428            single_filter,
429        };
430
431        esp!(unsafe { twai_driver_install(&general_config, &timing_config, &filter_config) })?;
432
433        Ok(Self(PhantomData, config.alerts, config.tx_queue_len > 0))
434    }
435
436    pub fn start(&mut self) -> Result<(), EspError> {
437        esp!(unsafe { twai_start() })
438    }
439
440    pub fn stop(&mut self) -> Result<(), EspError> {
441        esp!(unsafe { twai_stop() })
442    }
443
444    pub fn transmit(&self, frame: &Frame, timeout: TickType_t) -> Result<(), EspError> {
445        esp!(unsafe { twai_transmit(&frame.0, timeout) })
446    }
447
448    pub fn receive(&self, timeout: TickType_t) -> Result<Frame, EspError> {
449        let mut rx_msg = Default::default();
450
451        match esp_result!(unsafe { twai_receive(&mut rx_msg, timeout) }, ()) {
452            Ok(_) => Ok(Frame(rx_msg)),
453            Err(err) => Err(err),
454        }
455    }
456
457    pub fn read_alerts(&self, timeout: TickType_t) -> Result<EnumSet<Alert>, EspError> {
458        let mut alerts = 0;
459
460        esp!(unsafe { twai_read_alerts(&mut alerts, timeout) })?;
461
462        Ok(EnumSet::from_repr_truncated(alerts))
463    }
464}
465
466impl Drop for CanDriver<'_> {
467    fn drop(&mut self) {
468        let _ = self.stop();
469        esp!(unsafe { twai_driver_uninstall() }).unwrap();
470    }
471}
472
473unsafe impl Send for CanDriver<'_> {}
474
475impl embedded_hal_0_2::blocking::can::Can for CanDriver<'_> {
476    type Frame = Frame;
477    type Error = Can02Error;
478
479    fn transmit(&mut self, frame: &Self::Frame) -> Result<(), Self::Error> {
480        CanDriver::transmit(self, frame, BLOCK).map_err(Can02Error::other)
481    }
482
483    fn receive(&mut self) -> Result<Self::Frame, Self::Error> {
484        CanDriver::receive(self, BLOCK).map_err(Can02Error::other)
485    }
486}
487
488impl embedded_can::blocking::Can for CanDriver<'_> {
489    type Frame = Frame;
490    type Error = CanError;
491
492    fn transmit(&mut self, frame: &Self::Frame) -> Result<(), Self::Error> {
493        CanDriver::transmit(self, frame, BLOCK).map_err(CanError::other)
494    }
495
496    fn receive(&mut self) -> Result<Self::Frame, Self::Error> {
497        CanDriver::receive(self, BLOCK).map_err(CanError::other)
498    }
499}
500
501impl embedded_hal_0_2::can::nb::Can for CanDriver<'_> {
502    type Frame = Frame;
503    type Error = Can02Error;
504
505    fn transmit(&mut self, frame: &Self::Frame) -> nb::Result<Option<Self::Frame>, Self::Error> {
506        match CanDriver::transmit(self, frame, NON_BLOCK) {
507            Ok(_) => Ok(None),
508            Err(e) if e.code() == ESP_FAIL => Err(nb::Error::WouldBlock),
509            Err(e) if e.code() == ESP_ERR_TIMEOUT => Err(nb::Error::WouldBlock),
510            Err(e) => Err(nb::Error::Other(Can02Error::other(e))),
511        }
512    }
513
514    fn receive(&mut self) -> nb::Result<Self::Frame, Self::Error> {
515        match CanDriver::receive(self, NON_BLOCK) {
516            Ok(frame) => Ok(frame),
517            Err(e) if e.code() == ESP_ERR_TIMEOUT => Err(nb::Error::WouldBlock),
518            Err(e) => Err(nb::Error::Other(Can02Error::other(e))),
519        }
520    }
521}
522
523impl embedded_can::nb::Can for CanDriver<'_> {
524    type Frame = Frame;
525    type Error = CanError;
526
527    fn transmit(&mut self, frame: &Self::Frame) -> nb::Result<Option<Self::Frame>, Self::Error> {
528        match CanDriver::transmit(self, frame, NON_BLOCK) {
529            Ok(_) => Ok(None),
530            Err(e) if e.code() == ESP_FAIL => Err(nb::Error::WouldBlock),
531            Err(e) if e.code() == ESP_ERR_TIMEOUT => Err(nb::Error::WouldBlock),
532            Err(e) => Err(nb::Error::Other(CanError::other(e))),
533        }
534    }
535
536    fn receive(&mut self) -> nb::Result<Self::Frame, Self::Error> {
537        match CanDriver::receive(self, NON_BLOCK) {
538            Ok(frame) => Ok(frame),
539            Err(e) if e.code() == ESP_ERR_TIMEOUT => Err(nb::Error::WouldBlock),
540            Err(e) => Err(nb::Error::Other(CanError::other(e))),
541        }
542    }
543}
544
545fn read_alerts() -> EnumSet<Alert> {
546    Alert::Success | Alert::Received | Alert::ReceiveQueueFull
547}
548
549fn write_alerts() -> EnumSet<Alert> {
550    Alert::Success | Alert::TransmitIdle | Alert::TransmitFailed | Alert::TransmitRetried
551}
552
553pub type OwnedAsyncCanDriver<'d> = AsyncCanDriver<'d, CanDriver<'d>>;
554
555pub struct AsyncCanDriver<'d, T>
556where
557    T: BorrowMut<CanDriver<'d>>,
558{
559    driver: T,
560    task: TaskHandle_t,
561    _data: PhantomData<&'d ()>,
562}
563
564impl<'d> AsyncCanDriver<'d, CanDriver<'d>> {
565    pub fn new(
566        can: CAN<'d>,
567        tx: impl OutputPin + 'd,
568        rx: impl InputPin + 'd,
569        config: &config::Config,
570    ) -> Result<Self, EspError> {
571        Self::wrap(CanDriver::new(can, tx, rx, config)?)
572    }
573}
574
575impl<'d, T> AsyncCanDriver<'d, T>
576where
577    T: BorrowMut<CanDriver<'d>>,
578{
579    pub fn wrap(driver: T) -> Result<Self, EspError> {
580        Self::wrap_custom(driver, None, None)
581    }
582
583    pub fn wrap_custom(
584        mut driver: T,
585        priority: Option<u8>,
586        pin_to_core: Option<Core>,
587    ) -> Result<Self, EspError> {
588        let _ = driver.borrow_mut().stop();
589
590        let mut alerts = 0;
591        esp!(unsafe {
592            twai_reconfigure_alerts(
593                driver
594                    .borrow()
595                    .1
596                    .union(read_alerts())
597                    .union(write_alerts())
598                    .as_repr(),
599                &mut alerts,
600            )
601        })?;
602
603        let task = unsafe {
604            task::create(
605                Self::process_alerts,
606                CStr::from_bytes_until_nul(b"CAN - Alerts task\0").unwrap(),
607                2048,
608                core::ptr::null_mut(),
609                priority.unwrap_or(6),
610                pin_to_core,
611            )?
612        };
613
614        Ok(Self {
615            driver,
616            task,
617            _data: PhantomData,
618        })
619    }
620
621    pub fn driver(&self) -> &CanDriver<'d> {
622        self.driver.borrow()
623    }
624
625    pub fn driver_mut(&mut self) -> &mut CanDriver<'d> {
626        self.driver.borrow_mut()
627    }
628
629    pub fn start(&mut self) -> Result<(), EspError> {
630        self.driver.borrow_mut().start()
631    }
632
633    pub fn stop(&mut self) -> Result<(), EspError> {
634        self.driver.borrow_mut().stop()
635    }
636
637    pub async fn transmit(&self, frame: &Frame) -> Result<(), EspError> {
638        loop {
639            let res = self.driver.borrow().transmit(frame, delay::NON_BLOCK);
640
641            match res {
642                Ok(()) => return Ok(()),
643                Err(e)
644                    if e.code() != ESP_ERR_TIMEOUT
645                        && (e.code() != ESP_FAIL || self.driver.borrow().2) =>
646                {
647                    return Err(e)
648                }
649                _ => (),
650            }
651
652            WRITE_NOTIFICATION.wait().await;
653        }
654    }
655
656    pub async fn receive(&self) -> Result<Frame, EspError> {
657        loop {
658            let res = self.driver.borrow().receive(delay::NON_BLOCK);
659
660            match res {
661                Ok(frame) => return Ok(frame),
662                Err(e) if e.code() != ESP_ERR_TIMEOUT => return Err(e),
663                _ => (),
664            }
665
666            READ_NOTIFICATION.wait().await;
667        }
668    }
669
670    pub async fn read_alerts(&self) -> Result<EnumSet<Alert>, EspError> {
671        let alerts = loop {
672            let alerts = EnumSet::from_repr(ALERT_NOTIFICATION.wait().await.into())
673                .intersection(self.driver.borrow().1);
674
675            if !alerts.is_empty() {
676                break alerts;
677            }
678        };
679
680        Ok(alerts)
681    }
682
683    extern "C" fn process_alerts(_arg: *mut core::ffi::c_void) {
684        let mut alerts = 0;
685
686        loop {
687            if unsafe { twai_read_alerts(&mut alerts, delay::BLOCK) } == 0 {
688                let ealerts: EnumSet<Alert> = EnumSet::from_repr_truncated(alerts);
689
690                if !ealerts.is_disjoint(read_alerts()) {
691                    READ_NOTIFICATION.notify_lsb();
692                }
693
694                if !ealerts.is_disjoint(write_alerts()) {
695                    WRITE_NOTIFICATION.notify_lsb();
696                }
697
698                if let Some(alerts) = NonZeroU32::new(alerts) {
699                    ALERT_NOTIFICATION.notify(alerts);
700                }
701            }
702        }
703    }
704}
705
706impl<'d, T> Drop for AsyncCanDriver<'d, T>
707where
708    T: BorrowMut<CanDriver<'d>>,
709{
710    fn drop(&mut self) {
711        let _ = self.stop();
712
713        unsafe { task::destroy(self.task) };
714
715        let mut alerts = 0;
716        esp!(unsafe { twai_reconfigure_alerts(self.driver.borrow().1.as_repr(), &mut alerts) })
717            .unwrap();
718
719        READ_NOTIFICATION.reset();
720        WRITE_NOTIFICATION.reset();
721        ALERT_NOTIFICATION.reset();
722    }
723}
724
725unsafe impl<'d, T> Send for AsyncCanDriver<'d, T> where T: BorrowMut<CanDriver<'d>> + Send {}
726
727static READ_NOTIFICATION: Notification = Notification::new();
728static WRITE_NOTIFICATION: Notification = Notification::new();
729static ALERT_NOTIFICATION: Notification = Notification::new();
730
731/// Twai message flags
732#[derive(Debug, EnumSetType)]
733pub enum Flags {
734    /// Message is in Extended Frame Format (29bit ID)
735    Extended,
736    ///  Message is a Remote Frame (Remote Transmission Request)
737    Remote,
738    /// Transmit message using Single Shot Transmission
739    /// (Message will not be retransmitted upon error or loss of arbitration).
740    /// Unused for received message.
741    SingleShot,
742    /// Transmit message using Self Reception Request
743    /// (Transmitted message will also received by the same node).
744    /// Unused for received message.
745    SelfReception,
746    /// Message's Data length code is larger than 8.
747    /// This will break compliance with TWAI
748    DlcNonComp,
749    None,
750}
751
752pub struct Frame(twai_message_t);
753
754impl Frame {
755    pub fn new(id: u32, flags: EnumSet<Flags>, data: &[u8]) -> Option<Self> {
756        let dlc = data.len();
757
758        if dlc <= 8 {
759            // unions are not very well supported in rust
760            // therefore setting those union flags is quite hairy
761            let mut twai_flags = twai_message_t__bindgen_ty_1::default();
762
763            // Iterate over the flags set and set the corresponding bits in the union
764            for flag in flags.iter() {
765                match flag {
766                    Flags::Extended => unsafe { twai_flags.__bindgen_anon_1.set_extd(1) },
767                    Flags::Remote => unsafe { twai_flags.__bindgen_anon_1.set_rtr(1) },
768                    Flags::SingleShot => unsafe { twai_flags.__bindgen_anon_1.set_ss(1) },
769                    Flags::SelfReception => unsafe { twai_flags.__bindgen_anon_1.set_self(1) },
770                    Flags::DlcNonComp => unsafe { twai_flags.__bindgen_anon_1.set_dlc_non_comp(1) },
771                    Flags::None => {}
772                }
773            }
774
775            let mut payload = [0; 8];
776            payload[..dlc].copy_from_slice(data);
777
778            let twai_message = twai_message_t {
779                __bindgen_anon_1: twai_flags,
780                identifier: id,
781                data_length_code: dlc as u8,
782                data: payload,
783            };
784
785            Some(Frame(twai_message))
786        } else {
787            None
788        }
789    }
790
791    pub fn new_remote(id: u32, extended: bool, dlc: usize) -> Option<Self> {
792        if dlc <= 8 {
793            // unions are not very well supported in rust
794            // therefore setting those union flags is quite hairy
795            let mut flags = twai_message_t__bindgen_ty_1::default();
796
797            // set bits in an union
798            unsafe { flags.__bindgen_anon_1.set_rtr(1) };
799            if extended {
800                unsafe { flags.__bindgen_anon_1.set_extd(1) };
801            }
802
803            let twai_message = twai_message_t {
804                __bindgen_anon_1: flags,
805                identifier: id,
806                data_length_code: dlc as u8,
807                data: [0; 8],
808            };
809
810            Some(Frame(twai_message))
811        } else {
812            None
813        }
814    }
815
816    pub fn is_extended(&self) -> bool {
817        unsafe { self.0.__bindgen_anon_1.__bindgen_anon_1.extd() == 1 }
818    }
819
820    pub fn is_remote_frame(&self) -> bool {
821        unsafe { self.0.__bindgen_anon_1.__bindgen_anon_1.rtr() == 1 }
822    }
823
824    pub fn identifier(&self) -> u32 {
825        self.0.identifier
826    }
827
828    pub fn dlc(&self) -> usize {
829        self.0.data_length_code as usize
830    }
831
832    pub fn data(&self) -> &[u8] {
833        &self.0.data[..self.dlc()]
834    }
835}
836
837impl core::fmt::Display for Frame {
838    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
839        if self.is_extended() {
840            write!(
841                f,
842                "Frame {{ id: {:08x}, remote: {}, data: {:?} }}",
843                self.identifier(),
844                self.is_remote_frame(),
845                self.data()
846            )
847        } else {
848            write!(
849                f,
850                "Frame {{ id: {:03x}, remote: {}, data: {:?} }}",
851                self.identifier(),
852                self.is_remote_frame(),
853                self.data()
854            )
855        }
856    }
857}
858
859impl embedded_hal_0_2::can::Frame for Frame {
860    fn new(id: impl Into<embedded_hal_0_2::can::Id>, data: &[u8]) -> Option<Self> {
861        let (id, flags) = match id.into() {
862            embedded_hal_0_2::can::Id::Standard(id) => (id.as_raw() as u32, Flags::None),
863            embedded_hal_0_2::can::Id::Extended(id) => (id.as_raw(), Flags::Extended),
864        };
865
866        Self::new(id, flags.into(), data)
867    }
868
869    fn new_remote(id: impl Into<embedded_hal_0_2::can::Id>, dlc: usize) -> Option<Self> {
870        let (id, extended) = match id.into() {
871            embedded_hal_0_2::can::Id::Standard(id) => (id.as_raw() as u32, false),
872            embedded_hal_0_2::can::Id::Extended(id) => (id.as_raw(), true),
873        };
874
875        Self::new_remote(id, extended, dlc)
876    }
877
878    fn is_extended(&self) -> bool {
879        Frame::is_extended(self)
880    }
881
882    fn is_standard(&self) -> bool {
883        !self.is_extended()
884    }
885
886    fn is_remote_frame(&self) -> bool {
887        Frame::is_remote_frame(self)
888    }
889
890    fn is_data_frame(&self) -> bool {
891        !self.is_remote_frame()
892    }
893
894    fn id(&self) -> embedded_hal_0_2::can::Id {
895        if self.is_standard() {
896            let id = unsafe {
897                embedded_hal_0_2::can::StandardId::new_unchecked(self.identifier() as u16)
898            };
899            embedded_hal_0_2::can::Id::Standard(id)
900        } else {
901            let id = unsafe { embedded_hal_0_2::can::ExtendedId::new_unchecked(self.identifier()) };
902            embedded_hal_0_2::can::Id::Extended(id)
903        }
904    }
905
906    fn dlc(&self) -> usize {
907        Frame::dlc(self)
908    }
909
910    fn data(&self) -> &[u8] {
911        Frame::data(self)
912    }
913}
914
915impl embedded_can::Frame for Frame {
916    fn new(id: impl Into<embedded_can::Id>, data: &[u8]) -> Option<Self> {
917        let (id, flags) = match id.into() {
918            embedded_can::Id::Standard(id) => (id.as_raw() as u32, Flags::None),
919            embedded_can::Id::Extended(id) => (id.as_raw(), Flags::Extended),
920        };
921
922        Self::new(id, flags.into(), data)
923    }
924
925    fn new_remote(id: impl Into<embedded_can::Id>, dlc: usize) -> Option<Self> {
926        let (id, extended) = match id.into() {
927            embedded_can::Id::Standard(id) => (id.as_raw() as u32, false),
928            embedded_can::Id::Extended(id) => (id.as_raw(), true),
929        };
930
931        Self::new_remote(id, extended, dlc)
932    }
933
934    fn is_extended(&self) -> bool {
935        Frame::is_extended(self)
936    }
937
938    fn is_standard(&self) -> bool {
939        !self.is_extended()
940    }
941
942    fn is_remote_frame(&self) -> bool {
943        Frame::is_remote_frame(self)
944    }
945
946    fn is_data_frame(&self) -> bool {
947        !self.is_remote_frame()
948    }
949
950    fn id(&self) -> embedded_can::Id {
951        if self.is_standard() {
952            let id = unsafe { embedded_can::StandardId::new_unchecked(self.identifier() as u16) };
953            embedded_can::Id::Standard(id)
954        } else {
955            let id = unsafe { embedded_can::ExtendedId::new_unchecked(self.identifier()) };
956            embedded_can::Id::Extended(id)
957        }
958    }
959
960    fn dlc(&self) -> usize {
961        Frame::dlc(self)
962    }
963
964    fn data(&self) -> &[u8] {
965        Frame::data(self)
966    }
967}
968
969crate::impl_peripheral!(CAN);