diff options
| author | Corey Schuhen <[email protected]> | 2024-03-24 15:13:55 +1000 |
|---|---|---|
| committer | Corey Schuhen <[email protected]> | 2024-03-28 09:32:13 +1000 |
| commit | 2217b802781b5f2188b4da659aca47f9d89ee032 (patch) | |
| tree | 3054378ec4087372858312e74091f9a16ce26efd /examples/stm32f1 | |
| parent | f5daa50a7baceb44f2aad44bf6ce055bccb08433 (diff) | |
CAN: Unify API's between BXCAN and FDCAN. Use Envelope for all read methods instead of a tuple sometimes.
Diffstat (limited to 'examples/stm32f1')
| -rw-r--r-- | examples/stm32f1/Cargo.toml | 1 | ||||
| -rw-r--r-- | examples/stm32f1/src/bin/can.rs | 102 |
2 files changed, 90 insertions, 13 deletions
diff --git a/examples/stm32f1/Cargo.toml b/examples/stm32f1/Cargo.toml index df5d32f70..4f282f326 100644 --- a/examples/stm32f1/Cargo.toml +++ b/examples/stm32f1/Cargo.toml | |||
| @@ -23,6 +23,7 @@ panic-probe = { version = "0.3", features = ["print-defmt"] } | |||
| 23 | futures = { version = "0.3.17", default-features = false, features = ["async-await"] } | 23 | futures = { version = "0.3.17", default-features = false, features = ["async-await"] } |
| 24 | heapless = { version = "0.8", default-features = false } | 24 | heapless = { version = "0.8", default-features = false } |
| 25 | nb = "1.0.0" | 25 | nb = "1.0.0" |
| 26 | static_cell = "2.0.0" | ||
| 26 | 27 | ||
| 27 | [profile.dev] | 28 | [profile.dev] |
| 28 | opt-level = "s" | 29 | opt-level = "s" |
diff --git a/examples/stm32f1/src/bin/can.rs b/examples/stm32f1/src/bin/can.rs index ac337e8a0..90cb9e46b 100644 --- a/examples/stm32f1/src/bin/can.rs +++ b/examples/stm32f1/src/bin/can.rs | |||
| @@ -4,11 +4,12 @@ | |||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_stm32::can::{ | 6 | use embassy_stm32::can::{ |
| 7 | filter, Can, Fifo, Frame, Id, Rx0InterruptHandler, Rx1InterruptHandler, SceInterruptHandler, StandardId, | 7 | filter, Can, Envelope, Fifo, Frame, Id, Rx0InterruptHandler, Rx1InterruptHandler, SceInterruptHandler, StandardId, |
| 8 | TxInterruptHandler, | 8 | TxInterruptHandler, |
| 9 | }; | 9 | }; |
| 10 | use embassy_stm32::peripherals::CAN; | 10 | use embassy_stm32::peripherals::CAN; |
| 11 | use embassy_stm32::{bind_interrupts, Config}; | 11 | use embassy_stm32::{bind_interrupts, Config}; |
| 12 | use static_cell::StaticCell; | ||
| 12 | use {defmt_rtt as _, panic_probe as _}; | 13 | use {defmt_rtt as _, panic_probe as _}; |
| 13 | 14 | ||
| 14 | bind_interrupts!(struct Irqs { | 15 | bind_interrupts!(struct Irqs { |
| @@ -21,6 +22,27 @@ bind_interrupts!(struct Irqs { | |||
| 21 | // This example is configured to work with real CAN transceivers on B8/B9. | 22 | // This example is configured to work with real CAN transceivers on B8/B9. |
| 22 | // See other examples for loopback. | 23 | // See other examples for loopback. |
| 23 | 24 | ||
| 25 | fn handle_frame(env: Envelope, read_mode: &str) { | ||
| 26 | match env.frame.id() { | ||
| 27 | Id::Extended(id) => { | ||
| 28 | defmt::println!( | ||
| 29 | "{} Extended Frame id={:x} {:02x}", | ||
| 30 | read_mode, | ||
| 31 | id.as_raw(), | ||
| 32 | env.frame.data() | ||
| 33 | ); | ||
| 34 | } | ||
| 35 | Id::Standard(id) => { | ||
| 36 | defmt::println!( | ||
| 37 | "{} Standard Frame id={:x} {:02x}", | ||
| 38 | read_mode, | ||
| 39 | id.as_raw(), | ||
| 40 | env.frame.data() | ||
| 41 | ); | ||
| 42 | } | ||
| 43 | } | ||
| 44 | } | ||
| 45 | |||
| 24 | #[embassy_executor::main] | 46 | #[embassy_executor::main] |
| 25 | async fn main(_spawner: Spawner) { | 47 | async fn main(_spawner: Spawner) { |
| 26 | let p = embassy_stm32::init(Config::default()); | 48 | let p = embassy_stm32::init(Config::default()); |
| @@ -28,6 +50,9 @@ async fn main(_spawner: Spawner) { | |||
| 28 | // Set alternate pin mapping to B8/B9 | 50 | // Set alternate pin mapping to B8/B9 |
| 29 | embassy_stm32::pac::AFIO.mapr().modify(|w| w.set_can1_remap(2)); | 51 | embassy_stm32::pac::AFIO.mapr().modify(|w| w.set_can1_remap(2)); |
| 30 | 52 | ||
| 53 | static RX_BUF: StaticCell<embassy_stm32::can::RxBuf<10>> = StaticCell::new(); | ||
| 54 | static TX_BUF: StaticCell<embassy_stm32::can::TxBuf<10>> = StaticCell::new(); | ||
| 55 | |||
| 31 | let mut can = Can::new(p.CAN, p.PB8, p.PB9, Irqs); | 56 | let mut can = Can::new(p.CAN, p.PB8, p.PB9, Irqs); |
| 32 | 57 | ||
| 33 | can.as_mut() | 58 | can.as_mut() |
| @@ -43,21 +68,72 @@ async fn main(_spawner: Spawner) { | |||
| 43 | can.set_bitrate(250_000); | 68 | can.set_bitrate(250_000); |
| 44 | 69 | ||
| 45 | can.enable().await; | 70 | can.enable().await; |
| 46 | |||
| 47 | let mut i: u8 = 0; | 71 | let mut i: u8 = 0; |
| 72 | |||
| 73 | /* | ||
| 74 | // Example for using buffered Tx and Rx without needing to | ||
| 75 | // split first as is done below. | ||
| 76 | let mut can = can.buffered( | ||
| 77 | TX_BUF.init(embassy_stm32::can::TxBuf::<10>::new()), | ||
| 78 | RX_BUF.init(embassy_stm32::can::RxBuf::<10>::new())); | ||
| 79 | loop { | ||
| 80 | let tx_frame = Frame::new_data(unwrap!(StandardId::new(i as _)), &[i, 0, 1, 2, 3, 4, 5, 6]).unwrap(); | ||
| 81 | can.write(&tx_frame).await; | ||
| 82 | |||
| 83 | match can.read().await { | ||
| 84 | Ok((frame, ts)) => { | ||
| 85 | handle_frame(Envelope { ts, frame }, "Buf"); | ||
| 86 | } | ||
| 87 | Err(err) => { | ||
| 88 | defmt::println!("Error {}", err); | ||
| 89 | } | ||
| 90 | } | ||
| 91 | i += 1; | ||
| 92 | } | ||
| 93 | |||
| 94 | */ | ||
| 95 | let (mut tx, mut rx) = can.split(); | ||
| 96 | |||
| 97 | // This example shows using the wait_not_empty API before try read | ||
| 98 | while i < 3 { | ||
| 99 | let tx_frame = Frame::new_data(unwrap!(StandardId::new(i as _)), &[i, 0, 1, 2, 3, 4, 5, 6]).unwrap(); | ||
| 100 | tx.write(&tx_frame).await; | ||
| 101 | |||
| 102 | rx.wait_not_empty().await; | ||
| 103 | let env = rx.try_read().unwrap(); | ||
| 104 | handle_frame(env, "Wait"); | ||
| 105 | i += 1; | ||
| 106 | } | ||
| 107 | |||
| 108 | // This example shows using the full async non-buffered API | ||
| 109 | while i < 6 { | ||
| 110 | let tx_frame = Frame::new_data(unwrap!(StandardId::new(i as _)), &[i, 0, 1, 2, 3, 4, 5, 6]).unwrap(); | ||
| 111 | tx.write(&tx_frame).await; | ||
| 112 | |||
| 113 | match rx.read().await { | ||
| 114 | Ok(env) => { | ||
| 115 | handle_frame(env, "NoBuf"); | ||
| 116 | } | ||
| 117 | Err(err) => { | ||
| 118 | defmt::println!("Error {}", err); | ||
| 119 | } | ||
| 120 | } | ||
| 121 | i += 1; | ||
| 122 | } | ||
| 123 | |||
| 124 | // This example shows using buffered RX and TX. User passes in desired buffer (size) | ||
| 125 | // It's possible this way to have just RX or TX buffered. | ||
| 126 | let mut rx = rx.buffered(RX_BUF.init(embassy_stm32::can::RxBuf::<10>::new())); | ||
| 127 | let mut tx = tx.buffered(TX_BUF.init(embassy_stm32::can::TxBuf::<10>::new())); | ||
| 128 | |||
| 48 | loop { | 129 | loop { |
| 49 | let tx_frame = Frame::new_data(unwrap!(StandardId::new(i as _)), &[i, 0, 1, 2, 3, 4, 5, 6]).unwrap(); | 130 | let tx_frame = Frame::new_data(unwrap!(StandardId::new(i as _)), &[i, 0, 1, 2, 3, 4, 5, 6]).unwrap(); |
| 50 | can.write(&tx_frame).await; | 131 | tx.write(&tx_frame).await; |
| 51 | 132 | ||
| 52 | match can.read().await { | 133 | match rx.read().await { |
| 53 | Ok(env) => match env.frame.id() { | 134 | Ok(envelope) => { |
| 54 | Id::Extended(id) => { | 135 | handle_frame(envelope, "Buf"); |
| 55 | defmt::println!("Extended Frame id={:x} {:02x}", id.as_raw(), env.frame.data()); | 136 | } |
| 56 | } | ||
| 57 | Id::Standard(id) => { | ||
| 58 | defmt::println!("Standard Frame id={:x} {:02x}", id.as_raw(), env.frame.data()); | ||
| 59 | } | ||
| 60 | }, | ||
| 61 | Err(err) => { | 137 | Err(err) => { |
| 62 | defmt::println!("Error {}", err); | 138 | defmt::println!("Error {}", err); |
| 63 | } | 139 | } |
