diff options
| author | Dario Nieuwenhuis <[email protected]> | 2024-02-23 01:45:10 +0100 |
|---|---|---|
| committer | GitHub <[email protected]> | 2024-02-23 01:45:10 +0100 |
| commit | a6a5d9913cda2ecfe89b63fa0bcf7afaebc2dac0 (patch) | |
| tree | 14124a6f34d351a979cb110a0ce566b588f5d272 /examples | |
| parent | 5b7e2d88265b5633fa53047961598fbc38bffed0 (diff) | |
| parent | 2855bb69680a42a721fe88168657ea1e634e8766 (diff) | |
Merge branch 'main' into stm32l0-reset-rtc
Diffstat (limited to 'examples')
| -rw-r--r-- | examples/rp/src/bin/usb_hid_mouse.rs | 182 | ||||
| -rw-r--r-- | examples/stm32g4/Cargo.toml | 2 | ||||
| -rw-r--r-- | examples/stm32g4/src/bin/can.rs | 182 | ||||
| -rw-r--r-- | examples/stm32h5/src/bin/can.rs | 90 | ||||
| -rw-r--r-- | examples/stm32h7/src/bin/can.rs | 90 | ||||
| -rw-r--r-- | examples/stm32u5/src/bin/usb_serial.rs | 27 |
6 files changed, 479 insertions, 94 deletions
diff --git a/examples/rp/src/bin/usb_hid_mouse.rs b/examples/rp/src/bin/usb_hid_mouse.rs new file mode 100644 index 000000000..afebd8813 --- /dev/null +++ b/examples/rp/src/bin/usb_hid_mouse.rs | |||
| @@ -0,0 +1,182 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | use core::sync::atomic::{AtomicBool, Ordering}; | ||
| 5 | |||
| 6 | use defmt::*; | ||
| 7 | use embassy_executor::Spawner; | ||
| 8 | use embassy_futures::join::join; | ||
| 9 | use embassy_rp::bind_interrupts; | ||
| 10 | use embassy_rp::clocks::RoscRng; | ||
| 11 | use embassy_rp::gpio::{Input, Pull}; | ||
| 12 | use embassy_rp::peripherals::USB; | ||
| 13 | use embassy_rp::usb::{Driver, InterruptHandler}; | ||
| 14 | use embassy_time::Timer; | ||
| 15 | use embassy_usb::class::hid::{HidReaderWriter, ReportId, RequestHandler, State}; | ||
| 16 | use embassy_usb::control::OutResponse; | ||
| 17 | use embassy_usb::{Builder, Config, Handler}; | ||
| 18 | use rand::Rng; | ||
| 19 | use usbd_hid::descriptor::{MouseReport, SerializedDescriptor}; | ||
| 20 | use {defmt_rtt as _, panic_probe as _}; | ||
| 21 | |||
| 22 | bind_interrupts!(struct Irqs { | ||
| 23 | USBCTRL_IRQ => InterruptHandler<USB>; | ||
| 24 | }); | ||
| 25 | |||
| 26 | #[embassy_executor::main] | ||
| 27 | async fn main(_spawner: Spawner) { | ||
| 28 | let p = embassy_rp::init(Default::default()); | ||
| 29 | // Create the driver, from the HAL. | ||
| 30 | let driver = Driver::new(p.USB, Irqs); | ||
| 31 | |||
| 32 | // Create embassy-usb Config | ||
| 33 | let mut config = Config::new(0xc0de, 0xcafe); | ||
| 34 | config.manufacturer = Some("Embassy"); | ||
| 35 | config.product = Some("HID keyboard example"); | ||
| 36 | config.serial_number = Some("12345678"); | ||
| 37 | config.max_power = 100; | ||
| 38 | config.max_packet_size_0 = 64; | ||
| 39 | |||
| 40 | // Create embassy-usb DeviceBuilder using the driver and config. | ||
| 41 | // It needs some buffers for building the descriptors. | ||
| 42 | let mut device_descriptor = [0; 256]; | ||
| 43 | let mut config_descriptor = [0; 256]; | ||
| 44 | let mut bos_descriptor = [0; 256]; | ||
| 45 | // You can also add a Microsoft OS descriptor. | ||
| 46 | let mut msos_descriptor = [0; 256]; | ||
| 47 | let mut control_buf = [0; 64]; | ||
| 48 | let request_handler = MyRequestHandler {}; | ||
| 49 | let mut device_handler = MyDeviceHandler::new(); | ||
| 50 | |||
| 51 | let mut state = State::new(); | ||
| 52 | |||
| 53 | let mut builder = Builder::new( | ||
| 54 | driver, | ||
| 55 | config, | ||
| 56 | &mut device_descriptor, | ||
| 57 | &mut config_descriptor, | ||
| 58 | &mut bos_descriptor, | ||
| 59 | &mut msos_descriptor, | ||
| 60 | &mut control_buf, | ||
| 61 | ); | ||
| 62 | |||
| 63 | builder.handler(&mut device_handler); | ||
| 64 | |||
| 65 | // Create classes on the builder. | ||
| 66 | let config = embassy_usb::class::hid::Config { | ||
| 67 | report_descriptor: MouseReport::desc(), | ||
| 68 | request_handler: Some(&request_handler), | ||
| 69 | poll_ms: 60, | ||
| 70 | max_packet_size: 64, | ||
| 71 | }; | ||
| 72 | let hid = HidReaderWriter::<_, 1, 8>::new(&mut builder, &mut state, config); | ||
| 73 | |||
| 74 | // Build the builder. | ||
| 75 | let mut usb = builder.build(); | ||
| 76 | |||
| 77 | // Run the USB device. | ||
| 78 | let usb_fut = usb.run(); | ||
| 79 | |||
| 80 | // Set up the signal pin that will be used to trigger the keyboard. | ||
| 81 | let mut signal_pin = Input::new(p.PIN_16, Pull::None); | ||
| 82 | |||
| 83 | // Enable the schmitt trigger to slightly debounce. | ||
| 84 | signal_pin.set_schmitt(true); | ||
| 85 | |||
| 86 | let (reader, mut writer) = hid.split(); | ||
| 87 | |||
| 88 | // Do stuff with the class! | ||
| 89 | let in_fut = async { | ||
| 90 | let mut rng = RoscRng; | ||
| 91 | |||
| 92 | loop { | ||
| 93 | // every 1 second | ||
| 94 | _ = Timer::after_secs(1).await; | ||
| 95 | let report = MouseReport { | ||
| 96 | buttons: 0, | ||
| 97 | x: rng.gen_range(-100..100), // random small x movement | ||
| 98 | y: rng.gen_range(-100..100), // random small y movement | ||
| 99 | wheel: 0, | ||
| 100 | pan: 0, | ||
| 101 | }; | ||
| 102 | // Send the report. | ||
| 103 | match writer.write_serialize(&report).await { | ||
| 104 | Ok(()) => {} | ||
| 105 | Err(e) => warn!("Failed to send report: {:?}", e), | ||
| 106 | } | ||
| 107 | } | ||
| 108 | }; | ||
| 109 | |||
| 110 | let out_fut = async { | ||
| 111 | reader.run(false, &request_handler).await; | ||
| 112 | }; | ||
| 113 | |||
| 114 | // Run everything concurrently. | ||
| 115 | // If we had made everything `'static` above instead, we could do this using separate tasks instead. | ||
| 116 | join(usb_fut, join(in_fut, out_fut)).await; | ||
| 117 | } | ||
| 118 | |||
| 119 | struct MyRequestHandler {} | ||
| 120 | |||
| 121 | impl RequestHandler for MyRequestHandler { | ||
| 122 | fn get_report(&self, id: ReportId, _buf: &mut [u8]) -> Option<usize> { | ||
| 123 | info!("Get report for {:?}", id); | ||
| 124 | None | ||
| 125 | } | ||
| 126 | |||
| 127 | fn set_report(&self, id: ReportId, data: &[u8]) -> OutResponse { | ||
| 128 | info!("Set report for {:?}: {=[u8]}", id, data); | ||
| 129 | OutResponse::Accepted | ||
| 130 | } | ||
| 131 | |||
| 132 | fn set_idle_ms(&self, id: Option<ReportId>, dur: u32) { | ||
| 133 | info!("Set idle rate for {:?} to {:?}", id, dur); | ||
| 134 | } | ||
| 135 | |||
| 136 | fn get_idle_ms(&self, id: Option<ReportId>) -> Option<u32> { | ||
| 137 | info!("Get idle rate for {:?}", id); | ||
| 138 | None | ||
| 139 | } | ||
| 140 | } | ||
| 141 | |||
| 142 | struct MyDeviceHandler { | ||
| 143 | configured: AtomicBool, | ||
| 144 | } | ||
| 145 | |||
| 146 | impl MyDeviceHandler { | ||
| 147 | fn new() -> Self { | ||
| 148 | MyDeviceHandler { | ||
| 149 | configured: AtomicBool::new(false), | ||
| 150 | } | ||
| 151 | } | ||
| 152 | } | ||
| 153 | |||
| 154 | impl Handler for MyDeviceHandler { | ||
| 155 | fn enabled(&mut self, enabled: bool) { | ||
| 156 | self.configured.store(false, Ordering::Relaxed); | ||
| 157 | if enabled { | ||
| 158 | info!("Device enabled"); | ||
| 159 | } else { | ||
| 160 | info!("Device disabled"); | ||
| 161 | } | ||
| 162 | } | ||
| 163 | |||
| 164 | fn reset(&mut self) { | ||
| 165 | self.configured.store(false, Ordering::Relaxed); | ||
| 166 | info!("Bus reset, the Vbus current limit is 100mA"); | ||
| 167 | } | ||
| 168 | |||
| 169 | fn addressed(&mut self, addr: u8) { | ||
| 170 | self.configured.store(false, Ordering::Relaxed); | ||
| 171 | info!("USB address set to: {}", addr); | ||
| 172 | } | ||
| 173 | |||
| 174 | fn configured(&mut self, configured: bool) { | ||
| 175 | self.configured.store(configured, Ordering::Relaxed); | ||
| 176 | if configured { | ||
| 177 | info!("Device configured, it may now draw up to the configured current limit from Vbus.") | ||
| 178 | } else { | ||
| 179 | info!("Device is no longer configured, the Vbus current limit is 100mA."); | ||
| 180 | } | ||
| 181 | } | ||
| 182 | } | ||
diff --git a/examples/stm32g4/Cargo.toml b/examples/stm32g4/Cargo.toml index 895ad3e7c..74ccfa3b0 100644 --- a/examples/stm32g4/Cargo.toml +++ b/examples/stm32g4/Cargo.toml | |||
| @@ -20,9 +20,11 @@ defmt-rtt = "0.4" | |||
| 20 | cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] } | 20 | cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] } |
| 21 | cortex-m-rt = "0.7.0" | 21 | cortex-m-rt = "0.7.0" |
| 22 | embedded-hal = "0.2.6" | 22 | embedded-hal = "0.2.6" |
| 23 | embedded-can = { version = "0.4" } | ||
| 23 | panic-probe = { version = "0.3", features = ["print-defmt"] } | 24 | panic-probe = { version = "0.3", features = ["print-defmt"] } |
| 24 | futures = { version = "0.3.17", default-features = false, features = ["async-await"] } | 25 | futures = { version = "0.3.17", default-features = false, features = ["async-await"] } |
| 25 | heapless = { version = "0.8", default-features = false } | 26 | heapless = { version = "0.8", default-features = false } |
| 27 | static_cell = "2.0.0" | ||
| 26 | 28 | ||
| 27 | [profile.release] | 29 | [profile.release] |
| 28 | debug = 2 | 30 | debug = 2 |
diff --git a/examples/stm32g4/src/bin/can.rs b/examples/stm32g4/src/bin/can.rs index 727921fba..affa97039 100644 --- a/examples/stm32g4/src/bin/can.rs +++ b/examples/stm32g4/src/bin/can.rs | |||
| @@ -5,6 +5,7 @@ use embassy_executor::Spawner; | |||
| 5 | use embassy_stm32::peripherals::*; | 5 | use embassy_stm32::peripherals::*; |
| 6 | use embassy_stm32::{bind_interrupts, can, Config}; | 6 | use embassy_stm32::{bind_interrupts, can, Config}; |
| 7 | use embassy_time::Timer; | 7 | use embassy_time::Timer; |
| 8 | use static_cell::StaticCell; | ||
| 8 | use {defmt_rtt as _, panic_probe as _}; | 9 | use {defmt_rtt as _, panic_probe as _}; |
| 9 | 10 | ||
| 10 | bind_interrupts!(struct Irqs { | 11 | bind_interrupts!(struct Irqs { |
| @@ -18,39 +19,190 @@ async fn main(_spawner: Spawner) { | |||
| 18 | 19 | ||
| 19 | let peripherals = embassy_stm32::init(config); | 20 | let peripherals = embassy_stm32::init(config); |
| 20 | 21 | ||
| 21 | let mut can = can::Fdcan::new(peripherals.FDCAN1, peripherals.PA11, peripherals.PA12, Irqs); | 22 | let mut can = can::FdcanConfigurator::new(peripherals.FDCAN1, peripherals.PA11, peripherals.PA12, Irqs); |
| 23 | |||
| 24 | can.set_extended_filter( | ||
| 25 | can::fd::filter::ExtendedFilterSlot::_0, | ||
| 26 | can::fd::filter::ExtendedFilter::accept_all_into_fifo1(), | ||
| 27 | ); | ||
| 22 | 28 | ||
| 23 | // 250k bps | 29 | // 250k bps |
| 24 | can.set_bitrate(250_000); | 30 | can.set_bitrate(250_000); |
| 25 | 31 | ||
| 32 | let use_fd = false; | ||
| 33 | |||
| 34 | // 1M bps | ||
| 35 | if use_fd { | ||
| 36 | can.set_fd_data_bitrate(1_000_000, false); | ||
| 37 | } | ||
| 38 | |||
| 26 | info!("Configured"); | 39 | info!("Configured"); |
| 27 | 40 | ||
| 28 | //let mut can = can.into_external_loopback_mode(); | 41 | let mut can = can.start(match use_fd { |
| 29 | let mut can = can.into_normal_mode(); | 42 | true => can::FdcanOperatingMode::InternalLoopbackMode, |
| 43 | false => can::FdcanOperatingMode::NormalOperationMode, | ||
| 44 | }); | ||
| 30 | 45 | ||
| 31 | let mut i = 0; | 46 | let mut i = 0; |
| 47 | let mut last_read_ts = embassy_time::Instant::now(); | ||
| 48 | |||
| 32 | loop { | 49 | loop { |
| 33 | let frame = can::TxFrame::new( | 50 | let frame = can::frame::ClassicFrame::new_extended(0x123456F, &[i; 8]).unwrap(); |
| 34 | can::TxFrameHeader { | ||
| 35 | len: 1, | ||
| 36 | frame_format: can::FrameFormat::Standard, | ||
| 37 | id: can::StandardId::new(0x123).unwrap().into(), | ||
| 38 | bit_rate_switching: false, | ||
| 39 | marker: None, | ||
| 40 | }, | ||
| 41 | &[i], | ||
| 42 | ) | ||
| 43 | .unwrap(); | ||
| 44 | info!("Writing frame"); | 51 | info!("Writing frame"); |
| 52 | |||
| 45 | _ = can.write(&frame).await; | 53 | _ = can.write(&frame).await; |
| 46 | 54 | ||
| 47 | match can.read().await { | 55 | match can.read().await { |
| 48 | Ok(rx_frame) => info!("Rx: {}", rx_frame.data()[0]), | 56 | Ok((rx_frame, ts)) => { |
| 57 | let delta = (ts - last_read_ts).as_millis(); | ||
| 58 | last_read_ts = ts; | ||
| 59 | info!( | ||
| 60 | "Rx: {} {:02x} --- {}ms", | ||
| 61 | rx_frame.header().len(), | ||
| 62 | rx_frame.data()[0..rx_frame.header().len() as usize], | ||
| 63 | delta, | ||
| 64 | ) | ||
| 65 | } | ||
| 49 | Err(_err) => error!("Error in frame"), | 66 | Err(_err) => error!("Error in frame"), |
| 50 | } | 67 | } |
| 51 | 68 | ||
| 52 | Timer::after_millis(250).await; | 69 | Timer::after_millis(250).await; |
| 53 | 70 | ||
| 54 | i += 1; | 71 | i += 1; |
| 72 | if i > 2 { | ||
| 73 | break; | ||
| 74 | } | ||
| 75 | } | ||
| 76 | |||
| 77 | // Use the FD API's even if we don't get FD packets. | ||
| 78 | |||
| 79 | loop { | ||
| 80 | if use_fd { | ||
| 81 | let frame = can::frame::FdFrame::new_extended(0x123456F, &[i; 16]).unwrap(); | ||
| 82 | info!("Writing frame using FD API"); | ||
| 83 | _ = can.write_fd(&frame).await; | ||
| 84 | } else { | ||
| 85 | let frame = can::frame::FdFrame::new_extended(0x123456F, &[i; 8]).unwrap(); | ||
| 86 | info!("Writing frame using FD API"); | ||
| 87 | _ = can.write_fd(&frame).await; | ||
| 88 | } | ||
| 89 | |||
| 90 | match can.read_fd().await { | ||
| 91 | Ok((rx_frame, ts)) => { | ||
| 92 | let delta = (ts - last_read_ts).as_millis(); | ||
| 93 | last_read_ts = ts; | ||
| 94 | info!( | ||
| 95 | "Rx: {} {:02x} --- using FD API {}ms", | ||
| 96 | rx_frame.header().len(), | ||
| 97 | rx_frame.data()[0..rx_frame.header().len() as usize], | ||
| 98 | delta, | ||
| 99 | ) | ||
| 100 | } | ||
| 101 | Err(_err) => error!("Error in frame"), | ||
| 102 | } | ||
| 103 | |||
| 104 | Timer::after_millis(250).await; | ||
| 105 | |||
| 106 | i += 1; | ||
| 107 | if i > 4 { | ||
| 108 | break; | ||
| 109 | } | ||
| 110 | } | ||
| 111 | i = 0; | ||
| 112 | let (mut tx, mut rx) = can.split(); | ||
| 113 | // With split | ||
| 114 | loop { | ||
| 115 | let frame = can::frame::ClassicFrame::new_extended(0x123456F, &[i; 8]).unwrap(); | ||
| 116 | info!("Writing frame"); | ||
| 117 | _ = tx.write(&frame).await; | ||
| 118 | |||
| 119 | match rx.read().await { | ||
| 120 | Ok((rx_frame, ts)) => { | ||
| 121 | let delta = (ts - last_read_ts).as_millis(); | ||
| 122 | last_read_ts = ts; | ||
| 123 | info!( | ||
| 124 | "Rx: {} {:02x} --- {}ms", | ||
| 125 | rx_frame.header().len(), | ||
| 126 | rx_frame.data()[0..rx_frame.header().len() as usize], | ||
| 127 | delta, | ||
| 128 | ) | ||
| 129 | } | ||
| 130 | Err(_err) => error!("Error in frame"), | ||
| 131 | } | ||
| 132 | |||
| 133 | Timer::after_millis(250).await; | ||
| 134 | |||
| 135 | i += 1; | ||
| 136 | |||
| 137 | if i > 2 { | ||
| 138 | break; | ||
| 139 | } | ||
| 140 | } | ||
| 141 | |||
| 142 | let can = can::Fdcan::join(tx, rx); | ||
| 143 | |||
| 144 | info!("\n\n\nBuffered\n"); | ||
| 145 | if use_fd { | ||
| 146 | static TX_BUF: StaticCell<can::TxFdBuf<8>> = StaticCell::new(); | ||
| 147 | static RX_BUF: StaticCell<can::RxFdBuf<10>> = StaticCell::new(); | ||
| 148 | let mut can = can.buffered_fd( | ||
| 149 | TX_BUF.init(can::TxFdBuf::<8>::new()), | ||
| 150 | RX_BUF.init(can::RxFdBuf::<10>::new()), | ||
| 151 | ); | ||
| 152 | loop { | ||
| 153 | let frame = can::frame::FdFrame::new_extended(0x123456F, &[i; 16]).unwrap(); | ||
| 154 | info!("Writing frame"); | ||
| 155 | |||
| 156 | _ = can.write(frame).await; | ||
| 157 | |||
| 158 | match can.read().await { | ||
| 159 | Ok((rx_frame, ts)) => { | ||
| 160 | let delta = (ts - last_read_ts).as_millis(); | ||
| 161 | last_read_ts = ts; | ||
| 162 | info!( | ||
| 163 | "Rx: {} {:02x} --- {}ms", | ||
| 164 | rx_frame.header().len(), | ||
| 165 | rx_frame.data()[0..rx_frame.header().len() as usize], | ||
| 166 | delta, | ||
| 167 | ) | ||
| 168 | } | ||
| 169 | Err(_err) => error!("Error in frame"), | ||
| 170 | } | ||
| 171 | |||
| 172 | Timer::after_millis(250).await; | ||
| 173 | |||
| 174 | i += 1; | ||
| 175 | } | ||
| 176 | } else { | ||
| 177 | static TX_BUF: StaticCell<can::TxBuf<8>> = StaticCell::new(); | ||
| 178 | static RX_BUF: StaticCell<can::RxBuf<10>> = StaticCell::new(); | ||
| 179 | let mut can = can.buffered( | ||
| 180 | TX_BUF.init(can::TxBuf::<8>::new()), | ||
| 181 | RX_BUF.init(can::RxBuf::<10>::new()), | ||
| 182 | ); | ||
| 183 | loop { | ||
| 184 | let frame = can::frame::ClassicFrame::new_extended(0x123456F, &[i; 8]).unwrap(); | ||
| 185 | info!("Writing frame"); | ||
| 186 | |||
| 187 | _ = can.write(frame).await; | ||
| 188 | |||
| 189 | match can.read().await { | ||
| 190 | Ok((rx_frame, ts)) => { | ||
| 191 | let delta = (ts - last_read_ts).as_millis(); | ||
| 192 | last_read_ts = ts; | ||
| 193 | info!( | ||
| 194 | "Rx: {} {:02x} --- {}ms", | ||
| 195 | rx_frame.header().len(), | ||
| 196 | rx_frame.data()[0..rx_frame.header().len() as usize], | ||
| 197 | delta, | ||
| 198 | ) | ||
| 199 | } | ||
| 200 | Err(_err) => error!("Error in frame"), | ||
| 201 | } | ||
| 202 | |||
| 203 | Timer::after_millis(250).await; | ||
| 204 | |||
| 205 | i += 1; | ||
| 206 | } | ||
| 55 | } | 207 | } |
| 56 | } | 208 | } |
diff --git a/examples/stm32h5/src/bin/can.rs b/examples/stm32h5/src/bin/can.rs index 2906d1576..e5ccfe4f7 100644 --- a/examples/stm32h5/src/bin/can.rs +++ b/examples/stm32h5/src/bin/can.rs | |||
| @@ -16,54 +16,76 @@ bind_interrupts!(struct Irqs { | |||
| 16 | #[embassy_executor::main] | 16 | #[embassy_executor::main] |
| 17 | async fn main(_spawner: Spawner) { | 17 | async fn main(_spawner: Spawner) { |
| 18 | let mut config = Config::default(); | 18 | let mut config = Config::default(); |
| 19 | 19 | config.rcc.hse = Some(rcc::Hse { | |
| 20 | // configure FDCAN to use PLL1_Q at 64 MHz | 20 | freq: embassy_stm32::time::Hertz(25_000_000), |
| 21 | config.rcc.pll1 = Some(rcc::Pll { | 21 | mode: rcc::HseMode::Oscillator, |
| 22 | source: rcc::PllSource::HSI, | ||
| 23 | prediv: rcc::PllPreDiv::DIV4, | ||
| 24 | mul: rcc::PllMul::MUL8, | ||
| 25 | divp: None, | ||
| 26 | divq: Some(rcc::PllDiv::DIV2), | ||
| 27 | divr: None, | ||
| 28 | }); | 22 | }); |
| 29 | config.rcc.fdcan_clock_source = rcc::FdCanClockSource::PLL1_Q; | 23 | config.rcc.fdcan_clock_source = rcc::FdCanClockSource::HSE; |
| 30 | 24 | ||
| 31 | let peripherals = embassy_stm32::init(config); | 25 | let peripherals = embassy_stm32::init(config); |
| 32 | 26 | ||
| 33 | let mut can = can::Fdcan::new(peripherals.FDCAN1, peripherals.PA11, peripherals.PA12, Irqs); | 27 | let mut can = can::FdcanConfigurator::new(peripherals.FDCAN1, peripherals.PA11, peripherals.PA12, Irqs); |
| 34 | 28 | ||
| 35 | can.can.apply_config( | 29 | // 250k bps |
| 36 | can::config::FdCanConfig::default().set_nominal_bit_timing(can::config::NominalBitTiming { | 30 | can.set_bitrate(250_000); |
| 37 | sync_jump_width: 1.try_into().unwrap(), | ||
| 38 | prescaler: 8.try_into().unwrap(), | ||
| 39 | seg1: 13.try_into().unwrap(), | ||
| 40 | seg2: 2.try_into().unwrap(), | ||
| 41 | }), | ||
| 42 | ); | ||
| 43 | 31 | ||
| 44 | info!("Configured"); | 32 | //let mut can = can.into_internal_loopback_mode(); |
| 33 | let mut can = can.into_normal_mode(); | ||
| 45 | 34 | ||
| 46 | let mut can = can.into_external_loopback_mode(); | 35 | info!("CAN Configured"); |
| 47 | //let mut can = can.into_normal_mode(); | ||
| 48 | 36 | ||
| 49 | let mut i = 0; | 37 | let mut i = 0; |
| 38 | let mut last_read_ts = embassy_time::Instant::now(); | ||
| 39 | |||
| 50 | loop { | 40 | loop { |
| 51 | let frame = can::TxFrame::new( | 41 | let frame = can::frame::ClassicFrame::new_extended(0x123456F, &[i; 8]).unwrap(); |
| 52 | can::TxFrameHeader { | ||
| 53 | len: 1, | ||
| 54 | frame_format: can::FrameFormat::Standard, | ||
| 55 | id: can::StandardId::new(0x123).unwrap().into(), | ||
| 56 | bit_rate_switching: false, | ||
| 57 | marker: None, | ||
| 58 | }, | ||
| 59 | &[i], | ||
| 60 | ) | ||
| 61 | .unwrap(); | ||
| 62 | info!("Writing frame"); | 42 | info!("Writing frame"); |
| 63 | _ = can.write(&frame).await; | 43 | _ = can.write(&frame).await; |
| 64 | 44 | ||
| 65 | match can.read().await { | 45 | match can.read().await { |
| 66 | Ok(rx_frame) => info!("Rx: {}", rx_frame.data()[0]), | 46 | Ok((rx_frame, ts)) => { |
| 47 | let delta = (ts - last_read_ts).as_millis(); | ||
| 48 | last_read_ts = ts; | ||
| 49 | info!( | ||
| 50 | "Rx: {:x} {:x} {:x} {:x} --- NEW {}", | ||
| 51 | rx_frame.data()[0], | ||
| 52 | rx_frame.data()[1], | ||
| 53 | rx_frame.data()[2], | ||
| 54 | rx_frame.data()[3], | ||
| 55 | delta, | ||
| 56 | ) | ||
| 57 | } | ||
| 58 | Err(_err) => error!("Error in frame"), | ||
| 59 | } | ||
| 60 | |||
| 61 | Timer::after_millis(250).await; | ||
| 62 | |||
| 63 | i += 1; | ||
| 64 | if i > 3 { | ||
| 65 | break; | ||
| 66 | } | ||
| 67 | } | ||
| 68 | |||
| 69 | let (mut tx, mut rx) = can.split(); | ||
| 70 | // With split | ||
| 71 | loop { | ||
| 72 | let frame = can::frame::ClassicFrame::new_extended(0x123456F, &[i; 8]).unwrap(); | ||
| 73 | info!("Writing frame"); | ||
| 74 | _ = tx.write(&frame).await; | ||
| 75 | |||
| 76 | match rx.read().await { | ||
| 77 | Ok((rx_frame, ts)) => { | ||
| 78 | let delta = (ts - last_read_ts).as_millis(); | ||
| 79 | last_read_ts = ts; | ||
| 80 | info!( | ||
| 81 | "Rx: {:x} {:x} {:x} {:x} --- NEW {}", | ||
| 82 | rx_frame.data()[0], | ||
| 83 | rx_frame.data()[1], | ||
| 84 | rx_frame.data()[2], | ||
| 85 | rx_frame.data()[3], | ||
| 86 | delta, | ||
| 87 | ) | ||
| 88 | } | ||
| 67 | Err(_err) => error!("Error in frame"), | 89 | Err(_err) => error!("Error in frame"), |
| 68 | } | 90 | } |
| 69 | 91 | ||
diff --git a/examples/stm32h7/src/bin/can.rs b/examples/stm32h7/src/bin/can.rs index 2906d1576..e5ccfe4f7 100644 --- a/examples/stm32h7/src/bin/can.rs +++ b/examples/stm32h7/src/bin/can.rs | |||
| @@ -16,54 +16,76 @@ bind_interrupts!(struct Irqs { | |||
| 16 | #[embassy_executor::main] | 16 | #[embassy_executor::main] |
| 17 | async fn main(_spawner: Spawner) { | 17 | async fn main(_spawner: Spawner) { |
| 18 | let mut config = Config::default(); | 18 | let mut config = Config::default(); |
| 19 | 19 | config.rcc.hse = Some(rcc::Hse { | |
| 20 | // configure FDCAN to use PLL1_Q at 64 MHz | 20 | freq: embassy_stm32::time::Hertz(25_000_000), |
| 21 | config.rcc.pll1 = Some(rcc::Pll { | 21 | mode: rcc::HseMode::Oscillator, |
| 22 | source: rcc::PllSource::HSI, | ||
| 23 | prediv: rcc::PllPreDiv::DIV4, | ||
| 24 | mul: rcc::PllMul::MUL8, | ||
| 25 | divp: None, | ||
| 26 | divq: Some(rcc::PllDiv::DIV2), | ||
| 27 | divr: None, | ||
| 28 | }); | 22 | }); |
| 29 | config.rcc.fdcan_clock_source = rcc::FdCanClockSource::PLL1_Q; | 23 | config.rcc.fdcan_clock_source = rcc::FdCanClockSource::HSE; |
| 30 | 24 | ||
| 31 | let peripherals = embassy_stm32::init(config); | 25 | let peripherals = embassy_stm32::init(config); |
| 32 | 26 | ||
| 33 | let mut can = can::Fdcan::new(peripherals.FDCAN1, peripherals.PA11, peripherals.PA12, Irqs); | 27 | let mut can = can::FdcanConfigurator::new(peripherals.FDCAN1, peripherals.PA11, peripherals.PA12, Irqs); |
| 34 | 28 | ||
| 35 | can.can.apply_config( | 29 | // 250k bps |
| 36 | can::config::FdCanConfig::default().set_nominal_bit_timing(can::config::NominalBitTiming { | 30 | can.set_bitrate(250_000); |
| 37 | sync_jump_width: 1.try_into().unwrap(), | ||
| 38 | prescaler: 8.try_into().unwrap(), | ||
| 39 | seg1: 13.try_into().unwrap(), | ||
| 40 | seg2: 2.try_into().unwrap(), | ||
| 41 | }), | ||
| 42 | ); | ||
| 43 | 31 | ||
| 44 | info!("Configured"); | 32 | //let mut can = can.into_internal_loopback_mode(); |
| 33 | let mut can = can.into_normal_mode(); | ||
| 45 | 34 | ||
| 46 | let mut can = can.into_external_loopback_mode(); | 35 | info!("CAN Configured"); |
| 47 | //let mut can = can.into_normal_mode(); | ||
| 48 | 36 | ||
| 49 | let mut i = 0; | 37 | let mut i = 0; |
| 38 | let mut last_read_ts = embassy_time::Instant::now(); | ||
| 39 | |||
| 50 | loop { | 40 | loop { |
| 51 | let frame = can::TxFrame::new( | 41 | let frame = can::frame::ClassicFrame::new_extended(0x123456F, &[i; 8]).unwrap(); |
| 52 | can::TxFrameHeader { | ||
| 53 | len: 1, | ||
| 54 | frame_format: can::FrameFormat::Standard, | ||
| 55 | id: can::StandardId::new(0x123).unwrap().into(), | ||
| 56 | bit_rate_switching: false, | ||
| 57 | marker: None, | ||
| 58 | }, | ||
| 59 | &[i], | ||
| 60 | ) | ||
| 61 | .unwrap(); | ||
| 62 | info!("Writing frame"); | 42 | info!("Writing frame"); |
| 63 | _ = can.write(&frame).await; | 43 | _ = can.write(&frame).await; |
| 64 | 44 | ||
| 65 | match can.read().await { | 45 | match can.read().await { |
| 66 | Ok(rx_frame) => info!("Rx: {}", rx_frame.data()[0]), | 46 | Ok((rx_frame, ts)) => { |
| 47 | let delta = (ts - last_read_ts).as_millis(); | ||
| 48 | last_read_ts = ts; | ||
| 49 | info!( | ||
| 50 | "Rx: {:x} {:x} {:x} {:x} --- NEW {}", | ||
| 51 | rx_frame.data()[0], | ||
| 52 | rx_frame.data()[1], | ||
| 53 | rx_frame.data()[2], | ||
| 54 | rx_frame.data()[3], | ||
| 55 | delta, | ||
| 56 | ) | ||
| 57 | } | ||
| 58 | Err(_err) => error!("Error in frame"), | ||
| 59 | } | ||
| 60 | |||
| 61 | Timer::after_millis(250).await; | ||
| 62 | |||
| 63 | i += 1; | ||
| 64 | if i > 3 { | ||
| 65 | break; | ||
| 66 | } | ||
| 67 | } | ||
| 68 | |||
| 69 | let (mut tx, mut rx) = can.split(); | ||
| 70 | // With split | ||
| 71 | loop { | ||
| 72 | let frame = can::frame::ClassicFrame::new_extended(0x123456F, &[i; 8]).unwrap(); | ||
| 73 | info!("Writing frame"); | ||
| 74 | _ = tx.write(&frame).await; | ||
| 75 | |||
| 76 | match rx.read().await { | ||
| 77 | Ok((rx_frame, ts)) => { | ||
| 78 | let delta = (ts - last_read_ts).as_millis(); | ||
| 79 | last_read_ts = ts; | ||
| 80 | info!( | ||
| 81 | "Rx: {:x} {:x} {:x} {:x} --- NEW {}", | ||
| 82 | rx_frame.data()[0], | ||
| 83 | rx_frame.data()[1], | ||
| 84 | rx_frame.data()[2], | ||
| 85 | rx_frame.data()[3], | ||
| 86 | delta, | ||
| 87 | ) | ||
| 88 | } | ||
| 67 | Err(_err) => error!("Error in frame"), | 89 | Err(_err) => error!("Error in frame"), |
| 68 | } | 90 | } |
| 69 | 91 | ||
diff --git a/examples/stm32u5/src/bin/usb_serial.rs b/examples/stm32u5/src/bin/usb_serial.rs index dca34fd0e..99cdeacc9 100644 --- a/examples/stm32u5/src/bin/usb_serial.rs +++ b/examples/stm32u5/src/bin/usb_serial.rs | |||
| @@ -4,7 +4,6 @@ | |||
| 4 | use defmt::{panic, *}; | 4 | use defmt::{panic, *}; |
| 5 | use defmt_rtt as _; // global logger | 5 | use defmt_rtt as _; // global logger |
| 6 | use embassy_executor::Spawner; | 6 | use embassy_executor::Spawner; |
| 7 | use embassy_stm32::rcc::*; | ||
| 8 | use embassy_stm32::usb_otg::{Driver, Instance}; | 7 | use embassy_stm32::usb_otg::{Driver, Instance}; |
| 9 | use embassy_stm32::{bind_interrupts, peripherals, usb_otg, Config}; | 8 | use embassy_stm32::{bind_interrupts, peripherals, usb_otg, Config}; |
| 10 | use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; | 9 | use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; |
| @@ -22,22 +21,28 @@ async fn main(_spawner: Spawner) { | |||
| 22 | info!("Hello World!"); | 21 | info!("Hello World!"); |
| 23 | 22 | ||
| 24 | let mut config = Config::default(); | 23 | let mut config = Config::default(); |
| 25 | config.rcc.mux = ClockSrc::PLL1_R(PllConfig { | 24 | { |
| 26 | source: PllSource::HSI, | 25 | use embassy_stm32::rcc::*; |
| 27 | m: Pllm::DIV2, | 26 | config.rcc.hsi = true; |
| 28 | n: Plln::MUL10, | 27 | config.rcc.pll1 = Some(Pll { |
| 29 | p: Plldiv::DIV1, | 28 | source: PllSource::HSI, // 16 MHz |
| 30 | q: Plldiv::DIV1, | 29 | prediv: PllPreDiv::DIV1, |
| 31 | r: Plldiv::DIV1, | 30 | mul: PllMul::MUL10, |
| 32 | }); | 31 | divp: None, |
| 33 | config.rcc.hsi48 = Some(Hsi48Config { sync_from_usb: true }); // needed for USB | 32 | divq: None, |
| 33 | divr: Some(PllDiv::DIV1), // 160 MHz | ||
| 34 | }); | ||
| 35 | config.rcc.mux = ClockSrc::PLL1_R; | ||
| 36 | config.rcc.voltage_range = VoltageScale::RANGE1; | ||
| 37 | config.rcc.hsi48 = Some(Hsi48Config { sync_from_usb: true }); // needed for USB | ||
| 38 | } | ||
| 34 | 39 | ||
| 35 | let p = embassy_stm32::init(config); | 40 | let p = embassy_stm32::init(config); |
| 36 | 41 | ||
| 37 | // Create the driver, from the HAL. | 42 | // Create the driver, from the HAL. |
| 38 | let mut ep_out_buffer = [0u8; 256]; | 43 | let mut ep_out_buffer = [0u8; 256]; |
| 39 | let mut config = embassy_stm32::usb_otg::Config::default(); | 44 | let mut config = embassy_stm32::usb_otg::Config::default(); |
| 40 | config.vbus_detection = true; | 45 | config.vbus_detection = false; |
| 41 | let driver = Driver::new_fs(p.USB_OTG_FS, Irqs, p.PA12, p.PA11, &mut ep_out_buffer, config); | 46 | let driver = Driver::new_fs(p.USB_OTG_FS, Irqs, p.PA12, p.PA11, &mut ep_out_buffer, config); |
| 42 | 47 | ||
| 43 | // Create embassy-usb Config | 48 | // Create embassy-usb Config |
