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