aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2024-05-30 12:16:17 +0000
committerGitHub <[email protected]>2024-05-30 12:16:17 +0000
commitb378ec4558306a7d10572301b7e078c055bc47ac (patch)
treec44d01880527615a844d7bc7a1c86c9def345909
parent39c5a6c3f7fe294bc7c5e6beaa0eac67399e62f9 (diff)
parentb4a2f7fb70ac3f0b0d9226ab5ff5aab7a5bf8649 (diff)
Merge pull request #3020 from cschuhen/feature/bxcan_no_generics
Remove generics for BXCAN.
-rw-r--r--embassy-stm32/src/can/bxcan/mod.rs294
-rw-r--r--embassy-stm32/src/can/bxcan/registers.rs12
-rw-r--r--examples/stm32f7/src/bin/can.rs4
-rw-r--r--tests/stm32/src/bin/can.rs4
4 files changed, 200 insertions, 114 deletions
diff --git a/embassy-stm32/src/can/bxcan/mod.rs b/embassy-stm32/src/can/bxcan/mod.rs
index ac225d7d2..69e20e909 100644
--- a/embassy-stm32/src/can/bxcan/mod.rs
+++ b/embassy-stm32/src/can/bxcan/mod.rs
@@ -5,6 +5,7 @@ use core::future::poll_fn;
5use core::marker::PhantomData; 5use core::marker::PhantomData;
6use core::task::Poll; 6use core::task::Poll;
7 7
8use embassy_hal_internal::interrupt::InterruptExt;
8use embassy_hal_internal::{into_ref, PeripheralRef}; 9use embassy_hal_internal::{into_ref, PeripheralRef};
9use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; 10use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
10use embassy_sync::channel::Channel; 11use embassy_sync::channel::Channel;
@@ -154,7 +155,9 @@ impl<T: Instance> Drop for CanConfig<'_, T> {
154 155
155/// CAN driver 156/// CAN driver
156pub struct Can<'d, T: Instance> { 157pub struct Can<'d, T: Instance> {
157 peri: PeripheralRef<'d, T>, 158 _peri: PeripheralRef<'d, T>,
159 info: &'static Info,
160 state: &'static State,
158} 161}
159 162
160/// Error returned by `try_write` 163/// Error returned by `try_write`
@@ -179,6 +182,8 @@ impl<'d, T: Instance> Can<'d, T> {
179 + 'd, 182 + 'd,
180 ) -> Self { 183 ) -> Self {
181 into_ref!(peri, rx, tx); 184 into_ref!(peri, rx, tx);
185 let info = T::info();
186 let regs = &T::info().regs;
182 187
183 rx.set_as_af(rx.af_num(), AFType::Input); 188 rx.set_as_af(rx.af_num(), AFType::Input);
184 tx.set_as_af(tx.af_num(), AFType::OutputPushPull); 189 tx.set_as_af(tx.af_num(), AFType::OutputPushPull);
@@ -186,7 +191,7 @@ impl<'d, T: Instance> Can<'d, T> {
186 rcc::enable_and_reset::<T>(); 191 rcc::enable_and_reset::<T>();
187 192
188 { 193 {
189 T::regs().ier().write(|w| { 194 regs.0.ier().write(|w| {
190 w.set_errie(true); 195 w.set_errie(true);
191 w.set_fmpie(0, true); 196 w.set_fmpie(0, true);
192 w.set_fmpie(1, true); 197 w.set_fmpie(1, true);
@@ -197,7 +202,7 @@ impl<'d, T: Instance> Can<'d, T> {
197 w.set_lecie(true); 202 w.set_lecie(true);
198 }); 203 });
199 204
200 T::regs().mcr().write(|w| { 205 regs.0.mcr().write(|w| {
201 // Enable timestamps on rx messages 206 // Enable timestamps on rx messages
202 207
203 w.set_ttcm(true); 208 w.set_ttcm(true);
@@ -205,17 +210,14 @@ impl<'d, T: Instance> Can<'d, T> {
205 } 210 }
206 211
207 unsafe { 212 unsafe {
208 T::TXInterrupt::unpend(); 213 info.tx_interrupt.unpend();
209 T::TXInterrupt::enable(); 214 info.tx_interrupt.enable();
210 215 info.rx0_interrupt.unpend();
211 T::RX0Interrupt::unpend(); 216 info.rx0_interrupt.enable();
212 T::RX0Interrupt::enable(); 217 info.rx1_interrupt.unpend();
213 218 info.rx1_interrupt.enable();
214 T::RX1Interrupt::unpend(); 219 info.sce_interrupt.unpend();
215 T::RX1Interrupt::enable(); 220 info.sce_interrupt.enable();
216
217 T::SCEInterrupt::unpend();
218 T::SCEInterrupt::enable();
219 } 221 }
220 222
221 rx.set_as_af(rx.af_num(), AFType::Input); 223 rx.set_as_af(rx.af_num(), AFType::Input);
@@ -223,7 +225,11 @@ impl<'d, T: Instance> Can<'d, T> {
223 225
224 Registers(T::regs()).leave_init_mode(); 226 Registers(T::regs()).leave_init_mode();
225 227
226 Self { peri } 228 Self {
229 _peri: peri,
230 info: T::info(),
231 state: T::state(),
232 }
227 } 233 }
228 234
229 /// Set CAN bit rate. 235 /// Set CAN bit rate.
@@ -265,12 +271,12 @@ impl<'d, T: Instance> Can<'d, T> {
265 /// Waking the peripheral manually does not trigger a wake-up interrupt. 271 /// Waking the peripheral manually does not trigger a wake-up interrupt.
266 /// This will wait until the peripheral has acknowledged it has awoken from sleep mode 272 /// This will wait until the peripheral has acknowledged it has awoken from sleep mode
267 pub fn wakeup(&mut self) { 273 pub fn wakeup(&mut self) {
268 Registers(T::regs()).wakeup() 274 self.info.regs.wakeup()
269 } 275 }
270 276
271 /// Check if the peripheral is currently in sleep mode 277 /// Check if the peripheral is currently in sleep mode
272 pub fn is_sleeping(&self) -> bool { 278 pub fn is_sleeping(&self) -> bool {
273 T::regs().msr().read().slak() 279 self.info.regs.0.msr().read().slak()
274 } 280 }
275 281
276 /// Put the peripheral in sleep mode 282 /// Put the peripheral in sleep mode
@@ -282,11 +288,11 @@ impl<'d, T: Instance> Can<'d, T> {
282 /// If the peripheral has automatic wakeup enabled, when a Start-of-Frame is detected 288 /// If the peripheral has automatic wakeup enabled, when a Start-of-Frame is detected
283 /// the peripheral will automatically wake and receive the incoming message. 289 /// the peripheral will automatically wake and receive the incoming message.
284 pub async fn sleep(&mut self) { 290 pub async fn sleep(&mut self) {
285 T::regs().ier().modify(|i| i.set_slkie(true)); 291 self.info.regs.0.ier().modify(|i| i.set_slkie(true));
286 T::regs().mcr().modify(|m| m.set_sleep(true)); 292 self.info.regs.0.mcr().modify(|m| m.set_sleep(true));
287 293
288 poll_fn(|cx| { 294 poll_fn(|cx| {
289 T::state().err_waker.register(cx.waker()); 295 self.state.err_waker.register(cx.waker());
290 if self.is_sleeping() { 296 if self.is_sleeping() {
291 Poll::Ready(()) 297 Poll::Ready(())
292 } else { 298 } else {
@@ -295,7 +301,7 @@ impl<'d, T: Instance> Can<'d, T> {
295 }) 301 })
296 .await; 302 .await;
297 303
298 T::regs().ier().modify(|i| i.set_slkie(false)); 304 self.info.regs.0.ier().modify(|i| i.set_slkie(false));
299 } 305 }
300 306
301 /// Enable FIFO scheduling of outgoing frames. 307 /// Enable FIFO scheduling of outgoing frames.
@@ -337,7 +343,13 @@ impl<'d, T: Instance> Can<'d, T> {
337 343
338 /// Waits for a specific transmit mailbox to become empty 344 /// Waits for a specific transmit mailbox to become empty
339 pub async fn flush(&self, mb: Mailbox) { 345 pub async fn flush(&self, mb: Mailbox) {
340 CanTx::<T>::flush_inner(mb).await 346 CanTx {
347 _phantom: PhantomData,
348 info: self.info,
349 state: self.state,
350 }
351 .flush_inner(mb)
352 .await;
341 } 353 }
342 354
343 /// Waits until any of the transmit mailboxes become empty 355 /// Waits until any of the transmit mailboxes become empty
@@ -347,12 +359,24 @@ impl<'d, T: Instance> Can<'d, T> {
347 /// This will happen if FIFO scheduling of outgoing frames is not enabled, 359 /// This will happen if FIFO scheduling of outgoing frames is not enabled,
348 /// and a frame with equal priority is already queued for transmission. 360 /// and a frame with equal priority is already queued for transmission.
349 pub async fn flush_any(&self) { 361 pub async fn flush_any(&self) {
350 CanTx::<T>::flush_any_inner().await 362 CanTx {
363 _phantom: PhantomData,
364 info: self.info,
365 state: self.state,
366 }
367 .flush_any_inner()
368 .await
351 } 369 }
352 370
353 /// Waits until all of the transmit mailboxes become empty 371 /// Waits until all of the transmit mailboxes become empty
354 pub async fn flush_all(&self) { 372 pub async fn flush_all(&self) {
355 CanTx::<T>::flush_all_inner().await 373 CanTx {
374 _phantom: PhantomData,
375 info: self.info,
376 state: self.state,
377 }
378 .flush_all_inner()
379 .await
356 } 380 }
357 381
358 /// Attempts to abort the sending of a frame that is pending in a mailbox. 382 /// Attempts to abort the sending of a frame that is pending in a mailbox.
@@ -363,12 +387,12 @@ impl<'d, T: Instance> Can<'d, T> {
363 /// If there is a frame in the provided mailbox, and it is canceled successfully, this function 387 /// If there is a frame in the provided mailbox, and it is canceled successfully, this function
364 /// returns `true`. 388 /// returns `true`.
365 pub fn abort(&mut self, mailbox: Mailbox) -> bool { 389 pub fn abort(&mut self, mailbox: Mailbox) -> bool {
366 Registers(T::regs()).abort(mailbox) 390 self.info.regs.abort(mailbox)
367 } 391 }
368 392
369 /// Returns `true` if no frame is pending for transmission. 393 /// Returns `true` if no frame is pending for transmission.
370 pub fn is_transmitter_idle(&self) -> bool { 394 pub fn is_transmitter_idle(&self) -> bool {
371 Registers(T::regs()).is_idle() 395 self.info.regs.is_idle()
372 } 396 }
373 397
374 /// Read a CAN frame. 398 /// Read a CAN frame.
@@ -377,31 +401,35 @@ impl<'d, T: Instance> Can<'d, T> {
377 /// 401 ///
378 /// Returns a tuple of the time the message was received and the message frame 402 /// Returns a tuple of the time the message was received and the message frame
379 pub async fn read(&mut self) -> Result<Envelope, BusError> { 403 pub async fn read(&mut self) -> Result<Envelope, BusError> {
380 T::state().rx_mode.read::<T>().await 404 self.state.rx_mode.read(self.info, self.state).await
381 } 405 }
382 406
383 /// Attempts to read a CAN frame without blocking. 407 /// Attempts to read a CAN frame without blocking.
384 /// 408 ///
385 /// Returns [Err(TryReadError::Empty)] if there are no frames in the rx queue. 409 /// Returns [Err(TryReadError::Empty)] if there are no frames in the rx queue.
386 pub fn try_read(&mut self) -> Result<Envelope, TryReadError> { 410 pub fn try_read(&mut self) -> Result<Envelope, TryReadError> {
387 T::state().rx_mode.try_read::<T>() 411 self.state.rx_mode.try_read(self.info)
388 } 412 }
389 413
390 /// Waits while receive queue is empty. 414 /// Waits while receive queue is empty.
391 pub async fn wait_not_empty(&mut self) { 415 pub async fn wait_not_empty(&mut self) {
392 T::state().rx_mode.wait_not_empty::<T>().await 416 self.state.rx_mode.wait_not_empty(self.info, self.state).await
393 } 417 }
394 418
395 /// Split the CAN driver into transmit and receive halves. 419 /// Split the CAN driver into transmit and receive halves.
396 /// 420 ///
397 /// Useful for doing separate transmit/receive tasks. 421 /// Useful for doing separate transmit/receive tasks.
398 pub fn split<'c>(&'c mut self) -> (CanTx<'d, T>, CanRx<'d, T>) { 422 pub fn split<'c>(&'c mut self) -> (CanTx<'d>, CanRx<'d>) {
399 ( 423 (
400 CanTx { 424 CanTx {
401 _peri: unsafe { self.peri.clone_unchecked() }, 425 _phantom: PhantomData,
426 info: self.info,
427 state: self.state,
402 }, 428 },
403 CanRx { 429 CanRx {
404 peri: unsafe { self.peri.clone_unchecked() }, 430 _phantom: PhantomData,
431 info: self.info,
432 state: self.state,
405 }, 433 },
406 ) 434 )
407 } 435 }
@@ -411,7 +439,7 @@ impl<'d, T: Instance> Can<'d, T> {
411 &'c mut self, 439 &'c mut self,
412 txb: &'static mut TxBuf<TX_BUF_SIZE>, 440 txb: &'static mut TxBuf<TX_BUF_SIZE>,
413 rxb: &'static mut RxBuf<RX_BUF_SIZE>, 441 rxb: &'static mut RxBuf<RX_BUF_SIZE>,
414 ) -> BufferedCan<'d, T, TX_BUF_SIZE, RX_BUF_SIZE> { 442 ) -> BufferedCan<'d, TX_BUF_SIZE, RX_BUF_SIZE> {
415 let (tx, rx) = self.split(); 443 let (tx, rx) = self.split();
416 BufferedCan { 444 BufferedCan {
417 tx: tx.buffered(txb), 445 tx: tx.buffered(txb),
@@ -426,17 +454,17 @@ impl<'d, T: FilterOwner> Can<'d, T> {
426 /// To modify filters of a slave peripheral, `modify_filters` has to be called on the master 454 /// To modify filters of a slave peripheral, `modify_filters` has to be called on the master
427 /// peripheral instead. 455 /// peripheral instead.
428 pub fn modify_filters(&mut self) -> MasterFilters<'_, T> { 456 pub fn modify_filters(&mut self) -> MasterFilters<'_, T> {
429 unsafe { MasterFilters::new(T::regs()) } 457 unsafe { MasterFilters::new(self.info.regs.0) }
430 } 458 }
431} 459}
432 460
433/// Buffered CAN driver. 461/// Buffered CAN driver.
434pub struct BufferedCan<'d, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> { 462pub struct BufferedCan<'d, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> {
435 tx: BufferedCanTx<'d, T, TX_BUF_SIZE>, 463 tx: BufferedCanTx<'d, TX_BUF_SIZE>,
436 rx: BufferedCanRx<'d, T, RX_BUF_SIZE>, 464 rx: BufferedCanRx<'d, RX_BUF_SIZE>,
437} 465}
438 466
439impl<'d, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> BufferedCan<'d, T, TX_BUF_SIZE, RX_BUF_SIZE> { 467impl<'d, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> BufferedCan<'d, TX_BUF_SIZE, RX_BUF_SIZE> {
440 /// Async write frame to TX buffer. 468 /// Async write frame to TX buffer.
441 pub async fn write(&mut self, frame: &Frame) { 469 pub async fn write(&mut self, frame: &Frame) {
442 self.tx.write(frame).await 470 self.tx.write(frame).await
@@ -471,18 +499,20 @@ impl<'d, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> Buffer
471} 499}
472 500
473/// CAN driver, transmit half. 501/// CAN driver, transmit half.
474pub struct CanTx<'d, T: Instance> { 502pub struct CanTx<'d> {
475 _peri: PeripheralRef<'d, T>, 503 _phantom: PhantomData<&'d ()>,
504 info: &'static Info,
505 state: &'static State,
476} 506}
477 507
478impl<'d, T: Instance> CanTx<'d, T> { 508impl<'d> CanTx<'d> {
479 /// Queues the message to be sent. 509 /// Queues the message to be sent.
480 /// 510 ///
481 /// If the TX queue is full, this will wait until there is space, therefore exerting backpressure. 511 /// If the TX queue is full, this will wait until there is space, therefore exerting backpressure.
482 pub async fn write(&mut self, frame: &Frame) -> TransmitStatus { 512 pub async fn write(&mut self, frame: &Frame) -> TransmitStatus {
483 poll_fn(|cx| { 513 poll_fn(|cx| {
484 T::state().tx_mode.register(cx.waker()); 514 self.state.tx_mode.register(cx.waker());
485 if let Ok(status) = Registers(T::regs()).transmit(frame) { 515 if let Ok(status) = self.info.regs.transmit(frame) {
486 return Poll::Ready(status); 516 return Poll::Ready(status);
487 } 517 }
488 518
@@ -501,13 +531,13 @@ impl<'d, T: Instance> CanTx<'d, T> {
501 /// This is done to work around a hardware limitation that could lead to out-of-order delivery 531 /// This is done to work around a hardware limitation that could lead to out-of-order delivery
502 /// of frames with the same priority. 532 /// of frames with the same priority.
503 pub fn try_write(&mut self, frame: &Frame) -> Result<TransmitStatus, TryWriteError> { 533 pub fn try_write(&mut self, frame: &Frame) -> Result<TransmitStatus, TryWriteError> {
504 Registers(T::regs()).transmit(frame).map_err(|_| TryWriteError::Full) 534 self.info.regs.transmit(frame).map_err(|_| TryWriteError::Full)
505 } 535 }
506 536
507 async fn flush_inner(mb: Mailbox) { 537 async fn flush_inner(&self, mb: Mailbox) {
508 poll_fn(|cx| { 538 poll_fn(|cx| {
509 T::state().tx_mode.register(cx.waker()); 539 self.state.tx_mode.register(cx.waker());
510 if T::regs().tsr().read().tme(mb.index()) { 540 if self.info.regs.0.tsr().read().tme(mb.index()) {
511 return Poll::Ready(()); 541 return Poll::Ready(());
512 } 542 }
513 543
@@ -518,14 +548,14 @@ impl<'d, T: Instance> CanTx<'d, T> {
518 548
519 /// Waits for a specific transmit mailbox to become empty 549 /// Waits for a specific transmit mailbox to become empty
520 pub async fn flush(&self, mb: Mailbox) { 550 pub async fn flush(&self, mb: Mailbox) {
521 Self::flush_inner(mb).await 551 self.flush_inner(mb).await
522 } 552 }
523 553
524 async fn flush_any_inner() { 554 async fn flush_any_inner(&self) {
525 poll_fn(|cx| { 555 poll_fn(|cx| {
526 T::state().tx_mode.register(cx.waker()); 556 self.state.tx_mode.register(cx.waker());
527 557
528 let tsr = T::regs().tsr().read(); 558 let tsr = self.info.regs.0.tsr().read();
529 if tsr.tme(Mailbox::Mailbox0.index()) 559 if tsr.tme(Mailbox::Mailbox0.index())
530 || tsr.tme(Mailbox::Mailbox1.index()) 560 || tsr.tme(Mailbox::Mailbox1.index())
531 || tsr.tme(Mailbox::Mailbox2.index()) 561 || tsr.tme(Mailbox::Mailbox2.index())
@@ -545,14 +575,14 @@ impl<'d, T: Instance> CanTx<'d, T> {
545 /// This will happen if FIFO scheduling of outgoing frames is not enabled, 575 /// This will happen if FIFO scheduling of outgoing frames is not enabled,
546 /// and a frame with equal priority is already queued for transmission. 576 /// and a frame with equal priority is already queued for transmission.
547 pub async fn flush_any(&self) { 577 pub async fn flush_any(&self) {
548 Self::flush_any_inner().await 578 self.flush_any_inner().await
549 } 579 }
550 580
551 async fn flush_all_inner() { 581 async fn flush_all_inner(&self) {
552 poll_fn(|cx| { 582 poll_fn(|cx| {
553 T::state().tx_mode.register(cx.waker()); 583 self.state.tx_mode.register(cx.waker());
554 584
555 let tsr = T::regs().tsr().read(); 585 let tsr = self.info.regs.0.tsr().read();
556 if tsr.tme(Mailbox::Mailbox0.index()) 586 if tsr.tme(Mailbox::Mailbox0.index())
557 && tsr.tme(Mailbox::Mailbox1.index()) 587 && tsr.tme(Mailbox::Mailbox1.index())
558 && tsr.tme(Mailbox::Mailbox2.index()) 588 && tsr.tme(Mailbox::Mailbox2.index())
@@ -567,7 +597,7 @@ impl<'d, T: Instance> CanTx<'d, T> {
567 597
568 /// Waits until all of the transmit mailboxes become empty 598 /// Waits until all of the transmit mailboxes become empty
569 pub async fn flush_all(&self) { 599 pub async fn flush_all(&self) {
570 Self::flush_all_inner().await 600 self.flush_all_inner().await
571 } 601 }
572 602
573 /// Attempts to abort the sending of a frame that is pending in a mailbox. 603 /// Attempts to abort the sending of a frame that is pending in a mailbox.
@@ -578,20 +608,20 @@ impl<'d, T: Instance> CanTx<'d, T> {
578 /// If there is a frame in the provided mailbox, and it is canceled successfully, this function 608 /// If there is a frame in the provided mailbox, and it is canceled successfully, this function
579 /// returns `true`. 609 /// returns `true`.
580 pub fn abort(&mut self, mailbox: Mailbox) -> bool { 610 pub fn abort(&mut self, mailbox: Mailbox) -> bool {
581 Registers(T::regs()).abort(mailbox) 611 self.info.regs.abort(mailbox)
582 } 612 }
583 613
584 /// Returns `true` if no frame is pending for transmission. 614 /// Returns `true` if no frame is pending for transmission.
585 pub fn is_idle(&self) -> bool { 615 pub fn is_idle(&self) -> bool {
586 Registers(T::regs()).is_idle() 616 self.info.regs.is_idle()
587 } 617 }
588 618
589 /// Return a buffered instance of driver. User must supply Buffers 619 /// Return a buffered instance of driver. User must supply Buffers
590 pub fn buffered<const TX_BUF_SIZE: usize>( 620 pub fn buffered<const TX_BUF_SIZE: usize>(
591 self, 621 self,
592 txb: &'static mut TxBuf<TX_BUF_SIZE>, 622 txb: &'static mut TxBuf<TX_BUF_SIZE>,
593 ) -> BufferedCanTx<'d, T, TX_BUF_SIZE> { 623 ) -> BufferedCanTx<'d, TX_BUF_SIZE> {
594 BufferedCanTx::new(self, txb) 624 BufferedCanTx::new(self.info, self.state, self, txb)
595 } 625 }
596} 626}
597 627
@@ -599,23 +629,35 @@ impl<'d, T: Instance> CanTx<'d, T> {
599pub type TxBuf<const BUF_SIZE: usize> = Channel<CriticalSectionRawMutex, Frame, BUF_SIZE>; 629pub type TxBuf<const BUF_SIZE: usize> = Channel<CriticalSectionRawMutex, Frame, BUF_SIZE>;
600 630
601/// Buffered CAN driver, transmit half. 631/// Buffered CAN driver, transmit half.
602pub struct BufferedCanTx<'d, T: Instance, const TX_BUF_SIZE: usize> { 632pub struct BufferedCanTx<'d, const TX_BUF_SIZE: usize> {
603 _tx: CanTx<'d, T>, 633 info: &'static Info,
634 state: &'static State,
635 _tx: CanTx<'d>,
604 tx_buf: &'static TxBuf<TX_BUF_SIZE>, 636 tx_buf: &'static TxBuf<TX_BUF_SIZE>,
605} 637}
606 638
607impl<'d, T: Instance, const TX_BUF_SIZE: usize> BufferedCanTx<'d, T, TX_BUF_SIZE> { 639impl<'d, const TX_BUF_SIZE: usize> BufferedCanTx<'d, TX_BUF_SIZE> {
608 fn new(_tx: CanTx<'d, T>, tx_buf: &'static TxBuf<TX_BUF_SIZE>) -> Self { 640 fn new(info: &'static Info, state: &'static State, _tx: CanTx<'d>, tx_buf: &'static TxBuf<TX_BUF_SIZE>) -> Self {
609 Self { _tx, tx_buf }.setup() 641 Self {
642 info,
643 state,
644 _tx,
645 tx_buf,
646 }
647 .setup()
610 } 648 }
611 649
612 fn setup(self) -> Self { 650 fn setup(self) -> Self {
613 // We don't want interrupts being processed while we change modes. 651 // We don't want interrupts being processed while we change modes.
614 critical_section::with(|_| unsafe { 652 critical_section::with(|_| {
615 let tx_inner = super::common::ClassicBufferedTxInner { 653 let tx_inner = super::common::ClassicBufferedTxInner {
616 tx_receiver: self.tx_buf.receiver().into(), 654 tx_receiver: self.tx_buf.receiver().into(),
617 }; 655 };
618 T::mut_state().tx_mode = TxMode::Buffered(tx_inner); 656 let state = self.state as *const State;
657 unsafe {
658 let mut_state = state as *mut State;
659 (*mut_state).tx_mode = TxMode::Buffered(tx_inner);
660 }
619 }); 661 });
620 self 662 self
621 } 663 }
@@ -623,60 +665,67 @@ impl<'d, T: Instance, const TX_BUF_SIZE: usize> BufferedCanTx<'d, T, TX_BUF_SIZE
623 /// Async write frame to TX buffer. 665 /// Async write frame to TX buffer.
624 pub async fn write(&mut self, frame: &Frame) { 666 pub async fn write(&mut self, frame: &Frame) {
625 self.tx_buf.send(*frame).await; 667 self.tx_buf.send(*frame).await;
626 T::TXInterrupt::pend(); // Wake for Tx 668 let waker = self.info.tx_waker;
669 waker(); // Wake for Tx
627 } 670 }
628 671
629 /// Returns a sender that can be used for sending CAN frames. 672 /// Returns a sender that can be used for sending CAN frames.
630 pub fn writer(&self) -> BufferedCanSender { 673 pub fn writer(&self) -> BufferedCanSender {
631 BufferedCanSender { 674 BufferedCanSender {
632 tx_buf: self.tx_buf.sender().into(), 675 tx_buf: self.tx_buf.sender().into(),
633 waker: T::TXInterrupt::pend, 676 waker: self.info.tx_waker,
634 } 677 }
635 } 678 }
636} 679}
637 680
638impl<'d, T: Instance, const TX_BUF_SIZE: usize> Drop for BufferedCanTx<'d, T, TX_BUF_SIZE> { 681impl<'d, const TX_BUF_SIZE: usize> Drop for BufferedCanTx<'d, TX_BUF_SIZE> {
639 fn drop(&mut self) { 682 fn drop(&mut self) {
640 critical_section::with(|_| unsafe { 683 critical_section::with(|_| {
641 T::mut_state().tx_mode = TxMode::NonBuffered(embassy_sync::waitqueue::AtomicWaker::new()); 684 let state = self.state as *const State;
685 unsafe {
686 let mut_state = state as *mut State;
687 (*mut_state).tx_mode = TxMode::NonBuffered(embassy_sync::waitqueue::AtomicWaker::new());
688 }
642 }); 689 });
643 } 690 }
644} 691}
645 692
646/// CAN driver, receive half. 693/// CAN driver, receive half.
647#[allow(dead_code)] 694#[allow(dead_code)]
648pub struct CanRx<'d, T: Instance> { 695pub struct CanRx<'d> {
649 peri: PeripheralRef<'d, T>, 696 _phantom: PhantomData<&'d ()>,
697 info: &'static Info,
698 state: &'static State,
650} 699}
651 700
652impl<'d, T: Instance> CanRx<'d, T> { 701impl<'d> CanRx<'d> {
653 /// Read a CAN frame. 702 /// Read a CAN frame.
654 /// 703 ///
655 /// If no CAN frame is in the RX buffer, this will wait until there is one. 704 /// If no CAN frame is in the RX buffer, this will wait until there is one.
656 /// 705 ///
657 /// Returns a tuple of the time the message was received and the message frame 706 /// Returns a tuple of the time the message was received and the message frame
658 pub async fn read(&mut self) -> Result<Envelope, BusError> { 707 pub async fn read(&mut self) -> Result<Envelope, BusError> {
659 T::state().rx_mode.read::<T>().await 708 self.state.rx_mode.read(self.info, self.state).await
660 } 709 }
661 710
662 /// Attempts to read a CAN frame without blocking. 711 /// Attempts to read a CAN frame without blocking.
663 /// 712 ///
664 /// Returns [Err(TryReadError::Empty)] if there are no frames in the rx queue. 713 /// Returns [Err(TryReadError::Empty)] if there are no frames in the rx queue.
665 pub fn try_read(&mut self) -> Result<Envelope, TryReadError> { 714 pub fn try_read(&mut self) -> Result<Envelope, TryReadError> {
666 T::state().rx_mode.try_read::<T>() 715 self.state.rx_mode.try_read(self.info)
667 } 716 }
668 717
669 /// Waits while receive queue is empty. 718 /// Waits while receive queue is empty.
670 pub async fn wait_not_empty(&mut self) { 719 pub async fn wait_not_empty(&mut self) {
671 T::state().rx_mode.wait_not_empty::<T>().await 720 self.state.rx_mode.wait_not_empty(self.info, self.state).await
672 } 721 }
673 722
674 /// Return a buffered instance of driver. User must supply Buffers 723 /// Return a buffered instance of driver. User must supply Buffers
675 pub fn buffered<const RX_BUF_SIZE: usize>( 724 pub fn buffered<const RX_BUF_SIZE: usize>(
676 self, 725 self,
677 rxb: &'static mut RxBuf<RX_BUF_SIZE>, 726 rxb: &'static mut RxBuf<RX_BUF_SIZE>,
678 ) -> BufferedCanRx<'d, T, RX_BUF_SIZE> { 727 ) -> BufferedCanRx<'d, RX_BUF_SIZE> {
679 BufferedCanRx::new(self, rxb) 728 BufferedCanRx::new(self.info, self.state, self, rxb)
680 } 729 }
681} 730}
682 731
@@ -684,23 +733,35 @@ impl<'d, T: Instance> CanRx<'d, T> {
684pub type RxBuf<const BUF_SIZE: usize> = Channel<CriticalSectionRawMutex, Result<Envelope, BusError>, BUF_SIZE>; 733pub type RxBuf<const BUF_SIZE: usize> = Channel<CriticalSectionRawMutex, Result<Envelope, BusError>, BUF_SIZE>;
685 734
686/// CAN driver, receive half in Buffered mode. 735/// CAN driver, receive half in Buffered mode.
687pub struct BufferedCanRx<'d, T: Instance, const RX_BUF_SIZE: usize> { 736pub struct BufferedCanRx<'d, const RX_BUF_SIZE: usize> {
688 _rx: CanRx<'d, T>, 737 info: &'static Info,
738 state: &'static State,
739 _rx: CanRx<'d>,
689 rx_buf: &'static RxBuf<RX_BUF_SIZE>, 740 rx_buf: &'static RxBuf<RX_BUF_SIZE>,
690} 741}
691 742
692impl<'d, T: Instance, const RX_BUF_SIZE: usize> BufferedCanRx<'d, T, RX_BUF_SIZE> { 743impl<'d, const RX_BUF_SIZE: usize> BufferedCanRx<'d, RX_BUF_SIZE> {
693 fn new(_rx: CanRx<'d, T>, rx_buf: &'static RxBuf<RX_BUF_SIZE>) -> Self { 744 fn new(info: &'static Info, state: &'static State, _rx: CanRx<'d>, rx_buf: &'static RxBuf<RX_BUF_SIZE>) -> Self {
694 BufferedCanRx { _rx, rx_buf }.setup() 745 BufferedCanRx {
746 info,
747 state,
748 _rx,
749 rx_buf,
750 }
751 .setup()
695 } 752 }
696 753
697 fn setup(self) -> Self { 754 fn setup(self) -> Self {
698 // We don't want interrupts being processed while we change modes. 755 // We don't want interrupts being processed while we change modes.
699 critical_section::with(|_| unsafe { 756 critical_section::with(|_| {
700 let rx_inner = super::common::ClassicBufferedRxInner { 757 let rx_inner = super::common::ClassicBufferedRxInner {
701 rx_sender: self.rx_buf.sender().into(), 758 rx_sender: self.rx_buf.sender().into(),
702 }; 759 };
703 T::mut_state().rx_mode = RxMode::Buffered(rx_inner); 760 let state = self.state as *const State;
761 unsafe {
762 let mut_state = state as *mut State;
763 (*mut_state).rx_mode = RxMode::Buffered(rx_inner);
764 }
704 }); 765 });
705 self 766 self
706 } 767 }
@@ -714,7 +775,7 @@ impl<'d, T: Instance, const RX_BUF_SIZE: usize> BufferedCanRx<'d, T, RX_BUF_SIZE
714 /// 775 ///
715 /// Returns [Err(TryReadError::Empty)] if there are no frames in the rx queue. 776 /// Returns [Err(TryReadError::Empty)] if there are no frames in the rx queue.
716 pub fn try_read(&mut self) -> Result<Envelope, TryReadError> { 777 pub fn try_read(&mut self) -> Result<Envelope, TryReadError> {
717 match &T::state().rx_mode { 778 match &self.state.rx_mode {
718 RxMode::Buffered(_) => { 779 RxMode::Buffered(_) => {
719 if let Ok(result) = self.rx_buf.try_receive() { 780 if let Ok(result) = self.rx_buf.try_receive() {
720 match result { 781 match result {
@@ -722,7 +783,7 @@ impl<'d, T: Instance, const RX_BUF_SIZE: usize> BufferedCanRx<'d, T, RX_BUF_SIZE
722 Err(e) => Err(TryReadError::BusError(e)), 783 Err(e) => Err(TryReadError::BusError(e)),
723 } 784 }
724 } else { 785 } else {
725 if let Some(err) = Registers(T::regs()).curr_error() { 786 if let Some(err) = self.info.regs.curr_error() {
726 return Err(TryReadError::BusError(err)); 787 return Err(TryReadError::BusError(err));
727 } else { 788 } else {
728 Err(TryReadError::Empty) 789 Err(TryReadError::Empty)
@@ -746,10 +807,14 @@ impl<'d, T: Instance, const RX_BUF_SIZE: usize> BufferedCanRx<'d, T, RX_BUF_SIZE
746 } 807 }
747} 808}
748 809
749impl<'d, T: Instance, const RX_BUF_SIZE: usize> Drop for BufferedCanRx<'d, T, RX_BUF_SIZE> { 810impl<'d, const RX_BUF_SIZE: usize> Drop for BufferedCanRx<'d, RX_BUF_SIZE> {
750 fn drop(&mut self) { 811 fn drop(&mut self) {
751 critical_section::with(|_| unsafe { 812 critical_section::with(|_| {
752 T::mut_state().rx_mode = RxMode::NonBuffered(embassy_sync::waitqueue::AtomicWaker::new()); 813 let state = self.state as *const State;
814 unsafe {
815 let mut_state = state as *mut State;
816 (*mut_state).rx_mode = RxMode::NonBuffered(embassy_sync::waitqueue::AtomicWaker::new());
817 }
753 }); 818 });
754 } 819 }
755} 820}
@@ -839,13 +904,13 @@ impl RxMode {
839 } 904 }
840 } 905 }
841 906
842 pub async fn read<T: Instance>(&self) -> Result<Envelope, BusError> { 907 pub(crate) async fn read(&self, info: &Info, state: &State) -> Result<Envelope, BusError> {
843 match self { 908 match self {
844 Self::NonBuffered(waker) => { 909 Self::NonBuffered(waker) => {
845 poll_fn(|cx| { 910 poll_fn(|cx| {
846 T::state().err_waker.register(cx.waker()); 911 state.err_waker.register(cx.waker());
847 waker.register(cx.waker()); 912 waker.register(cx.waker());
848 match self.try_read::<T>() { 913 match self.try_read(info) {
849 Ok(result) => Poll::Ready(Ok(result)), 914 Ok(result) => Poll::Ready(Ok(result)),
850 Err(TryReadError::Empty) => Poll::Pending, 915 Err(TryReadError::Empty) => Poll::Pending,
851 Err(TryReadError::BusError(be)) => Poll::Ready(Err(be)), 916 Err(TryReadError::BusError(be)) => Poll::Ready(Err(be)),
@@ -858,17 +923,17 @@ impl RxMode {
858 } 923 }
859 } 924 }
860 } 925 }
861 pub fn try_read<T: Instance>(&self) -> Result<Envelope, TryReadError> { 926 pub(crate) fn try_read(&self, info: &Info) -> Result<Envelope, TryReadError> {
862 match self { 927 match self {
863 Self::NonBuffered(_) => { 928 Self::NonBuffered(_) => {
864 let registers = Registers(T::regs()); 929 let registers = &info.regs;
865 if let Some(msg) = registers.receive_fifo(RxFifo::Fifo0) { 930 if let Some(msg) = registers.receive_fifo(RxFifo::Fifo0) {
866 T::regs().ier().write(|w| { 931 registers.0.ier().write(|w| {
867 w.set_fmpie(0, true); 932 w.set_fmpie(0, true);
868 }); 933 });
869 Ok(msg) 934 Ok(msg)
870 } else if let Some(msg) = registers.receive_fifo(RxFifo::Fifo1) { 935 } else if let Some(msg) = registers.receive_fifo(RxFifo::Fifo1) {
871 T::regs().ier().write(|w| { 936 registers.0.ier().write(|w| {
872 w.set_fmpie(1, true); 937 w.set_fmpie(1, true);
873 }); 938 });
874 Ok(msg) 939 Ok(msg)
@@ -883,12 +948,12 @@ impl RxMode {
883 } 948 }
884 } 949 }
885 } 950 }
886 pub async fn wait_not_empty<T: Instance>(&self) { 951 pub(crate) async fn wait_not_empty(&self, info: &Info, state: &State) {
887 match &T::state().rx_mode { 952 match &state.rx_mode {
888 Self::NonBuffered(waker) => { 953 Self::NonBuffered(waker) => {
889 poll_fn(|cx| { 954 poll_fn(|cx| {
890 waker.register(cx.waker()); 955 waker.register(cx.waker());
891 if Registers(T::regs()).receive_frame_available() { 956 if info.regs.receive_frame_available() {
892 Poll::Ready(()) 957 Poll::Ready(())
893 } else { 958 } else {
894 Poll::Pending 959 Poll::Pending
@@ -903,7 +968,7 @@ impl RxMode {
903 } 968 }
904} 969}
905 970
906enum TxMode { 971pub(crate) enum TxMode {
907 NonBuffered(AtomicWaker), 972 NonBuffered(AtomicWaker),
908 Buffered(super::common::ClassicBufferedTxInner), 973 Buffered(super::common::ClassicBufferedTxInner),
909} 974}
@@ -943,7 +1008,7 @@ impl TxMode {
943 } 1008 }
944} 1009}
945 1010
946struct State { 1011pub(crate) struct State {
947 pub(crate) rx_mode: RxMode, 1012 pub(crate) rx_mode: RxMode,
948 pub(crate) tx_mode: TxMode, 1013 pub(crate) tx_mode: TxMode,
949 pub err_waker: AtomicWaker, 1014 pub err_waker: AtomicWaker,
@@ -959,7 +1024,17 @@ impl State {
959 } 1024 }
960} 1025}
961 1026
1027pub(crate) struct Info {
1028 regs: Registers,
1029 tx_interrupt: crate::interrupt::Interrupt,
1030 rx0_interrupt: crate::interrupt::Interrupt,
1031 rx1_interrupt: crate::interrupt::Interrupt,
1032 sce_interrupt: crate::interrupt::Interrupt,
1033 tx_waker: fn(),
1034}
1035
962trait SealedInstance { 1036trait SealedInstance {
1037 fn info() -> &'static Info;
963 fn regs() -> crate::pac::can::Can; 1038 fn regs() -> crate::pac::can::Can;
964 fn state() -> &'static State; 1039 fn state() -> &'static State;
965 unsafe fn mut_state() -> &'static mut State; 1040 unsafe fn mut_state() -> &'static mut State;
@@ -1012,6 +1087,17 @@ foreach_peripheral!(
1012 (can, $inst:ident) => { 1087 (can, $inst:ident) => {
1013 impl SealedInstance for peripherals::$inst { 1088 impl SealedInstance for peripherals::$inst {
1014 1089
1090 fn info() -> &'static Info {
1091 static INFO: Info = Info {
1092 regs: Registers(crate::pac::$inst),
1093 tx_interrupt: crate::_generated::peripheral_interrupts::$inst::TX::IRQ,
1094 rx0_interrupt: crate::_generated::peripheral_interrupts::$inst::RX0::IRQ,
1095 rx1_interrupt: crate::_generated::peripheral_interrupts::$inst::RX1::IRQ,
1096 sce_interrupt: crate::_generated::peripheral_interrupts::$inst::SCE::IRQ,
1097 tx_waker: crate::_generated::peripheral_interrupts::$inst::TX::pend,
1098 };
1099 &INFO
1100 }
1015 fn regs() -> crate::pac::can::Can { 1101 fn regs() -> crate::pac::can::Can {
1016 crate::pac::$inst 1102 crate::pac::$inst
1017 } 1103 }
diff --git a/embassy-stm32/src/can/bxcan/registers.rs b/embassy-stm32/src/can/bxcan/registers.rs
index ad27e0744..e7c7525d8 100644
--- a/embassy-stm32/src/can/bxcan/registers.rs
+++ b/embassy-stm32/src/can/bxcan/registers.rs
@@ -131,7 +131,7 @@ impl Registers {
131 /// Note that this will not trigger [`Interrupt::Wakeup`], only reception of an incoming CAN 131 /// Note that this will not trigger [`Interrupt::Wakeup`], only reception of an incoming CAN
132 /// frame will cause that interrupt. 132 /// frame will cause that interrupt.
133 #[allow(dead_code)] 133 #[allow(dead_code)]
134 pub fn wakeup(&mut self) { 134 pub fn wakeup(&self) {
135 self.0.mcr().modify(|reg| { 135 self.0.mcr().modify(|reg| {
136 reg.set_sleep(false); 136 reg.set_sleep(false);
137 reg.set_inrq(false); 137 reg.set_inrq(false);
@@ -216,7 +216,7 @@ impl Registers {
216 /// If FIFO scheduling is enabled, frames are transmitted in the order that they are passed to this function. 216 /// If FIFO scheduling is enabled, frames are transmitted in the order that they are passed to this function.
217 /// 217 ///
218 /// If all transmit mailboxes are full, this function returns [`nb::Error::WouldBlock`]. 218 /// If all transmit mailboxes are full, this function returns [`nb::Error::WouldBlock`].
219 pub fn transmit(&mut self, frame: &Frame) -> nb::Result<TransmitStatus, Infallible> { 219 pub fn transmit(&self, frame: &Frame) -> nb::Result<TransmitStatus, Infallible> {
220 // Check if FIFO scheduling is enabled. 220 // Check if FIFO scheduling is enabled.
221 let fifo_scheduling = self.0.mcr().read().txfp(); 221 let fifo_scheduling = self.0.mcr().read().txfp();
222 222
@@ -292,7 +292,7 @@ impl Registers {
292 Ok(()) 292 Ok(())
293 } 293 }
294 294
295 fn write_mailbox(&mut self, idx: usize, frame: &Frame) { 295 fn write_mailbox(&self, idx: usize, frame: &Frame) {
296 debug_assert!(idx < 3); 296 debug_assert!(idx < 3);
297 297
298 let mb = self.0.tx(idx); 298 let mb = self.0.tx(idx);
@@ -309,7 +309,7 @@ impl Registers {
309 }); 309 });
310 } 310 }
311 311
312 fn read_pending_mailbox(&mut self, idx: usize) -> Option<Frame> { 312 fn read_pending_mailbox(&self, idx: usize) -> Option<Frame> {
313 if self.abort_by_index(idx) { 313 if self.abort_by_index(idx) {
314 debug_assert!(idx < 3); 314 debug_assert!(idx < 3);
315 315
@@ -332,7 +332,7 @@ impl Registers {
332 } 332 }
333 333
334 /// Tries to abort a pending frame. Returns `true` when aborted. 334 /// Tries to abort a pending frame. Returns `true` when aborted.
335 fn abort_by_index(&mut self, idx: usize) -> bool { 335 fn abort_by_index(&self, idx: usize) -> bool {
336 self.0.tsr().write(|reg| reg.set_abrq(idx, true)); 336 self.0.tsr().write(|reg| reg.set_abrq(idx, true));
337 337
338 // Wait for the abort request to be finished. 338 // Wait for the abort request to be finished.
@@ -351,7 +351,7 @@ impl Registers {
351 /// 351 ///
352 /// If there is a frame in the provided mailbox, and it is canceled successfully, this function 352 /// If there is a frame in the provided mailbox, and it is canceled successfully, this function
353 /// returns `true`. 353 /// returns `true`.
354 pub fn abort(&mut self, mailbox: Mailbox) -> bool { 354 pub fn abort(&self, mailbox: Mailbox) -> bool {
355 // If the mailbox is empty, the value of TXOKx depends on what happened with the previous 355 // If the mailbox is empty, the value of TXOKx depends on what happened with the previous
356 // frame in that mailbox. Only call abort_by_index() if the mailbox is not empty. 356 // frame in that mailbox. Only call abort_by_index() if the mailbox is not empty.
357 let tsr = self.0.tsr().read(); 357 let tsr = self.0.tsr().read();
diff --git a/examples/stm32f7/src/bin/can.rs b/examples/stm32f7/src/bin/can.rs
index e32b4d3df..f4d6d8c19 100644
--- a/examples/stm32f7/src/bin/can.rs
+++ b/examples/stm32f7/src/bin/can.rs
@@ -24,7 +24,7 @@ bind_interrupts!(struct Irqs {
24}); 24});
25 25
26#[embassy_executor::task] 26#[embassy_executor::task]
27pub async fn send_can_message(tx: &'static mut CanTx<'static, CAN3>) { 27pub async fn send_can_message(tx: &'static mut CanTx<'static>) {
28 loop { 28 loop {
29 let frame = Frame::new_data(unwrap!(StandardId::new(0 as _)), &[0]).unwrap(); 29 let frame = Frame::new_data(unwrap!(StandardId::new(0 as _)), &[0]).unwrap();
30 tx.write(&frame).await; 30 tx.write(&frame).await;
@@ -62,7 +62,7 @@ async fn main(spawner: Spawner) {
62 62
63 let (tx, mut rx) = can.split(); 63 let (tx, mut rx) = can.split();
64 64
65 static CAN_TX: StaticCell<CanTx<'static, CAN3>> = StaticCell::new(); 65 static CAN_TX: StaticCell<CanTx<'static>> = StaticCell::new();
66 let tx = CAN_TX.init(tx); 66 let tx = CAN_TX.init(tx);
67 spawner.spawn(send_can_message(tx)).unwrap(); 67 spawner.spawn(send_can_message(tx)).unwrap();
68 68
diff --git a/tests/stm32/src/bin/can.rs b/tests/stm32/src/bin/can.rs
index 004b1a729..f63076512 100644
--- a/tests/stm32/src/bin/can.rs
+++ b/tests/stm32/src/bin/can.rs
@@ -19,8 +19,8 @@ mod can_common;
19use can_common::*; 19use can_common::*;
20 20
21type Can<'d> = embassy_stm32::can::Can<'d, embassy_stm32::peripherals::CAN1>; 21type Can<'d> = embassy_stm32::can::Can<'d, embassy_stm32::peripherals::CAN1>;
22type CanTx<'d> = embassy_stm32::can::CanTx<'d, embassy_stm32::peripherals::CAN1>; 22type CanTx<'d> = embassy_stm32::can::CanTx<'d>;
23type CanRx<'d> = embassy_stm32::can::CanRx<'d, embassy_stm32::peripherals::CAN1>; 23type CanRx<'d> = embassy_stm32::can::CanRx<'d>;
24 24
25bind_interrupts!(struct Irqs { 25bind_interrupts!(struct Irqs {
26 CAN1_RX0 => Rx0InterruptHandler<CAN1>; 26 CAN1_RX0 => Rx0InterruptHandler<CAN1>;