stm32_hal2/can/mod.rs
1//! Support for Controller Area Network (CAN) bus. Thinly wraps the [bxCAN](https://docs.rs/bxcan/0.5.0/bxcan/)
2//! or [can-fd](https://crates.io/keywords/can-fd) libraries.
3//!
4//! Requires the `can_bx` or `can_fd_g[h]` features. F3, F4, and L4 use BX CAN. G0, G4, L5, and H7 use FD CAN.
5
6use cfg_if::cfg_if;
7
8use crate::{
9 error::{Error, Result},
10 pac::RCC,
11 util::{bounded_loop, rcc_en_reset},
12};
13
14// todo: H5 support.
15cfg_if! {
16 if #[cfg(feature = "f3")] {
17 use bxcan;
18 use crate::pac::{can, CAN};
19
20 } else if #[cfg(any(feature = "f4", feature = "l4"))] {
21 use bxcan;
22 // todo: F4 has CAN2 as well.
23 use crate::pac::{CAN1 as CAN};
24 } else { // eg G0, H7
25 use fdcan;
26 // todo: CAN2 on H7.
27 use crate::pac::{FDCAN1 as CAN};
28 }
29}
30
31cfg_if! {
32 if #[cfg(feature = "g4")] {
33 pub mod g4;
34 pub use g4::*;
35 } else {
36 /// Interface to the CAN peripheral.
37 pub struct Can {
38 pub regs: CAN,
39 }
40
41 impl Can {
42 /// Initialize a CAN peripheral, including enabling and resetting
43 /// its RCC peripheral clock. This is not handled by the `bxcan` or `canfd` crates.
44 pub fn new(regs: CAN) -> Self {
45 let rcc = unsafe { &*RCC::ptr() };
46
47 cfg_if! {
48 if #[cfg(feature = "f3")] {
49 rcc_en_reset!(apb1, can, rcc);
50 } else if #[cfg(any(feature = "f4", feature = "l4"))] {
51 rcc_en_reset!(apb1, can1, rcc);
52 } else if #[cfg(feature = "h7")]{
53 // We don't yet have apb1h support in `rcc_en_reset`.
54 rcc.apb1henr().modify(|_, w| w.fdcanen().bit(true));
55 rcc.apb1hrstr().modify(|_, w| w.fdcanrst().bit(true));
56 rcc.apb1hrstr().modify(|_, w| w.fdcanrst().clear_bit());
57
58 // set_message_ram_layout();
59
60 } else {
61 rcc_en_reset!(apb1, fdcan, rcc);
62 }
63 }
64
65 Self { regs }
66 }
67
68 /// Print the (raw) contents of the status register.
69 pub fn read_status(&self) -> u32 {
70 cfg_if! {
71 if #[cfg(any(feature = "h7", feature = "l5"))] {
72 unsafe { self.regs.psr().read().bits() }
73 } else {
74 unsafe { self.regs.msr.read().bits() }
75 }
76 }
77 }
78 }
79
80 #[cfg(feature = "h7")]
81 // todo: Troubleshooting. COpied from H7xx-hal
82 /// Set the message RAM layout. This is flexible on H7. This function hard-sets it to the setting
83 /// that is hard-set by hardware on G4.
84 /// todo: Allow flexibility.
85 ///
86 /// Note: Perhaps due to a reset of message ram called by the FDCAN crate's `.into_config_mode()`,
87 /// we run this in application firmware once in config mode. Although a better API would be in the constructor
88 /// This must be done after initial setup (Enabling RCC clocks most-likely).
89 pub fn set_message_ram_layout() -> Result<()> {
90 let regs = unsafe { &(*CAN::ptr()) };
91
92 // RM, section 56.4.1: Operation modes: "Access to the FDCAN configuration registers is only
93 // enabled when both INIT bit in FDCAN_CCCR register and CCE bit in FDCAN_CCCR register are set.
94 // Note: we do this as 2 separate writes. RM: "CCE bit in FDCAN_CCCR register can only be set/cleared while INIT bit in FDCAN_CCCR
95 // is set. CCE bit in FDCAN_CCCR register is automatically cleared when INIT bit in
96 // FDCAN_CCCR is cleared."
97 regs.cccr().modify(|_, w| w.init().bit(true));
98 bounded_loop!(regs.cccr.read().init().bit_is_clear(), Error::RegisterUnchanged);
99 regs.cccr().modify(|_, w| w.cce().bit(true));
100 bounded_loop!(regs.cccr.read().cce().bit_is_clear(), Error::RegisterUnchanged);
101
102 let mut word_addr = 0x000; // todo: 0x400 for FDCAN2?
103
104 use fdcan::message_ram::*;
105
106 // 11-bit filter
107 regs.sidfc()
108 .modify(|_, w| unsafe { w.flssa().bits(word_addr) });
109 word_addr += STANDARD_FILTER_MAX as u16;
110
111 // 29-bit filter
112 regs.xidfc()
113 .modify(|_, w| unsafe { w.flesa().bits(word_addr) });
114 word_addr += 2 * EXTENDED_FILTER_MAX as u16;
115
116 // Rx FIFO 0
117 regs.rxf0c().modify(|_, w| unsafe {
118 w.f0sa()
119 .bits(word_addr)
120 .f0s()
121 .bits(RX_FIFO_MAX)
122 .f0wm()
123 .bits(RX_FIFO_MAX)
124 });
125 word_addr += 18 * RX_FIFO_MAX as u16;
126
127 // Rx FIFO 1
128 regs.rxf1c().modify(|_, w| unsafe {
129 w.f1sa()
130 .bits(word_addr)
131 .f1s()
132 .bits(RX_FIFO_MAX)
133 .f1wm()
134 .bits(RX_FIFO_MAX)
135 });
136 word_addr += 18 * RX_FIFO_MAX as u16;
137
138 // Rx buffer - see below
139 // Tx event FIFO
140 regs.txefc().modify(|_, w| unsafe {
141 w.efsa()
142 .bits(word_addr)
143 .efs()
144 .bits(TX_EVENT_MAX)
145 .efwm()
146 .bits(TX_EVENT_MAX)
147 });
148 word_addr += 2 * TX_EVENT_MAX as u16;
149
150 // Tx buffers
151 regs.txbc()
152 .modify(|_, w| unsafe { w.tbsa().bits(word_addr).tfqs().bits(TX_FIFO_MAX) });
153 word_addr += 18 * TX_FIFO_MAX as u16;
154
155 // Rx Buffer - not used
156 regs.rxbc().modify(|_, w| unsafe { w.rbsa().bits(word_addr) });
157
158 // TX event FIFO?
159 // Trigger memory?
160
161 // Set the element sizes to 16 bytes
162 regs.rxesc()
163 .modify(|_, w| unsafe { w.rbds().bits(0b111).f1ds().bits(0b111).f0ds().bits(0b111) });
164 regs.txesc().modify(|_, w| unsafe { w.tbds().bits(0b111) });
165 }
166
167 // Implement the traits required for the `bxcan` or `fdcan` library.
168 cfg_if! {
169 if #[cfg(feature = "can_bx")] {
170 unsafe impl bxcan::Instance for Can {
171 const REGISTERS: *mut bxcan::RegisterBlock = CAN::ptr() as *mut _;
172 }
173
174 unsafe impl bxcan::FilterOwner for Can {
175 #[cfg(any(feature = "f3", feature = "f4"))]
176 const NUM_FILTER_BANKS: u8 = 28;
177 #[cfg(any(feature = "l4"))]
178 const NUM_FILTER_BANKS: u8 = 14;
179 }
180
181 unsafe impl bxcan::MasterInstance for Can {}
182 } else {
183 unsafe impl fdcan::Instance for Can {
184 const REGISTERS: *mut fdcan::RegisterBlock = CAN::ptr() as *mut _;
185 }
186
187 unsafe impl fdcan::message_ram::Instance for Can {
188 #[cfg(feature = "h7")]
189 // H743 RM, table 8. "Register boundary addresses". 0x4000_AC00 - 0x4000_D3FF". CAN message RAM.
190 const MSG_RAM: *mut fdcan::message_ram::RegisterBlock = (0x4000_ac00 as *mut _);
191 // todo: (0x4000_ac00 + 0x1000) for H7, CAN2.
192 // todo: (0x4000_a750 as *mut _) for G4, CAN2
193 // todo: (0x4000_aaa0 as *mut _) fir G4 CAN3.
194 }
195 }
196 }
197 // todo: H5 support.
198
199 }
200}