esp_hal/twai/
mod.rs

1//! # Two-wire Automotive Interface (TWAI)
2//!
3//! ## Overview
4//!
5//! The TWAI is a multi-master, multi-cast communication protocol with error
6//! detection and signaling and inbuilt message priorities and arbitration. The
7//! TWAI protocol is suited for automotive and industrial applications.
8//!
9//! See ESP-IDF's
10#![doc = concat!("[TWAI documentation](https://docs.espressif.com/projects/esp-idf/en/latest/", crate::chip!(), "/api-reference/peripherals/twai.html#twai-protocol-summary)")]
11//! for a summary on the protocol.
12//!
13//! ## Configuration
14//! The driver  offers functions for initializing the TWAI peripheral, setting
15//! up the timing parameters, configuring acceptance filters, handling
16//! interrupts, and transmitting/receiving messages on the TWAI bus.
17//!
18//! This driver manages the ISO 11898-1 compatible TWAI
19//! controllers. It supports Standard Frame Format (11-bit) and Extended Frame
20//! Format (29-bit) frame identifiers.
21//!
22//! ## Examples
23//!
24//! ### Transmitting and Receiving Messages
25//!
26//! ```rust, no_run
27#![doc = crate::before_snippet!()]
28//! # use esp_hal::twai;
29//! # use esp_hal::twai::filter;
30//! # use esp_hal::twai::filter::SingleStandardFilter;
31//! # use esp_hal::twai::TwaiConfiguration;
32//! # use esp_hal::twai::BaudRate;
33//! # use esp_hal::twai::TwaiMode;
34//! # use nb::block;
35//! // Use GPIO pins 2 and 3 to connect to the respective pins on the TWAI
36//! // transceiver.
37//! let twai_rx_pin = peripherals.GPIO3;
38//! let twai_tx_pin = peripherals.GPIO2;
39//!
40//! // The speed of the TWAI bus.
41//! const TWAI_BAUDRATE: twai::BaudRate = BaudRate::B1000K;
42//!
43//! // Begin configuring the TWAI peripheral. The peripheral is in a reset like
44//! // state that prevents transmission but allows configuration.
45//! let mut twai_config = twai::TwaiConfiguration::new(
46//!     peripherals.TWAI0,
47//!     twai_rx_pin,
48//!     twai_tx_pin,
49//!     TWAI_BAUDRATE,
50//!     TwaiMode::Normal
51//! );
52//!
53//! // Partially filter the incoming messages to reduce overhead of receiving
54//! // undesired messages
55//! twai_config.set_filter(const { SingleStandardFilter::new(b"xxxxxxxxxx0",
56//! b"x", [b"xxxxxxxx", b"xxxxxxxx"]) });
57//!
58//! // Start the peripheral. This locks the configuration settings of the
59//! // peripheral and puts it into operation mode, allowing packets to be sent
60//! // and received.
61//! let mut twai = twai_config.start();
62//!
63//! loop {
64//!     // Wait for a frame to be received.
65//!     let frame = block!(twai.receive())?;
66//!
67//!     // Transmit the frame back.
68//!     let _result = block!(twai.transmit(&frame))?;
69//! }
70//! # }
71//! ```
72//! 
73//! ### Self-testing (self reception of transmitted messages)
74//! ```rust, no_run
75#![doc = crate::before_snippet!()]
76//! # use esp_hal::twai;
77//! # use esp_hal::twai::filter;
78//! # use esp_hal::twai::filter::SingleStandardFilter;
79//! # use esp_hal::twai::TwaiConfiguration;
80//! # use esp_hal::twai::BaudRate;
81//! # use esp_hal::twai::EspTwaiFrame;
82//! # use esp_hal::twai::StandardId;
83//! # use esp_hal::twai::TwaiMode;
84//! # use nb::block;
85//! // Use GPIO pins 2 and 3 to connect to the respective pins on the TWAI
86//! // transceiver.
87//! let can_rx_pin = peripherals.GPIO3;
88//! let can_tx_pin = peripherals.GPIO2;
89//!
90//! // The speed of the TWAI bus.
91//! const TWAI_BAUDRATE: twai::BaudRate = BaudRate::B1000K;
92//!
93//! // Begin configuring the TWAI peripheral.
94//! let mut can_config = twai::TwaiConfiguration::new(
95//!     peripherals.TWAI0,
96//!     can_rx_pin,
97//!     can_tx_pin,
98//!     TWAI_BAUDRATE,
99//!     TwaiMode::SelfTest
100//! );
101//!
102//! // Partially filter the incoming messages to reduce overhead of receiving
103//! // undesired messages
104//! can_config.set_filter(const { SingleStandardFilter::new(b"xxxxxxxxxx0",
105//! b"x", [b"xxxxxxxx", b"xxxxxxxx"]) });
106//!
107//! // Start the peripheral. This locks the configuration settings of the
108//! // peripheral and puts it into operation mode, allowing packets to be sent
109//! // and received.
110//! let mut can = can_config.start();
111//!
112//! # // TODO: `new_*` should return Result not Option
113//! let frame = EspTwaiFrame::new_self_reception(StandardId::ZERO,
114//!     &[1, 2, 3]).unwrap(); // Wait for a frame to be received.
115//! let frame = block!(can.receive())?;
116//!
117//! # loop {}
118//! # }
119//! ```
120
121use core::marker::PhantomData;
122
123use self::filter::{Filter, FilterType};
124use crate::{
125    Async,
126    Blocking,
127    DriverMode,
128    gpio::{
129        DriveMode,
130        InputConfig,
131        InputSignal,
132        OutputConfig,
133        OutputSignal,
134        Pull,
135        interconnect::{PeripheralInput, PeripheralOutput},
136    },
137    interrupt::InterruptHandler,
138    pac::twai0::RegisterBlock,
139    system::{Cpu, PeripheralGuard},
140    twai::filter::SingleStandardFilter,
141};
142
143pub mod filter;
144
145/// TWAI error kind
146///
147/// This represents a common set of TWAI operation errors. HAL implementations
148/// are free to define more specific or additional error types. However, by
149/// providing a mapping to these common TWAI errors, generic code can still
150/// react to them.
151#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
152#[non_exhaustive]
153pub enum ErrorKind {
154    /// The peripheral receive buffer was overrun.
155    Overrun,
156    // MAC sublayer errors
157    /// A bit error is detected at that bit time when the bit value that is
158    /// monitored differs from the bit value sent.
159    Bit,
160    /// A stuff error is detected at the bit time of the sixth consecutive
161    /// equal bit level in a frame field that shall be coded by the method
162    /// of bit stuffing.
163    Stuff,
164    /// Calculated CRC sequence does not equal the received one.
165    Crc,
166    /// A form error shall be detected when a fixed-form bit field contains
167    /// one or more illegal bits.
168    Form,
169    /// An ACK  error shall be detected by a transmitter whenever it does not
170    /// monitor a dominant bit during the ACK slot.
171    Acknowledge,
172    /// A different error occurred. The original error may contain more
173    /// information.
174    Other,
175}
176
177macro_rules! impl_display {
178    ($($kind:ident => $msg:expr),* $(,)?) => {
179        impl core::fmt::Display for ErrorKind {
180            fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
181                match self {
182                    $(Self::$kind => write!(f, $msg)),*
183                }
184            }
185        }
186
187        #[cfg(feature = "defmt")]
188        impl defmt::Format for ErrorKind {
189            fn format(&self, f: defmt::Formatter<'_>) {
190                match self {
191                    $(Self::$kind => defmt::write!(f, $msg)),*
192                }
193            }
194        }
195    };
196}
197
198impl_display! {
199    Overrun => "The peripheral receive buffer was overrun",
200    Bit => "Bit value that is monitored differs from the bit value sent",
201    Stuff => "Sixth consecutive equal bits detected",
202    Crc => "Calculated CRC sequence does not equal the received one",
203    Form => "A fixed-form bit field contains one or more illegal bits",
204    Acknowledge => "Transmitted frame was not acknowledged",
205    Other => "A different error occurred. The original error may contain more information",
206}
207
208#[instability::unstable]
209impl From<ErrorKind> for embedded_can::ErrorKind {
210    fn from(value: ErrorKind) -> Self {
211        match value {
212            ErrorKind::Overrun => embedded_can::ErrorKind::Overrun,
213            ErrorKind::Bit => embedded_can::ErrorKind::Bit,
214            ErrorKind::Stuff => embedded_can::ErrorKind::Stuff,
215            ErrorKind::Crc => embedded_can::ErrorKind::Crc,
216            ErrorKind::Form => embedded_can::ErrorKind::Form,
217            ErrorKind::Acknowledge => embedded_can::ErrorKind::Acknowledge,
218            ErrorKind::Other => embedded_can::ErrorKind::Other,
219        }
220    }
221}
222
223#[instability::unstable]
224impl embedded_can::Error for ErrorKind {
225    fn kind(&self) -> embedded_can::ErrorKind {
226        (*self).into()
227    }
228}
229
230/// Specifies in which mode the TWAI controller will operate.
231#[derive(Debug, Copy, Clone, Eq, PartialEq)]
232#[cfg_attr(feature = "defmt", derive(defmt::Format))]
233pub enum TwaiMode {
234    /// Normal operating mode
235    Normal,
236    /// Self-test mode (no acknowledgement required for a successful message
237    /// transmission)
238    SelfTest,
239    /// Listen only operating mode
240    ListenOnly,
241}
242
243/// Standard 11-bit TWAI Identifier (`0..=0x7FF`).
244#[derive(Debug, Copy, Clone, Eq, PartialEq)]
245#[cfg_attr(feature = "defmt", derive(defmt::Format))]
246pub struct StandardId(u16);
247
248impl StandardId {
249    /// TWAI ID `0`, the highest priority.
250    pub const ZERO: Self = StandardId(0);
251
252    /// TWAI ID `0x7FF`, the lowest priority.
253    pub const MAX: Self = StandardId(0x7FF);
254
255    /// Tries to create a `StandardId` from a raw 16-bit integer.
256    ///
257    /// This will return `None` if `raw` is out of range of an 11-bit integer
258    /// (`> 0x7FF`).
259    #[inline]
260    pub fn new(raw: u16) -> Option<Self> {
261        if raw <= 0x7FF {
262            Some(StandardId(raw))
263        } else {
264            None
265        }
266    }
267
268    /// Creates a new `StandardId` without checking if it is inside the valid
269    /// range.
270    ///
271    /// # Safety
272    /// Using this method can create an invalid ID and is thus marked as unsafe.
273    #[inline]
274    pub const unsafe fn new_unchecked(raw: u16) -> Self {
275        StandardId(raw)
276    }
277
278    /// Returns TWAI Identifier as a raw 16-bit integer.
279    #[inline]
280    pub fn as_raw(&self) -> u16 {
281        self.0
282    }
283}
284
285#[instability::unstable]
286impl From<StandardId> for embedded_can::StandardId {
287    fn from(value: StandardId) -> Self {
288        embedded_can::StandardId::new(value.as_raw()).unwrap()
289    }
290}
291
292#[instability::unstable]
293impl From<embedded_can::StandardId> for StandardId {
294    fn from(value: embedded_can::StandardId) -> Self {
295        StandardId::new(value.as_raw()).unwrap()
296    }
297}
298
299/// Extended 29-bit TWAI Identifier (`0..=1FFF_FFFF`).
300#[derive(Debug, Copy, Clone, Eq, PartialEq)]
301#[cfg_attr(feature = "defmt", derive(defmt::Format))]
302pub struct ExtendedId(u32);
303
304impl ExtendedId {
305    /// TWAI ID `0`, the highest priority.
306    pub const ZERO: Self = ExtendedId(0);
307
308    /// TWAI ID `0x1FFFFFFF`, the lowest priority.
309    pub const MAX: Self = ExtendedId(0x1FFF_FFFF);
310
311    /// Tries to create a `ExtendedId` from a raw 32-bit integer.
312    ///
313    /// This will return `None` if `raw` is out of range of an 29-bit integer
314    /// (`> 0x1FFF_FFFF`).
315    #[inline]
316    pub fn new(raw: u32) -> Option<Self> {
317        if raw <= 0x1FFF_FFFF {
318            Some(ExtendedId(raw))
319        } else {
320            None
321        }
322    }
323
324    /// Creates a new `ExtendedId` without checking if it is inside the valid
325    /// range.
326    ///
327    /// # Safety
328    /// Using this method can create an invalid ID and is thus marked as unsafe.
329    #[inline]
330    pub const unsafe fn new_unchecked(raw: u32) -> Self {
331        ExtendedId(raw)
332    }
333
334    /// Returns TWAI Identifier as a raw 32-bit integer.
335    #[inline]
336    pub fn as_raw(&self) -> u32 {
337        self.0
338    }
339
340    /// Returns the Base ID part of this extended identifier.
341    pub fn standard_id(&self) -> StandardId {
342        // ID-28 to ID-18
343        StandardId((self.0 >> 18) as u16)
344    }
345}
346
347#[instability::unstable]
348impl From<ExtendedId> for embedded_can::ExtendedId {
349    fn from(value: ExtendedId) -> Self {
350        embedded_can::ExtendedId::new(value.0).unwrap()
351    }
352}
353
354#[instability::unstable]
355impl From<embedded_can::ExtendedId> for ExtendedId {
356    fn from(value: embedded_can::ExtendedId) -> Self {
357        ExtendedId::new(value.as_raw()).unwrap()
358    }
359}
360
361/// A TWAI Identifier (standard or extended).
362#[derive(Debug, Copy, Clone, Eq, PartialEq)]
363#[cfg_attr(feature = "defmt", derive(defmt::Format))]
364pub enum Id {
365    /// Standard 11-bit Identifier (`0..=0x7FF`).
366    Standard(StandardId),
367    /// Extended 29-bit Identifier (`0..=0x1FFF_FFFF`).
368    Extended(ExtendedId),
369}
370
371impl From<StandardId> for Id {
372    #[inline]
373    fn from(id: StandardId) -> Self {
374        Id::Standard(id)
375    }
376}
377
378impl From<ExtendedId> for Id {
379    #[inline]
380    fn from(id: ExtendedId) -> Self {
381        Id::Extended(id)
382    }
383}
384
385#[instability::unstable]
386impl From<Id> for embedded_can::Id {
387    fn from(value: Id) -> Self {
388        match value {
389            Id::Standard(id) => embedded_can::Id::Standard(id.into()),
390            Id::Extended(id) => embedded_can::Id::Extended(id.into()),
391        }
392    }
393}
394
395#[instability::unstable]
396impl From<embedded_can::Id> for Id {
397    fn from(value: embedded_can::Id) -> Self {
398        match value {
399            embedded_can::Id::Standard(id) => Id::Standard(id.into()),
400            embedded_can::Id::Extended(id) => Id::Extended(id.into()),
401        }
402    }
403}
404
405/// A TWAI Frame.
406#[derive(Clone, Copy, Debug)]
407#[cfg_attr(feature = "defmt", derive(defmt::Format))]
408pub struct EspTwaiFrame {
409    id: Id,
410    dlc: usize,
411    data: [u8; 8],
412    is_remote: bool,
413    self_reception: bool,
414}
415
416impl EspTwaiFrame {
417    /// Creates a new `EspTwaiFrame` with the specified ID and data payload.
418    pub fn new(id: impl Into<Id>, data: &[u8]) -> Option<Self> {
419        // TWAI frames cannot contain more than 8 bytes of data.
420        if data.len() > 8 {
421            return None;
422        }
423
424        let mut d: [u8; 8] = [0; 8];
425        d[..data.len()].copy_from_slice(data);
426
427        Some(EspTwaiFrame {
428            id: id.into(),
429            data: d,
430            dlc: data.len(),
431            is_remote: false,
432            self_reception: false,
433        })
434    }
435
436    /// Creates a new `EspTwaiFrame` for a transmission request with the
437    /// specified ID and data length (DLC).
438    pub fn new_remote(id: impl Into<Id>, dlc: usize) -> Option<Self> {
439        // TWAI frames cannot have more than 8 bytes.
440        if dlc > 8 {
441            return None;
442        }
443
444        Some(EspTwaiFrame {
445            id: id.into(),
446            data: [0; 8],
447            dlc,
448            is_remote: true,
449            self_reception: false,
450        })
451    }
452
453    /// Creates a new `EspTwaiFrame` ready for self-reception with the specified
454    /// ID and data payload.
455    pub fn new_self_reception(id: impl Into<Id>, data: &[u8]) -> Option<Self> {
456        if data.len() > 8 {
457            return None;
458        }
459
460        let mut d: [u8; 8] = [0; 8];
461        d[..data.len()].copy_from_slice(data);
462
463        Some(EspTwaiFrame {
464            id: id.into(),
465            data: d,
466            dlc: data.len(),
467            is_remote: false,
468            self_reception: true,
469        })
470    }
471
472    /// Make a new frame from an id, pointer to the TWAI_DATA_x_REG registers,
473    /// and the length of the data payload (dlc).
474    ///
475    /// # Safety
476    /// This is unsafe because it directly accesses peripheral registers.
477    unsafe fn new_from_data_registers(
478        id: impl Into<Id>,
479        registers: *const u32,
480        dlc: usize,
481    ) -> Self {
482        let mut data: [u8; 8] = [0; 8];
483
484        // Copy the data from the memory mapped peripheral into actual memory.
485        unsafe {
486            copy_from_data_register(&mut data[..dlc], registers);
487        }
488
489        Self {
490            id: id.into(),
491            data,
492            dlc,
493            is_remote: false,
494            self_reception: false,
495        }
496    }
497}
498
499#[instability::unstable]
500impl embedded_can::Frame for EspTwaiFrame {
501    fn new(id: impl Into<embedded_can::Id>, data: &[u8]) -> Option<Self> {
502        Self::new(id.into(), data)
503    }
504
505    fn new_remote(id: impl Into<embedded_can::Id>, dlc: usize) -> Option<Self> {
506        Self::new_remote(id.into(), dlc)
507    }
508
509    fn is_extended(&self) -> bool {
510        matches!(self.id, Id::Extended(_))
511    }
512
513    fn is_remote_frame(&self) -> bool {
514        self.is_remote
515    }
516
517    fn id(&self) -> embedded_can::Id {
518        self.id.into()
519    }
520
521    fn dlc(&self) -> usize {
522        self.dlc
523    }
524
525    fn data(&self) -> &[u8] {
526        // Remote frames do not contain data, yet have a value for the dlc so return
527        // an empty slice for remote frames.
528        match self.is_remote {
529            true => &[],
530            false => &self.data[0..self.dlc],
531        }
532    }
533}
534
535/// The underlying timings for the TWAI peripheral.
536#[derive(Debug, Copy, Clone, Eq, PartialEq)]
537#[cfg_attr(feature = "defmt", derive(defmt::Format))]
538pub struct TimingConfig {
539    /// The baudrate prescaler is used to determine the period of each time
540    /// quantum by dividing the TWAI controller's source clock.
541    pub baud_rate_prescaler: u16,
542
543    /// The synchronization jump width is used to determine the maximum number
544    /// of time quanta a single bit time can be lengthened/shortened for
545    /// synchronization purposes.
546    pub sync_jump_width: u8,
547
548    /// Timing segment 1 consists of 1 to 16 time quanta before sample point.
549    pub tseg_1: u8,
550
551    /// Timing Segment 2 consists of 1 to 8 time quanta after sample point.
552    pub tseg_2: u8,
553
554    /// Enabling triple sampling causes 3 time quanta to be sampled per bit
555    /// instead of 1.
556    pub triple_sample: bool,
557}
558
559/// A selection of pre-determined baudrates for the TWAI driver.
560/// Currently these timings are sourced from the ESP IDF C driver which assumes
561/// an APB clock of 80MHz.
562#[derive(Debug, Copy, Clone, Eq, PartialEq)]
563#[cfg_attr(feature = "defmt", derive(defmt::Format))]
564pub enum BaudRate {
565    /// A baud rate of 125 Kbps.
566    B125K,
567    /// A baud rate of 250 Kbps.
568    B250K,
569    /// A baud rate of 500 Kbps.
570    B500K,
571    /// A baud rate of 1 Mbps.
572    B1000K,
573    /// A custom baud rate defined by the user.
574    ///
575    /// This variant allows users to specify their own timing configuration
576    /// using a `TimingConfig` struct.
577    Custom(TimingConfig),
578}
579
580impl BaudRate {
581    /// Convert the BaudRate into the timings that the peripheral needs.
582    // See: https://github.com/espressif/esp-idf/tree/master/components/hal/include/hal/twai_types.h
583    const fn timing(self) -> TimingConfig {
584        #[cfg(not(esp32h2))]
585        let timing = match self {
586            Self::B125K => TimingConfig {
587                baud_rate_prescaler: 32,
588                sync_jump_width: 3,
589                tseg_1: 15,
590                tseg_2: 4,
591                triple_sample: false,
592            },
593            Self::B250K => TimingConfig {
594                baud_rate_prescaler: 16,
595                sync_jump_width: 3,
596                tseg_1: 15,
597                tseg_2: 4,
598                triple_sample: false,
599            },
600            Self::B500K => TimingConfig {
601                baud_rate_prescaler: 8,
602                sync_jump_width: 3,
603                tseg_1: 15,
604                tseg_2: 4,
605                triple_sample: false,
606            },
607            Self::B1000K => TimingConfig {
608                baud_rate_prescaler: 4,
609                sync_jump_width: 3,
610                tseg_1: 15,
611                tseg_2: 4,
612                triple_sample: false,
613            },
614            Self::Custom(timing_config) => timing_config,
615        };
616
617        #[cfg(esp32h2)]
618        let timing = match self {
619            Self::B125K => TimingConfig {
620                baud_rate_prescaler: 16,
621                sync_jump_width: 3,
622                tseg_1: 11,
623                tseg_2: 4,
624                triple_sample: false,
625            },
626            Self::B250K => TimingConfig {
627                baud_rate_prescaler: 8,
628                sync_jump_width: 3,
629                tseg_1: 11,
630                tseg_2: 4,
631                triple_sample: false,
632            },
633            Self::B500K => TimingConfig {
634                baud_rate_prescaler: 4,
635                sync_jump_width: 3,
636                tseg_1: 11,
637                tseg_2: 4,
638                triple_sample: false,
639            },
640            Self::B1000K => TimingConfig {
641                baud_rate_prescaler: 2,
642                sync_jump_width: 3,
643                tseg_1: 11,
644                tseg_2: 4,
645                triple_sample: false,
646            },
647            Self::Custom(timing_config) => timing_config,
648        };
649
650        // clock source on ESP32-C6 is xtal (40MHz)
651        #[cfg(esp32c6)]
652        let timing = TimingConfig {
653            baud_rate_prescaler: timing.baud_rate_prescaler / 2,
654            ..timing
655        };
656
657        timing
658    }
659}
660
661/// An inactive TWAI peripheral in the "Reset"/configuration state.
662pub struct TwaiConfiguration<'d, Dm: DriverMode> {
663    twai: AnyTwai<'d>,
664    filter: Option<(FilterType, [u8; 8])>,
665    phantom: PhantomData<Dm>,
666    mode: TwaiMode,
667    _guard: PeripheralGuard,
668}
669
670impl<'d, Dm> TwaiConfiguration<'d, Dm>
671where
672    Dm: DriverMode,
673{
674    fn new_internal(
675        twai: AnyTwai<'d>,
676        rx_pin: impl PeripheralInput<'d>,
677        tx_pin: impl PeripheralOutput<'d>,
678        baud_rate: BaudRate,
679        no_transceiver: bool,
680        mode: TwaiMode,
681    ) -> Self {
682        let rx_pin = rx_pin.into();
683        let tx_pin = tx_pin.into();
684
685        let guard = PeripheralGuard::new(twai.peripheral());
686
687        let mut this = TwaiConfiguration {
688            twai,
689            filter: None, // We'll immediately call `set_filter`
690            phantom: PhantomData,
691            mode,
692            _guard: guard,
693        };
694
695        // Accept all messages by default.
696        this.set_filter(
697            const { SingleStandardFilter::new(b"xxxxxxxxxxx", b"x", [b"xxxxxxxx", b"xxxxxxxx"]) },
698        );
699
700        // Set RESET bit to 1
701        this.regs().mode().write(|w| w.reset_mode().set_bit());
702
703        // Enable extended register layout
704        #[cfg(esp32)]
705        this.regs()
706            .clock_divider()
707            .modify(|_, w| w.ext_mode().set_bit());
708
709        // Set up the GPIO pins.
710        let tx_config = if no_transceiver {
711            OutputConfig::default()
712                .with_drive_mode(DriveMode::OpenDrain)
713                .with_pull(Pull::Up)
714        } else {
715            OutputConfig::default()
716        };
717
718        tx_pin.apply_output_config(&tx_config);
719        rx_pin.apply_input_config(&InputConfig::default().with_pull(if no_transceiver {
720            Pull::Up
721        } else {
722            Pull::None
723        }));
724
725        tx_pin.set_output_enable(true);
726        rx_pin.set_input_enable(true);
727
728        this.twai.output_signal().connect_to(&tx_pin);
729        this.twai.input_signal().connect_to(&rx_pin);
730
731        // Freeze REC by changing to LOM mode
732        this.set_mode(TwaiMode::ListenOnly);
733
734        // Set TEC to 0
735        this.regs()
736            .tx_err_cnt()
737            .write(|w| unsafe { w.tx_err_cnt().bits(0) });
738
739        // Set REC to 0
740        this.regs()
741            .rx_err_cnt()
742            .write(|w| unsafe { w.rx_err_cnt().bits(0) });
743
744        // Set EWL to 96
745        this.regs()
746            .err_warning_limit()
747            .write(|w| unsafe { w.err_warning_limit().bits(96) });
748
749        this.set_baud_rate(baud_rate);
750        this
751    }
752
753    fn regs(&self) -> &RegisterBlock {
754        self.twai.register_block()
755    }
756
757    fn internal_set_interrupt_handler(&mut self, handler: InterruptHandler) {
758        for core in Cpu::other() {
759            crate::interrupt::disable(core, self.twai.interrupt());
760        }
761        unsafe { crate::interrupt::bind_interrupt(self.twai.interrupt(), handler.handler()) };
762
763        unwrap!(crate::interrupt::enable(
764            self.twai.interrupt(),
765            handler.priority()
766        ));
767    }
768
769    /// Set the bitrate of the bus.
770    ///
771    /// Note: The timings currently assume a APB_CLK of 80MHz.
772    fn set_baud_rate(&mut self, baud_rate: BaudRate) {
773        // TWAI is clocked from the APB_CLK according to Table 6-4 [ESP32C3 Reference Manual](https://www.espressif.com/sites/default/files/documentation/esp32-c3_technical_reference_manual_en.pdf)
774        // Included timings are all for 80MHz so assert that we are running at 80MHz.
775        #[cfg(not(any(esp32h2, esp32c6)))]
776        {
777            let apb_clock = crate::clock::Clocks::get().apb_clock;
778            assert!(apb_clock.as_mhz() == 80);
779        }
780
781        // Unpack the baud rate timings and convert them to the values needed for the
782        // register. Many of the registers have a minimum value of 1 which is
783        // represented by having zero bits set, therefore many values need to
784        // have 1 subtracted from them before being stored into the register.
785        let timing = baud_rate.timing();
786
787        #[cfg_attr(not(esp32), allow(unused_mut))]
788        let mut prescaler = timing.baud_rate_prescaler;
789
790        #[cfg(esp32)]
791        {
792            // From <https://github.com/espressif/esp-idf/blob/6e5a178b3120dced7fa5c29c655cc22ea182df3d/components/soc/esp32/register/soc/twai_struct.h#L79>
793            // and <https://github.com/espressif/esp-idf/blob/6e5a178b3120dced7fa5c29c655cc22ea182df3d/components/hal/esp32/include/hal/twai_ll.h#L528-L534>:
794            if timing.baud_rate_prescaler > 128 {
795                // Enable /2 baudrate divider by setting `brp_div`.
796                // `brp_div` is not an interrupt, it will prescale BRP by 2. Only available on
797                // ESP32 Revision 2 or later. Reserved otherwise.
798                self.regs().int_ena().modify(|_, w| w.brp_div().set_bit());
799                prescaler = timing.baud_rate_prescaler / 2;
800            } else {
801                // Disable /2 baudrate divider by clearing brp_div.
802                self.regs().int_ena().modify(|_, w| w.brp_div().clear_bit());
803            }
804        }
805
806        let prescale = (prescaler / 2) - 1;
807        let sjw = timing.sync_jump_width - 1;
808        let tseg_1 = timing.tseg_1 - 1;
809        let tseg_2 = timing.tseg_2 - 1;
810        let triple_sample = timing.triple_sample;
811
812        // Set up the prescaler and sync jump width.
813        self.regs().bus_timing_0().modify(|_, w| unsafe {
814            w.baud_presc().bits(prescale as _);
815            w.sync_jump_width().bits(sjw)
816        });
817
818        // Set up the time segment 1, time segment 2, and triple sample.
819        self.regs().bus_timing_1().modify(|_, w| unsafe {
820            w.time_seg1().bits(tseg_1);
821            w.time_seg2().bits(tseg_2);
822            w.time_samp().bit(triple_sample)
823        });
824
825        // disable CLKOUT
826        self.regs()
827            .clock_divider()
828            .modify(|_, w| w.clock_off().set_bit());
829    }
830
831    /// Set up the acceptance filter on the device.
832    ///
833    /// NOTE: On a bus with mixed 11-bit and 29-bit packet id's, you may
834    /// experience an 11-bit filter match against a 29-bit frame and vice
835    /// versa. Your application should check the id again once a frame has
836    /// been received to make sure it is the expected value.
837    ///
838    /// You may use a `const {}` block to ensure that the filter is parsed
839    /// during program compilation.
840    ///
841    /// The filter is not applied to the peripheral until [`Self::start`] is
842    /// called.
843    ///
844    /// [ESP32C3 Reference Manual](https://www.espressif.com/sites/default/files/documentation/esp32-c3_technical_reference_manual_en.pdf#subsubsection.29.4.6)
845    pub fn set_filter(&mut self, filter: impl Filter) {
846        // Convert the filter into values for the registers and store them for later
847        // use.
848        self.filter = Some((filter.filter_type(), filter.to_registers()));
849    }
850
851    fn apply_filter(&self) {
852        let Some((filter_type, registers)) = self.filter.as_ref() else {
853            return;
854        };
855
856        // Set or clear the rx filter mode bit depending on the filter type.
857        self.regs()
858            .mode()
859            .modify(|_, w| w.rx_filter_mode().bit(*filter_type == FilterType::Single));
860
861        // Copy the filter to the peripheral.
862        unsafe {
863            copy_to_data_register(self.regs().data_0().as_ptr(), registers);
864        }
865    }
866
867    /// Set the error warning threshold.
868    ///
869    /// In the case when any of an error counter value exceeds the threshold, or
870    /// all the error counter values are below the threshold, an error
871    /// warning interrupt will be triggered (given the enable signal is
872    /// valid).
873    pub fn set_error_warning_limit(&mut self, limit: u8) {
874        self.regs()
875            .err_warning_limit()
876            .write(|w| unsafe { w.err_warning_limit().bits(limit) });
877    }
878
879    /// Set the operating mode based on provided option
880    fn set_mode(&self, mode: TwaiMode) {
881        self.regs().mode().modify(|_, w| {
882            // self-test mode turns off acknowledgement requirement
883            w.self_test_mode().bit(mode == TwaiMode::SelfTest);
884            w.listen_only_mode().bit(mode == TwaiMode::ListenOnly)
885        });
886    }
887
888    /// Put the peripheral into Operation Mode, allowing the transmission and
889    /// reception of packets using the new object.
890    pub fn start(self) -> Twai<'d, Dm> {
891        self.apply_filter();
892        self.set_mode(self.mode);
893
894        // Clear the TEC and REC
895        self.regs()
896            .tx_err_cnt()
897            .write(|w| unsafe { w.tx_err_cnt().bits(0) });
898
899        let rec =
900            if cfg!(any(esp32, esp32s2, esp32s3, esp32c3)) && self.mode == TwaiMode::ListenOnly {
901                // Errata workaround: Prevent transmission of dominant error frame while in
902                // listen only mode by setting REC to 128 before exiting reset mode.
903                // This forces the controller to be error passive (thus only transmits recessive
904                // bits). The TEC/REC remain frozen in listen only mode thus
905                // ensuring we remain error passive.
906                128
907            } else {
908                0
909            };
910        self.regs()
911            .rx_err_cnt()
912            .write(|w| unsafe { w.rx_err_cnt().bits(rec) });
913
914        // Clear any interrupts by reading the status register
915        cfg_if::cfg_if! {
916            if #[cfg(any(esp32, esp32c3, esp32s2, esp32s3))] {
917                let _ = self.regs().int_raw().read();
918            } else {
919                let _ = self.regs().interrupt().read();
920            }
921        }
922
923        // Put the peripheral into operation mode by clearing the reset mode bit.
924        self.regs().mode().modify(|_, w| w.reset_mode().clear_bit());
925
926        Twai {
927            rx: TwaiRx {
928                twai: unsafe { self.twai.clone_unchecked() },
929                phantom: PhantomData,
930                _guard: PeripheralGuard::new(self.twai.peripheral()),
931            },
932            tx: TwaiTx {
933                twai: unsafe { self.twai.clone_unchecked() },
934                phantom: PhantomData,
935                _guard: PeripheralGuard::new(self.twai.peripheral()),
936            },
937            twai: unsafe { self.twai.clone_unchecked() },
938            phantom: PhantomData,
939        }
940    }
941}
942
943impl<'d> TwaiConfiguration<'d, Blocking> {
944    /// Create a new instance of [TwaiConfiguration]
945    ///
946    /// You will need to use a transceiver to connect to the TWAI bus
947    pub fn new(
948        peripheral: impl Instance + 'd,
949        rx_pin: impl PeripheralInput<'d>,
950        tx_pin: impl PeripheralOutput<'d>,
951        baud_rate: BaudRate,
952        mode: TwaiMode,
953    ) -> Self {
954        Self::new_internal(peripheral.degrade(), rx_pin, tx_pin, baud_rate, false, mode)
955    }
956
957    /// Create a new instance of [TwaiConfiguration] meant to connect two ESP32s
958    /// directly
959    ///
960    /// You don't need a transceiver by following the description in the
961    /// `twai.rs` example
962    pub fn new_no_transceiver(
963        peripheral: impl Instance + 'd,
964        rx_pin: impl PeripheralInput<'d>,
965        tx_pin: impl PeripheralOutput<'d>,
966        baud_rate: BaudRate,
967        mode: TwaiMode,
968    ) -> Self {
969        Self::new_internal(peripheral.degrade(), rx_pin, tx_pin, baud_rate, true, mode)
970    }
971
972    /// Convert the configuration into an async configuration.
973    pub fn into_async(mut self) -> TwaiConfiguration<'d, Async> {
974        self.set_interrupt_handler(self.twai.async_handler());
975        TwaiConfiguration {
976            twai: self.twai,
977            filter: self.filter,
978            phantom: PhantomData,
979            mode: self.mode,
980            _guard: self._guard,
981        }
982    }
983
984    /// Registers an interrupt handler for the TWAI peripheral.
985    ///
986    /// Note that this will replace any previously registered interrupt
987    /// handlers.
988    #[instability::unstable]
989    pub fn set_interrupt_handler(&mut self, handler: crate::interrupt::InterruptHandler) {
990        self.internal_set_interrupt_handler(handler);
991    }
992}
993
994impl<'d> TwaiConfiguration<'d, Async> {
995    /// Convert the configuration into a blocking configuration.
996    pub fn into_blocking(self) -> TwaiConfiguration<'d, Blocking> {
997        use crate::{interrupt, system::Cpu};
998
999        interrupt::disable(Cpu::current(), self.twai.interrupt());
1000
1001        // Re-create in  blocking mode
1002        TwaiConfiguration {
1003            twai: self.twai,
1004            filter: self.filter,
1005            phantom: PhantomData,
1006            mode: self.mode,
1007            _guard: self._guard,
1008        }
1009    }
1010}
1011
1012impl crate::private::Sealed for TwaiConfiguration<'_, Blocking> {}
1013
1014#[instability::unstable]
1015impl crate::interrupt::InterruptConfigurable for TwaiConfiguration<'_, Blocking> {
1016    fn set_interrupt_handler(&mut self, handler: crate::interrupt::InterruptHandler) {
1017        self.internal_set_interrupt_handler(handler);
1018    }
1019}
1020
1021/// An active TWAI peripheral in Normal Mode.
1022///
1023/// In this mode, the TWAI controller can transmit and receive messages
1024/// including error signals (such as error and overload frames).
1025pub struct Twai<'d, Dm: DriverMode> {
1026    twai: AnyTwai<'d>,
1027    tx: TwaiTx<'d, Dm>,
1028    rx: TwaiRx<'d, Dm>,
1029    phantom: PhantomData<Dm>,
1030}
1031
1032impl<'d, Dm> Twai<'d, Dm>
1033where
1034    Dm: DriverMode,
1035{
1036    fn regs(&self) -> &RegisterBlock {
1037        self.twai.register_block()
1038    }
1039
1040    fn mode(&self) -> TwaiMode {
1041        let mode = self.regs().mode().read();
1042
1043        if mode.self_test_mode().bit_is_set() {
1044            TwaiMode::SelfTest
1045        } else if mode.listen_only_mode().bit_is_set() {
1046            TwaiMode::ListenOnly
1047        } else {
1048            TwaiMode::Normal
1049        }
1050    }
1051
1052    /// Stop the peripheral, putting it into reset mode and enabling
1053    /// reconfiguration.
1054    pub fn stop(self) -> TwaiConfiguration<'d, Dm> {
1055        // Put the peripheral into reset/configuration mode by setting the reset mode
1056        // bit.
1057        self.regs().mode().modify(|_, w| w.reset_mode().set_bit());
1058
1059        let mode = self.mode();
1060
1061        let guard = PeripheralGuard::new(self.twai.peripheral());
1062        TwaiConfiguration {
1063            twai: self.twai,
1064            filter: None, // filter already applied, no need to restore it
1065            phantom: PhantomData,
1066            mode,
1067            _guard: guard,
1068        }
1069    }
1070
1071    /// Returns the value of the receive error counter.
1072    pub fn receive_error_count(&self) -> u8 {
1073        self.regs().rx_err_cnt().read().rx_err_cnt().bits()
1074    }
1075
1076    /// Returns the value of the transmit error counter.
1077    pub fn transmit_error_count(&self) -> u8 {
1078        self.regs().tx_err_cnt().read().tx_err_cnt().bits()
1079    }
1080
1081    /// Check if the controller is in a bus off state.
1082    pub fn is_bus_off(&self) -> bool {
1083        self.regs().status().read().bus_off_st().bit_is_set()
1084    }
1085
1086    /// Get the number of messages that the peripheral has available in the
1087    /// receive FIFO.
1088    ///
1089    /// Note that this may not be the number of valid messages in the receive
1090    /// FIFO due to fifo overflow/overrun.
1091    pub fn num_available_messages(&self) -> u8 {
1092        self.regs()
1093            .rx_message_cnt()
1094            .read()
1095            .rx_message_counter()
1096            .bits()
1097    }
1098
1099    /// Clear the receive FIFO, discarding any valid, partial, or invalid
1100    /// packets.
1101    ///
1102    /// This is typically used to clear an overrun receive FIFO.
1103    ///
1104    /// TODO: Not sure if this needs to be guarded against Bus Off or other
1105    /// error states.
1106    pub fn clear_receive_fifo(&self) {
1107        while self.num_available_messages() > 0 {
1108            release_receive_fifo(self.regs());
1109        }
1110    }
1111
1112    /// Sends the specified `EspTwaiFrame` over the TWAI bus.
1113    pub fn transmit(&mut self, frame: &EspTwaiFrame) -> nb::Result<(), EspTwaiError> {
1114        self.tx.transmit(frame)
1115    }
1116
1117    /// Receives a TWAI frame from the TWAI bus.
1118    pub fn receive(&mut self) -> nb::Result<EspTwaiFrame, EspTwaiError> {
1119        self.rx.receive()
1120    }
1121
1122    /// Consumes this `Twai` instance and splits it into transmitting and
1123    /// receiving halves.
1124    pub fn split(self) -> (TwaiRx<'d, Dm>, TwaiTx<'d, Dm>) {
1125        (self.rx, self.tx)
1126    }
1127}
1128
1129/// Interface to the TWAI transmitter part.
1130pub struct TwaiTx<'d, Dm: DriverMode> {
1131    twai: AnyTwai<'d>,
1132    phantom: PhantomData<Dm>,
1133    _guard: PeripheralGuard,
1134}
1135
1136impl<Dm> TwaiTx<'_, Dm>
1137where
1138    Dm: DriverMode,
1139{
1140    fn regs(&self) -> &RegisterBlock {
1141        self.twai.register_block()
1142    }
1143
1144    /// Transmit a frame.
1145    ///
1146    /// Because of how the TWAI registers are set up, we have to do some
1147    /// assembly of bytes. Note that these registers serve a filter
1148    /// configuration role when the device is in configuration mode so
1149    /// patching the svd files to improve this may be non-trivial.
1150    ///
1151    /// [ESP32C3 Reference Manual](https://www.espressif.com/sites/default/files/documentation/esp32-c3_technical_reference_manual_en.pdf#subsubsection.29.4.4.2)
1152    ///
1153    /// NOTE: TODO: This may not work if using the self reception/self test
1154    /// functionality. See notes 1 and 2 in the "Frame Identifier" section
1155    /// of the reference manual.
1156    pub fn transmit(&mut self, frame: &EspTwaiFrame) -> nb::Result<(), EspTwaiError> {
1157        let status = self.regs().status().read();
1158
1159        // Check that the peripheral is not in a bus off state.
1160        if status.bus_off_st().bit_is_set() {
1161            return nb::Result::Err(nb::Error::Other(EspTwaiError::BusOff));
1162        }
1163        // Check that the peripheral is not already transmitting a packet.
1164        if !status.tx_buf_st().bit_is_set() {
1165            return nb::Result::Err(nb::Error::WouldBlock);
1166        }
1167
1168        write_frame(self.regs(), frame);
1169
1170        Ok(())
1171    }
1172}
1173
1174/// Interface to the TWAI receiver part.
1175pub struct TwaiRx<'d, Dm: DriverMode> {
1176    twai: AnyTwai<'d>,
1177    phantom: PhantomData<Dm>,
1178    _guard: PeripheralGuard,
1179}
1180
1181impl<Dm> TwaiRx<'_, Dm>
1182where
1183    Dm: DriverMode,
1184{
1185    fn regs(&self) -> &RegisterBlock {
1186        self.twai.register_block()
1187    }
1188
1189    /// Receive a frame
1190    pub fn receive(&mut self) -> nb::Result<EspTwaiFrame, EspTwaiError> {
1191        let status = self.regs().status().read();
1192
1193        // Check that the peripheral is not in a bus off state.
1194        if status.bus_off_st().bit_is_set() {
1195            return nb::Result::Err(nb::Error::Other(EspTwaiError::BusOff));
1196        }
1197
1198        // Check that we actually have packets to receive.
1199        if !status.rx_buf_st().bit_is_set() {
1200            return nb::Result::Err(nb::Error::WouldBlock);
1201        }
1202
1203        // Check if the packet in the receive buffer is valid or overrun.
1204        if status.miss_st().bit_is_set() {
1205            return nb::Result::Err(nb::Error::Other(EspTwaiError::EmbeddedHAL(
1206                ErrorKind::Overrun,
1207            )));
1208        }
1209
1210        Ok(read_frame(self.regs())?)
1211    }
1212}
1213
1214/// Represents errors that can occur in the TWAI driver.
1215/// This enum defines the possible errors that can be encountered when
1216/// interacting with the TWAI peripheral.
1217#[derive(Debug, Copy, Clone, Eq, PartialEq)]
1218#[cfg_attr(feature = "defmt", derive(defmt::Format))]
1219pub enum EspTwaiError {
1220    /// TWAI peripheral has entered a bus-off state.
1221    BusOff,
1222    /// The received frame contains an invalid DLC.
1223    NonCompliantDlc(u8),
1224    /// Encapsulates errors defined by the embedded-hal crate.
1225    EmbeddedHAL(ErrorKind),
1226}
1227
1228#[instability::unstable]
1229impl embedded_can::Error for EspTwaiError {
1230    fn kind(&self) -> embedded_can::ErrorKind {
1231        if let Self::EmbeddedHAL(kind) = self {
1232            (*kind).into()
1233        } else {
1234            embedded_can::ErrorKind::Other
1235        }
1236    }
1237}
1238
1239/// Copy data from multiple TWAI_DATA_x_REG registers, packing the source into
1240/// the destination.
1241///
1242/// # Safety
1243/// This function is marked unsafe because it reads arbitrarily from
1244/// memory-mapped registers. Specifically, this function is used with the
1245/// TWAI_DATA_x_REG registers which has different results based on the mode of
1246/// the peripheral.
1247#[inline(always)]
1248unsafe fn copy_from_data_register(dest: &mut [u8], src: *const u32) {
1249    for (i, dest) in dest.iter_mut().enumerate() {
1250        // Perform a volatile read to avoid compiler optimizations.
1251        unsafe {
1252            *dest = src.add(i).read_volatile() as u8;
1253        }
1254    }
1255}
1256
1257/// Copy data to multiple TWAI_DATA_x_REG registers, unpacking the source into
1258/// the destination.
1259///
1260/// # Safety
1261/// This function is marked unsafe because it writes arbitrarily to
1262/// memory-mapped registers. Specifically, this function is used with the
1263/// TWAI_DATA_x_REG registers which has different results based on the mode of
1264/// the peripheral.
1265#[inline(always)]
1266unsafe fn copy_to_data_register(dest: *mut u32, src: &[u8]) {
1267    for (i, src) in src.iter().enumerate() {
1268        // Perform a volatile write to avoid compiler optimizations.
1269        unsafe {
1270            dest.add(i).write_volatile(*src as u32);
1271        }
1272    }
1273}
1274
1275#[instability::unstable]
1276impl<Dm> embedded_can::nb::Can for Twai<'_, Dm>
1277where
1278    Dm: DriverMode,
1279{
1280    type Frame = EspTwaiFrame;
1281    type Error = EspTwaiError;
1282
1283    /// Transmit a frame.
1284    fn transmit(&mut self, frame: &Self::Frame) -> nb::Result<Option<Self::Frame>, Self::Error> {
1285        self.tx.transmit(frame)?;
1286
1287        // Success in readying packet for transmit. No packets can be replaced in the
1288        // transmit buffer so return None in accordance with the
1289        // embedded-can/embedded-hal trait.
1290        nb::Result::Ok(None)
1291    }
1292
1293    /// Return a received frame if there are any available.
1294    fn receive(&mut self) -> nb::Result<Self::Frame, Self::Error> {
1295        self.rx.receive()
1296    }
1297}
1298
1299/// TWAI peripheral instance.
1300#[doc(hidden)]
1301pub trait PrivateInstance: crate::private::Sealed {
1302    /// The identifier number for this TWAI instance.
1303    fn number(&self) -> usize;
1304
1305    /// Returns the system peripheral marker for this instance.
1306    fn peripheral(&self) -> crate::system::Peripheral;
1307
1308    /// Input signal.
1309    fn input_signal(&self) -> InputSignal;
1310    /// Output signal.
1311    fn output_signal(&self) -> OutputSignal;
1312    /// The interrupt associated with this TWAI instance.
1313    fn interrupt(&self) -> crate::peripherals::Interrupt;
1314
1315    /// Provides an asynchronous interrupt handler for TWAI instance.
1316    fn async_handler(&self) -> InterruptHandler;
1317
1318    /// Returns a reference to the register block for TWAI instance.
1319    fn register_block(&self) -> &RegisterBlock;
1320
1321    /// Enables interrupts for the TWAI peripheral.
1322    fn enable_interrupts(&self) {
1323        cfg_if::cfg_if! {
1324            if #[cfg(any(esp32, esp32c3, esp32s2, esp32s3))] {
1325                self.register_block().int_ena().modify(|_, w| {
1326                    w.rx_int_ena().set_bit();
1327                    w.tx_int_ena().set_bit();
1328                    w.bus_err_int_ena().set_bit();
1329                    w.arb_lost_int_ena().set_bit();
1330                    w.err_passive_int_ena().set_bit()
1331                });
1332            } else {
1333                self.register_block().interrupt_enable().modify(|_, w| {
1334                    w.ext_receive_int_ena().set_bit();
1335                    w.ext_transmit_int_ena().set_bit();
1336                    w.bus_err_int_ena().set_bit();
1337                    w.arbitration_lost_int_ena().set_bit();
1338                    w.err_passive_int_ena().set_bit()
1339                });
1340            }
1341        }
1342    }
1343
1344    /// Returns a reference to the asynchronous state for this TWAI instance.
1345    fn async_state(&self) -> &asynch::TwaiAsyncState;
1346}
1347
1348/// Read a frame from the peripheral.
1349fn read_frame(register_block: &RegisterBlock) -> Result<EspTwaiFrame, EspTwaiError> {
1350    // Read the frame information and extract the frame id format and dlc.
1351    let data_0 = register_block.data_0().read().tx_byte_0().bits();
1352
1353    let is_standard_format = data_0 & (0b1 << 7) == 0;
1354    let is_data_frame = data_0 & (0b1 << 6) == 0;
1355    let self_reception = data_0 & (0b1 << 4) != 0;
1356    let dlc = data_0 & 0b1111;
1357
1358    if dlc > 8 {
1359        // Release the packet we read from the FIFO, allowing the peripheral to prepare
1360        // the next packet.
1361        release_receive_fifo(register_block);
1362
1363        return Err(EspTwaiError::NonCompliantDlc(dlc));
1364    }
1365    let dlc = dlc as usize;
1366
1367    // Read the payload from the packet and construct a frame.
1368    let (id, data_ptr) = if is_standard_format {
1369        // Frame uses standard 11 bit id.
1370        let data_1 = register_block.data_1().read().tx_byte_1().bits();
1371        let data_2 = register_block.data_2().read().tx_byte_2().bits();
1372
1373        let raw_id: u16 = ((data_1 as u16) << 3) | ((data_2 as u16) >> 5);
1374
1375        let id = Id::from(StandardId::new(raw_id).unwrap());
1376        (id, register_block.data_3().as_ptr())
1377    } else {
1378        // Frame uses extended 29 bit id.
1379        let data_1 = register_block.data_1().read().tx_byte_1().bits();
1380        let data_2 = register_block.data_2().read().tx_byte_2().bits();
1381        let data_3 = register_block.data_3().read().tx_byte_3().bits();
1382        let data_4 = register_block.data_4().read().tx_byte_4().bits();
1383
1384        let raw_id: u32 = ((data_1 as u32) << 21)
1385            | ((data_2 as u32) << 13)
1386            | ((data_3 as u32) << 5)
1387            | ((data_4 as u32) >> 3);
1388
1389        let id = Id::from(ExtendedId::new(raw_id).unwrap());
1390        (id, register_block.data_5().as_ptr())
1391    };
1392
1393    let mut frame = if is_data_frame {
1394        unsafe { EspTwaiFrame::new_from_data_registers(id, data_ptr, dlc) }
1395    } else {
1396        EspTwaiFrame::new_remote(id, dlc).unwrap()
1397    };
1398    frame.self_reception = self_reception;
1399
1400    // Release the packet we read from the FIFO, allowing the peripheral to prepare
1401    // the next packet.
1402    release_receive_fifo(register_block);
1403
1404    Ok(frame)
1405}
1406
1407/// Release the message in the buffer. This will decrement the received
1408/// message counter and prepare the next message in the FIFO for
1409/// reading.
1410fn release_receive_fifo(register_block: &RegisterBlock) {
1411    register_block.cmd().write(|w| w.release_buf().set_bit());
1412}
1413
1414/// Write a frame to the peripheral.
1415fn write_frame(register_block: &RegisterBlock, frame: &EspTwaiFrame) {
1416    // Assemble the frame information into the data_0 byte.
1417    let frame_format: u8 = matches!(frame.id, Id::Extended(_)) as u8;
1418    let self_reception: u8 = frame.self_reception as u8;
1419    let rtr_bit: u8 = frame.is_remote as u8;
1420    let dlc_bits: u8 = frame.dlc as u8 & 0b1111;
1421
1422    let data_0: u8 = (frame_format << 7) | (rtr_bit << 6) | (self_reception << 4) | dlc_bits;
1423
1424    register_block
1425        .data_0()
1426        .write(|w| unsafe { w.tx_byte_0().bits(data_0) });
1427
1428    // Assemble the identifier information of the packet and return where the data
1429    // buffer starts.
1430    let data_ptr = match frame.id {
1431        Id::Standard(id) => {
1432            let id = id.as_raw();
1433
1434            register_block
1435                .data_1()
1436                .write(|w| unsafe { w.tx_byte_1().bits((id >> 3) as u8) });
1437
1438            register_block
1439                .data_2()
1440                .write(|w| unsafe { w.tx_byte_2().bits((id << 5) as u8) });
1441
1442            register_block.data_3().as_ptr()
1443        }
1444        Id::Extended(id) => {
1445            let id = id.as_raw();
1446
1447            register_block
1448                .data_1()
1449                .write(|w| unsafe { w.tx_byte_1().bits((id >> 21) as u8) });
1450            register_block
1451                .data_2()
1452                .write(|w| unsafe { w.tx_byte_2().bits((id >> 13) as u8) });
1453            register_block
1454                .data_3()
1455                .write(|w| unsafe { w.tx_byte_3().bits((id >> 5) as u8) });
1456            register_block
1457                .data_4()
1458                .write(|w| unsafe { w.tx_byte_4().bits((id << 3) as u8) });
1459
1460            register_block.data_5().as_ptr()
1461        }
1462    };
1463
1464    // Store the data portion of the packet into the transmit buffer.
1465    unsafe {
1466        copy_to_data_register(
1467            data_ptr,
1468            match frame.is_remote {
1469                true => &[], // RTR frame, so no data is included.
1470                false => &frame.data[0..frame.dlc],
1471            },
1472        )
1473    }
1474
1475    // Trigger the appropriate transmission request based on self_reception flag
1476    if frame.self_reception {
1477        register_block.cmd().write(|w| w.self_rx_req().set_bit());
1478    } else {
1479        // Set the transmit request command, this will lock the transmit buffer until
1480        // the transmission is complete or aborted.
1481        register_block.cmd().write(|w| w.tx_req().set_bit());
1482    }
1483}
1484
1485impl PrivateInstance for crate::peripherals::TWAI0<'_> {
1486    fn number(&self) -> usize {
1487        0
1488    }
1489
1490    fn peripheral(&self) -> crate::system::Peripheral {
1491        crate::system::Peripheral::Twai0
1492    }
1493
1494    fn input_signal(&self) -> InputSignal {
1495        cfg_if::cfg_if! {
1496            if #[cfg(any(esp32, esp32c3, esp32s2, esp32s3))] {
1497                InputSignal::TWAI_RX
1498            } else {
1499                InputSignal::TWAI0_RX
1500            }
1501        }
1502    }
1503
1504    fn output_signal(&self) -> OutputSignal {
1505        cfg_if::cfg_if! {
1506            if #[cfg(any(esp32, esp32c3, esp32s2, esp32s3))] {
1507                OutputSignal::TWAI_TX
1508            } else {
1509                OutputSignal::TWAI0_TX
1510            }
1511        }
1512    }
1513
1514    fn interrupt(&self) -> crate::peripherals::Interrupt {
1515        crate::peripherals::Interrupt::TWAI0
1516    }
1517
1518    fn async_handler(&self) -> InterruptHandler {
1519        asynch::twai0
1520    }
1521
1522    #[inline(always)]
1523    fn register_block(&self) -> &RegisterBlock {
1524        crate::peripherals::TWAI0::regs()
1525    }
1526
1527    fn async_state(&self) -> &asynch::TwaiAsyncState {
1528        static STATE: asynch::TwaiAsyncState = asynch::TwaiAsyncState::new();
1529        &STATE
1530    }
1531}
1532
1533#[cfg(twai1)]
1534impl PrivateInstance for crate::peripherals::TWAI1<'_> {
1535    fn number(&self) -> usize {
1536        1
1537    }
1538
1539    fn peripheral(&self) -> crate::system::Peripheral {
1540        crate::system::Peripheral::Twai1
1541    }
1542
1543    fn input_signal(&self) -> InputSignal {
1544        InputSignal::TWAI1_RX
1545    }
1546
1547    fn output_signal(&self) -> OutputSignal {
1548        OutputSignal::TWAI1_TX
1549    }
1550
1551    fn interrupt(&self) -> crate::peripherals::Interrupt {
1552        crate::peripherals::Interrupt::TWAI1
1553    }
1554
1555    fn async_handler(&self) -> InterruptHandler {
1556        asynch::twai1
1557    }
1558
1559    #[inline(always)]
1560    fn register_block(&self) -> &RegisterBlock {
1561        crate::peripherals::TWAI1::regs()
1562    }
1563
1564    fn async_state(&self) -> &asynch::TwaiAsyncState {
1565        static STATE: asynch::TwaiAsyncState = asynch::TwaiAsyncState::new();
1566        &STATE
1567    }
1568}
1569
1570crate::any_peripheral! {
1571    /// Any TWAI peripheral.
1572    pub peripheral AnyTwai<'d> {
1573        #[cfg(twai0)]
1574        Twai0(crate::peripherals::TWAI0<'d>),
1575        #[cfg(twai1)]
1576        Twai1(crate::peripherals::TWAI1<'d>),
1577    }
1578}
1579
1580impl PrivateInstance for AnyTwai<'_> {
1581    delegate::delegate! {
1582        to match &self.0 {
1583            #[cfg(twai0)]
1584            AnyTwaiInner::Twai0(twai) => twai,
1585            #[cfg(twai1)]
1586            AnyTwaiInner::Twai1(twai) => twai,
1587        } {
1588            fn number(&self) -> usize;
1589            fn peripheral(&self) -> crate::system::Peripheral;
1590            fn input_signal(&self) -> InputSignal;
1591            fn output_signal(&self) -> OutputSignal;
1592            fn interrupt(&self) -> crate::peripherals::Interrupt;
1593            fn async_handler(&self) -> InterruptHandler;
1594            fn register_block(&self) -> &RegisterBlock;
1595            fn async_state(&self) -> &asynch::TwaiAsyncState;
1596        }
1597    }
1598}
1599
1600/// A peripheral singleton compatible with the TWAI driver.
1601pub trait Instance: PrivateInstance + IntoAnyTwai {}
1602
1603impl Instance for crate::peripherals::TWAI0<'_> {}
1604#[cfg(twai1)]
1605impl Instance for crate::peripherals::TWAI1<'_> {}
1606impl Instance for AnyTwai<'_> {}
1607
1608mod asynch {
1609    use core::{future::poll_fn, task::Poll};
1610
1611    use embassy_sync::{
1612        blocking_mutex::raw::CriticalSectionRawMutex,
1613        channel::Channel,
1614        waitqueue::AtomicWaker,
1615    };
1616    use procmacros::handler;
1617
1618    use super::*;
1619    use crate::peripherals::TWAI0;
1620    #[cfg(twai1)]
1621    use crate::peripherals::TWAI1;
1622
1623    pub struct TwaiAsyncState {
1624        pub tx_waker: AtomicWaker,
1625        pub err_waker: AtomicWaker,
1626        pub rx_queue: Channel<CriticalSectionRawMutex, Result<EspTwaiFrame, EspTwaiError>, 32>,
1627    }
1628
1629    impl Default for TwaiAsyncState {
1630        fn default() -> Self {
1631            Self::new()
1632        }
1633    }
1634
1635    impl TwaiAsyncState {
1636        pub const fn new() -> Self {
1637            Self {
1638                tx_waker: AtomicWaker::new(),
1639                err_waker: AtomicWaker::new(),
1640                rx_queue: Channel::new(),
1641            }
1642        }
1643    }
1644
1645    impl Twai<'_, Async> {
1646        /// Transmits an `EspTwaiFrame` asynchronously over the TWAI bus.
1647        ///
1648        /// The transmission is aborted if the future is dropped. The technical
1649        /// reference manual does not specifiy if aborting the transmission also
1650        /// stops it, in case it is activly transmitting. Therefor it could be
1651        /// the case that even though the future is dropped, the frame was sent
1652        /// anyways.
1653        pub async fn transmit_async(&mut self, frame: &EspTwaiFrame) -> Result<(), EspTwaiError> {
1654            self.tx.transmit_async(frame).await
1655        }
1656        /// Receives an `EspTwaiFrame` asynchronously over the TWAI bus.
1657        pub async fn receive_async(&mut self) -> Result<EspTwaiFrame, EspTwaiError> {
1658            self.rx.receive_async().await
1659        }
1660    }
1661
1662    #[must_use = "futures do nothing unless you `.await` or poll them"]
1663    pub struct TransmitFuture<'d, 'f> {
1664        twai: AnyTwai<'d>,
1665        frame: &'f EspTwaiFrame,
1666        in_flight: bool,
1667    }
1668
1669    impl<'d, 'f> TransmitFuture<'d, 'f> {
1670        pub fn new(twai: AnyTwai<'d>, frame: &'f EspTwaiFrame) -> Self {
1671            Self {
1672                twai,
1673                frame,
1674                in_flight: false,
1675            }
1676        }
1677    }
1678
1679    impl core::future::Future for TransmitFuture<'_, '_> {
1680        type Output = Result<(), EspTwaiError>;
1681
1682        fn poll(
1683            mut self: core::pin::Pin<&mut Self>,
1684            cx: &mut core::task::Context<'_>,
1685        ) -> Poll<Self::Output> {
1686            self.twai.async_state().tx_waker.register(cx.waker());
1687
1688            let regs = self.twai.register_block();
1689            let status = regs.status().read();
1690
1691            // Check that the peripheral is not in a bus off state.
1692            if status.bus_off_st().bit_is_set() {
1693                return Poll::Ready(Err(EspTwaiError::BusOff));
1694            }
1695
1696            // Check that the peripheral is not currently transmitting a packet.
1697            if !status.tx_buf_st().bit_is_set() {
1698                return Poll::Pending;
1699            }
1700
1701            if !self.in_flight {
1702                write_frame(regs, self.frame);
1703                self.in_flight = true;
1704                return Poll::Pending;
1705            }
1706
1707            Poll::Ready(Ok(()))
1708        }
1709    }
1710
1711    impl Drop for TransmitFuture<'_, '_> {
1712        fn drop(&mut self) {
1713            self.twai
1714                .register_block()
1715                .cmd()
1716                .write(|w| w.abort_tx().set_bit());
1717        }
1718    }
1719
1720    impl TwaiTx<'_, Async> {
1721        /// Transmits an `EspTwaiFrame` asynchronously over the TWAI bus.
1722        ///
1723        /// The transmission is aborted if the future is dropped. The technical
1724        /// reference manual does not specifiy if aborting the transmission also
1725        /// stops it, in case it is activly transmitting. Therefor it could be
1726        /// the case that even though the future is dropped, the frame was sent
1727        /// anyways.
1728        pub async fn transmit_async(&mut self, frame: &EspTwaiFrame) -> Result<(), EspTwaiError> {
1729            self.twai.enable_interrupts();
1730            TransmitFuture::new(self.twai.reborrow(), frame).await
1731        }
1732    }
1733
1734    impl TwaiRx<'_, Async> {
1735        /// Receives an `EspTwaiFrame` asynchronously over the TWAI bus.
1736        pub async fn receive_async(&mut self) -> Result<EspTwaiFrame, EspTwaiError> {
1737            self.twai.enable_interrupts();
1738            poll_fn(|cx| {
1739                self.twai.async_state().err_waker.register(cx.waker());
1740
1741                if let Poll::Ready(result) = self.twai.async_state().rx_queue.poll_receive(cx) {
1742                    return Poll::Ready(result);
1743                }
1744
1745                let status = self.regs().status().read();
1746
1747                // Check that the peripheral is not in a bus off state.
1748                if status.bus_off_st().bit_is_set() {
1749                    return Poll::Ready(Err(EspTwaiError::BusOff));
1750                }
1751
1752                // Check if the packet in the receive buffer is valid or overrun.
1753                if status.miss_st().bit_is_set() {
1754                    return Poll::Ready(Err(EspTwaiError::EmbeddedHAL(ErrorKind::Overrun)));
1755                }
1756
1757                Poll::Pending
1758            })
1759            .await
1760        }
1761    }
1762
1763    fn handle_interrupt(register_block: &RegisterBlock, async_state: &TwaiAsyncState) {
1764        cfg_if::cfg_if! {
1765            if #[cfg(any(esp32, esp32c3, esp32s2, esp32s3))] {
1766                let intr_enable = register_block.int_ena().read();
1767                let intr_status = register_block.int_raw().read();
1768
1769                let int_ena_reg = register_block.int_ena();
1770
1771                let tx_int_status = intr_status.tx_int_st();
1772                let rx_int_status = intr_status.rx_int_st();
1773            } else {
1774                let intr_enable = register_block.interrupt_enable().read();
1775                let intr_status = register_block.interrupt().read();
1776
1777                let int_ena_reg = register_block.interrupt_enable();
1778
1779                let tx_int_status = intr_status.transmit_int_st();
1780                let rx_int_status = intr_status.receive_int_st();
1781            }
1782        }
1783
1784        if tx_int_status.bit_is_set() {
1785            async_state.tx_waker.wake();
1786        }
1787
1788        if rx_int_status.bit_is_set() {
1789            let status = register_block.status().read();
1790
1791            let rx_queue = &async_state.rx_queue;
1792
1793            if status.bus_off_st().bit_is_set() {
1794                let _ = rx_queue.try_send(Err(EspTwaiError::BusOff));
1795            }
1796
1797            if status.miss_st().bit_is_set() {
1798                let _ = rx_queue.try_send(Err(EspTwaiError::EmbeddedHAL(ErrorKind::Overrun)));
1799            }
1800
1801            match read_frame(register_block) {
1802                Ok(frame) => {
1803                    let _ = rx_queue.try_send(Ok(frame));
1804                }
1805                Err(e) => warn!("Error reading frame: {:?}", e),
1806            }
1807        }
1808
1809        if intr_status.bits() & 0b11111100 > 0 {
1810            let err_capture = register_block.err_code_cap().read();
1811            let status = register_block.status().read();
1812
1813            // Read error code direction (transmitting or receiving)
1814            let ecc_direction = err_capture.ecc_direction().bit_is_set();
1815
1816            // If the error comes from Tx and Tx request is pending
1817            if !ecc_direction && !status.tx_buf_st().bit_is_set() {
1818                // Cancel a pending transmission request
1819                register_block.cmd().write(|w| w.abort_tx().set_bit());
1820            }
1821
1822            async_state.err_waker.wake();
1823        }
1824
1825        // Clear interrupt request bits
1826        unsafe {
1827            int_ena_reg.modify(|_, w| w.bits(intr_enable.bits() & (!intr_status.bits() | 1)));
1828        }
1829    }
1830
1831    #[handler]
1832    pub(super) fn twai0() {
1833        let twai = unsafe { TWAI0::steal() };
1834        handle_interrupt(twai.register_block(), twai.async_state());
1835    }
1836
1837    #[cfg(twai1)]
1838    #[handler]
1839    pub(super) fn twai1() {
1840        let twai = unsafe { TWAI1::steal() };
1841        handle_interrupt(twai.register_block(), twai.async_state());
1842    }
1843}