1#, "/api-reference/peripherals/twai.html#twai-protocol-summary)")]
11#![doc = crate::before_snippet!()]
28#![doc = crate::before_snippet!()]
76use 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#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
150#[non_exhaustive]
151pub enum ErrorKind {
152 Overrun,
154 Bit,
158 Stuff,
162 Crc,
164 Form,
167 Acknowledge,
170 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#[derive(Debug, Copy, Clone, Eq, PartialEq)]
230#[cfg_attr(feature = "defmt", derive(defmt::Format))]
231pub enum TwaiMode {
232 Normal,
234 SelfTest,
237 ListenOnly,
239}
240
241#[derive(Debug, Copy, Clone, Eq, PartialEq)]
243#[cfg_attr(feature = "defmt", derive(defmt::Format))]
244pub struct StandardId(u16);
245
246impl StandardId {
247 pub const ZERO: Self = StandardId(0);
249
250 pub const MAX: Self = StandardId(0x7FF);
252
253 #[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 #[inline]
272 pub const unsafe fn new_unchecked(raw: u16) -> Self {
273 StandardId(raw)
274 }
275
276 #[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#[derive(Debug, Copy, Clone, Eq, PartialEq)]
299#[cfg_attr(feature = "defmt", derive(defmt::Format))]
300pub struct ExtendedId(u32);
301
302impl ExtendedId {
303 pub const ZERO: Self = ExtendedId(0);
305
306 pub const MAX: Self = ExtendedId(0x1FFF_FFFF);
308
309 #[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 #[inline]
328 pub const unsafe fn new_unchecked(raw: u32) -> Self {
329 ExtendedId(raw)
330 }
331
332 #[inline]
334 pub fn as_raw(&self) -> u32 {
335 self.0
336 }
337
338 pub fn standard_id(&self) -> StandardId {
340 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#[derive(Debug, Copy, Clone, Eq, PartialEq)]
361#[cfg_attr(feature = "defmt", derive(defmt::Format))]
362pub enum Id {
363 Standard(StandardId),
365 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#[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 pub fn new(id: impl Into<Id>, data: &[u8]) -> Option<Self> {
417 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 pub fn new_remote(id: impl Into<Id>, dlc: usize) -> Option<Self> {
437 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 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 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_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 match self.is_remote {
525 true => &[],
526 false => &self.data[0..self.dlc],
527 }
528 }
529}
530
531#[derive(Debug, Copy, Clone, Eq, PartialEq)]
533#[cfg_attr(feature = "defmt", derive(defmt::Format))]
534pub struct TimingConfig {
535 pub baud_rate_prescaler: u16,
538
539 pub sync_jump_width: u8,
543
544 pub tseg_1: u8,
546
547 pub tseg_2: u8,
549
550 pub triple_sample: bool,
553}
554
555#[derive(Debug, Copy, Clone, Eq, PartialEq)]
559#[cfg_attr(feature = "defmt", derive(defmt::Format))]
560pub enum BaudRate {
561 B125K,
563 B250K,
565 B500K,
567 B1000K,
569 Custom(TimingConfig),
574}
575
576impl BaudRate {
577 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 #[cfg(esp32c6)]
648 let timing = TimingConfig {
649 baud_rate_prescaler: timing.baud_rate_prescaler / 2,
650 ..timing
651 };
652
653 timing
654 }
655}
656
657pub 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, phantom: PhantomData,
686 mode,
687 _guard: guard,
688 };
689
690 this.set_filter(
692 const { SingleStandardFilter::new(b"xxxxxxxxxxx", b"x", [b"xxxxxxxx", b"xxxxxxxx"]) },
693 );
694
695 this.regs().mode().write(|w| w.reset_mode().set_bit());
697
698 #[cfg(esp32)]
700 this.regs()
701 .clock_divider()
702 .modify(|_, w| w.ext_mode().set_bit());
703
704 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 rx_pin.init_input(rx_pull);
719 this.twai.input_signal().connect_to(rx_pin);
720
721 this.set_mode(TwaiMode::ListenOnly);
723
724 this.regs()
726 .tx_err_cnt()
727 .write(|w| unsafe { w.tx_err_cnt().bits(0) });
728
729 this.regs()
731 .rx_err_cnt()
732 .write(|w| unsafe { w.rx_err_cnt().bits(0) });
733
734 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 fn set_baud_rate(&mut self, baud_rate: BaudRate) {
763 #[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 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 if timing.baud_rate_prescaler > 128 {
785 self.regs().int_ena().modify(|_, w| w.brp_div().set_bit());
789 prescaler = timing.baud_rate_prescaler / 2;
790 } else {
791 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 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 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 self.regs()
817 .clock_divider()
818 .modify(|_, w| w.clock_off().set_bit());
819 }
820
821 pub fn set_filter(&mut self, filter: impl Filter) {
836 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 self.regs()
848 .mode()
849 .modify(|_, w| w.rx_filter_mode().bit(*filter_type == FilterType::Single));
850
851 unsafe {
853 copy_to_data_register(self.regs().data_0().as_ptr(), registers);
854 }
855 }
856
857 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 fn set_mode(&self, mode: TwaiMode) {
871 self.regs().mode().modify(|_, w| {
872 w.self_test_mode().bit(mode == TwaiMode::SelfTest);
874 w.listen_only_mode().bit(mode == TwaiMode::ListenOnly)
875 });
876 }
877
878 pub fn start(self) -> Twai<'d, Dm> {
881 self.apply_filter();
882 self.set_mode(self.mode);
883
884 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 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 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 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 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 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 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 #[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 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 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
1013pub 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 pub fn stop(self) -> TwaiConfiguration<'d, Dm> {
1047 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, phantom: PhantomData,
1058 mode,
1059 _guard: guard,
1060 }
1061 }
1062
1063 pub fn receive_error_count(&self) -> u8 {
1065 self.regs().rx_err_cnt().read().rx_err_cnt().bits()
1066 }
1067
1068 pub fn transmit_error_count(&self) -> u8 {
1070 self.regs().tx_err_cnt().read().tx_err_cnt().bits()
1071 }
1072
1073 pub fn is_bus_off(&self) -> bool {
1075 self.regs().status().read().bus_off_st().bit_is_set()
1076 }
1077
1078 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 pub fn clear_receive_fifo(&self) {
1099 while self.num_available_messages() > 0 {
1100 release_receive_fifo(self.regs());
1101 }
1102 }
1103
1104 pub fn transmit(&mut self, frame: &EspTwaiFrame) -> nb::Result<(), EspTwaiError> {
1106 self.tx.transmit(frame)
1107 }
1108
1109 pub fn receive(&mut self) -> nb::Result<EspTwaiFrame, EspTwaiError> {
1111 self.rx.receive()
1112 }
1113
1114 pub fn split(self) -> (TwaiRx<'d, Dm>, TwaiTx<'d, Dm>) {
1117 (self.rx, self.tx)
1118 }
1119}
1120
1121pub 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 pub fn transmit(&mut self, frame: &EspTwaiFrame) -> nb::Result<(), EspTwaiError> {
1149 let status = self.regs().status().read();
1150
1151 if status.bus_off_st().bit_is_set() {
1153 return nb::Result::Err(nb::Error::Other(EspTwaiError::BusOff));
1154 }
1155 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
1166pub 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 pub fn receive(&mut self) -> nb::Result<EspTwaiFrame, EspTwaiError> {
1183 let status = self.regs().status().read();
1184
1185 if status.bus_off_st().bit_is_set() {
1187 return nb::Result::Err(nb::Error::Other(EspTwaiError::BusOff));
1188 }
1189
1190 if !status.rx_buf_st().bit_is_set() {
1192 return nb::Result::Err(nb::Error::WouldBlock);
1193 }
1194
1195 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#[derive(Debug, Copy, Clone, Eq, PartialEq)]
1210#[cfg_attr(feature = "defmt", derive(defmt::Format))]
1211pub enum EspTwaiError {
1212 BusOff,
1214 NonCompliantDlc(u8),
1216 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#[inline(always)]
1240unsafe fn copy_from_data_register(dest: &mut [u8], src: *const u32) {
1241 for (i, dest) in dest.iter_mut().enumerate() {
1242 *dest = src.add(i).read_volatile() as u8;
1244 }
1245}
1246
1247#[inline(always)]
1256unsafe fn copy_to_data_register(dest: *mut u32, src: &[u8]) {
1257 for (i, src) in src.iter().enumerate() {
1258 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 fn transmit(&mut self, frame: &Self::Frame) -> nb::Result<Option<Self::Frame>, Self::Error> {
1273 self.tx.transmit(frame)?;
1274
1275 nb::Result::Ok(None)
1279 }
1280
1281 fn receive(&mut self) -> nb::Result<Self::Frame, Self::Error> {
1283 self.rx.receive()
1284 }
1285}
1286
1287#[doc(hidden)]
1289pub trait Instance: Peripheral<P = Self> + Into<AnyTwai> + 'static {
1290 fn number(&self) -> usize;
1292
1293 fn peripheral(&self) -> crate::system::Peripheral;
1295
1296 fn input_signal(&self) -> InputSignal;
1298 fn output_signal(&self) -> OutputSignal;
1300 fn interrupt(&self) -> crate::peripherals::Interrupt;
1302
1303 fn async_handler(&self) -> InterruptHandler;
1305
1306 fn register_block(&self) -> &RegisterBlock;
1308
1309 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 fn async_state(&self) -> &asynch::TwaiAsyncState;
1334}
1335
1336fn read_frame(register_block: &RegisterBlock) -> Result<EspTwaiFrame, EspTwaiError> {
1338 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_receive_fifo(register_block);
1350
1351 return Err(EspTwaiError::NonCompliantDlc(dlc));
1352 }
1353 let dlc = dlc as usize;
1354
1355 let (id, data_ptr) = if is_standard_format {
1357 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 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_receive_fifo(register_block);
1391
1392 Ok(frame)
1393}
1394
1395fn release_receive_fifo(register_block: &RegisterBlock) {
1399 register_block.cmd().write(|w| w.release_buf().set_bit());
1400}
1401
1402fn write_frame(register_block: &RegisterBlock, frame: &EspTwaiFrame) {
1404 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 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 unsafe {
1454 copy_to_data_register(
1455 data_ptr,
1456 match frame.is_remote {
1457 true => &[], false => &frame.data[0..frame.dlc],
1459 },
1460 )
1461 }
1462
1463 if frame.self_reception {
1465 register_block.cmd().write(|w| w.self_rx_req().set_bit());
1466 } else {
1467 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 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 pub async fn transmit_async(&mut self, frame: &EspTwaiFrame) -> Result<(), EspTwaiError> {
1634 self.tx.transmit_async(frame).await
1635 }
1636 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 if status.bus_off_st().bit_is_set() {
1674 return Poll::Ready(Err(EspTwaiError::BusOff));
1675 }
1676
1677 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 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 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 if status.bus_off_st().bit_is_set() {
1730 return Poll::Ready(Err(EspTwaiError::BusOff));
1731 }
1732
1733 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 let ecc_direction = err_capture.ecc_direction().bit_is_set();
1796
1797 if !ecc_direction && !status.tx_buf_st().bit_is_set() {
1799 register_block.cmd().write(|w| w.abort_tx().set_bit());
1801 }
1802
1803 async_state.err_waker.wake();
1804 }
1805
1806 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}