diff options
| author | Dario Nieuwenhuis <[email protected]> | 2024-05-30 12:16:17 +0000 |
|---|---|---|
| committer | GitHub <[email protected]> | 2024-05-30 12:16:17 +0000 |
| commit | b378ec4558306a7d10572301b7e078c055bc47ac (patch) | |
| tree | c44d01880527615a844d7bc7a1c86c9def345909 | |
| parent | 39c5a6c3f7fe294bc7c5e6beaa0eac67399e62f9 (diff) | |
| parent | b4a2f7fb70ac3f0b0d9226ab5ff5aab7a5bf8649 (diff) | |
Merge pull request #3020 from cschuhen/feature/bxcan_no_generics
Remove generics for BXCAN.
| -rw-r--r-- | embassy-stm32/src/can/bxcan/mod.rs | 294 | ||||
| -rw-r--r-- | embassy-stm32/src/can/bxcan/registers.rs | 12 | ||||
| -rw-r--r-- | examples/stm32f7/src/bin/can.rs | 4 | ||||
| -rw-r--r-- | tests/stm32/src/bin/can.rs | 4 |
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; | |||
| 5 | use core::marker::PhantomData; | 5 | use core::marker::PhantomData; |
| 6 | use core::task::Poll; | 6 | use core::task::Poll; |
| 7 | 7 | ||
| 8 | use embassy_hal_internal::interrupt::InterruptExt; | ||
| 8 | use embassy_hal_internal::{into_ref, PeripheralRef}; | 9 | use embassy_hal_internal::{into_ref, PeripheralRef}; |
| 9 | use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; | 10 | use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; |
| 10 | use embassy_sync::channel::Channel; | 11 | use embassy_sync::channel::Channel; |
| @@ -154,7 +155,9 @@ impl<T: Instance> Drop for CanConfig<'_, T> { | |||
| 154 | 155 | ||
| 155 | /// CAN driver | 156 | /// CAN driver |
| 156 | pub struct Can<'d, T: Instance> { | 157 | pub 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. |
| 434 | pub struct BufferedCan<'d, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> { | 462 | pub 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 | ||
| 439 | impl<'d, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> BufferedCan<'d, T, TX_BUF_SIZE, RX_BUF_SIZE> { | 467 | impl<'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. |
| 474 | pub struct CanTx<'d, T: Instance> { | 502 | pub struct CanTx<'d> { |
| 475 | _peri: PeripheralRef<'d, T>, | 503 | _phantom: PhantomData<&'d ()>, |
| 504 | info: &'static Info, | ||
| 505 | state: &'static State, | ||
| 476 | } | 506 | } |
| 477 | 507 | ||
| 478 | impl<'d, T: Instance> CanTx<'d, T> { | 508 | impl<'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> { | |||
| 599 | pub type TxBuf<const BUF_SIZE: usize> = Channel<CriticalSectionRawMutex, Frame, BUF_SIZE>; | 629 | pub 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. |
| 602 | pub struct BufferedCanTx<'d, T: Instance, const TX_BUF_SIZE: usize> { | 632 | pub 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 | ||
| 607 | impl<'d, T: Instance, const TX_BUF_SIZE: usize> BufferedCanTx<'d, T, TX_BUF_SIZE> { | 639 | impl<'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 | ||
| 638 | impl<'d, T: Instance, const TX_BUF_SIZE: usize> Drop for BufferedCanTx<'d, T, TX_BUF_SIZE> { | 681 | impl<'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)] |
| 648 | pub struct CanRx<'d, T: Instance> { | 695 | pub struct CanRx<'d> { |
| 649 | peri: PeripheralRef<'d, T>, | 696 | _phantom: PhantomData<&'d ()>, |
| 697 | info: &'static Info, | ||
| 698 | state: &'static State, | ||
| 650 | } | 699 | } |
| 651 | 700 | ||
| 652 | impl<'d, T: Instance> CanRx<'d, T> { | 701 | impl<'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> { | |||
| 684 | pub type RxBuf<const BUF_SIZE: usize> = Channel<CriticalSectionRawMutex, Result<Envelope, BusError>, BUF_SIZE>; | 733 | pub 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. |
| 687 | pub struct BufferedCanRx<'d, T: Instance, const RX_BUF_SIZE: usize> { | 736 | pub 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 | ||
| 692 | impl<'d, T: Instance, const RX_BUF_SIZE: usize> BufferedCanRx<'d, T, RX_BUF_SIZE> { | 743 | impl<'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 | ||
| 749 | impl<'d, T: Instance, const RX_BUF_SIZE: usize> Drop for BufferedCanRx<'d, T, RX_BUF_SIZE> { | 810 | impl<'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 | ||
| 906 | enum TxMode { | 971 | pub(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 | ||
| 946 | struct State { | 1011 | pub(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 | ||
| 1027 | pub(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 | |||
| 962 | trait SealedInstance { | 1036 | trait 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] |
| 27 | pub async fn send_can_message(tx: &'static mut CanTx<'static, CAN3>) { | 27 | pub 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; | |||
| 19 | use can_common::*; | 19 | use can_common::*; |
| 20 | 20 | ||
| 21 | type Can<'d> = embassy_stm32::can::Can<'d, embassy_stm32::peripherals::CAN1>; | 21 | type Can<'d> = embassy_stm32::can::Can<'d, embassy_stm32::peripherals::CAN1>; |
| 22 | type CanTx<'d> = embassy_stm32::can::CanTx<'d, embassy_stm32::peripherals::CAN1>; | 22 | type CanTx<'d> = embassy_stm32::can::CanTx<'d>; |
| 23 | type CanRx<'d> = embassy_stm32::can::CanRx<'d, embassy_stm32::peripherals::CAN1>; | 23 | type CanRx<'d> = embassy_stm32::can::CanRx<'d>; |
| 24 | 24 | ||
| 25 | bind_interrupts!(struct Irqs { | 25 | bind_interrupts!(struct Irqs { |
| 26 | CAN1_RX0 => Rx0InterruptHandler<CAN1>; | 26 | CAN1_RX0 => Rx0InterruptHandler<CAN1>; |
