aboutsummaryrefslogtreecommitdiff
path: root/embassy-stm32/src
diff options
context:
space:
mode:
Diffstat (limited to 'embassy-stm32/src')
-rw-r--r--embassy-stm32/src/can/fd/config.rs438
-rw-r--r--embassy-stm32/src/can/fd/filter.rs379
-rw-r--r--embassy-stm32/src/can/fd/message_ram/common.rs134
-rw-r--r--embassy-stm32/src/can/fd/message_ram/enums.rs233
-rw-r--r--embassy-stm32/src/can/fd/message_ram/extended_filter.rs136
-rw-r--r--embassy-stm32/src/can/fd/message_ram/generic.rs168
-rw-r--r--embassy-stm32/src/can/fd/message_ram/mod.rs170
-rw-r--r--embassy-stm32/src/can/fd/message_ram/rxfifo_element.rs122
-rw-r--r--embassy-stm32/src/can/fd/message_ram/standard_filter.rs136
-rw-r--r--embassy-stm32/src/can/fd/message_ram/txbuffer_element.rs433
-rw-r--r--embassy-stm32/src/can/fd/message_ram/txevent_element.rs138
-rw-r--r--embassy-stm32/src/can/fd/mod.rs6
-rw-r--r--embassy-stm32/src/can/fd/peripheral.rs828
-rw-r--r--embassy-stm32/src/can/fdcan.rs1042
-rw-r--r--embassy-stm32/src/can/frame.rs370
-rw-r--r--embassy-stm32/src/dma/bdma.rs6
-rw-r--r--embassy-stm32/src/dma/dma.rs8
-rw-r--r--embassy-stm32/src/dma/dmamux.rs2
-rw-r--r--embassy-stm32/src/dma/gpdma.rs2
-rw-r--r--embassy-stm32/src/flash/h50.rs124
-rw-r--r--embassy-stm32/src/flash/mod.rs3
-rw-r--r--embassy-stm32/src/rcc/bd.rs17
-rw-r--r--embassy-stm32/src/rcc/u5.rs627
-rw-r--r--embassy-stm32/src/timer/mod.rs64
-rw-r--r--embassy-stm32/src/usb/usb.rs2
25 files changed, 4781 insertions, 807 deletions
diff --git a/embassy-stm32/src/can/fd/config.rs b/embassy-stm32/src/can/fd/config.rs
new file mode 100644
index 000000000..38b409121
--- /dev/null
+++ b/embassy-stm32/src/can/fd/config.rs
@@ -0,0 +1,438 @@
1//! Configuration for FDCAN Module
2//! Note: This file is copied and modified from fdcan crate by Richard Meadows
3
4use core::num::{NonZeroU16, NonZeroU8};
5
6/// Configures the bit timings.
7///
8/// You can use <http://www.bittiming.can-wiki.info/> to calculate the `btr` parameter. Enter
9/// parameters as follows:
10///
11/// - *Clock Rate*: The input clock speed to the CAN peripheral (*not* the CPU clock speed).
12/// This is the clock rate of the peripheral bus the CAN peripheral is attached to (eg. APB1).
13/// - *Sample Point*: Should normally be left at the default value of 87.5%.
14/// - *SJW*: Should normally be left at the default value of 1.
15///
16/// Then copy the `CAN_BUS_TIME` register value from the table and pass it as the `btr`
17/// parameter to this method.
18#[derive(Clone, Copy, Debug)]
19pub struct NominalBitTiming {
20 /// Value by which the oscillator frequency is divided for generating the bit time quanta. The bit
21 /// time is built up from a multiple of this quanta. Valid values are 1 to 512.
22 pub prescaler: NonZeroU16,
23 /// Valid values are 1 to 128.
24 pub seg1: NonZeroU8,
25 /// Valid values are 1 to 255.
26 pub seg2: NonZeroU8,
27 /// Valid values are 1 to 128.
28 pub sync_jump_width: NonZeroU8,
29}
30impl NominalBitTiming {
31 #[inline]
32 pub(crate) fn nbrp(&self) -> u16 {
33 u16::from(self.prescaler) & 0x1FF
34 }
35 #[inline]
36 pub(crate) fn ntseg1(&self) -> u8 {
37 u8::from(self.seg1)
38 }
39 #[inline]
40 pub(crate) fn ntseg2(&self) -> u8 {
41 u8::from(self.seg2) & 0x7F
42 }
43 #[inline]
44 pub(crate) fn nsjw(&self) -> u8 {
45 u8::from(self.sync_jump_width) & 0x7F
46 }
47}
48
49impl Default for NominalBitTiming {
50 #[inline]
51 fn default() -> Self {
52 // Kernel Clock 8MHz, Bit rate: 500kbit/s. Corresponds to a NBTP
53 // register value of 0x0600_0A03
54 Self {
55 prescaler: NonZeroU16::new(1).unwrap(),
56 seg1: NonZeroU8::new(11).unwrap(),
57 seg2: NonZeroU8::new(4).unwrap(),
58 sync_jump_width: NonZeroU8::new(4).unwrap(),
59 }
60 }
61}
62
63/// Configures the data bit timings for the FdCan Variable Bitrates.
64/// This is not used when frame_transmit is set to anything other than AllowFdCanAndBRS.
65#[derive(Clone, Copy, Debug)]
66pub struct DataBitTiming {
67 /// Tranceiver Delay Compensation
68 pub transceiver_delay_compensation: bool,
69 /// The value by which the oscillator frequency is divided to generate the bit time quanta. The bit
70 /// time is built up from a multiple of this quanta. Valid values for the Baud Rate Prescaler are 1
71 /// to 31.
72 pub prescaler: NonZeroU16,
73 /// Valid values are 1 to 31.
74 pub seg1: NonZeroU8,
75 /// Valid values are 1 to 15.
76 pub seg2: NonZeroU8,
77 /// Must always be smaller than DTSEG2, valid values are 1 to 15.
78 pub sync_jump_width: NonZeroU8,
79}
80impl DataBitTiming {
81 // #[inline]
82 // fn tdc(&self) -> u8 {
83 // let tsd = self.transceiver_delay_compensation as u8;
84 // //TODO: stm32g4 does not export the TDC field
85 // todo!()
86 // }
87 #[inline]
88 pub(crate) fn dbrp(&self) -> u8 {
89 (u16::from(self.prescaler) & 0x001F) as u8
90 }
91 #[inline]
92 pub(crate) fn dtseg1(&self) -> u8 {
93 u8::from(self.seg1) & 0x1F
94 }
95 #[inline]
96 pub(crate) fn dtseg2(&self) -> u8 {
97 u8::from(self.seg2) & 0x0F
98 }
99 #[inline]
100 pub(crate) fn dsjw(&self) -> u8 {
101 u8::from(self.sync_jump_width) & 0x0F
102 }
103}
104
105impl Default for DataBitTiming {
106 #[inline]
107 fn default() -> Self {
108 // Kernel Clock 8MHz, Bit rate: 500kbit/s. Corresponds to a DBTP
109 // register value of 0x0000_0A33
110 Self {
111 transceiver_delay_compensation: false,
112 prescaler: NonZeroU16::new(1).unwrap(),
113 seg1: NonZeroU8::new(11).unwrap(),
114 seg2: NonZeroU8::new(4).unwrap(),
115 sync_jump_width: NonZeroU8::new(4).unwrap(),
116 }
117 }
118}
119
120/// Configures which modes to use
121/// Individual headers can contain a desire to be send via FdCan
122/// or use Bit rate switching. But if this general setting does not allow
123/// that, only classic CAN is used instead.
124#[derive(Clone, Copy, Debug)]
125pub enum FrameTransmissionConfig {
126 /// Only allow Classic CAN message Frames
127 ClassicCanOnly,
128 /// Allow (non-brs) FdCAN Message Frames
129 AllowFdCan,
130 /// Allow FdCAN Message Frames and allow Bit Rate Switching
131 AllowFdCanAndBRS,
132}
133
134///
135#[derive(Clone, Copy, Debug)]
136pub enum ClockDivider {
137 /// Divide by 1
138 _1 = 0b0000,
139 /// Divide by 2
140 _2 = 0b0001,
141 /// Divide by 4
142 _4 = 0b0010,
143 /// Divide by 6
144 _6 = 0b0011,
145 /// Divide by 8
146 _8 = 0b0100,
147 /// Divide by 10
148 _10 = 0b0101,
149 /// Divide by 12
150 _12 = 0b0110,
151 /// Divide by 14
152 _14 = 0b0111,
153 /// Divide by 16
154 _16 = 0b1000,
155 /// Divide by 18
156 _18 = 0b1001,
157 /// Divide by 20
158 _20 = 0b1010,
159 /// Divide by 22
160 _22 = 0b1011,
161 /// Divide by 24
162 _24 = 0b1100,
163 /// Divide by 26
164 _26 = 0b1101,
165 /// Divide by 28
166 _28 = 0b1110,
167 /// Divide by 30
168 _30 = 0b1111,
169}
170
171/// Prescaler of the Timestamp counter
172#[derive(Clone, Copy, Debug)]
173pub enum TimestampPrescaler {
174 /// 1
175 _1 = 1,
176 /// 2
177 _2 = 2,
178 /// 3
179 _3 = 3,
180 /// 4
181 _4 = 4,
182 /// 5
183 _5 = 5,
184 /// 6
185 _6 = 6,
186 /// 7
187 _7 = 7,
188 /// 8
189 _8 = 8,
190 /// 9
191 _9 = 9,
192 /// 10
193 _10 = 10,
194 /// 11
195 _11 = 11,
196 /// 12
197 _12 = 12,
198 /// 13
199 _13 = 13,
200 /// 14
201 _14 = 14,
202 /// 15
203 _15 = 15,
204 /// 16
205 _16 = 16,
206}
207
208/// Selects the source of the Timestamp counter
209#[derive(Clone, Copy, Debug)]
210pub enum TimestampSource {
211 /// The Timestamp counter is disabled
212 None,
213 /// Using the FdCan input clock as the Timstamp counter's source,
214 /// and using a specific prescaler
215 Prescaler(TimestampPrescaler),
216 /// Using TIM3 as a source
217 FromTIM3,
218}
219
220/// How to handle frames in the global filter
221#[derive(Clone, Copy, Debug)]
222pub enum NonMatchingFilter {
223 /// Frames will go to Fifo0 when they do no match any specific filter
224 IntoRxFifo0 = 0b00,
225 /// Frames will go to Fifo1 when they do no match any specific filter
226 IntoRxFifo1 = 0b01,
227 /// Frames will be rejected when they do not match any specific filter
228 Reject = 0b11,
229}
230
231/// How to handle frames which do not match a specific filter
232#[derive(Clone, Copy, Debug)]
233pub struct GlobalFilter {
234 /// How to handle non-matching standard frames
235 pub handle_standard_frames: NonMatchingFilter,
236
237 /// How to handle non-matching extended frames
238 pub handle_extended_frames: NonMatchingFilter,
239
240 /// How to handle remote standard frames
241 pub reject_remote_standard_frames: bool,
242
243 /// How to handle remote extended frames
244 pub reject_remote_extended_frames: bool,
245}
246impl GlobalFilter {
247 /// Reject all non-matching and remote frames
248 pub const fn reject_all() -> Self {
249 Self {
250 handle_standard_frames: NonMatchingFilter::Reject,
251 handle_extended_frames: NonMatchingFilter::Reject,
252 reject_remote_standard_frames: true,
253 reject_remote_extended_frames: true,
254 }
255 }
256
257 /// How to handle non-matching standard frames
258 pub const fn set_handle_standard_frames(mut self, filter: NonMatchingFilter) -> Self {
259 self.handle_standard_frames = filter;
260 self
261 }
262 /// How to handle non-matching exteded frames
263 pub const fn set_handle_extended_frames(mut self, filter: NonMatchingFilter) -> Self {
264 self.handle_extended_frames = filter;
265 self
266 }
267 /// How to handle remote standard frames
268 pub const fn set_reject_remote_standard_frames(mut self, filter: bool) -> Self {
269 self.reject_remote_standard_frames = filter;
270 self
271 }
272 /// How to handle remote extended frames
273 pub const fn set_reject_remote_extended_frames(mut self, filter: bool) -> Self {
274 self.reject_remote_extended_frames = filter;
275 self
276 }
277}
278impl Default for GlobalFilter {
279 #[inline]
280 fn default() -> Self {
281 Self {
282 handle_standard_frames: NonMatchingFilter::IntoRxFifo0,
283 handle_extended_frames: NonMatchingFilter::IntoRxFifo0,
284 reject_remote_standard_frames: false,
285 reject_remote_extended_frames: false,
286 }
287 }
288}
289
290/// FdCan Config Struct
291#[derive(Clone, Copy, Debug)]
292pub struct FdCanConfig {
293 /// Nominal Bit Timings
294 pub nbtr: NominalBitTiming,
295 /// (Variable) Data Bit Timings
296 pub dbtr: DataBitTiming,
297 /// Enables or disables automatic retransmission of messages
298 ///
299 /// If this is enabled, the CAN peripheral will automatically try to retransmit each frame
300 /// util it can be sent. Otherwise, it will try only once to send each frame.
301 ///
302 /// Automatic retransmission is enabled by default.
303 pub automatic_retransmit: bool,
304 /// Enabled or disables the pausing between transmissions
305 ///
306 /// This feature looses up burst transmissions coming from a single node and it protects against
307 /// "babbling idiot" scenarios where the application program erroneously requests too many
308 /// transmissions.
309 pub transmit_pause: bool,
310 /// Enabled or disables the pausing between transmissions
311 ///
312 /// This feature looses up burst transmissions coming from a single node and it protects against
313 /// "babbling idiot" scenarios where the application program erroneously requests too many
314 /// transmissions.
315 pub frame_transmit: FrameTransmissionConfig,
316 /// Non Isoe Mode
317 /// If this is set, the FDCAN uses the CAN FD frame format as specified by the Bosch CAN
318 /// FD Specification V1.0.
319 pub non_iso_mode: bool,
320 /// Edge Filtering: Two consecutive dominant tq required to detect an edge for hard synchronization
321 pub edge_filtering: bool,
322 /// Enables protocol exception handling
323 pub protocol_exception_handling: bool,
324 /// Sets the general clock divider for this FdCAN instance
325 pub clock_divider: ClockDivider,
326 /// Sets the timestamp source
327 pub timestamp_source: TimestampSource,
328 /// Configures the Global Filter
329 pub global_filter: GlobalFilter,
330}
331
332impl FdCanConfig {
333 /// Configures the bit timings.
334 #[inline]
335 pub const fn set_nominal_bit_timing(mut self, btr: NominalBitTiming) -> Self {
336 self.nbtr = btr;
337 self
338 }
339
340 /// Configures the bit timings.
341 #[inline]
342 pub const fn set_data_bit_timing(mut self, btr: DataBitTiming) -> Self {
343 self.dbtr = btr;
344 self
345 }
346
347 /// Enables or disables automatic retransmission of messages
348 ///
349 /// If this is enabled, the CAN peripheral will automatically try to retransmit each frame
350 /// util it can be sent. Otherwise, it will try only once to send each frame.
351 ///
352 /// Automatic retransmission is enabled by default.
353 #[inline]
354 pub const fn set_automatic_retransmit(mut self, enabled: bool) -> Self {
355 self.automatic_retransmit = enabled;
356 self
357 }
358
359 /// Enabled or disables the pausing between transmissions
360 ///
361 /// This feature looses up burst transmissions coming from a single node and it protects against
362 /// "babbling idiot" scenarios where the application program erroneously requests too many
363 /// transmissions.
364 #[inline]
365 pub const fn set_transmit_pause(mut self, enabled: bool) -> Self {
366 self.transmit_pause = enabled;
367 self
368 }
369
370 /// If this is set, the FDCAN uses the CAN FD frame format as specified by the Bosch CAN
371 /// FD Specification V1.0.
372 #[inline]
373 pub const fn set_non_iso_mode(mut self, enabled: bool) -> Self {
374 self.non_iso_mode = enabled;
375 self
376 }
377
378 /// Two consecutive dominant tq required to detect an edge for hard synchronization
379 #[inline]
380 pub const fn set_edge_filtering(mut self, enabled: bool) -> Self {
381 self.edge_filtering = enabled;
382 self
383 }
384
385 /// Sets the allowed transmission types for messages.
386 #[inline]
387 pub const fn set_frame_transmit(mut self, fts: FrameTransmissionConfig) -> Self {
388 self.frame_transmit = fts;
389 self
390 }
391
392 /// Enables protocol exception handling
393 #[inline]
394 pub const fn set_protocol_exception_handling(mut self, peh: bool) -> Self {
395 self.protocol_exception_handling = peh;
396 self
397 }
398
399 /// Sets the general clock divider for this FdCAN instance
400 #[inline]
401 pub const fn set_clock_divider(mut self, div: ClockDivider) -> Self {
402 self.clock_divider = div;
403 self
404 }
405
406 /// Sets the timestamp source
407 #[inline]
408 pub const fn set_timestamp_source(mut self, tss: TimestampSource) -> Self {
409 self.timestamp_source = tss;
410 self
411 }
412
413 /// Sets the global filter settings
414 #[inline]
415 pub const fn set_global_filter(mut self, filter: GlobalFilter) -> Self {
416 self.global_filter = filter;
417 self
418 }
419}
420
421impl Default for FdCanConfig {
422 #[inline]
423 fn default() -> Self {
424 Self {
425 nbtr: NominalBitTiming::default(),
426 dbtr: DataBitTiming::default(),
427 automatic_retransmit: true,
428 transmit_pause: false,
429 frame_transmit: FrameTransmissionConfig::ClassicCanOnly,
430 non_iso_mode: false,
431 edge_filtering: false,
432 protocol_exception_handling: true,
433 clock_divider: ClockDivider::_1,
434 timestamp_source: TimestampSource::None,
435 global_filter: GlobalFilter::default(),
436 }
437 }
438}
diff --git a/embassy-stm32/src/can/fd/filter.rs b/embassy-stm32/src/can/fd/filter.rs
new file mode 100644
index 000000000..3e2129e6e
--- /dev/null
+++ b/embassy-stm32/src/can/fd/filter.rs
@@ -0,0 +1,379 @@
1//! Definition of Filter structs for FDCAN Module
2//! Note: This file is copied and modified from fdcan crate by Richard Meadows
3
4use embedded_can::{ExtendedId, StandardId};
5
6use crate::can::fd::message_ram;
7pub use crate::can::fd::message_ram::{EXTENDED_FILTER_MAX, STANDARD_FILTER_MAX};
8
9/// A Standard Filter
10pub type StandardFilter = Filter<StandardId, u16>;
11/// An Extended Filter
12pub type ExtendedFilter = Filter<ExtendedId, u32>;
13
14impl Default for StandardFilter {
15 fn default() -> Self {
16 StandardFilter::disable()
17 }
18}
19impl Default for ExtendedFilter {
20 fn default() -> Self {
21 ExtendedFilter::disable()
22 }
23}
24
25impl StandardFilter {
26 /// Accept all messages in FIFO 0
27 pub fn accept_all_into_fifo0() -> StandardFilter {
28 StandardFilter {
29 filter: FilterType::BitMask { filter: 0x0, mask: 0x0 },
30 action: Action::StoreInFifo0,
31 }
32 }
33
34 /// Accept all messages in FIFO 1
35 pub fn accept_all_into_fifo1() -> StandardFilter {
36 StandardFilter {
37 filter: FilterType::BitMask { filter: 0x0, mask: 0x0 },
38 action: Action::StoreInFifo1,
39 }
40 }
41
42 /// Reject all messages
43 pub fn reject_all() -> StandardFilter {
44 StandardFilter {
45 filter: FilterType::BitMask { filter: 0x0, mask: 0x0 },
46 action: Action::Reject,
47 }
48 }
49
50 /// Disable the filter
51 pub fn disable() -> StandardFilter {
52 StandardFilter {
53 filter: FilterType::Disabled,
54 action: Action::Disable,
55 }
56 }
57}
58
59impl ExtendedFilter {
60 /// Accept all messages in FIFO 0
61 pub fn accept_all_into_fifo0() -> ExtendedFilter {
62 ExtendedFilter {
63 filter: FilterType::BitMask { filter: 0x0, mask: 0x0 },
64 action: Action::StoreInFifo0,
65 }
66 }
67
68 /// Accept all messages in FIFO 1
69 pub fn accept_all_into_fifo1() -> ExtendedFilter {
70 ExtendedFilter {
71 filter: FilterType::BitMask { filter: 0x0, mask: 0x0 },
72 action: Action::StoreInFifo1,
73 }
74 }
75
76 /// Reject all messages
77 pub fn reject_all() -> ExtendedFilter {
78 ExtendedFilter {
79 filter: FilterType::BitMask { filter: 0x0, mask: 0x0 },
80 action: Action::Reject,
81 }
82 }
83
84 /// Disable the filter
85 pub fn disable() -> ExtendedFilter {
86 ExtendedFilter {
87 filter: FilterType::Disabled,
88 action: Action::Disable,
89 }
90 }
91}
92
93/// Filter Type
94#[derive(Clone, Copy, Debug)]
95pub enum FilterType<ID, UNIT>
96where
97 ID: Copy + Clone + core::fmt::Debug,
98 UNIT: Copy + Clone + core::fmt::Debug,
99{
100 /// Match with a range between two messages
101 Range {
102 /// First Id of the range
103 from: ID,
104 /// Last Id of the range
105 to: ID,
106 },
107 /// Match with a bitmask
108 BitMask {
109 /// Filter of the bitmask
110 filter: UNIT,
111 /// Mask of the bitmask
112 mask: UNIT,
113 },
114 /// Match with a single ID
115 DedicatedSingle(ID),
116 /// Match with one of two ID's
117 DedicatedDual(ID, ID),
118 /// Filter is disabled
119 Disabled,
120}
121impl<ID, UNIT> From<FilterType<ID, UNIT>> for message_ram::enums::FilterType
122where
123 ID: Copy + Clone + core::fmt::Debug,
124 UNIT: Copy + Clone + core::fmt::Debug,
125{
126 fn from(f: FilterType<ID, UNIT>) -> Self {
127 match f {
128 FilterType::Range { to: _, from: _ } => Self::RangeFilter,
129 FilterType::BitMask { filter: _, mask: _ } => Self::ClassicFilter,
130 FilterType::DedicatedSingle(_) => Self::DualIdFilter,
131 FilterType::DedicatedDual(_, _) => Self::DualIdFilter,
132 FilterType::Disabled => Self::FilterDisabled,
133 }
134 }
135}
136
137/// Filter Action
138#[derive(Clone, Copy, Debug)]
139pub enum Action {
140 /// No Action
141 Disable = 0b000,
142 /// Store an matching message in FIFO 0
143 StoreInFifo0 = 0b001,
144 /// Store an matching message in FIFO 1
145 StoreInFifo1 = 0b010,
146 /// Reject an matching message
147 Reject = 0b011,
148 /// Flag a matching message (But not store?!?)
149 FlagHighPrio = 0b100,
150 /// Flag a matching message as a High Priority message and store it in FIFO 0
151 FlagHighPrioAndStoreInFifo0 = 0b101,
152 /// Flag a matching message as a High Priority message and store it in FIFO 1
153 FlagHighPrioAndStoreInFifo1 = 0b110,
154}
155impl From<Action> for message_ram::enums::FilterElementConfig {
156 fn from(a: Action) -> Self {
157 match a {
158 Action::Disable => Self::DisableFilterElement,
159 Action::StoreInFifo0 => Self::StoreInFifo0,
160 Action::StoreInFifo1 => Self::StoreInFifo1,
161 Action::Reject => Self::Reject,
162 Action::FlagHighPrio => Self::SetPriority,
163 Action::FlagHighPrioAndStoreInFifo0 => Self::SetPriorityAndStoreInFifo0,
164 Action::FlagHighPrioAndStoreInFifo1 => Self::SetPriorityAndStoreInFifo1,
165 }
166 }
167}
168
169/// Filter
170#[derive(Clone, Copy, Debug)]
171pub struct Filter<ID, UNIT>
172where
173 ID: Copy + Clone + core::fmt::Debug,
174 UNIT: Copy + Clone + core::fmt::Debug,
175{
176 /// How to match an incoming message
177 pub filter: FilterType<ID, UNIT>,
178 /// What to do with a matching message
179 pub action: Action,
180}
181
182/// Standard Filter Slot
183#[derive(Debug, Copy, Clone, Eq, PartialEq)]
184pub enum StandardFilterSlot {
185 /// 0
186 _0 = 0,
187 /// 1
188 _1 = 1,
189 /// 2
190 _2 = 2,
191 /// 3
192 _3 = 3,
193 /// 4
194 _4 = 4,
195 /// 5
196 _5 = 5,
197 /// 6
198 _6 = 6,
199 /// 7
200 _7 = 7,
201 /// 8
202 _8 = 8,
203 /// 9
204 _9 = 9,
205 /// 10
206 _10 = 10,
207 /// 11
208 _11 = 11,
209 /// 12
210 _12 = 12,
211 /// 13
212 _13 = 13,
213 /// 14
214 _14 = 14,
215 /// 15
216 _15 = 15,
217 /// 16
218 _16 = 16,
219 /// 17
220 _17 = 17,
221 /// 18
222 _18 = 18,
223 /// 19
224 _19 = 19,
225 /// 20
226 _20 = 20,
227 /// 21
228 _21 = 21,
229 /// 22
230 _22 = 22,
231 /// 23
232 _23 = 23,
233 /// 24
234 _24 = 24,
235 /// 25
236 _25 = 25,
237 /// 26
238 _26 = 26,
239 /// 27
240 _27 = 27,
241}
242impl From<u8> for StandardFilterSlot {
243 fn from(u: u8) -> Self {
244 match u {
245 0 => StandardFilterSlot::_0,
246 1 => StandardFilterSlot::_1,
247 2 => StandardFilterSlot::_2,
248 3 => StandardFilterSlot::_3,
249 4 => StandardFilterSlot::_4,
250 5 => StandardFilterSlot::_5,
251 6 => StandardFilterSlot::_6,
252 7 => StandardFilterSlot::_7,
253 8 => StandardFilterSlot::_8,
254 9 => StandardFilterSlot::_9,
255 10 => StandardFilterSlot::_10,
256 11 => StandardFilterSlot::_11,
257 12 => StandardFilterSlot::_12,
258 13 => StandardFilterSlot::_13,
259 14 => StandardFilterSlot::_14,
260 15 => StandardFilterSlot::_15,
261 16 => StandardFilterSlot::_16,
262 17 => StandardFilterSlot::_17,
263 18 => StandardFilterSlot::_18,
264 19 => StandardFilterSlot::_19,
265 20 => StandardFilterSlot::_20,
266 21 => StandardFilterSlot::_21,
267 22 => StandardFilterSlot::_22,
268 23 => StandardFilterSlot::_23,
269 24 => StandardFilterSlot::_24,
270 25 => StandardFilterSlot::_25,
271 26 => StandardFilterSlot::_26,
272 27 => StandardFilterSlot::_27,
273 _ => panic!("Standard Filter Slot Too High!"),
274 }
275 }
276}
277
278/// Extended Filter Slot
279#[derive(Debug, Copy, Clone, Eq, PartialEq)]
280pub enum ExtendedFilterSlot {
281 /// 0
282 _0 = 0,
283 /// 1
284 _1 = 1,
285 /// 2
286 _2 = 2,
287 /// 3
288 _3 = 3,
289 /// 4
290 _4 = 4,
291 /// 5
292 _5 = 5,
293 /// 6
294 _6 = 6,
295 /// 7
296 _7 = 7,
297}
298impl From<u8> for ExtendedFilterSlot {
299 fn from(u: u8) -> Self {
300 match u {
301 0 => ExtendedFilterSlot::_0,
302 1 => ExtendedFilterSlot::_1,
303 2 => ExtendedFilterSlot::_2,
304 3 => ExtendedFilterSlot::_3,
305 4 => ExtendedFilterSlot::_4,
306 5 => ExtendedFilterSlot::_5,
307 6 => ExtendedFilterSlot::_6,
308 7 => ExtendedFilterSlot::_7,
309 _ => panic!("Extended Filter Slot Too High!"), // Should be unreachable
310 }
311 }
312}
313
314/// Enum over both Standard and Extended Filter ID's
315#[derive(Debug, Copy, Clone, Eq, PartialEq)]
316pub enum FilterId {
317 /// Standard Filter Slots
318 Standard(StandardFilterSlot),
319 /// Extended Filter Slots
320 Extended(ExtendedFilterSlot),
321}
322
323pub(crate) trait ActivateFilter<ID, UNIT>
324where
325 ID: Copy + Clone + core::fmt::Debug,
326 UNIT: Copy + Clone + core::fmt::Debug,
327{
328 fn activate(&mut self, f: Filter<ID, UNIT>);
329 // fn read(&self) -> Filter<ID, UNIT>;
330}
331
332impl ActivateFilter<StandardId, u16> for message_ram::StandardFilter {
333 fn activate(&mut self, f: Filter<StandardId, u16>) {
334 let sft = f.filter.into();
335
336 let (sfid1, sfid2) = match f.filter {
337 FilterType::Range { to, from } => (to.as_raw(), from.as_raw()),
338 FilterType::DedicatedSingle(id) => (id.as_raw(), id.as_raw()),
339 FilterType::DedicatedDual(id1, id2) => (id1.as_raw(), id2.as_raw()),
340 FilterType::BitMask { filter, mask } => (filter, mask),
341 FilterType::Disabled => (0x0, 0x0),
342 };
343 let sfec = f.action.into();
344 self.write(|w| {
345 unsafe { w.sfid1().bits(sfid1).sfid2().bits(sfid2) }
346 .sft()
347 .set_filter_type(sft)
348 .sfec()
349 .set_filter_element_config(sfec)
350 });
351 }
352 // fn read(&self) -> Filter<StandardId, u16> {
353 // todo!()
354 // }
355}
356impl ActivateFilter<ExtendedId, u32> for message_ram::ExtendedFilter {
357 fn activate(&mut self, f: Filter<ExtendedId, u32>) {
358 let eft = f.filter.into();
359
360 let (efid1, efid2) = match f.filter {
361 FilterType::Range { to, from } => (to.as_raw(), from.as_raw()),
362 FilterType::DedicatedSingle(id) => (id.as_raw(), id.as_raw()),
363 FilterType::DedicatedDual(id1, id2) => (id1.as_raw(), id2.as_raw()),
364 FilterType::BitMask { filter, mask } => (filter, mask),
365 FilterType::Disabled => (0x0, 0x0),
366 };
367 let efec = f.action.into();
368 self.write(|w| {
369 unsafe { w.efid1().bits(efid1).efid2().bits(efid2) }
370 .eft()
371 .set_filter_type(eft)
372 .efec()
373 .set_filter_element_config(efec)
374 });
375 }
376 // fn read(&self) -> Filter<ExtendedId, u32> {
377 // todo!()
378 // }
379}
diff --git a/embassy-stm32/src/can/fd/message_ram/common.rs b/embassy-stm32/src/can/fd/message_ram/common.rs
new file mode 100644
index 000000000..108c1a428
--- /dev/null
+++ b/embassy-stm32/src/can/fd/message_ram/common.rs
@@ -0,0 +1,134 @@
1// Note: This file is copied and modified from fdcan crate by Richard Meadows
2#![allow(non_camel_case_types)]
3#![allow(non_snake_case)]
4#![allow(unused)]
5
6use super::enums::{
7 BitRateSwitching, ErrorStateIndicator, FilterElementConfig, FilterType, FrameFormat, IdType,
8 RemoteTransmissionRequest,
9};
10use super::generic;
11
12#[doc = "Reader of field `ID`"]
13pub type ID_R = generic::R<u32, u32>;
14
15#[doc = "Reader of field `RTR`"]
16pub type RTR_R = generic::R<bool, RemoteTransmissionRequest>;
17impl RTR_R {
18 pub fn rtr(&self) -> RemoteTransmissionRequest {
19 match self.bits {
20 false => RemoteTransmissionRequest::TransmitDataFrame,
21 true => RemoteTransmissionRequest::TransmitRemoteFrame,
22 }
23 }
24 pub fn is_transmit_remote_frame(&self) -> bool {
25 *self == RemoteTransmissionRequest::TransmitRemoteFrame
26 }
27 pub fn is_transmit_data_frame(&self) -> bool {
28 *self == RemoteTransmissionRequest::TransmitDataFrame
29 }
30}
31
32#[doc = "Reader of field `XTD`"]
33pub type XTD_R = generic::R<bool, IdType>;
34impl XTD_R {
35 pub fn id_type(&self) -> IdType {
36 match self.bits() {
37 false => IdType::StandardId,
38 true => IdType::ExtendedId,
39 }
40 }
41 pub fn is_standard_id(&self) -> bool {
42 *self == IdType::StandardId
43 }
44 pub fn is_exteded_id(&self) -> bool {
45 *self == IdType::ExtendedId
46 }
47}
48
49#[doc = "Reader of field `ESI`"]
50pub type ESI_R = generic::R<bool, ErrorStateIndicator>;
51impl ESI_R {
52 pub fn error_state(&self) -> ErrorStateIndicator {
53 match self.bits() {
54 false => ErrorStateIndicator::ErrorActive,
55 true => ErrorStateIndicator::ErrorPassive,
56 }
57 }
58 pub fn is_error_active(&self) -> bool {
59 *self == ErrorStateIndicator::ErrorActive
60 }
61 pub fn is_error_passive(&self) -> bool {
62 *self == ErrorStateIndicator::ErrorPassive
63 }
64}
65
66#[doc = "Reader of field `DLC`"]
67pub type DLC_R = generic::R<u8, u8>;
68
69#[doc = "Reader of field `BRS`"]
70pub type BRS_R = generic::R<bool, BitRateSwitching>;
71impl BRS_R {
72 pub fn bit_rate_switching(&self) -> BitRateSwitching {
73 match self.bits() {
74 true => BitRateSwitching::WithBRS,
75 false => BitRateSwitching::WithoutBRS,
76 }
77 }
78 pub fn is_with_brs(&self) -> bool {
79 *self == BitRateSwitching::WithBRS
80 }
81 pub fn is_without_brs(&self) -> bool {
82 *self == BitRateSwitching::WithoutBRS
83 }
84}
85
86#[doc = "Reader of field `FDF`"]
87pub type FDF_R = generic::R<bool, FrameFormat>;
88impl FDF_R {
89 pub fn frame_format(&self) -> FrameFormat {
90 match self.bits() {
91 false => FrameFormat::Classic,
92 true => FrameFormat::Fdcan,
93 }
94 }
95 pub fn is_classic_format(&self) -> bool {
96 *self == FrameFormat::Classic
97 }
98 pub fn is_fdcan_format(&self) -> bool {
99 *self == FrameFormat::Fdcan
100 }
101}
102
103#[doc = "Reader of field `(X|S)FT`"]
104pub type ESFT_R = generic::R<u8, FilterType>;
105impl ESFT_R {
106 #[doc = r"Gets the Filtertype"]
107 #[inline(always)]
108 pub fn to_filter_type(&self) -> FilterType {
109 match self.bits() {
110 0b00 => FilterType::RangeFilter,
111 0b01 => FilterType::DualIdFilter,
112 0b10 => FilterType::ClassicFilter,
113 0b11 => FilterType::FilterDisabled,
114 _ => unreachable!(),
115 }
116 }
117}
118
119#[doc = "Reader of field `(E|S)FEC`"]
120pub type ESFEC_R = generic::R<u8, FilterElementConfig>;
121impl ESFEC_R {
122 pub fn to_filter_element_config(&self) -> FilterElementConfig {
123 match self.bits() {
124 0b000 => FilterElementConfig::DisableFilterElement,
125 0b001 => FilterElementConfig::StoreInFifo0,
126 0b010 => FilterElementConfig::StoreInFifo1,
127 0b011 => FilterElementConfig::Reject,
128 0b100 => FilterElementConfig::SetPriority,
129 0b101 => FilterElementConfig::SetPriorityAndStoreInFifo0,
130 0b110 => FilterElementConfig::SetPriorityAndStoreInFifo1,
131 _ => unimplemented!(),
132 }
133 }
134}
diff --git a/embassy-stm32/src/can/fd/message_ram/enums.rs b/embassy-stm32/src/can/fd/message_ram/enums.rs
new file mode 100644
index 000000000..0ec5e0f34
--- /dev/null
+++ b/embassy-stm32/src/can/fd/message_ram/enums.rs
@@ -0,0 +1,233 @@
1// Note: This file is copied and modified from fdcan crate by Richard Meadows
2
3/// Datalength is the message length generalised over
4/// the Standard (Classic) and FDCAN message types
5
6#[derive(Clone, Copy, Debug, PartialEq)]
7pub enum DataLength {
8 Classic(u8),
9 Fdcan(u8),
10}
11impl DataLength {
12 /// Creates a DataLength type
13 ///
14 /// Uses the byte length and Type of frame as input
15 pub fn new(len: u8, ff: FrameFormat) -> DataLength {
16 match ff {
17 FrameFormat::Classic => match len {
18 0..=8 => DataLength::Classic(len),
19 _ => panic!("DataLength > 8"),
20 },
21 FrameFormat::Fdcan => match len {
22 0..=64 => DataLength::Fdcan(len),
23 _ => panic!("DataLength > 64"),
24 },
25 }
26 }
27 /// Specialised function to create classic frames
28 pub fn new_classic(len: u8) -> DataLength {
29 Self::new(len, FrameFormat::Classic)
30 }
31 /// Specialised function to create FDCAN frames
32 pub fn new_fdcan(len: u8) -> DataLength {
33 Self::new(len, FrameFormat::Fdcan)
34 }
35
36 /// returns the length in bytes
37 pub fn len(&self) -> u8 {
38 match self {
39 DataLength::Classic(l) | DataLength::Fdcan(l) => *l,
40 }
41 }
42
43 pub(crate) fn dlc(&self) -> u8 {
44 match self {
45 DataLength::Classic(l) => *l,
46 // See RM0433 Rev 7 Table 475. DLC coding
47 DataLength::Fdcan(l) => match l {
48 0..=8 => *l,
49 9..=12 => 9,
50 13..=16 => 10,
51 17..=20 => 11,
52 21..=24 => 12,
53 25..=32 => 13,
54 33..=48 => 14,
55 49..=64 => 15,
56 _ => panic!("DataLength > 64"),
57 },
58 }
59 }
60}
61impl From<DataLength> for FrameFormat {
62 fn from(dl: DataLength) -> FrameFormat {
63 match dl {
64 DataLength::Classic(_) => FrameFormat::Classic,
65 DataLength::Fdcan(_) => FrameFormat::Fdcan,
66 }
67 }
68}
69
70/// Wheter or not to generate an Tx Event
71#[derive(Clone, Copy, Debug, PartialEq)]
72pub enum Event {
73 /// Do not generate an Tx Event
74 NoEvent,
75 /// Generate an Tx Event with a specified ID
76 Event(u8),
77}
78
79impl From<Event> for EventControl {
80 fn from(e: Event) -> Self {
81 match e {
82 Event::NoEvent => EventControl::DoNotStore,
83 Event::Event(_) => EventControl::Store,
84 }
85 }
86}
87
88impl From<Option<u8>> for Event {
89 fn from(mm: Option<u8>) -> Self {
90 match mm {
91 None => Event::NoEvent,
92 Some(mm) => Event::Event(mm),
93 }
94 }
95}
96
97impl From<Event> for Option<u8> {
98 fn from(e: Event) -> Option<u8> {
99 match e {
100 Event::NoEvent => None,
101 Event::Event(mm) => Some(mm),
102 }
103 }
104}
105
106/// TODO
107#[derive(Clone, Copy, Debug, PartialEq)]
108pub enum ErrorStateIndicator {
109 /// TODO
110 ErrorActive = 0,
111 /// TODO
112 ErrorPassive = 1,
113}
114impl From<ErrorStateIndicator> for bool {
115 #[inline(always)]
116 fn from(e: ErrorStateIndicator) -> Self {
117 e as u8 != 0
118 }
119}
120
121/// Type of frame, standard (classic) or FdCAN
122#[derive(Clone, Copy, Debug, PartialEq)]
123pub enum FrameFormat {
124 Classic = 0,
125 Fdcan = 1,
126}
127impl From<FrameFormat> for bool {
128 #[inline(always)]
129 fn from(e: FrameFormat) -> Self {
130 e as u8 != 0
131 }
132}
133
134/// Type of Id, Standard or Extended
135#[derive(Clone, Copy, Debug, PartialEq)]
136pub enum IdType {
137 /// Standard ID
138 StandardId = 0,
139 /// Extended ID
140 ExtendedId = 1,
141}
142impl From<IdType> for bool {
143 #[inline(always)]
144 fn from(e: IdType) -> Self {
145 e as u8 != 0
146 }
147}
148
149/// Whether the frame contains data or requests data
150#[derive(Clone, Copy, Debug, PartialEq)]
151pub enum RemoteTransmissionRequest {
152 /// Frame contains data
153 TransmitDataFrame = 0,
154 /// frame does not contain data
155 TransmitRemoteFrame = 1,
156}
157impl From<RemoteTransmissionRequest> for bool {
158 #[inline(always)]
159 fn from(e: RemoteTransmissionRequest) -> Self {
160 e as u8 != 0
161 }
162}
163
164/// Whether BitRateSwitching should be or was enabled
165#[derive(Clone, Copy, Debug, PartialEq)]
166pub enum BitRateSwitching {
167 /// disable bit rate switching
168 WithoutBRS = 0,
169 /// enable bit rate switching
170 WithBRS = 1,
171}
172impl From<BitRateSwitching> for bool {
173 #[inline(always)]
174 fn from(e: BitRateSwitching) -> Self {
175 e as u8 != 0
176 }
177}
178
179/// Whether to store transmit Events
180#[derive(Clone, Copy, Debug, PartialEq)]
181pub enum EventControl {
182 /// do not store an tx event
183 DoNotStore,
184 /// store transmit events
185 Store,
186}
187impl From<EventControl> for bool {
188 #[inline(always)]
189 fn from(e: EventControl) -> Self {
190 e as u8 != 0
191 }
192}
193
194/// If an received message matched any filters
195#[derive(Clone, Copy, Debug, PartialEq)]
196pub enum FilterFrameMatch {
197 /// This did match filter <id>
198 DidMatch(u8),
199 /// This received frame did not match any specific filters
200 DidNotMatch,
201}
202
203/// Type of filter to be used
204#[derive(Clone, Copy, Debug, PartialEq)]
205pub enum FilterType {
206 /// Filter uses the range between two id's
207 RangeFilter = 0b00,
208 /// The filter matches on two specific id's (or one ID checked twice)
209 DualIdFilter = 0b01,
210 /// Filter is using a bitmask
211 ClassicFilter = 0b10,
212 /// Filter is disabled
213 FilterDisabled = 0b11,
214}
215
216#[derive(Clone, Copy, Debug, PartialEq)]
217pub enum FilterElementConfig {
218 /// Filter is disabled
219 DisableFilterElement = 0b000,
220 /// Store a matching message in FIFO 0
221 StoreInFifo0 = 0b001,
222 /// Store a matching message in FIFO 1
223 StoreInFifo1 = 0b010,
224 /// Reject a matching message
225 Reject = 0b011,
226 /// Flag that a priority message has been received, *But do note store!*??
227 SetPriority = 0b100,
228 /// Flag and store message in FIFO 0
229 SetPriorityAndStoreInFifo0 = 0b101,
230 /// Flag and store message in FIFO 1
231 SetPriorityAndStoreInFifo1 = 0b110,
232 //_Unused = 0b111,
233}
diff --git a/embassy-stm32/src/can/fd/message_ram/extended_filter.rs b/embassy-stm32/src/can/fd/message_ram/extended_filter.rs
new file mode 100644
index 000000000..453e9056e
--- /dev/null
+++ b/embassy-stm32/src/can/fd/message_ram/extended_filter.rs
@@ -0,0 +1,136 @@
1// Note: This file is copied and modified from fdcan crate by Richard Meadows
2
3#![allow(non_camel_case_types)]
4#![allow(non_snake_case)]
5#![allow(unused)]
6
7use super::common::{ESFEC_R, ESFT_R};
8use super::enums::{FilterElementConfig, FilterType};
9use super::generic;
10
11#[doc = "Reader of register ExtendedFilter"]
12pub(crate) type R = generic::R<super::ExtendedFilterType, super::ExtendedFilter>;
13#[doc = "Writer for register ExtendedFilter"]
14pub(crate) type W = generic::W<super::ExtendedFilterType, super::ExtendedFilter>;
15#[doc = "Register ExtendedFilter `reset()`'s"]
16impl generic::ResetValue for super::ExtendedFilter {
17 type Type = super::ExtendedFilterType;
18 #[inline(always)]
19 fn reset_value() -> Self::Type {
20 // Sets filter element to Disabled
21 [0x0, 0x0]
22 }
23}
24
25#[doc = "Reader of field `EFID2`"]
26pub(crate) type EFID2_R = generic::R<u32, u32>;
27#[doc = "Write proxy for field `EFID2`"]
28pub(crate) struct EFID2_W<'a> {
29 w: &'a mut W,
30}
31impl<'a> EFID2_W<'a> {
32 #[doc = r"Writes raw bits to the field"]
33 #[inline(always)]
34 pub unsafe fn bits(self, value: u32) -> &'a mut W {
35 self.w.bits[1] = (self.w.bits[1] & !(0x1FFFFFFF)) | ((value as u32) & 0x1FFFFFFF);
36 self.w
37 }
38}
39
40#[doc = "Reader of field `EFID1`"]
41pub(crate) type EFID1_R = generic::R<u32, u32>;
42#[doc = "Write proxy for field `EFID1`"]
43pub(crate) struct EFID1_W<'a> {
44 w: &'a mut W,
45}
46impl<'a> EFID1_W<'a> {
47 #[doc = r"Writes raw bits to the field"]
48 #[inline(always)]
49 pub unsafe fn bits(self, value: u32) -> &'a mut W {
50 self.w.bits[0] = (self.w.bits[0] & !(0x1FFFFFFF)) | ((value as u32) & 0x1FFFFFFF);
51 self.w
52 }
53}
54
55#[doc = "Write proxy for field `EFEC`"]
56pub(crate) struct EFEC_W<'a> {
57 w: &'a mut W,
58}
59impl<'a> EFEC_W<'a> {
60 #[doc = r"Writes raw bits to the field"]
61 #[inline(always)]
62 pub unsafe fn bits(self, value: u8) -> &'a mut W {
63 self.w.bits[0] = (self.w.bits[0] & !(0x07 << 29)) | (((value as u32) & 0x07) << 29);
64 self.w
65 }
66 #[doc = r"Sets the field according to FilterElementConfig"]
67 #[inline(always)]
68 pub fn set_filter_element_config(self, fec: FilterElementConfig) -> &'a mut W {
69 //SAFETY: FilterElementConfig only be valid options
70 unsafe { self.bits(fec as u8) }
71 }
72}
73
74#[doc = "Write proxy for field `EFT`"]
75pub(crate) struct EFT_W<'a> {
76 w: &'a mut W,
77}
78impl<'a> EFT_W<'a> {
79 #[doc = r"Sets the field according the FilterType"]
80 #[inline(always)]
81 pub fn set_filter_type(self, filter: FilterType) -> &'a mut W {
82 //SAFETY: FilterType only be valid options
83 unsafe { self.bits(filter as u8) }
84 }
85 #[doc = r"Writes raw bits to the field"]
86 #[inline(always)]
87 pub unsafe fn bits(self, value: u8) -> &'a mut W {
88 self.w.bits[1] = (self.w.bits[1] & !(0x03 << 30)) | (((value as u32) & 0x03) << 30);
89 self.w
90 }
91}
92
93impl R {
94 #[doc = "Byte 0 - Bits 0:28 - EFID1"]
95 #[inline(always)]
96 pub fn sfid1(&self) -> EFID1_R {
97 EFID1_R::new(((self.bits[0]) & 0x1FFFFFFF) as u32)
98 }
99 #[doc = "Byte 0 - Bits 29:31 - EFEC"]
100 #[inline(always)]
101 pub fn efec(&self) -> ESFEC_R {
102 ESFEC_R::new(((self.bits[0] >> 29) & 0x07) as u8)
103 }
104 #[doc = "Byte 1 - Bits 0:28 - EFID2"]
105 #[inline(always)]
106 pub fn sfid2(&self) -> EFID2_R {
107 EFID2_R::new(((self.bits[1]) & 0x1FFFFFFF) as u32)
108 }
109 #[doc = "Byte 1 - Bits 30:31 - EFT"]
110 #[inline(always)]
111 pub fn eft(&self) -> ESFT_R {
112 ESFT_R::new(((self.bits[1] >> 30) & 0x03) as u8)
113 }
114}
115impl W {
116 #[doc = "Byte 0 - Bits 0:28 - EFID1"]
117 #[inline(always)]
118 pub fn efid1(&mut self) -> EFID1_W {
119 EFID1_W { w: self }
120 }
121 #[doc = "Byte 0 - Bits 29:31 - EFEC"]
122 #[inline(always)]
123 pub fn efec(&mut self) -> EFEC_W {
124 EFEC_W { w: self }
125 }
126 #[doc = "Byte 1 - Bits 0:28 - EFID2"]
127 #[inline(always)]
128 pub fn efid2(&mut self) -> EFID2_W {
129 EFID2_W { w: self }
130 }
131 #[doc = "Byte 1 - Bits 30:31 - EFT"]
132 #[inline(always)]
133 pub fn eft(&mut self) -> EFT_W {
134 EFT_W { w: self }
135 }
136}
diff --git a/embassy-stm32/src/can/fd/message_ram/generic.rs b/embassy-stm32/src/can/fd/message_ram/generic.rs
new file mode 100644
index 000000000..1a5e121b4
--- /dev/null
+++ b/embassy-stm32/src/can/fd/message_ram/generic.rs
@@ -0,0 +1,168 @@
1// Note: This file is copied and modified from fdcan crate by Richard Meadows
2
3use core::marker;
4
5///This trait shows that register has `read` method
6///
7///Registers marked with `Writable` can be also `modify`'ed
8pub trait Readable {}
9
10///This trait shows that register has `write`, `write_with_zero` and `reset` method
11///
12///Registers marked with `Readable` can be also `modify`'ed
13pub trait Writable {}
14
15///Reset value of the register
16///
17///This value is initial value for `write` method.
18///It can be also directly writed to register by `reset` method.
19pub trait ResetValue {
20 ///Register size
21 type Type;
22 ///Reset value of the register
23 fn reset_value() -> Self::Type;
24}
25
26///This structure provides volatile access to register
27pub struct Reg<U, REG> {
28 register: vcell::VolatileCell<U>,
29 _marker: marker::PhantomData<REG>,
30}
31
32unsafe impl<U: Send, REG> Send for Reg<U, REG> {}
33
34impl<U, REG> Reg<U, REG>
35where
36 Self: Readable,
37 U: Copy,
38{
39 ///Reads the contents of `Readable` register
40 ///
41 ///You can read the contents of a register in such way:
42 ///```ignore
43 ///let bits = periph.reg.read().bits();
44 ///```
45 ///or get the content of a particular field of a register.
46 ///```ignore
47 ///let reader = periph.reg.read();
48 ///let bits = reader.field1().bits();
49 ///let flag = reader.field2().bit_is_set();
50 ///```
51 #[inline(always)]
52 pub fn read(&self) -> R<U, Self> {
53 R {
54 bits: self.register.get(),
55 _reg: marker::PhantomData,
56 }
57 }
58}
59
60impl<U, REG> Reg<U, REG>
61where
62 Self: ResetValue<Type = U> + Writable,
63 U: Copy,
64{
65 ///Writes the reset value to `Writable` register
66 ///
67 ///Resets the register to its initial state
68 #[inline(always)]
69 pub fn reset(&self) {
70 self.register.set(Self::reset_value())
71 }
72}
73
74impl<U, REG> Reg<U, REG>
75where
76 Self: ResetValue<Type = U> + Writable,
77 U: Copy,
78{
79 ///Writes bits to `Writable` register
80 ///
81 ///You can write raw bits into a register:
82 ///```ignore
83 ///periph.reg.write(|w| unsafe { w.bits(rawbits) });
84 ///```
85 ///or write only the fields you need:
86 ///```ignore
87 ///periph.reg.write(|w| w
88 /// .field1().bits(newfield1bits)
89 /// .field2().set_bit()
90 /// .field3().variant(VARIANT)
91 ///);
92 ///```
93 ///Other fields will have reset value.
94 #[inline(always)]
95 pub fn write<F>(&self, f: F)
96 where
97 F: FnOnce(&mut W<U, Self>) -> &mut W<U, Self>,
98 {
99 self.register.set(
100 f(&mut W {
101 bits: Self::reset_value(),
102 _reg: marker::PhantomData,
103 })
104 .bits,
105 );
106 }
107}
108
109///Register/field reader
110///
111///Result of the [`read`](Reg::read) method of a register.
112///Also it can be used in the [`modify`](Reg::read) method
113pub struct R<U, T> {
114 pub(crate) bits: U,
115 _reg: marker::PhantomData<T>,
116}
117
118impl<U, T> R<U, T>
119where
120 U: Copy,
121{
122 ///Create new instance of reader
123 #[inline(always)]
124 pub(crate) fn new(bits: U) -> Self {
125 Self {
126 bits,
127 _reg: marker::PhantomData,
128 }
129 }
130 ///Read raw bits from register/field
131 #[inline(always)]
132 pub fn bits(&self) -> U {
133 self.bits
134 }
135}
136
137impl<U, T, FI> PartialEq<FI> for R<U, T>
138where
139 U: PartialEq,
140 FI: Copy + Into<U>,
141{
142 #[inline(always)]
143 fn eq(&self, other: &FI) -> bool {
144 self.bits.eq(&(*other).into())
145 }
146}
147
148impl<FI> R<bool, FI> {
149 ///Value of the field as raw bits
150 #[inline(always)]
151 pub fn bit(&self) -> bool {
152 self.bits
153 }
154 ///Returns `true` if the bit is clear (0)
155 #[inline(always)]
156 pub fn bit_is_clear(&self) -> bool {
157 !self.bit()
158 }
159}
160
161///Register writer
162///
163///Used as an argument to the closures in the [`write`](Reg::write) and [`modify`](Reg::modify) methods of the register
164pub struct W<U, REG> {
165 ///Writable bits
166 pub(crate) bits: U,
167 _reg: marker::PhantomData<REG>,
168}
diff --git a/embassy-stm32/src/can/fd/message_ram/mod.rs b/embassy-stm32/src/can/fd/message_ram/mod.rs
new file mode 100644
index 000000000..830edf3bb
--- /dev/null
+++ b/embassy-stm32/src/can/fd/message_ram/mod.rs
@@ -0,0 +1,170 @@
1// Note: This file is copied and modified from fdcan crate by Richard Meadows
2
3use volatile_register::RW;
4
5pub(crate) mod common;
6pub(crate) mod enums;
7pub(crate) mod generic;
8
9/// Number of Receive Fifos configured by this module
10pub const RX_FIFOS_MAX: u8 = 2;
11/// Number of Receive Messages per RxFifo configured by this module
12pub const RX_FIFO_MAX: u8 = 3;
13/// Number of Transmit Messages configured by this module
14pub const TX_FIFO_MAX: u8 = 3;
15/// Number of Transmit Events configured by this module
16pub const TX_EVENT_MAX: u8 = 3;
17/// Number of Standard Filters configured by this module
18pub const STANDARD_FILTER_MAX: u8 = 28;
19/// Number of Extended Filters configured by this module
20pub const EXTENDED_FILTER_MAX: u8 = 8;
21
22/// MessageRam Overlay
23#[repr(C)]
24pub struct RegisterBlock {
25 pub(crate) filters: Filters,
26 pub(crate) receive: [Receive; RX_FIFOS_MAX as usize],
27 pub(crate) transmit: Transmit,
28}
29impl RegisterBlock {
30 pub fn reset(&mut self) {
31 self.filters.reset();
32 self.receive[0].reset();
33 self.receive[1].reset();
34 self.transmit.reset();
35 }
36}
37
38#[repr(C)]
39pub(crate) struct Filters {
40 pub(crate) flssa: [StandardFilter; STANDARD_FILTER_MAX as usize],
41 pub(crate) flesa: [ExtendedFilter; EXTENDED_FILTER_MAX as usize],
42}
43impl Filters {
44 pub fn reset(&mut self) {
45 for sf in &mut self.flssa {
46 sf.reset();
47 }
48 for ef in &mut self.flesa {
49 ef.reset();
50 }
51 }
52}
53
54#[repr(C)]
55pub(crate) struct Receive {
56 pub(crate) fxsa: [RxFifoElement; RX_FIFO_MAX as usize],
57}
58impl Receive {
59 pub fn reset(&mut self) {
60 for fe in &mut self.fxsa {
61 fe.reset();
62 }
63 }
64}
65
66#[repr(C)]
67pub(crate) struct Transmit {
68 pub(crate) efsa: [TxEventElement; TX_EVENT_MAX as usize],
69 pub(crate) tbsa: [TxBufferElement; TX_FIFO_MAX as usize],
70}
71impl Transmit {
72 pub fn reset(&mut self) {
73 for ee in &mut self.efsa {
74 ee.reset();
75 }
76 for be in &mut self.tbsa {
77 be.reset();
78 }
79 }
80}
81
82pub(crate) mod standard_filter;
83pub(crate) type StandardFilterType = u32;
84pub(crate) type StandardFilter = generic::Reg<StandardFilterType, _StandardFilter>;
85pub(crate) struct _StandardFilter;
86impl generic::Readable for StandardFilter {}
87impl generic::Writable for StandardFilter {}
88
89pub(crate) mod extended_filter;
90pub(crate) type ExtendedFilterType = [u32; 2];
91pub(crate) type ExtendedFilter = generic::Reg<ExtendedFilterType, _ExtendedFilter>;
92pub(crate) struct _ExtendedFilter;
93impl generic::Readable for ExtendedFilter {}
94impl generic::Writable for ExtendedFilter {}
95
96pub(crate) mod txevent_element;
97pub(crate) type TxEventElementType = [u32; 2];
98pub(crate) type TxEventElement = generic::Reg<TxEventElementType, _TxEventElement>;
99pub(crate) struct _TxEventElement;
100impl generic::Readable for TxEventElement {}
101impl generic::Writable for TxEventElement {}
102
103pub(crate) mod rxfifo_element;
104#[repr(C)]
105pub(crate) struct RxFifoElement {
106 pub(crate) header: RxFifoElementHeader,
107 pub(crate) data: [RW<u32>; 16],
108}
109impl RxFifoElement {
110 pub(crate) fn reset(&mut self) {
111 self.header.reset();
112 for byte in self.data.iter_mut() {
113 unsafe { byte.write(0) };
114 }
115 }
116}
117pub(crate) type RxFifoElementHeaderType = [u32; 2];
118pub(crate) type RxFifoElementHeader = generic::Reg<RxFifoElementHeaderType, _RxFifoElement>;
119pub(crate) struct _RxFifoElement;
120impl generic::Readable for RxFifoElementHeader {}
121impl generic::Writable for RxFifoElementHeader {}
122
123pub(crate) mod txbuffer_element;
124#[repr(C)]
125pub(crate) struct TxBufferElement {
126 pub(crate) header: TxBufferElementHeader,
127 pub(crate) data: [RW<u32>; 16],
128}
129impl TxBufferElement {
130 pub(crate) fn reset(&mut self) {
131 self.header.reset();
132 for byte in self.data.iter_mut() {
133 unsafe { byte.write(0) };
134 }
135 }
136}
137pub(crate) type TxBufferElementHeader = generic::Reg<TxBufferElementHeaderType, _TxBufferElement>;
138pub(crate) type TxBufferElementHeaderType = [u32; 2];
139pub(crate) struct _TxBufferElement;
140impl generic::Readable for TxBufferElementHeader {}
141impl generic::Writable for TxBufferElementHeader {}
142
143/// FdCan Message RAM instance.
144///
145/// # Safety
146///
147/// It is only safe to implement this trait, when:
148///
149/// * The implementing type has ownership of the Message RAM, preventing any
150/// other accesses to the register block.
151/// * `MSG_RAM` is a pointer to the Message RAM block and can be safely accessed
152/// for as long as ownership or a borrow of the implementing type is present.
153pub unsafe trait Instance {
154 const MSG_RAM: *mut RegisterBlock;
155 fn msg_ram(&self) -> &RegisterBlock {
156 unsafe { &*Self::MSG_RAM }
157 }
158 fn msg_ram_mut(&mut self) -> &mut RegisterBlock {
159 unsafe { &mut *Self::MSG_RAM }
160 }
161}
162
163// Ensure the RegisterBlock is the same size as on pg 1957 of RM0440.
164static_assertions::assert_eq_size!(Filters, [u32; 28 + 16]);
165static_assertions::assert_eq_size!(Receive, [u32; 54]);
166static_assertions::assert_eq_size!(Transmit, [u32; 6 + 54]);
167static_assertions::assert_eq_size!(
168 RegisterBlock,
169 [u32; 28 /*Standard Filters*/ +16 /*Extended Filters*/ +54 /*RxFifo0*/ +54 /*RxFifo1*/ +6 /*TxEvent*/ +54 /*TxFifo */]
170);
diff --git a/embassy-stm32/src/can/fd/message_ram/rxfifo_element.rs b/embassy-stm32/src/can/fd/message_ram/rxfifo_element.rs
new file mode 100644
index 000000000..48fc3a091
--- /dev/null
+++ b/embassy-stm32/src/can/fd/message_ram/rxfifo_element.rs
@@ -0,0 +1,122 @@
1// Note: This file is copied and modified from fdcan crate by Richard Meadows
2
3#![allow(non_camel_case_types)]
4#![allow(non_snake_case)]
5#![allow(unused)]
6
7use super::common::{BRS_R, DLC_R, ESI_R, FDF_R, ID_R, RTR_R, XTD_R};
8use super::enums::{DataLength, FilterFrameMatch, FrameFormat};
9use super::generic;
10
11#[doc = "Reader of register RxFifoElement"]
12pub(crate) type R = generic::R<super::RxFifoElementHeaderType, super::RxFifoElementHeader>;
13// #[doc = "Writer for register ExtendedFilter"]
14// pub(crate) type W = generic::W<super::RxFifoElementHeaderType, super::RxFifoElementHeader>;
15#[doc = "Register ExtendedFilter `reset()`'s"]
16impl generic::ResetValue for super::RxFifoElementHeader {
17 type Type = super::RxFifoElementHeaderType;
18 #[inline(always)]
19 fn reset_value() -> Self::Type {
20 [0x0, 0x0]
21 }
22}
23
24#[doc = "Reader of field `RXTS`"]
25pub(crate) type RXTS_R = generic::R<u16, u16>;
26
27#[doc = "Reader of field `FIDX`"]
28pub(crate) type FIDX_R = generic::R<u8, u8>;
29
30pub(crate) struct _ANMF;
31#[doc = "Reader of field `ANMF`"]
32pub(crate) type ANMF_R = generic::R<bool, _ANMF>;
33impl ANMF_R {
34 pub fn is_matching_frame(&self) -> bool {
35 self.bit_is_clear()
36 }
37}
38
39impl R {
40 #[doc = "Byte 0 - Bits 0:28 - ID"]
41 #[inline(always)]
42 pub fn id(&self) -> ID_R {
43 ID_R::new(((self.bits[0]) & 0x1FFFFFFF) as u32)
44 }
45 #[doc = "Byte 0 - Bit 29 - RTR"]
46 #[inline(always)]
47 pub fn rtr(&self) -> RTR_R {
48 RTR_R::new(((self.bits[0] >> 29) & 0x01) != 0)
49 }
50 #[doc = "Byte 0 - Bit 30 - XTD"]
51 #[inline(always)]
52 pub fn xtd(&self) -> XTD_R {
53 XTD_R::new(((self.bits[0] >> 30) & 0x01) != 0)
54 }
55 #[doc = "Byte 0 - Bit 30 - ESI"]
56 #[inline(always)]
57 pub fn esi(&self) -> ESI_R {
58 ESI_R::new(((self.bits[0] >> 31) & 0x01) != 0)
59 }
60 #[doc = "Byte 1 - Bits 0:15 - RXTS"]
61 #[inline(always)]
62 pub fn txts(&self) -> RXTS_R {
63 RXTS_R::new(((self.bits[1]) & 0xFFFF) as u16)
64 }
65 #[doc = "Byte 1 - Bits 16:19 - DLC"]
66 #[inline(always)]
67 pub fn dlc(&self) -> DLC_R {
68 DLC_R::new(((self.bits[1] >> 16) & 0x0F) as u8)
69 }
70 #[doc = "Byte 1 - Bits 20 - BRS"]
71 #[inline(always)]
72 pub fn brs(&self) -> BRS_R {
73 BRS_R::new(((self.bits[1] >> 20) & 0x01) != 0)
74 }
75 #[doc = "Byte 1 - Bits 20 - FDF"]
76 #[inline(always)]
77 pub fn fdf(&self) -> FDF_R {
78 FDF_R::new(((self.bits[1] >> 21) & 0x01) != 0)
79 }
80 #[doc = "Byte 1 - Bits 24:30 - FIDX"]
81 #[inline(always)]
82 pub fn fidx(&self) -> FIDX_R {
83 FIDX_R::new(((self.bits[1] >> 24) & 0xFF) as u8)
84 }
85 #[doc = "Byte 1 - Bits 31 - ANMF"]
86 #[inline(always)]
87 pub fn anmf(&self) -> ANMF_R {
88 ANMF_R::new(((self.bits[1] >> 31) & 0x01) != 0)
89 }
90 pub fn to_data_length(&self) -> DataLength {
91 let dlc = self.dlc().bits();
92 let ff = self.fdf().frame_format();
93 let len = if ff == FrameFormat::Fdcan {
94 // See RM0433 Rev 7 Table 475. DLC coding
95 match dlc {
96 0..=8 => dlc,
97 9 => 12,
98 10 => 16,
99 11 => 20,
100 12 => 24,
101 13 => 32,
102 14 => 48,
103 15 => 64,
104 _ => panic!("DLC > 15"),
105 }
106 } else {
107 match dlc {
108 0..=8 => dlc,
109 9..=15 => 8,
110 _ => panic!("DLC > 15"),
111 }
112 };
113 DataLength::new(len, ff)
114 }
115 pub fn to_filter_match(&self) -> FilterFrameMatch {
116 if self.anmf().is_matching_frame() {
117 FilterFrameMatch::DidMatch(self.fidx().bits())
118 } else {
119 FilterFrameMatch::DidNotMatch
120 }
121 }
122}
diff --git a/embassy-stm32/src/can/fd/message_ram/standard_filter.rs b/embassy-stm32/src/can/fd/message_ram/standard_filter.rs
new file mode 100644
index 000000000..3a3bbcf12
--- /dev/null
+++ b/embassy-stm32/src/can/fd/message_ram/standard_filter.rs
@@ -0,0 +1,136 @@
1// Note: This file is copied and modified from fdcan crate by Richard Meadows
2
3#![allow(non_camel_case_types)]
4#![allow(non_snake_case)]
5#![allow(unused)]
6
7use super::common::{ESFEC_R, ESFT_R};
8use super::enums::{FilterElementConfig, FilterType};
9use super::generic;
10
11#[doc = "Reader of register StandardFilter"]
12pub(crate) type R = generic::R<super::StandardFilterType, super::StandardFilter>;
13#[doc = "Writer for register StandardFilter"]
14pub(crate) type W = generic::W<super::StandardFilterType, super::StandardFilter>;
15#[doc = "Register StandardFilter `reset()`'s with value 0xC0000"]
16impl generic::ResetValue for super::StandardFilter {
17 type Type = super::StandardFilterType;
18 #[inline(always)]
19 fn reset_value() -> Self::Type {
20 // Sets filter element to Disabled
21 0xC000
22 }
23}
24
25#[doc = "Reader of field `SFID2`"]
26pub(crate) type SFID2_R = generic::R<u16, u16>;
27#[doc = "Write proxy for field `SFID2`"]
28pub(crate) struct SFID2_W<'a> {
29 w: &'a mut W,
30}
31impl<'a> SFID2_W<'a> {
32 #[doc = r"Writes raw bits to the field"]
33 #[inline(always)]
34 pub unsafe fn bits(self, value: u16) -> &'a mut W {
35 self.w.bits = (self.w.bits & !(0x07ff)) | ((value as u32) & 0x07ff);
36 self.w
37 }
38}
39
40#[doc = "Reader of field `SFID1`"]
41pub(crate) type SFID1_R = generic::R<u16, u16>;
42#[doc = "Write proxy for field `SFID1`"]
43pub(crate) struct SFID1_W<'a> {
44 w: &'a mut W,
45}
46impl<'a> SFID1_W<'a> {
47 #[doc = r"Writes raw bits to the field"]
48 #[inline(always)]
49 pub unsafe fn bits(self, value: u16) -> &'a mut W {
50 self.w.bits = (self.w.bits & !(0x07ff << 16)) | (((value as u32) & 0x07ff) << 16);
51 self.w
52 }
53}
54
55#[doc = "Write proxy for field `SFEC`"]
56pub(crate) struct SFEC_W<'a> {
57 w: &'a mut W,
58}
59impl<'a> SFEC_W<'a> {
60 #[doc = r"Writes raw bits to the field"]
61 #[inline(always)]
62 pub unsafe fn bits(self, value: u8) -> &'a mut W {
63 self.w.bits = (self.w.bits & !(0x07 << 27)) | (((value as u32) & 0x07) << 27);
64 self.w
65 }
66 #[doc = r"Sets the field according to FilterElementConfig"]
67 #[inline(always)]
68 pub fn set_filter_element_config(self, fec: FilterElementConfig) -> &'a mut W {
69 //SAFETY: FilterElementConfig only be valid options
70 unsafe { self.bits(fec as u8) }
71 }
72}
73
74#[doc = "Write proxy for field `SFT`"]
75pub(crate) struct SFT_W<'a> {
76 w: &'a mut W,
77}
78impl<'a> SFT_W<'a> {
79 #[doc = r"Sets the field according the FilterType"]
80 #[inline(always)]
81 pub fn set_filter_type(self, filter: FilterType) -> &'a mut W {
82 //SAFETY: FilterType only be valid options
83 unsafe { self.bits(filter as u8) }
84 }
85 #[doc = r"Writes raw bits to the field"]
86 #[inline(always)]
87 pub unsafe fn bits(self, value: u8) -> &'a mut W {
88 self.w.bits = (self.w.bits & !(0x03 << 30)) | (((value as u32) & 0x03) << 30);
89 self.w
90 }
91}
92
93impl R {
94 #[doc = "Bits 0:10 - SFID2"]
95 #[inline(always)]
96 pub fn sfid2(&self) -> SFID2_R {
97 SFID2_R::new((self.bits & 0x07ff) as u16)
98 }
99 #[doc = "Bits 16:26 - SFID1"]
100 #[inline(always)]
101 pub fn sfid1(&self) -> SFID1_R {
102 SFID1_R::new(((self.bits >> 16) & 0x07ff) as u16)
103 }
104 #[doc = "Bits 27:29 - SFEC"]
105 #[inline(always)]
106 pub fn sfec(&self) -> ESFEC_R {
107 ESFEC_R::new(((self.bits >> 27) & 0x07) as u8)
108 }
109 #[doc = "Bits 30:31 - SFT"]
110 #[inline(always)]
111 pub fn sft(&self) -> ESFT_R {
112 ESFT_R::new(((self.bits >> 30) & 0x03) as u8)
113 }
114}
115impl W {
116 #[doc = "Bits 0:10 - SFID2"]
117 #[inline(always)]
118 pub fn sfid2(&mut self) -> SFID2_W {
119 SFID2_W { w: self }
120 }
121 #[doc = "Bits 16:26 - SFID1"]
122 #[inline(always)]
123 pub fn sfid1(&mut self) -> SFID1_W {
124 SFID1_W { w: self }
125 }
126 #[doc = "Bits 27:29 - SFEC"]
127 #[inline(always)]
128 pub fn sfec(&mut self) -> SFEC_W {
129 SFEC_W { w: self }
130 }
131 #[doc = "Bits 30:31 - SFT"]
132 #[inline(always)]
133 pub fn sft(&mut self) -> SFT_W {
134 SFT_W { w: self }
135 }
136}
diff --git a/embassy-stm32/src/can/fd/message_ram/txbuffer_element.rs b/embassy-stm32/src/can/fd/message_ram/txbuffer_element.rs
new file mode 100644
index 000000000..455406a1c
--- /dev/null
+++ b/embassy-stm32/src/can/fd/message_ram/txbuffer_element.rs
@@ -0,0 +1,433 @@
1// Note: This file is copied and modified from fdcan crate by Richard Meadows
2
3#![allow(non_camel_case_types)]
4#![allow(non_snake_case)]
5#![allow(unused)]
6
7use super::common::{BRS_R, DLC_R, ESI_R, FDF_R, ID_R, RTR_R, XTD_R};
8use super::enums::{
9 BitRateSwitching, DataLength, ErrorStateIndicator, Event, EventControl, FrameFormat, IdType,
10 RemoteTransmissionRequest,
11};
12use super::generic;
13
14#[doc = "Reader of register TxBufferElement"]
15pub(crate) type R = generic::R<super::TxBufferElementHeaderType, super::TxBufferElementHeader>;
16#[doc = "Writer for register TxBufferElement"]
17pub(crate) type W = generic::W<super::TxBufferElementHeaderType, super::TxBufferElementHeader>;
18impl generic::ResetValue for super::TxBufferElementHeader {
19 type Type = super::TxBufferElementHeaderType;
20
21 #[allow(dead_code)]
22 #[inline(always)]
23 fn reset_value() -> Self::Type {
24 [0; 2]
25 }
26}
27
28#[doc = "Write proxy for field `ESI`"]
29pub(crate) struct ESI_W<'a> {
30 w: &'a mut W,
31}
32impl<'a> ESI_W<'a> {
33 #[doc = r"Writes `variant` to the field"]
34 #[inline(always)]
35 #[allow(dead_code)]
36 pub fn set_error_indicator(self, esi: ErrorStateIndicator) -> &'a mut W {
37 self.bit(esi as u8 != 0)
38 }
39
40 #[doc = r"Sets the field bit"]
41 #[inline(always)]
42 #[allow(dead_code)]
43 pub fn set_bit(self) -> &'a mut W {
44 self.bit(true)
45 }
46 #[doc = r"Clears the field bit"]
47 #[inline(always)]
48 #[allow(dead_code)]
49 pub fn clear_bit(self) -> &'a mut W {
50 self.bit(false)
51 }
52 #[doc = r"Writes raw bits to the field"]
53 #[inline(always)]
54 #[allow(dead_code)]
55 pub fn bit(self, value: bool) -> &'a mut W {
56 self.w.bits[0] = (self.w.bits[0] & !(0x01 << 31)) | (((value as u32) & 0x01) << 31);
57 self.w
58 }
59}
60
61#[doc = "Write proxy for field `XTD`"]
62pub(crate) struct XTD_W<'a> {
63 w: &'a mut W,
64}
65impl<'a> XTD_W<'a> {
66 #[doc = r"Writes `variant` to the field"]
67 #[inline(always)]
68 #[allow(dead_code)]
69 pub fn set_id_type(self, idt: IdType) -> &'a mut W {
70 self.bit(idt as u8 != 0)
71 }
72
73 #[doc = r"Sets the field bit"]
74 #[inline(always)]
75 #[allow(dead_code)]
76 pub fn set_bit(self) -> &'a mut W {
77 self.bit(true)
78 }
79 #[doc = r"Clears the field bit"]
80 #[inline(always)]
81 #[allow(dead_code)]
82 pub fn clear_bit(self) -> &'a mut W {
83 self.bit(false)
84 }
85 #[doc = r"Writes raw bits to the field"]
86 #[inline(always)]
87 #[allow(dead_code)]
88 pub fn bit(self, value: bool) -> &'a mut W {
89 self.w.bits[0] = (self.w.bits[0] & !(0x01 << 30)) | (((value as u32) & 0x01) << 30);
90 self.w
91 }
92}
93
94#[doc = "Write proxy for field `RTR`"]
95pub(crate) struct RTR_W<'a> {
96 w: &'a mut W,
97}
98impl<'a> RTR_W<'a> {
99 #[doc = r"Writes `variant` to the field"]
100 #[inline(always)]
101 #[allow(dead_code)]
102 pub fn set_rtr(self, rtr: RemoteTransmissionRequest) -> &'a mut W {
103 self.bit(rtr as u8 != 0)
104 }
105
106 #[doc = r"Sets the field bit"]
107 #[inline(always)]
108 #[allow(dead_code)]
109 pub fn set_bit(self) -> &'a mut W {
110 self.bit(true)
111 }
112 #[doc = r"Clears the field bit"]
113 #[inline(always)]
114 #[allow(dead_code)]
115 pub fn clear_bit(self) -> &'a mut W {
116 self.bit(false)
117 }
118 #[doc = r"Writes raw bits to the field"]
119 #[inline(always)]
120 #[allow(dead_code)]
121 pub fn bit(self, value: bool) -> &'a mut W {
122 self.w.bits[0] = (self.w.bits[0] & !(0x01 << 29)) | (((value as u32) & 0x01) << 29);
123 self.w
124 }
125}
126
127#[doc = "Write proxy for field `ID`"]
128pub(crate) struct ID_W<'a> {
129 w: &'a mut W,
130}
131impl<'a> ID_W<'a> {
132 #[doc = r"Writes raw bits to the field"]
133 #[inline(always)]
134 #[allow(dead_code)]
135 pub unsafe fn bits(self, value: u32) -> &'a mut W {
136 self.w.bits[0] = (self.w.bits[0] & !(0x1FFFFFFF)) | ((value as u32) & 0x1FFFFFFF);
137 self.w
138 }
139}
140
141#[doc = "Write proxy for field `DLC`"]
142pub(crate) struct DLC_W<'a> {
143 w: &'a mut W,
144}
145impl<'a> DLC_W<'a> {
146 #[doc = r"Writes raw bits to the field"]
147 #[inline(always)]
148 #[allow(dead_code)]
149 pub unsafe fn bits(self, value: u8) -> &'a mut W {
150 self.w.bits[1] = (self.w.bits[1] & !(0x0F << 16)) | (((value as u32) & 0x0F) << 16);
151 self.w
152 }
153}
154
155#[doc = "Write proxy for field `BRS`"]
156pub(crate) struct BRS_W<'a> {
157 w: &'a mut W,
158}
159impl<'a> BRS_W<'a> {
160 #[doc = r"Writes `variant` to the field"]
161 #[inline(always)]
162 #[allow(dead_code)]
163 pub fn set_brs(self, brs: BitRateSwitching) -> &'a mut W {
164 self.bit(brs as u8 != 0)
165 }
166
167 #[doc = r"Sets the field bit"]
168 #[inline(always)]
169 #[allow(dead_code)]
170 pub fn set_bit(self) -> &'a mut W {
171 self.bit(true)
172 }
173 #[doc = r"Clears the field bit"]
174 #[inline(always)]
175 #[allow(dead_code)]
176 pub fn clear_bit(self) -> &'a mut W {
177 self.bit(false)
178 }
179 #[doc = r"Writes raw bits to the field"]
180 #[inline(always)]
181 #[allow(dead_code)]
182 pub fn bit(self, value: bool) -> &'a mut W {
183 self.w.bits[1] = (self.w.bits[1] & !(0x01 << 20)) | (((value as u32) & 0x01) << 20);
184 self.w
185 }
186}
187
188#[doc = "Write proxy for field `FDF`"]
189pub(crate) struct FDF_W<'a> {
190 w: &'a mut W,
191}
192impl<'a> FDF_W<'a> {
193 #[doc = r"Writes `variant` to the field"]
194 #[inline(always)]
195 #[allow(dead_code)]
196 pub fn set_format(self, fdf: FrameFormat) -> &'a mut W {
197 self.bit(fdf as u8 != 0)
198 }
199
200 #[doc = r"Sets the field bit"]
201 #[inline(always)]
202 #[allow(dead_code)]
203 pub fn set_bit(self) -> &'a mut W {
204 self.bit(true)
205 }
206 #[doc = r"Clears the field bit"]
207 #[inline(always)]
208 #[allow(dead_code)]
209 pub fn clear_bit(self) -> &'a mut W {
210 self.bit(false)
211 }
212 #[doc = r"Writes raw bits to the field"]
213 #[inline(always)]
214 #[allow(dead_code)]
215 pub fn bit(self, value: bool) -> &'a mut W {
216 self.w.bits[1] = (self.w.bits[1] & !(0x01 << 21)) | (((value as u32) & 0x01) << 21);
217 self.w
218 }
219}
220
221#[doc = "Reader of field `EFC`"]
222pub(crate) type EFC_R = generic::R<bool, EventControl>;
223impl EFC_R {
224 pub fn to_event_control(&self) -> EventControl {
225 match self.bit() {
226 false => EventControl::DoNotStore,
227 true => EventControl::Store,
228 }
229 }
230}
231#[doc = "Write proxy for field `EFC`"]
232pub(crate) struct EFC_W<'a> {
233 w: &'a mut W,
234}
235impl<'a> EFC_W<'a> {
236 #[doc = r"Writes `variant` to the field"]
237 #[inline(always)]
238 #[allow(dead_code)]
239 pub fn set_event_control(self, efc: EventControl) -> &'a mut W {
240 self.bit(match efc {
241 EventControl::DoNotStore => false,
242 EventControl::Store => true,
243 })
244 }
245
246 #[doc = r"Sets the field bit"]
247 #[inline(always)]
248 #[allow(dead_code)]
249 pub fn set_bit(self) -> &'a mut W {
250 self.bit(true)
251 }
252 #[doc = r"Clears the field bit"]
253 #[inline(always)]
254 #[allow(dead_code)]
255 pub fn clear_bit(self) -> &'a mut W {
256 self.bit(false)
257 }
258 #[doc = r"Writes raw bits to the field"]
259 #[inline(always)]
260 #[allow(dead_code)]
261 pub fn bit(self, value: bool) -> &'a mut W {
262 self.w.bits[1] = (self.w.bits[1] & !(0x01 << 23)) | (((value as u32) & 0x01) << 23);
263 self.w
264 }
265}
266
267struct Marker(u8);
268impl From<Event> for Marker {
269 fn from(e: Event) -> Marker {
270 match e {
271 Event::NoEvent => Marker(0),
272 Event::Event(mm) => Marker(mm),
273 }
274 }
275}
276
277#[doc = "Reader of field `MM`"]
278pub(crate) type MM_R = generic::R<u8, u8>;
279#[doc = "Write proxy for field `MM`"]
280pub(crate) struct MM_W<'a> {
281 w: &'a mut W,
282}
283impl<'a> MM_W<'a> {
284 #[doc = r"Writes raw bits to the field"]
285 #[inline(always)]
286 pub unsafe fn bits(self, value: u8) -> &'a mut W {
287 self.w.bits[1] = (self.w.bits[1] & !(0x7F << 24)) | (((value as u32) & 0x7F) << 24);
288 self.w
289 }
290
291 fn set_message_marker(self, mm: Marker) -> &'a mut W {
292 unsafe { self.bits(mm.0) }
293 }
294}
295
296impl R {
297 #[doc = "Byte 0 - Bits 0:28 - ID"]
298 #[inline(always)]
299 pub fn id(&self) -> ID_R {
300 ID_R::new(((self.bits[0]) & 0x1FFFFFFF) as u32)
301 }
302 #[doc = "Byte 0 - Bit 29 - RTR"]
303 #[inline(always)]
304 pub fn rtr(&self) -> RTR_R {
305 RTR_R::new(((self.bits[0] >> 29) & 0x01) != 0)
306 }
307 #[doc = "Byte 0 - Bit 30 - XTD"]
308 #[inline(always)]
309 pub fn xtd(&self) -> XTD_R {
310 XTD_R::new(((self.bits[0] >> 30) & 0x01) != 0)
311 }
312 #[doc = "Byte 0 - Bit 30 - ESI"]
313 #[inline(always)]
314 pub fn esi(&self) -> ESI_R {
315 ESI_R::new(((self.bits[0] >> 31) & 0x01) != 0)
316 }
317 #[doc = "Byte 1 - Bits 16:19 - DLC"]
318 #[inline(always)]
319 pub fn dlc(&self) -> DLC_R {
320 DLC_R::new(((self.bits[1] >> 16) & 0x0F) as u8)
321 }
322 #[doc = "Byte 1 - Bits 20 - BRS"]
323 #[inline(always)]
324 pub fn brs(&self) -> BRS_R {
325 BRS_R::new(((self.bits[1] >> 20) & 0x01) != 0)
326 }
327 #[doc = "Byte 1 - Bits 20 - FDF"]
328 #[inline(always)]
329 pub fn fdf(&self) -> FDF_R {
330 FDF_R::new(((self.bits[1] >> 21) & 0x01) != 0)
331 }
332 #[doc = "Byte 1 - Bits 23 - EFC"]
333 #[inline(always)]
334 pub fn efc(&self) -> EFC_R {
335 EFC_R::new(((self.bits[1] >> 23) & 0x01) != 0)
336 }
337 #[doc = "Byte 1 - Bits 24:31 - MM"]
338 #[inline(always)]
339 pub fn mm(&self) -> MM_R {
340 MM_R::new(((self.bits[1] >> 24) & 0xFF) as u8)
341 }
342 pub fn to_data_length(&self) -> DataLength {
343 let dlc = self.dlc().bits();
344 let ff = self.fdf().frame_format();
345 let len = if ff == FrameFormat::Fdcan {
346 // See RM0433 Rev 7 Table 475. DLC coding
347 match dlc {
348 0..=8 => dlc,
349 9 => 12,
350 10 => 16,
351 11 => 20,
352 12 => 24,
353 13 => 32,
354 14 => 48,
355 15 => 64,
356 _ => panic!("DLC > 15"),
357 }
358 } else {
359 match dlc {
360 0..=8 => dlc,
361 9..=15 => 8,
362 _ => panic!("DLC > 15"),
363 }
364 };
365 DataLength::new(len, ff)
366 }
367 pub fn to_event(&self) -> Event {
368 let mm = self.mm().bits();
369 let efc = self.efc().to_event_control();
370 match efc {
371 EventControl::DoNotStore => Event::NoEvent,
372 EventControl::Store => Event::Event(mm),
373 }
374 }
375}
376impl W {
377 #[doc = "Byte 0 - Bits 0:28 - ID"]
378 #[inline(always)]
379 pub fn id(&mut self) -> ID_W {
380 ID_W { w: self }
381 }
382 #[doc = "Byte 0 - Bit 29 - RTR"]
383 #[inline(always)]
384 pub fn rtr(&mut self) -> RTR_W {
385 RTR_W { w: self }
386 }
387 #[doc = "Byte 0 - Bit 30 - XTD"]
388 #[inline(always)]
389 pub fn xtd(&mut self) -> XTD_W {
390 XTD_W { w: self }
391 }
392 #[doc = "Byte 0 - Bit 31 - ESI"]
393 #[inline(always)]
394 pub fn esi(&mut self) -> ESI_W {
395 ESI_W { w: self }
396 }
397 #[doc = "Byte 1 - Bit 16:19 - DLC"]
398 #[inline(always)]
399 pub fn dlc(&mut self) -> DLC_W {
400 DLC_W { w: self }
401 }
402 #[doc = "Byte 1 - Bit 20 - BRS"]
403 #[inline(always)]
404 pub fn brs(&mut self) -> BRS_W {
405 BRS_W { w: self }
406 }
407 #[doc = "Byte 1 - Bit 21 - FDF"]
408 #[inline(always)]
409 pub fn fdf(&mut self) -> FDF_W {
410 FDF_W { w: self }
411 }
412 #[doc = "Byte 1 - Bit 23 - EFC"]
413 #[inline(always)]
414 pub fn efc(&mut self) -> EFC_W {
415 EFC_W { w: self }
416 }
417 #[doc = "Byte 1 - Bit 24:31 - MM"]
418 #[inline(always)]
419 pub fn mm(&mut self) -> MM_W {
420 MM_W { w: self }
421 }
422 #[doc = "Convenience function for setting the data length and frame format"]
423 #[inline(always)]
424 pub fn set_len(&mut self, dl: impl Into<DataLength>) -> &mut Self {
425 let dl: DataLength = dl.into();
426 self.fdf().set_format(dl.into());
427 unsafe { self.dlc().bits(dl.dlc()) }
428 }
429 pub fn set_event(&mut self, event: Event) -> &mut Self {
430 self.mm().set_message_marker(event.into());
431 self.efc().set_event_control(event.into())
432 }
433}
diff --git a/embassy-stm32/src/can/fd/message_ram/txevent_element.rs b/embassy-stm32/src/can/fd/message_ram/txevent_element.rs
new file mode 100644
index 000000000..817a4449f
--- /dev/null
+++ b/embassy-stm32/src/can/fd/message_ram/txevent_element.rs
@@ -0,0 +1,138 @@
1// Note: This file is copied and modified from fdcan crate by Richard Meadows
2
3#![allow(non_camel_case_types)]
4#![allow(non_snake_case)]
5#![allow(unused)]
6
7use super::common::{BRS_R, DLC_R, ESI_R, RTR_R, XTD_R};
8use super::generic;
9
10#[doc = "Reader of register TxEventElement"]
11pub(crate) type R = generic::R<super::TxEventElementType, super::TxEventElement>;
12// #[doc = "Writer for register TxEventElement"]
13// pub(crate) type W = generic::W<super::TxEventElementType, super::TxEventElement>;
14#[doc = "Register TxEventElement `reset()`'s"]
15impl generic::ResetValue for super::TxEventElement {
16 type Type = super::TxEventElementType;
17 #[inline(always)]
18 fn reset_value() -> Self::Type {
19 [0, 0]
20 }
21}
22
23#[doc = "Reader of field `ID`"]
24pub(crate) type ID_R = generic::R<u32, u32>;
25
26#[doc = "Reader of field `TXTS`"]
27pub(crate) type TXTS_R = generic::R<u16, u16>;
28
29#[derive(Clone, Copy, Debug, PartialEq)]
30pub(crate) enum DataLengthFormat {
31 StandardLength = 0,
32 FDCANLength = 1,
33}
34impl From<DataLengthFormat> for bool {
35 #[inline(always)]
36 fn from(dlf: DataLengthFormat) -> Self {
37 dlf as u8 != 0
38 }
39}
40
41#[doc = "Reader of field `EDL`"]
42pub(crate) type EDL_R = generic::R<bool, DataLengthFormat>;
43impl EDL_R {
44 pub fn data_length_format(&self) -> DataLengthFormat {
45 match self.bits() {
46 false => DataLengthFormat::StandardLength,
47 true => DataLengthFormat::FDCANLength,
48 }
49 }
50 pub fn is_standard_length(&self) -> bool {
51 *self == DataLengthFormat::StandardLength
52 }
53 pub fn is_fdcan_length(&self) -> bool {
54 *self == DataLengthFormat::FDCANLength
55 }
56}
57
58#[derive(Clone, Copy, Debug, PartialEq)]
59pub(crate) enum EventType {
60 //_Reserved = 0b00,
61 TxEvent = 0b01,
62 TxDespiteAbort = 0b10,
63 //_Reserved = 0b10,
64}
65
66#[doc = "Reader of field `EFC`"]
67pub(crate) type EFC_R = generic::R<u8, EventType>;
68impl EFC_R {
69 pub fn event_type(&self) -> EventType {
70 match self.bits() {
71 0b01 => EventType::TxEvent,
72 0b10 => EventType::TxDespiteAbort,
73 _ => unimplemented!(),
74 }
75 }
76 pub fn is_tx_event(&self) -> bool {
77 self.event_type() == EventType::TxEvent
78 }
79 pub fn is_despite_abort(&self) -> bool {
80 self.event_type() == EventType::TxDespiteAbort
81 }
82}
83
84#[doc = "Reader of field `MM`"]
85pub(crate) type MM_R = generic::R<u8, u8>;
86
87impl R {
88 #[doc = "Byte 0 - Bits 0:28 - ID"]
89 #[inline(always)]
90 pub fn id(&self) -> ID_R {
91 ID_R::new(((self.bits[0]) & 0x1FFFFFFF) as u32)
92 }
93 #[doc = "Byte 0 - Bit 29 - RTR"]
94 #[inline(always)]
95 pub fn rtr(&self) -> RTR_R {
96 RTR_R::new(((self.bits[0] >> 29) & 0x01) != 0)
97 }
98 #[doc = "Byte 0 - Bit 30 - XTD"]
99 #[inline(always)]
100 pub fn xtd(&self) -> XTD_R {
101 XTD_R::new(((self.bits[0] >> 30) & 0x01) != 0)
102 }
103 #[doc = "Byte 0 - Bit 30 - ESI"]
104 #[inline(always)]
105 pub fn esi(&self) -> ESI_R {
106 ESI_R::new(((self.bits[0] >> 31) & 0x01) != 0)
107 }
108 #[doc = "Byte 1 - Bits 0:15 - TXTS"]
109 #[inline(always)]
110 pub fn txts(&self) -> TXTS_R {
111 TXTS_R::new(((self.bits[1]) & 0xFFFF) as u16)
112 }
113 #[doc = "Byte 1 - Bits 16:19 - DLC"]
114 #[inline(always)]
115 pub fn dlc(&self) -> DLC_R {
116 DLC_R::new(((self.bits[1] >> 16) & 0x0F) as u8)
117 }
118 #[doc = "Byte 1 - Bits 20 - BRS"]
119 #[inline(always)]
120 pub fn brs(&self) -> BRS_R {
121 BRS_R::new(((self.bits[1] >> 20) & 0x01) != 0)
122 }
123 #[doc = "Byte 1 - Bits 21 - EDL"]
124 #[inline(always)]
125 pub fn edl(&self) -> EDL_R {
126 EDL_R::new(((self.bits[1] >> 21) & 0x01) != 0)
127 }
128 #[doc = "Byte 1 - Bits 22:23 - EFC"]
129 #[inline(always)]
130 pub fn efc(&self) -> EFC_R {
131 EFC_R::new(((self.bits[1] >> 22) & 0x03) as u8)
132 }
133 #[doc = "Byte 1 - Bits 24:31 - MM"]
134 #[inline(always)]
135 pub fn mm(&self) -> MM_R {
136 MM_R::new(((self.bits[1] >> 24) & 0xFF) as u8)
137 }
138}
diff --git a/embassy-stm32/src/can/fd/mod.rs b/embassy-stm32/src/can/fd/mod.rs
new file mode 100644
index 000000000..271ca0b3c
--- /dev/null
+++ b/embassy-stm32/src/can/fd/mod.rs
@@ -0,0 +1,6 @@
1//! Module containing that which is specific to fdcan hardware variant
2
3pub mod config;
4pub mod filter;
5pub(crate) mod message_ram;
6pub(crate) mod peripheral;
diff --git a/embassy-stm32/src/can/fd/peripheral.rs b/embassy-stm32/src/can/fd/peripheral.rs
new file mode 100644
index 000000000..0771d6fbb
--- /dev/null
+++ b/embassy-stm32/src/can/fd/peripheral.rs
@@ -0,0 +1,828 @@
1// Note: This file is copied and modified from fdcan crate by Richard Meadows
2
3use core::convert::Infallible;
4use core::slice;
5
6use cfg_if::cfg_if;
7
8use crate::can::enums::*;
9use crate::can::fd::config::*;
10use crate::can::fd::message_ram::enums::*;
11use crate::can::fd::message_ram::{RegisterBlock, RxFifoElement, TxBufferElement};
12use crate::can::frame::*;
13
14/// Loopback Mode
15#[derive(Clone, Copy, Debug)]
16enum LoopbackMode {
17 None,
18 Internal,
19 External,
20}
21
22pub struct Registers {
23 pub regs: &'static crate::pac::can::Fdcan,
24 pub msgram: &'static crate::pac::fdcanram::Fdcanram,
25}
26
27impl Registers {
28 fn tx_buffer_element(&self, bufidx: usize) -> &mut TxBufferElement {
29 &mut self.msg_ram_mut().transmit.tbsa[bufidx]
30 }
31 pub fn msg_ram_mut(&self) -> &mut RegisterBlock {
32 let ptr = self.msgram.as_ptr() as *mut RegisterBlock;
33 unsafe { &mut (*ptr) }
34 }
35
36 fn rx_fifo_element(&self, fifonr: usize, bufnum: usize) -> &mut RxFifoElement {
37 &mut self.msg_ram_mut().receive[fifonr].fxsa[bufnum]
38 }
39
40 pub fn read_classic(&self, fifonr: usize) -> Option<(ClassicFrame, u16)> {
41 // Fill level - do we have a msg?
42 if self.regs.rxfs(fifonr).read().ffl() < 1 {
43 return None;
44 }
45
46 let read_idx = self.regs.rxfs(fifonr).read().fgi();
47 let mailbox = self.rx_fifo_element(fifonr, read_idx as usize);
48
49 let mut buffer: [u8; 8] = [0; 8];
50 let maybe_header = extract_frame(mailbox, &mut buffer);
51
52 // Clear FIFO, reduces count and increments read buf
53 self.regs.rxfa(fifonr).modify(|w| w.set_fai(read_idx));
54
55 match maybe_header {
56 Some((header, ts)) => {
57 let data = ClassicData::new(&buffer[0..header.len() as usize]);
58 Some((ClassicFrame::new(header, data.unwrap()), ts))
59 }
60 None => None,
61 }
62 }
63
64 pub fn read_fd(&self, fifonr: usize) -> Option<(FdFrame, u16)> {
65 // Fill level - do we have a msg?
66 if self.regs.rxfs(fifonr).read().ffl() < 1 {
67 return None;
68 }
69
70 let read_idx = self.regs.rxfs(fifonr).read().fgi();
71 let mailbox = self.rx_fifo_element(fifonr, read_idx as usize);
72
73 let mut buffer: [u8; 64] = [0; 64];
74 let maybe_header = extract_frame(mailbox, &mut buffer);
75
76 // Clear FIFO, reduces count and increments read buf
77 self.regs.rxfa(fifonr).modify(|w| w.set_fai(read_idx));
78
79 match maybe_header {
80 Some((header, ts)) => {
81 let data = FdData::new(&buffer[0..header.len() as usize]);
82 Some((FdFrame::new(header, data.unwrap()), ts))
83 }
84 None => None,
85 }
86 }
87
88 pub fn put_tx_frame(&self, bufidx: usize, header: &Header, buffer: &[u8]) {
89 // Fill level - do we have a msg?
90 //if self.regs.rxfs(fifonr).read().ffl() < 1 { return None; }
91
92 //let read_idx = self.regs.rxfs(fifonr).read().fgi();
93
94 let mailbox = self.tx_buffer_element(bufidx);
95
96 mailbox.reset();
97 put_tx_header(mailbox, header);
98 put_tx_data(mailbox, &buffer[..header.len() as usize]);
99
100 // Set <idx as Mailbox> as ready to transmit
101 self.regs.txbar().modify(|w| w.set_ar(bufidx, true));
102 }
103
104 fn reg_to_error(value: u8) -> Option<BusError> {
105 match value {
106 //0b000 => None,
107 0b001 => Some(BusError::Stuff),
108 0b010 => Some(BusError::Form),
109 0b011 => Some(BusError::Acknowledge),
110 0b100 => Some(BusError::BitRecessive),
111 0b101 => Some(BusError::BitDominant),
112 0b110 => Some(BusError::Crc),
113 //0b111 => Some(BusError::NoError),
114 _ => None,
115 }
116 }
117
118 pub fn curr_error(&self) -> Option<BusError> {
119 let err = { self.regs.psr().read() };
120 if err.bo() {
121 return Some(BusError::BusOff);
122 } else if err.ep() {
123 return Some(BusError::BusPassive);
124 } else if err.ew() {
125 return Some(BusError::BusWarning);
126 } else {
127 cfg_if! {
128 if #[cfg(stm32h7)] {
129 let lec = err.lec();
130 } else {
131 let lec = err.lec().to_bits();
132 }
133 }
134 if let Some(err) = Self::reg_to_error(lec) {
135 return Some(err);
136 }
137 }
138 None
139 }
140 /// Returns if the tx queue is able to accept new messages without having to cancel an existing one
141 #[inline]
142 pub fn tx_queue_is_full(&self) -> bool {
143 self.regs.txfqs().read().tfqf()
144 }
145
146 #[inline]
147 pub fn has_pending_frame(&self, idx: usize) -> bool {
148 self.regs.txbrp().read().trp(idx)
149 }
150
151 /// Returns `Ok` when the mailbox is free or if it contains pending frame with a
152 /// lower priority (higher ID) than the identifier `id`.
153 #[inline]
154 pub fn is_available(&self, bufidx: usize, id: &embedded_can::Id) -> bool {
155 if self.has_pending_frame(bufidx) {
156 let mailbox = self.tx_buffer_element(bufidx);
157
158 let header_reg = mailbox.header.read();
159 let old_id = make_id(header_reg.id().bits(), header_reg.xtd().bits());
160
161 *id > old_id
162 } else {
163 true
164 }
165 }
166
167 /// Attempts to abort the sending of a frame that is pending in a mailbox.
168 ///
169 /// If there is no frame in the provided mailbox, or its transmission succeeds before it can be
170 /// aborted, this function has no effect and returns `false`.
171 ///
172 /// If there is a frame in the provided mailbox, and it is canceled successfully, this function
173 /// returns `true`.
174 #[inline]
175 pub fn abort(&self, bufidx: usize) -> bool {
176 let can = self.regs;
177
178 // Check if there is a request pending to abort
179 if self.has_pending_frame(bufidx) {
180 // Abort Request
181 can.txbcr().write(|w| w.set_cr(bufidx, true));
182
183 // Wait for the abort request to be finished.
184 loop {
185 if can.txbcf().read().cf(bufidx) {
186 // Return false when a transmission has occured
187 break can.txbto().read().to(bufidx) == false;
188 }
189 }
190 } else {
191 false
192 }
193 }
194
195 #[inline]
196 //fn abort_pending_mailbox<PTX, R>(&mut self, idx: Mailbox, pending: PTX) -> Option<R>
197 pub fn abort_pending_mailbox(&self, bufidx: usize) -> Option<ClassicFrame>
198//where
199 // PTX: FnOnce(Mailbox, TxFrameHeader, &[u32]) -> R,
200 {
201 if self.abort(bufidx) {
202 let mailbox = self.tx_buffer_element(bufidx);
203
204 let header_reg = mailbox.header.read();
205 let id = make_id(header_reg.id().bits(), header_reg.xtd().bits());
206
207 let len = match header_reg.to_data_length() {
208 DataLength::Fdcan(len) => len,
209 DataLength::Classic(len) => len,
210 };
211 if len as usize > ClassicFrame::MAX_DATA_LEN {
212 return None;
213 }
214
215 //let tx_ram = self.tx_msg_ram();
216 let mut data = [0u8; 64];
217 data_from_tx_buffer(&mut data, mailbox, len as usize);
218
219 let cd = ClassicData::new(&data).unwrap();
220 Some(ClassicFrame::new(Header::new(id, len, header_reg.rtr().bit()), cd))
221 } else {
222 // Abort request failed because the frame was already sent (or being sent) on
223 // the bus. All mailboxes are now free. This can happen for small prescaler
224 // values (e.g. 1MBit/s bit timing with a source clock of 8MHz) or when an ISR
225 // has preempted the execution.
226 None
227 }
228 }
229
230 #[inline]
231 //fn abort_pending_mailbox<PTX, R>(&mut self, idx: Mailbox, pending: PTX) -> Option<R>
232 pub fn abort_pending_fd_mailbox(&self, bufidx: usize) -> Option<FdFrame>
233//where
234 // PTX: FnOnce(Mailbox, TxFrameHeader, &[u32]) -> R,
235 {
236 if self.abort(bufidx) {
237 let mailbox = self.tx_buffer_element(bufidx);
238
239 let header_reg = mailbox.header.read();
240 let id = make_id(header_reg.id().bits(), header_reg.xtd().bits());
241
242 let len = match header_reg.to_data_length() {
243 DataLength::Fdcan(len) => len,
244 DataLength::Classic(len) => len,
245 };
246 if len as usize > FdFrame::MAX_DATA_LEN {
247 return None;
248 }
249
250 //let tx_ram = self.tx_msg_ram();
251 let mut data = [0u8; 64];
252 data_from_tx_buffer(&mut data, mailbox, len as usize);
253
254 let cd = FdData::new(&data).unwrap();
255
256 let header = if header_reg.fdf().frame_format() == FrameFormat::Fdcan {
257 Header::new_fd(id, len, header_reg.rtr().bit(), header_reg.brs().bit())
258 } else {
259 Header::new(id, len, header_reg.rtr().bit())
260 };
261
262 Some(FdFrame::new(header, cd))
263 } else {
264 // Abort request failed because the frame was already sent (or being sent) on
265 // the bus. All mailboxes are now free. This can happen for small prescaler
266 // values (e.g. 1MBit/s bit timing with a source clock of 8MHz) or when an ISR
267 // has preempted the execution.
268 None
269 }
270 }
271
272 /// As Transmit, but if there is a pending frame, `pending` will be called so that the frame can
273 /// be preserved.
274 //pub fn transmit_preserve<PTX, P>(
275 pub fn write_classic(&self, frame: &ClassicFrame) -> nb::Result<Option<ClassicFrame>, Infallible> {
276 let queue_is_full = self.tx_queue_is_full();
277
278 let id = frame.header().id();
279
280 // If the queue is full,
281 // Discard the first slot with a lower priority message
282 let (idx, pending_frame) = if queue_is_full {
283 if self.is_available(0, id) {
284 (0, self.abort_pending_mailbox(0))
285 } else if self.is_available(1, id) {
286 (1, self.abort_pending_mailbox(1))
287 } else if self.is_available(2, id) {
288 (2, self.abort_pending_mailbox(2))
289 } else {
290 // For now we bail when there is no lower priority slot available
291 // Can this lead to priority inversion?
292 return Err(nb::Error::WouldBlock);
293 }
294 } else {
295 // Read the Write Pointer
296 let idx = self.regs.txfqs().read().tfqpi();
297
298 (idx, None)
299 };
300
301 self.put_tx_frame(idx as usize, frame.header(), frame.data());
302
303 Ok(pending_frame)
304 }
305
306 /// As Transmit, but if there is a pending frame, `pending` will be called so that the frame can
307 /// be preserved.
308 //pub fn transmit_preserve<PTX, P>(
309 pub fn write_fd(&self, frame: &FdFrame) -> nb::Result<Option<FdFrame>, Infallible> {
310 let queue_is_full = self.tx_queue_is_full();
311
312 let id = frame.header().id();
313
314 // If the queue is full,
315 // Discard the first slot with a lower priority message
316 let (idx, pending_frame) = if queue_is_full {
317 if self.is_available(0, id) {
318 (0, self.abort_pending_fd_mailbox(0))
319 } else if self.is_available(1, id) {
320 (1, self.abort_pending_fd_mailbox(1))
321 } else if self.is_available(2, id) {
322 (2, self.abort_pending_fd_mailbox(2))
323 } else {
324 // For now we bail when there is no lower priority slot available
325 // Can this lead to priority inversion?
326 return Err(nb::Error::WouldBlock);
327 }
328 } else {
329 // Read the Write Pointer
330 let idx = self.regs.txfqs().read().tfqpi();
331
332 (idx, None)
333 };
334
335 self.put_tx_frame(idx as usize, frame.header(), frame.data());
336
337 Ok(pending_frame)
338 }
339
340 #[inline]
341 fn reset_msg_ram(&mut self) {
342 self.msg_ram_mut().reset();
343 }
344
345 #[inline]
346 fn enter_init_mode(&mut self) {
347 self.regs.cccr().modify(|w| w.set_init(true));
348 while false == self.regs.cccr().read().init() {}
349 self.regs.cccr().modify(|w| w.set_cce(true));
350 }
351
352 /// Enables or disables loopback mode: Internally connects the TX and RX
353 /// signals together.
354 #[inline]
355 fn set_loopback_mode(&mut self, mode: LoopbackMode) {
356 let (test, mon, lbck) = match mode {
357 LoopbackMode::None => (false, false, false),
358 LoopbackMode::Internal => (true, true, true),
359 LoopbackMode::External => (true, false, true),
360 };
361
362 self.set_test_mode(test);
363 self.set_bus_monitoring_mode(mon);
364
365 self.regs.test().modify(|w| w.set_lbck(lbck));
366 }
367
368 /// Enables or disables silent mode: Disconnects the TX signal from the pin.
369 #[inline]
370 fn set_bus_monitoring_mode(&mut self, enabled: bool) {
371 self.regs.cccr().modify(|w| w.set_mon(enabled));
372 }
373
374 #[inline]
375 fn set_restricted_operations(&mut self, enabled: bool) {
376 self.regs.cccr().modify(|w| w.set_asm(enabled));
377 }
378
379 #[inline]
380 fn set_normal_operations(&mut self, _enabled: bool) {
381 self.set_loopback_mode(LoopbackMode::None);
382 }
383
384 #[inline]
385 fn set_test_mode(&mut self, enabled: bool) {
386 self.regs.cccr().modify(|w| w.set_test(enabled));
387 }
388
389 #[inline]
390 fn set_power_down_mode(&mut self, enabled: bool) {
391 self.regs.cccr().modify(|w| w.set_csr(enabled));
392 while self.regs.cccr().read().csa() != enabled {}
393 }
394
395 /// Moves out of PoweredDownMode and into ConfigMode
396 #[inline]
397 pub fn into_config_mode(mut self, _config: FdCanConfig) {
398 self.set_power_down_mode(false);
399 self.enter_init_mode();
400
401 self.reset_msg_ram();
402
403 // check the FDCAN core matches our expections
404 assert!(
405 self.regs.crel().read().rel() == 3,
406 "Expected FDCAN core major release 3"
407 );
408 assert!(
409 self.regs.endn().read().etv() == 0x87654321_u32,
410 "Error reading endianness test value from FDCAN core"
411 );
412
413 // Framework specific settings are set here
414
415 // set TxBuffer to Queue Mode
416 self.regs.txbc().write(|w| w.set_tfqm(true));
417
418 // set standard filters list size to 28
419 // set extended filters list size to 8
420 // REQUIRED: we use the memory map as if these settings are set
421 // instead of re-calculating them.
422 #[cfg(not(stm32h7))]
423 {
424 self.regs.rxgfc().modify(|w| {
425 w.set_lss(crate::can::fd::message_ram::STANDARD_FILTER_MAX);
426 w.set_lse(crate::can::fd::message_ram::EXTENDED_FILTER_MAX);
427 });
428 }
429 #[cfg(stm32h7)]
430 {
431 self.regs
432 .sidfc()
433 .modify(|w| w.set_lss(crate::can::fd::message_ram::STANDARD_FILTER_MAX));
434 self.regs
435 .xidfc()
436 .modify(|w| w.set_lse(crate::can::fd::message_ram::EXTENDED_FILTER_MAX));
437 }
438
439 /*
440 for fid in 0..crate::can::message_ram::STANDARD_FILTER_MAX {
441 self.set_standard_filter((fid as u8).into(), StandardFilter::disable());
442 }
443 for fid in 0..Ecrate::can::message_ram::XTENDED_FILTER_MAX {
444 self.set_extended_filter(fid.into(), ExtendedFilter::disable());
445 }
446 */
447 }
448
449 /// Disables the CAN interface and returns back the raw peripheral it was created from.
450 #[inline]
451 pub fn free(mut self) {
452 //self.disable_interrupts(Interrupts::all());
453
454 //TODO check this!
455 self.enter_init_mode();
456 self.set_power_down_mode(true);
457 //self.control.instance
458 }
459
460 /// Applies the settings of a new FdCanConfig See [`FdCanConfig`]
461 #[inline]
462 pub fn apply_config(&mut self, config: FdCanConfig) {
463 self.set_data_bit_timing(config.dbtr);
464 self.set_nominal_bit_timing(config.nbtr);
465 self.set_automatic_retransmit(config.automatic_retransmit);
466 self.set_transmit_pause(config.transmit_pause);
467 self.set_frame_transmit(config.frame_transmit);
468 //self.set_interrupt_line_config(config.interrupt_line_config);
469 self.set_non_iso_mode(config.non_iso_mode);
470 self.set_edge_filtering(config.edge_filtering);
471 self.set_protocol_exception_handling(config.protocol_exception_handling);
472 self.set_global_filter(config.global_filter);
473 }
474
475 #[inline]
476 fn leave_init_mode(&mut self, config: FdCanConfig) {
477 self.apply_config(config);
478
479 self.regs.cccr().modify(|w| w.set_cce(false));
480 self.regs.cccr().modify(|w| w.set_init(false));
481 while self.regs.cccr().read().init() == true {}
482 }
483
484 /// Moves out of ConfigMode and into specified mode
485 #[inline]
486 pub fn into_mode(mut self, config: FdCanConfig, mode: crate::can::_version::FdcanOperatingMode) {
487 match mode {
488 crate::can::FdcanOperatingMode::InternalLoopbackMode => self.set_loopback_mode(LoopbackMode::Internal),
489 crate::can::FdcanOperatingMode::ExternalLoopbackMode => self.set_loopback_mode(LoopbackMode::External),
490 crate::can::FdcanOperatingMode::NormalOperationMode => self.set_normal_operations(true),
491 crate::can::FdcanOperatingMode::RestrictedOperationMode => self.set_restricted_operations(true),
492 crate::can::FdcanOperatingMode::BusMonitoringMode => self.set_bus_monitoring_mode(true),
493 }
494 self.leave_init_mode(config);
495 }
496
497 /// Moves out of ConfigMode and into InternalLoopbackMode
498 #[inline]
499 pub fn into_internal_loopback(mut self, config: FdCanConfig) {
500 self.set_loopback_mode(LoopbackMode::Internal);
501 self.leave_init_mode(config);
502 }
503
504 /// Moves out of ConfigMode and into ExternalLoopbackMode
505 #[inline]
506 pub fn into_external_loopback(mut self, config: FdCanConfig) {
507 self.set_loopback_mode(LoopbackMode::External);
508 self.leave_init_mode(config);
509 }
510
511 /// Moves out of ConfigMode and into RestrictedOperationMode
512 #[inline]
513 pub fn into_restricted(mut self, config: FdCanConfig) {
514 self.set_restricted_operations(true);
515 self.leave_init_mode(config);
516 }
517
518 /// Moves out of ConfigMode and into NormalOperationMode
519 #[inline]
520 pub fn into_normal(mut self, config: FdCanConfig) {
521 self.set_normal_operations(true);
522 self.leave_init_mode(config);
523 }
524
525 /// Moves out of ConfigMode and into BusMonitoringMode
526 #[inline]
527 pub fn into_bus_monitoring(mut self, config: FdCanConfig) {
528 self.set_bus_monitoring_mode(true);
529 self.leave_init_mode(config);
530 }
531
532 /// Moves out of ConfigMode and into Testmode
533 #[inline]
534 pub fn into_test_mode(mut self, config: FdCanConfig) {
535 self.set_test_mode(true);
536 self.leave_init_mode(config);
537 }
538
539 /// Moves out of ConfigMode and into PoweredDownmode
540 #[inline]
541 pub fn into_powered_down(mut self, config: FdCanConfig) {
542 self.set_power_down_mode(true);
543 self.leave_init_mode(config);
544 }
545
546 /// Configures the bit timings.
547 ///
548 /// You can use <http://www.bittiming.can-wiki.info/> to calculate the `btr` parameter. Enter
549 /// parameters as follows:
550 ///
551 /// - *Clock Rate*: The input clock speed to the CAN peripheral (*not* the CPU clock speed).
552 /// This is the clock rate of the peripheral bus the CAN peripheral is attached to (eg. APB1).
553 /// - *Sample Point*: Should normally be left at the default value of 87.5%.
554 /// - *SJW*: Should normally be left at the default value of 1.
555 ///
556 /// Then copy the `CAN_BUS_TIME` register value from the table and pass it as the `btr`
557 /// parameter to this method.
558 #[inline]
559 pub fn set_nominal_bit_timing(&mut self, btr: NominalBitTiming) {
560 //self.control.config.nbtr = btr;
561
562 self.regs.nbtp().write(|w| {
563 w.set_nbrp(btr.nbrp() - 1);
564 w.set_ntseg1(btr.ntseg1() - 1);
565 w.set_ntseg2(btr.ntseg2() - 1);
566 w.set_nsjw(btr.nsjw() - 1);
567 });
568 }
569
570 /// Configures the data bit timings for the FdCan Variable Bitrates.
571 /// This is not used when frame_transmit is set to anything other than AllowFdCanAndBRS.
572 #[inline]
573 pub fn set_data_bit_timing(&mut self, btr: DataBitTiming) {
574 //self.control.config.dbtr = btr;
575
576 self.regs.dbtp().write(|w| {
577 w.set_dbrp(btr.dbrp() - 1);
578 w.set_dtseg1(btr.dtseg1() - 1);
579 w.set_dtseg2(btr.dtseg2() - 1);
580 w.set_dsjw(btr.dsjw() - 1);
581 });
582 }
583
584 /// Enables or disables automatic retransmission of messages
585 ///
586 /// If this is enabled, the CAN peripheral will automatically try to retransmit each frame
587 /// util it can be sent. Otherwise, it will try only once to send each frame.
588 ///
589 /// Automatic retransmission is enabled by default.
590 #[inline]
591 pub fn set_automatic_retransmit(&mut self, enabled: bool) {
592 self.regs.cccr().modify(|w| w.set_dar(!enabled));
593 //self.control.config.automatic_retransmit = enabled;
594 }
595
596 /// Configures the transmit pause feature. See
597 /// [`FdCanConfig::set_transmit_pause`]
598 #[inline]
599 pub fn set_transmit_pause(&mut self, enabled: bool) {
600 self.regs.cccr().modify(|w| w.set_txp(!enabled));
601 //self.control.config.transmit_pause = enabled;
602 }
603
604 /// Configures non-iso mode. See [`FdCanConfig::set_non_iso_mode`]
605 #[inline]
606 pub fn set_non_iso_mode(&mut self, enabled: bool) {
607 self.regs.cccr().modify(|w| w.set_niso(enabled));
608 //self.control.config.non_iso_mode = enabled;
609 }
610
611 /// Configures edge filtering. See [`FdCanConfig::set_edge_filtering`]
612 #[inline]
613 pub fn set_edge_filtering(&mut self, enabled: bool) {
614 self.regs.cccr().modify(|w| w.set_efbi(enabled));
615 //self.control.config.edge_filtering = enabled;
616 }
617
618 /// Configures frame transmission mode. See
619 /// [`FdCanConfig::set_frame_transmit`]
620 #[inline]
621 pub fn set_frame_transmit(&mut self, fts: FrameTransmissionConfig) {
622 let (fdoe, brse) = match fts {
623 FrameTransmissionConfig::ClassicCanOnly => (false, false),
624 FrameTransmissionConfig::AllowFdCan => (true, false),
625 FrameTransmissionConfig::AllowFdCanAndBRS => (true, true),
626 };
627
628 self.regs.cccr().modify(|w| {
629 w.set_fdoe(fdoe);
630 #[cfg(stm32h7)]
631 w.set_bse(brse);
632 #[cfg(not(stm32h7))]
633 w.set_brse(brse);
634 });
635
636 //self.control.config.frame_transmit = fts;
637 }
638
639 /// Sets the protocol exception handling on/off
640 #[inline]
641 pub fn set_protocol_exception_handling(&mut self, enabled: bool) {
642 self.regs.cccr().modify(|w| w.set_pxhd(!enabled));
643
644 //self.control.config.protocol_exception_handling = enabled;
645 }
646
647 /// Configures and resets the timestamp counter
648 #[inline]
649 pub fn set_timestamp_counter_source(&mut self, select: TimestampSource) {
650 #[cfg(stm32h7)]
651 let (tcp, tss) = match select {
652 TimestampSource::None => (0, 0),
653 TimestampSource::Prescaler(p) => (p as u8, 1),
654 TimestampSource::FromTIM3 => (0, 2),
655 };
656
657 #[cfg(not(stm32h7))]
658 let (tcp, tss) = match select {
659 TimestampSource::None => (0, stm32_metapac::can::vals::Tss::ZERO),
660 TimestampSource::Prescaler(p) => (p as u8, stm32_metapac::can::vals::Tss::INCREMENT),
661 TimestampSource::FromTIM3 => (0, stm32_metapac::can::vals::Tss::EXTERNAL),
662 };
663
664 self.regs.tscc().write(|w| {
665 w.set_tcp(tcp);
666 w.set_tss(tss);
667 });
668
669 //self.control.config.timestamp_source = select;
670 }
671
672 #[cfg(not(stm32h7))]
673 /// Configures the global filter settings
674 #[inline]
675 pub fn set_global_filter(&mut self, filter: GlobalFilter) {
676 let anfs = match filter.handle_standard_frames {
677 crate::can::fd::config::NonMatchingFilter::IntoRxFifo0 => stm32_metapac::can::vals::Anfs::ACCEPT_FIFO_0,
678 crate::can::fd::config::NonMatchingFilter::IntoRxFifo1 => stm32_metapac::can::vals::Anfs::ACCEPT_FIFO_1,
679 crate::can::fd::config::NonMatchingFilter::Reject => stm32_metapac::can::vals::Anfs::REJECT,
680 };
681 let anfe = match filter.handle_extended_frames {
682 crate::can::fd::config::NonMatchingFilter::IntoRxFifo0 => stm32_metapac::can::vals::Anfe::ACCEPT_FIFO_0,
683 crate::can::fd::config::NonMatchingFilter::IntoRxFifo1 => stm32_metapac::can::vals::Anfe::ACCEPT_FIFO_1,
684 crate::can::fd::config::NonMatchingFilter::Reject => stm32_metapac::can::vals::Anfe::REJECT,
685 };
686
687 self.regs.rxgfc().modify(|w| {
688 w.set_anfs(anfs);
689 w.set_anfe(anfe);
690 w.set_rrfs(filter.reject_remote_standard_frames);
691 w.set_rrfe(filter.reject_remote_extended_frames);
692 });
693 }
694
695 #[cfg(stm32h7)]
696 /// Configures the global filter settings
697 #[inline]
698 pub fn set_global_filter(&mut self, filter: GlobalFilter) {
699 let anfs = match filter.handle_standard_frames {
700 crate::can::fd::config::NonMatchingFilter::IntoRxFifo0 => 0,
701 crate::can::fd::config::NonMatchingFilter::IntoRxFifo1 => 1,
702 crate::can::fd::config::NonMatchingFilter::Reject => 2,
703 };
704
705 let anfe = match filter.handle_extended_frames {
706 crate::can::fd::config::NonMatchingFilter::IntoRxFifo0 => 0,
707 crate::can::fd::config::NonMatchingFilter::IntoRxFifo1 => 1,
708 crate::can::fd::config::NonMatchingFilter::Reject => 2,
709 };
710
711 self.regs.gfc().modify(|w| {
712 w.set_anfs(anfs);
713 w.set_anfe(anfe);
714 w.set_rrfs(filter.reject_remote_standard_frames);
715 w.set_rrfe(filter.reject_remote_extended_frames);
716 });
717 }
718}
719
720fn make_id(id: u32, extended: bool) -> embedded_can::Id {
721 if extended {
722 embedded_can::Id::from(unsafe { embedded_can::ExtendedId::new_unchecked(id & 0x1FFFFFFF) })
723 } else {
724 embedded_can::Id::from(unsafe { embedded_can::StandardId::new_unchecked((id & 0x000007FF) as u16) })
725 }
726}
727
728fn put_tx_header(mailbox: &mut TxBufferElement, header: &Header) {
729 let (id, id_type) = match header.id() {
730 embedded_can::Id::Standard(id) => (id.as_raw() as u32, IdType::StandardId),
731 embedded_can::Id::Extended(id) => (id.as_raw() as u32, IdType::ExtendedId),
732 };
733
734 // Use FDCAN only for DLC > 8. FDCAN users can revise this if required.
735 let frame_format = if header.len() > 8 || header.fdcan() {
736 FrameFormat::Fdcan
737 } else {
738 FrameFormat::Classic
739 };
740 let brs = header.len() > 8 || header.bit_rate_switching();
741
742 mailbox.header.write(|w| {
743 unsafe { w.id().bits(id) }
744 .rtr()
745 .bit(header.len() == 0 && header.rtr())
746 .xtd()
747 .set_id_type(id_type)
748 .set_len(DataLength::new(header.len(), frame_format))
749 .set_event(Event::NoEvent)
750 .fdf()
751 .set_format(frame_format)
752 .brs()
753 .bit(brs)
754 //esi.set_error_indicator(//TODO//)
755 });
756}
757
758fn put_tx_data(mailbox: &mut TxBufferElement, buffer: &[u8]) {
759 let mut lbuffer = [0_u32; 16];
760 let len = buffer.len();
761 let data = unsafe { slice::from_raw_parts_mut(lbuffer.as_mut_ptr() as *mut u8, len) };
762 data[..len].copy_from_slice(&buffer[..len]);
763 let data_len = ((len) + 3) / 4;
764 for (register, byte) in mailbox.data.iter_mut().zip(lbuffer[..data_len].iter()) {
765 unsafe { register.write(*byte) };
766 }
767}
768
769fn data_from_fifo(buffer: &mut [u8], mailbox: &RxFifoElement, len: usize) {
770 for (i, register) in mailbox.data.iter().enumerate() {
771 let register_value = register.read();
772 let register_bytes = unsafe { slice::from_raw_parts(&register_value as *const u32 as *const u8, 4) };
773 let num_bytes = (len) - i * 4;
774 if num_bytes <= 4 {
775 buffer[i * 4..i * 4 + num_bytes].copy_from_slice(&register_bytes[..num_bytes]);
776 break;
777 }
778 buffer[i * 4..(i + 1) * 4].copy_from_slice(register_bytes);
779 }
780}
781
782fn data_from_tx_buffer(buffer: &mut [u8], mailbox: &TxBufferElement, len: usize) {
783 for (i, register) in mailbox.data.iter().enumerate() {
784 let register_value = register.read();
785 let register_bytes = unsafe { slice::from_raw_parts(&register_value as *const u32 as *const u8, 4) };
786 let num_bytes = (len) - i * 4;
787 if num_bytes <= 4 {
788 buffer[i * 4..i * 4 + num_bytes].copy_from_slice(&register_bytes[..num_bytes]);
789 break;
790 }
791 buffer[i * 4..(i + 1) * 4].copy_from_slice(register_bytes);
792 }
793}
794
795impl From<&RxFifoElement> for ClassicFrame {
796 fn from(mailbox: &RxFifoElement) -> Self {
797 let header_reg = mailbox.header.read();
798
799 let id = make_id(header_reg.id().bits(), header_reg.xtd().bits());
800 let dlc = header_reg.to_data_length().len();
801 let len = dlc as usize;
802
803 let mut buffer: [u8; 64] = [0; 64];
804 data_from_fifo(&mut buffer, mailbox, len);
805 let data = ClassicData::new(&buffer[0..len]);
806 let header = Header::new(id, dlc, header_reg.rtr().bits());
807 ClassicFrame::new(header, data.unwrap())
808 }
809}
810
811fn extract_frame(mailbox: &RxFifoElement, buffer: &mut [u8]) -> Option<(Header, u16)> {
812 let header_reg = mailbox.header.read();
813
814 let id = make_id(header_reg.id().bits(), header_reg.xtd().bits());
815 let dlc = header_reg.to_data_length().len();
816 let len = dlc as usize;
817 let timestamp = header_reg.txts().bits;
818 if len > buffer.len() {
819 return None;
820 }
821 data_from_fifo(buffer, mailbox, len);
822 let header = if header_reg.fdf().bits {
823 Header::new_fd(id, dlc, header_reg.rtr().bits(), header_reg.brs().bits())
824 } else {
825 Header::new(id, dlc, header_reg.rtr().bits())
826 };
827 Some((header, timestamp))
828}
diff --git a/embassy-stm32/src/can/fdcan.rs b/embassy-stm32/src/can/fdcan.rs
index faf4af73f..f1f6f935e 100644
--- a/embassy-stm32/src/can/fdcan.rs
+++ b/embassy-stm32/src/can/fdcan.rs
@@ -1,16 +1,16 @@
1#[allow(unused_variables)]
1use core::future::poll_fn; 2use core::future::poll_fn;
2use core::marker::PhantomData; 3use core::marker::PhantomData;
3use core::ops::{Deref, DerefMut};
4use core::task::Poll; 4use core::task::Poll;
5 5
6use cfg_if::cfg_if; 6pub mod fd;
7use embassy_hal_internal::{into_ref, PeripheralRef}; 7use embassy_hal_internal::{into_ref, PeripheralRef};
8pub use fdcan::frame::{FrameFormat, RxFrameInfo, TxFrameHeader}; 8use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
9pub use fdcan::id::{ExtendedId, Id, StandardId}; 9use embassy_sync::channel::Channel;
10use fdcan::message_ram::RegisterBlock; 10use fd::config::*;
11use fdcan::{self, LastErrorCode}; 11use fd::filter::*;
12pub use fdcan::{config, filter};
13 12
13use crate::can::fd::peripheral::Registers;
14use crate::gpio::sealed::AFType; 14use crate::gpio::sealed::AFType;
15use crate::interrupt::typelevel::Interrupt; 15use crate::interrupt::typelevel::Interrupt;
16use crate::rcc::RccPeripheral; 16use crate::rcc::RccPeripheral;
@@ -20,127 +20,14 @@ pub mod enums;
20use enums::*; 20use enums::*;
21pub mod util; 21pub mod util;
22 22
23/// CAN Frame returned by read 23pub mod frame;
24pub struct RxFrame { 24use frame::*;
25 /// CAN Header info: frame ID, data length and other meta
26 pub header: RxFrameInfo,
27 /// CAN(0-8 bytes) or FDCAN(0-64 bytes) Frame data
28 pub data: Data,
29 /// Reception time.
30 #[cfg(feature = "time")]
31 pub timestamp: embassy_time::Instant,
32}
33
34/// CAN frame used for write
35pub struct TxFrame {
36 /// CAN Header info: frame ID, data length and other meta
37 pub header: TxFrameHeader,
38 /// CAN(0-8 bytes) or FDCAN(0-64 bytes) Frame data
39 pub data: Data,
40}
41
42impl TxFrame {
43 /// Create new TX frame from header and data
44 pub fn new(header: TxFrameHeader, data: &[u8]) -> Option<Self> {
45 if data.len() < header.len as usize {
46 return None;
47 }
48
49 let Some(data) = Data::new(data) else { return None };
50
51 Some(TxFrame { header, data })
52 }
53
54 fn from_preserved(header: TxFrameHeader, data32: &[u32]) -> Option<Self> {
55 let mut data = [0u8; 64];
56
57 for i in 0..data32.len() {
58 data[4 * i..][..4].copy_from_slice(&data32[i].to_le_bytes());
59 }
60
61 let Some(data) = Data::new(&data) else { return None };
62
63 Some(TxFrame { header, data })
64 }
65
66 /// Access frame data. Slice length will match header.
67 pub fn data(&self) -> &[u8] {
68 &self.data.bytes[..(self.header.len as usize)]
69 }
70}
71
72impl RxFrame {
73 pub(crate) fn new(
74 header: RxFrameInfo,
75 data: &[u8],
76 #[cfg(feature = "time")] timestamp: embassy_time::Instant,
77 ) -> Self {
78 let data = Data::new(&data).unwrap_or_else(|| Data::empty());
79 25
80 RxFrame { 26#[cfg(feature = "time")]
81 header, 27type Timestamp = embassy_time::Instant;
82 data,
83 #[cfg(feature = "time")]
84 timestamp,
85 }
86 }
87
88 /// Access frame data. Slice length will match header.
89 pub fn data(&self) -> &[u8] {
90 &self.data.bytes[..(self.header.len as usize)]
91 }
92}
93
94/// Payload of a (FD)CAN data frame.
95///
96/// Contains 0 to 64 Bytes of data.
97#[derive(Debug, Copy, Clone)]
98pub struct Data {
99 pub(crate) bytes: [u8; 64],
100}
101
102impl Data {
103 /// Creates a data payload from a raw byte slice.
104 ///
105 /// Returns `None` if `data` is more than 64 bytes (which is the maximum) or
106 /// cannot be represented with an FDCAN DLC.
107 pub fn new(data: &[u8]) -> Option<Self> {
108 if !Data::is_valid_len(data.len()) {
109 return None;
110 }
111
112 let mut bytes = [0; 64];
113 bytes[..data.len()].copy_from_slice(data);
114
115 Some(Self { bytes })
116 }
117
118 /// Raw read access to data.
119 pub fn raw(&self) -> &[u8] {
120 &self.bytes
121 }
122 28
123 /// Checks if the length can be encoded in FDCAN DLC field. 29#[cfg(not(feature = "time"))]
124 pub const fn is_valid_len(len: usize) -> bool { 30type Timestamp = u16;
125 match len {
126 0..=8 => true,
127 12 => true,
128 16 => true,
129 20 => true,
130 24 => true,
131 32 => true,
132 48 => true,
133 64 => true,
134 _ => false,
135 }
136 }
137
138 /// Creates an empty data payload containing 0 bytes.
139 #[inline]
140 pub const fn empty() -> Self {
141 Self { bytes: [0; 64] }
142 }
143}
144 31
145/// Interrupt handler channel 0. 32/// Interrupt handler channel 0.
146pub struct IT0InterruptHandler<T: Instance> { 33pub struct IT0InterruptHandler<T: Instance> {
@@ -154,14 +41,37 @@ impl<T: Instance> interrupt::typelevel::Handler<T::IT0Interrupt> for IT0Interrup
154 41
155 let ir = regs.ir().read(); 42 let ir = regs.ir().read();
156 43
157 if ir.tc() { 44 {
158 regs.ir().write(|w| w.set_tc(true)); 45 if ir.tc() {
159 T::state().tx_waker.wake(); 46 regs.ir().write(|w| w.set_tc(true));
160 } 47 }
48 if ir.tefn() {
49 regs.ir().write(|w| w.set_tefn(true));
50 }
161 51
162 if ir.tefn() { 52 match &T::state().tx_mode {
163 regs.ir().write(|w| w.set_tefn(true)); 53 sealed::TxMode::NonBuffered(waker) => waker.wake(),
164 T::state().tx_waker.wake(); 54 sealed::TxMode::ClassicBuffered(buf) => {
55 if !T::registers().tx_queue_is_full() {
56 match buf.tx_receiver.try_receive() {
57 Ok(frame) => {
58 _ = T::registers().write_classic(&frame);
59 }
60 Err(_) => {}
61 }
62 }
63 }
64 sealed::TxMode::FdBuffered(buf) => {
65 if !T::registers().tx_queue_is_full() {
66 match buf.tx_receiver.try_receive() {
67 Ok(frame) => {
68 _ = T::registers().write_fd(&frame);
69 }
70 Err(_) => {}
71 }
72 }
73 }
74 }
165 } 75 }
166 76
167 if ir.ped() || ir.pea() { 77 if ir.ped() || ir.pea() {
@@ -172,13 +82,11 @@ impl<T: Instance> interrupt::typelevel::Handler<T::IT0Interrupt> for IT0Interrup
172 } 82 }
173 83
174 if ir.rfn(0) { 84 if ir.rfn(0) {
175 regs.ir().write(|w| w.set_rfn(0, true)); 85 T::state().rx_mode.on_interrupt::<T>(0);
176 T::state().rx_waker.wake();
177 } 86 }
178 87
179 if ir.rfn(1) { 88 if ir.rfn(1) {
180 regs.ir().write(|w| w.set_rfn(1, true)); 89 T::state().rx_mode.on_interrupt::<T>(1);
181 T::state().rx_waker.wake();
182 } 90 }
183 } 91 }
184} 92}
@@ -192,44 +100,56 @@ impl<T: Instance> interrupt::typelevel::Handler<T::IT1Interrupt> for IT1Interrup
192 unsafe fn on_interrupt() {} 100 unsafe fn on_interrupt() {}
193} 101}
194 102
195impl BusError { 103#[derive(Debug, Copy, Clone, Eq, PartialEq)]
196 fn try_from(lec: LastErrorCode) -> Option<BusError> { 104#[cfg_attr(feature = "defmt", derive(defmt::Format))]
197 match lec { 105/// Different operating modes
198 LastErrorCode::AckError => Some(BusError::Acknowledge), 106pub enum FdcanOperatingMode {
199 // `0` data bit encodes a dominant state. `1` data bit is recessive. 107 //PoweredDownMode,
200 // Bit0Error: During transmit, the node wanted to send a 0 but monitored a 1 108 //ConfigMode,
201 LastErrorCode::Bit0Error => Some(BusError::BitRecessive), 109 /// This mode can be used for a “Hot Selftest”, meaning the FDCAN can be tested without
202 LastErrorCode::Bit1Error => Some(BusError::BitDominant), 110 /// affecting a running CAN system connected to the FDCAN_TX and FDCAN_RX pins. In this
203 LastErrorCode::CRCError => Some(BusError::Crc), 111 /// mode, FDCAN_RX pin is disconnected from the FDCAN and FDCAN_TX pin is held
204 LastErrorCode::FormError => Some(BusError::Form), 112 /// recessive.
205 LastErrorCode::StuffError => Some(BusError::Stuff), 113 InternalLoopbackMode,
206 _ => None, 114 /// This mode is provided for hardware self-test. To be independent from external stimulation,
207 } 115 /// the FDCAN ignores acknowledge errors (recessive bit sampled in the acknowledge slot of a
208 } 116 /// data / remote frame) in Loop Back mode. In this mode the FDCAN performs an internal
117 /// feedback from its transmit output to its receive input. The actual value of the FDCAN_RX
118 /// input pin is disregarded by the FDCAN. The transmitted messages can be monitored at the
119 /// FDCAN_TX transmit pin.
120 ExternalLoopbackMode,
121 /// The normal use of the Fdcan instance after configurations
122 NormalOperationMode,
123 /// In Restricted operation mode the node is able to receive data and remote frames and to give
124 /// acknowledge to valid frames, but it does not send data frames, remote frames, active error
125 /// frames, or overload frames. In case of an error condition or overload condition, it does not
126 /// send dominant bits, instead it waits for the occurrence of bus idle condition to resynchronize
127 /// itself to the CAN communication. The error counters for transmit and receive are frozen while
128 /// error logging (can_errors) is active. TODO: automatically enter in this mode?
129 RestrictedOperationMode,
130 /// In Bus monitoring mode (for more details refer to ISO11898-1, 10.12 Bus monitoring),
131 /// the FDCAN is able to receive valid data frames and valid remote frames, but cannot start a
132 /// transmission. In this mode, it sends only recessive bits on the CAN bus. If the FDCAN is
133 /// required to send a dominant bit (ACK bit, overload flag, active error flag), the bit is
134 /// rerouted internally so that the FDCAN can monitor it, even if the CAN bus remains in recessive
135 /// state. In Bus monitoring mode the TXBRP register is held in reset state. The Bus monitoring
136 /// mode can be used to analyze the traffic on a CAN bus without affecting it by the transmission
137 /// of dominant bits.
138 BusMonitoringMode,
139 //TestMode,
209} 140}
210 141
211/// Operating modes trait
212pub trait FdcanOperatingMode {}
213impl FdcanOperatingMode for fdcan::PoweredDownMode {}
214impl FdcanOperatingMode for fdcan::ConfigMode {}
215impl FdcanOperatingMode for fdcan::InternalLoopbackMode {}
216impl FdcanOperatingMode for fdcan::ExternalLoopbackMode {}
217impl FdcanOperatingMode for fdcan::NormalOperationMode {}
218impl FdcanOperatingMode for fdcan::RestrictedOperationMode {}
219impl FdcanOperatingMode for fdcan::BusMonitoringMode {}
220impl FdcanOperatingMode for fdcan::TestMode {}
221
222/// FDCAN Instance 142/// FDCAN Instance
223pub struct Fdcan<'d, T: Instance, M: FdcanOperatingMode> { 143pub struct FdcanConfigurator<'d, T: Instance> {
144 config: crate::can::fd::config::FdCanConfig,
224 /// Reference to internals. 145 /// Reference to internals.
225 pub can: fdcan::FdCan<FdcanInstance<'d, T>, M>, 146 instance: FdcanInstance<'d, T>,
226 ns_per_timer_tick: u64, // For FDCAN internal timer
227} 147}
228 148
229fn calc_ns_per_timer_tick<T: Instance>(mode: config::FrameTransmissionConfig) -> u64 { 149fn calc_ns_per_timer_tick<T: Instance>(mode: crate::can::fd::config::FrameTransmissionConfig) -> u64 {
230 match mode { 150 match mode {
231 // Use timestamp from Rx FIFO to adjust timestamp reported to user 151 // Use timestamp from Rx FIFO to adjust timestamp reported to user
232 config::FrameTransmissionConfig::ClassicCanOnly => { 152 crate::can::fd::config::FrameTransmissionConfig::ClassicCanOnly => {
233 let freq = T::frequency(); 153 let freq = T::frequency();
234 let prescale: u64 = 154 let prescale: u64 =
235 ({ T::regs().nbtp().read().nbrp() } + 1) as u64 * ({ T::regs().tscc().read().tcp() } + 1) as u64; 155 ({ T::regs().nbtp().read().nbrp() } + 1) as u64 * ({ T::regs().tscc().read().tcp() } + 1) as u64;
@@ -241,42 +161,7 @@ fn calc_ns_per_timer_tick<T: Instance>(mode: config::FrameTransmissionConfig) ->
241 } 161 }
242} 162}
243 163
244#[cfg(feature = "time")] 164impl<'d, T: Instance> FdcanConfigurator<'d, T> {
245fn calc_timestamp<T: Instance>(ns_per_timer_tick: u64, ts_val: u16) -> embassy_time::Instant {
246 let now_embassy = embassy_time::Instant::now();
247 if ns_per_timer_tick == 0 {
248 return now_embassy;
249 }
250 let now_can = { T::regs().tscv().read().tsc() };
251 let delta = now_can.overflowing_sub(ts_val).0 as u64;
252 let ns = ns_per_timer_tick * delta as u64;
253 now_embassy - embassy_time::Duration::from_nanos(ns)
254}
255
256fn curr_error<T: Instance>() -> Option<BusError> {
257 let err = { T::regs().psr().read() };
258 if err.bo() {
259 return Some(BusError::BusOff);
260 } else if err.ep() {
261 return Some(BusError::BusPassive);
262 } else if err.ew() {
263 return Some(BusError::BusWarning);
264 } else {
265 cfg_if! {
266 if #[cfg(stm32h7)] {
267 let lec = err.lec();
268 } else {
269 let lec = err.lec().to_bits();
270 }
271 }
272 if let Ok(err) = LastErrorCode::try_from(lec) {
273 return BusError::try_from(err);
274 }
275 }
276 None
277}
278
279impl<'d, T: Instance> Fdcan<'d, T, fdcan::ConfigMode> {
280 /// Creates a new Fdcan instance, keeping the peripheral in sleep mode. 165 /// Creates a new Fdcan instance, keeping the peripheral in sleep mode.
281 /// You must call [Fdcan::enable_non_blocking] to use the peripheral. 166 /// You must call [Fdcan::enable_non_blocking] to use the peripheral.
282 pub fn new( 167 pub fn new(
@@ -286,7 +171,7 @@ impl<'d, T: Instance> Fdcan<'d, T, fdcan::ConfigMode> {
286 _irqs: impl interrupt::typelevel::Binding<T::IT0Interrupt, IT0InterruptHandler<T>> 171 _irqs: impl interrupt::typelevel::Binding<T::IT0Interrupt, IT0InterruptHandler<T>>
287 + interrupt::typelevel::Binding<T::IT1Interrupt, IT1InterruptHandler<T>> 172 + interrupt::typelevel::Binding<T::IT1Interrupt, IT1InterruptHandler<T>>
288 + 'd, 173 + 'd,
289 ) -> Fdcan<'d, T, fdcan::ConfigMode> { 174 ) -> FdcanConfigurator<'d, T> {
290 into_ref!(peri, rx, tx); 175 into_ref!(peri, rx, tx);
291 176
292 rx.set_as_af(rx.af_num(), AFType::Input); 177 rx.set_as_af(rx.af_num(), AFType::Input);
@@ -294,11 +179,12 @@ impl<'d, T: Instance> Fdcan<'d, T, fdcan::ConfigMode> {
294 179
295 T::enable_and_reset(); 180 T::enable_and_reset();
296 181
182 let mut config = crate::can::fd::config::FdCanConfig::default();
183 T::registers().into_config_mode(config);
184
297 rx.set_as_af(rx.af_num(), AFType::Input); 185 rx.set_as_af(rx.af_num(), AFType::Input);
298 tx.set_as_af(tx.af_num(), AFType::OutputPushPull); 186 tx.set_as_af(tx.af_num(), AFType::OutputPushPull);
299 187
300 let mut can = fdcan::FdCan::new(FdcanInstance(peri)).into_config_mode();
301
302 T::configure_msg_ram(); 188 T::configure_msg_ram();
303 unsafe { 189 unsafe {
304 // Enable timestamping 190 // Enable timestamping
@@ -308,6 +194,7 @@ impl<'d, T: Instance> Fdcan<'d, T, fdcan::ConfigMode> {
308 .write(|w| w.set_tss(stm32_metapac::can::vals::Tss::INCREMENT)); 194 .write(|w| w.set_tss(stm32_metapac::can::vals::Tss::INCREMENT));
309 #[cfg(stm32h7)] 195 #[cfg(stm32h7)]
310 T::regs().tscc().write(|w| w.set_tss(0x01)); 196 T::regs().tscc().write(|w| w.set_tss(0x01));
197 config.timestamp_source = TimestampSource::Prescaler(TimestampPrescaler::_1);
311 198
312 T::IT0Interrupt::unpend(); // Not unsafe 199 T::IT0Interrupt::unpend(); // Not unsafe
313 T::IT0Interrupt::enable(); 200 T::IT0Interrupt::enable();
@@ -320,94 +207,134 @@ impl<'d, T: Instance> Fdcan<'d, T, fdcan::ConfigMode> {
320 T::regs().txbtie().write(|w| w.0 = 0xffff_ffff); 207 T::regs().txbtie().write(|w| w.0 = 0xffff_ffff);
321 } 208 }
322 209
323 can.enable_interrupt(fdcan::interrupt::Interrupt::RxFifo0NewMsg); 210 T::regs().ie().modify(|w| {
324 can.enable_interrupt(fdcan::interrupt::Interrupt::RxFifo1NewMsg); 211 w.set_rfne(0, true); // Rx Fifo 0 New Msg
325 can.enable_interrupt(fdcan::interrupt::Interrupt::TxComplete); 212 w.set_rfne(1, true); // Rx Fifo 1 New Msg
326 can.enable_interrupt_line(fdcan::interrupt::InterruptLine::_0, true); 213 w.set_tce(true); // Tx Complete
327 can.enable_interrupt_line(fdcan::interrupt::InterruptLine::_1, true); 214 });
215 T::regs().ile().modify(|w| {
216 w.set_eint0(true); // Interrupt Line 0
217 w.set_eint1(true); // Interrupt Line 1
218 });
219
220 Self {
221 config,
222 instance: FdcanInstance(peri),
223 }
224 }
225
226 /// Get configuration
227 pub fn config(&self) -> crate::can::fd::config::FdCanConfig {
228 return self.config;
229 }
328 230
329 let ns_per_timer_tick = calc_ns_per_timer_tick::<T>(can.get_config().frame_transmit); 231 /// Set configuration
330 Self { can, ns_per_timer_tick } 232 pub fn set_config(&mut self, config: crate::can::fd::config::FdCanConfig) {
233 self.config = config;
331 } 234 }
332 235
333 /// Configures the bit timings calculated from supplied bitrate. 236 /// Configures the bit timings calculated from supplied bitrate.
334 pub fn set_bitrate(&mut self, bitrate: u32) { 237 pub fn set_bitrate(&mut self, bitrate: u32) {
335 let bit_timing = util::calc_can_timings(T::frequency(), bitrate).unwrap(); 238 let bit_timing = util::calc_can_timings(T::frequency(), bitrate).unwrap();
336 self.can.set_nominal_bit_timing(config::NominalBitTiming { 239
240 let nbtr = crate::can::fd::config::NominalBitTiming {
337 sync_jump_width: bit_timing.sync_jump_width, 241 sync_jump_width: bit_timing.sync_jump_width,
338 prescaler: bit_timing.prescaler, 242 prescaler: bit_timing.prescaler,
339 seg1: bit_timing.seg1, 243 seg1: bit_timing.seg1,
340 seg2: bit_timing.seg2, 244 seg2: bit_timing.seg2,
341 }); 245 };
246 self.config = self.config.set_nominal_bit_timing(nbtr);
342 } 247 }
343}
344 248
345macro_rules! impl_transition { 249 /// Configures the bit timings for VBR data calculated from supplied bitrate. This also sets confit to allow can FD and VBR
346 ($from_mode:ident, $to_mode:ident, $name:ident, $func: ident) => { 250 pub fn set_fd_data_bitrate(&mut self, bitrate: u32, transceiver_delay_compensation: bool) {
347 impl<'d, T: Instance> Fdcan<'d, T, fdcan::$from_mode> { 251 let bit_timing = util::calc_can_timings(T::frequency(), bitrate).unwrap();
348 /// Transition from $from_mode:ident mode to $to_mode:ident mode 252 // Note, used existing calcluation for normal(non-VBR) bitrate, appears to work for 250k/1M
349 pub fn $name(self) -> Fdcan<'d, T, fdcan::$to_mode> { 253 let nbtr = crate::can::fd::config::DataBitTiming {
350 let ns_per_timer_tick = calc_ns_per_timer_tick::<T>(self.can.get_config().frame_transmit); 254 transceiver_delay_compensation,
351 Fdcan { 255 sync_jump_width: bit_timing.sync_jump_width,
352 can: self.can.$func(), 256 prescaler: bit_timing.prescaler,
353 ns_per_timer_tick, 257 seg1: bit_timing.seg1,
354 } 258 seg2: bit_timing.seg2,
355 } 259 };
260 self.config.frame_transmit = FrameTransmissionConfig::AllowFdCanAndBRS;
261 self.config = self.config.set_data_bit_timing(nbtr);
262 }
263
264 /// Set an Standard Address CAN filter into slot 'id'
265 #[inline]
266 pub fn set_standard_filter(&mut self, slot: StandardFilterSlot, filter: StandardFilter) {
267 T::registers().msg_ram_mut().filters.flssa[slot as usize].activate(filter);
268 }
269
270 /// Set an array of Standard Address CAN filters and overwrite the current set
271 pub fn set_standard_filters(&mut self, filters: &[StandardFilter; STANDARD_FILTER_MAX as usize]) {
272 for (i, f) in filters.iter().enumerate() {
273 T::registers().msg_ram_mut().filters.flssa[i].activate(*f);
356 } 274 }
357 }; 275 }
358}
359 276
360impl_transition!(PoweredDownMode, ConfigMode, into_config_mode, into_config_mode); 277 /// Set an Extended Address CAN filter into slot 'id'
361impl_transition!(InternalLoopbackMode, ConfigMode, into_config_mode, into_config_mode); 278 #[inline]
279 pub fn set_extended_filter(&mut self, slot: ExtendedFilterSlot, filter: ExtendedFilter) {
280 T::registers().msg_ram_mut().filters.flesa[slot as usize].activate(filter);
281 }
362 282
363impl_transition!(ConfigMode, NormalOperationMode, into_normal_mode, into_normal); 283 /// Set an array of Extended Address CAN filters and overwrite the current set
364impl_transition!( 284 pub fn set_extended_filters(&mut self, filters: &[ExtendedFilter; EXTENDED_FILTER_MAX as usize]) {
365 ConfigMode, 285 for (i, f) in filters.iter().enumerate() {
366 ExternalLoopbackMode, 286 T::registers().msg_ram_mut().filters.flesa[i].activate(*f);
367 into_external_loopback_mode, 287 }
368 into_external_loopback 288 }
369);
370impl_transition!(
371 ConfigMode,
372 InternalLoopbackMode,
373 into_internal_loopback_mode,
374 into_internal_loopback
375);
376 289
377impl<'d, T: Instance, M: FdcanOperatingMode> Fdcan<'d, T, M> 290 /// Start in mode.
378where 291 pub fn start(self, mode: FdcanOperatingMode) -> Fdcan<'d, T> {
379 M: fdcan::Transmit, 292 let ns_per_timer_tick = calc_ns_per_timer_tick::<T>(self.config.frame_transmit);
380 M: fdcan::Receive, 293 critical_section::with(|_| unsafe {
381{ 294 T::mut_state().ns_per_timer_tick = ns_per_timer_tick;
382 /// Queues the message to be sent but exerts backpressure. If a lower-priority 295 });
383 /// frame is dropped from the mailbox, it is returned. If no lower-priority frames 296 T::registers().into_mode(self.config, mode);
384 /// can be replaced, this call asynchronously waits for a frame to be successfully 297 let ret = Fdcan {
385 /// transmitted, then tries again. 298 config: self.config,
386 pub async fn write(&mut self, frame: &TxFrame) -> Option<TxFrame> { 299 instance: self.instance,
387 poll_fn(|cx| { 300 _mode: mode,
388 T::state().tx_waker.register(cx.waker()); 301 };
389 if let Ok(dropped) = self 302 ret
390 .can 303 }
391 .transmit_preserve(frame.header, &frame.data.bytes, &mut |_, hdr, data32| {
392 TxFrame::from_preserved(hdr, data32)
393 })
394 {
395 return Poll::Ready(dropped.flatten());
396 }
397 304
398 // Couldn't replace any lower priority frames. Need to wait for some mailboxes 305 /// Start, entering mode. Does same as start(mode)
399 // to clear. 306 pub fn into_normal_mode(self) -> Fdcan<'d, T> {
400 Poll::Pending 307 self.start(FdcanOperatingMode::NormalOperationMode)
401 })
402 .await
403 } 308 }
404 309
310 /// Start, entering mode. Does same as start(mode)
311 pub fn into_internal_loopback_mode(self) -> Fdcan<'d, T> {
312 self.start(FdcanOperatingMode::InternalLoopbackMode)
313 }
314
315 /// Start, entering mode. Does same as start(mode)
316 pub fn into_external_loopback_mode(self) -> Fdcan<'d, T> {
317 self.start(FdcanOperatingMode::ExternalLoopbackMode)
318 }
319}
320
321/// FDCAN Instance
322pub struct Fdcan<'d, T: Instance> {
323 config: crate::can::fd::config::FdCanConfig,
324 /// Reference to internals.
325 instance: FdcanInstance<'d, T>,
326 _mode: FdcanOperatingMode,
327}
328
329impl<'d, T: Instance> Fdcan<'d, T> {
405 /// Flush one of the TX mailboxes. 330 /// Flush one of the TX mailboxes.
406 pub async fn flush(&self, mb: fdcan::Mailbox) { 331 pub async fn flush(&self, idx: usize) {
407 poll_fn(|cx| { 332 poll_fn(|cx| {
408 T::state().tx_waker.register(cx.waker()); 333 T::state().tx_mode.register(cx.waker());
409 334
410 let idx: u8 = mb.into(); 335 if idx > 3 {
336 panic!("Bad mailbox");
337 }
411 let idx = 1 << idx; 338 let idx = 1 << idx;
412 if !T::regs().txbrp().read().trp(idx) { 339 if !T::regs().txbrp().read().trp(idx) {
413 return Poll::Ready(()); 340 return Poll::Ready(());
@@ -418,179 +345,454 @@ where
418 .await; 345 .await;
419 } 346 }
420 347
348 /// Queues the message to be sent but exerts backpressure. If a lower-priority
349 /// frame is dropped from the mailbox, it is returned. If no lower-priority frames
350 /// can be replaced, this call asynchronously waits for a frame to be successfully
351 /// transmitted, then tries again.
352 pub async fn write(&mut self, frame: &ClassicFrame) -> Option<ClassicFrame> {
353 T::state().tx_mode.write::<T>(frame).await
354 }
355
421 /// Returns the next received message frame 356 /// Returns the next received message frame
422 pub async fn read(&mut self) -> Result<RxFrame, BusError> { 357 pub async fn read(&mut self) -> Result<(ClassicFrame, Timestamp), BusError> {
423 poll_fn(|cx| { 358 T::state().rx_mode.read::<T>().await
424 T::state().err_waker.register(cx.waker()); 359 }
425 T::state().rx_waker.register(cx.waker()); 360
426 361 /// Queues the message to be sent but exerts backpressure. If a lower-priority
427 let mut buffer: [u8; 64] = [0; 64]; 362 /// frame is dropped from the mailbox, it is returned. If no lower-priority frames
428 if let Ok(rx) = self.can.receive0(&mut buffer) { 363 /// can be replaced, this call asynchronously waits for a frame to be successfully
429 // rx: fdcan::ReceiveOverrun<RxFrameInfo> 364 /// transmitted, then tries again.
430 // TODO: report overrun? 365 pub async fn write_fd(&mut self, frame: &FdFrame) -> Option<FdFrame> {
431 // for now we just drop it 366 T::state().tx_mode.write_fd::<T>(frame).await
432 367 }
433 let frame: RxFrame = RxFrame::new( 368
434 rx.unwrap(), 369 /// Returns the next received message frame
435 &buffer, 370 pub async fn read_fd(&mut self) -> Result<(FdFrame, Timestamp), BusError> {
436 #[cfg(feature = "time")] 371 T::state().rx_mode.read_fd::<T>().await
437 calc_timestamp::<T>(self.ns_per_timer_tick, rx.unwrap().time_stamp),
438 );
439 return Poll::Ready(Ok(frame));
440 } else if let Ok(rx) = self.can.receive1(&mut buffer) {
441 // rx: fdcan::ReceiveOverrun<RxFrameInfo>
442 // TODO: report overrun?
443 // for now we just drop it
444
445 let frame: RxFrame = RxFrame::new(
446 rx.unwrap(),
447 &buffer,
448 #[cfg(feature = "time")]
449 calc_timestamp::<T>(self.ns_per_timer_tick, rx.unwrap().time_stamp),
450 );
451 return Poll::Ready(Ok(frame));
452 } else if let Some(err) = curr_error::<T>() {
453 // TODO: this is probably wrong
454 return Poll::Ready(Err(err));
455 }
456 Poll::Pending
457 })
458 .await
459 } 372 }
460 373
461 /// Split instance into separate Tx(write) and Rx(read) portions 374 /// Split instance into separate Tx(write) and Rx(read) portions
462 pub fn split<'c>(&'c mut self) -> (FdcanTx<'c, 'd, T, M>, FdcanRx<'c, 'd, T, M>) { 375 pub fn split(self) -> (FdcanTx<'d, T>, FdcanRx<'d, T>) {
463 let (mut _control, tx, rx0, rx1) = self.can.split_by_ref();
464 ( 376 (
465 FdcanTx { _control, tx }, 377 FdcanTx {
378 config: self.config,
379 _instance: self.instance,
380 _mode: self._mode,
381 },
466 FdcanRx { 382 FdcanRx {
467 rx0, 383 _instance1: PhantomData::<T>,
468 rx1, 384 _instance2: T::regs(),
469 ns_per_timer_tick: self.ns_per_timer_tick, 385 _mode: self._mode,
470 }, 386 },
471 ) 387 )
472 } 388 }
389
390 /// Join split rx and tx portions back together
391 pub fn join(tx: FdcanTx<'d, T>, rx: FdcanRx<'d, T>) -> Self {
392 Fdcan {
393 config: tx.config,
394 //_instance2: T::regs(),
395 instance: tx._instance,
396 _mode: rx._mode,
397 }
398 }
399
400 /// Return a buffered instance of driver without CAN FD support. User must supply Buffers
401 pub fn buffered<const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize>(
402 &self,
403 tx_buf: &'static mut TxBuf<TX_BUF_SIZE>,
404 rxb: &'static mut RxBuf<RX_BUF_SIZE>,
405 ) -> BufferedCan<'d, T, TX_BUF_SIZE, RX_BUF_SIZE> {
406 BufferedCan::new(PhantomData::<T>, T::regs(), self._mode, tx_buf, rxb)
407 }
408
409 /// Return a buffered instance of driver with CAN FD support. User must supply Buffers
410 pub fn buffered_fd<const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize>(
411 &self,
412 tx_buf: &'static mut TxFdBuf<TX_BUF_SIZE>,
413 rxb: &'static mut RxFdBuf<RX_BUF_SIZE>,
414 ) -> BufferedCanFd<'d, T, TX_BUF_SIZE, RX_BUF_SIZE> {
415 BufferedCanFd::new(PhantomData::<T>, T::regs(), self._mode, tx_buf, rxb)
416 }
473} 417}
474 418
475/// FDCAN Tx only Instance 419/// User supplied buffer for RX Buffering
476pub struct FdcanTx<'c, 'd, T: Instance, M: fdcan::Transmit> { 420pub type RxBuf<const BUF_SIZE: usize> = Channel<CriticalSectionRawMutex, (ClassicFrame, Timestamp), BUF_SIZE>;
477 _control: &'c mut fdcan::FdCanControl<FdcanInstance<'d, T>, M>, 421
478 tx: &'c mut fdcan::Tx<FdcanInstance<'d, T>, M>, 422/// User supplied buffer for TX buffering
423pub type TxBuf<const BUF_SIZE: usize> = Channel<CriticalSectionRawMutex, ClassicFrame, BUF_SIZE>;
424
425/// Buffered FDCAN Instance
426pub struct BufferedCan<'d, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> {
427 _instance1: PhantomData<T>,
428 _instance2: &'d crate::pac::can::Fdcan,
429 _mode: FdcanOperatingMode,
430 tx_buf: &'static TxBuf<TX_BUF_SIZE>,
431 rx_buf: &'static RxBuf<RX_BUF_SIZE>,
479} 432}
480 433
481impl<'c, 'd, T: Instance, M: fdcan::Transmit> FdcanTx<'c, 'd, T, M> { 434impl<'c, 'd, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize>
482 /// Queues the message to be sent but exerts backpressure. If a lower-priority 435 BufferedCan<'d, T, TX_BUF_SIZE, RX_BUF_SIZE>
483 /// frame is dropped from the mailbox, it is returned. If no lower-priority frames 436{
484 /// can be replaced, this call asynchronously waits for a frame to be successfully 437 fn new(
485 /// transmitted, then tries again. 438 _instance1: PhantomData<T>,
486 pub async fn write(&mut self, frame: &TxFrame) -> Option<TxFrame> { 439 _instance2: &'d crate::pac::can::Fdcan,
487 poll_fn(|cx| { 440 _mode: FdcanOperatingMode,
488 T::state().tx_waker.register(cx.waker()); 441 tx_buf: &'static TxBuf<TX_BUF_SIZE>,
489 if let Ok(dropped) = self 442 rx_buf: &'static RxBuf<RX_BUF_SIZE>,
490 .tx 443 ) -> Self {
491 .transmit_preserve(frame.header, &frame.data.bytes, &mut |_, hdr, data32| { 444 BufferedCan {
492 TxFrame::from_preserved(hdr, data32) 445 _instance1,
493 }) 446 _instance2,
494 { 447 _mode,
495 return Poll::Ready(dropped.flatten()); 448 tx_buf,
496 } 449 rx_buf,
450 }
451 .setup()
452 }
497 453
498 // Couldn't replace any lower priority frames. Need to wait for some mailboxes 454 fn setup(self) -> Self {
499 // to clear. 455 // We don't want interrupts being processed while we change modes.
500 Poll::Pending 456 critical_section::with(|_| unsafe {
501 }) 457 let rx_inner = sealed::ClassicBufferedRxInner {
502 .await 458 rx_sender: self.rx_buf.sender().into(),
459 };
460 let tx_inner = sealed::ClassicBufferedTxInner {
461 tx_receiver: self.tx_buf.receiver().into(),
462 };
463 T::mut_state().rx_mode = sealed::RxMode::ClassicBuffered(rx_inner);
464 T::mut_state().tx_mode = sealed::TxMode::ClassicBuffered(tx_inner);
465 });
466 self
467 }
468
469 /// Async write frame to TX buffer.
470 pub async fn write(&mut self, frame: ClassicFrame) {
471 self.tx_buf.send(frame).await;
472 T::IT0Interrupt::pend(); // Wake for Tx
473 }
474
475 /// Async read frame from RX buffer.
476 pub async fn read(&mut self) -> Result<(ClassicFrame, Timestamp), BusError> {
477 Ok(self.rx_buf.receive().await)
503 } 478 }
504} 479}
505 480
506/// FDCAN Rx only Instance 481impl<'c, 'd, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> Drop
507#[allow(dead_code)] 482 for BufferedCan<'d, T, TX_BUF_SIZE, RX_BUF_SIZE>
508pub struct FdcanRx<'c, 'd, T: Instance, M: fdcan::Receive> { 483{
509 rx0: &'c mut fdcan::Rx<FdcanInstance<'d, T>, M, fdcan::Fifo0>, 484 fn drop(&mut self) {
510 rx1: &'c mut fdcan::Rx<FdcanInstance<'d, T>, M, fdcan::Fifo1>, 485 critical_section::with(|_| unsafe {
511 ns_per_timer_tick: u64, // For FDCAN internal timer 486 T::mut_state().rx_mode = sealed::RxMode::NonBuffered(embassy_sync::waitqueue::AtomicWaker::new());
487 T::mut_state().tx_mode = sealed::TxMode::NonBuffered(embassy_sync::waitqueue::AtomicWaker::new());
488 });
489 }
512} 490}
513 491
514impl<'c, 'd, T: Instance, M: fdcan::Receive> FdcanRx<'c, 'd, T, M> { 492/// User supplied buffer for RX Buffering
515 /// Returns the next received message frame 493pub type RxFdBuf<const BUF_SIZE: usize> = Channel<CriticalSectionRawMutex, (FdFrame, Timestamp), BUF_SIZE>;
516 pub async fn read(&mut self) -> Result<RxFrame, BusError> {
517 poll_fn(|cx| {
518 T::state().err_waker.register(cx.waker());
519 T::state().rx_waker.register(cx.waker());
520
521 let mut buffer: [u8; 64] = [0; 64];
522 if let Ok(rx) = self.rx0.receive(&mut buffer) {
523 // rx: fdcan::ReceiveOverrun<RxFrameInfo>
524 // TODO: report overrun?
525 // for now we just drop it
526 let frame: RxFrame = RxFrame::new(
527 rx.unwrap(),
528 &buffer,
529 #[cfg(feature = "time")]
530 calc_timestamp::<T>(self.ns_per_timer_tick, rx.unwrap().time_stamp),
531 );
532 return Poll::Ready(Ok(frame));
533 } else if let Ok(rx) = self.rx1.receive(&mut buffer) {
534 // rx: fdcan::ReceiveOverrun<RxFrameInfo>
535 // TODO: report overrun?
536 // for now we just drop it
537 let frame: RxFrame = RxFrame::new(
538 rx.unwrap(),
539 &buffer,
540 #[cfg(feature = "time")]
541 calc_timestamp::<T>(self.ns_per_timer_tick, rx.unwrap().time_stamp),
542 );
543 return Poll::Ready(Ok(frame));
544 } else if let Some(err) = curr_error::<T>() {
545 // TODO: this is probably wrong
546 return Poll::Ready(Err(err));
547 }
548 494
549 Poll::Pending 495/// User supplied buffer for TX buffering
550 }) 496pub type TxFdBuf<const BUF_SIZE: usize> = Channel<CriticalSectionRawMutex, FdFrame, BUF_SIZE>;
551 .await 497
498/// Buffered FDCAN Instance
499pub struct BufferedCanFd<'d, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> {
500 _instance1: PhantomData<T>,
501 _instance2: &'d crate::pac::can::Fdcan,
502 _mode: FdcanOperatingMode,
503 tx_buf: &'static TxFdBuf<TX_BUF_SIZE>,
504 rx_buf: &'static RxFdBuf<RX_BUF_SIZE>,
505}
506
507impl<'c, 'd, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize>
508 BufferedCanFd<'d, T, TX_BUF_SIZE, RX_BUF_SIZE>
509{
510 fn new(
511 _instance1: PhantomData<T>,
512 _instance2: &'d crate::pac::can::Fdcan,
513 _mode: FdcanOperatingMode,
514 tx_buf: &'static TxFdBuf<TX_BUF_SIZE>,
515 rx_buf: &'static RxFdBuf<RX_BUF_SIZE>,
516 ) -> Self {
517 BufferedCanFd {
518 _instance1,
519 _instance2,
520 _mode,
521 tx_buf,
522 rx_buf,
523 }
524 .setup()
525 }
526
527 fn setup(self) -> Self {
528 // We don't want interrupts being processed while we change modes.
529 critical_section::with(|_| unsafe {
530 let rx_inner = sealed::FdBufferedRxInner {
531 rx_sender: self.rx_buf.sender().into(),
532 };
533 let tx_inner = sealed::FdBufferedTxInner {
534 tx_receiver: self.tx_buf.receiver().into(),
535 };
536 T::mut_state().rx_mode = sealed::RxMode::FdBuffered(rx_inner);
537 T::mut_state().tx_mode = sealed::TxMode::FdBuffered(tx_inner);
538 });
539 self
540 }
541
542 /// Async write frame to TX buffer.
543 pub async fn write(&mut self, frame: FdFrame) {
544 self.tx_buf.send(frame).await;
545 T::IT0Interrupt::pend(); // Wake for Tx
546 }
547
548 /// Async read frame from RX buffer.
549 pub async fn read(&mut self) -> Result<(FdFrame, Timestamp), BusError> {
550 Ok(self.rx_buf.receive().await)
552 } 551 }
553} 552}
554impl<'d, T: Instance, M: FdcanOperatingMode> Deref for Fdcan<'d, T, M> {
555 type Target = fdcan::FdCan<FdcanInstance<'d, T>, M>;
556 553
557 fn deref(&self) -> &Self::Target { 554impl<'c, 'd, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> Drop
558 &self.can 555 for BufferedCanFd<'d, T, TX_BUF_SIZE, RX_BUF_SIZE>
556{
557 fn drop(&mut self) {
558 critical_section::with(|_| unsafe {
559 T::mut_state().rx_mode = sealed::RxMode::NonBuffered(embassy_sync::waitqueue::AtomicWaker::new());
560 T::mut_state().tx_mode = sealed::TxMode::NonBuffered(embassy_sync::waitqueue::AtomicWaker::new());
561 });
559 } 562 }
560} 563}
561 564
562impl<'d, T: Instance, M: FdcanOperatingMode> DerefMut for Fdcan<'d, T, M> { 565/// FDCAN Rx only Instance
563 fn deref_mut(&mut self) -> &mut Self::Target { 566pub struct FdcanRx<'d, T: Instance> {
564 &mut self.can 567 _instance1: PhantomData<T>,
568 _instance2: &'d crate::pac::can::Fdcan,
569 _mode: FdcanOperatingMode,
570}
571
572/// FDCAN Tx only Instance
573pub struct FdcanTx<'d, T: Instance> {
574 config: crate::can::fd::config::FdCanConfig,
575 _instance: FdcanInstance<'d, T>, //(PeripheralRef<'a, T>);
576 _mode: FdcanOperatingMode,
577}
578
579impl<'c, 'd, T: Instance> FdcanTx<'d, T> {
580 /// Queues the message to be sent but exerts backpressure. If a lower-priority
581 /// frame is dropped from the mailbox, it is returned. If no lower-priority frames
582 /// can be replaced, this call asynchronously waits for a frame to be successfully
583 /// transmitted, then tries again.
584 pub async fn write(&mut self, frame: &ClassicFrame) -> Option<ClassicFrame> {
585 T::state().tx_mode.write::<T>(frame).await
586 }
587
588 /// Queues the message to be sent but exerts backpressure. If a lower-priority
589 /// frame is dropped from the mailbox, it is returned. If no lower-priority frames
590 /// can be replaced, this call asynchronously waits for a frame to be successfully
591 /// transmitted, then tries again.
592 pub async fn write_fd(&mut self, frame: &FdFrame) -> Option<FdFrame> {
593 T::state().tx_mode.write_fd::<T>(frame).await
594 }
595}
596
597impl<'c, 'd, T: Instance> FdcanRx<'d, T> {
598 /// Returns the next received message frame
599 pub async fn read(&mut self) -> Result<(ClassicFrame, Timestamp), BusError> {
600 T::state().rx_mode.read::<T>().await
601 }
602
603 /// Returns the next received message frame
604 pub async fn read_fd(&mut self) -> Result<(FdFrame, Timestamp), BusError> {
605 T::state().rx_mode.read_fd::<T>().await
565 } 606 }
566} 607}
567 608
568pub(crate) mod sealed { 609pub(crate) mod sealed {
610 use core::future::poll_fn;
611 use core::task::Poll;
612
613 use embassy_sync::channel::{DynamicReceiver, DynamicSender};
569 use embassy_sync::waitqueue::AtomicWaker; 614 use embassy_sync::waitqueue::AtomicWaker;
570 615
616 use crate::can::_version::{BusError, Timestamp};
617 use crate::can::frame::{ClassicFrame, FdFrame};
618
619 pub struct ClassicBufferedRxInner {
620 pub rx_sender: DynamicSender<'static, (ClassicFrame, Timestamp)>,
621 }
622 pub struct ClassicBufferedTxInner {
623 pub tx_receiver: DynamicReceiver<'static, ClassicFrame>,
624 }
625
626 pub struct FdBufferedRxInner {
627 pub rx_sender: DynamicSender<'static, (FdFrame, Timestamp)>,
628 }
629 pub struct FdBufferedTxInner {
630 pub tx_receiver: DynamicReceiver<'static, FdFrame>,
631 }
632
633 pub enum RxMode {
634 NonBuffered(AtomicWaker),
635 ClassicBuffered(ClassicBufferedRxInner),
636 FdBuffered(FdBufferedRxInner),
637 }
638
639 impl RxMode {
640 pub fn register(&self, arg: &core::task::Waker) {
641 match self {
642 RxMode::NonBuffered(waker) => waker.register(arg),
643 _ => {
644 panic!("Bad Mode")
645 }
646 }
647 }
648
649 pub fn on_interrupt<T: Instance>(&self, fifonr: usize) {
650 T::regs().ir().write(|w| w.set_rfn(fifonr, true));
651 match self {
652 RxMode::NonBuffered(waker) => {
653 waker.wake();
654 }
655 RxMode::ClassicBuffered(buf) => {
656 if let Some(r) = T::registers().read_classic(fifonr) {
657 let ts = T::calc_timestamp(T::state().ns_per_timer_tick, r.1);
658 let _ = buf.rx_sender.try_send((r.0, ts));
659 }
660 }
661 RxMode::FdBuffered(buf) => {
662 if let Some(r) = T::registers().read_fd(fifonr) {
663 let ts = T::calc_timestamp(T::state().ns_per_timer_tick, r.1);
664 let _ = buf.rx_sender.try_send((r.0, ts));
665 }
666 }
667 }
668 }
669
670 pub async fn read<T: Instance>(&self) -> Result<(ClassicFrame, Timestamp), BusError> {
671 poll_fn(|cx| {
672 T::state().err_waker.register(cx.waker());
673 self.register(cx.waker());
674
675 if let Some((msg, ts)) = T::registers().read_classic(0) {
676 let ts = T::calc_timestamp(T::state().ns_per_timer_tick, ts);
677 return Poll::Ready(Ok((msg, ts)));
678 } else if let Some((msg, ts)) = T::registers().read_classic(1) {
679 let ts = T::calc_timestamp(T::state().ns_per_timer_tick, ts);
680 return Poll::Ready(Ok((msg, ts)));
681 } else if let Some(err) = T::registers().curr_error() {
682 // TODO: this is probably wrong
683 return Poll::Ready(Err(err));
684 }
685 Poll::Pending
686 })
687 .await
688 }
689
690 pub async fn read_fd<T: Instance>(&self) -> Result<(FdFrame, Timestamp), BusError> {
691 poll_fn(|cx| {
692 T::state().err_waker.register(cx.waker());
693 self.register(cx.waker());
694
695 if let Some((msg, ts)) = T::registers().read_fd(0) {
696 let ts = T::calc_timestamp(T::state().ns_per_timer_tick, ts);
697 return Poll::Ready(Ok((msg, ts)));
698 } else if let Some((msg, ts)) = T::registers().read_fd(1) {
699 let ts = T::calc_timestamp(T::state().ns_per_timer_tick, ts);
700 return Poll::Ready(Ok((msg, ts)));
701 } else if let Some(err) = T::registers().curr_error() {
702 // TODO: this is probably wrong
703 return Poll::Ready(Err(err));
704 }
705 Poll::Pending
706 })
707 .await
708 }
709 }
710
711 pub enum TxMode {
712 NonBuffered(AtomicWaker),
713 ClassicBuffered(ClassicBufferedTxInner),
714 FdBuffered(FdBufferedTxInner),
715 }
716
717 impl TxMode {
718 pub fn register(&self, arg: &core::task::Waker) {
719 match self {
720 TxMode::NonBuffered(waker) => {
721 waker.register(arg);
722 }
723 _ => {
724 panic!("Bad mode");
725 }
726 }
727 }
728
729 /// Queues the message to be sent but exerts backpressure. If a lower-priority
730 /// frame is dropped from the mailbox, it is returned. If no lower-priority frames
731 /// can be replaced, this call asynchronously waits for a frame to be successfully
732 /// transmitted, then tries again.
733 pub async fn write<T: Instance>(&self, frame: &ClassicFrame) -> Option<ClassicFrame> {
734 poll_fn(|cx| {
735 self.register(cx.waker());
736
737 if let Ok(dropped) = T::registers().write_classic(frame) {
738 return Poll::Ready(dropped);
739 }
740
741 // Couldn't replace any lower priority frames. Need to wait for some mailboxes
742 // to clear.
743 Poll::Pending
744 })
745 .await
746 }
747
748 /// Queues the message to be sent but exerts backpressure. If a lower-priority
749 /// frame is dropped from the mailbox, it is returned. If no lower-priority frames
750 /// can be replaced, this call asynchronously waits for a frame to be successfully
751 /// transmitted, then tries again.
752 pub async fn write_fd<T: Instance>(&self, frame: &FdFrame) -> Option<FdFrame> {
753 poll_fn(|cx| {
754 self.register(cx.waker());
755
756 if let Ok(dropped) = T::registers().write_fd(frame) {
757 return Poll::Ready(dropped);
758 }
759
760 // Couldn't replace any lower priority frames. Need to wait for some mailboxes
761 // to clear.
762 Poll::Pending
763 })
764 .await
765 }
766 }
767
571 pub struct State { 768 pub struct State {
572 pub tx_waker: AtomicWaker, 769 pub rx_mode: RxMode,
770 pub tx_mode: TxMode,
771 pub ns_per_timer_tick: u64,
772
573 pub err_waker: AtomicWaker, 773 pub err_waker: AtomicWaker,
574 pub rx_waker: AtomicWaker,
575 } 774 }
576 775
577 impl State { 776 impl State {
578 pub const fn new() -> Self { 777 pub const fn new() -> Self {
579 Self { 778 Self {
580 tx_waker: AtomicWaker::new(), 779 rx_mode: RxMode::NonBuffered(AtomicWaker::new()),
780 tx_mode: TxMode::NonBuffered(AtomicWaker::new()),
781 ns_per_timer_tick: 0,
581 err_waker: AtomicWaker::new(), 782 err_waker: AtomicWaker::new(),
582 rx_waker: AtomicWaker::new(),
583 } 783 }
584 } 784 }
585 } 785 }
586 786
587 pub trait Instance { 787 pub trait Instance {
588 const REGISTERS: *mut fdcan::RegisterBlock;
589 const MSG_RAM: *mut fdcan::message_ram::RegisterBlock;
590 const MSG_RAM_OFFSET: usize; 788 const MSG_RAM_OFFSET: usize;
591 789
592 fn regs() -> &'static crate::pac::can::Fdcan; 790 fn regs() -> &'static crate::pac::can::Fdcan;
791 fn registers() -> crate::can::fd::peripheral::Registers;
792 fn ram() -> &'static crate::pac::fdcanram::Fdcanram;
593 fn state() -> &'static State; 793 fn state() -> &'static State;
794 unsafe fn mut_state() -> &'static mut State;
795 fn calc_timestamp(ns_per_timer_tick: u64, ts_val: u16) -> Timestamp;
594 796
595 #[cfg(not(stm32h7))] 797 #[cfg(not(stm32h7))]
596 fn configure_msg_ram() {} 798 fn configure_msg_ram() {}
@@ -599,7 +801,8 @@ pub(crate) mod sealed {
599 fn configure_msg_ram() { 801 fn configure_msg_ram() {
600 let r = Self::regs(); 802 let r = Self::regs();
601 803
602 use fdcan::message_ram::*; 804 use crate::can::fd::message_ram::*;
805 //use fdcan::message_ram::*;
603 let mut offset_words = Self::MSG_RAM_OFFSET as u16; 806 let mut offset_words = Self::MSG_RAM_OFFSET as u16;
604 807
605 // 11-bit filter 808 // 11-bit filter
@@ -677,32 +880,45 @@ pub trait Instance: sealed::Instance + RccPeripheral + InterruptableInstance + '
677/// Fdcan Instance struct 880/// Fdcan Instance struct
678pub struct FdcanInstance<'a, T>(PeripheralRef<'a, T>); 881pub struct FdcanInstance<'a, T>(PeripheralRef<'a, T>);
679 882
680unsafe impl<'d, T: Instance> fdcan::message_ram::Instance for FdcanInstance<'d, T> {
681 const MSG_RAM: *mut RegisterBlock = T::MSG_RAM;
682}
683
684unsafe impl<'d, T: Instance> fdcan::Instance for FdcanInstance<'d, T>
685where
686 FdcanInstance<'d, T>: fdcan::message_ram::Instance,
687{
688 const REGISTERS: *mut fdcan::RegisterBlock = T::REGISTERS;
689}
690
691macro_rules! impl_fdcan { 883macro_rules! impl_fdcan {
692 ($inst:ident, $msg_ram_inst:ident, $msg_ram_offset:literal) => { 884 ($inst:ident, $msg_ram_inst:ident, $msg_ram_offset:literal) => {
693 impl sealed::Instance for peripherals::$inst { 885 impl sealed::Instance for peripherals::$inst {
694 const REGISTERS: *mut fdcan::RegisterBlock = crate::pac::$inst.as_ptr() as *mut _;
695 const MSG_RAM: *mut fdcan::message_ram::RegisterBlock = crate::pac::$msg_ram_inst.as_ptr() as *mut _;
696 const MSG_RAM_OFFSET: usize = $msg_ram_offset; 886 const MSG_RAM_OFFSET: usize = $msg_ram_offset;
697 887
698 fn regs() -> &'static crate::pac::can::Fdcan { 888 fn regs() -> &'static crate::pac::can::Fdcan {
699 &crate::pac::$inst 889 &crate::pac::$inst
700 } 890 }
701 891 fn registers() -> Registers {
892 Registers{regs: &crate::pac::$inst, msgram: &crate::pac::$msg_ram_inst}
893 }
894 fn ram() -> &'static crate::pac::fdcanram::Fdcanram {
895 &crate::pac::$msg_ram_inst
896 }
897 unsafe fn mut_state() -> & 'static mut sealed::State {
898 static mut STATE: sealed::State = sealed::State::new();
899 & mut STATE
900 }
702 fn state() -> &'static sealed::State { 901 fn state() -> &'static sealed::State {
703 static STATE: sealed::State = sealed::State::new(); 902 unsafe { peripherals::$inst::mut_state() }
704 &STATE
705 } 903 }
904
905#[cfg(feature = "time")]
906fn calc_timestamp(ns_per_timer_tick: u64, ts_val: u16) -> Timestamp {
907 let now_embassy = embassy_time::Instant::now();
908 if ns_per_timer_tick == 0 {
909 return now_embassy;
910 }
911 let cantime = { Self::regs().tscv().read().tsc() };
912 let delta = cantime.overflowing_sub(ts_val).0 as u64;
913 let ns = ns_per_timer_tick * delta as u64;
914 now_embassy - embassy_time::Duration::from_nanos(ns)
915}
916
917#[cfg(not(feature = "time"))]
918fn calc_timestamp(_ns_per_timer_tick: u64, ts_val: u16) -> Timestamp {
919 ts_val
920}
921
706 } 922 }
707 923
708 impl Instance for peripherals::$inst {} 924 impl Instance for peripherals::$inst {}
diff --git a/embassy-stm32/src/can/frame.rs b/embassy-stm32/src/can/frame.rs
new file mode 100644
index 000000000..725a9b1ab
--- /dev/null
+++ b/embassy-stm32/src/can/frame.rs
@@ -0,0 +1,370 @@
1//! Definition for CAN Frames
2use bit_field::BitField;
3
4/// CAN Header, without meta data
5#[derive(Debug, Copy, Clone)]
6pub struct Header {
7 id: embedded_can::Id,
8 len: u8,
9 flags: u8,
10}
11
12impl Header {
13 const FLAG_RTR: usize = 0; // Remote
14 const FLAG_FDCAN: usize = 1; // FDCan vs Classic CAN
15 const FLAG_BRS: usize = 2; // Bit-rate switching, ignored for Classic CAN
16
17 /// Create new CAN Header
18 pub fn new(id: embedded_can::Id, len: u8, rtr: bool) -> Header {
19 let mut flags = 0u8;
20 flags.set_bit(Self::FLAG_RTR, rtr);
21 Header { id, len, flags }
22 }
23
24 /// Create new CAN FD Header
25 pub fn new_fd(id: embedded_can::Id, len: u8, rtr: bool, brs: bool) -> Header {
26 let mut flags = 0u8;
27 flags.set_bit(Self::FLAG_RTR, rtr);
28 flags.set_bit(Self::FLAG_FDCAN, true);
29 flags.set_bit(Self::FLAG_BRS, brs);
30 Header { id, len, flags }
31 }
32
33 /// Return ID
34 pub fn id(&self) -> &embedded_can::Id {
35 &self.id
36 }
37
38 /// Return length as u8
39 pub fn len(&self) -> u8 {
40 self.len
41 }
42
43 /// Is remote frame
44 pub fn rtr(&self) -> bool {
45 self.flags.get_bit(Self::FLAG_RTR)
46 }
47
48 /// Request/is FDCAN frame
49 pub fn fdcan(&self) -> bool {
50 self.flags.get_bit(Self::FLAG_FDCAN)
51 }
52
53 /// Request/is Flexible Data Rate
54 pub fn bit_rate_switching(&self) -> bool {
55 self.flags.get_bit(Self::FLAG_BRS)
56 }
57}
58
59/// Payload of a classic CAN data frame.
60///
61/// Contains 0 to 8 Bytes of data.
62#[derive(Debug, Copy, Clone)]
63pub struct ClassicData {
64 pub(crate) bytes: [u8; 8],
65}
66
67impl ClassicData {
68 /// Creates a data payload from a raw byte slice.
69 ///
70 /// Returns `None` if `data` is more than 64 bytes (which is the maximum) or
71 /// cannot be represented with an FDCAN DLC.
72 pub fn new(data: &[u8]) -> Option<Self> {
73 if !FdData::is_valid_len(data.len()) {
74 return None;
75 }
76
77 let mut bytes = [0; 8];
78 bytes[..data.len()].copy_from_slice(data);
79
80 Some(Self { bytes })
81 }
82
83 /// Raw read access to data.
84 pub fn raw(&self) -> &[u8] {
85 &self.bytes
86 }
87
88 /// Checks if the length can be encoded in FDCAN DLC field.
89 pub const fn is_valid_len(len: usize) -> bool {
90 match len {
91 0..=8 => true,
92 _ => false,
93 }
94 }
95
96 /// Creates an empty data payload containing 0 bytes.
97 #[inline]
98 pub const fn empty() -> Self {
99 Self { bytes: [0; 8] }
100 }
101}
102
103/// Frame with up to 8 bytes of data payload as per Classic CAN
104#[derive(Debug, Copy, Clone)]
105pub struct ClassicFrame {
106 can_header: Header,
107 data: ClassicData,
108}
109
110impl ClassicFrame {
111 pub(crate) const MAX_DATA_LEN: usize = 8;
112
113 /// Create a new CAN classic Frame
114 pub fn new(can_header: Header, data: ClassicData) -> ClassicFrame {
115 ClassicFrame { can_header, data }
116 }
117
118 /// Create new extended frame
119 pub fn new_extended(raw_id: u32, raw_data: &[u8]) -> Option<Self> {
120 if let Some(id) = embedded_can::ExtendedId::new(raw_id) {
121 match ClassicData::new(raw_data) {
122 Some(data) => Some(ClassicFrame::new(
123 Header::new(id.into(), raw_data.len() as u8, false),
124 data,
125 )),
126 None => None,
127 }
128 } else {
129 None
130 }
131 }
132
133 /// Create new standard frame
134 pub fn new_standard(raw_id: u16, raw_data: &[u8]) -> Option<Self> {
135 if let Some(id) = embedded_can::StandardId::new(raw_id) {
136 match ClassicData::new(raw_data) {
137 Some(data) => Some(ClassicFrame::new(
138 Header::new(id.into(), raw_data.len() as u8, false),
139 data,
140 )),
141 None => None,
142 }
143 } else {
144 None
145 }
146 }
147
148 /// Create new remote frame
149 pub fn new_remote(id: impl Into<embedded_can::Id>, len: usize) -> Option<Self> {
150 if len <= 8usize {
151 Some(ClassicFrame::new(
152 Header::new(id.into(), len as u8, true),
153 ClassicData::empty(),
154 ))
155 } else {
156 None
157 }
158 }
159
160 /// Get reference to data
161 pub fn header(&self) -> &Header {
162 &self.can_header
163 }
164
165 /// Return ID
166 pub fn id(&self) -> &embedded_can::Id {
167 &self.can_header.id
168 }
169
170 /// Get reference to data
171 pub fn data(&self) -> &[u8] {
172 &self.data.raw()
173 }
174}
175
176impl embedded_can::Frame for ClassicFrame {
177 fn new(id: impl Into<embedded_can::Id>, raw_data: &[u8]) -> Option<Self> {
178 match ClassicData::new(raw_data) {
179 Some(data) => Some(ClassicFrame::new(
180 Header::new(id.into(), raw_data.len() as u8, false),
181 data,
182 )),
183 None => None,
184 }
185 }
186 fn new_remote(id: impl Into<embedded_can::Id>, len: usize) -> Option<Self> {
187 if len <= 8 {
188 Some(ClassicFrame::new(
189 Header::new(id.into(), len as u8, true),
190 ClassicData::empty(),
191 ))
192 } else {
193 None
194 }
195 }
196 fn is_extended(&self) -> bool {
197 match self.can_header.id {
198 embedded_can::Id::Extended(_) => true,
199 embedded_can::Id::Standard(_) => true,
200 }
201 }
202 fn is_remote_frame(&self) -> bool {
203 self.can_header.rtr()
204 }
205 fn id(&self) -> embedded_can::Id {
206 self.can_header.id
207 }
208 fn dlc(&self) -> usize {
209 self.can_header.len as usize
210 }
211 fn data(&self) -> &[u8] {
212 &self.data.raw()
213 }
214}
215
216/// Payload of a (FD)CAN data frame.
217///
218/// Contains 0 to 64 Bytes of data.
219#[derive(Debug, Copy, Clone)]
220pub struct FdData {
221 pub(crate) bytes: [u8; 64],
222}
223
224impl FdData {
225 /// Creates a data payload from a raw byte slice.
226 ///
227 /// Returns `None` if `data` is more than 64 bytes (which is the maximum) or
228 /// cannot be represented with an FDCAN DLC.
229 pub fn new(data: &[u8]) -> Option<Self> {
230 if !FdData::is_valid_len(data.len()) {
231 return None;
232 }
233
234 let mut bytes = [0; 64];
235 bytes[..data.len()].copy_from_slice(data);
236
237 Some(Self { bytes })
238 }
239
240 /// Raw read access to data.
241 pub fn raw(&self) -> &[u8] {
242 &self.bytes
243 }
244
245 /// Checks if the length can be encoded in FDCAN DLC field.
246 pub const fn is_valid_len(len: usize) -> bool {
247 match len {
248 0..=8 => true,
249 12 => true,
250 16 => true,
251 20 => true,
252 24 => true,
253 32 => true,
254 48 => true,
255 64 => true,
256 _ => false,
257 }
258 }
259
260 /// Creates an empty data payload containing 0 bytes.
261 #[inline]
262 pub const fn empty() -> Self {
263 Self { bytes: [0; 64] }
264 }
265}
266
267/// Frame with up to 8 bytes of data payload as per Fd CAN
268#[derive(Debug, Copy, Clone)]
269pub struct FdFrame {
270 can_header: Header,
271 data: FdData,
272}
273
274impl FdFrame {
275 pub(crate) const MAX_DATA_LEN: usize = 64;
276
277 /// Create a new CAN classic Frame
278 pub fn new(can_header: Header, data: FdData) -> FdFrame {
279 FdFrame { can_header, data }
280 }
281
282 /// Create new extended frame
283 pub fn new_extended(raw_id: u32, raw_data: &[u8]) -> Option<Self> {
284 if let Some(id) = embedded_can::ExtendedId::new(raw_id) {
285 match FdData::new(raw_data) {
286 Some(data) => Some(FdFrame::new(Header::new(id.into(), raw_data.len() as u8, false), data)),
287 None => None,
288 }
289 } else {
290 None
291 }
292 }
293
294 /// Create new standard frame
295 pub fn new_standard(raw_id: u16, raw_data: &[u8]) -> Option<Self> {
296 if let Some(id) = embedded_can::StandardId::new(raw_id) {
297 match FdData::new(raw_data) {
298 Some(data) => Some(FdFrame::new(Header::new(id.into(), raw_data.len() as u8, false), data)),
299 None => None,
300 }
301 } else {
302 None
303 }
304 }
305
306 /// Create new remote frame
307 pub fn new_remote(id: impl Into<embedded_can::Id>, len: usize) -> Option<Self> {
308 if len <= 8 {
309 Some(FdFrame::new(Header::new(id.into(), len as u8, true), FdData::empty()))
310 } else {
311 None
312 }
313 }
314
315 /// Get reference to data
316 pub fn header(&self) -> &Header {
317 &self.can_header
318 }
319
320 /// Return ID
321 pub fn id(&self) -> &embedded_can::Id {
322 &self.can_header.id
323 }
324
325 /// Get reference to data
326 pub fn data(&self) -> &[u8] {
327 &self.data.raw()
328 }
329}
330
331impl embedded_can::Frame for FdFrame {
332 fn new(id: impl Into<embedded_can::Id>, raw_data: &[u8]) -> Option<Self> {
333 match FdData::new(raw_data) {
334 Some(data) => Some(FdFrame::new(
335 Header::new_fd(id.into(), raw_data.len() as u8, false, true),
336 data,
337 )),
338 None => None,
339 }
340 }
341 fn new_remote(id: impl Into<embedded_can::Id>, len: usize) -> Option<Self> {
342 if len <= 8 {
343 Some(FdFrame::new(
344 Header::new_fd(id.into(), len as u8, true, true),
345 FdData::empty(),
346 ))
347 } else {
348 None
349 }
350 }
351 fn is_extended(&self) -> bool {
352 match self.can_header.id {
353 embedded_can::Id::Extended(_) => true,
354 embedded_can::Id::Standard(_) => true,
355 }
356 }
357 fn is_remote_frame(&self) -> bool {
358 self.can_header.rtr()
359 }
360 fn id(&self) -> embedded_can::Id {
361 self.can_header.id
362 }
363 // Returns length in bytes even for CANFD packets which embedded-can does not really mention.
364 fn dlc(&self) -> usize {
365 self.can_header.len as usize
366 }
367 fn data(&self) -> &[u8] {
368 &self.data.raw()
369 }
370}
diff --git a/embassy-stm32/src/dma/bdma.rs b/embassy-stm32/src/dma/bdma.rs
index 077cfdcd9..994bdb1e6 100644
--- a/embassy-stm32/src/dma/bdma.rs
+++ b/embassy-stm32/src/dma/bdma.rs
@@ -299,7 +299,7 @@ impl<'a, C: Channel> Transfer<'a, C> {
299 STATE.complete_count[this.channel.index()].store(0, Ordering::Release); 299 STATE.complete_count[this.channel.index()].store(0, Ordering::Release);
300 300
301 #[cfg(dmamux)] 301 #[cfg(dmamux)]
302 super::dmamux::configure_dmamux(&mut *this.channel, _request); 302 super::dmamux::configure_dmamux(&*this.channel, _request);
303 303
304 ch.par().write_value(peri_addr as u32); 304 ch.par().write_value(peri_addr as u32);
305 ch.mar().write_value(mem_addr as u32); 305 ch.mar().write_value(mem_addr as u32);
@@ -483,7 +483,7 @@ impl<'a, C: Channel, W: Word> ReadableRingBuffer<'a, C, W> {
483 this.clear_irqs(); 483 this.clear_irqs();
484 484
485 #[cfg(dmamux)] 485 #[cfg(dmamux)]
486 super::dmamux::configure_dmamux(&mut *this.channel, _request); 486 super::dmamux::configure_dmamux(&*this.channel, _request);
487 487
488 let ch = dma.ch(channel_number); 488 let ch = dma.ch(channel_number);
489 ch.par().write_value(peri_addr as u32); 489 ch.par().write_value(peri_addr as u32);
@@ -641,7 +641,7 @@ impl<'a, C: Channel, W: Word> WritableRingBuffer<'a, C, W> {
641 this.clear_irqs(); 641 this.clear_irqs();
642 642
643 #[cfg(dmamux)] 643 #[cfg(dmamux)]
644 super::dmamux::configure_dmamux(&mut *this.channel, _request); 644 super::dmamux::configure_dmamux(&*this.channel, _request);
645 645
646 let ch = dma.ch(channel_number); 646 let ch = dma.ch(channel_number);
647 ch.par().write_value(peri_addr as u32); 647 ch.par().write_value(peri_addr as u32);
diff --git a/embassy-stm32/src/dma/dma.rs b/embassy-stm32/src/dma/dma.rs
index ef9bb3d78..e762b1bde 100644
--- a/embassy-stm32/src/dma/dma.rs
+++ b/embassy-stm32/src/dma/dma.rs
@@ -366,7 +366,7 @@ impl<'a, C: Channel> Transfer<'a, C> {
366 this.clear_irqs(); 366 this.clear_irqs();
367 367
368 #[cfg(dmamux)] 368 #[cfg(dmamux)]
369 super::dmamux::configure_dmamux(&mut *this.channel, _request); 369 super::dmamux::configure_dmamux(&*this.channel, _request);
370 370
371 ch.par().write_value(peri_addr as u32); 371 ch.par().write_value(peri_addr as u32);
372 ch.m0ar().write_value(mem_addr as u32); 372 ch.m0ar().write_value(mem_addr as u32);
@@ -522,7 +522,7 @@ impl<'a, C: Channel, W: Word> DoubleBuffered<'a, C, W> {
522 this.clear_irqs(); 522 this.clear_irqs();
523 523
524 #[cfg(dmamux)] 524 #[cfg(dmamux)]
525 super::dmamux::configure_dmamux(&mut *this.channel, _request); 525 super::dmamux::configure_dmamux(&*this.channel, _request);
526 526
527 let ch = dma.st(channel_number); 527 let ch = dma.st(channel_number);
528 ch.par().write_value(peri_addr as u32); 528 ch.par().write_value(peri_addr as u32);
@@ -726,7 +726,7 @@ impl<'a, C: Channel, W: Word> ReadableRingBuffer<'a, C, W> {
726 this.clear_irqs(); 726 this.clear_irqs();
727 727
728 #[cfg(dmamux)] 728 #[cfg(dmamux)]
729 super::dmamux::configure_dmamux(&mut *this.channel, _request); 729 super::dmamux::configure_dmamux(&*this.channel, _request);
730 730
731 let ch = dma.st(channel_number); 731 let ch = dma.st(channel_number);
732 ch.par().write_value(peri_addr as u32); 732 ch.par().write_value(peri_addr as u32);
@@ -901,7 +901,7 @@ impl<'a, C: Channel, W: Word> WritableRingBuffer<'a, C, W> {
901 this.clear_irqs(); 901 this.clear_irqs();
902 902
903 #[cfg(dmamux)] 903 #[cfg(dmamux)]
904 super::dmamux::configure_dmamux(&mut *this.channel, _request); 904 super::dmamux::configure_dmamux(&*this.channel, _request);
905 905
906 let ch = dma.st(channel_number); 906 let ch = dma.st(channel_number);
907 ch.par().write_value(peri_addr as u32); 907 ch.par().write_value(peri_addr as u32);
diff --git a/embassy-stm32/src/dma/dmamux.rs b/embassy-stm32/src/dma/dmamux.rs
index 9cd494724..ac6f44107 100644
--- a/embassy-stm32/src/dma/dmamux.rs
+++ b/embassy-stm32/src/dma/dmamux.rs
@@ -2,7 +2,7 @@
2 2
3use crate::{pac, peripherals}; 3use crate::{pac, peripherals};
4 4
5pub(crate) fn configure_dmamux<M: MuxChannel>(channel: &mut M, request: u8) { 5pub(crate) fn configure_dmamux<M: MuxChannel>(channel: &M, request: u8) {
6 let ch_mux_regs = channel.mux_regs().ccr(channel.mux_num()); 6 let ch_mux_regs = channel.mux_regs().ccr(channel.mux_num());
7 ch_mux_regs.write(|reg| { 7 ch_mux_regs.write(|reg| {
8 reg.set_nbreq(0); 8 reg.set_nbreq(0);
diff --git a/embassy-stm32/src/dma/gpdma.rs b/embassy-stm32/src/dma/gpdma.rs
index 34b2426b9..337e7b309 100644
--- a/embassy-stm32/src/dma/gpdma.rs
+++ b/embassy-stm32/src/dma/gpdma.rs
@@ -259,7 +259,7 @@ impl<'a, C: Channel> Transfer<'a, C> {
259 let this = Self { channel }; 259 let this = Self { channel };
260 260
261 #[cfg(dmamux)] 261 #[cfg(dmamux)]
262 super::dmamux::configure_dmamux(&mut *this.channel, request); 262 super::dmamux::configure_dmamux(&*this.channel, request);
263 263
264 ch.cr().write(|w| w.set_reset(true)); 264 ch.cr().write(|w| w.set_reset(true));
265 ch.fcr().write(|w| w.0 = 0xFFFF_FFFF); // clear all irqs 265 ch.fcr().write(|w| w.0 = 0xFFFF_FFFF); // clear all irqs
diff --git a/embassy-stm32/src/flash/h50.rs b/embassy-stm32/src/flash/h50.rs
new file mode 100644
index 000000000..db05bef5d
--- /dev/null
+++ b/embassy-stm32/src/flash/h50.rs
@@ -0,0 +1,124 @@
1/// STM32H50 series flash impl. See RM0492
2use core::{
3 ptr::write_volatile,
4 sync::atomic::{fence, Ordering},
5};
6
7use cortex_m::interrupt;
8use pac::flash::regs::Nssr;
9use pac::flash::vals::Bksel;
10
11use super::{Error, FlashBank, FlashRegion, FlashSector, FLASH_REGIONS, WRITE_SIZE};
12use crate::pac;
13
14pub(crate) const fn is_default_layout() -> bool {
15 true
16}
17
18pub(crate) const fn get_flash_regions() -> &'static [&'static FlashRegion] {
19 &FLASH_REGIONS
20}
21
22pub(crate) unsafe fn lock() {
23 pac::FLASH.nscr().modify(|w| w.set_lock(true));
24}
25
26pub(crate) unsafe fn unlock() {
27 while busy() {}
28
29 if pac::FLASH.nscr().read().lock() {
30 pac::FLASH.nskeyr().write_value(0x4567_0123);
31 pac::FLASH.nskeyr().write_value(0xCDEF_89AB);
32 }
33}
34
35pub(crate) unsafe fn enable_blocking_write() {
36 assert_eq!(0, WRITE_SIZE % 4);
37 pac::FLASH.nscr().write(|w| w.set_pg(true));
38}
39
40pub(crate) unsafe fn disable_blocking_write() {
41 pac::FLASH.nscr().write(|w| w.set_pg(false));
42}
43
44pub(crate) unsafe fn blocking_write(start_address: u32, buf: &[u8; WRITE_SIZE]) -> Result<(), Error> {
45 let mut address = start_address;
46 for val in buf.chunks(4) {
47 write_volatile(address as *mut u32, u32::from_le_bytes(val.try_into().unwrap()));
48 address += val.len() as u32;
49
50 // prevents parallelism errors
51 fence(Ordering::SeqCst);
52 }
53
54 wait_ready_blocking()
55}
56
57pub(crate) unsafe fn blocking_erase_sector(sector: &FlashSector) -> Result<(), Error> {
58 assert!(sector.bank != FlashBank::Otp);
59 assert!(sector.index_in_bank < 8);
60
61 while busy() {}
62
63 interrupt::free(|_| {
64 pac::FLASH.nscr().modify(|w| {
65 w.set_bksel(match sector.bank {
66 FlashBank::Bank1 => Bksel::B_0X0,
67 FlashBank::Bank2 => Bksel::B_0X1,
68 _ => unreachable!(),
69 });
70 w.set_snb(sector.index_in_bank);
71 w.set_ser(true);
72 w.set_strt(true);
73 })
74 });
75
76 let ret = wait_ready_blocking();
77 pac::FLASH.nscr().modify(|w| w.set_ser(false));
78 ret
79}
80
81pub(crate) unsafe fn wait_ready_blocking() -> Result<(), Error> {
82 loop {
83 let sr = pac::FLASH.nssr().read();
84
85 if !sr_busy(sr) {
86 if sr.wrperr() {
87 return Err(Error::Protected);
88 }
89 if sr.pgserr() {
90 return Err(Error::Seq);
91 }
92 if sr.strberr() {
93 // writing several times to the same byte in the write buffer
94 return Err(Error::Prog);
95 }
96 if sr.incerr() {
97 // attempting write operation before completion of previous
98 // write operation
99 return Err(Error::Seq);
100 }
101
102 return Ok(());
103 }
104 }
105}
106
107pub(crate) unsafe fn clear_all_err() {
108 pac::FLASH.nsccr().modify(|w| {
109 w.set_clr_wrperr(true);
110 w.set_clr_pgserr(true);
111 w.set_clr_strberr(true);
112 w.set_clr_incerr(true);
113 })
114}
115
116fn sr_busy(sr: Nssr) -> bool {
117 // Note: RM0492 sometimes incorrectly refers to WBNE as NSWBNE
118 sr.bsy() || sr.dbne() || sr.wbne()
119}
120
121fn busy() -> bool {
122 let sr = pac::FLASH.nssr().read();
123 sr_busy(sr)
124}
diff --git a/embassy-stm32/src/flash/mod.rs b/embassy-stm32/src/flash/mod.rs
index 4f43a7a48..1d8031e82 100644
--- a/embassy-stm32/src/flash/mod.rs
+++ b/embassy-stm32/src/flash/mod.rs
@@ -102,10 +102,11 @@ pub enum FlashBank {
102#[cfg_attr(flash_h7, path = "h7.rs")] 102#[cfg_attr(flash_h7, path = "h7.rs")]
103#[cfg_attr(flash_h7ab, path = "h7.rs")] 103#[cfg_attr(flash_h7ab, path = "h7.rs")]
104#[cfg_attr(flash_u5, path = "u5.rs")] 104#[cfg_attr(flash_u5, path = "u5.rs")]
105#[cfg_attr(flash_h50, path = "h50.rs")]
105#[cfg_attr( 106#[cfg_attr(
106 not(any( 107 not(any(
107 flash_l0, flash_l1, flash_l4, flash_wl, flash_wb, flash_f0, flash_f1, flash_f3, flash_f4, flash_f7, flash_g0, 108 flash_l0, flash_l1, flash_l4, flash_wl, flash_wb, flash_f0, flash_f1, flash_f3, flash_f4, flash_f7, flash_g0,
108 flash_g4, flash_h7, flash_h7ab, flash_u5 109 flash_g4, flash_h7, flash_h7ab, flash_u5, flash_h50
109 )), 110 )),
110 path = "other.rs" 111 path = "other.rs"
111)] 112)]
diff --git a/embassy-stm32/src/rcc/bd.rs b/embassy-stm32/src/rcc/bd.rs
index d381ec1bd..39407b28c 100644
--- a/embassy-stm32/src/rcc/bd.rs
+++ b/embassy-stm32/src/rcc/bd.rs
@@ -201,11 +201,18 @@ impl LsConfig {
201 bdcr().modify(|w| w.set_bdrst(true)); 201 bdcr().modify(|w| w.set_bdrst(true));
202 bdcr().modify(|w| w.set_bdrst(false)); 202 bdcr().modify(|w| w.set_bdrst(false));
203 } 203 }
204 #[cfg(any(stm32h5))] 204 // H5 has a terrible, terrible errata: 'SRAM2 is erased when the backup domain is reset'
205 { 205 // pending a more sane sane way to handle this, just don't reset BD for now.
206 bdcr().modify(|w| w.set_vswrst(true)); 206 // This means the RTCSEL write below will have no effect, only if it has already been written
207 bdcr().modify(|w| w.set_vswrst(false)); 207 // after last power-on. Since it's uncommon to dynamically change RTCSEL, this is better than
208 } 208 // letting half our RAM go magically *poof*.
209 // STM32H503CB/EB/KB/RB device errata - 2.2.8 SRAM2 unduly erased upon a backup domain reset
210 // STM32H562xx/563xx/573xx device errata - 2.2.14 SRAM2 is erased when the backup domain is reset
211 //#[cfg(any(stm32h5))]
212 //{
213 // bdcr().modify(|w| w.set_vswrst(true));
214 // bdcr().modify(|w| w.set_vswrst(false));
215 //}
209 #[cfg(any(stm32c0, stm32l0))] 216 #[cfg(any(stm32c0, stm32l0))]
210 { 217 {
211 bdcr().modify(|w| w.set_rtcrst(true)); 218 bdcr().modify(|w| w.set_rtcrst(true));
diff --git a/embassy-stm32/src/rcc/u5.rs b/embassy-stm32/src/rcc/u5.rs
index 20cc3112a..72613f0f3 100644
--- a/embassy-stm32/src/rcc/u5.rs
+++ b/embassy-stm32/src/rcc/u5.rs
@@ -1,134 +1,83 @@
1pub use crate::pac::rcc::vals::{Hpre as AHBPrescaler, Msirange, Plldiv, Pllm, Plln, Ppre as APBPrescaler}; 1pub use crate::pac::pwr::vals::Vos as VoltageScale;
2use crate::pac::rcc::vals::{Msirgsel, Pllmboost, Pllrge, Pllsrc, Sw}; 2pub use crate::pac::rcc::vals::{
3 Hpre as AHBPrescaler, Msirange, Msirange as MSIRange, Plldiv as PllDiv, Pllm as PllPreDiv, Plln as PllMul,
4 Pllsrc as PllSource, Ppre as APBPrescaler, Sw as ClockSrc,
5};
6use crate::pac::rcc::vals::{Hseext, Msirgsel, Pllmboost, Pllrge};
3use crate::pac::{FLASH, PWR, RCC}; 7use crate::pac::{FLASH, PWR, RCC};
4use crate::time::Hertz; 8use crate::time::Hertz;
5 9
6/// HSI speed 10/// HSI speed
7pub const HSI_FREQ: Hertz = Hertz(16_000_000); 11pub const HSI_FREQ: Hertz = Hertz(16_000_000);
8 12
9pub use crate::pac::pwr::vals::Vos as VoltageScale; 13#[derive(Clone, Copy, Eq, PartialEq)]
10 14pub enum HseMode {
11#[derive(Copy, Clone)] 15 /// crystal/ceramic oscillator (HSEBYP=0)
12#[allow(non_camel_case_types)] 16 Oscillator,
13pub enum ClockSrc { 17 /// external analog clock (low swing) (HSEBYP=1, HSEEXT=0)
14 /// Use an internal medium speed oscillator (MSIS) as the system clock. 18 Bypass,
15 MSI(Msirange), 19 /// external digital clock (full swing) (HSEBYP=1, HSEEXT=1)
16 /// Use the external high speed clock as the system clock. 20 BypassDigital,
17 ///
18 /// HSE clocks faster than 25 MHz require at least `VoltageScale::RANGE3`, and HSE clocks must
19 /// never exceed 50 MHz.
20 HSE(Hertz),
21 /// Use the 16 MHz internal high speed oscillator as the system clock.
22 HSI,
23 /// Use PLL1 as the system clock.
24 PLL1_R(PllConfig),
25} 21}
26 22
27impl Default for ClockSrc { 23#[derive(Clone, Copy, Eq, PartialEq)]
28 fn default() -> Self { 24pub struct Hse {
29 // The default system clock source is MSIS @ 4 MHz, per RM0456 § 11.4.9 25 /// HSE frequency.
30 ClockSrc::MSI(Msirange::RANGE_4MHZ) 26 pub freq: Hertz,
31 } 27 /// HSE mode.
28 pub mode: HseMode,
32} 29}
33 30
34#[derive(Clone, Copy)] 31#[derive(Clone, Copy)]
35pub struct PllConfig { 32pub struct Pll {
36 /// The clock source for the PLL. 33 /// The clock source for the PLL.
37 pub source: PllSource, 34 pub source: PllSource,
38 /// The PLL prescaler. 35 /// The PLL pre-divider.
39 /// 36 ///
40 /// The clock speed of the `source` divided by `m` must be between 4 and 16 MHz. 37 /// The clock speed of the `source` divided by `m` must be between 4 and 16 MHz.
41 pub m: Pllm, 38 pub prediv: PllPreDiv,
42 /// The PLL multiplier. 39 /// The PLL multiplier.
43 /// 40 ///
44 /// The multiplied clock – `source` divided by `m` times `n` – must be between 128 and 544 41 /// The multiplied clock – `source` divided by `m` times `n` – must be between 128 and 544
45 /// MHz. The upper limit may be lower depending on the `Config { voltage_range }`. 42 /// MHz. The upper limit may be lower depending on the `Config { voltage_range }`.
46 pub n: Plln, 43 pub mul: PllMul,
47 /// The divider for the P output. 44 /// The divider for the P output.
48 /// 45 ///
49 /// The P output is one of several options 46 /// The P output is one of several options
50 /// that can be used to feed the SAI/MDF/ADF Clock mux's. 47 /// that can be used to feed the SAI/MDF/ADF Clock mux's.
51 pub p: Plldiv, 48 pub divp: Option<PllDiv>,
52 /// The divider for the Q output. 49 /// The divider for the Q output.
53 /// 50 ///
54 /// The Q ouput is one of severals options that can be used to feed the 48MHz clocks 51 /// The Q ouput is one of severals options that can be used to feed the 48MHz clocks
55 /// and the OCTOSPI clock. It may also be used on the MDF/ADF clock mux's. 52 /// and the OCTOSPI clock. It may also be used on the MDF/ADF clock mux's.
56 pub q: Plldiv, 53 pub divq: Option<PllDiv>,
57 /// The divider for the R output. 54 /// The divider for the R output.
58 /// 55 ///
59 /// When used to drive the system clock, `source` divided by `m` times `n` divided by `r` 56 /// When used to drive the system clock, `source` divided by `m` times `n` divided by `r`
60 /// must not exceed 160 MHz. System clocks above 55 MHz require a non-default 57 /// must not exceed 160 MHz. System clocks above 55 MHz require a non-default
61 /// `Config { voltage_range }`. 58 /// `Config { voltage_range }`.
62 pub r: Plldiv, 59 pub divr: Option<PllDiv>,
63}
64
65impl PllConfig {
66 /// A configuration for HSI / 1 * 10 / 1 = 160 MHz
67 pub const fn hsi_160mhz() -> Self {
68 PllConfig {
69 source: PllSource::HSI,
70 m: Pllm::DIV1,
71 n: Plln::MUL10,
72 p: Plldiv::DIV3,
73 q: Plldiv::DIV2,
74 r: Plldiv::DIV1,
75 }
76 }
77
78 /// A configuration for MSIS @ 48 MHz / 3 * 10 / 1 = 160 MHz
79 pub const fn msis_160mhz() -> Self {
80 PllConfig {
81 source: PllSource::MSIS(Msirange::RANGE_48MHZ),
82 m: Pllm::DIV3,
83 n: Plln::MUL10,
84 p: Plldiv::DIV3,
85 q: Plldiv::DIV2,
86 r: Plldiv::DIV1,
87 }
88 }
89}
90
91#[derive(Clone, Copy)]
92pub enum PllSource {
93 /// Use an internal medium speed oscillator as the PLL source.
94 MSIS(Msirange),
95 /// Use the external high speed clock as the system PLL source.
96 ///
97 /// HSE clocks faster than 25 MHz require at least `VoltageScale::RANGE3`, and HSE clocks must
98 /// never exceed 50 MHz.
99 HSE(Hertz),
100 /// Use the 16 MHz internal high speed oscillator as the PLL source.
101 HSI,
102} 60}
103 61
104impl Into<Pllsrc> for PllSource { 62pub struct Config {
105 fn into(self) -> Pllsrc { 63 // base clock sources
106 match self { 64 pub msi: Option<MSIRange>,
107 PllSource::MSIS(..) => Pllsrc::MSIS, 65 pub hsi: bool,
108 PllSource::HSE(..) => Pllsrc::HSE, 66 pub hse: Option<Hse>,
109 PllSource::HSI => Pllsrc::HSI, 67 pub hsi48: Option<super::Hsi48Config>,
110 }
111 }
112}
113 68
114impl Into<Sw> for ClockSrc { 69 // pll
115 fn into(self) -> Sw { 70 pub pll1: Option<Pll>,
116 match self { 71 pub pll2: Option<Pll>,
117 ClockSrc::MSI(..) => Sw::MSIS, 72 pub pll3: Option<Pll>,
118 ClockSrc::HSE(..) => Sw::HSE,
119 ClockSrc::HSI => Sw::HSI,
120 ClockSrc::PLL1_R(..) => Sw::PLL1_R,
121 }
122 }
123}
124 73
125pub struct Config { 74 // sysclk, buses.
126 pub mux: ClockSrc, 75 pub mux: ClockSrc,
127 pub ahb_pre: AHBPrescaler, 76 pub ahb_pre: AHBPrescaler,
128 pub apb1_pre: APBPrescaler, 77 pub apb1_pre: APBPrescaler,
129 pub apb2_pre: APBPrescaler, 78 pub apb2_pre: APBPrescaler,
130 pub apb3_pre: APBPrescaler, 79 pub apb3_pre: APBPrescaler,
131 pub hsi48: Option<super::Hsi48Config>, 80
132 /// The voltage range influences the maximum clock frequencies for different parts of the 81 /// The voltage range influences the maximum clock frequencies for different parts of the
133 /// device. In particular, system clocks exceeding 110 MHz require `RANGE1`, and system clocks 82 /// device. In particular, system clocks exceeding 110 MHz require `RANGE1`, and system clocks
134 /// exceeding 55 MHz require at least `RANGE2`. 83 /// exceeding 55 MHz require at least `RANGE2`.
@@ -138,35 +87,35 @@ pub struct Config {
138 pub ls: super::LsConfig, 87 pub ls: super::LsConfig,
139} 88}
140 89
141impl Config { 90impl Default for Config {
142 unsafe fn init_hsi(&self) -> Hertz { 91 fn default() -> Self {
143 RCC.cr().write(|w| w.set_hsion(true)); 92 Self {
144 while !RCC.cr().read().hsirdy() {} 93 msi: Some(Msirange::RANGE_4MHZ),
145 94 hse: None,
146 HSI_FREQ 95 hsi: false,
147 } 96 hsi48: Some(Default::default()),
148 97 pll1: None,
149 unsafe fn init_hse(&self, frequency: Hertz) -> Hertz { 98 pll2: None,
150 // Check frequency limits per RM456 § 11.4.10 99 pll3: None,
151 match self.voltage_range { 100 mux: ClockSrc::MSIS,
152 VoltageScale::RANGE1 | VoltageScale::RANGE2 | VoltageScale::RANGE3 => { 101 ahb_pre: AHBPrescaler::DIV1,
153 assert!(frequency.0 <= 50_000_000); 102 apb1_pre: APBPrescaler::DIV1,
154 } 103 apb2_pre: APBPrescaler::DIV1,
155 VoltageScale::RANGE4 => { 104 apb3_pre: APBPrescaler::DIV1,
156 assert!(frequency.0 <= 25_000_000); 105 voltage_range: VoltageScale::RANGE1,
157 } 106 ls: Default::default(),
158 } 107 }
159
160 // Enable HSE, and wait for it to stabilize
161 RCC.cr().write(|w| w.set_hseon(true));
162 while !RCC.cr().read().hserdy() {}
163
164 frequency
165 } 108 }
109}
110
111pub(crate) unsafe fn init(config: Config) {
112 // Set the requested power mode
113 PWR.vosr().modify(|w| w.set_vos(config.voltage_range));
114 while !PWR.vosr().read().vosrdy() {}
166 115
167 unsafe fn init_msis(&self, range: Msirange) -> Hertz { 116 let msi = config.msi.map(|range| {
168 // Check MSI output per RM0456 § 11.4.10 117 // Check MSI output per RM0456 § 11.4.10
169 match self.voltage_range { 118 match config.voltage_range {
170 VoltageScale::RANGE4 => { 119 VoltageScale::RANGE4 => {
171 assert!(msirange_to_hertz(range).0 <= 24_000_000); 120 assert!(msirange_to_hertz(range).0 <= 24_000_000);
172 } 121 }
@@ -191,223 +140,98 @@ impl Config {
191 }); 140 });
192 while !RCC.cr().read().msisrdy() {} 141 while !RCC.cr().read().msisrdy() {}
193 msirange_to_hertz(range) 142 msirange_to_hertz(range)
194 }
195}
196
197impl Default for Config {
198 fn default() -> Self {
199 Self {
200 mux: ClockSrc::default(),
201 ahb_pre: AHBPrescaler::DIV1,
202 apb1_pre: APBPrescaler::DIV1,
203 apb2_pre: APBPrescaler::DIV1,
204 apb3_pre: APBPrescaler::DIV1,
205 hsi48: Some(Default::default()),
206 voltage_range: VoltageScale::RANGE3,
207 ls: Default::default(),
208 }
209 }
210}
211
212pub(crate) unsafe fn init(config: Config) {
213 // Ensure PWR peripheral clock is enabled
214 RCC.ahb3enr().modify(|w| {
215 w.set_pwren(true);
216 }); 143 });
217 RCC.ahb3enr().read(); // synchronize
218 144
219 // Set the requested power mode 145 let hsi = config.hsi.then(|| {
220 PWR.vosr().modify(|w| { 146 RCC.cr().write(|w| w.set_hsion(true));
221 w.set_vos(config.voltage_range); 147 while !RCC.cr().read().hsirdy() {}
148
149 HSI_FREQ
222 }); 150 });
223 while !PWR.vosr().read().vosrdy() {}
224 151
225 let sys_clk = match config.mux { 152 let hse = config.hse.map(|hse| {
226 ClockSrc::MSI(range) => config.init_msis(range), 153 // Check frequency limits per RM456 § 11.4.10
227 ClockSrc::HSE(freq) => config.init_hse(freq), 154 match config.voltage_range {
228 ClockSrc::HSI => config.init_hsi(), 155 VoltageScale::RANGE1 | VoltageScale::RANGE2 | VoltageScale::RANGE3 => {
229 ClockSrc::PLL1_R(pll) => { 156 assert!(hse.freq.0 <= 50_000_000);
230 // Configure the PLL source
231 let source_clk = match pll.source {
232 PllSource::MSIS(range) => config.init_msis(range),
233 PllSource::HSE(hertz) => config.init_hse(hertz),
234 PllSource::HSI => config.init_hsi(),
235 };
236
237 // Calculate the reference clock, which is the source divided by m
238 let reference_clk = source_clk / pll.m;
239
240 // Check limits per RM0456 § 11.4.6
241 assert!(Hertz::mhz(4) <= reference_clk && reference_clk <= Hertz::mhz(16));
242
243 // Calculate the PLL1 VCO clock and PLL1 R output clock
244 let pll1_clk = reference_clk * pll.n;
245 let pll1r_clk = pll1_clk / pll.r;
246
247 // Check system clock per RM0456 § 11.4.9
248 assert!(pll1r_clk <= Hertz::mhz(160));
249
250 // Check PLL clocks per RM0456 § 11.4.10
251 match config.voltage_range {
252 VoltageScale::RANGE1 => {
253 assert!(pll1_clk >= Hertz::mhz(128) && pll1_clk <= Hertz::mhz(544));
254 assert!(pll1r_clk <= Hertz::mhz(208));
255 }
256 VoltageScale::RANGE2 => {
257 assert!(pll1_clk >= Hertz::mhz(128) && pll1_clk <= Hertz::mhz(544));
258 assert!(pll1r_clk <= Hertz::mhz(110));
259 }
260 VoltageScale::RANGE3 => {
261 assert!(pll1_clk >= Hertz::mhz(128) && pll1_clk <= Hertz::mhz(330));
262 assert!(pll1r_clk <= Hertz::mhz(55));
263 }
264 VoltageScale::RANGE4 => {
265 panic!("PLL is unavailable in voltage range 4");
266 }
267 } 157 }
158 VoltageScale::RANGE4 => {
159 assert!(hse.freq.0 <= 25_000_000);
160 }
161 }
268 162
269 // § 10.5.4: if we're targeting >= 55 MHz, we must configure PLL1MBOOST to a prescaler 163 // Enable HSE, and wait for it to stabilize
270 // value that results in an output between 4 and 16 MHz for the PWR EPOD boost 164 RCC.cr().write(|w| {
271 let mboost = if pll1r_clk >= Hertz::mhz(55) { 165 w.set_hseon(true);
272 // source_clk can be up to 50 MHz, so there's just a few cases: 166 w.set_hsebyp(hse.mode != HseMode::Oscillator);
273 if source_clk > Hertz::mhz(32) { 167 w.set_hseext(match hse.mode {
274 // Divide by 4, giving EPOD 8-12.5 MHz 168 HseMode::Oscillator | HseMode::Bypass => Hseext::ANALOG,
275 Pllmboost::DIV4 169 HseMode::BypassDigital => Hseext::DIGITAL,
276 } else if source_clk > Hertz::mhz(16) {
277 // Divide by 2, giving EPOD 8-16 MHz
278 Pllmboost::DIV2
279 } else {
280 // Bypass, giving EPOD 4-16 MHz
281 Pllmboost::DIV1
282 }
283 } else {
284 // Nothing to do
285 Pllmboost::DIV1
286 };
287
288 // Disable the PLL, and wait for it to disable
289 RCC.cr().modify(|w| w.set_pllon(0, false));
290 while RCC.cr().read().pllrdy(0) {}
291
292 // Configure the PLL
293 RCC.pll1cfgr().write(|w| {
294 // Configure PLL1 source and prescaler
295 w.set_pllsrc(pll.source.into());
296 w.set_pllm(pll.m);
297
298 // Configure PLL1 input frequncy range
299 let input_range = if reference_clk <= Hertz::mhz(8) {
300 Pllrge::FREQ_4TO8MHZ
301 } else {
302 Pllrge::FREQ_8TO16MHZ
303 };
304 w.set_pllrge(input_range);
305
306 // Set the prescaler for PWR EPOD
307 w.set_pllmboost(mboost);
308
309 // Enable PLL1_R output
310 w.set_pllren(true);
311 }); 170 });
171 });
172 while !RCC.cr().read().hserdy() {}
312 173
313 // Configure the PLL divisors 174 hse.freq
314 RCC.pll1divr().modify(|w| { 175 });
315 // Set the VCO multiplier
316 w.set_plln(pll.n);
317 w.set_pllp(pll.p);
318 w.set_pllq(pll.q);
319 // Set the R output divisor
320 w.set_pllr(pll.r);
321 });
322 176
323 // Do we need the EPOD booster to reach the target clock speed per § 10.5.4? 177 let hsi48 = config.hsi48.map(super::init_hsi48);
324 if pll1r_clk >= Hertz::mhz(55) {
325 // Enable the booster
326 PWR.vosr().modify(|w| {
327 w.set_boosten(true);
328 });
329 while !PWR.vosr().read().boostrdy() {}
330 }
331 178
332 // Enable the PLL 179 let pll_input = PllInput { hse, hsi, msi };
333 RCC.cr().modify(|w| w.set_pllon(0, true)); 180 let pll1 = init_pll(PllInstance::Pll1, config.pll1, &pll_input, config.voltage_range);
334 while !RCC.cr().read().pllrdy(0) {} 181 let pll2 = init_pll(PllInstance::Pll2, config.pll2, &pll_input, config.voltage_range);
182 let pll3 = init_pll(PllInstance::Pll3, config.pll3, &pll_input, config.voltage_range);
335 183
336 pll1r_clk 184 let sys_clk = match config.mux {
337 } 185 ClockSrc::HSE => hse.unwrap(),
186 ClockSrc::HSI => hsi.unwrap(),
187 ClockSrc::MSIS => msi.unwrap(),
188 ClockSrc::PLL1_R => pll1.r.unwrap(),
338 }; 189 };
339 190
340 let hsi48 = config.hsi48.map(super::init_hsi48); 191 // Do we need the EPOD booster to reach the target clock speed per § 10.5.4?
192 if sys_clk >= Hertz::mhz(55) {
193 // Enable the booster
194 PWR.vosr().modify(|w| w.set_boosten(true));
195 while !PWR.vosr().read().boostrdy() {}
196 }
341 197
342 // The clock source is ready 198 // The clock source is ready
343 // Calculate and set the flash wait states 199 // Calculate and set the flash wait states
344 let wait_states = match config.voltage_range { 200 let wait_states = match config.voltage_range {
345 // VOS 1 range VCORE 1.26V - 1.40V 201 // VOS 1 range VCORE 1.26V - 1.40V
346 VoltageScale::RANGE1 => { 202 VoltageScale::RANGE1 => match sys_clk.0 {
347 if sys_clk.0 < 32_000_000 { 203 ..=32_000_000 => 0,
348 0 204 ..=64_000_000 => 1,
349 } else if sys_clk.0 < 64_000_000 { 205 ..=96_000_000 => 2,
350 1 206 ..=128_000_000 => 3,
351 } else if sys_clk.0 < 96_000_000 { 207 _ => 4,
352 2 208 },
353 } else if sys_clk.0 < 128_000_000 {
354 3
355 } else {
356 4
357 }
358 }
359 // VOS 2 range VCORE 1.15V - 1.26V 209 // VOS 2 range VCORE 1.15V - 1.26V
360 VoltageScale::RANGE2 => { 210 VoltageScale::RANGE2 => match sys_clk.0 {
361 if sys_clk.0 < 30_000_000 { 211 ..=30_000_000 => 0,
362 0 212 ..=60_000_000 => 1,
363 } else if sys_clk.0 < 60_000_000 { 213 ..=90_000_000 => 2,
364 1 214 _ => 3,
365 } else if sys_clk.0 < 90_000_000 { 215 },
366 2
367 } else {
368 3
369 }
370 }
371 // VOS 3 range VCORE 1.05V - 1.15V 216 // VOS 3 range VCORE 1.05V - 1.15V
372 VoltageScale::RANGE3 => { 217 VoltageScale::RANGE3 => match sys_clk.0 {
373 if sys_clk.0 < 24_000_000 { 218 ..=24_000_000 => 0,
374 0 219 ..=48_000_000 => 1,
375 } else if sys_clk.0 < 48_000_000 { 220 _ => 2,
376 1 221 },
377 } else {
378 2
379 }
380 }
381 // VOS 4 range VCORE 0.95V - 1.05V 222 // VOS 4 range VCORE 0.95V - 1.05V
382 VoltageScale::RANGE4 => { 223 VoltageScale::RANGE4 => match sys_clk.0 {
383 if sys_clk.0 < 12_000_000 { 224 ..=12_000_000 => 0,
384 0 225 _ => 1,
385 } else { 226 },
386 1
387 }
388 }
389 }; 227 };
390 FLASH.acr().modify(|w| { 228 FLASH.acr().modify(|w| {
391 w.set_latency(wait_states); 229 w.set_latency(wait_states);
392 }); 230 });
393 231
394 // Switch the system clock source 232 // Switch the system clock source
395 RCC.cfgr1().modify(|w| { 233 RCC.cfgr1().modify(|w| w.set_sw(config.mux));
396 w.set_sw(config.mux.into()); 234 while RCC.cfgr1().read().sws() != config.mux {}
397 });
398
399 // RM0456 § 11.4.9 specifies maximum bus frequencies per voltage range, but the maximum bus
400 // frequency for each voltage range exactly matches the maximum permitted PLL output frequency.
401 // Given that:
402 //
403 // 1. Any bus frequency can never exceed the system clock frequency;
404 // 2. We checked the PLL output frequency if we're using it as a system clock;
405 // 3. The maximum HSE frequencies at each voltage range are lower than the bus limits, and
406 // we checked the HSE frequency if configured as a system clock; and
407 // 4. The maximum frequencies from the other clock sources are lower than the lowest bus
408 // frequency limit
409 //
410 // ...then we do not need to perform additional bus-related frequency checks.
411 235
412 // Configure the bus prescalers 236 // Configure the bus prescalers
413 RCC.cfgr2().modify(|w| { 237 RCC.cfgr2().modify(|w| {
@@ -419,64 +243,52 @@ pub(crate) unsafe fn init(config: Config) {
419 w.set_ppre3(config.apb3_pre); 243 w.set_ppre3(config.apb3_pre);
420 }); 244 });
421 245
422 let ahb_freq = sys_clk / config.ahb_pre; 246 let hclk = sys_clk / config.ahb_pre;
423
424 let (apb1_freq, apb1_tim_freq) = match config.apb1_pre {
425 APBPrescaler::DIV1 => (ahb_freq, ahb_freq),
426 pre => {
427 let freq = ahb_freq / pre;
428 (freq, freq * 2u32)
429 }
430 };
431 247
432 let (apb2_freq, apb2_tim_freq) = match config.apb2_pre { 248 let hclk_max = match config.voltage_range {
433 APBPrescaler::DIV1 => (ahb_freq, ahb_freq), 249 VoltageScale::RANGE1 => Hertz::mhz(160),
434 pre => { 250 VoltageScale::RANGE2 => Hertz::mhz(110),
435 let freq = ahb_freq / pre; 251 VoltageScale::RANGE3 => Hertz::mhz(55),
436 (freq, freq * 2u32) 252 VoltageScale::RANGE4 => Hertz::mhz(25),
437 }
438 }; 253 };
254 assert!(hclk <= hclk_max);
439 255
440 let (apb3_freq, _apb3_tim_freq) = match config.apb3_pre { 256 let (pclk1, pclk1_tim) = super::util::calc_pclk(hclk, config.apb1_pre);
441 APBPrescaler::DIV1 => (ahb_freq, ahb_freq), 257 let (pclk2, pclk2_tim) = super::util::calc_pclk(hclk, config.apb2_pre);
442 pre => { 258 let (pclk3, _) = super::util::calc_pclk(hclk, config.apb3_pre);
443 let freq = ahb_freq / pre;
444 (freq, freq * 2u32)
445 }
446 };
447 259
448 let rtc = config.ls.init(); 260 let rtc = config.ls.init();
449 261
450 set_clocks!( 262 set_clocks!(
451 sys: Some(sys_clk), 263 sys: Some(sys_clk),
452 hclk1: Some(ahb_freq), 264 hclk1: Some(hclk),
453 hclk2: Some(ahb_freq), 265 hclk2: Some(hclk),
454 hclk3: Some(ahb_freq), 266 hclk3: Some(hclk),
455 pclk1: Some(apb1_freq), 267 pclk1: Some(pclk1),
456 pclk2: Some(apb2_freq), 268 pclk2: Some(pclk2),
457 pclk3: Some(apb3_freq), 269 pclk3: Some(pclk3),
458 pclk1_tim: Some(apb1_tim_freq), 270 pclk1_tim: Some(pclk1_tim),
459 pclk2_tim: Some(apb2_tim_freq), 271 pclk2_tim: Some(pclk2_tim),
460 hsi48: hsi48, 272 hsi48: hsi48,
461 rtc: rtc, 273 rtc: rtc,
274 hse: hse,
275 hsi: hsi,
276 pll1_p: pll1.p,
277 pll1_q: pll1.q,
278 pll1_r: pll1.r,
279 pll2_p: pll2.p,
280 pll2_q: pll2.q,
281 pll2_r: pll2.r,
282 pll3_p: pll3.p,
283 pll3_q: pll3.q,
284 pll3_r: pll3.r,
462 285
463 // TODO 286 // TODO
464 hse: None,
465 hsi: None,
466 audioclk: None, 287 audioclk: None,
467 hsi48_div_2: None, 288 hsi48_div_2: None,
468 lse: None, 289 lse: None,
469 lsi: None, 290 lsi: None,
470 msik: None, 291 msik: None,
471 pll1_p: None,
472 pll1_q: None,
473 pll1_r: None,
474 pll2_p: None,
475 pll2_q: None,
476 pll2_r: None,
477 pll3_p: None,
478 pll3_q: None,
479 pll3_r: None,
480 iclk: None, 292 iclk: None,
481 ); 293 );
482} 294}
@@ -501,3 +313,126 @@ fn msirange_to_hertz(range: Msirange) -> Hertz {
501 Msirange::RANGE_100KHZ => Hertz(100_000), 313 Msirange::RANGE_100KHZ => Hertz(100_000),
502 } 314 }
503} 315}
316
317pub(super) struct PllInput {
318 pub hsi: Option<Hertz>,
319 pub hse: Option<Hertz>,
320 pub msi: Option<Hertz>,
321}
322
323#[allow(unused)]
324#[derive(Default)]
325pub(super) struct PllOutput {
326 pub p: Option<Hertz>,
327 pub q: Option<Hertz>,
328 pub r: Option<Hertz>,
329}
330
331#[derive(PartialEq, Eq, Clone, Copy)]
332enum PllInstance {
333 Pll1 = 0,
334 Pll2 = 1,
335 Pll3 = 2,
336}
337
338fn pll_enable(instance: PllInstance, enabled: bool) {
339 RCC.cr().modify(|w| w.set_pllon(instance as _, enabled));
340 while RCC.cr().read().pllrdy(instance as _) != enabled {}
341}
342
343fn init_pll(instance: PllInstance, config: Option<Pll>, input: &PllInput, voltage_range: VoltageScale) -> PllOutput {
344 // Disable PLL
345 pll_enable(instance, false);
346
347 let Some(pll) = config else { return PllOutput::default() };
348
349 let src_freq = match pll.source {
350 PllSource::DISABLE => panic!("must not select PLL source as DISABLE"),
351 PllSource::HSE => unwrap!(input.hse),
352 PllSource::HSI => unwrap!(input.hsi),
353 PllSource::MSIS => unwrap!(input.msi),
354 };
355
356 // Calculate the reference clock, which is the source divided by m
357 let ref_freq = src_freq / pll.prediv;
358 // Check limits per RM0456 § 11.4.6
359 assert!(Hertz::mhz(4) <= ref_freq && ref_freq <= Hertz::mhz(16));
360
361 // Check PLL clocks per RM0456 § 11.4.10
362 let (vco_min, vco_max, out_max) = match voltage_range {
363 VoltageScale::RANGE1 => (Hertz::mhz(128), Hertz::mhz(544), Hertz::mhz(208)),
364 VoltageScale::RANGE2 => (Hertz::mhz(128), Hertz::mhz(544), Hertz::mhz(110)),
365 VoltageScale::RANGE3 => (Hertz::mhz(128), Hertz::mhz(330), Hertz::mhz(55)),
366 VoltageScale::RANGE4 => panic!("PLL is unavailable in voltage range 4"),
367 };
368
369 // Calculate the PLL VCO clock
370 let vco_freq = ref_freq * pll.mul;
371 assert!(vco_freq >= vco_min && vco_freq <= vco_max);
372
373 // Calculate output clocks.
374 let p = pll.divp.map(|div| vco_freq / div);
375 let q = pll.divq.map(|div| vco_freq / div);
376 let r = pll.divr.map(|div| vco_freq / div);
377 for freq in [p, q, r] {
378 if let Some(freq) = freq {
379 assert!(freq <= out_max);
380 }
381 }
382
383 let divr = match instance {
384 PllInstance::Pll1 => RCC.pll1divr(),
385 PllInstance::Pll2 => RCC.pll2divr(),
386 PllInstance::Pll3 => RCC.pll3divr(),
387 };
388 divr.write(|w| {
389 w.set_plln(pll.mul);
390 w.set_pllp(pll.divp.unwrap_or(PllDiv::DIV1));
391 w.set_pllq(pll.divq.unwrap_or(PllDiv::DIV1));
392 w.set_pllr(pll.divr.unwrap_or(PllDiv::DIV1));
393 });
394
395 let input_range = match ref_freq.0 {
396 ..=8_000_000 => Pllrge::FREQ_4TO8MHZ,
397 _ => Pllrge::FREQ_8TO16MHZ,
398 };
399
400 macro_rules! write_fields {
401 ($w:ident) => {
402 $w.set_pllpen(pll.divp.is_some());
403 $w.set_pllqen(pll.divq.is_some());
404 $w.set_pllren(pll.divr.is_some());
405 $w.set_pllm(pll.prediv);
406 $w.set_pllsrc(pll.source);
407 $w.set_pllrge(input_range);
408 };
409 }
410
411 match instance {
412 PllInstance::Pll1 => RCC.pll1cfgr().write(|w| {
413 // § 10.5.4: if we're targeting >= 55 MHz, we must configure PLL1MBOOST to a prescaler
414 // value that results in an output between 4 and 16 MHz for the PWR EPOD boost
415 if r.unwrap() >= Hertz::mhz(55) {
416 // source_clk can be up to 50 MHz, so there's just a few cases:
417 let mboost = match src_freq.0 {
418 ..=16_000_000 => Pllmboost::DIV1, // Bypass, giving EPOD 4-16 MHz
419 ..=32_000_000 => Pllmboost::DIV2, // Divide by 2, giving EPOD 8-16 MHz
420 _ => Pllmboost::DIV4, // Divide by 4, giving EPOD 8-12.5 MHz
421 };
422 w.set_pllmboost(mboost);
423 }
424 write_fields!(w);
425 }),
426 PllInstance::Pll2 => RCC.pll2cfgr().write(|w| {
427 write_fields!(w);
428 }),
429 PllInstance::Pll3 => RCC.pll3cfgr().write(|w| {
430 write_fields!(w);
431 }),
432 }
433
434 // Enable PLL
435 pll_enable(instance, true);
436
437 PllOutput { p, q, r }
438}
diff --git a/embassy-stm32/src/timer/mod.rs b/embassy-stm32/src/timer/mod.rs
index 9480d6972..9397da2a1 100644
--- a/embassy-stm32/src/timer/mod.rs
+++ b/embassy-stm32/src/timer/mod.rs
@@ -65,17 +65,17 @@ pub(crate) mod sealed {
65 fn regs_core() -> crate::pac::timer::TimCore; 65 fn regs_core() -> crate::pac::timer::TimCore;
66 66
67 /// Start the timer. 67 /// Start the timer.
68 fn start(&mut self) { 68 fn start(&self) {
69 Self::regs_core().cr1().modify(|r| r.set_cen(true)); 69 Self::regs_core().cr1().modify(|r| r.set_cen(true));
70 } 70 }
71 71
72 /// Stop the timer. 72 /// Stop the timer.
73 fn stop(&mut self) { 73 fn stop(&self) {
74 Self::regs_core().cr1().modify(|r| r.set_cen(false)); 74 Self::regs_core().cr1().modify(|r| r.set_cen(false));
75 } 75 }
76 76
77 /// Reset the counter value to 0 77 /// Reset the counter value to 0
78 fn reset(&mut self) { 78 fn reset(&self) {
79 Self::regs_core().cnt().write(|r| r.set_cnt(0)); 79 Self::regs_core().cnt().write(|r| r.set_cnt(0));
80 } 80 }
81 81
@@ -85,7 +85,7 @@ pub(crate) mod sealed {
85 /// the timer counter will wrap around at the same frequency as is being set. 85 /// the timer counter will wrap around at the same frequency as is being set.
86 /// In center-aligned mode (which not all timers support), the wrap-around frequency is effectively halved 86 /// In center-aligned mode (which not all timers support), the wrap-around frequency is effectively halved
87 /// because it needs to count up and down. 87 /// because it needs to count up and down.
88 fn set_frequency(&mut self, frequency: Hertz) { 88 fn set_frequency(&self, frequency: Hertz) {
89 let f = frequency.0; 89 let f = frequency.0;
90 let timer_f = Self::frequency().0; 90 let timer_f = Self::frequency().0;
91 assert!(f > 0); 91 assert!(f > 0);
@@ -108,7 +108,7 @@ pub(crate) mod sealed {
108 /// Clear update interrupt. 108 /// Clear update interrupt.
109 /// 109 ///
110 /// Returns whether the update interrupt flag was set. 110 /// Returns whether the update interrupt flag was set.
111 fn clear_update_interrupt(&mut self) -> bool { 111 fn clear_update_interrupt(&self) -> bool {
112 let regs = Self::regs_core(); 112 let regs = Self::regs_core();
113 let sr = regs.sr().read(); 113 let sr = regs.sr().read();
114 if sr.uif() { 114 if sr.uif() {
@@ -122,12 +122,12 @@ pub(crate) mod sealed {
122 } 122 }
123 123
124 /// Enable/disable the update interrupt. 124 /// Enable/disable the update interrupt.
125 fn enable_update_interrupt(&mut self, enable: bool) { 125 fn enable_update_interrupt(&self, enable: bool) {
126 Self::regs_core().dier().modify(|r| r.set_uie(enable)); 126 Self::regs_core().dier().modify(|r| r.set_uie(enable));
127 } 127 }
128 128
129 /// Enable/disable autoreload preload. 129 /// Enable/disable autoreload preload.
130 fn set_autoreload_preload(&mut self, enable: bool) { 130 fn set_autoreload_preload(&self, enable: bool) {
131 Self::regs_core().cr1().modify(|r| r.set_arpe(enable)); 131 Self::regs_core().cr1().modify(|r| r.set_arpe(enable));
132 } 132 }
133 133
@@ -154,7 +154,7 @@ pub(crate) mod sealed {
154 fn regs_basic_no_cr2() -> crate::pac::timer::TimBasicNoCr2; 154 fn regs_basic_no_cr2() -> crate::pac::timer::TimBasicNoCr2;
155 155
156 /// Enable/disable the update dma. 156 /// Enable/disable the update dma.
157 fn enable_update_dma(&mut self, enable: bool) { 157 fn enable_update_dma(&self, enable: bool) {
158 Self::regs_basic_no_cr2().dier().modify(|r| r.set_ude(enable)); 158 Self::regs_basic_no_cr2().dier().modify(|r| r.set_ude(enable));
159 } 159 }
160 160
@@ -186,7 +186,7 @@ pub(crate) mod sealed {
186 fn regs_1ch() -> crate::pac::timer::Tim1ch; 186 fn regs_1ch() -> crate::pac::timer::Tim1ch;
187 187
188 /// Set clock divider. 188 /// Set clock divider.
189 fn set_clock_division(&mut self, ckd: vals::Ckd) { 189 fn set_clock_division(&self, ckd: vals::Ckd) {
190 Self::regs_1ch().cr1().modify(|r| r.set_ckd(ckd)); 190 Self::regs_1ch().cr1().modify(|r| r.set_ckd(ckd));
191 } 191 }
192 192
@@ -218,7 +218,7 @@ pub(crate) mod sealed {
218 fn regs_gp16() -> crate::pac::timer::TimGp16; 218 fn regs_gp16() -> crate::pac::timer::TimGp16;
219 219
220 /// Set counting mode. 220 /// Set counting mode.
221 fn set_counting_mode(&mut self, mode: CountingMode) { 221 fn set_counting_mode(&self, mode: CountingMode) {
222 let (cms, dir) = mode.into(); 222 let (cms, dir) = mode.into();
223 223
224 let timer_enabled = Self::regs_core().cr1().read().cen(); 224 let timer_enabled = Self::regs_core().cr1().read().cen();
@@ -237,7 +237,7 @@ pub(crate) mod sealed {
237 } 237 }
238 238
239 /// Set input capture filter. 239 /// Set input capture filter.
240 fn set_input_capture_filter(&mut self, channel: Channel, icf: vals::FilterValue) { 240 fn set_input_capture_filter(&self, channel: Channel, icf: vals::FilterValue) {
241 let raw_channel = channel.index(); 241 let raw_channel = channel.index();
242 Self::regs_gp16() 242 Self::regs_gp16()
243 .ccmr_input(raw_channel / 2) 243 .ccmr_input(raw_channel / 2)
@@ -245,17 +245,17 @@ pub(crate) mod sealed {
245 } 245 }
246 246
247 /// Clear input interrupt. 247 /// Clear input interrupt.
248 fn clear_input_interrupt(&mut self, channel: Channel) { 248 fn clear_input_interrupt(&self, channel: Channel) {
249 Self::regs_gp16().sr().modify(|r| r.set_ccif(channel.index(), false)); 249 Self::regs_gp16().sr().modify(|r| r.set_ccif(channel.index(), false));
250 } 250 }
251 251
252 /// Enable input interrupt. 252 /// Enable input interrupt.
253 fn enable_input_interrupt(&mut self, channel: Channel, enable: bool) { 253 fn enable_input_interrupt(&self, channel: Channel, enable: bool) {
254 Self::regs_gp16().dier().modify(|r| r.set_ccie(channel.index(), enable)); 254 Self::regs_gp16().dier().modify(|r| r.set_ccie(channel.index(), enable));
255 } 255 }
256 256
257 /// Set input capture prescaler. 257 /// Set input capture prescaler.
258 fn set_input_capture_prescaler(&mut self, channel: Channel, factor: u8) { 258 fn set_input_capture_prescaler(&self, channel: Channel, factor: u8) {
259 let raw_channel = channel.index(); 259 let raw_channel = channel.index();
260 Self::regs_gp16() 260 Self::regs_gp16()
261 .ccmr_input(raw_channel / 2) 261 .ccmr_input(raw_channel / 2)
@@ -263,7 +263,7 @@ pub(crate) mod sealed {
263 } 263 }
264 264
265 /// Set input TI selection. 265 /// Set input TI selection.
266 fn set_input_ti_selection(&mut self, channel: Channel, tisel: InputTISelection) { 266 fn set_input_ti_selection(&self, channel: Channel, tisel: InputTISelection) {
267 let raw_channel = channel.index(); 267 let raw_channel = channel.index();
268 Self::regs_gp16() 268 Self::regs_gp16()
269 .ccmr_input(raw_channel / 2) 269 .ccmr_input(raw_channel / 2)
@@ -271,7 +271,7 @@ pub(crate) mod sealed {
271 } 271 }
272 272
273 /// Set input capture mode. 273 /// Set input capture mode.
274 fn set_input_capture_mode(&mut self, channel: Channel, mode: InputCaptureMode) { 274 fn set_input_capture_mode(&self, channel: Channel, mode: InputCaptureMode) {
275 Self::regs_gp16().ccer().modify(|r| match mode { 275 Self::regs_gp16().ccer().modify(|r| match mode {
276 InputCaptureMode::Rising => { 276 InputCaptureMode::Rising => {
277 r.set_ccnp(channel.index(), false); 277 r.set_ccnp(channel.index(), false);
@@ -289,7 +289,7 @@ pub(crate) mod sealed {
289 } 289 }
290 290
291 /// Set output compare mode. 291 /// Set output compare mode.
292 fn set_output_compare_mode(&mut self, channel: Channel, mode: OutputCompareMode) { 292 fn set_output_compare_mode(&self, channel: Channel, mode: OutputCompareMode) {
293 let raw_channel: usize = channel.index(); 293 let raw_channel: usize = channel.index();
294 Self::regs_gp16() 294 Self::regs_gp16()
295 .ccmr_output(raw_channel / 2) 295 .ccmr_output(raw_channel / 2)
@@ -297,14 +297,14 @@ pub(crate) mod sealed {
297 } 297 }
298 298
299 /// Set output polarity. 299 /// Set output polarity.
300 fn set_output_polarity(&mut self, channel: Channel, polarity: OutputPolarity) { 300 fn set_output_polarity(&self, channel: Channel, polarity: OutputPolarity) {
301 Self::regs_gp16() 301 Self::regs_gp16()
302 .ccer() 302 .ccer()
303 .modify(|w| w.set_ccp(channel.index(), polarity.into())); 303 .modify(|w| w.set_ccp(channel.index(), polarity.into()));
304 } 304 }
305 305
306 /// Enable/disable a channel. 306 /// Enable/disable a channel.
307 fn enable_channel(&mut self, channel: Channel, enable: bool) { 307 fn enable_channel(&self, channel: Channel, enable: bool) {
308 Self::regs_gp16().ccer().modify(|w| w.set_cce(channel.index(), enable)); 308 Self::regs_gp16().ccer().modify(|w| w.set_cce(channel.index(), enable));
309 } 309 }
310 310
@@ -314,12 +314,12 @@ pub(crate) mod sealed {
314 } 314 }
315 315
316 /// Set compare value for a channel. 316 /// Set compare value for a channel.
317 fn set_compare_value(&mut self, channel: Channel, value: u16) { 317 fn set_compare_value(&self, channel: Channel, value: u16) {
318 Self::regs_gp16().ccr(channel.index()).modify(|w| w.set_ccr(value)); 318 Self::regs_gp16().ccr(channel.index()).modify(|w| w.set_ccr(value));
319 } 319 }
320 320
321 /// Get capture value for a channel. 321 /// Get capture value for a channel.
322 fn get_capture_value(&mut self, channel: Channel) -> u16 { 322 fn get_capture_value(&self, channel: Channel) -> u16 {
323 Self::regs_gp16().ccr(channel.index()).read().ccr() 323 Self::regs_gp16().ccr(channel.index()).read().ccr()
324 } 324 }
325 325
@@ -329,7 +329,7 @@ pub(crate) mod sealed {
329 } 329 }
330 330
331 /// Set output compare preload. 331 /// Set output compare preload.
332 fn set_output_compare_preload(&mut self, channel: Channel, preload: bool) { 332 fn set_output_compare_preload(&self, channel: Channel, preload: bool) {
333 let channel_index = channel.index(); 333 let channel_index = channel.index();
334 Self::regs_gp16() 334 Self::regs_gp16()
335 .ccmr_output(channel_index / 2) 335 .ccmr_output(channel_index / 2)
@@ -342,7 +342,7 @@ pub(crate) mod sealed {
342 } 342 }
343 343
344 /// Set capture compare DMA selection 344 /// Set capture compare DMA selection
345 fn set_cc_dma_selection(&mut self, ccds: super::vals::Ccds) { 345 fn set_cc_dma_selection(&self, ccds: super::vals::Ccds) {
346 Self::regs_gp16().cr2().modify(|w| w.set_ccds(ccds)) 346 Self::regs_gp16().cr2().modify(|w| w.set_ccds(ccds))
347 } 347 }
348 348
@@ -352,7 +352,7 @@ pub(crate) mod sealed {
352 } 352 }
353 353
354 /// Set capture compare DMA enable state 354 /// Set capture compare DMA enable state
355 fn set_cc_dma_enable_state(&mut self, channel: Channel, ccde: bool) { 355 fn set_cc_dma_enable_state(&self, channel: Channel, ccde: bool) {
356 Self::regs_gp16().dier().modify(|w| w.set_ccde(channel.index(), ccde)) 356 Self::regs_gp16().dier().modify(|w| w.set_ccde(channel.index(), ccde))
357 } 357 }
358 } 358 }
@@ -369,7 +369,7 @@ pub(crate) mod sealed {
369 fn regs_gp32() -> crate::pac::timer::TimGp32; 369 fn regs_gp32() -> crate::pac::timer::TimGp32;
370 370
371 /// Set timer frequency. 371 /// Set timer frequency.
372 fn set_frequency(&mut self, frequency: Hertz) { 372 fn set_frequency(&self, frequency: Hertz) {
373 let f = frequency.0; 373 let f = frequency.0;
374 assert!(f > 0); 374 assert!(f > 0);
375 let timer_f = Self::frequency().0; 375 let timer_f = Self::frequency().0;
@@ -398,12 +398,12 @@ pub(crate) mod sealed {
398 } 398 }
399 399
400 /// Set comapre value for a channel. 400 /// Set comapre value for a channel.
401 fn set_compare_value(&mut self, channel: Channel, value: u32) { 401 fn set_compare_value(&self, channel: Channel, value: u32) {
402 Self::regs_gp32().ccr(channel.index()).modify(|w| w.set_ccr(value)); 402 Self::regs_gp32().ccr(channel.index()).modify(|w| w.set_ccr(value));
403 } 403 }
404 404
405 /// Get capture value for a channel. 405 /// Get capture value for a channel.
406 fn get_capture_value(&mut self, channel: Channel) -> u32 { 406 fn get_capture_value(&self, channel: Channel) -> u32 {
407 Self::regs_gp32().ccr(channel.index()).read().ccr() 407 Self::regs_gp32().ccr(channel.index()).read().ccr()
408 } 408 }
409 409
@@ -430,17 +430,17 @@ pub(crate) mod sealed {
430 fn regs_1ch_cmp() -> crate::pac::timer::Tim1chCmp; 430 fn regs_1ch_cmp() -> crate::pac::timer::Tim1chCmp;
431 431
432 /// Set clock divider for the dead time. 432 /// Set clock divider for the dead time.
433 fn set_dead_time_clock_division(&mut self, value: vals::Ckd) { 433 fn set_dead_time_clock_division(&self, value: vals::Ckd) {
434 Self::regs_1ch_cmp().cr1().modify(|w| w.set_ckd(value)); 434 Self::regs_1ch_cmp().cr1().modify(|w| w.set_ckd(value));
435 } 435 }
436 436
437 /// Set dead time, as a fraction of the max duty value. 437 /// Set dead time, as a fraction of the max duty value.
438 fn set_dead_time_value(&mut self, value: u8) { 438 fn set_dead_time_value(&self, value: u8) {
439 Self::regs_1ch_cmp().bdtr().modify(|w| w.set_dtg(value)); 439 Self::regs_1ch_cmp().bdtr().modify(|w| w.set_dtg(value));
440 } 440 }
441 441
442 /// Enable timer outputs. 442 /// Enable timer outputs.
443 fn enable_outputs(&mut self) { 443 fn enable_outputs(&self) {
444 Self::regs_1ch_cmp().bdtr().modify(|w| w.set_moe(true)); 444 Self::regs_1ch_cmp().bdtr().modify(|w| w.set_moe(true));
445 } 445 }
446 } 446 }
@@ -468,14 +468,14 @@ pub(crate) mod sealed {
468 fn regs_advanced() -> crate::pac::timer::TimAdv; 468 fn regs_advanced() -> crate::pac::timer::TimAdv;
469 469
470 /// Set complementary output polarity. 470 /// Set complementary output polarity.
471 fn set_complementary_output_polarity(&mut self, channel: Channel, polarity: OutputPolarity) { 471 fn set_complementary_output_polarity(&self, channel: Channel, polarity: OutputPolarity) {
472 Self::regs_advanced() 472 Self::regs_advanced()
473 .ccer() 473 .ccer()
474 .modify(|w| w.set_ccnp(channel.index(), polarity.into())); 474 .modify(|w| w.set_ccnp(channel.index(), polarity.into()));
475 } 475 }
476 476
477 /// Enable/disable a complementary channel. 477 /// Enable/disable a complementary channel.
478 fn enable_complementary_channel(&mut self, channel: Channel, enable: bool) { 478 fn enable_complementary_channel(&self, channel: Channel, enable: bool) {
479 Self::regs_advanced() 479 Self::regs_advanced()
480 .ccer() 480 .ccer()
481 .modify(|w| w.set_ccne(channel.index(), enable)); 481 .modify(|w| w.set_ccne(channel.index(), enable));
diff --git a/embassy-stm32/src/usb/usb.rs b/embassy-stm32/src/usb/usb.rs
index 34d6b52fd..be321a19b 100644
--- a/embassy-stm32/src/usb/usb.rs
+++ b/embassy-stm32/src/usb/usb.rs
@@ -264,7 +264,7 @@ impl<'d, T: Instance> Driver<'d, T> {
264 264
265 let regs = T::regs(); 265 let regs = T::regs();
266 266
267 #[cfg(any(stm32l5, stm32wb))] 267 #[cfg(any(stm32l4, stm32l5, stm32wb))]
268 crate::pac::PWR.cr2().modify(|w| w.set_usv(true)); 268 crate::pac::PWR.cr2().modify(|w| w.set_usv(true));
269 269
270 #[cfg(pwr_h5)] 270 #[cfg(pwr_h5)]