aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2024-02-28 00:50:40 +0000
committerGitHub <[email protected]>2024-02-28 00:50:40 +0000
commitda4ccb62e441baae2a960485f085c5c0a8a55208 (patch)
tree9ae705ce7d13d67da34a42945f60368c04d23ae5
parent62c5df7e5bff50ce8553f675323fabf2e02ea2c6 (diff)
parenta8da42943fdd57ded612399d18846398cbd011d3 (diff)
Merge pull request #2635 from MaxiluxSystems/fdcan-refactor
stm32: can: fd: some refactoring
-rw-r--r--embassy-stm32/src/can/fd/peripheral.rs164
-rw-r--r--embassy-stm32/src/can/fdcan.rs66
-rw-r--r--embassy-stm32/src/can/frame.rs32
3 files changed, 68 insertions, 194 deletions
diff --git a/embassy-stm32/src/can/fd/peripheral.rs b/embassy-stm32/src/can/fd/peripheral.rs
index 9c29e4887..c5606b883 100644
--- a/embassy-stm32/src/can/fd/peripheral.rs
+++ b/embassy-stm32/src/can/fd/peripheral.rs
@@ -37,7 +37,7 @@ impl Registers {
37 &mut self.msg_ram_mut().receive[fifonr].fxsa[bufnum] 37 &mut self.msg_ram_mut().receive[fifonr].fxsa[bufnum]
38 } 38 }
39 39
40 pub fn read_classic(&self, fifonr: usize) -> Option<(ClassicFrame, u16)> { 40 pub fn read<F: CanHeader>(&self, fifonr: usize) -> Option<(F, u16)> {
41 // Fill level - do we have a msg? 41 // Fill level - do we have a msg?
42 if self.regs.rxfs(fifonr).read().ffl() < 1 { 42 if self.regs.rxfs(fifonr).read().ffl() < 1 {
43 return None; 43 return None;
@@ -54,43 +54,14 @@ impl Registers {
54 54
55 match maybe_header { 55 match maybe_header {
56 Some((header, ts)) => { 56 Some((header, ts)) => {
57 let data = ClassicData::new(&buffer[0..header.len() as usize]); 57 let data = &buffer[0..header.len() as usize];
58 Some((ClassicFrame::new(header, data.unwrap()), ts)) 58 Some((F::from_header(header, data)?, 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 } 59 }
84 None => None, 60 None => None,
85 } 61 }
86 } 62 }
87 63
88 pub fn put_tx_frame(&self, bufidx: usize, header: &Header, buffer: &[u8]) { 64 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); 65 let mailbox = self.tx_buffer_element(bufidx);
95 66
96 mailbox.reset(); 67 mailbox.reset();
@@ -193,11 +164,7 @@ impl Registers {
193 } 164 }
194 165
195 #[inline] 166 #[inline]
196 //fn abort_pending_mailbox<PTX, R>(&mut self, idx: Mailbox, pending: PTX) -> Option<R> 167 pub fn abort_pending_mailbox_generic<F: embedded_can::Frame>(&self, bufidx: usize) -> Option<F> {
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) { 168 if self.abort(bufidx) {
202 let mailbox = self.tx_buffer_element(bufidx); 169 let mailbox = self.tx_buffer_element(bufidx);
203 170
@@ -212,54 +179,14 @@ impl Registers {
212 return None; 179 return None;
213 } 180 }
214 181
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]; 182 let mut data = [0u8; 64];
252 data_from_tx_buffer(&mut data, mailbox, len as usize); 183 data_from_tx_buffer(&mut data, mailbox, len as usize);
253 184
254 let cd = FdData::new(&data).unwrap(); 185 if header_reg.rtr().bit() {
255 186 F::new_remote(id, len as usize)
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 { 187 } else {
259 Header::new(id, len, header_reg.rtr().bit()) 188 F::new(id, &data)
260 }; 189 }
261
262 Some(FdFrame::new(header, cd))
263 } else { 190 } else {
264 // Abort request failed because the frame was already sent (or being sent) on 191 // 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 192 // the bus. All mailboxes are now free. This can happen for small prescaler
@@ -269,10 +196,7 @@ impl Registers {
269 } 196 }
270 } 197 }
271 198
272 /// As Transmit, but if there is a pending frame, `pending` will be called so that the frame can 199 pub fn write<F: embedded_can::Frame + CanHeader>(&self, frame: &F) -> nb::Result<Option<F>, Infallible> {
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(); 200 let queue_is_full = self.tx_queue_is_full();
277 201
278 let id = frame.header().id(); 202 let id = frame.header().id();
@@ -281,45 +205,11 @@ impl Registers {
281 // Discard the first slot with a lower priority message 205 // Discard the first slot with a lower priority message
282 let (idx, pending_frame) = if queue_is_full { 206 let (idx, pending_frame) = if queue_is_full {
283 if self.is_available(0, id) { 207 if self.is_available(0, id) {
284 (0, self.abort_pending_mailbox(0)) 208 (0, self.abort_pending_mailbox_generic(0))
285 } else if self.is_available(1, id) { 209 } else if self.is_available(1, id) {
286 (1, self.abort_pending_mailbox(1)) 210 (1, self.abort_pending_mailbox_generic(1))
287 } else if self.is_available(2, id) { 211 } else if self.is_available(2, id) {
288 (2, self.abort_pending_mailbox(2)) 212 (2, self.abort_pending_mailbox_generic(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 { 213 } else {
324 // For now we bail when there is no lower priority slot available 214 // For now we bail when there is no lower priority slot available
325 // Can this lead to priority inversion? 215 // Can this lead to priority inversion?
@@ -557,8 +447,6 @@ impl Registers {
557 /// parameter to this method. 447 /// parameter to this method.
558 #[inline] 448 #[inline]
559 pub fn set_nominal_bit_timing(&mut self, btr: NominalBitTiming) { 449 pub fn set_nominal_bit_timing(&mut self, btr: NominalBitTiming) {
560 //self.control.config.nbtr = btr;
561
562 self.regs.nbtp().write(|w| { 450 self.regs.nbtp().write(|w| {
563 w.set_nbrp(btr.nbrp() - 1); 451 w.set_nbrp(btr.nbrp() - 1);
564 w.set_ntseg1(btr.ntseg1() - 1); 452 w.set_ntseg1(btr.ntseg1() - 1);
@@ -571,8 +459,6 @@ impl Registers {
571 /// This is not used when frame_transmit is set to anything other than AllowFdCanAndBRS. 459 /// This is not used when frame_transmit is set to anything other than AllowFdCanAndBRS.
572 #[inline] 460 #[inline]
573 pub fn set_data_bit_timing(&mut self, btr: DataBitTiming) { 461 pub fn set_data_bit_timing(&mut self, btr: DataBitTiming) {
574 //self.control.config.dbtr = btr;
575
576 self.regs.dbtp().write(|w| { 462 self.regs.dbtp().write(|w| {
577 w.set_dbrp(btr.dbrp() - 1); 463 w.set_dbrp(btr.dbrp() - 1);
578 w.set_dtseg1(btr.dtseg1() - 1); 464 w.set_dtseg1(btr.dtseg1() - 1);
@@ -590,7 +476,6 @@ impl Registers {
590 #[inline] 476 #[inline]
591 pub fn set_automatic_retransmit(&mut self, enabled: bool) { 477 pub fn set_automatic_retransmit(&mut self, enabled: bool) {
592 self.regs.cccr().modify(|w| w.set_dar(!enabled)); 478 self.regs.cccr().modify(|w| w.set_dar(!enabled));
593 //self.control.config.automatic_retransmit = enabled;
594 } 479 }
595 480
596 /// Configures the transmit pause feature. See 481 /// Configures the transmit pause feature. See
@@ -598,21 +483,18 @@ impl Registers {
598 #[inline] 483 #[inline]
599 pub fn set_transmit_pause(&mut self, enabled: bool) { 484 pub fn set_transmit_pause(&mut self, enabled: bool) {
600 self.regs.cccr().modify(|w| w.set_txp(!enabled)); 485 self.regs.cccr().modify(|w| w.set_txp(!enabled));
601 //self.control.config.transmit_pause = enabled;
602 } 486 }
603 487
604 /// Configures non-iso mode. See [`FdCanConfig::set_non_iso_mode`] 488 /// Configures non-iso mode. See [`FdCanConfig::set_non_iso_mode`]
605 #[inline] 489 #[inline]
606 pub fn set_non_iso_mode(&mut self, enabled: bool) { 490 pub fn set_non_iso_mode(&mut self, enabled: bool) {
607 self.regs.cccr().modify(|w| w.set_niso(enabled)); 491 self.regs.cccr().modify(|w| w.set_niso(enabled));
608 //self.control.config.non_iso_mode = enabled;
609 } 492 }
610 493
611 /// Configures edge filtering. See [`FdCanConfig::set_edge_filtering`] 494 /// Configures edge filtering. See [`FdCanConfig::set_edge_filtering`]
612 #[inline] 495 #[inline]
613 pub fn set_edge_filtering(&mut self, enabled: bool) { 496 pub fn set_edge_filtering(&mut self, enabled: bool) {
614 self.regs.cccr().modify(|w| w.set_efbi(enabled)); 497 self.regs.cccr().modify(|w| w.set_efbi(enabled));
615 //self.control.config.edge_filtering = enabled;
616 } 498 }
617 499
618 /// Configures frame transmission mode. See 500 /// Configures frame transmission mode. See
@@ -632,16 +514,12 @@ impl Registers {
632 #[cfg(not(stm32h7))] 514 #[cfg(not(stm32h7))]
633 w.set_brse(brse); 515 w.set_brse(brse);
634 }); 516 });
635
636 //self.control.config.frame_transmit = fts;
637 } 517 }
638 518
639 /// Sets the protocol exception handling on/off 519 /// Sets the protocol exception handling on/off
640 #[inline] 520 #[inline]
641 pub fn set_protocol_exception_handling(&mut self, enabled: bool) { 521 pub fn set_protocol_exception_handling(&mut self, enabled: bool) {
642 self.regs.cccr().modify(|w| w.set_pxhd(!enabled)); 522 self.regs.cccr().modify(|w| w.set_pxhd(!enabled));
643
644 //self.control.config.protocol_exception_handling = enabled;
645 } 523 }
646 524
647 /// Configures and resets the timestamp counter 525 /// Configures and resets the timestamp counter
@@ -665,8 +543,6 @@ impl Registers {
665 w.set_tcp(tcp); 543 w.set_tcp(tcp);
666 w.set_tss(tss); 544 w.set_tss(tss);
667 }); 545 });
668
669 //self.control.config.timestamp_source = select;
670 } 546 }
671 547
672 #[cfg(not(stm32h7))] 548 #[cfg(not(stm32h7))]
@@ -794,22 +670,6 @@ fn data_from_tx_buffer(buffer: &mut [u8], mailbox: &TxBufferElement, len: usize)
794 } 670 }
795} 671}
796 672
797impl From<&RxFifoElement> for ClassicFrame {
798 fn from(mailbox: &RxFifoElement) -> Self {
799 let header_reg = mailbox.header.read();
800
801 let id = make_id(header_reg.id().bits(), header_reg.xtd().bits());
802 let dlc = header_reg.to_data_length().len();
803 let len = dlc as usize;
804
805 let mut buffer: [u8; 64] = [0; 64];
806 data_from_fifo(&mut buffer, mailbox, len);
807 let data = ClassicData::new(&buffer[0..len]);
808 let header = Header::new(id, dlc, header_reg.rtr().bits());
809 ClassicFrame::new(header, data.unwrap())
810 }
811}
812
813fn extract_frame(mailbox: &RxFifoElement, buffer: &mut [u8]) -> Option<(Header, u16)> { 673fn extract_frame(mailbox: &RxFifoElement, buffer: &mut [u8]) -> Option<(Header, u16)> {
814 let header_reg = mailbox.header.read(); 674 let header_reg = mailbox.header.read();
815 675
diff --git a/embassy-stm32/src/can/fdcan.rs b/embassy-stm32/src/can/fdcan.rs
index 744d756f5..6a4a25cb7 100644
--- a/embassy-stm32/src/can/fdcan.rs
+++ b/embassy-stm32/src/can/fdcan.rs
@@ -58,7 +58,7 @@ impl<T: Instance> interrupt::typelevel::Handler<T::IT0Interrupt> for IT0Interrup
58 if !T::registers().tx_queue_is_full() { 58 if !T::registers().tx_queue_is_full() {
59 match buf.tx_receiver.try_receive() { 59 match buf.tx_receiver.try_receive() {
60 Ok(frame) => { 60 Ok(frame) => {
61 _ = T::registers().write_classic(&frame); 61 _ = T::registers().write(&frame);
62 } 62 }
63 Err(_) => {} 63 Err(_) => {}
64 } 64 }
@@ -68,7 +68,7 @@ impl<T: Instance> interrupt::typelevel::Handler<T::IT0Interrupt> for IT0Interrup
68 if !T::registers().tx_queue_is_full() { 68 if !T::registers().tx_queue_is_full() {
69 match buf.tx_receiver.try_receive() { 69 match buf.tx_receiver.try_receive() {
70 Ok(frame) => { 70 Ok(frame) => {
71 _ = T::registers().write_fd(&frame); 71 _ = T::registers().write(&frame);
72 } 72 }
73 Err(_) => {} 73 Err(_) => {}
74 } 74 }
@@ -359,7 +359,7 @@ impl<'d, T: Instance> Fdcan<'d, T> {
359 359
360 /// Returns the next received message frame 360 /// Returns the next received message frame
361 pub async fn read(&mut self) -> Result<(ClassicFrame, Timestamp), BusError> { 361 pub async fn read(&mut self) -> Result<(ClassicFrame, Timestamp), BusError> {
362 T::state().rx_mode.read::<T>().await 362 T::state().rx_mode.read_classic::<T>().await
363 } 363 }
364 364
365 /// Queues the message to be sent but exerts backpressure. If a lower-priority 365 /// Queues the message to be sent but exerts backpressure. If a lower-priority
@@ -633,7 +633,7 @@ impl<'c, 'd, T: Instance> FdcanTx<'d, T> {
633impl<'c, 'd, T: Instance> FdcanRx<'d, T> { 633impl<'c, 'd, T: Instance> FdcanRx<'d, T> {
634 /// Returns the next received message frame 634 /// Returns the next received message frame
635 pub async fn read(&mut self) -> Result<(ClassicFrame, Timestamp), BusError> { 635 pub async fn read(&mut self) -> Result<(ClassicFrame, Timestamp), BusError> {
636 T::state().rx_mode.read::<T>().await 636 T::state().rx_mode.read_classic::<T>().await
637 } 637 }
638 638
639 /// Returns the next received message frame 639 /// Returns the next received message frame
@@ -649,6 +649,7 @@ pub(crate) mod sealed {
649 use embassy_sync::channel::{DynamicReceiver, DynamicSender}; 649 use embassy_sync::channel::{DynamicReceiver, DynamicSender};
650 use embassy_sync::waitqueue::AtomicWaker; 650 use embassy_sync::waitqueue::AtomicWaker;
651 651
652 use super::CanHeader;
652 use crate::can::_version::{BusError, Timestamp}; 653 use crate::can::_version::{BusError, Timestamp};
653 use crate::can::frame::{ClassicFrame, FdFrame}; 654 use crate::can::frame::{ClassicFrame, FdFrame};
654 655
@@ -689,13 +690,13 @@ pub(crate) mod sealed {
689 waker.wake(); 690 waker.wake();
690 } 691 }
691 RxMode::ClassicBuffered(buf) => { 692 RxMode::ClassicBuffered(buf) => {
692 if let Some(r) = T::registers().read_classic(fifonr) { 693 if let Some(r) = T::registers().read(fifonr) {
693 let ts = T::calc_timestamp(T::state().ns_per_timer_tick, r.1); 694 let ts = T::calc_timestamp(T::state().ns_per_timer_tick, r.1);
694 let _ = buf.rx_sender.try_send((r.0, ts)); 695 let _ = buf.rx_sender.try_send((r.0, ts));
695 } 696 }
696 } 697 }
697 RxMode::FdBuffered(buf) => { 698 RxMode::FdBuffered(buf) => {
698 if let Some(r) = T::registers().read_fd(fifonr) { 699 if let Some(r) = T::registers().read(fifonr) {
699 let ts = T::calc_timestamp(T::state().ns_per_timer_tick, r.1); 700 let ts = T::calc_timestamp(T::state().ns_per_timer_tick, r.1);
700 let _ = buf.rx_sender.try_send((r.0, ts)); 701 let _ = buf.rx_sender.try_send((r.0, ts));
701 } 702 }
@@ -703,15 +704,15 @@ pub(crate) mod sealed {
703 } 704 }
704 } 705 }
705 706
706 pub async fn read<T: Instance>(&self) -> Result<(ClassicFrame, Timestamp), BusError> { 707 async fn read<T: Instance, F: CanHeader>(&self) -> Result<(F, Timestamp), BusError> {
707 poll_fn(|cx| { 708 poll_fn(|cx| {
708 T::state().err_waker.register(cx.waker()); 709 T::state().err_waker.register(cx.waker());
709 self.register(cx.waker()); 710 self.register(cx.waker());
710 711
711 if let Some((msg, ts)) = T::registers().read_classic(0) { 712 if let Some((msg, ts)) = T::registers().read(0) {
712 let ts = T::calc_timestamp(T::state().ns_per_timer_tick, ts); 713 let ts = T::calc_timestamp(T::state().ns_per_timer_tick, ts);
713 return Poll::Ready(Ok((msg, ts))); 714 return Poll::Ready(Ok((msg, ts)));
714 } else if let Some((msg, ts)) = T::registers().read_classic(1) { 715 } else if let Some((msg, ts)) = T::registers().read(1) {
715 let ts = T::calc_timestamp(T::state().ns_per_timer_tick, ts); 716 let ts = T::calc_timestamp(T::state().ns_per_timer_tick, ts);
716 return Poll::Ready(Ok((msg, ts))); 717 return Poll::Ready(Ok((msg, ts)));
717 } else if let Some(err) = T::registers().curr_error() { 718 } else if let Some(err) = T::registers().curr_error() {
@@ -723,24 +724,12 @@ pub(crate) mod sealed {
723 .await 724 .await
724 } 725 }
725 726
726 pub async fn read_fd<T: Instance>(&self) -> Result<(FdFrame, Timestamp), BusError> { 727 pub async fn read_classic<T: Instance>(&self) -> Result<(ClassicFrame, Timestamp), BusError> {
727 poll_fn(|cx| { 728 self.read::<T, _>().await
728 T::state().err_waker.register(cx.waker()); 729 }
729 self.register(cx.waker());
730 730
731 if let Some((msg, ts)) = T::registers().read_fd(0) { 731 pub async fn read_fd<T: Instance>(&self) -> Result<(FdFrame, Timestamp), BusError> {
732 let ts = T::calc_timestamp(T::state().ns_per_timer_tick, ts); 732 self.read::<T, _>().await
733 return Poll::Ready(Ok((msg, ts)));
734 } else if let Some((msg, ts)) = T::registers().read_fd(1) {
735 let ts = T::calc_timestamp(T::state().ns_per_timer_tick, ts);
736 return Poll::Ready(Ok((msg, ts)));
737 } else if let Some(err) = T::registers().curr_error() {
738 // TODO: this is probably wrong
739 return Poll::Ready(Err(err));
740 }
741 Poll::Pending
742 })
743 .await
744 } 733 }
745 } 734 }
746 735
@@ -766,11 +755,11 @@ pub(crate) mod sealed {
766 /// frame is dropped from the mailbox, it is returned. If no lower-priority frames 755 /// frame is dropped from the mailbox, it is returned. If no lower-priority frames
767 /// can be replaced, this call asynchronously waits for a frame to be successfully 756 /// can be replaced, this call asynchronously waits for a frame to be successfully
768 /// transmitted, then tries again. 757 /// transmitted, then tries again.
769 pub async fn write<T: Instance>(&self, frame: &ClassicFrame) -> Option<ClassicFrame> { 758 async fn write_generic<T: Instance, F: embedded_can::Frame + CanHeader>(&self, frame: &F) -> Option<F> {
770 poll_fn(|cx| { 759 poll_fn(|cx| {
771 self.register(cx.waker()); 760 self.register(cx.waker());
772 761
773 if let Ok(dropped) = T::registers().write_classic(frame) { 762 if let Ok(dropped) = T::registers().write(frame) {
774 return Poll::Ready(dropped); 763 return Poll::Ready(dropped);
775 } 764 }
776 765
@@ -785,19 +774,16 @@ pub(crate) mod sealed {
785 /// frame is dropped from the mailbox, it is returned. If no lower-priority frames 774 /// frame is dropped from the mailbox, it is returned. If no lower-priority frames
786 /// can be replaced, this call asynchronously waits for a frame to be successfully 775 /// can be replaced, this call asynchronously waits for a frame to be successfully
787 /// transmitted, then tries again. 776 /// transmitted, then tries again.
788 pub async fn write_fd<T: Instance>(&self, frame: &FdFrame) -> Option<FdFrame> { 777 pub async fn write<T: Instance>(&self, frame: &ClassicFrame) -> Option<ClassicFrame> {
789 poll_fn(|cx| { 778 self.write_generic::<T, _>(frame).await
790 self.register(cx.waker()); 779 }
791
792 if let Ok(dropped) = T::registers().write_fd(frame) {
793 return Poll::Ready(dropped);
794 }
795 780
796 // Couldn't replace any lower priority frames. Need to wait for some mailboxes 781 /// Queues the message to be sent but exerts backpressure. If a lower-priority
797 // to clear. 782 /// frame is dropped from the mailbox, it is returned. If no lower-priority frames
798 Poll::Pending 783 /// can be replaced, this call asynchronously waits for a frame to be successfully
799 }) 784 /// transmitted, then tries again.
800 .await 785 pub async fn write_fd<T: Instance>(&self, frame: &FdFrame) -> Option<FdFrame> {
786 self.write_generic::<T, _>(frame).await
801 } 787 }
802 } 788 }
803 789
diff --git a/embassy-stm32/src/can/frame.rs b/embassy-stm32/src/can/frame.rs
index 725a9b1ab..00a441db6 100644
--- a/embassy-stm32/src/can/frame.rs
+++ b/embassy-stm32/src/can/frame.rs
@@ -56,6 +56,16 @@ impl Header {
56 } 56 }
57} 57}
58 58
59/// Trait for FDCAN frame types, providing ability to construct from a Header
60/// and to retrieve the Header from a frame
61pub trait CanHeader: Sized {
62 /// Construct frame from header and payload
63 fn from_header(header: Header, data: &[u8]) -> Option<Self>;
64
65 /// Get this frame's header struct
66 fn header(&self) -> &Header;
67}
68
59/// Payload of a classic CAN data frame. 69/// Payload of a classic CAN data frame.
60/// 70///
61/// Contains 0 to 8 Bytes of data. 71/// Contains 0 to 8 Bytes of data.
@@ -213,6 +223,16 @@ impl embedded_can::Frame for ClassicFrame {
213 } 223 }
214} 224}
215 225
226impl CanHeader for ClassicFrame {
227 fn from_header(header: Header, data: &[u8]) -> Option<Self> {
228 Some(Self::new(header, ClassicData::new(data)?))
229 }
230
231 fn header(&self) -> &Header {
232 self.header()
233 }
234}
235
216/// Payload of a (FD)CAN data frame. 236/// Payload of a (FD)CAN data frame.
217/// 237///
218/// Contains 0 to 64 Bytes of data. 238/// Contains 0 to 64 Bytes of data.
@@ -272,8 +292,6 @@ pub struct FdFrame {
272} 292}
273 293
274impl FdFrame { 294impl FdFrame {
275 pub(crate) const MAX_DATA_LEN: usize = 64;
276
277 /// Create a new CAN classic Frame 295 /// Create a new CAN classic Frame
278 pub fn new(can_header: Header, data: FdData) -> FdFrame { 296 pub fn new(can_header: Header, data: FdData) -> FdFrame {
279 FdFrame { can_header, data } 297 FdFrame { can_header, data }
@@ -368,3 +386,13 @@ impl embedded_can::Frame for FdFrame {
368 &self.data.raw() 386 &self.data.raw()
369 } 387 }
370} 388}
389
390impl CanHeader for FdFrame {
391 fn from_header(header: Header, data: &[u8]) -> Option<Self> {
392 Some(Self::new(header, FdData::new(data)?))
393 }
394
395 fn header(&self) -> &Header {
396 self.header()
397 }
398}