diff options
| author | Torin Cooper-Bennun <[email protected]> | 2024-02-27 23:42:50 +0000 |
|---|---|---|
| committer | Torin Cooper-Bennun <[email protected]> | 2024-02-27 23:47:25 +0000 |
| commit | 0ed402fd79a6dfbe4f3b2187a97d160ce7c3140b (patch) | |
| tree | 2ff2759399f1fd11ca880fc519addb8aba443d1f | |
| parent | 62c5df7e5bff50ce8553f675323fabf2e02ea2c6 (diff) | |
stm32: can: fd: refactor out some duplicate code
| -rw-r--r-- | embassy-stm32/src/can/fd/peripheral.rs | 122 | ||||
| -rw-r--r-- | embassy-stm32/src/can/fdcan.rs | 66 | ||||
| -rw-r--r-- | embassy-stm32/src/can/frame.rs | 30 |
3 files changed, 68 insertions, 150 deletions
diff --git a/embassy-stm32/src/can/fd/peripheral.rs b/embassy-stm32/src/can/fd/peripheral.rs index 9c29e4887..7d26a5fe0 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,32 +54,8 @@ 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 | } |
| @@ -194,10 +170,9 @@ impl Registers { | |||
| 194 | 170 | ||
| 195 | #[inline] | 171 | #[inline] |
| 196 | //fn abort_pending_mailbox<PTX, R>(&mut self, idx: Mailbox, pending: PTX) -> Option<R> | 172 | //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 | 173 | //where |
| 199 | // PTX: FnOnce(Mailbox, TxFrameHeader, &[u32]) -> R, | 174 | // PTX: FnOnce(Mailbox, TxFrameHeader, &[u32]) -> R, |
| 200 | { | 175 | pub fn abort_pending_mailbox_generic<F: embedded_can::Frame>(&self, bufidx: usize) -> Option<F> { |
| 201 | if self.abort(bufidx) { | 176 | if self.abort(bufidx) { |
| 202 | let mailbox = self.tx_buffer_element(bufidx); | 177 | let mailbox = self.tx_buffer_element(bufidx); |
| 203 | 178 | ||
| @@ -216,50 +191,11 @@ impl Registers { | |||
| 216 | let mut data = [0u8; 64]; | 191 | let mut data = [0u8; 64]; |
| 217 | data_from_tx_buffer(&mut data, mailbox, len as usize); | 192 | data_from_tx_buffer(&mut data, mailbox, len as usize); |
| 218 | 193 | ||
| 219 | let cd = ClassicData::new(&data).unwrap(); | 194 | if header_reg.rtr().bit() { |
| 220 | Some(ClassicFrame::new(Header::new(id, len, header_reg.rtr().bit()), cd)) | 195 | F::new_remote(id, len as usize) |
| 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 { | 196 | } else { |
| 259 | Header::new(id, len, header_reg.rtr().bit()) | 197 | F::new(id, &data) |
| 260 | }; | 198 | } |
| 261 | |||
| 262 | Some(FdFrame::new(header, cd)) | ||
| 263 | } else { | 199 | } else { |
| 264 | // Abort request failed because the frame was already sent (or being sent) on | 200 | // 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 | 201 | // the bus. All mailboxes are now free. This can happen for small prescaler |
| @@ -272,41 +208,7 @@ impl Registers { | |||
| 272 | /// As Transmit, but if there is a pending frame, `pending` will be called so that the frame can | 208 | /// As Transmit, but if there is a pending frame, `pending` will be called so that the frame can |
| 273 | /// be preserved. | 209 | /// be preserved. |
| 274 | //pub fn transmit_preserve<PTX, P>( | 210 | //pub fn transmit_preserve<PTX, P>( |
| 275 | pub fn write_classic(&self, frame: &ClassicFrame) -> nb::Result<Option<ClassicFrame>, Infallible> { | 211 | pub fn write<F: embedded_can::Frame + CanHeader>(&self, frame: &F) -> nb::Result<Option<F>, 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(); | 212 | let queue_is_full = self.tx_queue_is_full(); |
| 311 | 213 | ||
| 312 | let id = frame.header().id(); | 214 | let id = frame.header().id(); |
| @@ -315,11 +217,11 @@ impl Registers { | |||
| 315 | // Discard the first slot with a lower priority message | 217 | // Discard the first slot with a lower priority message |
| 316 | let (idx, pending_frame) = if queue_is_full { | 218 | let (idx, pending_frame) = if queue_is_full { |
| 317 | if self.is_available(0, id) { | 219 | if self.is_available(0, id) { |
| 318 | (0, self.abort_pending_fd_mailbox(0)) | 220 | (0, self.abort_pending_mailbox_generic(0)) |
| 319 | } else if self.is_available(1, id) { | 221 | } else if self.is_available(1, id) { |
| 320 | (1, self.abort_pending_fd_mailbox(1)) | 222 | (1, self.abort_pending_mailbox_generic(1)) |
| 321 | } else if self.is_available(2, id) { | 223 | } else if self.is_available(2, id) { |
| 322 | (2, self.abort_pending_fd_mailbox(2)) | 224 | (2, self.abort_pending_mailbox_generic(2)) |
| 323 | } else { | 225 | } else { |
| 324 | // For now we bail when there is no lower priority slot available | 226 | // For now we bail when there is no lower priority slot available |
| 325 | // Can this lead to priority inversion? | 227 | // Can this lead to priority inversion? |
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> { | |||
| 633 | impl<'c, 'd, T: Instance> FdcanRx<'d, T> { | 633 | impl<'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..59b9fb08c 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 | ||
| 61 | pub 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 | ||
| 226 | impl 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. |
| @@ -368,3 +388,13 @@ impl embedded_can::Frame for FdFrame { | |||
| 368 | &self.data.raw() | 388 | &self.data.raw() |
| 369 | } | 389 | } |
| 370 | } | 390 | } |
| 391 | |||
| 392 | impl CanHeader for FdFrame { | ||
| 393 | fn from_header(header: Header, data: &[u8]) -> Option<Self> { | ||
| 394 | Some(Self::new(header, FdData::new(data)?)) | ||
| 395 | } | ||
| 396 | |||
| 397 | fn header(&self) -> &Header { | ||
| 398 | self.header() | ||
| 399 | } | ||
| 400 | } | ||
