diff options
| author | Dario Nieuwenhuis <[email protected]> | 2024-02-28 00:50:40 +0000 |
|---|---|---|
| committer | GitHub <[email protected]> | 2024-02-28 00:50:40 +0000 |
| commit | da4ccb62e441baae2a960485f085c5c0a8a55208 (patch) | |
| tree | 9ae705ce7d13d67da34a42945f60368c04d23ae5 | |
| parent | 62c5df7e5bff50ce8553f675323fabf2e02ea2c6 (diff) | |
| parent | a8da42943fdd57ded612399d18846398cbd011d3 (diff) | |
Merge pull request #2635 from MaxiluxSystems/fdcan-refactor
stm32: can: fd: some refactoring
| -rw-r--r-- | embassy-stm32/src/can/fd/peripheral.rs | 164 | ||||
| -rw-r--r-- | embassy-stm32/src/can/fdcan.rs | 66 | ||||
| -rw-r--r-- | embassy-stm32/src/can/frame.rs | 32 |
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 | ||
| 797 | impl 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 | |||
| 813 | fn extract_frame(mailbox: &RxFifoElement, buffer: &mut [u8]) -> Option<(Header, u16)> { | 673 | fn 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> { | |||
| 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..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 | ||
| 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. |
| @@ -272,8 +292,6 @@ pub struct FdFrame { | |||
| 272 | } | 292 | } |
| 273 | 293 | ||
| 274 | impl FdFrame { | 294 | impl 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 | |||
| 390 | impl 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 | } | ||
