diff options
Diffstat (limited to 'examples')
48 files changed, 1337 insertions, 312 deletions
diff --git a/examples/nrf52840/src/bin/gpiote_channel.rs b/examples/nrf52840/src/bin/gpiote_channel.rs index c7ddc1d8d..e358779b2 100644 --- a/examples/nrf52840/src/bin/gpiote_channel.rs +++ b/examples/nrf52840/src/bin/gpiote_channel.rs | |||
| @@ -12,10 +12,10 @@ async fn main(_spawner: Spawner) { | |||
| 12 | let p = embassy_nrf::init(Default::default()); | 12 | let p = embassy_nrf::init(Default::default()); |
| 13 | info!("Starting!"); | 13 | info!("Starting!"); |
| 14 | 14 | ||
| 15 | let ch1 = InputChannel::new(p.GPIOTE_CH0, p.P0_11, Pull::Up, InputChannelPolarity::HiToLo); | 15 | let mut ch1 = InputChannel::new(p.GPIOTE_CH0, p.P0_11, Pull::Up, InputChannelPolarity::HiToLo); |
| 16 | let ch2 = InputChannel::new(p.GPIOTE_CH1, p.P0_12, Pull::Up, InputChannelPolarity::LoToHi); | 16 | let mut ch2 = InputChannel::new(p.GPIOTE_CH1, p.P0_12, Pull::Up, InputChannelPolarity::LoToHi); |
| 17 | let ch3 = InputChannel::new(p.GPIOTE_CH2, p.P0_24, Pull::Up, InputChannelPolarity::Toggle); | 17 | let mut ch3 = InputChannel::new(p.GPIOTE_CH2, p.P0_24, Pull::Up, InputChannelPolarity::Toggle); |
| 18 | let ch4 = InputChannel::new(p.GPIOTE_CH3, p.P0_25, Pull::Up, InputChannelPolarity::Toggle); | 18 | let mut ch4 = InputChannel::new(p.GPIOTE_CH3, p.P0_25, Pull::Up, InputChannelPolarity::Toggle); |
| 19 | 19 | ||
| 20 | let button1 = async { | 20 | let button1 = async { |
| 21 | loop { | 21 | loop { |
diff --git a/examples/nrf52840/src/bin/usb_hid_keyboard.rs b/examples/nrf52840/src/bin/usb_hid_keyboard.rs index 1cd730503..7b7303526 100644 --- a/examples/nrf52840/src/bin/usb_hid_keyboard.rs +++ b/examples/nrf52840/src/bin/usb_hid_keyboard.rs | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | #![no_std] | 1 | #![no_std] |
| 2 | #![no_main] | 2 | #![no_main] |
| 3 | 3 | ||
| 4 | use core::sync::atomic::{AtomicBool, Ordering}; | 4 | use core::sync::atomic::{AtomicBool, AtomicU8, Ordering}; |
| 5 | 5 | ||
| 6 | use defmt::*; | 6 | use defmt::*; |
| 7 | use embassy_executor::Spawner; | 7 | use embassy_executor::Spawner; |
| @@ -13,7 +13,9 @@ use embassy_nrf::usb::vbus_detect::HardwareVbusDetect; | |||
| 13 | use embassy_nrf::{bind_interrupts, pac, peripherals, usb}; | 13 | use embassy_nrf::{bind_interrupts, pac, peripherals, usb}; |
| 14 | use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; | 14 | use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; |
| 15 | use embassy_sync::signal::Signal; | 15 | use embassy_sync::signal::Signal; |
| 16 | use embassy_usb::class::hid::{HidReaderWriter, ReportId, RequestHandler, State}; | 16 | use embassy_usb::class::hid::{ |
| 17 | HidBootProtocol, HidProtocolMode, HidReaderWriter, HidSubclass, ReportId, RequestHandler, State, | ||
| 18 | }; | ||
| 17 | use embassy_usb::control::OutResponse; | 19 | use embassy_usb::control::OutResponse; |
| 18 | use embassy_usb::{Builder, Config, Handler}; | 20 | use embassy_usb::{Builder, Config, Handler}; |
| 19 | use usbd_hid::descriptor::{KeyboardReport, SerializedDescriptor}; | 21 | use usbd_hid::descriptor::{KeyboardReport, SerializedDescriptor}; |
| @@ -26,6 +28,8 @@ bind_interrupts!(struct Irqs { | |||
| 26 | 28 | ||
| 27 | static SUSPENDED: AtomicBool = AtomicBool::new(false); | 29 | static SUSPENDED: AtomicBool = AtomicBool::new(false); |
| 28 | 30 | ||
| 31 | static HID_PROTOCOL_MODE: AtomicU8 = AtomicU8::new(HidProtocolMode::Boot as u8); | ||
| 32 | |||
| 29 | #[embassy_executor::main] | 33 | #[embassy_executor::main] |
| 30 | async fn main(_spawner: Spawner) { | 34 | async fn main(_spawner: Spawner) { |
| 31 | let p = embassy_nrf::init(Default::default()); | 35 | let p = embassy_nrf::init(Default::default()); |
| @@ -45,6 +49,10 @@ async fn main(_spawner: Spawner) { | |||
| 45 | config.max_power = 100; | 49 | config.max_power = 100; |
| 46 | config.max_packet_size_0 = 64; | 50 | config.max_packet_size_0 = 64; |
| 47 | config.supports_remote_wakeup = true; | 51 | config.supports_remote_wakeup = true; |
| 52 | config.composite_with_iads = false; | ||
| 53 | config.device_class = 0; | ||
| 54 | config.device_sub_class = 0; | ||
| 55 | config.device_protocol = 0; | ||
| 48 | 56 | ||
| 49 | // Create embassy-usb DeviceBuilder using the driver and config. | 57 | // Create embassy-usb DeviceBuilder using the driver and config. |
| 50 | // It needs some buffers for building the descriptors. | 58 | // It needs some buffers for building the descriptors. |
| @@ -74,6 +82,8 @@ async fn main(_spawner: Spawner) { | |||
| 74 | request_handler: None, | 82 | request_handler: None, |
| 75 | poll_ms: 60, | 83 | poll_ms: 60, |
| 76 | max_packet_size: 64, | 84 | max_packet_size: 64, |
| 85 | hid_subclass: HidSubclass::Boot, | ||
| 86 | hid_boot_protocol: HidBootProtocol::Keyboard, | ||
| 77 | }; | 87 | }; |
| 78 | let hid = HidReaderWriter::<_, 1, 8>::new(&mut builder, &mut state, config); | 88 | let hid = HidReaderWriter::<_, 1, 8>::new(&mut builder, &mut state, config); |
| 79 | 89 | ||
| @@ -106,6 +116,11 @@ async fn main(_spawner: Spawner) { | |||
| 106 | if SUSPENDED.load(Ordering::Acquire) { | 116 | if SUSPENDED.load(Ordering::Acquire) { |
| 107 | info!("Triggering remote wakeup"); | 117 | info!("Triggering remote wakeup"); |
| 108 | remote_wakeup.signal(()); | 118 | remote_wakeup.signal(()); |
| 119 | } else if HID_PROTOCOL_MODE.load(Ordering::Relaxed) == HidProtocolMode::Boot as u8 { | ||
| 120 | match writer.write(&[0, 0, 4, 0, 0, 0, 0, 0]).await { | ||
| 121 | Ok(()) => {} | ||
| 122 | Err(e) => warn!("Failed to send boot report: {:?}", e), | ||
| 123 | }; | ||
| 109 | } else { | 124 | } else { |
| 110 | let report = KeyboardReport { | 125 | let report = KeyboardReport { |
| 111 | keycodes: [4, 0, 0, 0, 0, 0], | 126 | keycodes: [4, 0, 0, 0, 0, 0], |
| @@ -121,16 +136,23 @@ async fn main(_spawner: Spawner) { | |||
| 121 | 136 | ||
| 122 | button.wait_for_high().await; | 137 | button.wait_for_high().await; |
| 123 | info!("RELEASED"); | 138 | info!("RELEASED"); |
| 124 | let report = KeyboardReport { | 139 | if HID_PROTOCOL_MODE.load(Ordering::Relaxed) == HidProtocolMode::Boot as u8 { |
| 125 | keycodes: [0, 0, 0, 0, 0, 0], | 140 | match writer.write(&[0, 0, 0, 0, 0, 0, 0, 0]).await { |
| 126 | leds: 0, | 141 | Ok(()) => {} |
| 127 | modifier: 0, | 142 | Err(e) => warn!("Failed to send boot report: {:?}", e), |
| 128 | reserved: 0, | 143 | }; |
| 129 | }; | 144 | } else { |
| 130 | match writer.write_serialize(&report).await { | 145 | let report = KeyboardReport { |
| 131 | Ok(()) => {} | 146 | keycodes: [0, 0, 0, 0, 0, 0], |
| 132 | Err(e) => warn!("Failed to send report: {:?}", e), | 147 | leds: 0, |
| 133 | }; | 148 | modifier: 0, |
| 149 | reserved: 0, | ||
| 150 | }; | ||
| 151 | match writer.write_serialize(&report).await { | ||
| 152 | Ok(()) => {} | ||
| 153 | Err(e) => warn!("Failed to send report: {:?}", e), | ||
| 154 | }; | ||
| 155 | } | ||
| 134 | } | 156 | } |
| 135 | }; | 157 | }; |
| 136 | 158 | ||
| @@ -156,6 +178,18 @@ impl RequestHandler for MyRequestHandler { | |||
| 156 | OutResponse::Accepted | 178 | OutResponse::Accepted |
| 157 | } | 179 | } |
| 158 | 180 | ||
| 181 | fn get_protocol(&self) -> HidProtocolMode { | ||
| 182 | let protocol = HidProtocolMode::from(HID_PROTOCOL_MODE.load(Ordering::Relaxed)); | ||
| 183 | info!("The current HID protocol mode is: {}", protocol); | ||
| 184 | protocol | ||
| 185 | } | ||
| 186 | |||
| 187 | fn set_protocol(&mut self, protocol: HidProtocolMode) -> OutResponse { | ||
| 188 | info!("Switching to HID protocol mode: {}", protocol); | ||
| 189 | HID_PROTOCOL_MODE.store(protocol as u8, Ordering::Relaxed); | ||
| 190 | OutResponse::Accepted | ||
| 191 | } | ||
| 192 | |||
| 159 | fn set_idle_ms(&mut self, id: Option<ReportId>, dur: u32) { | 193 | fn set_idle_ms(&mut self, id: Option<ReportId>, dur: u32) { |
| 160 | info!("Set idle rate for {:?} to {:?}", id, dur); | 194 | info!("Set idle rate for {:?} to {:?}", id, dur); |
| 161 | } | 195 | } |
diff --git a/examples/nrf52840/src/bin/usb_hid_mouse.rs b/examples/nrf52840/src/bin/usb_hid_mouse.rs index 3c0fc04e8..6bee4546b 100644 --- a/examples/nrf52840/src/bin/usb_hid_mouse.rs +++ b/examples/nrf52840/src/bin/usb_hid_mouse.rs | |||
| @@ -1,6 +1,8 @@ | |||
| 1 | #![no_std] | 1 | #![no_std] |
| 2 | #![no_main] | 2 | #![no_main] |
| 3 | 3 | ||
| 4 | use core::sync::atomic::{AtomicU8, Ordering}; | ||
| 5 | |||
| 4 | use defmt::*; | 6 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 7 | use embassy_executor::Spawner; |
| 6 | use embassy_futures::join::join; | 8 | use embassy_futures::join::join; |
| @@ -8,7 +10,9 @@ use embassy_nrf::usb::Driver; | |||
| 8 | use embassy_nrf::usb::vbus_detect::HardwareVbusDetect; | 10 | use embassy_nrf::usb::vbus_detect::HardwareVbusDetect; |
| 9 | use embassy_nrf::{bind_interrupts, pac, peripherals, usb}; | 11 | use embassy_nrf::{bind_interrupts, pac, peripherals, usb}; |
| 10 | use embassy_time::Timer; | 12 | use embassy_time::Timer; |
| 11 | use embassy_usb::class::hid::{HidWriter, ReportId, RequestHandler, State}; | 13 | use embassy_usb::class::hid::{ |
| 14 | HidBootProtocol, HidProtocolMode, HidSubclass, HidWriter, ReportId, RequestHandler, State, | ||
| 15 | }; | ||
| 12 | use embassy_usb::control::OutResponse; | 16 | use embassy_usb::control::OutResponse; |
| 13 | use embassy_usb::{Builder, Config}; | 17 | use embassy_usb::{Builder, Config}; |
| 14 | use usbd_hid::descriptor::{MouseReport, SerializedDescriptor}; | 18 | use usbd_hid::descriptor::{MouseReport, SerializedDescriptor}; |
| @@ -19,6 +23,8 @@ bind_interrupts!(struct Irqs { | |||
| 19 | CLOCK_POWER => usb::vbus_detect::InterruptHandler; | 23 | CLOCK_POWER => usb::vbus_detect::InterruptHandler; |
| 20 | }); | 24 | }); |
| 21 | 25 | ||
| 26 | static HID_PROTOCOL_MODE: AtomicU8 = AtomicU8::new(HidProtocolMode::Boot as u8); | ||
| 27 | |||
| 22 | #[embassy_executor::main] | 28 | #[embassy_executor::main] |
| 23 | async fn main(_spawner: Spawner) { | 29 | async fn main(_spawner: Spawner) { |
| 24 | let p = embassy_nrf::init(Default::default()); | 30 | let p = embassy_nrf::init(Default::default()); |
| @@ -37,6 +43,10 @@ async fn main(_spawner: Spawner) { | |||
| 37 | config.serial_number = Some("12345678"); | 43 | config.serial_number = Some("12345678"); |
| 38 | config.max_power = 100; | 44 | config.max_power = 100; |
| 39 | config.max_packet_size_0 = 64; | 45 | config.max_packet_size_0 = 64; |
| 46 | config.composite_with_iads = false; | ||
| 47 | config.device_class = 0; | ||
| 48 | config.device_sub_class = 0; | ||
| 49 | config.device_protocol = 0; | ||
| 40 | 50 | ||
| 41 | // Create embassy-usb DeviceBuilder using the driver and config. | 51 | // Create embassy-usb DeviceBuilder using the driver and config. |
| 42 | // It needs some buffers for building the descriptors. | 52 | // It needs some buffers for building the descriptors. |
| @@ -63,6 +73,8 @@ async fn main(_spawner: Spawner) { | |||
| 63 | request_handler: Some(&mut request_handler), | 73 | request_handler: Some(&mut request_handler), |
| 64 | poll_ms: 60, | 74 | poll_ms: 60, |
| 65 | max_packet_size: 8, | 75 | max_packet_size: 8, |
| 76 | hid_subclass: HidSubclass::Boot, | ||
| 77 | hid_boot_protocol: HidBootProtocol::Mouse, | ||
| 66 | }; | 78 | }; |
| 67 | 79 | ||
| 68 | let mut writer = HidWriter::<_, 5>::new(&mut builder, &mut state, config); | 80 | let mut writer = HidWriter::<_, 5>::new(&mut builder, &mut state, config); |
| @@ -80,16 +92,26 @@ async fn main(_spawner: Spawner) { | |||
| 80 | Timer::after_millis(500).await; | 92 | Timer::after_millis(500).await; |
| 81 | 93 | ||
| 82 | y = -y; | 94 | y = -y; |
| 83 | let report = MouseReport { | 95 | |
| 84 | buttons: 0, | 96 | if HID_PROTOCOL_MODE.load(Ordering::Relaxed) == HidProtocolMode::Boot as u8 { |
| 85 | x: 0, | 97 | let buttons = 0u8; |
| 86 | y, | 98 | let x = 0i8; |
| 87 | wheel: 0, | 99 | match writer.write(&[buttons, x as u8, y as u8]).await { |
| 88 | pan: 0, | 100 | Ok(()) => {} |
| 89 | }; | 101 | Err(e) => warn!("Failed to send boot report: {:?}", e), |
| 90 | match writer.write_serialize(&report).await { | 102 | } |
| 91 | Ok(()) => {} | 103 | } else { |
| 92 | Err(e) => warn!("Failed to send report: {:?}", e), | 104 | let report = MouseReport { |
| 105 | buttons: 0, | ||
| 106 | x: 0, | ||
| 107 | y, | ||
| 108 | wheel: 0, | ||
| 109 | pan: 0, | ||
| 110 | }; | ||
| 111 | match writer.write_serialize(&report).await { | ||
| 112 | Ok(()) => {} | ||
| 113 | Err(e) => warn!("Failed to send report: {:?}", e), | ||
| 114 | } | ||
| 93 | } | 115 | } |
| 94 | } | 116 | } |
| 95 | }; | 117 | }; |
| @@ -112,6 +134,18 @@ impl RequestHandler for MyRequestHandler { | |||
| 112 | OutResponse::Accepted | 134 | OutResponse::Accepted |
| 113 | } | 135 | } |
| 114 | 136 | ||
| 137 | fn get_protocol(&self) -> HidProtocolMode { | ||
| 138 | let protocol = HidProtocolMode::from(HID_PROTOCOL_MODE.load(Ordering::Relaxed)); | ||
| 139 | info!("The current HID protocol mode is: {}", protocol); | ||
| 140 | protocol | ||
| 141 | } | ||
| 142 | |||
| 143 | fn set_protocol(&mut self, protocol: HidProtocolMode) -> OutResponse { | ||
| 144 | info!("Switching to HID protocol mode: {}", protocol); | ||
| 145 | HID_PROTOCOL_MODE.store(protocol as u8, Ordering::Relaxed); | ||
| 146 | OutResponse::Accepted | ||
| 147 | } | ||
| 148 | |||
| 115 | fn set_idle_ms(&mut self, id: Option<ReportId>, dur: u32) { | 149 | fn set_idle_ms(&mut self, id: Option<ReportId>, dur: u32) { |
| 116 | info!("Set idle rate for {:?} to {:?}", id, dur); | 150 | info!("Set idle rate for {:?} to {:?}", id, dur); |
| 117 | } | 151 | } |
diff --git a/examples/nrf5340/src/bin/gpiote_channel.rs b/examples/nrf5340/src/bin/gpiote_channel.rs index a085310ce..41ee732c3 100644 --- a/examples/nrf5340/src/bin/gpiote_channel.rs +++ b/examples/nrf5340/src/bin/gpiote_channel.rs | |||
| @@ -12,10 +12,10 @@ async fn main(_spawner: Spawner) { | |||
| 12 | let p = embassy_nrf::init(Default::default()); | 12 | let p = embassy_nrf::init(Default::default()); |
| 13 | info!("Starting!"); | 13 | info!("Starting!"); |
| 14 | 14 | ||
| 15 | let ch1 = InputChannel::new(p.GPIOTE_CH0, p.P0_23, Pull::Up, InputChannelPolarity::HiToLo); | 15 | let mut ch1 = InputChannel::new(p.GPIOTE_CH0, p.P0_23, Pull::Up, InputChannelPolarity::HiToLo); |
| 16 | let ch2 = InputChannel::new(p.GPIOTE_CH1, p.P0_24, Pull::Up, InputChannelPolarity::LoToHi); | 16 | let mut ch2 = InputChannel::new(p.GPIOTE_CH1, p.P0_24, Pull::Up, InputChannelPolarity::LoToHi); |
| 17 | let ch3 = InputChannel::new(p.GPIOTE_CH2, p.P0_08, Pull::Up, InputChannelPolarity::Toggle); | 17 | let mut ch3 = InputChannel::new(p.GPIOTE_CH2, p.P0_08, Pull::Up, InputChannelPolarity::Toggle); |
| 18 | let ch4 = InputChannel::new(p.GPIOTE_CH3, p.P0_09, Pull::Up, InputChannelPolarity::Toggle); | 18 | let mut ch4 = InputChannel::new(p.GPIOTE_CH3, p.P0_09, Pull::Up, InputChannelPolarity::Toggle); |
| 19 | 19 | ||
| 20 | let button1 = async { | 20 | let button1 = async { |
| 21 | loop { | 21 | loop { |
diff --git a/examples/nrf54l15/memory.x b/examples/nrf54l15/memory.x index 1064c8a5c..332200828 100644 --- a/examples/nrf54l15/memory.x +++ b/examples/nrf54l15/memory.x | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | MEMORY | 1 | MEMORY |
| 2 | { | 2 | { |
| 3 | FLASH : ORIGIN = 0x00000000, LENGTH = 1536K | 3 | FLASH : ORIGIN = 0x00000000, LENGTH = 1524K |
| 4 | RAM : ORIGIN = 0x20000000, LENGTH = 256K | 4 | RAM : ORIGIN = 0x20000000, LENGTH = 256K |
| 5 | } | 5 | } |
diff --git a/examples/nrf54l15/src/bin/gpiote_channel.rs b/examples/nrf54l15/src/bin/gpiote_channel.rs index 6333250ba..cac8823f8 100644 --- a/examples/nrf54l15/src/bin/gpiote_channel.rs +++ b/examples/nrf54l15/src/bin/gpiote_channel.rs | |||
| @@ -12,10 +12,10 @@ async fn main(_spawner: Spawner) { | |||
| 12 | let p = embassy_nrf::init(Default::default()); | 12 | let p = embassy_nrf::init(Default::default()); |
| 13 | info!("Starting!"); | 13 | info!("Starting!"); |
| 14 | 14 | ||
| 15 | let ch1 = InputChannel::new(p.GPIOTE20_CH0, p.P1_13, Pull::Up, InputChannelPolarity::HiToLo); | 15 | let mut ch1 = InputChannel::new(p.GPIOTE20_CH0, p.P1_13, Pull::Up, InputChannelPolarity::HiToLo); |
| 16 | let ch2 = InputChannel::new(p.GPIOTE20_CH1, p.P1_09, Pull::Up, InputChannelPolarity::LoToHi); | 16 | let mut ch2 = InputChannel::new(p.GPIOTE20_CH1, p.P1_09, Pull::Up, InputChannelPolarity::LoToHi); |
| 17 | let ch3 = InputChannel::new(p.GPIOTE20_CH2, p.P1_08, Pull::Up, InputChannelPolarity::Toggle); | 17 | let mut ch3 = InputChannel::new(p.GPIOTE20_CH2, p.P1_08, Pull::Up, InputChannelPolarity::Toggle); |
| 18 | let ch4 = InputChannel::new(p.GPIOTE30_CH0, p.P0_04, Pull::Up, InputChannelPolarity::Toggle); | 18 | let mut ch4 = InputChannel::new(p.GPIOTE30_CH0, p.P0_04, Pull::Up, InputChannelPolarity::Toggle); |
| 19 | 19 | ||
| 20 | let button1 = async { | 20 | let button1 = async { |
| 21 | loop { | 21 | loop { |
diff --git a/examples/rp/src/bin/usb_hid_keyboard.rs b/examples/rp/src/bin/usb_hid_keyboard.rs index a7cb322d8..2f6d169bf 100644 --- a/examples/rp/src/bin/usb_hid_keyboard.rs +++ b/examples/rp/src/bin/usb_hid_keyboard.rs | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | #![no_std] | 1 | #![no_std] |
| 2 | #![no_main] | 2 | #![no_main] |
| 3 | 3 | ||
| 4 | use core::sync::atomic::{AtomicBool, Ordering}; | 4 | use core::sync::atomic::{AtomicBool, AtomicU8, Ordering}; |
| 5 | 5 | ||
| 6 | use defmt::*; | 6 | use defmt::*; |
| 7 | use embassy_executor::Spawner; | 7 | use embassy_executor::Spawner; |
| @@ -10,7 +10,9 @@ use embassy_rp::bind_interrupts; | |||
| 10 | use embassy_rp::gpio::{Input, Pull}; | 10 | use embassy_rp::gpio::{Input, Pull}; |
| 11 | use embassy_rp::peripherals::USB; | 11 | use embassy_rp::peripherals::USB; |
| 12 | use embassy_rp::usb::{Driver, InterruptHandler}; | 12 | use embassy_rp::usb::{Driver, InterruptHandler}; |
| 13 | use embassy_usb::class::hid::{HidReaderWriter, ReportId, RequestHandler, State}; | 13 | use embassy_usb::class::hid::{ |
| 14 | HidBootProtocol, HidProtocolMode, HidReaderWriter, HidSubclass, ReportId, RequestHandler, State, | ||
| 15 | }; | ||
| 14 | use embassy_usb::control::OutResponse; | 16 | use embassy_usb::control::OutResponse; |
| 15 | use embassy_usb::{Builder, Config, Handler}; | 17 | use embassy_usb::{Builder, Config, Handler}; |
| 16 | use usbd_hid::descriptor::{KeyboardReport, SerializedDescriptor}; | 18 | use usbd_hid::descriptor::{KeyboardReport, SerializedDescriptor}; |
| @@ -20,6 +22,8 @@ bind_interrupts!(struct Irqs { | |||
| 20 | USBCTRL_IRQ => InterruptHandler<USB>; | 22 | USBCTRL_IRQ => InterruptHandler<USB>; |
| 21 | }); | 23 | }); |
| 22 | 24 | ||
| 25 | static HID_PROTOCOL_MODE: AtomicU8 = AtomicU8::new(HidProtocolMode::Boot as u8); | ||
| 26 | |||
| 23 | #[embassy_executor::main] | 27 | #[embassy_executor::main] |
| 24 | async fn main(_spawner: Spawner) { | 28 | async fn main(_spawner: Spawner) { |
| 25 | let p = embassy_rp::init(Default::default()); | 29 | let p = embassy_rp::init(Default::default()); |
| @@ -33,6 +37,10 @@ async fn main(_spawner: Spawner) { | |||
| 33 | config.serial_number = Some("12345678"); | 37 | config.serial_number = Some("12345678"); |
| 34 | config.max_power = 100; | 38 | config.max_power = 100; |
| 35 | config.max_packet_size_0 = 64; | 39 | config.max_packet_size_0 = 64; |
| 40 | config.composite_with_iads = false; | ||
| 41 | config.device_class = 0; | ||
| 42 | config.device_sub_class = 0; | ||
| 43 | config.device_protocol = 0; | ||
| 36 | 44 | ||
| 37 | // Create embassy-usb DeviceBuilder using the driver and config. | 45 | // Create embassy-usb DeviceBuilder using the driver and config. |
| 38 | // It needs some buffers for building the descriptors. | 46 | // It needs some buffers for building the descriptors. |
| @@ -63,6 +71,8 @@ async fn main(_spawner: Spawner) { | |||
| 63 | request_handler: None, | 71 | request_handler: None, |
| 64 | poll_ms: 60, | 72 | poll_ms: 60, |
| 65 | max_packet_size: 64, | 73 | max_packet_size: 64, |
| 74 | hid_subclass: HidSubclass::Boot, | ||
| 75 | hid_boot_protocol: HidBootProtocol::Keyboard, | ||
| 66 | }; | 76 | }; |
| 67 | let hid = HidReaderWriter::<_, 1, 8>::new(&mut builder, &mut state, config); | 77 | let hid = HidReaderWriter::<_, 1, 8>::new(&mut builder, &mut state, config); |
| 68 | 78 | ||
| @@ -86,30 +96,46 @@ async fn main(_spawner: Spawner) { | |||
| 86 | info!("Waiting for HIGH on pin 16"); | 96 | info!("Waiting for HIGH on pin 16"); |
| 87 | signal_pin.wait_for_high().await; | 97 | signal_pin.wait_for_high().await; |
| 88 | info!("HIGH DETECTED"); | 98 | info!("HIGH DETECTED"); |
| 89 | // Create a report with the A key pressed. (no shift modifier) | 99 | |
| 90 | let report = KeyboardReport { | 100 | if HID_PROTOCOL_MODE.load(Ordering::Relaxed) == HidProtocolMode::Boot as u8 { |
| 91 | keycodes: [4, 0, 0, 0, 0, 0], | 101 | match writer.write(&[0, 0, 4, 0, 0, 0, 0, 0]).await { |
| 92 | leds: 0, | 102 | Ok(()) => {} |
| 93 | modifier: 0, | 103 | Err(e) => warn!("Failed to send boot report: {:?}", e), |
| 94 | reserved: 0, | 104 | }; |
| 95 | }; | 105 | } else { |
| 96 | // Send the report. | 106 | // Create a report with the A key pressed. (no shift modifier) |
| 97 | match writer.write_serialize(&report).await { | 107 | let report = KeyboardReport { |
| 98 | Ok(()) => {} | 108 | keycodes: [4, 0, 0, 0, 0, 0], |
| 99 | Err(e) => warn!("Failed to send report: {:?}", e), | 109 | leds: 0, |
| 100 | }; | 110 | modifier: 0, |
| 111 | reserved: 0, | ||
| 112 | }; | ||
| 113 | // Send the report. | ||
| 114 | match writer.write_serialize(&report).await { | ||
| 115 | Ok(()) => {} | ||
| 116 | Err(e) => warn!("Failed to send report: {:?}", e), | ||
| 117 | }; | ||
| 118 | } | ||
| 119 | |||
| 101 | signal_pin.wait_for_low().await; | 120 | signal_pin.wait_for_low().await; |
| 102 | info!("LOW DETECTED"); | 121 | info!("LOW DETECTED"); |
| 103 | let report = KeyboardReport { | 122 | if HID_PROTOCOL_MODE.load(Ordering::Relaxed) == HidProtocolMode::Boot as u8 { |
| 104 | keycodes: [0, 0, 0, 0, 0, 0], | 123 | match writer.write(&[0, 0, 0, 0, 0, 0, 0, 0]).await { |
| 105 | leds: 0, | 124 | Ok(()) => {} |
| 106 | modifier: 0, | 125 | Err(e) => warn!("Failed to send boot report: {:?}", e), |
| 107 | reserved: 0, | 126 | }; |
| 108 | }; | 127 | } else { |
| 109 | match writer.write_serialize(&report).await { | 128 | let report = KeyboardReport { |
| 110 | Ok(()) => {} | 129 | keycodes: [0, 0, 0, 0, 0, 0], |
| 111 | Err(e) => warn!("Failed to send report: {:?}", e), | 130 | leds: 0, |
| 112 | }; | 131 | modifier: 0, |
| 132 | reserved: 0, | ||
| 133 | }; | ||
| 134 | match writer.write_serialize(&report).await { | ||
| 135 | Ok(()) => {} | ||
| 136 | Err(e) => warn!("Failed to send report: {:?}", e), | ||
| 137 | }; | ||
| 138 | } | ||
| 113 | } | 139 | } |
| 114 | }; | 140 | }; |
| 115 | 141 | ||
| @@ -135,6 +161,18 @@ impl RequestHandler for MyRequestHandler { | |||
| 135 | OutResponse::Accepted | 161 | OutResponse::Accepted |
| 136 | } | 162 | } |
| 137 | 163 | ||
| 164 | fn get_protocol(&self) -> HidProtocolMode { | ||
| 165 | let protocol = HidProtocolMode::from(HID_PROTOCOL_MODE.load(Ordering::Relaxed)); | ||
| 166 | info!("The current HID protocol mode is: {}", protocol); | ||
| 167 | protocol | ||
| 168 | } | ||
| 169 | |||
| 170 | fn set_protocol(&mut self, protocol: HidProtocolMode) -> OutResponse { | ||
| 171 | info!("Switching to HID protocol mode: {}", protocol); | ||
| 172 | HID_PROTOCOL_MODE.store(protocol as u8, Ordering::Relaxed); | ||
| 173 | OutResponse::Accepted | ||
| 174 | } | ||
| 175 | |||
| 138 | fn set_idle_ms(&mut self, id: Option<ReportId>, dur: u32) { | 176 | fn set_idle_ms(&mut self, id: Option<ReportId>, dur: u32) { |
| 139 | info!("Set idle rate for {:?} to {:?}", id, dur); | 177 | info!("Set idle rate for {:?} to {:?}", id, dur); |
| 140 | } | 178 | } |
diff --git a/examples/rp/src/bin/usb_hid_mouse.rs b/examples/rp/src/bin/usb_hid_mouse.rs index 4454c593c..dc331cbdd 100755 --- a/examples/rp/src/bin/usb_hid_mouse.rs +++ b/examples/rp/src/bin/usb_hid_mouse.rs | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | #![no_std] | 1 | #![no_std] |
| 2 | #![no_main] | 2 | #![no_main] |
| 3 | 3 | ||
| 4 | use core::sync::atomic::{AtomicBool, Ordering}; | 4 | use core::sync::atomic::{AtomicBool, AtomicU8, Ordering}; |
| 5 | 5 | ||
| 6 | use defmt::*; | 6 | use defmt::*; |
| 7 | use embassy_executor::Spawner; | 7 | use embassy_executor::Spawner; |
| @@ -11,7 +11,9 @@ use embassy_rp::clocks::RoscRng; | |||
| 11 | use embassy_rp::peripherals::USB; | 11 | use embassy_rp::peripherals::USB; |
| 12 | use embassy_rp::usb::{Driver, InterruptHandler}; | 12 | use embassy_rp::usb::{Driver, InterruptHandler}; |
| 13 | use embassy_time::Timer; | 13 | use embassy_time::Timer; |
| 14 | use embassy_usb::class::hid::{HidReaderWriter, ReportId, RequestHandler, State}; | 14 | use embassy_usb::class::hid::{ |
| 15 | HidBootProtocol, HidProtocolMode, HidReaderWriter, HidSubclass, ReportId, RequestHandler, State, | ||
| 16 | }; | ||
| 15 | use embassy_usb::control::OutResponse; | 17 | use embassy_usb::control::OutResponse; |
| 16 | use embassy_usb::{Builder, Config, Handler}; | 18 | use embassy_usb::{Builder, Config, Handler}; |
| 17 | use rand::Rng; | 19 | use rand::Rng; |
| @@ -22,6 +24,8 @@ bind_interrupts!(struct Irqs { | |||
| 22 | USBCTRL_IRQ => InterruptHandler<USB>; | 24 | USBCTRL_IRQ => InterruptHandler<USB>; |
| 23 | }); | 25 | }); |
| 24 | 26 | ||
| 27 | static HID_PROTOCOL_MODE: AtomicU8 = AtomicU8::new(HidProtocolMode::Boot as u8); | ||
| 28 | |||
| 25 | #[embassy_executor::main] | 29 | #[embassy_executor::main] |
| 26 | async fn main(_spawner: Spawner) { | 30 | async fn main(_spawner: Spawner) { |
| 27 | let p = embassy_rp::init(Default::default()); | 31 | let p = embassy_rp::init(Default::default()); |
| @@ -35,6 +39,10 @@ async fn main(_spawner: Spawner) { | |||
| 35 | config.serial_number = Some("12345678"); | 39 | config.serial_number = Some("12345678"); |
| 36 | config.max_power = 100; | 40 | config.max_power = 100; |
| 37 | config.max_packet_size_0 = 64; | 41 | config.max_packet_size_0 = 64; |
| 42 | config.composite_with_iads = false; | ||
| 43 | config.device_class = 0; | ||
| 44 | config.device_sub_class = 0; | ||
| 45 | config.device_protocol = 0; | ||
| 38 | 46 | ||
| 39 | // Create embassy-usb DeviceBuilder using the driver and config. | 47 | // Create embassy-usb DeviceBuilder using the driver and config. |
| 40 | // It needs some buffers for building the descriptors. | 48 | // It needs some buffers for building the descriptors. |
| @@ -65,6 +73,8 @@ async fn main(_spawner: Spawner) { | |||
| 65 | request_handler: None, | 73 | request_handler: None, |
| 66 | poll_ms: 60, | 74 | poll_ms: 60, |
| 67 | max_packet_size: 64, | 75 | max_packet_size: 64, |
| 76 | hid_subclass: HidSubclass::Boot, | ||
| 77 | hid_boot_protocol: HidBootProtocol::Mouse, | ||
| 68 | }; | 78 | }; |
| 69 | let hid = HidReaderWriter::<_, 1, 8>::new(&mut builder, &mut state, config); | 79 | let hid = HidReaderWriter::<_, 1, 8>::new(&mut builder, &mut state, config); |
| 70 | 80 | ||
| @@ -83,17 +93,29 @@ async fn main(_spawner: Spawner) { | |||
| 83 | loop { | 93 | loop { |
| 84 | // every 1 second | 94 | // every 1 second |
| 85 | _ = Timer::after_secs(1).await; | 95 | _ = Timer::after_secs(1).await; |
| 86 | let report = MouseReport { | 96 | |
| 87 | buttons: 0, | 97 | let x = rng.random_range(-100..100); // random small x movement |
| 88 | x: rng.random_range(-100..100), // random small x movement | 98 | let y = rng.random_range(-100..100); // random small y movement |
| 89 | y: rng.random_range(-100..100), // random small y movement | 99 | |
| 90 | wheel: 0, | 100 | if HID_PROTOCOL_MODE.load(Ordering::Relaxed) == HidProtocolMode::Boot as u8 { |
| 91 | pan: 0, | 101 | let buttons = 0u8; |
| 92 | }; | 102 | match writer.write(&[buttons, x as u8, y as u8]).await { |
| 93 | // Send the report. | 103 | Ok(()) => {} |
| 94 | match writer.write_serialize(&report).await { | 104 | Err(e) => warn!("Failed to send boot report: {:?}", e), |
| 95 | Ok(()) => {} | 105 | } |
| 96 | Err(e) => warn!("Failed to send report: {:?}", e), | 106 | } else { |
| 107 | let report = MouseReport { | ||
| 108 | buttons: 0, | ||
| 109 | x, | ||
| 110 | y, | ||
| 111 | wheel: 0, | ||
| 112 | pan: 0, | ||
| 113 | }; | ||
| 114 | // Send the report. | ||
| 115 | match writer.write_serialize(&report).await { | ||
| 116 | Ok(()) => {} | ||
| 117 | Err(e) => warn!("Failed to send report: {:?}", e), | ||
| 118 | } | ||
| 97 | } | 119 | } |
| 98 | } | 120 | } |
| 99 | }; | 121 | }; |
| @@ -120,6 +142,18 @@ impl RequestHandler for MyRequestHandler { | |||
| 120 | OutResponse::Accepted | 142 | OutResponse::Accepted |
| 121 | } | 143 | } |
| 122 | 144 | ||
| 145 | fn get_protocol(&self) -> HidProtocolMode { | ||
| 146 | let protocol = HidProtocolMode::from(HID_PROTOCOL_MODE.load(Ordering::Relaxed)); | ||
| 147 | info!("The current HID protocol mode is: {}", protocol); | ||
| 148 | protocol | ||
| 149 | } | ||
| 150 | |||
| 151 | fn set_protocol(&mut self, protocol: HidProtocolMode) -> OutResponse { | ||
| 152 | info!("Switching to HID protocol mode: {}", protocol); | ||
| 153 | HID_PROTOCOL_MODE.store(protocol as u8, Ordering::Relaxed); | ||
| 154 | OutResponse::Accepted | ||
| 155 | } | ||
| 156 | |||
| 123 | fn set_idle_ms(&mut self, id: Option<ReportId>, dur: u32) { | 157 | fn set_idle_ms(&mut self, id: Option<ReportId>, dur: u32) { |
| 124 | info!("Set idle rate for {:?} to {:?}", id, dur); | 158 | info!("Set idle rate for {:?} to {:?}", id, dur); |
| 125 | } | 159 | } |
diff --git a/examples/rp235x/src/bin/usb_hid_keyboard.rs b/examples/rp235x/src/bin/usb_hid_keyboard.rs index 6f496e23a..d8f64c470 100644 --- a/examples/rp235x/src/bin/usb_hid_keyboard.rs +++ b/examples/rp235x/src/bin/usb_hid_keyboard.rs | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | #![no_std] | 1 | #![no_std] |
| 2 | #![no_main] | 2 | #![no_main] |
| 3 | 3 | ||
| 4 | use core::sync::atomic::{AtomicBool, Ordering}; | 4 | use core::sync::atomic::{AtomicBool, AtomicU8, Ordering}; |
| 5 | 5 | ||
| 6 | use defmt::*; | 6 | use defmt::*; |
| 7 | use embassy_executor::Spawner; | 7 | use embassy_executor::Spawner; |
| @@ -10,7 +10,9 @@ use embassy_rp::bind_interrupts; | |||
| 10 | use embassy_rp::gpio::{Input, Pull}; | 10 | use embassy_rp::gpio::{Input, Pull}; |
| 11 | use embassy_rp::peripherals::USB; | 11 | use embassy_rp::peripherals::USB; |
| 12 | use embassy_rp::usb::{Driver as UsbDriver, InterruptHandler}; | 12 | use embassy_rp::usb::{Driver as UsbDriver, InterruptHandler}; |
| 13 | use embassy_usb::class::hid::{HidReaderWriter, ReportId, RequestHandler, State as HidState}; | 13 | use embassy_usb::class::hid::{ |
| 14 | HidBootProtocol, HidProtocolMode, HidReaderWriter, HidSubclass, ReportId, RequestHandler, State as HidState, | ||
| 15 | }; | ||
| 14 | use embassy_usb::control::OutResponse; | 16 | use embassy_usb::control::OutResponse; |
| 15 | use embassy_usb::{Builder, Config, Handler}; | 17 | use embassy_usb::{Builder, Config, Handler}; |
| 16 | use usbd_hid::descriptor::{KeyboardReport, SerializedDescriptor}; | 18 | use usbd_hid::descriptor::{KeyboardReport, SerializedDescriptor}; |
| @@ -20,6 +22,8 @@ bind_interrupts!(struct Irqs { | |||
| 20 | USBCTRL_IRQ => InterruptHandler<USB>; | 22 | USBCTRL_IRQ => InterruptHandler<USB>; |
| 21 | }); | 23 | }); |
| 22 | 24 | ||
| 25 | static HID_PROTOCOL_MODE: AtomicU8 = AtomicU8::new(HidProtocolMode::Boot as u8); | ||
| 26 | |||
| 23 | #[embassy_executor::main] | 27 | #[embassy_executor::main] |
| 24 | async fn main(_spawner: Spawner) { | 28 | async fn main(_spawner: Spawner) { |
| 25 | let p = embassy_rp::init(Default::default()); | 29 | let p = embassy_rp::init(Default::default()); |
| @@ -33,6 +37,10 @@ async fn main(_spawner: Spawner) { | |||
| 33 | config.serial_number = Some("12345678"); | 37 | config.serial_number = Some("12345678"); |
| 34 | config.max_power = 100; | 38 | config.max_power = 100; |
| 35 | config.max_packet_size_0 = 64; | 39 | config.max_packet_size_0 = 64; |
| 40 | config.composite_with_iads = false; | ||
| 41 | config.device_class = 0; | ||
| 42 | config.device_sub_class = 0; | ||
| 43 | config.device_protocol = 0; | ||
| 36 | 44 | ||
| 37 | // Create embassy-usb DeviceBuilder using the driver and config. | 45 | // Create embassy-usb DeviceBuilder using the driver and config. |
| 38 | // It needs some buffers for building the descriptors. | 46 | // It needs some buffers for building the descriptors. |
| @@ -63,6 +71,8 @@ async fn main(_spawner: Spawner) { | |||
| 63 | request_handler: None, | 71 | request_handler: None, |
| 64 | poll_ms: 60, | 72 | poll_ms: 60, |
| 65 | max_packet_size: 64, | 73 | max_packet_size: 64, |
| 74 | hid_subclass: HidSubclass::Boot, | ||
| 75 | hid_boot_protocol: HidBootProtocol::Keyboard, | ||
| 66 | }; | 76 | }; |
| 67 | let hid = HidReaderWriter::<_, 1, 8>::new(&mut builder, &mut state, config); | 77 | let hid = HidReaderWriter::<_, 1, 8>::new(&mut builder, &mut state, config); |
| 68 | 78 | ||
| @@ -86,30 +96,45 @@ async fn main(_spawner: Spawner) { | |||
| 86 | info!("Waiting for HIGH on pin 16"); | 96 | info!("Waiting for HIGH on pin 16"); |
| 87 | signal_pin.wait_for_high().await; | 97 | signal_pin.wait_for_high().await; |
| 88 | info!("HIGH DETECTED"); | 98 | info!("HIGH DETECTED"); |
| 89 | // Create a report with the A key pressed. (no shift modifier) | 99 | |
| 90 | let report = KeyboardReport { | 100 | if HID_PROTOCOL_MODE.load(Ordering::Relaxed) == HidProtocolMode::Boot as u8 { |
| 91 | keycodes: [4, 0, 0, 0, 0, 0], | 101 | match writer.write(&[0, 0, 4, 0, 0, 0, 0, 0]).await { |
| 92 | leds: 0, | 102 | Ok(()) => {} |
| 93 | modifier: 0, | 103 | Err(e) => warn!("Failed to send boot report: {:?}", e), |
| 94 | reserved: 0, | 104 | }; |
| 95 | }; | 105 | } else { |
| 96 | // Send the report. | 106 | // Create a report with the A key pressed. (no shift modifier) |
| 97 | match writer.write_serialize(&report).await { | 107 | let report = KeyboardReport { |
| 98 | Ok(()) => {} | 108 | keycodes: [4, 0, 0, 0, 0, 0], |
| 99 | Err(e) => warn!("Failed to send report: {:?}", e), | 109 | leds: 0, |
| 100 | }; | 110 | modifier: 0, |
| 111 | reserved: 0, | ||
| 112 | }; | ||
| 113 | // Send the report. | ||
| 114 | match writer.write_serialize(&report).await { | ||
| 115 | Ok(()) => {} | ||
| 116 | Err(e) => warn!("Failed to send report: {:?}", e), | ||
| 117 | }; | ||
| 118 | } | ||
| 101 | signal_pin.wait_for_low().await; | 119 | signal_pin.wait_for_low().await; |
| 102 | info!("LOW DETECTED"); | 120 | info!("LOW DETECTED"); |
| 103 | let report = KeyboardReport { | 121 | if HID_PROTOCOL_MODE.load(Ordering::Relaxed) == HidProtocolMode::Boot as u8 { |
| 104 | keycodes: [0, 0, 0, 0, 0, 0], | 122 | match writer.write(&[0, 0, 0, 0, 0, 0, 0, 0]).await { |
| 105 | leds: 0, | 123 | Ok(()) => {} |
| 106 | modifier: 0, | 124 | Err(e) => warn!("Failed to send boot report: {:?}", e), |
| 107 | reserved: 0, | 125 | }; |
| 108 | }; | 126 | } else { |
| 109 | match writer.write_serialize(&report).await { | 127 | let report = KeyboardReport { |
| 110 | Ok(()) => {} | 128 | keycodes: [0, 0, 0, 0, 0, 0], |
| 111 | Err(e) => warn!("Failed to send report: {:?}", e), | 129 | leds: 0, |
| 112 | }; | 130 | modifier: 0, |
| 131 | reserved: 0, | ||
| 132 | }; | ||
| 133 | match writer.write_serialize(&report).await { | ||
| 134 | Ok(()) => {} | ||
| 135 | Err(e) => warn!("Failed to send report: {:?}", e), | ||
| 136 | }; | ||
| 137 | } | ||
| 113 | } | 138 | } |
| 114 | }; | 139 | }; |
| 115 | 140 | ||
| @@ -135,6 +160,18 @@ impl RequestHandler for MyRequestHandler { | |||
| 135 | OutResponse::Accepted | 160 | OutResponse::Accepted |
| 136 | } | 161 | } |
| 137 | 162 | ||
| 163 | fn get_protocol(&self) -> HidProtocolMode { | ||
| 164 | let protocol = HidProtocolMode::from(HID_PROTOCOL_MODE.load(Ordering::Relaxed)); | ||
| 165 | info!("The current HID protocol mode is: {}", protocol); | ||
| 166 | protocol | ||
| 167 | } | ||
| 168 | |||
| 169 | fn set_protocol(&mut self, protocol: HidProtocolMode) -> OutResponse { | ||
| 170 | info!("Switching to HID protocol mode: {}", protocol); | ||
| 171 | HID_PROTOCOL_MODE.store(protocol as u8, Ordering::Relaxed); | ||
| 172 | OutResponse::Accepted | ||
| 173 | } | ||
| 174 | |||
| 138 | fn set_idle_ms(&mut self, id: Option<ReportId>, dur: u32) { | 175 | fn set_idle_ms(&mut self, id: Option<ReportId>, dur: u32) { |
| 139 | info!("Set idle rate for {:?} to {:?}", id, dur); | 176 | info!("Set idle rate for {:?} to {:?}", id, dur); |
| 140 | } | 177 | } |
diff --git a/examples/stm32c0/src/bin/adc.rs b/examples/stm32c0/src/bin/adc.rs index 1f54b0b18..ad597b63c 100644 --- a/examples/stm32c0/src/bin/adc.rs +++ b/examples/stm32c0/src/bin/adc.rs | |||
| @@ -3,7 +3,6 @@ | |||
| 3 | 3 | ||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_stm32::adc::vals::Scandir; | ||
| 7 | use embassy_stm32::adc::{Adc, AdcChannel, AnyAdcChannel, Resolution, SampleTime}; | 6 | use embassy_stm32::adc::{Adc, AdcChannel, AnyAdcChannel, Resolution, SampleTime}; |
| 8 | use embassy_stm32::peripherals::ADC1; | 7 | use embassy_stm32::peripherals::ADC1; |
| 9 | use embassy_time::Timer; | 8 | use embassy_time::Timer; |
| @@ -17,7 +16,7 @@ async fn main(_spawner: Spawner) { | |||
| 17 | info!("ADC STM32C0 example."); | 16 | info!("ADC STM32C0 example."); |
| 18 | 17 | ||
| 19 | // We need to set certain sample time to be able to read temp sensor. | 18 | // We need to set certain sample time to be able to read temp sensor. |
| 20 | let mut adc = Adc::new(p.ADC1, SampleTime::CYCLES12_5, Resolution::BITS12); | 19 | let mut adc = Adc::new(p.ADC1, Resolution::BITS12); |
| 21 | let mut temp = adc.enable_temperature().degrade_adc(); | 20 | let mut temp = adc.enable_temperature().degrade_adc(); |
| 22 | let mut vref = adc.enable_vrefint().degrade_adc(); | 21 | let mut vref = adc.enable_vrefint().degrade_adc(); |
| 23 | let mut pin0 = p.PA0.degrade_adc(); | 22 | let mut pin0 = p.PA0.degrade_adc(); |
| @@ -27,16 +26,20 @@ async fn main(_spawner: Spawner) { | |||
| 27 | 26 | ||
| 28 | loop { | 27 | loop { |
| 29 | info!("============================"); | 28 | info!("============================"); |
| 30 | let blocking_temp = adc.blocking_read(&mut temp); | 29 | let blocking_temp = adc.blocking_read(&mut temp, SampleTime::CYCLES12_5); |
| 31 | let blocking_vref = adc.blocking_read(&mut vref); | 30 | let blocking_vref = adc.blocking_read(&mut vref, SampleTime::CYCLES12_5); |
| 32 | let blocing_pin0 = adc.blocking_read(&mut pin0); | 31 | let blocing_pin0 = adc.blocking_read(&mut pin0, SampleTime::CYCLES12_5); |
| 33 | info!( | 32 | info!( |
| 34 | "Blocking ADC read: vref = {}, temp = {}, pin0 = {}.", | 33 | "Blocking ADC read: vref = {}, temp = {}, pin0 = {}.", |
| 35 | blocking_vref, blocking_temp, blocing_pin0 | 34 | blocking_vref, blocking_temp, blocing_pin0 |
| 36 | ); | 35 | ); |
| 37 | 36 | ||
| 38 | let channels_seqence: [&mut AnyAdcChannel<ADC1>; 3] = [&mut vref, &mut temp, &mut pin0]; | 37 | let channels_sequence: [(&mut AnyAdcChannel<ADC1>, SampleTime); 3] = [ |
| 39 | adc.read(dma.reborrow(), channels_seqence.into_iter(), &mut read_buffer) | 38 | (&mut vref, SampleTime::CYCLES12_5), |
| 39 | (&mut temp, SampleTime::CYCLES12_5), | ||
| 40 | (&mut pin0, SampleTime::CYCLES12_5), | ||
| 41 | ]; | ||
| 42 | adc.read(dma.reborrow(), channels_sequence.into_iter(), &mut read_buffer) | ||
| 40 | .await; | 43 | .await; |
| 41 | // Values are ordered according to hardware ADC channel number! | 44 | // Values are ordered according to hardware ADC channel number! |
| 42 | info!( | 45 | info!( |
| @@ -44,15 +47,6 @@ async fn main(_spawner: Spawner) { | |||
| 44 | read_buffer[0], read_buffer[1], read_buffer[2] | 47 | read_buffer[0], read_buffer[1], read_buffer[2] |
| 45 | ); | 48 | ); |
| 46 | 49 | ||
| 47 | let hw_channel_selection: u32 = | ||
| 48 | (1 << temp.get_hw_channel()) + (1 << vref.get_hw_channel()) + (1 << pin0.get_hw_channel()); | ||
| 49 | adc.read_in_hw_order(dma.reborrow(), hw_channel_selection, Scandir::UP, &mut read_buffer) | ||
| 50 | .await; | ||
| 51 | info!( | ||
| 52 | "DMA ADC read in hardware order: vref = {}, temp = {}, pin0 = {}.", | ||
| 53 | read_buffer[2], read_buffer[1], read_buffer[0] | ||
| 54 | ); | ||
| 55 | |||
| 56 | Timer::after_millis(2000).await; | 50 | Timer::after_millis(2000).await; |
| 57 | } | 51 | } |
| 58 | } | 52 | } |
diff --git a/examples/stm32f0/Cargo.toml b/examples/stm32f0/Cargo.toml index a78873d21..177dd0ac2 100644 --- a/examples/stm32f0/Cargo.toml +++ b/examples/stm32f0/Cargo.toml | |||
| @@ -16,6 +16,7 @@ panic-probe = { version = "1.0.0", features = ["print-defmt"] } | |||
| 16 | embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } | 16 | embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } |
| 17 | embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } | 17 | embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } |
| 18 | embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } | 18 | embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } |
| 19 | embedded-hal-1 = { package = "embedded-hal", version = "1.0" } | ||
| 19 | static_cell = "2" | 20 | static_cell = "2" |
| 20 | portable-atomic = { version = "1.5", features = ["unsafe-assume-single-core"] } | 21 | portable-atomic = { version = "1.5", features = ["unsafe-assume-single-core"] } |
| 21 | 22 | ||
diff --git a/examples/stm32f0/src/bin/adc-watchdog.rs b/examples/stm32f0/src/bin/adc-watchdog.rs index ff98aac8e..6879dd10a 100644 --- a/examples/stm32f0/src/bin/adc-watchdog.rs +++ b/examples/stm32f0/src/bin/adc-watchdog.rs | |||
| @@ -3,7 +3,7 @@ | |||
| 3 | 3 | ||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_stm32::adc::{self, Adc, WatchdogChannels}; | 6 | use embassy_stm32::adc::{self, Adc, SampleTime, WatchdogChannels}; |
| 7 | use embassy_stm32::bind_interrupts; | 7 | use embassy_stm32::bind_interrupts; |
| 8 | use embassy_stm32::peripherals::ADC1; | 8 | use embassy_stm32::peripherals::ADC1; |
| 9 | use {defmt_rtt as _, panic_probe as _}; | 9 | use {defmt_rtt as _, panic_probe as _}; |
| @@ -23,12 +23,12 @@ async fn main(_spawner: Spawner) { | |||
| 23 | loop { | 23 | loop { |
| 24 | // Wait for pin to go high | 24 | // Wait for pin to go high |
| 25 | adc.init_watchdog(WatchdogChannels::from_channel(&pin), 0, 0x07F); | 25 | adc.init_watchdog(WatchdogChannels::from_channel(&pin), 0, 0x07F); |
| 26 | let v_high = adc.monitor_watchdog().await; | 26 | let v_high = adc.monitor_watchdog(SampleTime::CYCLES13_5).await; |
| 27 | info!("ADC sample is high {}", v_high); | 27 | info!("ADC sample is high {}", v_high); |
| 28 | 28 | ||
| 29 | // Wait for pin to go low | 29 | // Wait for pin to go low |
| 30 | adc.init_watchdog(WatchdogChannels::from_channel(&pin), 0x01f, 0xFFF); | 30 | adc.init_watchdog(WatchdogChannels::from_channel(&pin), 0x01f, 0xFFF); |
| 31 | let v_low = adc.monitor_watchdog().await; | 31 | let v_low = adc.monitor_watchdog(SampleTime::CYCLES13_5).await; |
| 32 | info!("ADC sample is low {}", v_low); | 32 | info!("ADC sample is low {}", v_low); |
| 33 | } | 33 | } |
| 34 | } | 34 | } |
diff --git a/examples/stm32f0/src/bin/adc.rs b/examples/stm32f0/src/bin/adc.rs index 8825e2687..fafeeffaf 100644 --- a/examples/stm32f0/src/bin/adc.rs +++ b/examples/stm32f0/src/bin/adc.rs | |||
| @@ -19,11 +19,10 @@ async fn main(_spawner: Spawner) { | |||
| 19 | info!("Hello World!"); | 19 | info!("Hello World!"); |
| 20 | 20 | ||
| 21 | let mut adc = Adc::new(p.ADC1, Irqs); | 21 | let mut adc = Adc::new(p.ADC1, Irqs); |
| 22 | adc.set_sample_time(SampleTime::CYCLES71_5); | ||
| 23 | let mut pin = p.PA1; | 22 | let mut pin = p.PA1; |
| 24 | 23 | ||
| 25 | let mut vrefint = adc.enable_vref(); | 24 | let mut vrefint = adc.enable_vref(); |
| 26 | let vrefint_sample = adc.read(&mut vrefint).await; | 25 | let vrefint_sample = adc.read(&mut vrefint, SampleTime::CYCLES13_5).await; |
| 27 | let convert_to_millivolts = |sample| { | 26 | let convert_to_millivolts = |sample| { |
| 28 | // From https://www.st.com/resource/en/datasheet/stm32f031c6.pdf | 27 | // From https://www.st.com/resource/en/datasheet/stm32f031c6.pdf |
| 29 | // 6.3.4 Embedded reference voltage | 28 | // 6.3.4 Embedded reference voltage |
| @@ -33,7 +32,7 @@ async fn main(_spawner: Spawner) { | |||
| 33 | }; | 32 | }; |
| 34 | 33 | ||
| 35 | loop { | 34 | loop { |
| 36 | let v = adc.read(&mut pin).await; | 35 | let v = adc.read(&mut pin, SampleTime::CYCLES13_5).await; |
| 37 | info!("--> {} - {} mV", v, convert_to_millivolts(v)); | 36 | info!("--> {} - {} mV", v, convert_to_millivolts(v)); |
| 38 | Timer::after_millis(100).await; | 37 | Timer::after_millis(100).await; |
| 39 | } | 38 | } |
diff --git a/examples/stm32f0/src/bin/i2c_master.rs b/examples/stm32f0/src/bin/i2c_master.rs new file mode 100644 index 000000000..2e61ecdf7 --- /dev/null +++ b/examples/stm32f0/src/bin/i2c_master.rs | |||
| @@ -0,0 +1,609 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | // Hardware Setup for NUCLEO-F072RB: | ||
| 5 | // - I2C1 pins: PB8 (SCL), PB9 (SDA) on CN5 connector | ||
| 6 | // - Connect to I2C slave device (e.g., Digilent Analog Discovery I2C slave, or EEPROM) | ||
| 7 | // - Default slave address: 0x50 | ||
| 8 | // - Pull-up resistors: 4.7kΩ on both SCL and SDA | ||
| 9 | // - CN5 Pin 10 (PB8/SCL) and CN5 Pin 9 (PB9/SDA) | ||
| 10 | // | ||
| 11 | // Analog Discovery - Waveforms Setup: | ||
| 12 | // - Increase buffer size: Settings -> Device Manager -> Option 4 | ||
| 13 | // - Run Protocol Analyzer | ||
| 14 | // - Configure as I2C Slave at address 0x50 | ||
| 15 | // - Connect and configure DIO pins for SCL and SDA | ||
| 16 | // - Frequency: 100kHz - [✓] Clock Stretching | ||
| 17 | |||
| 18 | use defmt::*; | ||
| 19 | use embassy_executor::Spawner; | ||
| 20 | use embassy_stm32::i2c::{Config, I2c, Master}; | ||
| 21 | use embassy_stm32::mode::{Async, Blocking}; | ||
| 22 | use embassy_stm32::time::Hertz; | ||
| 23 | use embassy_stm32::{bind_interrupts, i2c, peripherals}; | ||
| 24 | use embassy_time::Timer; | ||
| 25 | use embedded_hal_1::i2c::Operation; | ||
| 26 | use {defmt_rtt as _, panic_probe as _}; | ||
| 27 | |||
| 28 | bind_interrupts!(struct Irqs { | ||
| 29 | I2C1 => i2c::EventInterruptHandler<peripherals::I2C1>, i2c::ErrorInterruptHandler<peripherals::I2C1>; | ||
| 30 | }); | ||
| 31 | |||
| 32 | #[embassy_executor::main] | ||
| 33 | async fn main(_spawner: Spawner) { | ||
| 34 | let p = embassy_stm32::init(Default::default()); | ||
| 35 | info!("Run stm32 I2C v2 Master Tests..."); | ||
| 36 | |||
| 37 | let mut i2c_peri = p.I2C1; | ||
| 38 | let mut scl = p.PB8; | ||
| 39 | let mut sda = p.PB9; | ||
| 40 | |||
| 41 | let mut config = Config::default(); | ||
| 42 | config.frequency = Hertz(100_000); | ||
| 43 | |||
| 44 | // I2C slave address for Analog Discovery or test EEPROM | ||
| 45 | let slave_addr = 0x50u8; | ||
| 46 | |||
| 47 | // Wait for slave device to be ready | ||
| 48 | Timer::after_millis(100).await; | ||
| 49 | |||
| 50 | // ========== BLOCKING DIRECT API TESTS ========== | ||
| 51 | info!("========== BLOCKING DIRECT API TESTS =========="); | ||
| 52 | { | ||
| 53 | let mut i2c = I2c::new_blocking(i2c_peri.reborrow(), scl.reborrow(), sda.reborrow(), config); | ||
| 54 | |||
| 55 | info!("=== Test 1: Direct blocking_write ==="); | ||
| 56 | test_blocking_write(&mut i2c, slave_addr); | ||
| 57 | |||
| 58 | info!("=== Test 2: Direct blocking_read ==="); | ||
| 59 | test_blocking_read(&mut i2c, slave_addr); | ||
| 60 | |||
| 61 | info!("=== Test 3: Direct blocking_write_read ==="); | ||
| 62 | test_blocking_write_read(&mut i2c, slave_addr); | ||
| 63 | |||
| 64 | info!("=== Test 4: Direct blocking_write_vectored ==="); | ||
| 65 | test_blocking_write_vectored(&mut i2c, slave_addr); | ||
| 66 | |||
| 67 | info!("=== Test 5: Large buffer (>255 bytes) ==="); | ||
| 68 | test_blocking_large_buffer(&mut i2c, slave_addr); | ||
| 69 | |||
| 70 | info!("Blocking direct API tests OK"); | ||
| 71 | } | ||
| 72 | |||
| 73 | Timer::after_millis(100).await; | ||
| 74 | |||
| 75 | // ========== BLOCKING TRANSACTION TESTS ========== | ||
| 76 | info!("========== BLOCKING TRANSACTION TESTS =========="); | ||
| 77 | { | ||
| 78 | let mut i2c = I2c::new_blocking(i2c_peri.reborrow(), scl.reborrow(), sda.reborrow(), config); | ||
| 79 | |||
| 80 | info!("=== Test 6: Consecutive Writes (Should Merge) ==="); | ||
| 81 | test_consecutive_writes_blocking(&mut i2c, slave_addr); | ||
| 82 | |||
| 83 | info!("=== Test 7: Consecutive Reads (Should Merge) ==="); | ||
| 84 | test_consecutive_reads_blocking(&mut i2c, slave_addr); | ||
| 85 | |||
| 86 | info!("=== Test 8: Write then Read (RESTART) ==="); | ||
| 87 | test_write_then_read_blocking(&mut i2c, slave_addr); | ||
| 88 | |||
| 89 | info!("=== Test 9: Read then Write (RESTART) ==="); | ||
| 90 | test_read_then_write_blocking(&mut i2c, slave_addr); | ||
| 91 | |||
| 92 | info!("=== Test 10: Complex Mixed Sequence ==="); | ||
| 93 | test_mixed_sequence_blocking(&mut i2c, slave_addr); | ||
| 94 | |||
| 95 | info!("=== Test 11: Single Operations ==="); | ||
| 96 | test_single_operations_blocking(&mut i2c, slave_addr); | ||
| 97 | |||
| 98 | info!("Blocking transaction tests OK"); | ||
| 99 | } | ||
| 100 | |||
| 101 | Timer::after_millis(100).await; | ||
| 102 | |||
| 103 | // ========== ASYNC TESTS (DMA) ========== | ||
| 104 | info!("========== ASYNC TESTS (DMA) =========="); | ||
| 105 | { | ||
| 106 | let tx_dma = p.DMA1_CH2; | ||
| 107 | let rx_dma = p.DMA1_CH3; | ||
| 108 | |||
| 109 | let mut i2c = I2c::new(i2c_peri, scl, sda, Irqs, tx_dma, rx_dma, config); | ||
| 110 | |||
| 111 | // Direct API tests (reusing same I2C instance) | ||
| 112 | info!("=== Direct API Test 1: write() ==="); | ||
| 113 | test_async_write(&mut i2c, slave_addr).await; | ||
| 114 | |||
| 115 | info!("=== Direct API Test 2: read() ==="); | ||
| 116 | test_async_read(&mut i2c, slave_addr).await; | ||
| 117 | |||
| 118 | info!("=== Direct API Test 3: write_read() ==="); | ||
| 119 | test_async_write_read(&mut i2c, slave_addr).await; | ||
| 120 | |||
| 121 | info!("=== Direct API Test 4: write_vectored() ==="); | ||
| 122 | test_async_write_vectored(&mut i2c, slave_addr).await; | ||
| 123 | |||
| 124 | info!("=== Direct API Test 5: Large buffer (>255 bytes) ==="); | ||
| 125 | test_async_large_buffer(&mut i2c, slave_addr).await; | ||
| 126 | |||
| 127 | info!("Async Direct API tests OK"); | ||
| 128 | |||
| 129 | // Transaction tests | ||
| 130 | info!("=== Transaction Test 6: Consecutive Writes (Should Merge) ==="); | ||
| 131 | test_consecutive_writes_async(&mut i2c, slave_addr).await; | ||
| 132 | |||
| 133 | info!("=== Transaction Test 7: Consecutive Reads (Should Merge) ==="); | ||
| 134 | test_consecutive_reads_async(&mut i2c, slave_addr).await; | ||
| 135 | |||
| 136 | info!("=== Transaction Test 8: Write then Read (RESTART) ==="); | ||
| 137 | test_write_then_read_async(&mut i2c, slave_addr).await; | ||
| 138 | |||
| 139 | info!("=== Transaction Test 9: Read then Write (RESTART) ==="); | ||
| 140 | test_read_then_write_async(&mut i2c, slave_addr).await; | ||
| 141 | |||
| 142 | info!("=== Transaction Test 10: Complex Mixed Sequence ==="); | ||
| 143 | test_mixed_sequence_async(&mut i2c, slave_addr).await; | ||
| 144 | |||
| 145 | info!("=== Transaction Test 11: Single Operations ==="); | ||
| 146 | test_single_operations_async(&mut i2c, slave_addr).await; | ||
| 147 | |||
| 148 | info!("Async transaction tests OK"); | ||
| 149 | } | ||
| 150 | |||
| 151 | info!("All tests OK"); | ||
| 152 | cortex_m::asm::bkpt(); | ||
| 153 | } | ||
| 154 | |||
| 155 | // ==================== BLOCKING DIRECT API TEST FUNCTIONS ==================== | ||
| 156 | |||
| 157 | fn test_blocking_write(i2c: &mut I2c<'_, Blocking, Master>, addr: u8) { | ||
| 158 | let write_data = [0x42, 0x43, 0x44, 0x45]; | ||
| 159 | |||
| 160 | match i2c.blocking_write(addr, &write_data) { | ||
| 161 | Ok(_) => info!("✓ blocking_write succeeded: {:02x}", write_data), | ||
| 162 | Err(e) => { | ||
| 163 | error!("✗ blocking_write failed: {:?}", e); | ||
| 164 | defmt::panic!("Test failed: blocking_write"); | ||
| 165 | } | ||
| 166 | } | ||
| 167 | } | ||
| 168 | |||
| 169 | fn test_blocking_read(i2c: &mut I2c<'_, Blocking, Master>, addr: u8) { | ||
| 170 | let mut read_buf = [0u8; 8]; | ||
| 171 | |||
| 172 | match i2c.blocking_read(addr, &mut read_buf) { | ||
| 173 | Ok(_) => info!("✓ blocking_read succeeded: {:02x}", read_buf), | ||
| 174 | Err(e) => { | ||
| 175 | error!("✗ blocking_read failed: {:?}", e); | ||
| 176 | defmt::panic!("Test failed: blocking_read"); | ||
| 177 | } | ||
| 178 | } | ||
| 179 | } | ||
| 180 | |||
| 181 | fn test_blocking_write_read(i2c: &mut I2c<'_, Blocking, Master>, addr: u8) { | ||
| 182 | let write_data = [0x50, 0x51]; | ||
| 183 | let mut read_buf = [0u8; 6]; | ||
| 184 | |||
| 185 | match i2c.blocking_write_read(addr, &write_data, &mut read_buf) { | ||
| 186 | Ok(_) => { | ||
| 187 | info!("✓ blocking_write_read succeeded"); | ||
| 188 | info!(" Written: {:02x}", write_data); | ||
| 189 | info!(" Read: {:02x}", read_buf); | ||
| 190 | } | ||
| 191 | Err(e) => { | ||
| 192 | error!("✗ blocking_write_read failed: {:?}", e); | ||
| 193 | defmt::panic!("Test failed: blocking_write_read"); | ||
| 194 | } | ||
| 195 | } | ||
| 196 | } | ||
| 197 | |||
| 198 | fn test_blocking_write_vectored(i2c: &mut I2c<'_, Blocking, Master>, addr: u8) { | ||
| 199 | let buf1 = [0x60, 0x61, 0x62]; | ||
| 200 | let buf2 = [0x70, 0x71]; | ||
| 201 | let buf3 = [0x80, 0x81, 0x82, 0x83]; | ||
| 202 | let bufs = [&buf1[..], &buf2[..], &buf3[..]]; | ||
| 203 | |||
| 204 | match i2c.blocking_write_vectored(addr, &bufs) { | ||
| 205 | Ok(_) => info!("✓ blocking_write_vectored succeeded (9 bytes total)"), | ||
| 206 | Err(e) => { | ||
| 207 | error!("✗ blocking_write_vectored failed: {:?}", e); | ||
| 208 | defmt::panic!("Test failed: blocking_write_vectored"); | ||
| 209 | } | ||
| 210 | } | ||
| 211 | } | ||
| 212 | |||
| 213 | fn test_blocking_large_buffer(i2c: &mut I2c<'_, Blocking, Master>, addr: u8) { | ||
| 214 | // Test with 300 bytes to verify RELOAD mechanism works (needs chunking at 255 bytes) | ||
| 215 | let mut write_buf = [0u8; 300]; | ||
| 216 | for (i, byte) in write_buf.iter_mut().enumerate() { | ||
| 217 | *byte = (i & 0xFF) as u8; | ||
| 218 | } | ||
| 219 | |||
| 220 | match i2c.blocking_write(addr, &write_buf) { | ||
| 221 | Ok(_) => info!("✓ Large buffer write succeeded (300 bytes, tests RELOAD)"), | ||
| 222 | Err(e) => { | ||
| 223 | error!("✗ Large buffer write failed: {:?}", e); | ||
| 224 | defmt::panic!("Test failed: large buffer write"); | ||
| 225 | } | ||
| 226 | } | ||
| 227 | |||
| 228 | // Test large read | ||
| 229 | let mut read_buf = [0u8; 300]; | ||
| 230 | match i2c.blocking_read(addr, &mut read_buf) { | ||
| 231 | Ok(_) => info!("✓ Large buffer read succeeded (300 bytes, tests RELOAD)"), | ||
| 232 | Err(e) => { | ||
| 233 | error!("✗ Large buffer read failed: {:?}", e); | ||
| 234 | defmt::panic!("Test failed: large buffer read"); | ||
| 235 | } | ||
| 236 | } | ||
| 237 | } | ||
| 238 | |||
| 239 | // ==================== BLOCKING TRANSACTION TEST FUNCTIONS ==================== | ||
| 240 | |||
| 241 | fn test_consecutive_writes_blocking(i2c: &mut I2c<'_, Blocking, Master>, addr: u8) { | ||
| 242 | // Expected on bus: START, ADDR+W, data1, data2, data3, STOP | ||
| 243 | // NO intermediate RESTART/STOP between writes - they should be merged | ||
| 244 | let data1 = [0x10, 0x11, 0x12]; | ||
| 245 | let data2 = [0x20, 0x21]; | ||
| 246 | let data3 = [0x30, 0x31, 0x32, 0x33]; | ||
| 247 | |||
| 248 | let mut ops = [ | ||
| 249 | Operation::Write(&data1), | ||
| 250 | Operation::Write(&data2), | ||
| 251 | Operation::Write(&data3), | ||
| 252 | ]; | ||
| 253 | |||
| 254 | match i2c.blocking_transaction(addr, &mut ops) { | ||
| 255 | Ok(_) => info!("✓ Consecutive writes succeeded (merged 9 bytes)"), | ||
| 256 | Err(e) => { | ||
| 257 | error!("✗ Consecutive writes failed: {:?}", e); | ||
| 258 | defmt::panic!("Test failed: consecutive writes"); | ||
| 259 | } | ||
| 260 | } | ||
| 261 | } | ||
| 262 | |||
| 263 | fn test_consecutive_reads_blocking(i2c: &mut I2c<'_, Blocking, Master>, addr: u8) { | ||
| 264 | // Expected on bus: START, ADDR+R, data1, data2, data3, NACK, STOP | ||
| 265 | // NO intermediate RESTART/STOP between reads - they should be merged | ||
| 266 | let mut buf1 = [0u8; 4]; | ||
| 267 | let mut buf2 = [0u8; 3]; | ||
| 268 | let mut buf3 = [0u8; 2]; | ||
| 269 | |||
| 270 | let mut ops = [ | ||
| 271 | Operation::Read(&mut buf1), | ||
| 272 | Operation::Read(&mut buf2), | ||
| 273 | Operation::Read(&mut buf3), | ||
| 274 | ]; | ||
| 275 | |||
| 276 | match i2c.blocking_transaction(addr, &mut ops) { | ||
| 277 | Ok(_) => { | ||
| 278 | info!("✓ Consecutive reads succeeded (merged 9 bytes)"); | ||
| 279 | info!(" buf1: {:02x}", buf1); | ||
| 280 | info!(" buf2: {:02x}", buf2); | ||
| 281 | info!(" buf3: {:02x}", buf3); | ||
| 282 | } | ||
| 283 | Err(e) => { | ||
| 284 | error!("✗ Consecutive reads failed: {:?}", e); | ||
| 285 | defmt::panic!("Test failed: consecutive reads"); | ||
| 286 | } | ||
| 287 | } | ||
| 288 | } | ||
| 289 | |||
| 290 | fn test_write_then_read_blocking(i2c: &mut I2c<'_, Blocking, Master>, addr: u8) { | ||
| 291 | // Expected: START, ADDR+W, data, RESTART, ADDR+R, data, NACK, STOP | ||
| 292 | let write_data = [0xAA, 0xBB]; | ||
| 293 | let mut read_buf = [0u8; 4]; | ||
| 294 | |||
| 295 | let mut ops = [Operation::Write(&write_data), Operation::Read(&mut read_buf)]; | ||
| 296 | |||
| 297 | match i2c.blocking_transaction(addr, &mut ops) { | ||
| 298 | Ok(_) => { | ||
| 299 | info!("✓ Write-then-read succeeded with RESTART"); | ||
| 300 | info!(" Written: {:02x}", write_data); | ||
| 301 | info!(" Read: {:02x}", read_buf); | ||
| 302 | } | ||
| 303 | Err(e) => { | ||
| 304 | error!("✗ Write-then-read failed: {:?}", e); | ||
| 305 | defmt::panic!("Test failed: write-then-read"); | ||
| 306 | } | ||
| 307 | } | ||
| 308 | } | ||
| 309 | |||
| 310 | fn test_read_then_write_blocking(i2c: &mut I2c<'_, Blocking, Master>, addr: u8) { | ||
| 311 | // Expected: START, ADDR+R, data, NACK, RESTART, ADDR+W, data, STOP | ||
| 312 | let mut read_buf = [0u8; 3]; | ||
| 313 | let write_data = [0xCC, 0xDD, 0xEE]; | ||
| 314 | |||
| 315 | let mut ops = [Operation::Read(&mut read_buf), Operation::Write(&write_data)]; | ||
| 316 | |||
| 317 | match i2c.blocking_transaction(addr, &mut ops) { | ||
| 318 | Ok(_) => { | ||
| 319 | info!("✓ Read-then-write succeeded with RESTART"); | ||
| 320 | info!(" Read: {:02x}", read_buf); | ||
| 321 | info!(" Written: {:02x}", write_data); | ||
| 322 | } | ||
| 323 | Err(e) => { | ||
| 324 | error!("✗ Read-then-write failed: {:?}", e); | ||
| 325 | defmt::panic!("Test failed: read-then-write"); | ||
| 326 | } | ||
| 327 | } | ||
| 328 | } | ||
| 329 | |||
| 330 | fn test_mixed_sequence_blocking(i2c: &mut I2c<'_, Blocking, Master>, addr: u8) { | ||
| 331 | // Complex: W, W, R, R, W, R | ||
| 332 | // Groups: [W,W] RESTART [R,R] RESTART [W] RESTART [R] | ||
| 333 | let w1 = [0x01, 0x02]; | ||
| 334 | let w2 = [0x03, 0x04]; | ||
| 335 | let mut r1 = [0u8; 2]; | ||
| 336 | let mut r2 = [0u8; 2]; | ||
| 337 | let w3 = [0x05]; | ||
| 338 | let mut r3 = [0u8; 1]; | ||
| 339 | |||
| 340 | let mut ops = [ | ||
| 341 | Operation::Write(&w1), | ||
| 342 | Operation::Write(&w2), | ||
| 343 | Operation::Read(&mut r1), | ||
| 344 | Operation::Read(&mut r2), | ||
| 345 | Operation::Write(&w3), | ||
| 346 | Operation::Read(&mut r3), | ||
| 347 | ]; | ||
| 348 | |||
| 349 | match i2c.blocking_transaction(addr, &mut ops) { | ||
| 350 | Ok(_) => { | ||
| 351 | info!("✓ Mixed sequence succeeded"); | ||
| 352 | info!(" Groups: [W4] RESTART [R4] RESTART [W1] RESTART [R1]"); | ||
| 353 | } | ||
| 354 | Err(e) => { | ||
| 355 | error!("✗ Mixed sequence failed: {:?}", e); | ||
| 356 | defmt::panic!("Test failed: mixed sequence"); | ||
| 357 | } | ||
| 358 | } | ||
| 359 | } | ||
| 360 | |||
| 361 | fn test_single_operations_blocking(i2c: &mut I2c<'_, Blocking, Master>, addr: u8) { | ||
| 362 | // Test single write | ||
| 363 | let write_data = [0xFF]; | ||
| 364 | let mut ops = [Operation::Write(&write_data)]; | ||
| 365 | |||
| 366 | match i2c.blocking_transaction(addr, &mut ops) { | ||
| 367 | Ok(_) => info!("✓ Single write succeeded"), | ||
| 368 | Err(e) => { | ||
| 369 | error!("✗ Single write failed: {:?}", e); | ||
| 370 | defmt::panic!("Test failed: single write"); | ||
| 371 | } | ||
| 372 | } | ||
| 373 | |||
| 374 | // Test single read | ||
| 375 | let mut read_buf = [0u8; 1]; | ||
| 376 | let mut ops = [Operation::Read(&mut read_buf)]; | ||
| 377 | |||
| 378 | match i2c.blocking_transaction(addr, &mut ops) { | ||
| 379 | Ok(_) => info!("✓ Single read succeeded, data: 0x{:02x}", read_buf[0]), | ||
| 380 | Err(e) => { | ||
| 381 | error!("✗ Single read failed: {:?}", e); | ||
| 382 | defmt::panic!("Test failed: single read"); | ||
| 383 | } | ||
| 384 | } | ||
| 385 | } | ||
| 386 | |||
| 387 | // ==================== ASYNC DIRECT API TEST FUNCTIONS ==================== | ||
| 388 | |||
| 389 | async fn test_async_write(i2c: &mut I2c<'_, Async, Master>, addr: u8) { | ||
| 390 | let write_data = [0x42, 0x43, 0x44, 0x45]; | ||
| 391 | |||
| 392 | match i2c.write(addr, &write_data).await { | ||
| 393 | Ok(_) => info!("✓ async write succeeded: {:02x}", write_data), | ||
| 394 | Err(e) => { | ||
| 395 | error!("✗ async write failed: {:?}", e); | ||
| 396 | defmt::panic!("Test failed: async write"); | ||
| 397 | } | ||
| 398 | } | ||
| 399 | } | ||
| 400 | |||
| 401 | async fn test_async_read(i2c: &mut I2c<'_, Async, Master>, addr: u8) { | ||
| 402 | let mut read_buf = [0u8; 8]; | ||
| 403 | |||
| 404 | match i2c.read(addr, &mut read_buf).await { | ||
| 405 | Ok(_) => info!("✓ async read succeeded: {:02x}", read_buf), | ||
| 406 | Err(e) => { | ||
| 407 | error!("✗ async read failed: {:?}", e); | ||
| 408 | defmt::panic!("Test failed: async read"); | ||
| 409 | } | ||
| 410 | } | ||
| 411 | } | ||
| 412 | |||
| 413 | async fn test_async_write_read(i2c: &mut I2c<'_, Async, Master>, addr: u8) { | ||
| 414 | let write_data = [0x50, 0x51]; | ||
| 415 | let mut read_buf = [0u8; 6]; | ||
| 416 | |||
| 417 | match i2c.write_read(addr, &write_data, &mut read_buf).await { | ||
| 418 | Ok(_) => { | ||
| 419 | info!("✓ async write_read succeeded"); | ||
| 420 | info!(" Written: {:02x}", write_data); | ||
| 421 | info!(" Read: {:02x}", read_buf); | ||
| 422 | } | ||
| 423 | Err(e) => { | ||
| 424 | error!("✗ async write_read failed: {:?}", e); | ||
| 425 | defmt::panic!("Test failed: async write_read"); | ||
| 426 | } | ||
| 427 | } | ||
| 428 | } | ||
| 429 | |||
| 430 | async fn test_async_write_vectored(i2c: &mut I2c<'_, Async, Master>, addr: u8) { | ||
| 431 | let buf1 = [0x60, 0x61, 0x62]; | ||
| 432 | let buf2 = [0x70, 0x71]; | ||
| 433 | let buf3 = [0x80, 0x81, 0x82, 0x83]; | ||
| 434 | let bufs = [&buf1[..], &buf2[..], &buf3[..]]; | ||
| 435 | |||
| 436 | match i2c.write_vectored(addr.into(), &bufs).await { | ||
| 437 | Ok(_) => info!("✓ async write_vectored succeeded (9 bytes total)"), | ||
| 438 | Err(e) => { | ||
| 439 | error!("✗ async write_vectored failed: {:?}", e); | ||
| 440 | defmt::panic!("Test failed: async write_vectored"); | ||
| 441 | } | ||
| 442 | } | ||
| 443 | } | ||
| 444 | |||
| 445 | async fn test_async_large_buffer(i2c: &mut I2c<'_, Async, Master>, addr: u8) { | ||
| 446 | // Test with 300 bytes to verify RELOAD mechanism works with DMA (needs chunking at 255 bytes) | ||
| 447 | let mut write_buf = [0u8; 300]; | ||
| 448 | for (i, byte) in write_buf.iter_mut().enumerate() { | ||
| 449 | *byte = (i & 0xFF) as u8; | ||
| 450 | } | ||
| 451 | |||
| 452 | match i2c.write(addr, &write_buf).await { | ||
| 453 | Ok(_) => info!("✓ Large buffer async write succeeded (300 bytes, tests RELOAD with DMA)"), | ||
| 454 | Err(e) => { | ||
| 455 | error!("✗ Large buffer async write failed: {:?}", e); | ||
| 456 | defmt::panic!("Test failed: large buffer async write"); | ||
| 457 | } | ||
| 458 | } | ||
| 459 | |||
| 460 | // Test large read | ||
| 461 | let mut read_buf = [0u8; 300]; | ||
| 462 | match i2c.read(addr, &mut read_buf).await { | ||
| 463 | Ok(_) => info!("✓ Large buffer async read succeeded (300 bytes, tests RELOAD with DMA)"), | ||
| 464 | Err(e) => { | ||
| 465 | error!("✗ Large buffer async read failed: {:?}", e); | ||
| 466 | defmt::panic!("Test failed: large buffer async read"); | ||
| 467 | } | ||
| 468 | } | ||
| 469 | } | ||
| 470 | |||
| 471 | // ==================== ASYNC TRANSACTION TEST FUNCTIONS ==================== | ||
| 472 | |||
| 473 | async fn test_consecutive_writes_async(i2c: &mut I2c<'_, Async, Master>, addr: u8) { | ||
| 474 | let data1 = [0x10, 0x11, 0x12]; | ||
| 475 | let data2 = [0x20, 0x21]; | ||
| 476 | let data3 = [0x30, 0x31, 0x32, 0x33]; | ||
| 477 | |||
| 478 | let mut ops = [ | ||
| 479 | Operation::Write(&data1), | ||
| 480 | Operation::Write(&data2), | ||
| 481 | Operation::Write(&data3), | ||
| 482 | ]; | ||
| 483 | |||
| 484 | match i2c.transaction(addr, &mut ops).await { | ||
| 485 | Ok(_) => info!("✓ Consecutive writes succeeded (merged 9 bytes)"), | ||
| 486 | Err(e) => { | ||
| 487 | error!("✗ Consecutive writes failed: {:?}", e); | ||
| 488 | defmt::panic!("Test failed: consecutive writes"); | ||
| 489 | } | ||
| 490 | } | ||
| 491 | } | ||
| 492 | |||
| 493 | async fn test_consecutive_reads_async(i2c: &mut I2c<'_, Async, Master>, addr: u8) { | ||
| 494 | let mut buf1 = [0u8; 4]; | ||
| 495 | let mut buf2 = [0u8; 3]; | ||
| 496 | let mut buf3 = [0u8; 2]; | ||
| 497 | |||
| 498 | let mut ops = [ | ||
| 499 | Operation::Read(&mut buf1), | ||
| 500 | Operation::Read(&mut buf2), | ||
| 501 | Operation::Read(&mut buf3), | ||
| 502 | ]; | ||
| 503 | |||
| 504 | match i2c.transaction(addr, &mut ops).await { | ||
| 505 | Ok(_) => { | ||
| 506 | info!("✓ Consecutive reads succeeded (merged 9 bytes)"); | ||
| 507 | info!(" buf1: {:02x}", buf1); | ||
| 508 | info!(" buf2: {:02x}", buf2); | ||
| 509 | info!(" buf3: {:02x}", buf3); | ||
| 510 | } | ||
| 511 | Err(e) => { | ||
| 512 | error!("✗ Consecutive reads failed: {:?}", e); | ||
| 513 | defmt::panic!("Test failed: consecutive reads"); | ||
| 514 | } | ||
| 515 | } | ||
| 516 | } | ||
| 517 | |||
| 518 | async fn test_write_then_read_async(i2c: &mut I2c<'_, Async, Master>, addr: u8) { | ||
| 519 | let write_data = [0xAA, 0xBB]; | ||
| 520 | let mut read_buf = [0u8; 4]; | ||
| 521 | |||
| 522 | let mut ops = [Operation::Write(&write_data), Operation::Read(&mut read_buf)]; | ||
| 523 | |||
| 524 | match i2c.transaction(addr, &mut ops).await { | ||
| 525 | Ok(_) => { | ||
| 526 | info!("✓ Write-then-read succeeded with RESTART"); | ||
| 527 | info!(" Written: {:02x}", write_data); | ||
| 528 | info!(" Read: {:02x}", read_buf); | ||
| 529 | } | ||
| 530 | Err(e) => { | ||
| 531 | error!("✗ Write-then-read failed: {:?}", e); | ||
| 532 | defmt::panic!("Test failed: write-then-read"); | ||
| 533 | } | ||
| 534 | } | ||
| 535 | } | ||
| 536 | |||
| 537 | async fn test_read_then_write_async(i2c: &mut I2c<'_, Async, Master>, addr: u8) { | ||
| 538 | let mut read_buf = [0u8; 3]; | ||
| 539 | let write_data = [0xCC, 0xDD, 0xEE]; | ||
| 540 | |||
| 541 | let mut ops = [Operation::Read(&mut read_buf), Operation::Write(&write_data)]; | ||
| 542 | |||
| 543 | match i2c.transaction(addr, &mut ops).await { | ||
| 544 | Ok(_) => { | ||
| 545 | info!("✓ Read-then-write succeeded with RESTART"); | ||
| 546 | info!(" Read: {:02x}", read_buf); | ||
| 547 | info!(" Written: {:02x}", write_data); | ||
| 548 | } | ||
| 549 | Err(e) => { | ||
| 550 | error!("✗ Read-then-write failed: {:?}", e); | ||
| 551 | defmt::panic!("Test failed: read-then-write"); | ||
| 552 | } | ||
| 553 | } | ||
| 554 | } | ||
| 555 | |||
| 556 | async fn test_mixed_sequence_async(i2c: &mut I2c<'_, Async, Master>, addr: u8) { | ||
| 557 | let w1 = [0x01, 0x02]; | ||
| 558 | let w2 = [0x03, 0x04]; | ||
| 559 | let mut r1 = [0u8; 2]; | ||
| 560 | let mut r2 = [0u8; 2]; | ||
| 561 | let w3 = [0x05]; | ||
| 562 | let mut r3 = [0u8; 1]; | ||
| 563 | |||
| 564 | let mut ops = [ | ||
| 565 | Operation::Write(&w1), | ||
| 566 | Operation::Write(&w2), | ||
| 567 | Operation::Read(&mut r1), | ||
| 568 | Operation::Read(&mut r2), | ||
| 569 | Operation::Write(&w3), | ||
| 570 | Operation::Read(&mut r3), | ||
| 571 | ]; | ||
| 572 | |||
| 573 | match i2c.transaction(addr, &mut ops).await { | ||
| 574 | Ok(_) => { | ||
| 575 | info!("✓ Mixed sequence succeeded"); | ||
| 576 | info!(" Groups: [W4] RESTART [R4] RESTART [W1] RESTART [R1]"); | ||
| 577 | } | ||
| 578 | Err(e) => { | ||
| 579 | error!("✗ Mixed sequence failed: {:?}", e); | ||
| 580 | defmt::panic!("Test failed: mixed sequence"); | ||
| 581 | } | ||
| 582 | } | ||
| 583 | } | ||
| 584 | |||
| 585 | async fn test_single_operations_async(i2c: &mut I2c<'_, Async, Master>, addr: u8) { | ||
| 586 | // Test single write | ||
| 587 | let write_data = [0xFF]; | ||
| 588 | let mut ops = [Operation::Write(&write_data)]; | ||
| 589 | |||
| 590 | match i2c.transaction(addr, &mut ops).await { | ||
| 591 | Ok(_) => info!("✓ Single write succeeded"), | ||
| 592 | Err(e) => { | ||
| 593 | error!("✗ Single write failed: {:?}", e); | ||
| 594 | defmt::panic!("Test failed: single write"); | ||
| 595 | } | ||
| 596 | } | ||
| 597 | |||
| 598 | // Test single read | ||
| 599 | let mut read_buf = [0u8; 1]; | ||
| 600 | let mut ops = [Operation::Read(&mut read_buf)]; | ||
| 601 | |||
| 602 | match i2c.transaction(addr, &mut ops).await { | ||
| 603 | Ok(_) => info!("✓ Single read succeeded, data: 0x{:02x}", read_buf[0]), | ||
| 604 | Err(e) => { | ||
| 605 | error!("✗ Single read failed: {:?}", e); | ||
| 606 | defmt::panic!("Test failed: single read"); | ||
| 607 | } | ||
| 608 | } | ||
| 609 | } | ||
diff --git a/examples/stm32f1/src/bin/adc.rs b/examples/stm32f1/src/bin/adc.rs index 541ff159e..2451aee3d 100644 --- a/examples/stm32f1/src/bin/adc.rs +++ b/examples/stm32f1/src/bin/adc.rs | |||
| @@ -3,7 +3,7 @@ | |||
| 3 | 3 | ||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_stm32::adc::Adc; | 6 | use embassy_stm32::adc::{Adc, SampleTime}; |
| 7 | use embassy_stm32::peripherals::ADC1; | 7 | use embassy_stm32::peripherals::ADC1; |
| 8 | use embassy_stm32::{adc, bind_interrupts}; | 8 | use embassy_stm32::{adc, bind_interrupts}; |
| 9 | use embassy_time::Timer; | 9 | use embassy_time::Timer; |
| @@ -22,7 +22,7 @@ async fn main(_spawner: Spawner) { | |||
| 22 | let mut pin = p.PB1; | 22 | let mut pin = p.PB1; |
| 23 | 23 | ||
| 24 | let mut vrefint = adc.enable_vref(); | 24 | let mut vrefint = adc.enable_vref(); |
| 25 | let vrefint_sample = adc.read(&mut vrefint).await; | 25 | let vrefint_sample = adc.read(&mut vrefint, SampleTime::CYCLES13_5).await; |
| 26 | let convert_to_millivolts = |sample| { | 26 | let convert_to_millivolts = |sample| { |
| 27 | // From http://www.st.com/resource/en/datasheet/CD00161566.pdf | 27 | // From http://www.st.com/resource/en/datasheet/CD00161566.pdf |
| 28 | // 5.3.4 Embedded reference voltage | 28 | // 5.3.4 Embedded reference voltage |
| @@ -32,7 +32,7 @@ async fn main(_spawner: Spawner) { | |||
| 32 | }; | 32 | }; |
| 33 | 33 | ||
| 34 | loop { | 34 | loop { |
| 35 | let v = adc.read(&mut pin).await; | 35 | let v = adc.read(&mut pin, SampleTime::CYCLES13_5).await; |
| 36 | info!("--> {} - {} mV", v, convert_to_millivolts(v)); | 36 | info!("--> {} - {} mV", v, convert_to_millivolts(v)); |
| 37 | Timer::after_millis(100).await; | 37 | Timer::after_millis(100).await; |
| 38 | } | 38 | } |
diff --git a/examples/stm32f334/src/bin/adc.rs b/examples/stm32f334/src/bin/adc.rs index a993b00ca..486f160ec 100644 --- a/examples/stm32f334/src/bin/adc.rs +++ b/examples/stm32f334/src/bin/adc.rs | |||
| @@ -40,24 +40,22 @@ async fn main(_spawner: Spawner) -> ! { | |||
| 40 | 40 | ||
| 41 | let mut adc = Adc::new(p.ADC1, Irqs); | 41 | let mut adc = Adc::new(p.ADC1, Irqs); |
| 42 | 42 | ||
| 43 | adc.set_sample_time(SampleTime::CYCLES601_5); | ||
| 44 | |||
| 45 | info!("enable vrefint..."); | 43 | info!("enable vrefint..."); |
| 46 | 44 | ||
| 47 | let mut vrefint = adc.enable_vref(); | 45 | let mut vrefint = adc.enable_vref(); |
| 48 | let mut temperature = adc.enable_temperature(); | 46 | let mut temperature = adc.enable_temperature(); |
| 49 | 47 | ||
| 50 | loop { | 48 | loop { |
| 51 | let vref = adc.read(&mut vrefint).await; | 49 | let vref = adc.read(&mut vrefint, SampleTime::CYCLES601_5).await; |
| 52 | info!("read vref: {} (should be {})", vref, vrefint.value()); | 50 | info!("read vref: {} (should be {})", vref, vrefint.calibrated_value()); |
| 53 | 51 | ||
| 54 | let temp = adc.read(&mut temperature).await; | 52 | let temp = adc.read(&mut temperature, SampleTime::CYCLES601_5).await; |
| 55 | info!("read temperature: {}", temp); | 53 | info!("read temperature: {}", temp); |
| 56 | 54 | ||
| 57 | let pin = adc.read(&mut p.PA0).await; | 55 | let pin = adc.read(&mut p.PA0, SampleTime::CYCLES601_5).await; |
| 58 | info!("read pin: {}", pin); | 56 | info!("read pin: {}", pin); |
| 59 | 57 | ||
| 60 | let pin_mv = (pin as u32 * vrefint.value() as u32 / vref as u32) * 3300 / 4095; | 58 | let pin_mv = (pin as u32 * vrefint.calibrated_value() as u32 / vref as u32) * 3300 / 4095; |
| 61 | info!("computed pin mv: {}", pin_mv); | 59 | info!("computed pin mv: {}", pin_mv); |
| 62 | 60 | ||
| 63 | Timer::after_millis(500).await; | 61 | Timer::after_millis(500).await; |
diff --git a/examples/stm32f334/src/bin/opamp.rs b/examples/stm32f334/src/bin/opamp.rs index 3e621f2a1..9555fd35d 100644 --- a/examples/stm32f334/src/bin/opamp.rs +++ b/examples/stm32f334/src/bin/opamp.rs | |||
| @@ -42,8 +42,6 @@ async fn main(_spawner: Spawner) -> ! { | |||
| 42 | let mut adc = Adc::new(p.ADC2, Irqs); | 42 | let mut adc = Adc::new(p.ADC2, Irqs); |
| 43 | let mut opamp = OpAmp::new(p.OPAMP2); | 43 | let mut opamp = OpAmp::new(p.OPAMP2); |
| 44 | 44 | ||
| 45 | adc.set_sample_time(SampleTime::CYCLES601_5); | ||
| 46 | |||
| 47 | info!("enable vrefint..."); | 45 | info!("enable vrefint..."); |
| 48 | 46 | ||
| 49 | let mut vrefint = adc.enable_vref(); | 47 | let mut vrefint = adc.enable_vref(); |
| @@ -51,16 +49,16 @@ async fn main(_spawner: Spawner) -> ! { | |||
| 51 | let mut buffer = opamp.buffer_ext(p.PA7.reborrow(), p.PA6.reborrow()); | 49 | let mut buffer = opamp.buffer_ext(p.PA7.reborrow(), p.PA6.reborrow()); |
| 52 | 50 | ||
| 53 | loop { | 51 | loop { |
| 54 | let vref = adc.read(&mut vrefint).await; | 52 | let vref = adc.read(&mut vrefint, SampleTime::CYCLES601_5).await; |
| 55 | info!("read vref: {} (should be {})", vref, vrefint.value()); | 53 | info!("read vref: {} (should be {})", vref, vrefint.calibrated_value()); |
| 56 | 54 | ||
| 57 | let temp = adc.read(&mut temperature).await; | 55 | let temp = adc.read(&mut temperature, SampleTime::CYCLES601_5).await; |
| 58 | info!("read temperature: {}", temp); | 56 | info!("read temperature: {}", temp); |
| 59 | 57 | ||
| 60 | let buffer = adc.read(&mut buffer).await; | 58 | let buffer = adc.read(&mut buffer, SampleTime::CYCLES601_5).await; |
| 61 | info!("read buffer: {}", buffer); | 59 | info!("read buffer: {}", buffer); |
| 62 | 60 | ||
| 63 | let pin_mv = (buffer as u32 * vrefint.value() as u32 / vref as u32) * 3300 / 4095; | 61 | let pin_mv = (buffer as u32 * vrefint.calibrated_value() as u32 / vref as u32) * 3300 / 4095; |
| 64 | info!("computed pin mv: {}", pin_mv); | 62 | info!("computed pin mv: {}", pin_mv); |
| 65 | 63 | ||
| 66 | Timer::after_millis(500).await; | 64 | Timer::after_millis(500).await; |
diff --git a/examples/stm32f4/src/bin/adc.rs b/examples/stm32f4/src/bin/adc.rs index 423d29225..694e85657 100644 --- a/examples/stm32f4/src/bin/adc.rs +++ b/examples/stm32f4/src/bin/adc.rs | |||
| @@ -4,7 +4,7 @@ | |||
| 4 | use cortex_m::prelude::_embedded_hal_blocking_delay_DelayUs; | 4 | use cortex_m::prelude::_embedded_hal_blocking_delay_DelayUs; |
| 5 | use defmt::*; | 5 | use defmt::*; |
| 6 | use embassy_executor::Spawner; | 6 | use embassy_executor::Spawner; |
| 7 | use embassy_stm32::adc::{Adc, Temperature, VrefInt}; | 7 | use embassy_stm32::adc::{Adc, SampleTime, Temperature, VrefInt}; |
| 8 | use embassy_time::{Delay, Timer}; | 8 | use embassy_time::{Delay, Timer}; |
| 9 | use {defmt_rtt as _, panic_probe as _}; | 9 | use {defmt_rtt as _, panic_probe as _}; |
| 10 | 10 | ||
| @@ -14,7 +14,7 @@ async fn main(_spawner: Spawner) { | |||
| 14 | info!("Hello World!"); | 14 | info!("Hello World!"); |
| 15 | 15 | ||
| 16 | let mut delay = Delay; | 16 | let mut delay = Delay; |
| 17 | let mut adc = Adc::new(p.ADC1); | 17 | let mut adc = Adc::new_with_config(p.ADC1, Default::default()); |
| 18 | let mut pin = p.PC1; | 18 | let mut pin = p.PC1; |
| 19 | 19 | ||
| 20 | let mut vrefint = adc.enable_vrefint(); | 20 | let mut vrefint = adc.enable_vrefint(); |
| @@ -23,7 +23,7 @@ async fn main(_spawner: Spawner) { | |||
| 23 | // Startup delay can be combined to the maximum of either | 23 | // Startup delay can be combined to the maximum of either |
| 24 | delay.delay_us(Temperature::start_time_us().max(VrefInt::start_time_us())); | 24 | delay.delay_us(Temperature::start_time_us().max(VrefInt::start_time_us())); |
| 25 | 25 | ||
| 26 | let vrefint_sample = adc.blocking_read(&mut vrefint); | 26 | let vrefint_sample = adc.blocking_read(&mut vrefint, SampleTime::CYCLES112); |
| 27 | 27 | ||
| 28 | let convert_to_millivolts = |sample| { | 28 | let convert_to_millivolts = |sample| { |
| 29 | // From http://www.st.com/resource/en/datasheet/DM00071990.pdf | 29 | // From http://www.st.com/resource/en/datasheet/DM00071990.pdf |
| @@ -50,16 +50,16 @@ async fn main(_spawner: Spawner) { | |||
| 50 | 50 | ||
| 51 | loop { | 51 | loop { |
| 52 | // Read pin | 52 | // Read pin |
| 53 | let v = adc.blocking_read(&mut pin); | 53 | let v = adc.blocking_read(&mut pin, SampleTime::CYCLES112); |
| 54 | info!("PC1: {} ({} mV)", v, convert_to_millivolts(v)); | 54 | info!("PC1: {} ({} mV)", v, convert_to_millivolts(v)); |
| 55 | 55 | ||
| 56 | // Read internal temperature | 56 | // Read internal temperature |
| 57 | let v = adc.blocking_read(&mut temp); | 57 | let v = adc.blocking_read(&mut temp, SampleTime::CYCLES112); |
| 58 | let celcius = convert_to_celcius(v); | 58 | let celcius = convert_to_celcius(v); |
| 59 | info!("Internal temp: {} ({} C)", v, celcius); | 59 | info!("Internal temp: {} ({} C)", v, celcius); |
| 60 | 60 | ||
| 61 | // Read internal voltage reference | 61 | // Read internal voltage reference |
| 62 | let v = adc.blocking_read(&mut vrefint); | 62 | let v = adc.blocking_read(&mut vrefint, SampleTime::CYCLES112); |
| 63 | info!("VrefInt: {}", v); | 63 | info!("VrefInt: {}", v); |
| 64 | 64 | ||
| 65 | Timer::after_millis(100).await; | 65 | Timer::after_millis(100).await; |
diff --git a/examples/stm32f4/src/bin/adc_dma.rs b/examples/stm32f4/src/bin/adc_dma.rs index f8da91336..d61b1b2eb 100644 --- a/examples/stm32f4/src/bin/adc_dma.rs +++ b/examples/stm32f4/src/bin/adc_dma.rs | |||
| @@ -4,7 +4,7 @@ use cortex_m::singleton; | |||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_stm32::Peripherals; | 6 | use embassy_stm32::Peripherals; |
| 7 | use embassy_stm32::adc::{Adc, AdcChannel, RingBufferedAdc, SampleTime}; | 7 | use embassy_stm32::adc::{Adc, AdcChannel, RegularConversionMode, RingBufferedAdc, SampleTime}; |
| 8 | use embassy_time::Instant; | 8 | use embassy_time::Instant; |
| 9 | use {defmt_rtt as _, panic_probe as _}; | 9 | use {defmt_rtt as _, panic_probe as _}; |
| 10 | 10 | ||
| @@ -20,26 +20,28 @@ async fn adc_task(p: Peripherals) { | |||
| 20 | let adc_data: &mut [u16; ADC_BUF_SIZE] = singleton!(ADCDAT : [u16; ADC_BUF_SIZE] = [0u16; ADC_BUF_SIZE]).unwrap(); | 20 | let adc_data: &mut [u16; ADC_BUF_SIZE] = singleton!(ADCDAT : [u16; ADC_BUF_SIZE] = [0u16; ADC_BUF_SIZE]).unwrap(); |
| 21 | let adc_data2: &mut [u16; ADC_BUF_SIZE] = singleton!(ADCDAT2 : [u16; ADC_BUF_SIZE] = [0u16; ADC_BUF_SIZE]).unwrap(); | 21 | let adc_data2: &mut [u16; ADC_BUF_SIZE] = singleton!(ADCDAT2 : [u16; ADC_BUF_SIZE] = [0u16; ADC_BUF_SIZE]).unwrap(); |
| 22 | 22 | ||
| 23 | let adc = Adc::new(p.ADC1); | 23 | let adc = Adc::new_with_config(p.ADC1, Default::default()); |
| 24 | let adc2 = Adc::new(p.ADC2); | 24 | let adc2 = Adc::new_with_config(p.ADC2, Default::default()); |
| 25 | 25 | ||
| 26 | let mut adc: RingBufferedAdc<embassy_stm32::peripherals::ADC1> = adc.into_ring_buffered( | 26 | let mut adc: RingBufferedAdc<embassy_stm32::peripherals::ADC1> = adc.into_ring_buffered( |
| 27 | p.DMA2_CH0, | 27 | p.DMA2_CH0, |
| 28 | adc_data, | 28 | adc_data, |
| 29 | [ | 29 | [ |
| 30 | (&mut p.PA0.degrade_adc(), SampleTime::CYCLES112), | 30 | (p.PA0.degrade_adc(), SampleTime::CYCLES112), |
| 31 | (&mut p.PA2.degrade_adc(), SampleTime::CYCLES112), | 31 | (p.PA2.degrade_adc(), SampleTime::CYCLES112), |
| 32 | ] | 32 | ] |
| 33 | .into_iter(), | 33 | .into_iter(), |
| 34 | RegularConversionMode::Continuous, | ||
| 34 | ); | 35 | ); |
| 35 | let mut adc2: RingBufferedAdc<embassy_stm32::peripherals::ADC2> = adc2.into_ring_buffered( | 36 | let mut adc2: RingBufferedAdc<embassy_stm32::peripherals::ADC2> = adc2.into_ring_buffered( |
| 36 | p.DMA2_CH2, | 37 | p.DMA2_CH2, |
| 37 | adc_data2, | 38 | adc_data2, |
| 38 | [ | 39 | [ |
| 39 | (&mut p.PA1.degrade_adc(), SampleTime::CYCLES112), | 40 | (p.PA1.degrade_adc(), SampleTime::CYCLES112), |
| 40 | (&mut p.PA3.degrade_adc(), SampleTime::CYCLES112), | 41 | (p.PA3.degrade_adc(), SampleTime::CYCLES112), |
| 41 | ] | 42 | ] |
| 42 | .into_iter(), | 43 | .into_iter(), |
| 44 | RegularConversionMode::Continuous, | ||
| 43 | ); | 45 | ); |
| 44 | 46 | ||
| 45 | // Note that overrun is a big consideration in this implementation. Whatever task is running the adc.read() calls absolutely must circle back around | 47 | // Note that overrun is a big consideration in this implementation. Whatever task is running the adc.read() calls absolutely must circle back around |
diff --git a/examples/stm32f4/src/bin/usb_hid_keyboard.rs b/examples/stm32f4/src/bin/usb_hid_keyboard.rs index a3afb887c..9971e43f5 100644 --- a/examples/stm32f4/src/bin/usb_hid_keyboard.rs +++ b/examples/stm32f4/src/bin/usb_hid_keyboard.rs | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | #![no_std] | 1 | #![no_std] |
| 2 | #![no_main] | 2 | #![no_main] |
| 3 | 3 | ||
| 4 | use core::sync::atomic::{AtomicBool, Ordering}; | 4 | use core::sync::atomic::{AtomicBool, AtomicU8, Ordering}; |
| 5 | 5 | ||
| 6 | use defmt::*; | 6 | use defmt::*; |
| 7 | use embassy_executor::Spawner; | 7 | use embassy_executor::Spawner; |
| @@ -11,7 +11,9 @@ use embassy_stm32::gpio::Pull; | |||
| 11 | use embassy_stm32::time::Hertz; | 11 | use embassy_stm32::time::Hertz; |
| 12 | use embassy_stm32::usb::Driver; | 12 | use embassy_stm32::usb::Driver; |
| 13 | use embassy_stm32::{Config, bind_interrupts, peripherals, usb}; | 13 | use embassy_stm32::{Config, bind_interrupts, peripherals, usb}; |
| 14 | use embassy_usb::class::hid::{HidReaderWriter, ReportId, RequestHandler, State}; | 14 | use embassy_usb::class::hid::{ |
| 15 | HidBootProtocol, HidProtocolMode, HidReaderWriter, HidSubclass, ReportId, RequestHandler, State, | ||
| 16 | }; | ||
| 15 | use embassy_usb::control::OutResponse; | 17 | use embassy_usb::control::OutResponse; |
| 16 | use embassy_usb::{Builder, Handler}; | 18 | use embassy_usb::{Builder, Handler}; |
| 17 | use usbd_hid::descriptor::{KeyboardReport, SerializedDescriptor}; | 19 | use usbd_hid::descriptor::{KeyboardReport, SerializedDescriptor}; |
| @@ -21,6 +23,8 @@ bind_interrupts!(struct Irqs { | |||
| 21 | OTG_FS => usb::InterruptHandler<peripherals::USB_OTG_FS>; | 23 | OTG_FS => usb::InterruptHandler<peripherals::USB_OTG_FS>; |
| 22 | }); | 24 | }); |
| 23 | 25 | ||
| 26 | static HID_PROTOCOL_MODE: AtomicU8 = AtomicU8::new(HidProtocolMode::Boot as u8); | ||
| 27 | |||
| 24 | // If you are trying this and your USB device doesn't connect, the most | 28 | // If you are trying this and your USB device doesn't connect, the most |
| 25 | // common issues are the RCC config and vbus_detection | 29 | // common issues are the RCC config and vbus_detection |
| 26 | // | 30 | // |
| @@ -70,6 +74,10 @@ async fn main(_spawner: Spawner) { | |||
| 70 | config.serial_number = Some("12345678"); | 74 | config.serial_number = Some("12345678"); |
| 71 | config.max_power = 100; | 75 | config.max_power = 100; |
| 72 | config.max_packet_size_0 = 64; | 76 | config.max_packet_size_0 = 64; |
| 77 | config.composite_with_iads = false; | ||
| 78 | config.device_class = 0; | ||
| 79 | config.device_sub_class = 0; | ||
| 80 | config.device_protocol = 0; | ||
| 73 | 81 | ||
| 74 | // Create embassy-usb DeviceBuilder using the driver and config. | 82 | // Create embassy-usb DeviceBuilder using the driver and config. |
| 75 | // It needs some buffers for building the descriptors. | 83 | // It needs some buffers for building the descriptors. |
| @@ -101,6 +109,8 @@ async fn main(_spawner: Spawner) { | |||
| 101 | request_handler: None, | 109 | request_handler: None, |
| 102 | poll_ms: 60, | 110 | poll_ms: 60, |
| 103 | max_packet_size: 8, | 111 | max_packet_size: 8, |
| 112 | hid_subclass: HidSubclass::Boot, | ||
| 113 | hid_boot_protocol: HidBootProtocol::Keyboard, | ||
| 104 | }; | 114 | }; |
| 105 | 115 | ||
| 106 | let hid = HidReaderWriter::<_, 1, 8>::new(&mut builder, &mut state, config); | 116 | let hid = HidReaderWriter::<_, 1, 8>::new(&mut builder, &mut state, config); |
| @@ -121,32 +131,46 @@ async fn main(_spawner: Spawner) { | |||
| 121 | button.wait_for_rising_edge().await; | 131 | button.wait_for_rising_edge().await; |
| 122 | // signal_pin.wait_for_high().await; | 132 | // signal_pin.wait_for_high().await; |
| 123 | info!("Button pressed!"); | 133 | info!("Button pressed!"); |
| 124 | // Create a report with the A key pressed. (no shift modifier) | 134 | if HID_PROTOCOL_MODE.load(Ordering::Relaxed) == HidProtocolMode::Boot as u8 { |
| 125 | let report = KeyboardReport { | 135 | match writer.write(&[0, 0, 4, 0, 0, 0, 0, 0]).await { |
| 126 | keycodes: [4, 0, 0, 0, 0, 0], | 136 | Ok(()) => {} |
| 127 | leds: 0, | 137 | Err(e) => warn!("Failed to send boot report: {:?}", e), |
| 128 | modifier: 0, | 138 | }; |
| 129 | reserved: 0, | 139 | } else { |
| 130 | }; | 140 | // Create a report with the A key pressed. (no shift modifier) |
| 131 | // Send the report. | 141 | let report = KeyboardReport { |
| 132 | match writer.write_serialize(&report).await { | 142 | keycodes: [4, 0, 0, 0, 0, 0], |
| 133 | Ok(()) => {} | 143 | leds: 0, |
| 134 | Err(e) => warn!("Failed to send report: {:?}", e), | 144 | modifier: 0, |
| 135 | }; | 145 | reserved: 0, |
| 146 | }; | ||
| 147 | // Send the report. | ||
| 148 | match writer.write_serialize(&report).await { | ||
| 149 | Ok(()) => {} | ||
| 150 | Err(e) => warn!("Failed to send report: {:?}", e), | ||
| 151 | }; | ||
| 152 | } | ||
| 136 | 153 | ||
| 137 | button.wait_for_falling_edge().await; | 154 | button.wait_for_falling_edge().await; |
| 138 | // signal_pin.wait_for_low().await; | 155 | // signal_pin.wait_for_low().await; |
| 139 | info!("Button released!"); | 156 | info!("Button released!"); |
| 140 | let report = KeyboardReport { | 157 | if HID_PROTOCOL_MODE.load(Ordering::Relaxed) == HidProtocolMode::Boot as u8 { |
| 141 | keycodes: [0, 0, 0, 0, 0, 0], | 158 | match writer.write(&[0, 0, 0, 0, 0, 0, 0, 0]).await { |
| 142 | leds: 0, | 159 | Ok(()) => {} |
| 143 | modifier: 0, | 160 | Err(e) => warn!("Failed to send boot report: {:?}", e), |
| 144 | reserved: 0, | 161 | }; |
| 145 | }; | 162 | } else { |
| 146 | match writer.write_serialize(&report).await { | 163 | let report = KeyboardReport { |
| 147 | Ok(()) => {} | 164 | keycodes: [0, 0, 0, 0, 0, 0], |
| 148 | Err(e) => warn!("Failed to send report: {:?}", e), | 165 | leds: 0, |
| 149 | }; | 166 | modifier: 0, |
| 167 | reserved: 0, | ||
| 168 | }; | ||
| 169 | match writer.write_serialize(&report).await { | ||
| 170 | Ok(()) => {} | ||
| 171 | Err(e) => warn!("Failed to send report: {:?}", e), | ||
| 172 | }; | ||
| 173 | } | ||
| 150 | } | 174 | } |
| 151 | }; | 175 | }; |
| 152 | 176 | ||
| @@ -172,6 +196,18 @@ impl RequestHandler for MyRequestHandler { | |||
| 172 | OutResponse::Accepted | 196 | OutResponse::Accepted |
| 173 | } | 197 | } |
| 174 | 198 | ||
| 199 | fn get_protocol(&self) -> HidProtocolMode { | ||
| 200 | let protocol = HidProtocolMode::from(HID_PROTOCOL_MODE.load(Ordering::Relaxed)); | ||
| 201 | info!("The current HID protocol mode is: {}", protocol); | ||
| 202 | protocol | ||
| 203 | } | ||
| 204 | |||
| 205 | fn set_protocol(&mut self, protocol: HidProtocolMode) -> OutResponse { | ||
| 206 | info!("Switching to HID protocol mode: {}", protocol); | ||
| 207 | HID_PROTOCOL_MODE.store(protocol as u8, Ordering::Relaxed); | ||
| 208 | OutResponse::Accepted | ||
| 209 | } | ||
| 210 | |||
| 175 | fn set_idle_ms(&mut self, id: Option<ReportId>, dur: u32) { | 211 | fn set_idle_ms(&mut self, id: Option<ReportId>, dur: u32) { |
| 176 | info!("Set idle rate for {:?} to {:?}", id, dur); | 212 | info!("Set idle rate for {:?} to {:?}", id, dur); |
| 177 | } | 213 | } |
diff --git a/examples/stm32f4/src/bin/usb_hid_mouse.rs b/examples/stm32f4/src/bin/usb_hid_mouse.rs index 162a035f2..e83d01f88 100644 --- a/examples/stm32f4/src/bin/usb_hid_mouse.rs +++ b/examples/stm32f4/src/bin/usb_hid_mouse.rs | |||
| @@ -1,6 +1,8 @@ | |||
| 1 | #![no_std] | 1 | #![no_std] |
| 2 | #![no_main] | 2 | #![no_main] |
| 3 | 3 | ||
| 4 | use core::sync::atomic::{AtomicU8, Ordering}; | ||
| 5 | |||
| 4 | use defmt::*; | 6 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 7 | use embassy_executor::Spawner; |
| 6 | use embassy_futures::join::join; | 8 | use embassy_futures::join::join; |
| @@ -9,7 +11,9 @@ use embassy_stm32::usb::Driver; | |||
| 9 | use embassy_stm32::{Config, bind_interrupts, peripherals, usb}; | 11 | use embassy_stm32::{Config, bind_interrupts, peripherals, usb}; |
| 10 | use embassy_time::Timer; | 12 | use embassy_time::Timer; |
| 11 | use embassy_usb::Builder; | 13 | use embassy_usb::Builder; |
| 12 | use embassy_usb::class::hid::{HidWriter, ReportId, RequestHandler, State}; | 14 | use embassy_usb::class::hid::{ |
| 15 | HidBootProtocol, HidProtocolMode, HidSubclass, HidWriter, ReportId, RequestHandler, State, | ||
| 16 | }; | ||
| 13 | use embassy_usb::control::OutResponse; | 17 | use embassy_usb::control::OutResponse; |
| 14 | use usbd_hid::descriptor::{MouseReport, SerializedDescriptor}; | 18 | use usbd_hid::descriptor::{MouseReport, SerializedDescriptor}; |
| 15 | use {defmt_rtt as _, panic_probe as _}; | 19 | use {defmt_rtt as _, panic_probe as _}; |
| @@ -18,6 +22,8 @@ bind_interrupts!(struct Irqs { | |||
| 18 | OTG_FS => usb::InterruptHandler<peripherals::USB_OTG_FS>; | 22 | OTG_FS => usb::InterruptHandler<peripherals::USB_OTG_FS>; |
| 19 | }); | 23 | }); |
| 20 | 24 | ||
| 25 | static HID_PROTOCOL_MODE: AtomicU8 = AtomicU8::new(HidProtocolMode::Boot as u8); | ||
| 26 | |||
| 21 | // If you are trying this and your USB device doesn't connect, the most | 27 | // If you are trying this and your USB device doesn't connect, the most |
| 22 | // common issues are the RCC config and vbus_detection | 28 | // common issues are the RCC config and vbus_detection |
| 23 | // | 29 | // |
| @@ -65,6 +71,10 @@ async fn main(_spawner: Spawner) { | |||
| 65 | config.manufacturer = Some("Embassy"); | 71 | config.manufacturer = Some("Embassy"); |
| 66 | config.product = Some("HID mouse example"); | 72 | config.product = Some("HID mouse example"); |
| 67 | config.serial_number = Some("12345678"); | 73 | config.serial_number = Some("12345678"); |
| 74 | config.composite_with_iads = false; | ||
| 75 | config.device_class = 0; | ||
| 76 | config.device_sub_class = 0; | ||
| 77 | config.device_protocol = 0; | ||
| 68 | 78 | ||
| 69 | // Create embassy-usb DeviceBuilder using the driver and config. | 79 | // Create embassy-usb DeviceBuilder using the driver and config. |
| 70 | // It needs some buffers for building the descriptors. | 80 | // It needs some buffers for building the descriptors. |
| @@ -91,6 +101,8 @@ async fn main(_spawner: Spawner) { | |||
| 91 | request_handler: Some(&mut request_handler), | 101 | request_handler: Some(&mut request_handler), |
| 92 | poll_ms: 60, | 102 | poll_ms: 60, |
| 93 | max_packet_size: 8, | 103 | max_packet_size: 8, |
| 104 | hid_subclass: HidSubclass::Boot, | ||
| 105 | hid_boot_protocol: HidBootProtocol::Mouse, | ||
| 94 | }; | 106 | }; |
| 95 | 107 | ||
| 96 | let mut writer = HidWriter::<_, 5>::new(&mut builder, &mut state, config); | 108 | let mut writer = HidWriter::<_, 5>::new(&mut builder, &mut state, config); |
| @@ -108,16 +120,26 @@ async fn main(_spawner: Spawner) { | |||
| 108 | Timer::after_millis(500).await; | 120 | Timer::after_millis(500).await; |
| 109 | 121 | ||
| 110 | y = -y; | 122 | y = -y; |
| 111 | let report = MouseReport { | 123 | |
| 112 | buttons: 0, | 124 | if HID_PROTOCOL_MODE.load(Ordering::Relaxed) == HidProtocolMode::Boot as u8 { |
| 113 | x: 0, | 125 | let buttons = 0u8; |
| 114 | y, | 126 | let x = 0i8; |
| 115 | wheel: 0, | 127 | match writer.write(&[buttons, x as u8, y as u8]).await { |
| 116 | pan: 0, | 128 | Ok(()) => {} |
| 117 | }; | 129 | Err(e) => warn!("Failed to send boot report: {:?}", e), |
| 118 | match writer.write_serialize(&report).await { | 130 | } |
| 119 | Ok(()) => {} | 131 | } else { |
| 120 | Err(e) => warn!("Failed to send report: {:?}", e), | 132 | let report = MouseReport { |
| 133 | buttons: 0, | ||
| 134 | x: 0, | ||
| 135 | y, | ||
| 136 | wheel: 0, | ||
| 137 | pan: 0, | ||
| 138 | }; | ||
| 139 | match writer.write_serialize(&report).await { | ||
| 140 | Ok(()) => {} | ||
| 141 | Err(e) => warn!("Failed to send report: {:?}", e), | ||
| 142 | } | ||
| 121 | } | 143 | } |
| 122 | } | 144 | } |
| 123 | }; | 145 | }; |
| @@ -140,6 +162,18 @@ impl RequestHandler for MyRequestHandler { | |||
| 140 | OutResponse::Accepted | 162 | OutResponse::Accepted |
| 141 | } | 163 | } |
| 142 | 164 | ||
| 165 | fn get_protocol(&self) -> HidProtocolMode { | ||
| 166 | let protocol = HidProtocolMode::from(HID_PROTOCOL_MODE.load(Ordering::Relaxed)); | ||
| 167 | info!("The current HID protocol mode is: {}", protocol); | ||
| 168 | protocol | ||
| 169 | } | ||
| 170 | |||
| 171 | fn set_protocol(&mut self, protocol: HidProtocolMode) -> OutResponse { | ||
| 172 | info!("Switching to HID protocol mode: {}", protocol); | ||
| 173 | HID_PROTOCOL_MODE.store(protocol as u8, Ordering::Relaxed); | ||
| 174 | OutResponse::Accepted | ||
| 175 | } | ||
| 176 | |||
| 143 | fn set_idle_ms(&mut self, id: Option<ReportId>, dur: u32) { | 177 | fn set_idle_ms(&mut self, id: Option<ReportId>, dur: u32) { |
| 144 | info!("Set idle rate for {:?} to {:?}", id, dur); | 178 | info!("Set idle rate for {:?} to {:?}", id, dur); |
| 145 | } | 179 | } |
diff --git a/examples/stm32f469/src/bin/dsi_bsp.rs b/examples/stm32f469/src/bin/dsi_bsp.rs index d659291ff..7ba4da72b 100644 --- a/examples/stm32f469/src/bin/dsi_bsp.rs +++ b/examples/stm32f469/src/bin/dsi_bsp.rs | |||
| @@ -3,7 +3,7 @@ | |||
| 3 | 3 | ||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_stm32::dsihost::{DsiHost, PacketType, blocking_delay_ms}; | 6 | use embassy_stm32::dsihost::{DsiHost, PacketType}; |
| 7 | use embassy_stm32::gpio::{Level, Output, Speed}; | 7 | use embassy_stm32::gpio::{Level, Output, Speed}; |
| 8 | use embassy_stm32::ltdc::Ltdc; | 8 | use embassy_stm32::ltdc::Ltdc; |
| 9 | use embassy_stm32::pac::dsihost::regs::{Ier0, Ier1}; | 9 | use embassy_stm32::pac::dsihost::regs::{Ier0, Ier1}; |
| @@ -13,7 +13,7 @@ use embassy_stm32::rcc::{ | |||
| 13 | AHBPrescaler, APBPrescaler, Hse, HseMode, Pll, PllMul, PllPDiv, PllPreDiv, PllQDiv, PllRDiv, PllSource, Sysclk, | 13 | AHBPrescaler, APBPrescaler, Hse, HseMode, Pll, PllMul, PllPDiv, PllPreDiv, PllQDiv, PllRDiv, PllSource, Sysclk, |
| 14 | }; | 14 | }; |
| 15 | use embassy_stm32::time::mhz; | 15 | use embassy_stm32::time::mhz; |
| 16 | use embassy_time::Timer; | 16 | use embassy_time::{Duration, Timer, block_for}; |
| 17 | use {defmt_rtt as _, panic_probe as _}; | 17 | use {defmt_rtt as _, panic_probe as _}; |
| 18 | 18 | ||
| 19 | enum _Orientation { | 19 | enum _Orientation { |
| @@ -444,7 +444,7 @@ async fn main(_spawner: Spawner) { | |||
| 444 | dsi.enable_wrapper_dsi(); | 444 | dsi.enable_wrapper_dsi(); |
| 445 | 445 | ||
| 446 | // First, delay 120 ms (reason unknown, STM32 Cube Example does it) | 446 | // First, delay 120 ms (reason unknown, STM32 Cube Example does it) |
| 447 | blocking_delay_ms(120); | 447 | block_for(Duration::from_millis(120)); |
| 448 | 448 | ||
| 449 | // 1 to 26 | 449 | // 1 to 26 |
| 450 | dsi.write_cmd(0, NT35510_WRITES_0[0], &NT35510_WRITES_0[1..]).unwrap(); | 450 | dsi.write_cmd(0, NT35510_WRITES_0[0], &NT35510_WRITES_0[1..]).unwrap(); |
| @@ -480,7 +480,7 @@ async fn main(_spawner: Spawner) { | |||
| 480 | dsi.write_cmd(0, NT35510_WRITES_37[0], &NT35510_WRITES_37[1..]).unwrap(); | 480 | dsi.write_cmd(0, NT35510_WRITES_37[0], &NT35510_WRITES_37[1..]).unwrap(); |
| 481 | 481 | ||
| 482 | // Add a delay, otherwise MADCTL not taken | 482 | // Add a delay, otherwise MADCTL not taken |
| 483 | blocking_delay_ms(200); | 483 | block_for(Duration::from_millis(200)); |
| 484 | 484 | ||
| 485 | // Configure orientation as landscape | 485 | // Configure orientation as landscape |
| 486 | dsi.write_cmd(0, NT35510_MADCTL_LANDSCAPE[0], &NT35510_MADCTL_LANDSCAPE[1..]) | 486 | dsi.write_cmd(0, NT35510_MADCTL_LANDSCAPE[0], &NT35510_MADCTL_LANDSCAPE[1..]) |
| @@ -494,7 +494,7 @@ async fn main(_spawner: Spawner) { | |||
| 494 | dsi.write_cmd(0, NT35510_WRITES_27[0], &NT35510_WRITES_27[1..]).unwrap(); | 494 | dsi.write_cmd(0, NT35510_WRITES_27[0], &NT35510_WRITES_27[1..]).unwrap(); |
| 495 | 495 | ||
| 496 | // Wait for sleep out exit | 496 | // Wait for sleep out exit |
| 497 | blocking_delay_ms(120); | 497 | block_for(Duration::from_millis(120)); |
| 498 | 498 | ||
| 499 | // Configure COLOR_CODING | 499 | // Configure COLOR_CODING |
| 500 | dsi.write_cmd(0, NT35510_WRITES_37[0], &NT35510_WRITES_37[1..]).unwrap(); | 500 | dsi.write_cmd(0, NT35510_WRITES_37[0], &NT35510_WRITES_37[1..]).unwrap(); |
| @@ -590,7 +590,7 @@ async fn main(_spawner: Spawner) { | |||
| 590 | //LTDC->SRCR = LTDC_SRCR_IMR; | 590 | //LTDC->SRCR = LTDC_SRCR_IMR; |
| 591 | LTDC.srcr().modify(|w| w.set_imr(Imr::RELOAD)); | 591 | LTDC.srcr().modify(|w| w.set_imr(Imr::RELOAD)); |
| 592 | 592 | ||
| 593 | blocking_delay_ms(5000); | 593 | block_for(Duration::from_millis(5000)); |
| 594 | 594 | ||
| 595 | const READ_SIZE: u16 = 1; | 595 | const READ_SIZE: u16 = 1; |
| 596 | let mut data = [1u8; READ_SIZE as usize]; | 596 | let mut data = [1u8; READ_SIZE as usize]; |
| @@ -606,7 +606,7 @@ async fn main(_spawner: Spawner) { | |||
| 606 | .unwrap(); | 606 | .unwrap(); |
| 607 | info!("Display ID3: {:#04x}", data); | 607 | info!("Display ID3: {:#04x}", data); |
| 608 | 608 | ||
| 609 | blocking_delay_ms(500); | 609 | block_for(Duration::from_millis(500)); |
| 610 | 610 | ||
| 611 | info!("Config done, start blinking LED"); | 611 | info!("Config done, start blinking LED"); |
| 612 | loop { | 612 | loop { |
diff --git a/examples/stm32f7/src/bin/adc.rs b/examples/stm32f7/src/bin/adc.rs index 6689e3b5d..0f226d34e 100644 --- a/examples/stm32f7/src/bin/adc.rs +++ b/examples/stm32f7/src/bin/adc.rs | |||
| @@ -3,7 +3,7 @@ | |||
| 3 | 3 | ||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_stm32::adc::Adc; | 6 | use embassy_stm32::adc::{Adc, SampleTime}; |
| 7 | use embassy_time::Timer; | 7 | use embassy_time::Timer; |
| 8 | use {defmt_rtt as _, panic_probe as _}; | 8 | use {defmt_rtt as _, panic_probe as _}; |
| 9 | 9 | ||
| @@ -16,7 +16,7 @@ async fn main(_spawner: Spawner) { | |||
| 16 | let mut pin = p.PA3; | 16 | let mut pin = p.PA3; |
| 17 | 17 | ||
| 18 | let mut vrefint = adc.enable_vrefint(); | 18 | let mut vrefint = adc.enable_vrefint(); |
| 19 | let vrefint_sample = adc.blocking_read(&mut vrefint); | 19 | let vrefint_sample = adc.blocking_read(&mut vrefint, SampleTime::CYCLES112); |
| 20 | let convert_to_millivolts = |sample| { | 20 | let convert_to_millivolts = |sample| { |
| 21 | // From http://www.st.com/resource/en/datasheet/DM00273119.pdf | 21 | // From http://www.st.com/resource/en/datasheet/DM00273119.pdf |
| 22 | // 6.3.27 Reference voltage | 22 | // 6.3.27 Reference voltage |
| @@ -26,7 +26,7 @@ async fn main(_spawner: Spawner) { | |||
| 26 | }; | 26 | }; |
| 27 | 27 | ||
| 28 | loop { | 28 | loop { |
| 29 | let v = adc.blocking_read(&mut pin); | 29 | let v = adc.blocking_read(&mut pin, SampleTime::CYCLES112); |
| 30 | info!("--> {} - {} mV", v, convert_to_millivolts(v)); | 30 | info!("--> {} - {} mV", v, convert_to_millivolts(v)); |
| 31 | Timer::after_millis(100).await; | 31 | Timer::after_millis(100).await; |
| 32 | } | 32 | } |
diff --git a/examples/stm32g0/src/bin/adc.rs b/examples/stm32g0/src/bin/adc.rs index 7d8653ef2..972e43b55 100644 --- a/examples/stm32g0/src/bin/adc.rs +++ b/examples/stm32g0/src/bin/adc.rs | |||
| @@ -13,11 +13,10 @@ async fn main(_spawner: Spawner) { | |||
| 13 | info!("Hello World!"); | 13 | info!("Hello World!"); |
| 14 | 14 | ||
| 15 | let mut adc = Adc::new_with_clock(p.ADC1, Clock::Async { div: Presc::DIV1 }); | 15 | let mut adc = Adc::new_with_clock(p.ADC1, Clock::Async { div: Presc::DIV1 }); |
| 16 | adc.set_sample_time(SampleTime::CYCLES79_5); | ||
| 17 | let mut pin = p.PA1; | 16 | let mut pin = p.PA1; |
| 18 | 17 | ||
| 19 | let mut vrefint = adc.enable_vrefint(); | 18 | let mut vrefint = adc.enable_vrefint(); |
| 20 | let vrefint_sample = adc.blocking_read(&mut vrefint); | 19 | let vrefint_sample = adc.blocking_read(&mut vrefint, SampleTime::CYCLES79_5); |
| 21 | let convert_to_millivolts = |sample| { | 20 | let convert_to_millivolts = |sample| { |
| 22 | // From https://www.st.com/resource/en/datasheet/stm32g031g8.pdf | 21 | // From https://www.st.com/resource/en/datasheet/stm32g031g8.pdf |
| 23 | // 6.3.3 Embedded internal reference voltage | 22 | // 6.3.3 Embedded internal reference voltage |
| @@ -27,7 +26,7 @@ async fn main(_spawner: Spawner) { | |||
| 27 | }; | 26 | }; |
| 28 | 27 | ||
| 29 | loop { | 28 | loop { |
| 30 | let v = adc.blocking_read(&mut pin); | 29 | let v = adc.blocking_read(&mut pin, SampleTime::CYCLES79_5); |
| 31 | info!("--> {} - {} mV", v, convert_to_millivolts(v)); | 30 | info!("--> {} - {} mV", v, convert_to_millivolts(v)); |
| 32 | Timer::after_millis(100).await; | 31 | Timer::after_millis(100).await; |
| 33 | } | 32 | } |
diff --git a/examples/stm32g0/src/bin/adc_oversampling.rs b/examples/stm32g0/src/bin/adc_oversampling.rs index 834d1cd4a..aa8b1771b 100644 --- a/examples/stm32g0/src/bin/adc_oversampling.rs +++ b/examples/stm32g0/src/bin/adc_oversampling.rs | |||
| @@ -7,7 +7,7 @@ | |||
| 7 | 7 | ||
| 8 | use defmt::*; | 8 | use defmt::*; |
| 9 | use embassy_executor::Spawner; | 9 | use embassy_executor::Spawner; |
| 10 | use embassy_stm32::adc::{Adc, Clock, Ovsr, Ovss, Presc, SampleTime}; | 10 | use embassy_stm32::adc::{Adc, AdcConfig, Clock, Ovsr, Ovss, Presc, SampleTime}; |
| 11 | use embassy_time::Timer; | 11 | use embassy_time::Timer; |
| 12 | use {defmt_rtt as _, panic_probe as _}; | 12 | use {defmt_rtt as _, panic_probe as _}; |
| 13 | 13 | ||
| @@ -16,16 +16,17 @@ async fn main(_spawner: Spawner) { | |||
| 16 | let p = embassy_stm32::init(Default::default()); | 16 | let p = embassy_stm32::init(Default::default()); |
| 17 | info!("Adc oversample test"); | 17 | info!("Adc oversample test"); |
| 18 | 18 | ||
| 19 | let mut adc = Adc::new_with_clock(p.ADC1, Clock::Async { div: Presc::DIV1 }); | 19 | let mut config = AdcConfig::default(); |
| 20 | adc.set_sample_time(SampleTime::CYCLES1_5); | 20 | config.clock = Some(Clock::Async { div: Presc::DIV1 }); |
| 21 | let mut pin = p.PA1; | 21 | config.oversampling_ratio = Some(Ovsr::MUL16); |
| 22 | config.oversampling_shift = Some(Ovss::NO_SHIFT); | ||
| 23 | config.oversampling_enable = Some(true); | ||
| 22 | 24 | ||
| 23 | adc.set_oversampling_ratio(Ovsr::MUL16); | 25 | let mut adc = Adc::new_with_config(p.ADC1, config); |
| 24 | adc.set_oversampling_shift(Ovss::NO_SHIFT); | 26 | let mut pin = p.PA1; |
| 25 | adc.oversampling_enable(true); | ||
| 26 | 27 | ||
| 27 | loop { | 28 | loop { |
| 28 | let v = adc.blocking_read(&mut pin); | 29 | let v = adc.blocking_read(&mut pin, SampleTime::CYCLES1_5); |
| 29 | info!("--> {} ", v); //max 65520 = 0xFFF0 | 30 | info!("--> {} ", v); //max 65520 = 0xFFF0 |
| 30 | Timer::after_millis(100).await; | 31 | Timer::after_millis(100).await; |
| 31 | } | 32 | } |
diff --git a/examples/stm32g4/src/bin/adc.rs b/examples/stm32g4/src/bin/adc.rs index 920142a18..2149e0748 100644 --- a/examples/stm32g4/src/bin/adc.rs +++ b/examples/stm32g4/src/bin/adc.rs | |||
| @@ -28,12 +28,16 @@ async fn main(_spawner: Spawner) { | |||
| 28 | let mut p = embassy_stm32::init(config); | 28 | let mut p = embassy_stm32::init(config); |
| 29 | info!("Hello World!"); | 29 | info!("Hello World!"); |
| 30 | 30 | ||
| 31 | let mut adc = Adc::new(p.ADC2); | 31 | let mut adc = Adc::new(p.ADC2, Default::default()); |
| 32 | adc.set_sample_time(SampleTime::CYCLES24_5); | 32 | |
| 33 | let mut adc_temp = Adc::new(p.ADC1, Default::default()); | ||
| 34 | let mut temperature = adc_temp.enable_temperature(); | ||
| 33 | 35 | ||
| 34 | loop { | 36 | loop { |
| 35 | let measured = adc.blocking_read(&mut p.PA7); | 37 | let measured = adc.blocking_read(&mut p.PA7, SampleTime::CYCLES24_5); |
| 38 | let temperature = adc_temp.blocking_read(&mut temperature, SampleTime::CYCLES24_5); | ||
| 36 | info!("measured: {}", measured); | 39 | info!("measured: {}", measured); |
| 40 | info!("temperature: {}", temperature); | ||
| 37 | Timer::after_millis(500).await; | 41 | Timer::after_millis(500).await; |
| 38 | } | 42 | } |
| 39 | } | 43 | } |
diff --git a/examples/stm32g4/src/bin/adc_differential.rs b/examples/stm32g4/src/bin/adc_differential.rs index 301f0da84..6dedf88d6 100644 --- a/examples/stm32g4/src/bin/adc_differential.rs +++ b/examples/stm32g4/src/bin/adc_differential.rs | |||
| @@ -30,17 +30,16 @@ async fn main(_spawner: Spawner) { | |||
| 30 | config.rcc.mux.adc12sel = mux::Adcsel::SYS; | 30 | config.rcc.mux.adc12sel = mux::Adcsel::SYS; |
| 31 | config.rcc.sys = Sysclk::PLL1_R; | 31 | config.rcc.sys = Sysclk::PLL1_R; |
| 32 | } | 32 | } |
| 33 | let mut p = embassy_stm32::init(config); | 33 | let p = embassy_stm32::init(config); |
| 34 | 34 | ||
| 35 | let mut adc = Adc::new(p.ADC1); | 35 | let mut adc = Adc::new(p.ADC1, Default::default()); |
| 36 | adc.set_sample_time(SampleTime::CYCLES247_5); | 36 | let mut differential_channel = (p.PA0, p.PA1); |
| 37 | adc.set_differential(&mut p.PA0, true); //p:pa0,n:pa1 | ||
| 38 | 37 | ||
| 39 | // can also use | 38 | // can also use |
| 40 | // adc.set_differential_channel(1, true); | 39 | // adc.set_differential_channel(1, true); |
| 41 | info!("adc initialized"); | 40 | info!("adc initialized"); |
| 42 | loop { | 41 | loop { |
| 43 | let measured = adc.blocking_read(&mut p.PA0); | 42 | let measured = adc.blocking_read(&mut differential_channel, SampleTime::CYCLES247_5); |
| 44 | info!("data: {}", measured); | 43 | info!("data: {}", measured); |
| 45 | Timer::after_millis(500).await; | 44 | Timer::after_millis(500).await; |
| 46 | } | 45 | } |
diff --git a/examples/stm32g4/src/bin/adc_dma.rs b/examples/stm32g4/src/bin/adc_dma.rs index ef8b0c3c2..478b6b2ca 100644 --- a/examples/stm32g4/src/bin/adc_dma.rs +++ b/examples/stm32g4/src/bin/adc_dma.rs | |||
| @@ -33,7 +33,7 @@ async fn main(_spawner: Spawner) { | |||
| 33 | 33 | ||
| 34 | info!("Hello World!"); | 34 | info!("Hello World!"); |
| 35 | 35 | ||
| 36 | let mut adc = Adc::new(p.ADC1); | 36 | let mut adc = Adc::new(p.ADC1, Default::default()); |
| 37 | 37 | ||
| 38 | let mut dma = p.DMA1_CH1; | 38 | let mut dma = p.DMA1_CH1; |
| 39 | let mut vrefint_channel = adc.enable_vrefint().degrade_adc(); | 39 | let mut vrefint_channel = adc.enable_vrefint().degrade_adc(); |
diff --git a/examples/stm32g4/src/bin/adc_injected_and_regular.rs b/examples/stm32g4/src/bin/adc_injected_and_regular.rs index 3ae2ff064..1e97fa925 100644 --- a/examples/stm32g4/src/bin/adc_injected_and_regular.rs +++ b/examples/stm32g4/src/bin/adc_injected_and_regular.rs | |||
| @@ -77,7 +77,7 @@ async fn main(_spawner: embassy_executor::Spawner) { | |||
| 77 | pwm.set_mms2(Mms2::UPDATE); | 77 | pwm.set_mms2(Mms2::UPDATE); |
| 78 | 78 | ||
| 79 | // Configure regular conversions with DMA | 79 | // Configure regular conversions with DMA |
| 80 | let adc1 = Adc::new(p.ADC1); | 80 | let adc1 = Adc::new(p.ADC1, Default::default()); |
| 81 | 81 | ||
| 82 | let vrefint_channel = adc1.enable_vrefint().degrade_adc(); | 82 | let vrefint_channel = adc1.enable_vrefint().degrade_adc(); |
| 83 | let pa0 = p.PC1.degrade_adc(); | 83 | let pa0 = p.PC1.degrade_adc(); |
diff --git a/examples/stm32g4/src/bin/adc_oversampling.rs b/examples/stm32g4/src/bin/adc_oversampling.rs index 1e464183a..87ffea4be 100644 --- a/examples/stm32g4/src/bin/adc_oversampling.rs +++ b/examples/stm32g4/src/bin/adc_oversampling.rs | |||
| @@ -9,7 +9,7 @@ use defmt::*; | |||
| 9 | use embassy_executor::Spawner; | 9 | use embassy_executor::Spawner; |
| 10 | use embassy_stm32::Config; | 10 | use embassy_stm32::Config; |
| 11 | use embassy_stm32::adc::vals::{Rovsm, Trovs}; | 11 | use embassy_stm32::adc::vals::{Rovsm, Trovs}; |
| 12 | use embassy_stm32::adc::{Adc, SampleTime}; | 12 | use embassy_stm32::adc::{Adc, AdcConfig, SampleTime}; |
| 13 | use embassy_time::Timer; | 13 | use embassy_time::Timer; |
| 14 | use {defmt_rtt as _, panic_probe as _}; | 14 | use {defmt_rtt as _, panic_probe as _}; |
| 15 | 15 | ||
| @@ -32,8 +32,8 @@ async fn main(_spawner: Spawner) { | |||
| 32 | } | 32 | } |
| 33 | let mut p = embassy_stm32::init(config); | 33 | let mut p = embassy_stm32::init(config); |
| 34 | 34 | ||
| 35 | let mut adc = Adc::new(p.ADC1); | 35 | let mut config = AdcConfig::default(); |
| 36 | adc.set_sample_time(SampleTime::CYCLES6_5); | 36 | |
| 37 | // From https://www.st.com/resource/en/reference_manual/rm0440-stm32g4-series-advanced-armbased-32bit-mcus-stmicroelectronics.pdf | 37 | // From https://www.st.com/resource/en/reference_manual/rm0440-stm32g4-series-advanced-armbased-32bit-mcus-stmicroelectronics.pdf |
| 38 | // page652 Oversampler | 38 | // page652 Oversampler |
| 39 | // Table 172. Maximum output results vs N and M. Grayed values indicates truncation | 39 | // Table 172. Maximum output results vs N and M. Grayed values indicates truncation |
| @@ -45,12 +45,14 @@ async fn main(_spawner: Spawner) { | |||
| 45 | // 0x05 oversampling ratio X64 | 45 | // 0x05 oversampling ratio X64 |
| 46 | // 0x06 oversampling ratio X128 | 46 | // 0x06 oversampling ratio X128 |
| 47 | // 0x07 oversampling ratio X256 | 47 | // 0x07 oversampling ratio X256 |
| 48 | adc.set_oversampling_ratio(0x03); // ratio X3 | 48 | config.oversampling_ratio = Some(0x03); // ratio X3 |
| 49 | adc.set_oversampling_shift(0b0000); // no shift | 49 | config.oversampling_shift = Some(0b0000); // no shift |
| 50 | adc.enable_regular_oversampling_mode(Rovsm::RESUMED, Trovs::AUTOMATIC, true); | 50 | config.oversampling_mode = Some((Rovsm::RESUMED, Trovs::AUTOMATIC, true)); |
| 51 | |||
| 52 | let mut adc = Adc::new(p.ADC1, config); | ||
| 51 | 53 | ||
| 52 | loop { | 54 | loop { |
| 53 | let measured = adc.blocking_read(&mut p.PA0); | 55 | let measured = adc.blocking_read(&mut p.PA0, SampleTime::CYCLES6_5); |
| 54 | info!("data: 0x{:X}", measured); //max 0xFFF0 -> 65520 | 56 | info!("data: 0x{:X}", measured); //max 0xFFF0 -> 65520 |
| 55 | Timer::after_millis(500).await; | 57 | Timer::after_millis(500).await; |
| 56 | } | 58 | } |
diff --git a/examples/stm32h5/src/bin/adc.rs b/examples/stm32h5/src/bin/adc.rs index 0566320d4..c919b1a95 100644 --- a/examples/stm32h5/src/bin/adc.rs +++ b/examples/stm32h5/src/bin/adc.rs | |||
| @@ -45,14 +45,12 @@ async fn main(_spawner: Spawner) { | |||
| 45 | 45 | ||
| 46 | let mut adc = Adc::new(p.ADC1); | 46 | let mut adc = Adc::new(p.ADC1); |
| 47 | 47 | ||
| 48 | adc.set_sample_time(SampleTime::CYCLES24_5); | ||
| 49 | |||
| 50 | let mut vrefint_channel = adc.enable_vrefint(); | 48 | let mut vrefint_channel = adc.enable_vrefint(); |
| 51 | 49 | ||
| 52 | loop { | 50 | loop { |
| 53 | let vrefint = adc.blocking_read(&mut vrefint_channel); | 51 | let vrefint = adc.blocking_read(&mut vrefint_channel, SampleTime::CYCLES24_5); |
| 54 | info!("vrefint: {}", vrefint); | 52 | info!("vrefint: {}", vrefint); |
| 55 | let measured = adc.blocking_read(&mut p.PA0); | 53 | let measured = adc.blocking_read(&mut p.PA0, SampleTime::CYCLES24_5); |
| 56 | info!("measured: {}", measured); | 54 | info!("measured: {}", measured); |
| 57 | Timer::after_millis(500).await; | 55 | Timer::after_millis(500).await; |
| 58 | } | 56 | } |
diff --git a/examples/stm32h5/src/bin/adc_dma.rs b/examples/stm32h5/src/bin/adc_dma.rs index fb9fcbc5c..2138257f7 100644 --- a/examples/stm32h5/src/bin/adc_dma.rs +++ b/examples/stm32h5/src/bin/adc_dma.rs | |||
| @@ -6,7 +6,7 @@ use embassy_executor::Spawner; | |||
| 6 | use embassy_stm32::adc::{self, Adc, AdcChannel, RxDma, SampleTime}; | 6 | use embassy_stm32::adc::{self, Adc, AdcChannel, RxDma, SampleTime}; |
| 7 | use embassy_stm32::peripherals::{ADC1, ADC2, GPDMA1_CH0, GPDMA1_CH1, PA0, PA1, PA2, PA3}; | 7 | use embassy_stm32::peripherals::{ADC1, ADC2, GPDMA1_CH0, GPDMA1_CH1, PA0, PA1, PA2, PA3}; |
| 8 | use embassy_stm32::{Config, Peri}; | 8 | use embassy_stm32::{Config, Peri}; |
| 9 | use embassy_time::Instant; | 9 | use embassy_time::{Duration, Instant, Ticker}; |
| 10 | use {defmt_rtt as _, panic_probe as _}; | 10 | use {defmt_rtt as _, panic_probe as _}; |
| 11 | 11 | ||
| 12 | #[embassy_executor::main] | 12 | #[embassy_executor::main] |
| @@ -76,6 +76,9 @@ async fn adc_task<'a, T: adc::Instance>( | |||
| 76 | let mut pin1 = pin1.degrade_adc(); | 76 | let mut pin1 = pin1.degrade_adc(); |
| 77 | let mut pin2 = pin2.degrade_adc(); | 77 | let mut pin2 = pin2.degrade_adc(); |
| 78 | 78 | ||
| 79 | info!("adc init"); | ||
| 80 | |||
| 81 | let mut ticker = Ticker::every(Duration::from_millis(500)); | ||
| 79 | let mut tic = Instant::now(); | 82 | let mut tic = Instant::now(); |
| 80 | let mut buffer = [0u16; 512]; | 83 | let mut buffer = [0u16; 512]; |
| 81 | loop { | 84 | loop { |
| @@ -84,11 +87,13 @@ async fn adc_task<'a, T: adc::Instance>( | |||
| 84 | adc.read( | 87 | adc.read( |
| 85 | dma.reborrow(), | 88 | dma.reborrow(), |
| 86 | [(&mut pin1, SampleTime::CYCLES2_5), (&mut pin2, SampleTime::CYCLES2_5)].into_iter(), | 89 | [(&mut pin1, SampleTime::CYCLES2_5), (&mut pin2, SampleTime::CYCLES2_5)].into_iter(), |
| 87 | &mut buffer, | 90 | &mut buffer[0..2], |
| 88 | ) | 91 | ) |
| 89 | .await; | 92 | .await; |
| 90 | let toc = Instant::now(); | 93 | let toc = Instant::now(); |
| 91 | info!("\n adc1: {} dt = {}", buffer[0..16], (toc - tic).as_micros()); | 94 | info!("\n adc1: {} dt = {}", buffer[0..16], (toc - tic).as_micros()); |
| 92 | tic = toc; | 95 | tic = toc; |
| 96 | |||
| 97 | ticker.next().await; | ||
| 93 | } | 98 | } |
| 94 | } | 99 | } |
diff --git a/examples/stm32h7/src/bin/adc.rs b/examples/stm32h7/src/bin/adc.rs index a53c9d8d5..fc45541bf 100644 --- a/examples/stm32h7/src/bin/adc.rs +++ b/examples/stm32h7/src/bin/adc.rs | |||
| @@ -46,14 +46,12 @@ async fn main(_spawner: Spawner) { | |||
| 46 | 46 | ||
| 47 | let mut adc = Adc::new(p.ADC3); | 47 | let mut adc = Adc::new(p.ADC3); |
| 48 | 48 | ||
| 49 | adc.set_sample_time(SampleTime::CYCLES32_5); | ||
| 50 | |||
| 51 | let mut vrefint_channel = adc.enable_vrefint(); | 49 | let mut vrefint_channel = adc.enable_vrefint(); |
| 52 | 50 | ||
| 53 | loop { | 51 | loop { |
| 54 | let vrefint = adc.blocking_read(&mut vrefint_channel); | 52 | let vrefint = adc.blocking_read(&mut vrefint_channel, SampleTime::CYCLES32_5); |
| 55 | info!("vrefint: {}", vrefint); | 53 | info!("vrefint: {}", vrefint); |
| 56 | let measured = adc.blocking_read(&mut p.PC0); | 54 | let measured = adc.blocking_read(&mut p.PC0, SampleTime::CYCLES32_5); |
| 57 | info!("measured: {}", measured); | 55 | info!("measured: {}", measured); |
| 58 | Timer::after_millis(500).await; | 56 | Timer::after_millis(500).await; |
| 59 | } | 57 | } |
diff --git a/examples/stm32l0/src/bin/adc.rs b/examples/stm32l0/src/bin/adc.rs index 9dd09bc45..83be74ed9 100644 --- a/examples/stm32l0/src/bin/adc.rs +++ b/examples/stm32l0/src/bin/adc.rs | |||
| @@ -19,11 +19,10 @@ async fn main(_spawner: Spawner) { | |||
| 19 | info!("Hello World!"); | 19 | info!("Hello World!"); |
| 20 | 20 | ||
| 21 | let mut adc = Adc::new(p.ADC1, Irqs); | 21 | let mut adc = Adc::new(p.ADC1, Irqs); |
| 22 | adc.set_sample_time(SampleTime::CYCLES79_5); | ||
| 23 | let mut pin = p.PA1; | 22 | let mut pin = p.PA1; |
| 24 | 23 | ||
| 25 | let mut vrefint = adc.enable_vref(); | 24 | let mut vrefint = adc.enable_vref(); |
| 26 | let vrefint_sample = adc.read(&mut vrefint).await; | 25 | let vrefint_sample = adc.read(&mut vrefint, SampleTime::CYCLES79_5).await; |
| 27 | let convert_to_millivolts = |sample| { | 26 | let convert_to_millivolts = |sample| { |
| 28 | // From https://www.st.com/resource/en/datasheet/stm32l051c6.pdf | 27 | // From https://www.st.com/resource/en/datasheet/stm32l051c6.pdf |
| 29 | // 6.3.3 Embedded internal reference voltage | 28 | // 6.3.3 Embedded internal reference voltage |
| @@ -33,7 +32,7 @@ async fn main(_spawner: Spawner) { | |||
| 33 | }; | 32 | }; |
| 34 | 33 | ||
| 35 | loop { | 34 | loop { |
| 36 | let v = adc.read(&mut pin).await; | 35 | let v = adc.read(&mut pin, SampleTime::CYCLES79_5).await; |
| 37 | info!("--> {} - {} mV", v, convert_to_millivolts(v)); | 36 | info!("--> {} - {} mV", v, convert_to_millivolts(v)); |
| 38 | Timer::after_millis(100).await; | 37 | Timer::after_millis(100).await; |
| 39 | } | 38 | } |
diff --git a/examples/stm32l4/src/bin/adc.rs b/examples/stm32l4/src/bin/adc.rs index 40e907940..42766a5e3 100644 --- a/examples/stm32l4/src/bin/adc.rs +++ b/examples/stm32l4/src/bin/adc.rs | |||
| @@ -3,7 +3,7 @@ | |||
| 3 | 3 | ||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_stm32::Config; | 5 | use embassy_stm32::Config; |
| 6 | use embassy_stm32::adc::{Adc, Resolution}; | 6 | use embassy_stm32::adc::{Adc, AdcConfig, Resolution, SampleTime}; |
| 7 | use {defmt_rtt as _, panic_probe as _}; | 7 | use {defmt_rtt as _, panic_probe as _}; |
| 8 | 8 | ||
| 9 | #[cortex_m_rt::entry] | 9 | #[cortex_m_rt::entry] |
| @@ -17,13 +17,16 @@ fn main() -> ! { | |||
| 17 | } | 17 | } |
| 18 | let p = embassy_stm32::init(config); | 18 | let p = embassy_stm32::init(config); |
| 19 | 19 | ||
| 20 | let mut adc = Adc::new(p.ADC1); | 20 | let mut config = AdcConfig::default(); |
| 21 | config.resolution = Some(Resolution::BITS8); | ||
| 22 | |||
| 23 | let mut adc = Adc::new_with_config(p.ADC1, config); | ||
| 21 | //adc.enable_vref(); | 24 | //adc.enable_vref(); |
| 22 | adc.set_resolution(Resolution::BITS8); | 25 | |
| 23 | let mut channel = p.PC0; | 26 | let mut channel = p.PC0; |
| 24 | 27 | ||
| 25 | loop { | 28 | loop { |
| 26 | let v = adc.blocking_read(&mut channel); | 29 | let v = adc.blocking_read(&mut channel, SampleTime::from_bits(0)); |
| 27 | info!("--> {}", v); | 30 | info!("--> {}", v); |
| 28 | } | 31 | } |
| 29 | } | 32 | } |
diff --git a/examples/stm32l4/src/bin/adc_dma.rs b/examples/stm32l4/src/bin/adc_dma.rs index 7a9200edd..550da95a4 100644 --- a/examples/stm32l4/src/bin/adc_dma.rs +++ b/examples/stm32l4/src/bin/adc_dma.rs | |||
| @@ -4,7 +4,7 @@ | |||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_stm32::Config; | 6 | use embassy_stm32::Config; |
| 7 | use embassy_stm32::adc::{Adc, AdcChannel, SampleTime}; | 7 | use embassy_stm32::adc::{Adc, AdcChannel, RegularConversionMode, SampleTime}; |
| 8 | use {defmt_rtt as _, panic_probe as _}; | 8 | use {defmt_rtt as _, panic_probe as _}; |
| 9 | 9 | ||
| 10 | const DMA_BUF_LEN: usize = 512; | 10 | const DMA_BUF_LEN: usize = 512; |
| @@ -20,19 +20,16 @@ async fn main(_spawner: Spawner) { | |||
| 20 | } | 20 | } |
| 21 | let p = embassy_stm32::init(config); | 21 | let p = embassy_stm32::init(config); |
| 22 | 22 | ||
| 23 | let mut adc = Adc::new(p.ADC1); | 23 | let adc = Adc::new(p.ADC1); |
| 24 | let mut adc_pin0 = p.PA0.degrade_adc(); | 24 | let adc_pin0 = p.PA0.degrade_adc(); |
| 25 | let mut adc_pin1 = p.PA1.degrade_adc(); | 25 | let adc_pin1 = p.PA1.degrade_adc(); |
| 26 | let mut adc_dma_buf = [0u16; DMA_BUF_LEN]; | 26 | let mut adc_dma_buf = [0u16; DMA_BUF_LEN]; |
| 27 | let mut measurements = [0u16; DMA_BUF_LEN / 2]; | 27 | let mut measurements = [0u16; DMA_BUF_LEN / 2]; |
| 28 | let mut ring_buffered_adc = adc.into_ring_buffered( | 28 | let mut ring_buffered_adc = adc.into_ring_buffered( |
| 29 | p.DMA1_CH1, | 29 | p.DMA1_CH1, |
| 30 | &mut adc_dma_buf, | 30 | &mut adc_dma_buf, |
| 31 | [ | 31 | [(adc_pin0, SampleTime::CYCLES640_5), (adc_pin1, SampleTime::CYCLES640_5)].into_iter(), |
| 32 | (&mut adc_pin0, SampleTime::CYCLES640_5), | 32 | RegularConversionMode::Continuous, |
| 33 | (&mut adc_pin1, SampleTime::CYCLES640_5), | ||
| 34 | ] | ||
| 35 | .into_iter(), | ||
| 36 | ); | 33 | ); |
| 37 | 34 | ||
| 38 | info!("starting measurement loop"); | 35 | info!("starting measurement loop"); |
diff --git a/examples/stm32l5/src/bin/usb_hid_mouse.rs b/examples/stm32l5/src/bin/usb_hid_mouse.rs index b721f5b2e..d8f2de941 100644 --- a/examples/stm32l5/src/bin/usb_hid_mouse.rs +++ b/examples/stm32l5/src/bin/usb_hid_mouse.rs | |||
| @@ -1,6 +1,8 @@ | |||
| 1 | #![no_std] | 1 | #![no_std] |
| 2 | #![no_main] | 2 | #![no_main] |
| 3 | 3 | ||
| 4 | use core::sync::atomic::{AtomicU8, Ordering}; | ||
| 5 | |||
| 4 | use defmt::*; | 6 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 7 | use embassy_executor::Spawner; |
| 6 | use embassy_futures::join::join; | 8 | use embassy_futures::join::join; |
| @@ -8,7 +10,9 @@ use embassy_stm32::usb::Driver; | |||
| 8 | use embassy_stm32::{Config, bind_interrupts, peripherals, usb}; | 10 | use embassy_stm32::{Config, bind_interrupts, peripherals, usb}; |
| 9 | use embassy_time::Timer; | 11 | use embassy_time::Timer; |
| 10 | use embassy_usb::Builder; | 12 | use embassy_usb::Builder; |
| 11 | use embassy_usb::class::hid::{HidWriter, ReportId, RequestHandler, State}; | 13 | use embassy_usb::class::hid::{ |
| 14 | HidBootProtocol, HidProtocolMode, HidSubclass, HidWriter, ReportId, RequestHandler, State, | ||
| 15 | }; | ||
| 12 | use embassy_usb::control::OutResponse; | 16 | use embassy_usb::control::OutResponse; |
| 13 | use usbd_hid::descriptor::{MouseReport, SerializedDescriptor}; | 17 | use usbd_hid::descriptor::{MouseReport, SerializedDescriptor}; |
| 14 | use {defmt_rtt as _, panic_probe as _}; | 18 | use {defmt_rtt as _, panic_probe as _}; |
| @@ -17,6 +21,8 @@ bind_interrupts!(struct Irqs { | |||
| 17 | USB_FS => usb::InterruptHandler<peripherals::USB>; | 21 | USB_FS => usb::InterruptHandler<peripherals::USB>; |
| 18 | }); | 22 | }); |
| 19 | 23 | ||
| 24 | static HID_PROTOCOL_MODE: AtomicU8 = AtomicU8::new(HidProtocolMode::Boot as u8); | ||
| 25 | |||
| 20 | #[embassy_executor::main] | 26 | #[embassy_executor::main] |
| 21 | async fn main(_spawner: Spawner) { | 27 | async fn main(_spawner: Spawner) { |
| 22 | let mut config = Config::default(); | 28 | let mut config = Config::default(); |
| @@ -48,6 +54,10 @@ async fn main(_spawner: Spawner) { | |||
| 48 | config.serial_number = Some("12345678"); | 54 | config.serial_number = Some("12345678"); |
| 49 | config.max_power = 100; | 55 | config.max_power = 100; |
| 50 | config.max_packet_size_0 = 64; | 56 | config.max_packet_size_0 = 64; |
| 57 | config.composite_with_iads = false; | ||
| 58 | config.device_class = 0; | ||
| 59 | config.device_sub_class = 0; | ||
| 60 | config.device_protocol = 0; | ||
| 51 | 61 | ||
| 52 | // Create embassy-usb DeviceBuilder using the driver and config. | 62 | // Create embassy-usb DeviceBuilder using the driver and config. |
| 53 | // It needs some buffers for building the descriptors. | 63 | // It needs some buffers for building the descriptors. |
| @@ -73,6 +83,8 @@ async fn main(_spawner: Spawner) { | |||
| 73 | request_handler: Some(&mut request_handler), | 83 | request_handler: Some(&mut request_handler), |
| 74 | poll_ms: 60, | 84 | poll_ms: 60, |
| 75 | max_packet_size: 8, | 85 | max_packet_size: 8, |
| 86 | hid_subclass: HidSubclass::Boot, | ||
| 87 | hid_boot_protocol: HidBootProtocol::Mouse, | ||
| 76 | }; | 88 | }; |
| 77 | 89 | ||
| 78 | let mut writer = HidWriter::<_, 5>::new(&mut builder, &mut state, config); | 90 | let mut writer = HidWriter::<_, 5>::new(&mut builder, &mut state, config); |
| @@ -90,16 +102,26 @@ async fn main(_spawner: Spawner) { | |||
| 90 | Timer::after_millis(500).await; | 102 | Timer::after_millis(500).await; |
| 91 | 103 | ||
| 92 | y = -y; | 104 | y = -y; |
| 93 | let report = MouseReport { | 105 | |
| 94 | buttons: 0, | 106 | if HID_PROTOCOL_MODE.load(Ordering::Relaxed) == HidProtocolMode::Boot as u8 { |
| 95 | x: 0, | 107 | let buttons = 0u8; |
| 96 | y, | 108 | let x = 0i8; |
| 97 | wheel: 0, | 109 | match writer.write(&[buttons, x as u8, y as u8]).await { |
| 98 | pan: 0, | 110 | Ok(()) => {} |
| 99 | }; | 111 | Err(e) => warn!("Failed to send boot report: {:?}", e), |
| 100 | match writer.write_serialize(&report).await { | 112 | } |
| 101 | Ok(()) => {} | 113 | } else { |
| 102 | Err(e) => warn!("Failed to send report: {:?}", e), | 114 | let report = MouseReport { |
| 115 | buttons: 0, | ||
| 116 | x: 0, | ||
| 117 | y, | ||
| 118 | wheel: 0, | ||
| 119 | pan: 0, | ||
| 120 | }; | ||
| 121 | match writer.write_serialize(&report).await { | ||
| 122 | Ok(()) => {} | ||
| 123 | Err(e) => warn!("Failed to send report: {:?}", e), | ||
| 124 | } | ||
| 103 | } | 125 | } |
| 104 | } | 126 | } |
| 105 | }; | 127 | }; |
| @@ -122,6 +144,18 @@ impl RequestHandler for MyRequestHandler { | |||
| 122 | OutResponse::Accepted | 144 | OutResponse::Accepted |
| 123 | } | 145 | } |
| 124 | 146 | ||
| 147 | fn get_protocol(&self) -> HidProtocolMode { | ||
| 148 | let protocol = HidProtocolMode::from(HID_PROTOCOL_MODE.load(Ordering::Relaxed)); | ||
| 149 | info!("The current HID protocol mode is: {}", protocol); | ||
| 150 | protocol | ||
| 151 | } | ||
| 152 | |||
| 153 | fn set_protocol(&mut self, protocol: HidProtocolMode) -> OutResponse { | ||
| 154 | info!("Switching to HID protocol mode: {}", protocol); | ||
| 155 | HID_PROTOCOL_MODE.store(protocol as u8, Ordering::Relaxed); | ||
| 156 | OutResponse::Accepted | ||
| 157 | } | ||
| 158 | |||
| 125 | fn set_idle_ms(&mut self, id: Option<ReportId>, dur: u32) { | 159 | fn set_idle_ms(&mut self, id: Option<ReportId>, dur: u32) { |
| 126 | info!("Set idle rate for {:?} to {:?}", id, dur); | 160 | info!("Set idle rate for {:?} to {:?}", id, dur); |
| 127 | } | 161 | } |
diff --git a/examples/stm32n6/.cargo/config.toml b/examples/stm32n6/.cargo/config.toml new file mode 100644 index 000000000..2fdd70649 --- /dev/null +++ b/examples/stm32n6/.cargo/config.toml | |||
| @@ -0,0 +1,8 @@ | |||
| 1 | [target.thumbv8m.main-none-eabihf] | ||
| 2 | runner = 'probe-rs run --chip STM32N657' | ||
| 3 | |||
| 4 | [build] | ||
| 5 | target = "thumbv8m.main-none-eabihf" | ||
| 6 | |||
| 7 | [env] | ||
| 8 | DEFMT_LOG = "trace" | ||
diff --git a/examples/stm32n6/Cargo.toml b/examples/stm32n6/Cargo.toml new file mode 100644 index 000000000..5ed28eed1 --- /dev/null +++ b/examples/stm32n6/Cargo.toml | |||
| @@ -0,0 +1,78 @@ | |||
| 1 | [package] | ||
| 2 | edition = "2021" | ||
| 3 | name = "embassy-stm32n6-examples" | ||
| 4 | version = "0.1.0" | ||
| 5 | license = "MIT OR Apache-2.0" | ||
| 6 | publish = false | ||
| 7 | |||
| 8 | [dependencies] | ||
| 9 | # Change stm32h563zi to your chip name, if necessary. | ||
| 10 | embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = ["defmt", "stm32n657x0", "time-driver-any", "exti", "unstable-pac"] } | ||
| 11 | embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } | ||
| 12 | embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } | ||
| 13 | embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } | ||
| 14 | embassy-net = { version = "0.7.1", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", "proto-ipv6"] } | ||
| 15 | embassy-usb = { version = "0.5.1", path = "../../embassy-usb", features = ["defmt"] } | ||
| 16 | embassy-futures = { version = "0.1.2", path = "../../embassy-futures" } | ||
| 17 | |||
| 18 | defmt = "1.0.1" | ||
| 19 | defmt-rtt = "1.0.0" | ||
| 20 | |||
| 21 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } | ||
| 22 | cortex-m-rt = "0.7.0" | ||
| 23 | embedded-hal = "0.2.6" | ||
| 24 | embedded-hal-1 = { package = "embedded-hal", version = "1.0" } | ||
| 25 | embedded-hal-async = { version = "1.0" } | ||
| 26 | embedded-io-async = { version = "0.6.1" } | ||
| 27 | embedded-nal-async = "0.8.0" | ||
| 28 | panic-probe = { version = "1.0.0", features = ["print-defmt"] } | ||
| 29 | heapless = { version = "0.8", default-features = false } | ||
| 30 | critical-section = "1.1" | ||
| 31 | micromath = "2.0.0" | ||
| 32 | stm32-fmc = "0.3.0" | ||
| 33 | embedded-storage = "0.3.1" | ||
| 34 | static_cell = "2" | ||
| 35 | |||
| 36 | |||
| 37 | # cargo build/run | ||
| 38 | [profile.dev] | ||
| 39 | codegen-units = 1 | ||
| 40 | debug = 2 | ||
| 41 | debug-assertions = true # <- | ||
| 42 | incremental = false | ||
| 43 | opt-level = 3 # <- | ||
| 44 | overflow-checks = true # <- | ||
| 45 | |||
| 46 | # cargo test | ||
| 47 | [profile.test] | ||
| 48 | codegen-units = 1 | ||
| 49 | debug = 2 | ||
| 50 | debug-assertions = true # <- | ||
| 51 | incremental = false | ||
| 52 | opt-level = 3 # <- | ||
| 53 | overflow-checks = true # <- | ||
| 54 | |||
| 55 | # cargo build/run --release | ||
| 56 | [profile.release] | ||
| 57 | codegen-units = 1 | ||
| 58 | debug = 2 | ||
| 59 | debug-assertions = false # <- | ||
| 60 | incremental = false | ||
| 61 | lto = 'fat' | ||
| 62 | opt-level = 3 # <- | ||
| 63 | overflow-checks = false # <- | ||
| 64 | |||
| 65 | # cargo test --release | ||
| 66 | [profile.bench] | ||
| 67 | codegen-units = 1 | ||
| 68 | debug = 2 | ||
| 69 | debug-assertions = false # <- | ||
| 70 | incremental = false | ||
| 71 | lto = 'fat' | ||
| 72 | opt-level = 3 # <- | ||
| 73 | overflow-checks = false # <- | ||
| 74 | |||
| 75 | [package.metadata.embassy] | ||
| 76 | build = [ | ||
| 77 | { target = "thumbv8m.main-none-eabihf", artifact-dir = "out/examples/stm32n6" } | ||
| 78 | ] | ||
diff --git a/examples/stm32n6/build.rs b/examples/stm32n6/build.rs new file mode 100644 index 000000000..8cd32d7ed --- /dev/null +++ b/examples/stm32n6/build.rs | |||
| @@ -0,0 +1,5 @@ | |||
| 1 | fn main() { | ||
| 2 | println!("cargo:rustc-link-arg-bins=--nmagic"); | ||
| 3 | println!("cargo:rustc-link-arg-bins=-Tlink.x"); | ||
| 4 | println!("cargo:rustc-link-arg-bins=-Tdefmt.x"); | ||
| 5 | } | ||
diff --git a/examples/stm32n6/memory.x b/examples/stm32n6/memory.x new file mode 100644 index 000000000..59f127adc --- /dev/null +++ b/examples/stm32n6/memory.x | |||
| @@ -0,0 +1,5 @@ | |||
| 1 | MEMORY | ||
| 2 | { | ||
| 3 | FLASH : ORIGIN = 0x34180400, LENGTH = 255K | ||
| 4 | RAM : ORIGIN = 0x341C0000, LENGTH = 256K | ||
| 5 | } | ||
diff --git a/examples/stm32n6/src/bin/blinky.rs b/examples/stm32n6/src/bin/blinky.rs new file mode 100644 index 000000000..018967f08 --- /dev/null +++ b/examples/stm32n6/src/bin/blinky.rs | |||
| @@ -0,0 +1,36 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | use defmt::*; | ||
| 5 | use embassy_executor::Spawner; | ||
| 6 | use embassy_stm32::exti::ExtiInput; | ||
| 7 | use embassy_stm32::gpio::{Level, Output, Pull, Speed}; | ||
| 8 | use embassy_time::Timer; | ||
| 9 | use {defmt_rtt as _, panic_probe as _}; | ||
| 10 | |||
| 11 | #[embassy_executor::task] | ||
| 12 | async fn button_task(mut p: ExtiInput<'static>) { | ||
| 13 | loop { | ||
| 14 | p.wait_for_any_edge().await; | ||
| 15 | info!("button pressed!"); | ||
| 16 | } | ||
| 17 | } | ||
| 18 | |||
| 19 | #[embassy_executor::main] | ||
| 20 | async fn main(spawner: Spawner) { | ||
| 21 | let p = embassy_stm32::init(Default::default()); | ||
| 22 | info!("Hello World!"); | ||
| 23 | |||
| 24 | let mut led = Output::new(p.PG10, Level::High, Speed::Low); | ||
| 25 | let button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Up); | ||
| 26 | |||
| 27 | spawner.spawn(button_task(button).unwrap()); | ||
| 28 | |||
| 29 | loop { | ||
| 30 | led.set_high(); | ||
| 31 | Timer::after_millis(500).await; | ||
| 32 | |||
| 33 | led.set_low(); | ||
| 34 | Timer::after_millis(500).await; | ||
| 35 | } | ||
| 36 | } | ||
diff --git a/examples/stm32u0/src/bin/adc.rs b/examples/stm32u0/src/bin/adc.rs index 32a54299d..53bd37303 100644 --- a/examples/stm32u0/src/bin/adc.rs +++ b/examples/stm32u0/src/bin/adc.rs | |||
| @@ -3,7 +3,7 @@ | |||
| 3 | 3 | ||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_stm32::Config; | 5 | use embassy_stm32::Config; |
| 6 | use embassy_stm32::adc::{Adc, Resolution}; | 6 | use embassy_stm32::adc::{Adc, AdcConfig, Resolution, SampleTime}; |
| 7 | use embassy_time::Duration; | 7 | use embassy_time::Duration; |
| 8 | use {defmt_rtt as _, panic_probe as _}; | 8 | use {defmt_rtt as _, panic_probe as _}; |
| 9 | 9 | ||
| @@ -18,12 +18,13 @@ fn main() -> ! { | |||
| 18 | } | 18 | } |
| 19 | let p = embassy_stm32::init(config); | 19 | let p = embassy_stm32::init(config); |
| 20 | 20 | ||
| 21 | let mut adc = Adc::new(p.ADC1); | 21 | let mut config = AdcConfig::default(); |
| 22 | adc.set_resolution(Resolution::BITS8); | 22 | config.resolution = Some(Resolution::BITS8); |
| 23 | let mut adc = Adc::new_with_config(p.ADC1, config); | ||
| 23 | let mut channel = p.PC0; | 24 | let mut channel = p.PC0; |
| 24 | 25 | ||
| 25 | loop { | 26 | loop { |
| 26 | let v = adc.blocking_read(&mut channel); | 27 | let v = adc.blocking_read(&mut channel, SampleTime::CYCLES12_5); |
| 27 | info!("--> {}", v); | 28 | info!("--> {}", v); |
| 28 | embassy_time::block_for(Duration::from_millis(200)); | 29 | embassy_time::block_for(Duration::from_millis(200)); |
| 29 | } | 30 | } |
diff --git a/examples/stm32u5/src/bin/adc.rs b/examples/stm32u5/src/bin/adc.rs index 91e33053e..ad59c0bea 100644 --- a/examples/stm32u5/src/bin/adc.rs +++ b/examples/stm32u5/src/bin/adc.rs | |||
| @@ -2,8 +2,7 @@ | |||
| 2 | #![no_main] | 2 | #![no_main] |
| 3 | 3 | ||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_stm32::adc; | 5 | use embassy_stm32::adc::{self, Adc, AdcChannel, AdcConfig, SampleTime, adc4}; |
| 6 | use embassy_stm32::adc::{AdcChannel, adc4}; | ||
| 7 | use {defmt_rtt as _, panic_probe as _}; | 6 | use {defmt_rtt as _, panic_probe as _}; |
| 8 | 7 | ||
| 9 | #[embassy_executor::main] | 8 | #[embassy_executor::main] |
| @@ -13,56 +12,55 @@ async fn main(_spawner: embassy_executor::Spawner) { | |||
| 13 | let mut p = embassy_stm32::init(config); | 12 | let mut p = embassy_stm32::init(config); |
| 14 | 13 | ||
| 15 | // **** ADC1 init **** | 14 | // **** ADC1 init **** |
| 16 | let mut adc1 = adc::Adc::new(p.ADC1); | 15 | let mut config = AdcConfig::default(); |
| 16 | config.averaging = Some(adc::Averaging::Samples1024); | ||
| 17 | config.resolution = Some(adc::Resolution::BITS14); | ||
| 18 | let mut adc1 = Adc::new_with_config(p.ADC1, config); | ||
| 17 | let mut adc1_pin1 = p.PA3; // A0 on nucleo u5a5 | 19 | let mut adc1_pin1 = p.PA3; // A0 on nucleo u5a5 |
| 18 | let mut adc1_pin2 = p.PA2; // A1 | 20 | let mut adc1_pin2 = p.PA2; // A1 |
| 19 | adc1.set_resolution(adc::Resolution::BITS14); | ||
| 20 | adc1.set_averaging(adc::Averaging::Samples1024); | ||
| 21 | adc1.set_sample_time(adc::SampleTime::CYCLES160_5); | ||
| 22 | let max1 = adc::resolution_to_max_count(adc::Resolution::BITS14); | 21 | let max1 = adc::resolution_to_max_count(adc::Resolution::BITS14); |
| 23 | 22 | ||
| 24 | // **** ADC2 init **** | 23 | // **** ADC2 init **** |
| 25 | let mut adc2 = adc::Adc::new(p.ADC2); | 24 | let mut config = AdcConfig::default(); |
| 25 | config.averaging = Some(adc::Averaging::Samples1024); | ||
| 26 | config.resolution = Some(adc::Resolution::BITS14); | ||
| 27 | let mut adc2 = Adc::new_with_config(p.ADC2, config); | ||
| 26 | let mut adc2_pin1 = p.PC3; // A2 | 28 | let mut adc2_pin1 = p.PC3; // A2 |
| 27 | let mut adc2_pin2 = p.PB0; // A3 | 29 | let mut adc2_pin2 = p.PB0; // A3 |
| 28 | adc2.set_resolution(adc::Resolution::BITS14); | ||
| 29 | adc2.set_averaging(adc::Averaging::Samples1024); | ||
| 30 | adc2.set_sample_time(adc::SampleTime::CYCLES160_5); | ||
| 31 | let max2 = adc::resolution_to_max_count(adc::Resolution::BITS14); | 30 | let max2 = adc::resolution_to_max_count(adc::Resolution::BITS14); |
| 32 | 31 | ||
| 33 | // **** ADC4 init **** | 32 | // **** ADC4 init **** |
| 34 | let mut adc4 = adc4::Adc4::new(p.ADC4); | 33 | let mut adc4 = Adc::new_adc4(p.ADC4); |
| 35 | let mut adc4_pin1 = p.PC1; // A4 | 34 | let mut adc4_pin1 = p.PC1; // A4 |
| 36 | let mut adc4_pin2 = p.PC0; // A5 | 35 | let mut adc4_pin2 = p.PC0; // A5 |
| 37 | adc4.set_resolution(adc4::Resolution::BITS12); | 36 | adc4.set_resolution_adc4(adc4::Resolution::BITS12); |
| 38 | adc4.set_averaging(adc4::Averaging::Samples256); | 37 | adc4.set_averaging_adc4(adc4::Averaging::Samples256); |
| 39 | adc4.set_sample_time(adc4::SampleTime::CYCLES1_5); | ||
| 40 | let max4 = adc4::resolution_to_max_count(adc4::Resolution::BITS12); | 38 | let max4 = adc4::resolution_to_max_count(adc4::Resolution::BITS12); |
| 41 | 39 | ||
| 42 | // **** ADC1 blocking read **** | 40 | // **** ADC1 blocking read **** |
| 43 | let raw: u16 = adc1.blocking_read(&mut adc1_pin1); | 41 | let raw: u16 = adc1.blocking_read(&mut adc1_pin1, SampleTime::CYCLES160_5); |
| 44 | let volt: f32 = 3.3 * raw as f32 / max1 as f32; | 42 | let volt: f32 = 3.3 * raw as f32 / max1 as f32; |
| 45 | info!("Read adc1 pin 1 {}", volt); | 43 | info!("Read adc1 pin 1 {}", volt); |
| 46 | 44 | ||
| 47 | let raw: u16 = adc1.blocking_read(&mut adc1_pin2); | 45 | let raw: u16 = adc1.blocking_read(&mut adc1_pin2, SampleTime::CYCLES160_5); |
| 48 | let volt: f32 = 3.3 * raw as f32 / max1 as f32; | 46 | let volt: f32 = 3.3 * raw as f32 / max1 as f32; |
| 49 | info!("Read adc1 pin 2 {}", volt); | 47 | info!("Read adc1 pin 2 {}", volt); |
| 50 | 48 | ||
| 51 | // **** ADC2 blocking read **** | 49 | // **** ADC2 blocking read **** |
| 52 | let raw: u16 = adc2.blocking_read(&mut adc2_pin1); | 50 | let raw: u16 = adc2.blocking_read(&mut adc2_pin1, SampleTime::CYCLES160_5); |
| 53 | let volt: f32 = 3.3 * raw as f32 / max2 as f32; | 51 | let volt: f32 = 3.3 * raw as f32 / max2 as f32; |
| 54 | info!("Read adc2 pin 1 {}", volt); | 52 | info!("Read adc2 pin 1 {}", volt); |
| 55 | 53 | ||
| 56 | let raw: u16 = adc2.blocking_read(&mut adc2_pin2); | 54 | let raw: u16 = adc2.blocking_read(&mut adc2_pin2, SampleTime::CYCLES160_5); |
| 57 | let volt: f32 = 3.3 * raw as f32 / max2 as f32; | 55 | let volt: f32 = 3.3 * raw as f32 / max2 as f32; |
| 58 | info!("Read adc2 pin 2 {}", volt); | 56 | info!("Read adc2 pin 2 {}", volt); |
| 59 | 57 | ||
| 60 | // **** ADC4 blocking read **** | 58 | // **** ADC4 blocking read **** |
| 61 | let raw: u16 = adc4.blocking_read(&mut adc4_pin1); | 59 | let raw: u16 = adc4.blocking_read(&mut adc4_pin1, adc4::SampleTime::CYCLES1_5); |
| 62 | let volt: f32 = 3.3 * raw as f32 / max4 as f32; | 60 | let volt: f32 = 3.3 * raw as f32 / max4 as f32; |
| 63 | info!("Read adc4 pin 1 {}", volt); | 61 | info!("Read adc4 pin 1 {}", volt); |
| 64 | 62 | ||
| 65 | let raw: u16 = adc4.blocking_read(&mut adc4_pin2); | 63 | let raw: u16 = adc4.blocking_read(&mut adc4_pin2, adc4::SampleTime::CYCLES1_5); |
| 66 | let volt: f32 = 3.3 * raw as f32 / max4 as f32; | 64 | let volt: f32 = 3.3 * raw as f32 / max4 as f32; |
| 67 | info!("Read adc4 pin 2 {}", volt); | 65 | info!("Read adc4 pin 2 {}", volt); |
| 68 | 66 | ||
| @@ -97,11 +95,14 @@ async fn main(_spawner: embassy_executor::Spawner) { | |||
| 97 | // The channels must be in ascending order and can't repeat for ADC4 | 95 | // The channels must be in ascending order and can't repeat for ADC4 |
| 98 | adc4.read( | 96 | adc4.read( |
| 99 | p.GPDMA1_CH1.reborrow(), | 97 | p.GPDMA1_CH1.reborrow(), |
| 100 | [&mut degraded42, &mut degraded41].into_iter(), | 98 | [ |
| 99 | (&mut degraded42, adc4::SampleTime::CYCLES1_5), | ||
| 100 | (&mut degraded41, adc4::SampleTime::CYCLES1_5), | ||
| 101 | ] | ||
| 102 | .into_iter(), | ||
| 101 | &mut measurements, | 103 | &mut measurements, |
| 102 | ) | 104 | ) |
| 103 | .await | 105 | .await; |
| 104 | .unwrap(); | ||
| 105 | let volt2: f32 = 3.3 * measurements[0] as f32 / max4 as f32; | 106 | let volt2: f32 = 3.3 * measurements[0] as f32 / max4 as f32; |
| 106 | let volt1: f32 = 3.3 * measurements[1] as f32 / max4 as f32; | 107 | let volt1: f32 = 3.3 * measurements[1] as f32 / max4 as f32; |
| 107 | info!("Async read 4 pin 1 {}", volt1); | 108 | info!("Async read 4 pin 1 {}", volt1); |
diff --git a/examples/stm32wba/src/bin/adc.rs b/examples/stm32wba/src/bin/adc.rs index 8c80470b8..ade3f5d6a 100644 --- a/examples/stm32wba/src/bin/adc.rs +++ b/examples/stm32wba/src/bin/adc.rs | |||
| @@ -2,7 +2,7 @@ | |||
| 2 | #![no_main] | 2 | #![no_main] |
| 3 | 3 | ||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_stm32::adc::{AdcChannel, adc4}; | 5 | use embassy_stm32::adc::{Adc, AdcChannel, SampleTime, adc4}; |
| 6 | use {defmt_rtt as _, panic_probe as _}; | 6 | use {defmt_rtt as _, panic_probe as _}; |
| 7 | 7 | ||
| 8 | #[embassy_executor::main] | 8 | #[embassy_executor::main] |
| @@ -12,20 +12,20 @@ async fn main(_spawner: embassy_executor::Spawner) { | |||
| 12 | let mut p = embassy_stm32::init(config); | 12 | let mut p = embassy_stm32::init(config); |
| 13 | 13 | ||
| 14 | // **** ADC4 init **** | 14 | // **** ADC4 init **** |
| 15 | let mut adc4 = adc4::Adc4::new(p.ADC4); | 15 | let mut adc4 = Adc::new_adc4(p.ADC4); |
| 16 | let mut adc4_pin1 = p.PA0; // A4 | 16 | let mut adc4_pin1 = p.PA0; // A4 |
| 17 | let mut adc4_pin2 = p.PA1; // A5 | 17 | let mut adc4_pin2 = p.PA1; // A5 |
| 18 | adc4.set_resolution(adc4::Resolution::BITS12); | 18 | adc4.set_resolution_adc4(adc4::Resolution::BITS12); |
| 19 | adc4.set_averaging(adc4::Averaging::Samples256); | 19 | adc4.set_averaging_adc4(adc4::Averaging::Samples256); |
| 20 | adc4.set_sample_time(adc4::SampleTime::CYCLES1_5); | 20 | |
| 21 | let max4 = adc4::resolution_to_max_count(adc4::Resolution::BITS12); | 21 | let max4 = adc4::resolution_to_max_count(adc4::Resolution::BITS12); |
| 22 | 22 | ||
| 23 | // **** ADC4 blocking read **** | 23 | // **** ADC4 blocking read **** |
| 24 | let raw: u16 = adc4.blocking_read(&mut adc4_pin1); | 24 | let raw: u16 = adc4.blocking_read(&mut adc4_pin1, adc4::SampleTime::CYCLES1_5); |
| 25 | let volt: f32 = 3.0 * raw as f32 / max4 as f32; | 25 | let volt: f32 = 3.0 * raw as f32 / max4 as f32; |
| 26 | info!("Read adc4 pin 1 {}", volt); | 26 | info!("Read adc4 pin 1 {}", volt); |
| 27 | 27 | ||
| 28 | let raw: u16 = adc4.blocking_read(&mut adc4_pin2); | 28 | let raw: u16 = adc4.blocking_read(&mut adc4_pin2, adc4::SampleTime::CYCLES1_5); |
| 29 | let volt: f32 = 3.3 * raw as f32 / max4 as f32; | 29 | let volt: f32 = 3.3 * raw as f32 / max4 as f32; |
| 30 | info!("Read adc4 pin 2 {}", volt); | 30 | info!("Read adc4 pin 2 {}", volt); |
| 31 | 31 | ||
| @@ -37,11 +37,14 @@ async fn main(_spawner: embassy_executor::Spawner) { | |||
| 37 | // The channels must be in ascending order and can't repeat for ADC4 | 37 | // The channels must be in ascending order and can't repeat for ADC4 |
| 38 | adc4.read( | 38 | adc4.read( |
| 39 | p.GPDMA1_CH1.reborrow(), | 39 | p.GPDMA1_CH1.reborrow(), |
| 40 | [&mut degraded42, &mut degraded41].into_iter(), | 40 | [ |
| 41 | (&mut degraded42, SampleTime::CYCLES12_5), | ||
| 42 | (&mut degraded41, SampleTime::CYCLES12_5), | ||
| 43 | ] | ||
| 44 | .into_iter(), | ||
| 41 | &mut measurements, | 45 | &mut measurements, |
| 42 | ) | 46 | ) |
| 43 | .await | 47 | .await; |
| 44 | .unwrap(); | ||
| 45 | let volt2: f32 = 3.3 * measurements[0] as f32 / max4 as f32; | 48 | let volt2: f32 = 3.3 * measurements[0] as f32 / max4 as f32; |
| 46 | let volt1: f32 = 3.0 * measurements[1] as f32 / max4 as f32; | 49 | let volt1: f32 = 3.0 * measurements[1] as f32 / max4 as f32; |
| 47 | info!("Async read 4 pin 1 {}", volt1); | 50 | info!("Async read 4 pin 1 {}", volt1); |
diff --git a/examples/stm32wba6/src/bin/adc.rs b/examples/stm32wba6/src/bin/adc.rs index 8c80470b8..9d1f39419 100644 --- a/examples/stm32wba6/src/bin/adc.rs +++ b/examples/stm32wba6/src/bin/adc.rs | |||
| @@ -2,7 +2,7 @@ | |||
| 2 | #![no_main] | 2 | #![no_main] |
| 3 | 3 | ||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_stm32::adc::{AdcChannel, adc4}; | 5 | use embassy_stm32::adc::{Adc, AdcChannel, SampleTime, adc4}; |
| 6 | use {defmt_rtt as _, panic_probe as _}; | 6 | use {defmt_rtt as _, panic_probe as _}; |
| 7 | 7 | ||
| 8 | #[embassy_executor::main] | 8 | #[embassy_executor::main] |
| @@ -12,20 +12,19 @@ async fn main(_spawner: embassy_executor::Spawner) { | |||
| 12 | let mut p = embassy_stm32::init(config); | 12 | let mut p = embassy_stm32::init(config); |
| 13 | 13 | ||
| 14 | // **** ADC4 init **** | 14 | // **** ADC4 init **** |
| 15 | let mut adc4 = adc4::Adc4::new(p.ADC4); | 15 | let mut adc4 = Adc::new_adc4(p.ADC4); |
| 16 | let mut adc4_pin1 = p.PA0; // A4 | 16 | let mut adc4_pin1 = p.PA0; // A4 |
| 17 | let mut adc4_pin2 = p.PA1; // A5 | 17 | let mut adc4_pin2 = p.PA1; // A5 |
| 18 | adc4.set_resolution(adc4::Resolution::BITS12); | 18 | adc4.set_resolution_adc4(adc4::Resolution::BITS12); |
| 19 | adc4.set_averaging(adc4::Averaging::Samples256); | 19 | adc4.set_averaging_adc4(adc4::Averaging::Samples256); |
| 20 | adc4.set_sample_time(adc4::SampleTime::CYCLES1_5); | ||
| 21 | let max4 = adc4::resolution_to_max_count(adc4::Resolution::BITS12); | 20 | let max4 = adc4::resolution_to_max_count(adc4::Resolution::BITS12); |
| 22 | 21 | ||
| 23 | // **** ADC4 blocking read **** | 22 | // **** ADC4 blocking read **** |
| 24 | let raw: u16 = adc4.blocking_read(&mut adc4_pin1); | 23 | let raw: u16 = adc4.blocking_read(&mut adc4_pin1, adc4::SampleTime::CYCLES1_5); |
| 25 | let volt: f32 = 3.0 * raw as f32 / max4 as f32; | 24 | let volt: f32 = 3.0 * raw as f32 / max4 as f32; |
| 26 | info!("Read adc4 pin 1 {}", volt); | 25 | info!("Read adc4 pin 1 {}", volt); |
| 27 | 26 | ||
| 28 | let raw: u16 = adc4.blocking_read(&mut adc4_pin2); | 27 | let raw: u16 = adc4.blocking_read(&mut adc4_pin2, adc4::SampleTime::CYCLES1_5); |
| 29 | let volt: f32 = 3.3 * raw as f32 / max4 as f32; | 28 | let volt: f32 = 3.3 * raw as f32 / max4 as f32; |
| 30 | info!("Read adc4 pin 2 {}", volt); | 29 | info!("Read adc4 pin 2 {}", volt); |
| 31 | 30 | ||
| @@ -37,11 +36,14 @@ async fn main(_spawner: embassy_executor::Spawner) { | |||
| 37 | // The channels must be in ascending order and can't repeat for ADC4 | 36 | // The channels must be in ascending order and can't repeat for ADC4 |
| 38 | adc4.read( | 37 | adc4.read( |
| 39 | p.GPDMA1_CH1.reborrow(), | 38 | p.GPDMA1_CH1.reborrow(), |
| 40 | [&mut degraded42, &mut degraded41].into_iter(), | 39 | [ |
| 40 | (&mut degraded42, SampleTime::CYCLES12_5), | ||
| 41 | (&mut degraded41, SampleTime::CYCLES12_5), | ||
| 42 | ] | ||
| 43 | .into_iter(), | ||
| 41 | &mut measurements, | 44 | &mut measurements, |
| 42 | ) | 45 | ) |
| 43 | .await | 46 | .await; |
| 44 | .unwrap(); | ||
| 45 | let volt2: f32 = 3.3 * measurements[0] as f32 / max4 as f32; | 47 | let volt2: f32 = 3.3 * measurements[0] as f32 / max4 as f32; |
| 46 | let volt1: f32 = 3.0 * measurements[1] as f32 / max4 as f32; | 48 | let volt1: f32 = 3.0 * measurements[1] as f32 / max4 as f32; |
| 47 | info!("Async read 4 pin 1 {}", volt1); | 49 | info!("Async read 4 pin 1 {}", volt1); |
diff --git a/examples/stm32wl/src/bin/adc.rs b/examples/stm32wl/src/bin/adc.rs index 6b21b086b..adabe0df8 100644 --- a/examples/stm32wl/src/bin/adc.rs +++ b/examples/stm32wl/src/bin/adc.rs | |||
| @@ -18,11 +18,11 @@ async fn main(_spawner: Spawner) { | |||
| 18 | info!("Hello World!"); | 18 | info!("Hello World!"); |
| 19 | 19 | ||
| 20 | let mut adc = Adc::new_with_clock(p.ADC1, Clock::Sync { div: CkModePclk::DIV1 }); | 20 | let mut adc = Adc::new_with_clock(p.ADC1, Clock::Sync { div: CkModePclk::DIV1 }); |
| 21 | adc.set_sample_time(SampleTime::CYCLES79_5); | 21 | |
| 22 | let mut pin = p.PB2; | 22 | let mut pin = p.PB2; |
| 23 | 23 | ||
| 24 | let mut vrefint = adc.enable_vrefint(); | 24 | let mut vrefint = adc.enable_vrefint(); |
| 25 | let vrefint_sample = adc.blocking_read(&mut vrefint); | 25 | let vrefint_sample = adc.blocking_read(&mut vrefint, SampleTime::CYCLES79_5); |
| 26 | let convert_to_millivolts = |sample| { | 26 | let convert_to_millivolts = |sample| { |
| 27 | // From https://www.st.com/resource/en/datasheet/stm32g031g8.pdf | 27 | // From https://www.st.com/resource/en/datasheet/stm32g031g8.pdf |
| 28 | // 6.3.3 Embedded internal reference voltage | 28 | // 6.3.3 Embedded internal reference voltage |
| @@ -32,7 +32,7 @@ async fn main(_spawner: Spawner) { | |||
| 32 | }; | 32 | }; |
| 33 | 33 | ||
| 34 | loop { | 34 | loop { |
| 35 | let v = adc.blocking_read(&mut pin); | 35 | let v = adc.blocking_read(&mut pin, SampleTime::CYCLES79_5); |
| 36 | info!("--> {} - {} mV", v, convert_to_millivolts(v)); | 36 | info!("--> {} - {} mV", v, convert_to_millivolts(v)); |
| 37 | Timer::after_millis(100).await; | 37 | Timer::after_millis(100).await; |
| 38 | } | 38 | } |
diff --git a/examples/stm32wle5/src/bin/adc.rs b/examples/stm32wle5/src/bin/adc.rs index 8b830a1e6..4e0574d97 100644 --- a/examples/stm32wle5/src/bin/adc.rs +++ b/examples/stm32wle5/src/bin/adc.rs | |||
| @@ -73,11 +73,10 @@ async fn async_main(_spawner: Spawner) { | |||
| 73 | info!("Hello World!"); | 73 | info!("Hello World!"); |
| 74 | 74 | ||
| 75 | let mut adc = Adc::new(p.ADC1); | 75 | let mut adc = Adc::new(p.ADC1); |
| 76 | adc.set_sample_time(SampleTime::CYCLES79_5); | ||
| 77 | let mut pin = p.PA10; | 76 | let mut pin = p.PA10; |
| 78 | 77 | ||
| 79 | let mut vrefint = adc.enable_vrefint(); | 78 | let mut vrefint = adc.enable_vrefint(); |
| 80 | let vrefint_sample = adc.blocking_read(&mut vrefint); | 79 | let vrefint_sample = adc.blocking_read(&mut vrefint, SampleTime::CYCLES79_5); |
| 81 | let convert_to_millivolts = |sample| { | 80 | let convert_to_millivolts = |sample| { |
| 82 | // From https://www.st.com/resource/en/datasheet/stm32g031g8.pdf | 81 | // From https://www.st.com/resource/en/datasheet/stm32g031g8.pdf |
| 83 | // 6.3.3 Embedded internal reference voltage | 82 | // 6.3.3 Embedded internal reference voltage |
| @@ -87,7 +86,7 @@ async fn async_main(_spawner: Spawner) { | |||
| 87 | }; | 86 | }; |
| 88 | 87 | ||
| 89 | loop { | 88 | loop { |
| 90 | let v = adc.blocking_read(&mut pin); | 89 | let v = adc.blocking_read(&mut pin, SampleTime::CYCLES79_5); |
| 91 | info!("--> {} - {} mV", v, convert_to_millivolts(v)); | 90 | info!("--> {} - {} mV", v, convert_to_millivolts(v)); |
| 92 | Timer::after_secs(1).await; | 91 | Timer::after_secs(1).await; |
| 93 | } | 92 | } |
