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(®, 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}