mcan/
bus.rs

1//! Pad declarations for the CAN buses
2
3use crate::config::{BitTimingError, DATA_BIT_TIMING_RANGES, NOMINAL_BIT_TIMING_RANGES};
4use crate::filter::{FiltersExtended, FiltersStandard};
5use crate::interrupt::{state, InterruptConfiguration, OwnedInterruptSet};
6use crate::messageram::SharedMemoryInner;
7use crate::reg::{ecr::R as ECR, psr::R as PSR};
8use crate::rx_dedicated_buffers::RxDedicatedBuffer;
9use crate::rx_fifo::{Fifo0, Fifo1, RxFifo};
10use crate::tx_buffers::Tx;
11use crate::tx_event_fifo::TxEventFifo;
12use core::convert::From;
13use core::fmt::{self, Debug};
14use core::ops::Deref;
15
16use super::{
17    config::{CanConfig, Mode},
18    message::AnyMessage,
19    messageram::{Capacities, SharedMemory},
20};
21use fugit::HertzU32;
22use generic_array::typenum::Unsigned;
23
24/// Wrapper for the protocol status register
25pub struct ProtocolStatus(PSR);
26
27impl Deref for ProtocolStatus {
28    type Target = PSR;
29
30    fn deref(&self) -> &Self::Target {
31        &self.0
32    }
33}
34
35impl From<PSR> for ProtocolStatus {
36    fn from(value: PSR) -> Self {
37        Self(value)
38    }
39}
40
41impl Debug for ProtocolStatus {
42    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> fmt::Result {
43        f.debug_struct("ProtocolStatus")
44            .field("tdcv", &self.tdcv().bits())
45            .field("pxe", &self.pxe().bit())
46            .field("rfdf", &self.rfdf().bit())
47            .field("rbrs", &self.rbrs().bit())
48            .field("resi", &self.resi().bit())
49            .field("dlec", &self.dlec().bits())
50            .field("bo", &self.bo().bit())
51            .field("ew", &self.ew().bit())
52            .field("ep", &self.ep().bit())
53            .field("act", &self.act().bits())
54            .field("lec", &self.lec().bits())
55            .finish()
56    }
57}
58
59/// Wrapper for the error counters register
60pub struct ErrorCounters(ECR);
61
62impl Deref for ErrorCounters {
63    type Target = ECR;
64
65    fn deref(&self) -> &Self::Target {
66        &self.0
67    }
68}
69
70impl From<ECR> for ErrorCounters {
71    fn from(value: ECR) -> Self {
72        Self(value)
73    }
74}
75
76impl Debug for ErrorCounters {
77    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> fmt::Result {
78        f.debug_struct("ErrorCounters")
79            .field("cel", &self.cel().bits())
80            .field("rec", &self.rec().bits())
81            .field("rp", &self.rp().bit())
82            .field("tec", &self.tec().bits())
83            .finish()
84    }
85}
86
87/// Errors that may occur during configuration
88#[derive(Debug)]
89pub enum ConfigurationError {
90    /// Problems with the bit timing configuration
91    BitTiming(BitTimingError),
92    /// Time stamp prescaler value is not in the range [1, 16]
93    InvalidTimeStampPrescaler,
94}
95
96/// Error that may occur during construction
97#[derive(Debug)]
98pub struct MemoryNotAddressableError;
99
100impl From<BitTimingError> for ConfigurationError {
101    fn from(value: BitTimingError) -> Self {
102        Self::BitTiming(value)
103    }
104}
105
106/// A CAN bus that is not in configuration mode (CCE=0)
107///
108/// Some errors (including Bus_Off) can asynchronously stop bus operation
109/// (INIT=1), which will require user intervention to reactivate the bus to
110/// resume sending and receiving messages.
111pub struct Can<'a, Id, D, C: Capacities> {
112    /// Controls enabling and line selection of interrupts.
113    pub interrupt_configuration: InterruptConfiguration<Id>,
114    /// Initial set of interrupts in a disabled state.
115    pub interrupts: OwnedInterruptSet<Id, state::Disabled>,
116    /// Receive FIFO 0
117    pub rx_fifo_0: RxFifo<'a, Fifo0, Id, C::RxFifo0Message>,
118    /// Receive FIFO 1
119    pub rx_fifo_1: RxFifo<'a, Fifo1, Id, C::RxFifo1Message>,
120    /// Dedicated receive buffers
121    pub rx_dedicated_buffers: RxDedicatedBuffer<'a, Id, C::RxBufferMessage>,
122    /// Message transmission
123    pub tx: Tx<'a, Id, C>,
124    /// Events for successfully transmitted messages
125    pub tx_event_fifo: TxEventFifo<'a, Id>,
126    /// Auxiliary bits and bobs
127    pub aux: Aux<'a, Id, D>,
128}
129
130/// Auxiliary struct
131///
132/// Provides unsafe low-level register access as well as other common CAN APIs
133pub struct Aux<'a, Id, D> {
134    /// CAN bus peripheral
135    reg: crate::reg::Can<Id>,
136    /// [`Dependencies`] held for the target HAL
137    ///
138    /// [`Dependencies`]: mcan_core::Dependencies
139    dependencies: D,
140    /// Configuration
141    config: CanConfig,
142    /// Filters for messages with [`embedded_can::StandardId`]s
143    filters_standard: FiltersStandard<'a, Id>,
144    /// Filters for messages with [`embedded_can::ExtendedId`]s
145    filters_extended: FiltersExtended<'a, Id>,
146}
147
148/// Trait which erases generic parametrization for [`Aux`] type
149pub trait DynAux {
150    /// CAN identity type
151    type Id;
152
153    /// CAN dependencies type
154    type Deps;
155
156    /// Enters Initialization mode, without enabling configuration, to
157    /// disable CAN operation.
158    fn initialization_mode(&self);
159
160    /// Requests the peripheral to enter "power down" mode.
161    ///
162    /// See `Power Down (sleep mode)`, in the peripheral docs, for user
163    /// consideration regarding clocking and message handling.
164    ///
165    /// It is also worth noting that this mode should not be interpreted as the
166    /// peripheral being "powered off", since it is still possible to configure
167    /// the peripheral while in this mode.
168    fn power_down_mode(&self);
169
170    /// Check if the transition to `Power Down (sleep mode)` is complete and
171    /// that it is safe to completely disable the peripheral.
172    ///
173    /// Returns `false` if the peripheral is still handling outgoing or
174    /// incoming messages.
175    ///
176    /// If the bus is heavily congested, the peripheral might never enter
177    /// `Power Down (sleep mode)` on its own. In that case it can be forced by
178    /// calling `initialization_mode`.
179    fn is_ready_for_power_off(&self) -> bool;
180
181    /// Re-enters "Normal Operation" if in "Software Initialization" mode.
182    /// In Software Initialization, messages are not received or transmitted.
183    /// Configuration cannot be changed. In Normal Operation, messages can
184    /// be transmitted and received.
185    fn operational_mode(&self);
186
187    /// Returns `true` if the peripheral is in "Normal Operation" mode.
188    fn is_operational(&self) -> bool;
189
190    /// Access the error counters register value
191    fn error_counters(&self) -> ErrorCounters;
192
193    /// Access the protocol status register value
194    ///
195    /// Reading the register clears fields: PXE, RFDF, RBRS, RESI, DLEC, LEC.
196    fn protocol_status(&self) -> ProtocolStatus;
197
198    /// Current value of the timestamp counter
199    ///
200    /// If timestamping is disabled, its value is zero.
201    fn timestamp(&self) -> u16;
202
203    /// Returns `true` if the CAN bus is dominant.
204    fn is_dominant(&self) -> bool;
205
206    /// Returns `true` if the TX FIFO/Queue is full.
207    fn tx_buffer_full(&self) -> bool;
208}
209
210impl<Id: mcan_core::CanId, D: mcan_core::Dependencies<Id>> Aux<'_, Id, D> {
211    fn configuration_mode(&self) {
212        self.reg.configuration_mode()
213    }
214}
215
216impl<Id: mcan_core::CanId, D: mcan_core::Dependencies<Id>> DynAux for Aux<'_, Id, D> {
217    type Id = Id;
218    type Deps = D;
219
220    fn initialization_mode(&self) {
221        self.reg.initialization_mode();
222    }
223
224    fn operational_mode(&self) {
225        self.reg.operational_mode();
226    }
227
228    fn is_operational(&self) -> bool {
229        self.reg.is_operational()
230    }
231
232    fn error_counters(&self) -> ErrorCounters {
233        ErrorCounters(self.reg.ecr.read())
234    }
235
236    fn power_down_mode(&self) {
237        self.reg.cccr.write(|w| w.csr().set_bit());
238    }
239
240    fn is_ready_for_power_off(&self) -> bool {
241        self.reg.cccr.read().csa().bit_is_set()
242    }
243
244    fn protocol_status(&self) -> ProtocolStatus {
245        ProtocolStatus(self.reg.psr.read())
246    }
247
248    fn timestamp(&self) -> u16 {
249        self.reg.tscv.read().tsc().bits()
250    }
251
252    fn is_dominant(&self) -> bool {
253        self.reg.test.read().rx().bit_is_clear()
254    }
255
256    fn tx_buffer_full(&self) -> bool {
257        self.reg.txfqs.read().tfqf().bit_is_set()
258    }
259}
260
261/// A CAN bus in configuration mode. Before messages can be sent and received,
262/// it needs to be [`Self::finalize`]d.
263pub struct CanConfigurable<'a, Id, D, C: Capacities>(
264    /// The type invariant of CCE=0 is broken while this is wrapped.
265    Can<'a, Id, D, C>,
266);
267
268impl<'a, Id: mcan_core::CanId, D: mcan_core::Dependencies<Id>, C: Capacities>
269    CanConfigurable<'a, Id, D, C>
270{
271    /// Raw access to the registers.
272    ///
273    /// # Safety
274    /// The abstraction assumes that it has exclusive ownership of the
275    /// registers. Direct access can break such assumptions. Direct access
276    /// can break assumptions
277    pub unsafe fn registers(&self) -> &crate::reg::Can<Id> {
278        self.0.registers()
279    }
280
281    /// Allows reconfiguring the acceptance filters for standard IDs.
282    pub fn filters_standard(&mut self) -> &mut FiltersStandard<'a, Id> {
283        &mut self.0.aux.filters_standard
284    }
285
286    /// Allows reconfiguring the acceptance filters for extended IDs.
287    pub fn filters_extended(&mut self) -> &mut FiltersExtended<'a, Id> {
288        &mut self.0.aux.filters_extended
289    }
290
291    /// Allows reconfiguring interrupts.
292    pub fn interrupt_configuration(&mut self) -> &mut InterruptConfiguration<Id> {
293        &mut self.0.interrupt_configuration
294    }
295
296    /// Allows accessing the interrupt set necessary for the interrupt
297    /// reconfiguration.
298    pub fn interrupts(&mut self) -> &mut OwnedInterruptSet<Id, state::Disabled> {
299        &mut self.0.interrupts
300    }
301
302    /// Allows reconfiguring config
303    pub fn config(&mut self) -> &mut CanConfig {
304        &mut self.0.aux.config
305    }
306
307    /// Apply parameters from a bus config struct
308    fn apply_configuration(&mut self) -> Result<(), ConfigurationError> {
309        let reg = &self.0.aux.reg;
310        let config = &self.0.aux.config;
311        let dependencies = &self.0.aux.dependencies;
312        if !(1..=16).contains(&config.timestamp.prescaler) {
313            return Err(ConfigurationError::InvalidTimeStampPrescaler);
314        }
315
316        let nominal_prescaler = config
317            .nominal_timing
318            .prescaler(dependencies.can_clock(), &NOMINAL_BIT_TIMING_RANGES)?;
319
320        // Safety: The configuration is checked to be valid when computing the prescaler
321        reg.nbtp.write(|w| unsafe {
322            w.nsjw()
323                .bits(config.nominal_timing.sjw - 1)
324                .ntseg1()
325                .bits(config.nominal_timing.phase_seg_1 - 1)
326                .ntseg2()
327                .bits(config.nominal_timing.phase_seg_2 - 1)
328                .nbrp()
329                .bits(nominal_prescaler - 1)
330        });
331
332        // Safety: Every bit pattern of TCP is valid.
333        reg.tscc.write(|w| unsafe {
334            w.tss()
335                .variant(config.timestamp.select)
336                // Prescaler is 1 + tcp value.
337                .tcp()
338                .bits(config.timestamp.prescaler - 1)
339        });
340
341        match config.mode {
342            Mode::Classic => reg.cccr.modify(|_, w| w.fdoe().clear_bit()),
343            Mode::Fd {
344                allow_bit_rate_switching,
345                data_phase_timing,
346            } => {
347                reg.cccr
348                    .modify(|_, w| w.fdoe().set_bit().brse().bit(allow_bit_rate_switching));
349                let data_prescaler = data_phase_timing
350                    .prescaler(dependencies.can_clock(), &DATA_BIT_TIMING_RANGES)?;
351                // Safety: The configuration is checked to be valid when computing the prescaler
352                reg.dbtp.write(|w| unsafe {
353                    w.dsjw()
354                        .bits(data_phase_timing.sjw - 1)
355                        .dtseg1()
356                        .bits(data_phase_timing.phase_seg_1 - 1)
357                        .dtseg2()
358                        .bits(data_phase_timing.phase_seg_2 - 1)
359                        .dbrp()
360                        .bits((data_prescaler - 1) as u8)
361                });
362            }
363        };
364        // Repopulate mode configuration in `tx`
365        self.0.tx.mode = config.mode;
366
367        // Global filter configuration
368        // This setting is redundant and the same behaviour is achievable through main
369        // filter API
370        reg.gfc.write(|w| {
371            w.anfs()
372                .variant(crate::reg::gfc::ANFSSELECT_A::REJECT)
373                .anfe()
374                .variant(crate::reg::gfc::ANFESELECT_A::REJECT)
375        });
376
377        // Configure test/loopback mode
378        reg.cccr.modify(|_, w| w.test().bit(config.loopback));
379        reg.test.modify(|_, w| w.lbck().bit(config.loopback));
380
381        // Configure RX FIFO 0
382        reg.rxf0.c.modify(|_, w| {
383            let w = w.fom().bit(config.rx_fifo_0.mode.into());
384            let mut watermark = config.rx_fifo_0.watermark;
385            // According to the spec, any value > 64 is interpreted as watermark interrupt
386            // disabled, as is 0.
387            if watermark > 64 {
388                watermark = 0;
389            }
390            // Safety: The value is sanitized before the write
391            unsafe { w.fwm().bits(watermark) }
392        });
393
394        // Configure RX FIFO 1
395        reg.rxf1.c.modify(|_, w| {
396            let w = w.fom().bit(config.rx_fifo_1.mode.into());
397            let mut watermark = config.rx_fifo_1.watermark;
398            // According to the spec, any value > 64 is interpreted as watermark interrupt
399            // disabled, as is 0.
400            if watermark > 64 {
401                watermark = 0;
402            }
403            // Safety: The value is sanitized before the write
404            unsafe { w.fwm().bits(watermark) }
405        });
406
407        // Configure Tx Buffer
408        reg.txbc
409            .modify(|_, w| w.tfqm().bit(config.tx.tx_queue_submode.into()));
410
411        // Configure Tx Event Fifo
412        reg.txefc.modify(|_, w| {
413            let mut watermark = config.tx.tx_event_fifo_watermark;
414            // According to the spec, any value > 32 is interpreted as watermark interrupt
415            // disabled, as is 0.
416            if watermark > 32 {
417                watermark = 0;
418            }
419            // Safety: The value is sanitized before the write
420            unsafe { w.efwm().bits(watermark) }
421        });
422        Ok(())
423    }
424
425    /// Apply parameters from a ram config struct
426    ///
427    /// Ensuring that the RAM config struct is properly defined is basically our
428    /// only safeguard keeping the bus operational. Apart from that, the
429    /// memory RAM is largely unchecked and an improperly configured linker
430    /// script could interfere with bus operations.
431    fn apply_ram_config(reg: &crate::reg::Can<Id>, mem: &SharedMemoryInner<C>) {
432        // Standard id
433        //
434        // Safety:
435        // - Pointer is valid assuming SharedMemory location is within first 64K of RAM
436        // - Length is checked at compile-time on the `Capacities` constraints level
437        reg.sidfc.write(|w| unsafe {
438            w.flssa()
439                .bits(&mem.filters_standard as *const _ as u16)
440                .lss()
441                .bits(mem.filters_standard.len() as u8)
442        });
443
444        // Extended id
445        //
446        // Safety:
447        // - Pointer is valid assuming SharedMemory location is within first 64K of RAM
448        // - Length is checked at compile-time on the `Capacities` constraints level
449        reg.xidfc.write(|w| unsafe {
450            w.flesa()
451                .bits(&mem.filters_extended as *const _ as u16)
452                .lse()
453                .bits(mem.filters_extended.len() as u8)
454        });
455
456        // RX buffers
457        //
458        // Safety:
459        // - Pointer is valid assuming SharedMemory location is within first 64K of RAM
460        reg.rxbc
461            .write(|w| unsafe { w.rbsa().bits(&mem.rx_dedicated_buffers as *const _ as u16) });
462
463        // Data field size for buffers and FIFOs
464        reg.rxesc.write(|w| {
465            w.rbds()
466                .bits(C::RxBufferMessage::REG)
467                .f0ds()
468                .bits(C::RxFifo0Message::REG)
469                .f1ds()
470                .bits(C::RxFifo1Message::REG)
471        });
472
473        // RX FIFO 0
474        //
475        // Safety:
476        // - Pointer is valid assuming SharedMemory location is within first 64K of RAM
477        // - Length is checked at compile-time on the `Capacities` constraints level
478        reg.rxf0.c.write(|w| unsafe {
479            w.fsa()
480                .bits(&mem.rx_fifo_0 as *const _ as u16)
481                .fs()
482                .bits(mem.rx_fifo_0.len() as u8)
483        });
484
485        // RX FIFO 1
486        //
487        // Safety:
488        // - Pointer is valid assuming SharedMemory location is within first 64K of RAM
489        // - Length is checked at compile-time on the `Capacities` constraints level
490        reg.rxf1.c.write(|w| unsafe {
491            w.fsa()
492                .bits(&mem.rx_fifo_1 as *const _ as u16)
493                .fs()
494                .bits(mem.rx_fifo_1.len() as u8)
495        });
496
497        // TX buffers
498        //
499        // Safety:
500        // - Pointer is valid assuming SharedMemory location is within first 64K of RAM
501        // - Lengths are checked at compile-time on the `Capacities` constraints level
502        reg.txbc.write(|w| unsafe {
503            w.tfqs()
504                .bits(<C::TxBuffers as Unsigned>::U8 - <C::DedicatedTxBuffers as Unsigned>::U8)
505                .ndtb()
506                .bits(<C::DedicatedTxBuffers as Unsigned>::U8)
507                .tbsa()
508                .bits(&mem.tx_buffers as *const _ as u16)
509        });
510
511        // TX element size config
512        reg.txesc.write(|w| w.tbds().bits(C::TxMessage::REG));
513
514        // TX events
515        //
516        // Safety:
517        // - Pointer is valid assuming SharedMemory location is within first 64K of RAM
518        // - Lengths are checked at compile-time on the `Capacities` constraints level
519        reg.txefc.write(|w| unsafe {
520            w.efsa()
521                .bits(&mem.tx_event_fifo as *const _ as u16)
522                .efs()
523                .bits(mem.tx_event_fifo.len() as u8)
524        });
525    }
526
527    /// Create new can peripheral.
528    ///
529    /// The hardware requires that SharedMemory is contained within the first
530    /// 64K of system RAM. If this condition is not fulfilled, an error is
531    /// returned.
532    ///
533    /// The returned peripheral is not operational; use [`Self::finalize`] to
534    /// finish configuration and start transmitting and receiving.
535    pub fn new(
536        bitrate: HertzU32,
537        dependencies: D,
538        memory: &'a mut SharedMemory<C>,
539    ) -> Result<Self, MemoryNotAddressableError> {
540        // Safety:
541        // Since `dependencies` field implies ownership of the HW register pointed to by
542        // `Id: CanId`, `can` has a unique access to it
543        let reg = unsafe { crate::reg::Can::<Id>::new() };
544
545        reg.configuration_mode();
546
547        // Contract:
548        // `mcan_core::Dependencies::eligible_message_ram_start` contract guarantees
549        // `u16::MAX + 1` alignment and points to the beginning of the allocatable CAN
550        // memory region.
551        if !memory.is_addressable(dependencies.eligible_message_ram_start()) {
552            return Err(MemoryNotAddressableError);
553        }
554
555        let memory = memory.init();
556        Self::apply_ram_config(&reg, memory);
557
558        let config = CanConfig::new(bitrate);
559
560        // Safety: Since `Can::new` takes a PAC singleton, it can only be called once.
561        // Then no duplicates will be constructed. The registers that are
562        // delegated to these components should not be touched by any other
563        // code. This has to be upheld by all code that has access to the
564        // register block.
565
566        let (interrupt_configuration, interrupts) = unsafe { InterruptConfiguration::new() };
567
568        let can = CanConfigurable(Can {
569            interrupt_configuration,
570            interrupts,
571            rx_fifo_0: unsafe { RxFifo::new(&mut memory.rx_fifo_0) },
572            rx_fifo_1: unsafe { RxFifo::new(&mut memory.rx_fifo_1) },
573            rx_dedicated_buffers: unsafe {
574                RxDedicatedBuffer::new(&mut memory.rx_dedicated_buffers)
575            },
576            tx: unsafe { Tx::new(&mut memory.tx_buffers, config.mode) },
577            tx_event_fifo: unsafe { TxEventFifo::new(&mut memory.tx_event_fifo) },
578            aux: Aux {
579                reg,
580                dependencies,
581                config,
582                // Safety: The memory is zeroed by `memory.init`, so all filters are initially
583                // disabled.
584                filters_standard: unsafe { FiltersStandard::new(&mut memory.filters_standard) },
585                filters_extended: unsafe { FiltersExtended::new(&mut memory.filters_extended) },
586            },
587        });
588
589        Ok(can)
590    }
591
592    /// Locks the configuration and enters initialization mode.
593    pub fn finalize_initialized(mut self) -> Result<Can<'a, Id, D, C>, ConfigurationError> {
594        self.apply_configuration()?;
595
596        let can = self.0;
597        can.aux.initialization_mode();
598
599        Ok(can)
600    }
601
602    /// Locks the configuration and enters normal operation.
603    pub fn finalize(mut self) -> Result<Can<'a, Id, D, C>, ConfigurationError> {
604        self.apply_configuration()?;
605
606        let can = self.0;
607
608        // Enter normal operation (CCE is set to 0 automatically)
609        can.aux.operational_mode();
610
611        Ok(can)
612    }
613
614    /// Leaves the peripheral non-operational and makes the `Dependencies`
615    /// available again.
616    pub fn release(self) -> D {
617        self.0.aux.dependencies
618    }
619}
620
621impl<'a, Id: mcan_core::CanId, D: mcan_core::Dependencies<Id>, C: Capacities> Can<'a, Id, D, C> {
622    /// Raw access to the registers.
623    ///
624    /// # Safety
625    /// The abstraction assumes that it has exclusive ownership of the
626    /// registers. Direct access can break such assumptions.
627    pub unsafe fn registers(&self) -> &crate::reg::Can<Id> {
628        &self.aux.reg
629    }
630
631    /// Return to configuration mode. This resets some status registers, which
632    /// effectively clears received messages, messages pending transmission and
633    /// tranmit events.
634    pub fn configure(self) -> CanConfigurable<'a, Id, D, C> {
635        self.aux.configuration_mode();
636        CanConfigurable(self)
637    }
638
639    /// Disables the peripheral and makes the `Dependencies` available again.
640    pub fn release(self) -> D {
641        self.configure().release()
642    }
643}