aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.helix/languages.toml11
-rw-r--r--embassy-nrf/CHANGELOG.md4
-rw-r--r--embassy-nrf/src/chips/nrf54l15_app.rs2
-rw-r--r--embassy-nrf/src/gpiote.rs68
-rw-r--r--embassy-rp/CHANGELOG.md2
-rw-r--r--embassy-rp/src/pio/instr.rs16
-rw-r--r--embassy-stm32/CHANGELOG.md11
-rw-r--r--embassy-stm32/Cargo.toml32
-rw-r--r--embassy-stm32/build.rs391
-rw-r--r--embassy-stm32/src/adc/adc4.rs485
-rw-r--r--embassy-stm32/src/adc/c0.rs532
-rw-r--r--embassy-stm32/src/adc/f1.rs43
-rw-r--r--embassy-stm32/src/adc/f3.rs48
-rw-r--r--embassy-stm32/src/adc/f3_v1_1.rs5
-rw-r--r--embassy-stm32/src/adc/g4.rs867
-rw-r--r--embassy-stm32/src/adc/injected.rs6
-rw-r--r--embassy-stm32/src/adc/mod.rs355
-rw-r--r--embassy-stm32/src/adc/ringbuffered.rs12
-rw-r--r--embassy-stm32/src/adc/v1.rs53
-rw-r--r--embassy-stm32/src/adc/v2.rs372
-rw-r--r--embassy-stm32/src/adc/v3.rs984
-rw-r--r--embassy-stm32/src/adc/v4.rs555
-rw-r--r--embassy-stm32/src/adc/watchdog_v1.rs6
-rw-r--r--embassy-stm32/src/dma/gpdma/mod.rs1
-rw-r--r--embassy-stm32/src/dma/mod.rs4
-rw-r--r--embassy-stm32/src/dsihost.rs17
-rw-r--r--embassy-stm32/src/dts/tsel.rs17
-rw-r--r--embassy-stm32/src/eth/generic_phy.rs14
-rw-r--r--embassy-stm32/src/exti.rs32
-rw-r--r--embassy-stm32/src/flash/c.rs131
-rw-r--r--embassy-stm32/src/flash/common.rs8
-rw-r--r--embassy-stm32/src/flash/g.rs5
-rw-r--r--embassy-stm32/src/flash/mod.rs3
-rw-r--r--embassy-stm32/src/gpio.rs44
-rw-r--r--embassy-stm32/src/i2c/v2.rs713
-rw-r--r--embassy-stm32/src/lib.rs32
-rw-r--r--embassy-stm32/src/opamp.rs13
-rw-r--r--embassy-stm32/src/rcc/bd.rs110
-rw-r--r--embassy-stm32/src/rcc/mco.rs10
-rw-r--r--embassy-stm32/src/rcc/mod.rs1
-rw-r--r--embassy-stm32/src/rcc/n6.rs1046
-rw-r--r--embassy-stm32/src/timer/simple_pwm.rs48
-rw-r--r--embassy-stm32/src/ucpd.rs3
-rw-r--r--embassy-usb/CHANGELOG.md2
-rw-r--r--embassy-usb/src/class/hid.rs101
-rw-r--r--examples/nrf52840/src/bin/gpiote_channel.rs8
-rw-r--r--examples/nrf52840/src/bin/usb_hid_keyboard.rs58
-rw-r--r--examples/nrf52840/src/bin/usb_hid_mouse.rs56
-rw-r--r--examples/nrf5340/src/bin/gpiote_channel.rs8
-rw-r--r--examples/nrf54l15/memory.x2
-rw-r--r--examples/nrf54l15/src/bin/gpiote_channel.rs8
-rw-r--r--examples/rp/src/bin/usb_hid_keyboard.rs86
-rwxr-xr-xexamples/rp/src/bin/usb_hid_mouse.rs60
-rw-r--r--examples/rp235x/src/bin/usb_hid_keyboard.rs85
-rw-r--r--examples/stm32c0/src/bin/adc.rs26
-rw-r--r--examples/stm32f0/Cargo.toml1
-rw-r--r--examples/stm32f0/src/bin/adc-watchdog.rs6
-rw-r--r--examples/stm32f0/src/bin/adc.rs5
-rw-r--r--examples/stm32f0/src/bin/i2c_master.rs609
-rw-r--r--examples/stm32f1/src/bin/adc.rs6
-rw-r--r--examples/stm32f334/src/bin/adc.rs12
-rw-r--r--examples/stm32f334/src/bin/opamp.rs12
-rw-r--r--examples/stm32f4/src/bin/adc.rs12
-rw-r--r--examples/stm32f4/src/bin/adc_dma.rs16
-rw-r--r--examples/stm32f4/src/bin/usb_hid_keyboard.rs84
-rw-r--r--examples/stm32f4/src/bin/usb_hid_mouse.rs56
-rw-r--r--examples/stm32f469/src/bin/dsi_bsp.rs14
-rw-r--r--examples/stm32f7/src/bin/adc.rs6
-rw-r--r--examples/stm32g0/src/bin/adc.rs5
-rw-r--r--examples/stm32g0/src/bin/adc_oversampling.rs17
-rw-r--r--examples/stm32g4/src/bin/adc.rs10
-rw-r--r--examples/stm32g4/src/bin/adc_differential.rs9
-rw-r--r--examples/stm32g4/src/bin/adc_dma.rs2
-rw-r--r--examples/stm32g4/src/bin/adc_injected_and_regular.rs2
-rw-r--r--examples/stm32g4/src/bin/adc_oversampling.rs16
-rw-r--r--examples/stm32h5/src/bin/adc.rs6
-rw-r--r--examples/stm32h5/src/bin/adc_dma.rs9
-rw-r--r--examples/stm32h7/src/bin/adc.rs6
-rw-r--r--examples/stm32l0/src/bin/adc.rs5
-rw-r--r--examples/stm32l4/src/bin/adc.rs11
-rw-r--r--examples/stm32l4/src/bin/adc_dma.rs15
-rw-r--r--examples/stm32l5/src/bin/usb_hid_mouse.rs56
-rw-r--r--examples/stm32n6/.cargo/config.toml8
-rw-r--r--examples/stm32n6/Cargo.toml78
-rw-r--r--examples/stm32n6/build.rs5
-rw-r--r--examples/stm32n6/memory.x5
-rw-r--r--examples/stm32n6/src/bin/blinky.rs36
-rw-r--r--examples/stm32u0/src/bin/adc.rs9
-rw-r--r--examples/stm32u5/src/bin/adc.rs47
-rw-r--r--examples/stm32wba/src/bin/adc.rs23
-rw-r--r--examples/stm32wba6/src/bin/adc.rs22
-rw-r--r--examples/stm32wl/src/bin/adc.rs6
-rw-r--r--examples/stm32wle5/src/bin/adc.rs5
-rw-r--r--tests/stm32/src/bin/dac.rs9
-rw-r--r--tests/stm32/src/bin/dac_l1.rs11
95 files changed, 5567 insertions, 3317 deletions
diff --git a/.helix/languages.toml b/.helix/languages.toml
new file mode 100644
index 000000000..d34df4b24
--- /dev/null
+++ b/.helix/languages.toml
@@ -0,0 +1,11 @@
1[language-server.rust-analyzer.config.cargo]
2allTargets = false
3noDefaultFeatures = true
4target = "thumbv8m.main-none-eabihf"
5features = ["stm32n657x0", "time-driver-any", "unstable-pac", "exti"]
6
7[language-server.rust-analyzer.config.check]
8allTargets = false
9noDefaultFeatures = true
10target = "thumbv8m.main-none-eabihf"
11features = ["stm32n657x0", "time-driver-any", "unstable-pac", "exti"]
diff --git a/embassy-nrf/CHANGELOG.md b/embassy-nrf/CHANGELOG.md
index 72ecb116a..f6fe1e14f 100644
--- a/embassy-nrf/CHANGELOG.md
+++ b/embassy-nrf/CHANGELOG.md
@@ -23,6 +23,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
23- bugfix: Do not write to UICR from non-secure code on nrf53 23- bugfix: Do not write to UICR from non-secure code on nrf53
24- bugfix: Add delay to uart init anomaly fix 24- bugfix: Add delay to uart init anomaly fix
25- changed: `BufferedUarte::read_ready` now uses the same definition for 'empty' so following read calls will not block when true is returned 25- changed: `BufferedUarte::read_ready` now uses the same definition for 'empty' so following read calls will not block when true is returned
26- added: add `gpiote::InputChannel::wait_for_high()` and `wait_for_low()` to wait for specific signal level
27- changed: `gpiote::InputChannel::wait()` now takes a mutable reference to `self` to avoid interference from concurrent calls
28- changed: `gpiote::InputChannel::wait()` now ensures events are seen as soon as the function is called, even if the future is not polled
29- bugfix: use correct flash size for nRF54l
26 30
27## 0.8.0 - 2025-09-30 31## 0.8.0 - 2025-09-30
28 32
diff --git a/embassy-nrf/src/chips/nrf54l15_app.rs b/embassy-nrf/src/chips/nrf54l15_app.rs
index 0724f2ff6..8846717db 100644
--- a/embassy-nrf/src/chips/nrf54l15_app.rs
+++ b/embassy-nrf/src/chips/nrf54l15_app.rs
@@ -204,7 +204,7 @@ pub const FORCE_COPY_BUFFER_SIZE: usize = 1024;
204 204
205// 1.5 MB NVM 205// 1.5 MB NVM
206#[allow(unused)] 206#[allow(unused)]
207pub const FLASH_SIZE: usize = 1536 * 1024; 207pub const FLASH_SIZE: usize = 1524 * 1024;
208 208
209embassy_hal_internal::peripherals! { 209embassy_hal_internal::peripherals! {
210 // PPI 210 // PPI
diff --git a/embassy-nrf/src/gpiote.rs b/embassy-nrf/src/gpiote.rs
index 91944d8cd..d4f6668f3 100644
--- a/embassy-nrf/src/gpiote.rs
+++ b/embassy-nrf/src/gpiote.rs
@@ -349,16 +349,73 @@ impl<'d> InputChannel<'d> {
349 } 349 }
350 350
351 /// Asynchronously wait for an event in this channel. 351 /// Asynchronously wait for an event in this channel.
352 pub async fn wait(&self) { 352 ///
353 let g = self.ch.regs(); 353 /// It is possible to call this function and await the returned future later.
354 let num = self.ch.number(); 354 /// If an even occurs in the mean time, the future will immediately report ready.
355 let waker = self.ch.waker(); 355 pub fn wait(&mut self) -> impl Future<Output = ()> {
356 // NOTE: This is `-> impl Future` and not an `async fn` on purpose.
357 // Otherwise, events will only be detected starting at the first poll of the returned future.
358 Self::wait_internal(&mut self.ch)
359 }
360
361 /// Asynchronously wait for the pin to become high.
362 ///
363 /// The channel must be configured with [`InputChannelPolarity::LoToHi`] or [`InputChannelPolarity::Toggle`].
364 /// If the channel is not configured to detect rising edges, it is unspecified when the returned future completes.
365 ///
366 /// It is possible to call this function and await the returned future later.
367 /// If an even occurs in the mean time, the future will immediately report ready.
368 pub fn wait_for_high(&mut self) -> impl Future<Output = ()> {
369 // NOTE: This is `-> impl Future` and not an `async fn` on purpose.
370 // Otherwise, events will only be detected starting at the first poll of the returned future.
371
372 // Subscribe to the event before checking the pin level.
373 let wait = Self::wait_internal(&mut self.ch);
374 let pin = &self.pin;
375 async move {
376 if pin.is_high() {
377 return;
378 }
379 wait.await;
380 }
381 }
382
383 /// Asynchronously wait for the pin to become low.
384 ///
385 /// The channel must be configured with [`InputChannelPolarity::HiToLo`] or [`InputChannelPolarity::Toggle`].
386 /// If the channel is not configured to detect falling edges, it is unspecified when the returned future completes.
387 ///
388 /// It is possible to call this function and await the returned future later.
389 /// If an even occurs in the mean time, the future will immediately report ready.
390 pub fn wait_for_low(&mut self) -> impl Future<Output = ()> {
391 // NOTE: This is `-> impl Future` and not an `async fn` on purpose.
392 // Otherwise, events will only be detected starting at the first poll of the returned future.
393
394 // Subscribe to the event before checking the pin level.
395 let wait = Self::wait_internal(&mut self.ch);
396 let pin = &self.pin;
397 async move {
398 if pin.is_low() {
399 return;
400 }
401 wait.await;
402 }
403 }
404
405 /// Internal implementation for `wait()` and friends.
406 fn wait_internal(channel: &mut Peri<'_, AnyChannel>) -> impl Future<Output = ()> {
407 // NOTE: This is `-> impl Future` and not an `async fn` on purpose.
408 // Otherwise, events will only be detected starting at the first poll of the returned future.
409
410 let g = channel.regs();
411 let num = channel.number();
412 let waker = channel.waker();
356 413
357 // Enable interrupt 414 // Enable interrupt
358 g.events_in(num).write_value(0); 415 g.events_in(num).write_value(0);
359 g.intenset(INTNUM).write(|w| w.0 = 1 << num); 416 g.intenset(INTNUM).write(|w| w.0 = 1 << num);
360 417
361 poll_fn(|cx| { 418 poll_fn(move |cx| {
362 CHANNEL_WAKERS[waker].register(cx.waker()); 419 CHANNEL_WAKERS[waker].register(cx.waker());
363 420
364 if g.events_in(num).read() != 0 { 421 if g.events_in(num).read() != 0 {
@@ -367,7 +424,6 @@ impl<'d> InputChannel<'d> {
367 Poll::Pending 424 Poll::Pending
368 } 425 }
369 }) 426 })
370 .await;
371 } 427 }
372 428
373 /// Get the associated input pin. 429 /// Get the associated input pin.
diff --git a/embassy-rp/CHANGELOG.md b/embassy-rp/CHANGELOG.md
index 3b3cb5351..4b0d738a7 100644
--- a/embassy-rp/CHANGELOG.md
+++ b/embassy-rp/CHANGELOG.md
@@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
8<!-- next-header --> 8<!-- next-header -->
9## Unreleased - ReleaseDate 9## Unreleased - ReleaseDate
10 10
11- Add documentation for pio `get_x` about autopush.
11- Fix several minor typos in documentation 12- Fix several minor typos in documentation
12- Add PIO SPI 13- Add PIO SPI
13- Add PIO I2S input 14- Add PIO I2S input
@@ -114,3 +115,4 @@ Small release fixing a few gnarly bugs, upgrading is strongly recommended.
114- rename the Channel trait to Slice and the PwmPin to PwmChannel 115- rename the Channel trait to Slice and the PwmPin to PwmChannel
115- i2c: Fix race condition that appears on fast repeated transfers. 116- i2c: Fix race condition that appears on fast repeated transfers.
116- Add a basic "read to break" function 117- Add a basic "read to break" function
118
diff --git a/embassy-rp/src/pio/instr.rs b/embassy-rp/src/pio/instr.rs
index b15d507de..304ddb20a 100644
--- a/embassy-rp/src/pio/instr.rs
+++ b/embassy-rp/src/pio/instr.rs
@@ -5,6 +5,10 @@ use crate::pio::{Instance, StateMachine};
5 5
6impl<'d, PIO: Instance, const SM: usize> StateMachine<'d, PIO, SM> { 6impl<'d, PIO: Instance, const SM: usize> StateMachine<'d, PIO, SM> {
7 /// Set value of scratch register X. 7 /// Set value of scratch register X.
8 ///
9 /// SAFETY: autopull enabled else it will write undefined data.
10 /// Make sure to have setup the according configuration see
11 /// [shift_out](crate::pio::Config::shift_out) and [auto_fill](crate::pio::ShiftConfig::auto_fill).
8 pub unsafe fn set_x(&mut self, value: u32) { 12 pub unsafe fn set_x(&mut self, value: u32) {
9 const OUT: u16 = InstructionOperands::OUT { 13 const OUT: u16 = InstructionOperands::OUT {
10 destination: OutDestination::X, 14 destination: OutDestination::X,
@@ -16,6 +20,10 @@ impl<'d, PIO: Instance, const SM: usize> StateMachine<'d, PIO, SM> {
16 } 20 }
17 21
18 /// Get value of scratch register X. 22 /// Get value of scratch register X.
23 ///
24 /// SAFETY: autopush enabled else it will read undefined data.
25 /// Make sure to have setup the according configurations see
26 /// [shift_in](crate::pio::Config::shift_in) and [auto_fill](crate::pio::ShiftConfig::auto_fill).
19 pub unsafe fn get_x(&mut self) -> u32 { 27 pub unsafe fn get_x(&mut self) -> u32 {
20 const IN: u16 = InstructionOperands::IN { 28 const IN: u16 = InstructionOperands::IN {
21 source: InSource::X, 29 source: InSource::X,
@@ -27,6 +35,10 @@ impl<'d, PIO: Instance, const SM: usize> StateMachine<'d, PIO, SM> {
27 } 35 }
28 36
29 /// Set value of scratch register Y. 37 /// Set value of scratch register Y.
38 ///
39 /// SAFETY: autopull enabled else it will write undefined data.
40 /// Make sure to have setup the according configuration see
41 /// [shift_out](crate::pio::Config::shift_out) and [auto_fill](crate::pio::ShiftConfig::auto_fill).
30 pub unsafe fn set_y(&mut self, value: u32) { 42 pub unsafe fn set_y(&mut self, value: u32) {
31 const OUT: u16 = InstructionOperands::OUT { 43 const OUT: u16 = InstructionOperands::OUT {
32 destination: OutDestination::Y, 44 destination: OutDestination::Y,
@@ -38,6 +50,10 @@ impl<'d, PIO: Instance, const SM: usize> StateMachine<'d, PIO, SM> {
38 } 50 }
39 51
40 /// Get value of scratch register Y. 52 /// Get value of scratch register Y.
53 ///
54 /// SAFETY: autopush enabled else it will read undefined data.
55 /// Make sure to have setup the according configurations see
56 /// [shift_in](crate::pio::Config::shift_in) and [auto_fill](crate::pio::ShiftConfig::auto_fill).
41 pub unsafe fn get_y(&mut self) -> u32 { 57 pub unsafe fn get_y(&mut self) -> u32 {
42 const IN: u16 = InstructionOperands::IN { 58 const IN: u16 = InstructionOperands::IN {
43 source: InSource::Y, 59 source: InSource::Y,
diff --git a/embassy-stm32/CHANGELOG.md b/embassy-stm32/CHANGELOG.md
index 95d844dc8..c3b3cb3ab 100644
--- a/embassy-stm32/CHANGELOG.md
+++ b/embassy-stm32/CHANGELOG.md
@@ -8,6 +8,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
8## Unreleased - ReleaseDate 8## Unreleased - ReleaseDate
9 9
10- fix: Allow setting SAI peripheral `frame_length` to `256` 10- fix: Allow setting SAI peripheral `frame_length` to `256`
11- fix: flash erase on dual-bank STM32Gxxx
12- feat: Add support for STM32N657X0
13- feat: timer: Add 32-bit timer support to SimplePwm waveform_up method following waveform pattern ([#4717](https://github.com/embassy-rs/embassy/pull/4717))
11- feat: Add support for injected ADC measurements for g4 ([#4840](https://github.com/embassy-rs/embassy/pull/4840)) 14- feat: Add support for injected ADC measurements for g4 ([#4840](https://github.com/embassy-rs/embassy/pull/4840))
12- feat: Implement into_ring_buffered for g4 ([#4840](https://github.com/embassy-rs/embassy/pull/4840)) 15- feat: Implement into_ring_buffered for g4 ([#4840](https://github.com/embassy-rs/embassy/pull/4840))
13- feat: Add support for 13-bit address and 16-bit data SDRAM chips 16- feat: Add support for 13-bit address and 16-bit data SDRAM chips
@@ -42,7 +45,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
42- fix: sdmmc: don't wait for DBCKEND flag on sdmmc_v2 devices as it never fires (Fixes #4723) 45- fix: sdmmc: don't wait for DBCKEND flag on sdmmc_v2 devices as it never fires (Fixes #4723)
43- fix: usart: fix race condition in ringbuffered usart 46- fix: usart: fix race condition in ringbuffered usart
44- feat: Add backup_sram::init() for H5 devices to access BKPSRAM 47- feat: Add backup_sram::init() for H5 devices to access BKPSRAM
45- feat: Add I2C MultiMaster (Slave) support for I2C v1 48- feat: stm32/i2c v1: Add I2C MultiMaster (Slave) support
49- feat: stm32/i2c v2: Add transaction() and blocking_transaction() methods with contract-compliant operation merging
46- feat: stm32/fdcan: add ability to control automatic recovery from bus off ([#4821](https://github.com/embassy-rs/embassy/pull/4821)) 50- feat: stm32/fdcan: add ability to control automatic recovery from bus off ([#4821](https://github.com/embassy-rs/embassy/pull/4821))
47- low-power: update rtc api to allow reconfig 51- low-power: update rtc api to allow reconfig
48- adc: consolidate ringbuffer 52- adc: consolidate ringbuffer
@@ -52,6 +56,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
52- feat: stm32/dsi support zero parameter commands in `write_cmd` ([#4847](https://github.com/embassy-rs/embassy/pull/4847)) 56- feat: stm32/dsi support zero parameter commands in `write_cmd` ([#4847](https://github.com/embassy-rs/embassy/pull/4847))
53- feat: stm32/spi: added support for slave mode ([#4388](https://github.com/embassy-rs/embassy/pull/4388)) 57- feat: stm32/spi: added support for slave mode ([#4388](https://github.com/embassy-rs/embassy/pull/4388))
54- chore: Updated stm32-metapac and stm32-data dependencies 58- chore: Updated stm32-metapac and stm32-data dependencies
59- adc: reogranize and cleanup somewhat. require sample_time to be passed on conversion
60- fix: stm32/i2c v2 slave: prevent misaligned reads, error false positives, and incorrect counts of bytes read/written
61- feat: add flash support for c0 family ([#4874](https://github.com/embassy-rs/embassy/pull/4874))
62- fix: fixing channel numbers on vbat and vddcore for adc on adc
63- adc: adding disable to vbat
55 64
56## 0.4.0 - 2025-08-26 65## 0.4.0 - 2025-08-26
57 66
diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml
index 108321d0a..2f4f2ce51 100644
--- a/embassy-stm32/Cargo.toml
+++ b/embassy-stm32/Cargo.toml
@@ -99,6 +99,7 @@ build = [
99 {target = "thumbv8m.main-none-eabihf", features = ["defmt", "exti", "low-power", "stm32wba65ri", "time", "time-driver-any"]}, 99 {target = "thumbv8m.main-none-eabihf", features = ["defmt", "exti", "low-power", "stm32wba65ri", "time", "time-driver-any"]},
100 {target = "thumbv8m.main-none-eabihf", features = ["defmt", "exti", "stm32u5f9zj", "time", "time-driver-any"]}, 100 {target = "thumbv8m.main-none-eabihf", features = ["defmt", "exti", "stm32u5f9zj", "time", "time-driver-any"]},
101 {target = "thumbv8m.main-none-eabihf", features = ["defmt", "exti", "stm32u5g9nj", "time", "time-driver-any"]}, 101 {target = "thumbv8m.main-none-eabihf", features = ["defmt", "exti", "stm32u5g9nj", "time", "time-driver-any"]},
102 {target = "thumbv8m.main-none-eabihf", features = ["defmt", "exti", "stm32n657x0", "time", "time-driver-any"]},
102 {target = "thumbv7em-none-eabi", features = ["defmt", "exti", "stm32wb35ce", "time", "time-driver-any"]}, 103 {target = "thumbv7em-none-eabi", features = ["defmt", "exti", "stm32wb35ce", "time", "time-driver-any"]},
103 {target = "thumbv7em-none-eabi", features = ["defmt", "exti", "low-power", "stm32wb55rg", "time", "time-driver-any"]}, 104 {target = "thumbv7em-none-eabi", features = ["defmt", "exti", "low-power", "stm32wb55rg", "time", "time-driver-any"]},
104 {target = "thumbv6m-none-eabi", features = ["defmt", "exti", "stm32u031r8", "time", "time-driver-any"]}, 105 {target = "thumbv6m-none-eabi", features = ["defmt", "exti", "stm32u031r8", "time", "time-driver-any"]},
@@ -138,6 +139,7 @@ flavors = [
138 { regex_feature = "stm32wb.*", target = "thumbv7em-none-eabi" }, 139 { regex_feature = "stm32wb.*", target = "thumbv7em-none-eabi" },
139 { regex_feature = "stm32wba.*", target = "thumbv8m.main-none-eabihf" }, 140 { regex_feature = "stm32wba.*", target = "thumbv8m.main-none-eabihf" },
140 { regex_feature = "stm32wl.*", target = "thumbv7em-none-eabi" }, 141 { regex_feature = "stm32wl.*", target = "thumbv7em-none-eabi" },
142 { regex_feature = "stm32n6.*", target = "thumbv8m.main-none-eabihf" },
141] 143]
142 144
143[package.metadata.docs.rs] 145[package.metadata.docs.rs]
@@ -186,6 +188,7 @@ embedded-io = { version = "0.6.0" }
186embedded-io-async = { version = "0.6.1" } 188embedded-io-async = { version = "0.6.1" }
187chrono = { version = "^0.4", default-features = false, optional = true } 189chrono = { version = "^0.4", default-features = false, optional = true }
188bit_field = "0.10.2" 190bit_field = "0.10.2"
191trait-set = "0.3.0"
189document-features = "0.2.7" 192document-features = "0.2.7"
190 193
191static_assertions = { version = "1.1" } 194static_assertions = { version = "1.1" }
@@ -197,11 +200,11 @@ aligned = "0.4.1"
197heapless = "0.9.1" 200heapless = "0.9.1"
198 201
199#stm32-metapac = { version = "18" } 202#stm32-metapac = { version = "18" }
200stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-22374e3344a2c9150b9b3d4da45c03f398fdc54e" } 203stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-b77c8d968f53b18d6bdcd052e354b5070ec2bbc2" }
201 204
202[build-dependencies] 205[build-dependencies]
203#stm32-metapac = { version = "18", default-features = false, features = ["metadata"]} 206#stm32-metapac = { version = "18", default-features = false, features = ["metadata"]}
204stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-22374e3344a2c9150b9b3d4da45c03f398fdc54e", default-features = false, features = ["metadata"] } 207stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-b77c8d968f53b18d6bdcd052e354b5070ec2bbc2", default-features = false, features = ["metadata"] }
205 208
206proc-macro2 = "1.0.36" 209proc-macro2 = "1.0.36"
207quote = "1.0.15" 210quote = "1.0.15"
@@ -213,7 +216,6 @@ proptest = "1.5.0"
213proptest-state-machine = "0.3.0" 216proptest-state-machine = "0.3.0"
214 217
215 218
216
217[features] 219[features]
218default = ["rt"] 220default = ["rt"]
219 221
@@ -1642,6 +1644,30 @@ stm32l562qe = [ "stm32-metapac/stm32l562qe" ]
1642stm32l562re = [ "stm32-metapac/stm32l562re" ] 1644stm32l562re = [ "stm32-metapac/stm32l562re" ]
1643stm32l562ve = [ "stm32-metapac/stm32l562ve" ] 1645stm32l562ve = [ "stm32-metapac/stm32l562ve" ]
1644stm32l562ze = [ "stm32-metapac/stm32l562ze" ] 1646stm32l562ze = [ "stm32-metapac/stm32l562ze" ]
1647stm32n645a0 = [ "stm32-metapac/stm32n645a0" ]
1648stm32n645b0 = [ "stm32-metapac/stm32n645b0" ]
1649stm32n645i0 = [ "stm32-metapac/stm32n645i0" ]
1650stm32n645l0 = [ "stm32-metapac/stm32n645l0" ]
1651stm32n645x0 = [ "stm32-metapac/stm32n645x0" ]
1652stm32n645z0 = [ "stm32-metapac/stm32n645z0" ]
1653stm32n647a0 = [ "stm32-metapac/stm32n647a0" ]
1654stm32n647b0 = [ "stm32-metapac/stm32n647b0" ]
1655stm32n647i0 = [ "stm32-metapac/stm32n647i0" ]
1656stm32n647l0 = [ "stm32-metapac/stm32n647l0" ]
1657stm32n647x0 = [ "stm32-metapac/stm32n647x0" ]
1658stm32n647z0 = [ "stm32-metapac/stm32n647z0" ]
1659stm32n655a0 = [ "stm32-metapac/stm32n655a0" ]
1660stm32n655b0 = [ "stm32-metapac/stm32n655b0" ]
1661stm32n655i0 = [ "stm32-metapac/stm32n655i0" ]
1662stm32n655l0 = [ "stm32-metapac/stm32n655l0" ]
1663stm32n655x0 = [ "stm32-metapac/stm32n655x0" ]
1664stm32n655z0 = [ "stm32-metapac/stm32n655z0" ]
1665stm32n657a0 = [ "stm32-metapac/stm32n657a0" ]
1666stm32n657b0 = [ "stm32-metapac/stm32n657b0" ]
1667stm32n657i0 = [ "stm32-metapac/stm32n657i0" ]
1668stm32n657l0 = [ "stm32-metapac/stm32n657l0" ]
1669stm32n657x0 = [ "stm32-metapac/stm32n657x0" ]
1670stm32n657z0 = [ "stm32-metapac/stm32n657z0" ]
1645stm32u031c6 = [ "stm32-metapac/stm32u031c6" ] 1671stm32u031c6 = [ "stm32-metapac/stm32u031c6" ]
1646stm32u031c8 = [ "stm32-metapac/stm32u031c8" ] 1672stm32u031c8 = [ "stm32-metapac/stm32u031c8" ]
1647stm32u031f4 = [ "stm32-metapac/stm32u031f4" ] 1673stm32u031f4 = [ "stm32-metapac/stm32u031f4" ]
diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs
index 940e29417..1e11eb8dc 100644
--- a/embassy-stm32/build.rs
+++ b/embassy-stm32/build.rs
@@ -363,101 +363,108 @@ fn main() {
363 363
364 // ======== 364 // ========
365 // Generate FLASH regions 365 // Generate FLASH regions
366 let mut flash_regions = TokenStream::new(); 366 cfgs.declare("flash");
367 let flash_memory_regions: Vec<_> = memory 367 let mut has_flash = false;
368 .iter() 368 if !chip_name.starts_with("stm32n6") {
369 .filter(|x| x.kind == MemoryRegionKind::Flash && x.settings.is_some()) 369 cfgs.enable("flash");
370 .collect(); 370 has_flash = true;
371 for region in flash_memory_regions.iter() { 371
372 let region_name = format_ident!("{}", get_flash_region_name(region.name)); 372 let mut flash_regions = TokenStream::new();
373 let bank_variant = format_ident!( 373 let flash_memory_regions: Vec<_> = memory
374 "{}", 374 .iter()
375 if region.name.starts_with("BANK_1") { 375 .filter(|x| x.kind == MemoryRegionKind::Flash && x.settings.is_some())
376 "Bank1" 376 .collect();
377 } else if region.name.starts_with("BANK_2") { 377 for region in flash_memory_regions.iter() {
378 "Bank2" 378 let region_name = format_ident!("{}", get_flash_region_name(region.name));
379 } else if region.name == "OTP" { 379 let bank_variant = format_ident!(
380 "Otp" 380 "{}",
381 } else { 381 if region.name.starts_with("BANK_1") {
382 continue; 382 "Bank1"
383 } 383 } else if region.name.starts_with("BANK_2") {
384 ); 384 "Bank2"
385 let base = region.address; 385 } else if region.name == "OTP" {
386 let size = region.size; 386 "Otp"
387 let settings = region.settings.as_ref().unwrap(); 387 } else {
388 let erase_size = settings.erase_size; 388 continue;
389 let write_size = settings.write_size; 389 }
390 let erase_value = settings.erase_value; 390 );
391 391 let base = region.address;
392 flash_regions.extend(quote! { 392 let size = region.size;
393 pub const #region_name: crate::flash::FlashRegion = crate::flash::FlashRegion { 393 let settings = region.settings.as_ref().unwrap();
394 bank: crate::flash::FlashBank::#bank_variant, 394 let erase_size = settings.erase_size;
395 base: #base, 395 let write_size = settings.write_size;
396 size: #size, 396 let erase_value = settings.erase_value;
397 erase_size: #erase_size, 397
398 write_size: #write_size, 398 flash_regions.extend(quote! {
399 erase_value: #erase_value, 399 pub const #region_name: crate::flash::FlashRegion = crate::flash::FlashRegion {
400 _ensure_internal: (), 400 bank: crate::flash::FlashBank::#bank_variant,
401 }; 401 base: #base,
402 }); 402 size: #size,
403 erase_size: #erase_size,
404 write_size: #write_size,
405 erase_value: #erase_value,
406 _ensure_internal: (),
407 };
408 });
403 409
404 let region_type = format_ident!("{}", get_flash_region_type_name(region.name)); 410 let region_type = format_ident!("{}", get_flash_region_type_name(region.name));
405 flash_regions.extend(quote! { 411 flash_regions.extend(quote! {
406 #[cfg(flash)] 412 #[cfg(flash)]
407 pub struct #region_type<'d, MODE = crate::flash::Async>(pub &'static crate::flash::FlashRegion, pub(crate) embassy_hal_internal::Peri<'d, crate::peripherals::FLASH>, pub(crate) core::marker::PhantomData<MODE>); 413 pub struct #region_type<'d, MODE = crate::flash::Async>(pub &'static crate::flash::FlashRegion, pub(crate) embassy_hal_internal::Peri<'d, crate::peripherals::FLASH>, pub(crate) core::marker::PhantomData<MODE>);
408 }); 414 });
409 } 415 }
410 416
411 let (fields, (inits, region_names)): (Vec<TokenStream>, (Vec<TokenStream>, Vec<Ident>)) = flash_memory_regions 417 let (fields, (inits, region_names)): (Vec<TokenStream>, (Vec<TokenStream>, Vec<Ident>)) = flash_memory_regions
412 .iter() 418 .iter()
413 .map(|f| { 419 .map(|f| {
414 let region_name = get_flash_region_name(f.name); 420 let region_name = get_flash_region_name(f.name);
415 let field_name = format_ident!("{}", region_name.to_lowercase()); 421 let field_name = format_ident!("{}", region_name.to_lowercase());
416 let field_type = format_ident!("{}", get_flash_region_type_name(f.name)); 422 let field_type = format_ident!("{}", get_flash_region_type_name(f.name));
417 let field = quote! { 423 let field = quote! {
418 pub #field_name: #field_type<'d, MODE> 424 pub #field_name: #field_type<'d, MODE>
419 }; 425 };
420 let region_name = format_ident!("{}", region_name); 426 let region_name = format_ident!("{}", region_name);
421 let init = quote! { 427 let init = quote! {
422 #field_name: #field_type(&#region_name, unsafe { p.clone_unchecked()}, core::marker::PhantomData) 428 #field_name: #field_type(&#region_name, unsafe { p.clone_unchecked()}, core::marker::PhantomData)
423 }; 429 };
424 430
425 (field, (init, region_name)) 431 (field, (init, region_name))
426 }) 432 })
427 .unzip(); 433 .unzip();
428 434
429 let regions_len = flash_memory_regions.len(); 435 let regions_len = flash_memory_regions.len();
430 flash_regions.extend(quote! { 436 flash_regions.extend(quote! {
431 #[cfg(flash)] 437 #[cfg(flash)]
432 pub struct FlashLayout<'d, MODE = crate::flash::Async> { 438 pub struct FlashLayout<'d, MODE = crate::flash::Async> {
433 #(#fields),*, 439 #(#fields),*,
434 _mode: core::marker::PhantomData<MODE>, 440 _mode: core::marker::PhantomData<MODE>,
435 } 441 }
436 442
437 #[cfg(flash)] 443 #[cfg(flash)]
438 impl<'d, MODE> FlashLayout<'d, MODE> { 444 impl<'d, MODE> FlashLayout<'d, MODE> {
439 pub(crate) fn new(p: embassy_hal_internal::Peri<'d, crate::peripherals::FLASH>) -> Self { 445 pub(crate) fn new(p: embassy_hal_internal::Peri<'d, crate::peripherals::FLASH>) -> Self {
440 Self { 446 Self {
441 #(#inits),*, 447 #(#inits),*,
442 _mode: core::marker::PhantomData, 448 _mode: core::marker::PhantomData,
449 }
443 } 450 }
444 } 451 }
445 }
446 452
447 pub const FLASH_REGIONS: [&crate::flash::FlashRegion; #regions_len] = [ 453 pub const FLASH_REGIONS: [&crate::flash::FlashRegion; #regions_len] = [
448 #(&#region_names),* 454 #(&#region_names),*
449 ]; 455 ];
450 }); 456 });
451 457
452 let max_erase_size = flash_memory_regions 458 let max_erase_size = flash_memory_regions
453 .iter() 459 .iter()
454 .map(|region| region.settings.as_ref().unwrap().erase_size) 460 .map(|region| region.settings.as_ref().unwrap().erase_size)
455 .max() 461 .max()
456 .unwrap(); 462 .unwrap();
457 463
458 g.extend(quote! { pub const MAX_ERASE_SIZE: usize = #max_erase_size as usize; }); 464 g.extend(quote! { pub const MAX_ERASE_SIZE: usize = #max_erase_size as usize; });
459 465
460 g.extend(quote! { pub mod flash_regions { #flash_regions } }); 466 g.extend(quote! { pub mod flash_regions { #flash_regions } });
467 }
461 468
462 // ======== 469 // ========
463 // Extract the rcc registers 470 // Extract the rcc registers
@@ -1346,6 +1353,8 @@ fn main() {
1346 1353
1347 for p in METADATA.peripherals { 1354 for p in METADATA.peripherals {
1348 if let Some(regs) = &p.registers { 1355 if let Some(regs) = &p.registers {
1356 let mut adc_pairs: BTreeMap<u8, (Option<Ident>, Option<Ident>)> = BTreeMap::new();
1357
1349 for pin in p.pins { 1358 for pin in p.pins {
1350 let key = (regs.kind, pin.signal); 1359 let key = (regs.kind, pin.signal);
1351 if let Some(tr) = signals.get(&key) { 1360 if let Some(tr) = signals.get(&key) {
@@ -1467,25 +1476,29 @@ fn main() {
1467 }; 1476 };
1468 1477
1469 // H7 has differential voltage measurements 1478 // H7 has differential voltage measurements
1470 let ch: Option<u8> = if pin.signal.starts_with("INP") { 1479 let ch: Option<(u8, bool)> = if pin.signal.starts_with("INP") {
1471 Some(pin.signal.strip_prefix("INP").unwrap().parse().unwrap()) 1480 Some((pin.signal.strip_prefix("INP").unwrap().parse().unwrap(), false))
1472 } else if pin.signal.starts_with("INN") { 1481 } else if pin.signal.starts_with("INN") {
1473 // TODO handle in the future when embassy supports differential measurements 1482 Some((pin.signal.strip_prefix("INN").unwrap().parse().unwrap(), true))
1474 None
1475 } else if pin.signal.starts_with("IN") && pin.signal.ends_with('b') { 1483 } else if pin.signal.starts_with("IN") && pin.signal.ends_with('b') {
1476 // we number STM32L1 ADC bank 1 as 0..=31, bank 2 as 32..=63 1484 // we number STM32L1 ADC bank 1 as 0..=31, bank 2 as 32..=63
1477 let signal = pin.signal.strip_prefix("IN").unwrap().strip_suffix('b').unwrap(); 1485 let signal = pin.signal.strip_prefix("IN").unwrap().strip_suffix('b').unwrap();
1478 Some(32u8 + signal.parse::<u8>().unwrap()) 1486 Some((32u8 + signal.parse::<u8>().unwrap(), false))
1479 } else if pin.signal.starts_with("IN") { 1487 } else if pin.signal.starts_with("IN") {
1480 Some(pin.signal.strip_prefix("IN").unwrap().parse().unwrap()) 1488 Some((pin.signal.strip_prefix("IN").unwrap().parse().unwrap(), false))
1481 } else { 1489 } else {
1482 None 1490 None
1483 }; 1491 };
1484 if let Some(ch) = ch { 1492 if let Some((ch, false)) = ch {
1493 adc_pairs.entry(ch).or_insert((None, None)).0.replace(pin_name.clone());
1494
1485 g.extend(quote! { 1495 g.extend(quote! {
1486 impl_adc_pin!( #peri, #pin_name, #ch); 1496 impl_adc_pin!( #peri, #pin_name, #ch);
1487 }) 1497 })
1488 } 1498 }
1499 if let Some((ch, true)) = ch {
1500 adc_pairs.entry(ch).or_insert((None, None)).1.replace(pin_name.clone());
1501 }
1489 } 1502 }
1490 1503
1491 if regs.kind == "opamp" { 1504 if regs.kind == "opamp" {
@@ -1524,6 +1537,23 @@ fn main() {
1524 }) 1537 })
1525 } 1538 }
1526 } 1539 }
1540
1541 {
1542 let peri = format_ident!("{}", p.name);
1543
1544 for (ch, (pin, npin)) in adc_pairs {
1545 let (pin_name, npin_name) = match (pin, npin) {
1546 (Some(pin), Some(npin)) => (pin, npin),
1547 _ => {
1548 continue;
1549 }
1550 };
1551
1552 g.extend(quote! {
1553 impl_adc_pair!( #peri, #pin_name, #npin_name, #ch);
1554 })
1555 }
1556 }
1527 } 1557 }
1528 } 1558 }
1529 1559
@@ -1572,13 +1602,13 @@ fn main() {
1572 .into(); 1602 .into();
1573 1603
1574 if chip_name.starts_with("stm32u5") { 1604 if chip_name.starts_with("stm32u5") {
1575 signals.insert(("adc", "ADC4"), quote!(crate::adc::RxDma4)); 1605 signals.insert(("adc", "ADC4"), quote!(crate::adc::RxDma));
1576 } else { 1606 } else {
1577 signals.insert(("adc", "ADC4"), quote!(crate::adc::RxDma)); 1607 signals.insert(("adc", "ADC4"), quote!(crate::adc::RxDma));
1578 } 1608 }
1579 1609
1580 if chip_name.starts_with("stm32wba") { 1610 if chip_name.starts_with("stm32wba") {
1581 signals.insert(("adc", "ADC4"), quote!(crate::adc::RxDma4)); 1611 signals.insert(("adc", "ADC4"), quote!(crate::adc::RxDma));
1582 } 1612 }
1583 1613
1584 if chip_name.starts_with("stm32g4") { 1614 if chip_name.starts_with("stm32g4") {
@@ -1665,70 +1695,88 @@ fn main() {
1665 } 1695 }
1666 1696
1667 // ======== 1697 // ========
1668 // Generate Div/Mul impls for RCC prescalers/dividers/multipliers. 1698 // Generate Div/Mul impls for RCC and ADC prescalers/dividers/multipliers.
1669 for e in rcc_registers.ir.enums { 1699 for (kind, psc_enums) in ["rcc", "adc", "adccommon"].iter().filter_map(|kind| {
1670 fn is_rcc_name(e: &str) -> bool { 1700 METADATA
1671 match e { 1701 .peripherals
1672 "Pllp" | "Pllq" | "Pllr" | "Plldivst" | "Pllm" | "Plln" | "Prediv1" | "Prediv2" | "Hpre5" => true, 1702 .iter()
1673 "Timpre" | "Pllrclkpre" => false, 1703 .filter_map(|p| p.registers.as_ref())
1674 e if e.ends_with("pre") || e.ends_with("pres") || e.ends_with("div") || e.ends_with("mul") => true, 1704 .find(|r| r.kind == *kind)
1675 _ => false, 1705 .map(|r| (*kind, r.ir.enums))
1706 }) {
1707 for e in psc_enums.iter() {
1708 fn is_adc_name(e: &str) -> bool {
1709 match e {
1710 "Presc" | "Adc4Presc" | "Adcpre" => true,
1711 _ => false,
1712 }
1676 } 1713 }
1677 }
1678 1714
1679 fn parse_num(n: &str) -> Result<Frac, ()> { 1715 fn is_rcc_name(e: &str) -> bool {
1680 for prefix in ["DIV", "MUL"] { 1716 match e {
1681 if let Some(n) = n.strip_prefix(prefix) { 1717 "Pllp" | "Pllq" | "Pllr" | "Plldivst" | "Pllm" | "Plln" | "Prediv1" | "Prediv2" | "Hpre5" => true,
1682 let exponent = n.find('_').map(|e| n.len() - 1 - e).unwrap_or(0) as u32; 1718 "Timpre" | "Pllrclkpre" => false,
1683 let mantissa = n.replace('_', "").parse().map_err(|_| ())?; 1719 e if e.ends_with("pre") || e.ends_with("pres") || e.ends_with("div") || e.ends_with("mul") => true,
1684 let f = Frac { 1720 _ => false,
1685 num: mantissa,
1686 denom: 10u32.pow(exponent),
1687 };
1688 return Ok(f.simplify());
1689 } 1721 }
1690 } 1722 }
1691 Err(())
1692 }
1693 1723
1694 if is_rcc_name(e.name) { 1724 fn parse_num(n: &str) -> Result<Frac, ()> {
1695 let enum_name = format_ident!("{}", e.name); 1725 for prefix in ["DIV", "MUL"] {
1696 let mut muls = Vec::new(); 1726 if let Some(n) = n.strip_prefix(prefix) {
1697 let mut divs = Vec::new(); 1727 let exponent = n.find('_').map(|e| n.len() - 1 - e).unwrap_or(0) as u32;
1698 for v in e.variants { 1728 let mantissa = n.replace('_', "").parse().map_err(|_| ())?;
1699 let Ok(val) = parse_num(v.name) else { 1729 let f = Frac {
1700 panic!("could not parse mul/div. enum={} variant={}", e.name, v.name) 1730 num: mantissa,
1701 }; 1731 denom: 10u32.pow(exponent),
1702 let variant_name = format_ident!("{}", v.name); 1732 };
1703 let variant = quote!(crate::pac::rcc::vals::#enum_name::#variant_name); 1733 return Ok(f.simplify());
1704 let num = val.num; 1734 }
1705 let denom = val.denom; 1735 }
1706 muls.push(quote!(#variant => self * #num / #denom,)); 1736 Err(())
1707 divs.push(quote!(#variant => self * #denom / #num,));
1708 } 1737 }
1709 1738
1710 g.extend(quote! { 1739 if (kind == "rcc" && is_rcc_name(e.name)) || ((kind == "adccommon" || kind == "adc") && is_adc_name(e.name))
1711 impl core::ops::Div<crate::pac::rcc::vals::#enum_name> for crate::time::Hertz { 1740 {
1712 type Output = crate::time::Hertz; 1741 let kind = format_ident!("{}", kind);
1713 fn div(self, rhs: crate::pac::rcc::vals::#enum_name) -> Self::Output { 1742 let enum_name = format_ident!("{}", e.name);
1714 match rhs { 1743 let mut muls = Vec::new();
1715 #(#divs)* 1744 let mut divs = Vec::new();
1716 #[allow(unreachable_patterns)] 1745 for v in e.variants {
1717 _ => unreachable!(), 1746 let Ok(val) = parse_num(v.name) else {
1747 panic!("could not parse mul/div. enum={} variant={}", e.name, v.name)
1748 };
1749 let variant_name = format_ident!("{}", v.name);
1750 let variant = quote!(crate::pac::#kind::vals::#enum_name::#variant_name);
1751 let num = val.num;
1752 let denom = val.denom;
1753 muls.push(quote!(#variant => self * #num / #denom,));
1754 divs.push(quote!(#variant => self * #denom / #num,));
1755 }
1756
1757 g.extend(quote! {
1758 impl core::ops::Div<crate::pac::#kind::vals::#enum_name> for crate::time::Hertz {
1759 type Output = crate::time::Hertz;
1760 fn div(self, rhs: crate::pac::#kind::vals::#enum_name) -> Self::Output {
1761 match rhs {
1762 #(#divs)*
1763 #[allow(unreachable_patterns)]
1764 _ => unreachable!(),
1765 }
1718 } 1766 }
1719 } 1767 }
1720 } 1768 impl core::ops::Mul<crate::pac::#kind::vals::#enum_name> for crate::time::Hertz {
1721 impl core::ops::Mul<crate::pac::rcc::vals::#enum_name> for crate::time::Hertz { 1769 type Output = crate::time::Hertz;
1722 type Output = crate::time::Hertz; 1770 fn mul(self, rhs: crate::pac::#kind::vals::#enum_name) -> Self::Output {
1723 fn mul(self, rhs: crate::pac::rcc::vals::#enum_name) -> Self::Output { 1771 match rhs {
1724 match rhs { 1772 #(#muls)*
1725 #(#muls)* 1773 #[allow(unreachable_patterns)]
1726 #[allow(unreachable_patterns)] 1774 _ => unreachable!(),
1727 _ => unreachable!(), 1775 }
1728 } 1776 }
1729 } 1777 }
1730 } 1778 });
1731 }); 1779 }
1732 } 1780 }
1733 } 1781 }
1734 1782
@@ -1855,7 +1903,12 @@ fn main() {
1855 if r.kind == "dma" || r.kind == "bdma" || r.kind == "gpdma" || r.kind == "lpdma" { 1903 if r.kind == "dma" || r.kind == "bdma" || r.kind == "gpdma" || r.kind == "lpdma" {
1856 for irq in p.interrupts { 1904 for irq in p.interrupts {
1857 let ch_name = format!("{}_{}", p.name, irq.signal); 1905 let ch_name = format!("{}_{}", p.name, irq.signal);
1858 let ch = METADATA.dma_channels.iter().find(|c| c.name == ch_name).unwrap(); 1906 let ch = METADATA.dma_channels.iter().find(|c| c.name == ch_name);
1907
1908 if ch.is_none() {
1909 continue;
1910 }
1911 let ch = ch.unwrap();
1859 1912
1860 // Some H7 chips have BDMA1 hardcoded for DFSDM, ie no DMAMUX. It's unsupported, skip it. 1913 // Some H7 chips have BDMA1 hardcoded for DFSDM, ie no DMAMUX. It's unsupported, skip it.
1861 if has_dmamux && ch.dmamux.is_none() { 1914 if has_dmamux && ch.dmamux.is_none() {
@@ -2008,31 +2061,33 @@ fn main() {
2008 // ======== 2061 // ========
2009 // Generate flash constants 2062 // Generate flash constants
2010 2063
2011 let flash_regions: Vec<&MemoryRegion> = memory 2064 if has_flash {
2012 .iter() 2065 let flash_regions: Vec<&MemoryRegion> = memory
2013 .filter(|x| x.kind == MemoryRegionKind::Flash && x.name.starts_with("BANK_")) 2066 .iter()
2014 .collect(); 2067 .filter(|x| x.kind == MemoryRegionKind::Flash && x.name.starts_with("BANK_"))
2015 let first_flash = flash_regions.first().unwrap(); 2068 .collect();
2016 let total_flash_size = flash_regions 2069 let first_flash = flash_regions.first().unwrap();
2017 .iter() 2070 let total_flash_size = flash_regions
2018 .map(|x| x.size) 2071 .iter()
2019 .reduce(|acc, item| acc + item) 2072 .map(|x| x.size)
2020 .unwrap(); 2073 .reduce(|acc, item| acc + item)
2021 let write_sizes: HashSet<_> = flash_regions 2074 .unwrap();
2022 .iter() 2075 let write_sizes: HashSet<_> = flash_regions
2023 .map(|r| r.settings.as_ref().unwrap().write_size) 2076 .iter()
2024 .collect(); 2077 .map(|r| r.settings.as_ref().unwrap().write_size)
2025 assert_eq!(1, write_sizes.len()); 2078 .collect();
2079 assert_eq!(1, write_sizes.len());
2026 2080
2027 let flash_base = first_flash.address as usize; 2081 let flash_base = first_flash.address as usize;
2028 let total_flash_size = total_flash_size as usize; 2082 let total_flash_size = total_flash_size as usize;
2029 let write_size = (*write_sizes.iter().next().unwrap()) as usize; 2083 let write_size = (*write_sizes.iter().next().unwrap()) as usize;
2030 2084
2031 g.extend(quote!( 2085 g.extend(quote!(
2032 pub const FLASH_BASE: usize = #flash_base; 2086 pub const FLASH_BASE: usize = #flash_base;
2033 pub const FLASH_SIZE: usize = #total_flash_size; 2087 pub const FLASH_SIZE: usize = #total_flash_size;
2034 pub const WRITE_SIZE: usize = #write_size; 2088 pub const WRITE_SIZE: usize = #write_size;
2035 )); 2089 ));
2090 }
2036 2091
2037 // ======== 2092 // ========
2038 // Generate EEPROM constants 2093 // Generate EEPROM constants
diff --git a/embassy-stm32/src/adc/adc4.rs b/embassy-stm32/src/adc/adc4.rs
index 2608160a3..babdebfdb 100644
--- a/embassy-stm32/src/adc/adc4.rs
+++ b/embassy-stm32/src/adc/adc4.rs
@@ -4,8 +4,8 @@ use pac::adc::vals::{Adc4Dmacfg as Dmacfg, Adc4Exten as Exten, Adc4OversamplingR
4#[cfg(stm32wba)] 4#[cfg(stm32wba)]
5use pac::adc::vals::{Chselrmod, Cont, Dmacfg, Exten, OversamplingRatio, Ovss, Smpsel}; 5use pac::adc::vals::{Chselrmod, Cont, Dmacfg, Exten, OversamplingRatio, Ovss, Smpsel};
6 6
7use super::{AdcChannel, AnyAdcChannel, RxDma4, SealedAdcChannel, blocking_delay_us}; 7use super::blocking_delay_us;
8use crate::dma::Transfer; 8use crate::adc::ConversionMode;
9#[cfg(stm32u5)] 9#[cfg(stm32u5)]
10pub use crate::pac::adc::regs::Adc4Chselrmod0 as Chselr; 10pub use crate::pac::adc::regs::Adc4Chselrmod0 as Chselr;
11#[cfg(stm32wba)] 11#[cfg(stm32wba)]
@@ -24,56 +24,24 @@ pub const VREF_DEFAULT_MV: u32 = 3300;
24/// VREF voltage used for factory calibration of VREFINTCAL register. 24/// VREF voltage used for factory calibration of VREFINTCAL register.
25pub const VREF_CALIB_MV: u32 = 3300; 25pub const VREF_CALIB_MV: u32 = 3300;
26 26
27const VREF_CHANNEL: u8 = 0; 27impl<'d, T: Instance> super::SealedSpecialConverter<super::VrefInt> for Adc4<'d, T> {
28const VCORE_CHANNEL: u8 = 12; 28 const CHANNEL: u8 = 0;
29const TEMP_CHANNEL: u8 = 13;
30const VBAT_CHANNEL: u8 = 14;
31const DAC_CHANNEL: u8 = 21;
32
33// NOTE: Vrefint/Temperature/Vbat are not available on all ADCs, this currently cannot be modeled with stm32-data, so these are available from the software on all ADCs
34/// Internal voltage reference channel.
35pub struct VrefInt;
36impl<T: Instance> AdcChannel<T> for VrefInt {}
37impl<T: Instance> SealedAdcChannel<T> for VrefInt {
38 fn channel(&self) -> u8 {
39 VREF_CHANNEL
40 }
41} 29}
42 30
43/// Internal temperature channel. 31impl<'d, T: Instance> super::SealedSpecialConverter<super::Temperature> for Adc4<'d, T> {
44pub struct Temperature; 32 const CHANNEL: u8 = 13;
45impl<T: Instance> AdcChannel<T> for Temperature {}
46impl<T: Instance> SealedAdcChannel<T> for Temperature {
47 fn channel(&self) -> u8 {
48 TEMP_CHANNEL
49 }
50} 33}
51 34
52/// Internal battery voltage channel. 35impl<'d, T: Instance> super::SealedSpecialConverter<super::Vcore> for Adc4<'d, T> {
53pub struct Vbat; 36 const CHANNEL: u8 = 12;
54impl<T: Instance> AdcChannel<T> for Vbat {}
55impl<T: Instance> SealedAdcChannel<T> for Vbat {
56 fn channel(&self) -> u8 {
57 VBAT_CHANNEL
58 }
59} 37}
60 38
61/// Internal DAC channel. 39impl<'d, T: Instance> super::SealedSpecialConverter<super::Vbat> for Adc4<'d, T> {
62pub struct Dac; 40 const CHANNEL: u8 = 14;
63impl<T: Instance> AdcChannel<T> for Dac {}
64impl<T: Instance> SealedAdcChannel<T> for Dac {
65 fn channel(&self) -> u8 {
66 DAC_CHANNEL
67 }
68} 41}
69 42
70/// Internal Vcore channel. 43impl<'d, T: Instance> super::SealedSpecialConverter<super::Dac> for Adc4<'d, T> {
71pub struct Vcore; 44 const CHANNEL: u8 = 21;
72impl<T: Instance> AdcChannel<T> for Vcore {}
73impl<T: Instance> SealedAdcChannel<T> for Vcore {
74 fn channel(&self) -> u8 {
75 VCORE_CHANNEL
76 }
77} 45}
78 46
79#[derive(Copy, Clone)] 47#[derive(Copy, Clone)]
@@ -108,71 +76,17 @@ pub const fn resolution_to_max_count(res: Resolution) -> u32 {
108 } 76 }
109} 77}
110 78
111// NOTE (unused): The prescaler enum closely copies the hardware capabilities, 79fn from_ker_ck(frequency: Hertz) -> Presc {
112// but high prescaling doesn't make a lot of sense in the current implementation and is ommited. 80 let raw_prescaler = frequency.0 / MAX_ADC_CLK_FREQ.0;
113#[allow(unused)] 81 match raw_prescaler {
114enum Prescaler { 82 0 => Presc::DIV1,
115 NotDivided, 83 1 => Presc::DIV2,
116 DividedBy2, 84 2..=3 => Presc::DIV4,
117 DividedBy4, 85 4..=5 => Presc::DIV6,
118 DividedBy6, 86 6..=7 => Presc::DIV8,
119 DividedBy8, 87 8..=9 => Presc::DIV10,
120 DividedBy10, 88 10..=11 => Presc::DIV12,
121 DividedBy12, 89 _ => unimplemented!(),
122 DividedBy16,
123 DividedBy32,
124 DividedBy64,
125 DividedBy128,
126 DividedBy256,
127}
128
129impl Prescaler {
130 fn from_ker_ck(frequency: Hertz) -> Self {
131 let raw_prescaler = frequency.0 / MAX_ADC_CLK_FREQ.0;
132 match raw_prescaler {
133 0 => Self::NotDivided,
134 1 => Self::DividedBy2,
135 2..=3 => Self::DividedBy4,
136 4..=5 => Self::DividedBy6,
137 6..=7 => Self::DividedBy8,
138 8..=9 => Self::DividedBy10,
139 10..=11 => Self::DividedBy12,
140 _ => unimplemented!(),
141 }
142 }
143
144 fn divisor(&self) -> u32 {
145 match self {
146 Prescaler::NotDivided => 1,
147 Prescaler::DividedBy2 => 2,
148 Prescaler::DividedBy4 => 4,
149 Prescaler::DividedBy6 => 6,
150 Prescaler::DividedBy8 => 8,
151 Prescaler::DividedBy10 => 10,
152 Prescaler::DividedBy12 => 12,
153 Prescaler::DividedBy16 => 16,
154 Prescaler::DividedBy32 => 32,
155 Prescaler::DividedBy64 => 64,
156 Prescaler::DividedBy128 => 128,
157 Prescaler::DividedBy256 => 256,
158 }
159 }
160
161 fn presc(&self) -> Presc {
162 match self {
163 Prescaler::NotDivided => Presc::DIV1,
164 Prescaler::DividedBy2 => Presc::DIV2,
165 Prescaler::DividedBy4 => Presc::DIV4,
166 Prescaler::DividedBy6 => Presc::DIV6,
167 Prescaler::DividedBy8 => Presc::DIV8,
168 Prescaler::DividedBy10 => Presc::DIV10,
169 Prescaler::DividedBy12 => Presc::DIV12,
170 Prescaler::DividedBy16 => Presc::DIV16,
171 Prescaler::DividedBy32 => Presc::DIV32,
172 Prescaler::DividedBy64 => Presc::DIV64,
173 Prescaler::DividedBy128 => Presc::DIV128,
174 Prescaler::DividedBy256 => Presc::DIV256,
175 }
176 } 90 }
177} 91}
178 92
@@ -185,6 +99,122 @@ pub trait Instance: SealedInstance + crate::PeripheralType + crate::rcc::RccPeri
185 type Interrupt: crate::interrupt::typelevel::Interrupt; 99 type Interrupt: crate::interrupt::typelevel::Interrupt;
186} 100}
187 101
102foreach_adc!(
103 (ADC4, $common_inst:ident, $clock:ident) => {
104 use crate::peripherals::ADC4;
105
106 impl super::BasicAnyInstance for ADC4 {
107 type SampleTime = SampleTime;
108 }
109
110 impl super::SealedAnyInstance for ADC4 {
111 fn dr() -> *mut u16 {
112 ADC4::regs().dr().as_ptr() as *mut u16
113 }
114
115 fn enable() {
116 ADC4::regs().isr().write(|w| w.set_adrdy(true));
117 ADC4::regs().cr().modify(|w| w.set_aden(true));
118 while !ADC4::regs().isr().read().adrdy() {}
119 ADC4::regs().isr().write(|w| w.set_adrdy(true));
120 }
121
122 fn start() {
123 // Start conversion
124 ADC4::regs().cr().modify(|reg| {
125 reg.set_adstart(true);
126 });
127 }
128
129 fn stop() {
130 if ADC4::regs().cr().read().adstart() && !ADC4::regs().cr().read().addis() {
131 ADC4::regs().cr().modify(|reg| {
132 reg.set_adstp(true);
133 });
134 while ADC4::regs().cr().read().adstart() {}
135 }
136
137 // Reset configuration.
138 ADC4::regs().cfgr1().modify(|reg| {
139 reg.set_dmaen(false);
140 });
141 }
142
143 fn configure_dma(conversion_mode: ConversionMode) {
144 match conversion_mode {
145 ConversionMode::Singular => {
146 ADC4::regs().isr().modify(|reg| {
147 reg.set_ovr(true);
148 reg.set_eos(true);
149 reg.set_eoc(true);
150 });
151
152 ADC4::regs().cfgr1().modify(|reg| {
153 reg.set_dmaen(true);
154 reg.set_dmacfg(Dmacfg::ONE_SHOT);
155 #[cfg(stm32u5)]
156 reg.set_chselrmod(false);
157 #[cfg(stm32wba)]
158 reg.set_chselrmod(Chselrmod::ENABLE_INPUT)
159 });
160 }
161 #[cfg(any(adc_v2, adc_g4, adc_v3, adc_g0, adc_u0))]
162 _ => unreachable!(),
163 }
164 }
165
166 fn configure_sequence(sequence: impl ExactSizeIterator<Item = ((u8, bool), SampleTime)>) {
167 let mut prev_channel: i16 = -1;
168 #[cfg(stm32wba)]
169 ADC4::regs().chselr().write_value(Chselr(0_u32));
170 #[cfg(stm32u5)]
171 ADC4::regs().chselrmod0().write_value(Chselr(0_u32));
172 for (_i, ((channel, _), sample_time)) in sequence.enumerate() {
173 ADC4::regs().smpr().modify(|w| {
174 w.set_smp(_i, sample_time);
175 });
176
177 let channel_num = channel;
178 if channel_num as i16 <= prev_channel {
179 return;
180 };
181 prev_channel = channel_num as i16;
182
183 #[cfg(stm32wba)]
184 ADC4::regs().chselr().modify(|w| {
185 w.set_chsel0(channel as usize, true);
186 });
187 #[cfg(stm32u5)]
188 ADC4::regs().chselrmod0().modify(|w| {
189 w.set_chsel(channel as usize, true);
190 });
191 }
192 }
193
194 fn convert() -> u16 {
195 // Reset interrupts
196 ADC4::regs().isr().modify(|reg| {
197 reg.set_eos(true);
198 reg.set_eoc(true);
199 });
200
201 // Start conversion
202 ADC4::regs().cr().modify(|reg| {
203 reg.set_adstart(true);
204 });
205
206 while !ADC4::regs().isr().read().eos() {
207 // spin
208 }
209
210 ADC4::regs().dr().read().0 as u16
211 }
212 }
213
214 impl super::AnyInstance for ADC4 {}
215 };
216);
217
188pub struct Adc4<'d, T: Instance> { 218pub struct Adc4<'d, T: Instance> {
189 #[allow(unused)] 219 #[allow(unused)]
190 adc: crate::Peri<'d, T>, 220 adc: crate::Peri<'d, T>,
@@ -196,15 +226,15 @@ pub enum Adc4Error {
196 DMAError, 226 DMAError,
197} 227}
198 228
199impl<'d, T: Instance> Adc4<'d, T> { 229impl<'d, T: Instance + super::AnyInstance> super::Adc<'d, T> {
200 /// Create a new ADC driver. 230 /// Create a new ADC driver.
201 pub fn new(adc: Peri<'d, T>) -> Self { 231 pub fn new_adc4(adc: Peri<'d, T>) -> Self {
202 rcc::enable_and_reset::<T>(); 232 rcc::enable_and_reset::<T>();
203 let prescaler = Prescaler::from_ker_ck(T::frequency()); 233 let prescaler = from_ker_ck(T::frequency());
204 234
205 T::regs().ccr().modify(|w| w.set_presc(prescaler.presc())); 235 T::regs().ccr().modify(|w| w.set_presc(prescaler));
206 236
207 let frequency = Hertz(T::frequency().0 / prescaler.divisor()); 237 let frequency = T::frequency() / prescaler;
208 info!("ADC4 frequency set to {}", frequency); 238 info!("ADC4 frequency set to {}", frequency);
209 239
210 if frequency > MAX_ADC_CLK_FREQ { 240 if frequency > MAX_ADC_CLK_FREQ {
@@ -214,20 +244,6 @@ impl<'d, T: Instance> Adc4<'d, T> {
214 ); 244 );
215 } 245 }
216 246
217 let mut s = Self { adc };
218
219 s.power_up();
220
221 s.calibrate();
222 blocking_delay_us(1);
223
224 s.enable();
225 s.configure();
226
227 s
228 }
229
230 fn power_up(&mut self) {
231 T::regs().isr().modify(|w| { 247 T::regs().isr().modify(|w| {
232 w.set_ldordy(true); 248 w.set_ldordy(true);
233 }); 249 });
@@ -239,22 +255,15 @@ impl<'d, T: Instance> Adc4<'d, T> {
239 T::regs().isr().modify(|w| { 255 T::regs().isr().modify(|w| {
240 w.set_ldordy(true); 256 w.set_ldordy(true);
241 }); 257 });
242 }
243 258
244 fn calibrate(&mut self) {
245 T::regs().cr().modify(|w| w.set_adcal(true)); 259 T::regs().cr().modify(|w| w.set_adcal(true));
246 while T::regs().cr().read().adcal() {} 260 while T::regs().cr().read().adcal() {}
247 T::regs().isr().modify(|w| w.set_eocal(true)); 261 T::regs().isr().modify(|w| w.set_eocal(true));
248 }
249 262
250 fn enable(&mut self) { 263 blocking_delay_us(1);
251 T::regs().isr().write(|w| w.set_adrdy(true)); 264
252 T::regs().cr().modify(|w| w.set_aden(true)); 265 T::enable();
253 while !T::regs().isr().read().adrdy() {}
254 T::regs().isr().write(|w| w.set_adrdy(true));
255 }
256 266
257 fn configure(&mut self) {
258 // single conversion mode, software trigger 267 // single conversion mode, software trigger
259 T::regs().cfgr1().modify(|w| { 268 T::regs().cfgr1().modify(|w| {
260 #[cfg(stm32u5)] 269 #[cfg(stm32u5)]
@@ -280,73 +289,63 @@ impl<'d, T: Instance> Adc4<'d, T> {
280 w.set_smpsel(i, Smpsel::SMP1); 289 w.set_smpsel(i, Smpsel::SMP1);
281 } 290 }
282 }); 291 });
292
293 Self { adc }
283 } 294 }
284 295
285 /// Enable reading the voltage reference internal channel. 296 /// Enable reading the voltage reference internal channel.
286 pub fn enable_vrefint(&self) -> VrefInt { 297 pub fn enable_vrefint_adc4(&self) -> super::VrefInt {
287 T::regs().ccr().modify(|w| { 298 T::regs().ccr().modify(|w| {
288 w.set_vrefen(true); 299 w.set_vrefen(true);
289 }); 300 });
290 301
291 VrefInt {} 302 super::VrefInt {}
292 } 303 }
293 304
294 /// Enable reading the temperature internal channel. 305 /// Enable reading the temperature internal channel.
295 pub fn enable_temperature(&self) -> Temperature { 306 pub fn enable_temperature_adc4(&self) -> super::Temperature {
296 T::regs().ccr().modify(|w| { 307 T::regs().ccr().modify(|w| {
297 w.set_vsensesel(true); 308 w.set_vsensesel(true);
298 }); 309 });
299 310
300 Temperature {} 311 super::Temperature {}
301 } 312 }
302 313
303 /// Enable reading the vbat internal channel. 314 /// Enable reading the vbat internal channel.
304 #[cfg(stm32u5)] 315 #[cfg(stm32u5)]
305 pub fn enable_vbat(&self) -> Vbat { 316 pub fn enable_vbat_adc4(&self) -> super::Vbat {
306 T::regs().ccr().modify(|w| { 317 T::regs().ccr().modify(|w| {
307 w.set_vbaten(true); 318 w.set_vbaten(true);
308 }); 319 });
309 320
310 Vbat {} 321 super::Vbat {}
311 } 322 }
312 323
313 /// Enable reading the vbat internal channel. 324 /// Enable reading the vbat internal channel.
314 pub fn enable_vcore(&self) -> Vcore { 325 pub fn enable_vcore_adc4(&self) -> super::Vcore {
315 Vcore {} 326 super::Vcore {}
316 } 327 }
317 328
318 /// Enable reading the vbat internal channel. 329 /// Enable reading the vbat internal channel.
319 #[cfg(stm32u5)] 330 #[cfg(stm32u5)]
320 pub fn enable_dac_channel(&self, dac: DacChannel) -> Dac { 331 pub fn enable_dac_channel_adc4(&self, dac: DacChannel) -> super::Dac {
321 let mux; 332 let mux;
322 match dac { 333 match dac {
323 DacChannel::OUT1 => mux = false, 334 DacChannel::OUT1 => mux = false,
324 DacChannel::OUT2 => mux = true, 335 DacChannel::OUT2 => mux = true,
325 } 336 }
326 T::regs().or().modify(|w| w.set_chn21sel(mux)); 337 T::regs().or().modify(|w| w.set_chn21sel(mux));
327 Dac {} 338 super::Dac {}
328 }
329
330 /// Set the ADC sample time.
331 pub fn set_sample_time(&mut self, sample_time: SampleTime) {
332 T::regs().smpr().modify(|w| {
333 w.set_smp(0, sample_time);
334 });
335 }
336
337 /// Get the ADC sample time.
338 pub fn sample_time(&self) -> SampleTime {
339 T::regs().smpr().read().smp(0)
340 } 339 }
341 340
342 /// Set the ADC resolution. 341 /// Set the ADC resolution.
343 pub fn set_resolution(&mut self, resolution: Resolution) { 342 pub fn set_resolution_adc4(&mut self, resolution: Resolution) {
344 T::regs().cfgr1().modify(|w| w.set_res(resolution.into())); 343 T::regs().cfgr1().modify(|w| w.set_res(resolution.into()));
345 } 344 }
346 345
347 /// Set hardware averaging. 346 /// Set hardware averaging.
348 #[cfg(stm32u5)] 347 #[cfg(stm32u5)]
349 pub fn set_averaging(&mut self, averaging: Averaging) { 348 pub fn set_averaging_adc4(&mut self, averaging: Averaging) {
350 let (enable, samples, right_shift) = match averaging { 349 let (enable, samples, right_shift) = match averaging {
351 Averaging::Disabled => (false, OversamplingRatio::OVERSAMPLE2X, 0), 350 Averaging::Disabled => (false, OversamplingRatio::OVERSAMPLE2X, 0),
352 Averaging::Samples2 => (true, OversamplingRatio::OVERSAMPLE2X, 1), 351 Averaging::Samples2 => (true, OversamplingRatio::OVERSAMPLE2X, 1),
@@ -366,7 +365,7 @@ impl<'d, T: Instance> Adc4<'d, T> {
366 }) 365 })
367 } 366 }
368 #[cfg(stm32wba)] 367 #[cfg(stm32wba)]
369 pub fn set_averaging(&mut self, averaging: Averaging) { 368 pub fn set_averaging_adc4(&mut self, averaging: Averaging) {
370 let (enable, samples, right_shift) = match averaging { 369 let (enable, samples, right_shift) = match averaging {
371 Averaging::Disabled => (false, OversamplingRatio::OVERSAMPLE2X, Ovss::SHIFT0), 370 Averaging::Disabled => (false, OversamplingRatio::OVERSAMPLE2X, Ovss::SHIFT0),
372 Averaging::Samples2 => (true, OversamplingRatio::OVERSAMPLE2X, Ovss::SHIFT1), 371 Averaging::Samples2 => (true, OversamplingRatio::OVERSAMPLE2X, Ovss::SHIFT1),
@@ -385,164 +384,4 @@ impl<'d, T: Instance> Adc4<'d, T> {
385 w.set_ovse(enable) 384 w.set_ovse(enable)
386 }) 385 })
387 } 386 }
388
389 /// Read an ADC channel.
390 pub fn blocking_read(&mut self, channel: &mut impl AdcChannel<T>) -> u16 {
391 channel.setup();
392
393 // Select channel
394 #[cfg(stm32wba)]
395 {
396 T::regs().chselr().write_value(Chselr(0_u32));
397 T::regs().chselr().modify(|w| {
398 w.set_chsel0(channel.channel() as usize, true);
399 });
400 }
401 #[cfg(stm32u5)]
402 {
403 T::regs().chselrmod0().write_value(Chselr(0_u32));
404 T::regs().chselrmod0().modify(|w| {
405 w.set_chsel(channel.channel() as usize, true);
406 });
407 }
408
409 // Reset interrupts
410 T::regs().isr().modify(|reg| {
411 reg.set_eos(true);
412 reg.set_eoc(true);
413 });
414
415 // Start conversion
416 T::regs().cr().modify(|reg| {
417 reg.set_adstart(true);
418 });
419
420 while !T::regs().isr().read().eos() {
421 // spin
422 }
423
424 T::regs().dr().read().0 as u16
425 }
426
427 /// Read one or multiple ADC channels using DMA.
428 ///
429 /// `sequence` iterator and `readings` must have the same length.
430 /// The channels in `sequence` must be in ascending order.
431 ///
432 /// Example
433 /// ```rust,ignore
434 /// use embassy_stm32::adc::adc4;
435 /// use embassy_stm32::adc::AdcChannel;
436 ///
437 /// let mut adc4 = adc4::Adc4::new(p.ADC4);
438 /// let mut adc4_pin1 = p.PC1;
439 /// let mut adc4_pin2 = p.PC0;
440 /// let mut.into()d41 = adc4_pin1.into();
441 /// let mut.into()d42 = adc4_pin2.into();
442 /// let mut measurements = [0u16; 2];
443 /// // not that the channels must be in ascending order
444 /// adc4.read(
445 /// &mut p.GPDMA1_CH1,
446 /// [
447 /// &mut.into()d42,
448 /// &mut.into()d41,
449 /// ]
450 /// .into_iter(),
451 /// &mut measurements,
452 /// ).await.unwrap();
453 /// ```
454 pub async fn read(
455 &mut self,
456 rx_dma: Peri<'_, impl RxDma4<T>>,
457 sequence: impl ExactSizeIterator<Item = &mut AnyAdcChannel<T>>,
458 readings: &mut [u16],
459 ) -> Result<(), Adc4Error> {
460 assert!(sequence.len() != 0, "Asynchronous read sequence cannot be empty");
461 assert!(
462 sequence.len() == readings.len(),
463 "Sequence length must be equal to readings length"
464 );
465
466 // Ensure no conversions are ongoing
467 Self::cancel_conversions();
468
469 T::regs().isr().modify(|reg| {
470 reg.set_ovr(true);
471 reg.set_eos(true);
472 reg.set_eoc(true);
473 });
474
475 T::regs().cfgr1().modify(|reg| {
476 reg.set_dmaen(true);
477 reg.set_dmacfg(Dmacfg::ONE_SHOT);
478 #[cfg(stm32u5)]
479 reg.set_chselrmod(false);
480 #[cfg(stm32wba)]
481 reg.set_chselrmod(Chselrmod::ENABLE_INPUT)
482 });
483
484 // Verify and activate sequence
485 let mut prev_channel: i16 = -1;
486 #[cfg(stm32wba)]
487 T::regs().chselr().write_value(Chselr(0_u32));
488 #[cfg(stm32u5)]
489 T::regs().chselrmod0().write_value(Chselr(0_u32));
490 for channel in sequence {
491 let channel_num = channel.channel;
492 if channel_num as i16 <= prev_channel {
493 return Err(Adc4Error::InvalidSequence);
494 };
495 prev_channel = channel_num as i16;
496
497 #[cfg(stm32wba)]
498 T::regs().chselr().modify(|w| {
499 w.set_chsel0(channel.channel as usize, true);
500 });
501 #[cfg(stm32u5)]
502 T::regs().chselrmod0().modify(|w| {
503 w.set_chsel(channel.channel as usize, true);
504 });
505 }
506
507 let request = rx_dma.request();
508 let transfer = unsafe {
509 Transfer::new_read(
510 rx_dma,
511 request,
512 T::regs().dr().as_ptr() as *mut u16,
513 readings,
514 Default::default(),
515 )
516 };
517
518 // Start conversion
519 T::regs().cr().modify(|reg| {
520 reg.set_adstart(true);
521 });
522
523 transfer.await;
524
525 // Ensure conversions are finished.
526 Self::cancel_conversions();
527
528 // Reset configuration.
529 T::regs().cfgr1().modify(|reg| {
530 reg.set_dmaen(false);
531 });
532
533 if T::regs().isr().read().ovr() {
534 Err(Adc4Error::DMAError)
535 } else {
536 Ok(())
537 }
538 }
539
540 fn cancel_conversions() {
541 if T::regs().cr().read().adstart() && !T::regs().cr().read().addis() {
542 T::regs().cr().modify(|reg| {
543 reg.set_adstp(true);
544 });
545 while T::regs().cr().read().adstart() {}
546 }
547 }
548} 387}
diff --git a/embassy-stm32/src/adc/c0.rs b/embassy-stm32/src/adc/c0.rs
index fc28df346..d87bd1ed4 100644
--- a/embassy-stm32/src/adc/c0.rs
+++ b/embassy-stm32/src/adc/c0.rs
@@ -1,12 +1,10 @@
1use pac::adc::vals::Scandir;
2#[allow(unused)] 1#[allow(unused)]
3use pac::adc::vals::{Adstp, Align, Ckmode, Dmacfg, Exten, Ovrmod, Ovsr}; 2use pac::adc::vals::{Adstp, Align, Ckmode, Dmacfg, Exten, Ovrmod, Ovsr};
4use pac::adccommon::vals::Presc; 3use pac::adccommon::vals::Presc;
4use stm32_metapac::adc::vals::{SampleTime, Scandir};
5 5
6use super::{ 6use super::{Adc, Instance, Resolution, blocking_delay_us};
7 Adc, AdcChannel, AnyAdcChannel, Instance, Resolution, RxDma, SampleTime, SealedAdcChannel, blocking_delay_us, 7use crate::adc::{AnyInstance, ConversionMode};
8};
9use crate::dma::Transfer;
10use crate::time::Hertz; 8use crate::time::Hertz;
11use crate::{Peri, pac, rcc}; 9use crate::{Peri, pac, rcc};
12 10
@@ -19,152 +17,181 @@ const MAX_ADC_CLK_FREQ: Hertz = Hertz::mhz(25);
19 17
20const TIME_ADC_VOLTAGE_REGUALTOR_STARTUP_US: u32 = 20; 18const TIME_ADC_VOLTAGE_REGUALTOR_STARTUP_US: u32 = 20;
21 19
22const TEMP_CHANNEL: u8 = 9;
23const VREF_CHANNEL: u8 = 10;
24
25const NUM_HW_CHANNELS: u8 = 22;
26const CHSELR_SQ_SIZE: usize = 8; 20const CHSELR_SQ_SIZE: usize = 8;
27const CHSELR_SQ_MAX_CHANNEL: u8 = 14; 21const CHSELR_SQ_MAX_CHANNEL: u8 = 14;
28const CHSELR_SQ_SEQUENCE_END_MARKER: u8 = 0b1111; 22const CHSELR_SQ_SEQUENCE_END_MARKER: u8 = 0b1111;
29 23
30// NOTE: Vrefint/Temperature/Vbat are not available on all ADCs, 24impl<T: Instance> super::SealedSpecialConverter<super::VrefInt> for T {
31// this currently cannot be modeled with stm32-data, 25 const CHANNEL: u8 = 10;
32// so these are available from the software on all ADCs.
33/// Internal voltage reference channel.
34pub struct VrefInt;
35impl<T: Instance> AdcChannel<T> for VrefInt {}
36impl<T: Instance> SealedAdcChannel<T> for VrefInt {
37 fn channel(&self) -> u8 {
38 VREF_CHANNEL
39 }
40} 26}
41 27
42/// Internal temperature channel. 28impl<T: Instance> super::SealedSpecialConverter<super::Temperature> for T {
43pub struct Temperature; 29 const CHANNEL: u8 = 9;
44impl<T: Instance> AdcChannel<T> for Temperature {}
45impl<T: Instance> SealedAdcChannel<T> for Temperature {
46 fn channel(&self) -> u8 {
47 TEMP_CHANNEL
48 }
49} 30}
50 31
51#[derive(Copy, Clone, Debug)] 32fn from_ker_ck(frequency: Hertz) -> Presc {
52pub enum Prescaler { 33 let raw_prescaler = frequency.0 / MAX_ADC_CLK_FREQ.0;
53 NotDivided, 34 match raw_prescaler {
54 DividedBy2, 35 0 => Presc::DIV1,
55 DividedBy4, 36 1 => Presc::DIV2,
56 DividedBy6, 37 2..=3 => Presc::DIV4,
57 DividedBy8, 38 4..=5 => Presc::DIV6,
58 DividedBy10, 39 6..=7 => Presc::DIV8,
59 DividedBy12, 40 8..=9 => Presc::DIV10,
60 DividedBy16, 41 10..=11 => Presc::DIV12,
61 DividedBy32, 42 _ => unimplemented!(),
62 DividedBy64, 43 }
63 DividedBy128,
64 DividedBy256,
65} 44}
66 45
67impl Prescaler { 46impl<T: Instance> super::SealedAnyInstance for T {
68 fn from_ker_ck(frequency: Hertz) -> Self { 47 fn dr() -> *mut u16 {
69 let raw_prescaler = frequency.0 / MAX_ADC_CLK_FREQ.0; 48 T::regs().dr().as_ptr() as *mut u16
70 match raw_prescaler { 49 }
71 0 => Self::NotDivided, 50
72 1 => Self::DividedBy2, 51 fn enable() {
73 2..=3 => Self::DividedBy4, 52 T::regs().isr().modify(|w| w.set_adrdy(true));
74 4..=5 => Self::DividedBy6, 53 T::regs().cr().modify(|w| w.set_aden(true));
75 6..=7 => Self::DividedBy8, 54 // ADRDY is "ADC ready". Wait until it will be True.
76 8..=9 => Self::DividedBy10, 55 while !T::regs().isr().read().adrdy() {}
77 10..=11 => Self::DividedBy12, 56 }
78 _ => unimplemented!(), 57
79 } 58 fn start() {
59 // Start conversion
60 T::regs().cr().modify(|reg| {
61 reg.set_adstart(true);
62 });
80 } 63 }
81 64
82 #[allow(unused)] 65 fn stop() {
83 fn divisor(&self) -> u32 { 66 if T::regs().cr().read().adstart() && !T::regs().cr().read().addis() {
84 match self { 67 T::regs().cr().modify(|reg| {
85 Prescaler::NotDivided => 1, 68 reg.set_adstp(Adstp::STOP);
86 Prescaler::DividedBy2 => 2, 69 });
87 Prescaler::DividedBy4 => 4, 70 while T::regs().cr().read().adstart() {}
88 Prescaler::DividedBy6 => 6,
89 Prescaler::DividedBy8 => 8,
90 Prescaler::DividedBy10 => 10,
91 Prescaler::DividedBy12 => 12,
92 Prescaler::DividedBy16 => 16,
93 Prescaler::DividedBy32 => 32,
94 Prescaler::DividedBy64 => 64,
95 Prescaler::DividedBy128 => 128,
96 Prescaler::DividedBy256 => 256,
97 } 71 }
72
73 // Reset configuration.
74 T::regs().cfgr1().modify(|reg| {
75 reg.set_cont(false);
76 reg.set_dmacfg(Dmacfg::from_bits(0));
77 reg.set_dmaen(false);
78 });
98 } 79 }
99 80
100 fn presc(&self) -> Presc { 81 fn configure_dma(conversion_mode: super::ConversionMode) {
101 match self { 82 match conversion_mode {
102 Prescaler::NotDivided => Presc::DIV1, 83 ConversionMode::Singular => {
103 Prescaler::DividedBy2 => Presc::DIV2, 84 // Enable overrun control, so no new DMA requests will be generated until
104 Prescaler::DividedBy4 => Presc::DIV4, 85 // previous DR values is read.
105 Prescaler::DividedBy6 => Presc::DIV6, 86 T::regs().isr().modify(|reg| {
106 Prescaler::DividedBy8 => Presc::DIV8, 87 reg.set_ovr(true);
107 Prescaler::DividedBy10 => Presc::DIV10, 88 });
108 Prescaler::DividedBy12 => Presc::DIV12, 89
109 Prescaler::DividedBy16 => Presc::DIV16, 90 // Set continuous mode with oneshot dma.
110 Prescaler::DividedBy32 => Presc::DIV32, 91 T::regs().cfgr1().modify(|reg| {
111 Prescaler::DividedBy64 => Presc::DIV64, 92 reg.set_discen(false);
112 Prescaler::DividedBy128 => Presc::DIV128, 93 reg.set_cont(true);
113 Prescaler::DividedBy256 => Presc::DIV256, 94 reg.set_dmacfg(Dmacfg::DMA_ONE_SHOT);
95 reg.set_dmaen(true);
96 reg.set_ovrmod(Ovrmod::PRESERVE);
97 });
98 }
114 } 99 }
115 } 100 }
116}
117 101
118#[cfg(feature = "defmt")] 102 fn configure_sequence(sequence: impl ExactSizeIterator<Item = ((u8, bool), Self::SampleTime)>) {
119impl<'a> defmt::Format for Prescaler { 103 let mut needs_hw = sequence.len() == 1 || sequence.len() > CHSELR_SQ_SIZE;
120 fn format(&self, fmt: defmt::Formatter) { 104 let mut is_ordered_up = true;
121 match self { 105 let mut is_ordered_down = true;
122 Prescaler::NotDivided => defmt::write!(fmt, "Prescaler::NotDivided"), 106
123 Prescaler::DividedBy2 => defmt::write!(fmt, "Prescaler::DividedBy2"), 107 let sequence_len = sequence.len();
124 Prescaler::DividedBy4 => defmt::write!(fmt, "Prescaler::DividedBy4"), 108 let mut hw_channel_selection: u32 = 0;
125 Prescaler::DividedBy6 => defmt::write!(fmt, "Prescaler::DividedBy6"), 109 let mut last_channel: u8 = 0;
126 Prescaler::DividedBy8 => defmt::write!(fmt, "Prescaler::DividedBy8"), 110 let mut sample_time: Self::SampleTime = SampleTime::CYCLES2_5;
127 Prescaler::DividedBy10 => defmt::write!(fmt, "Prescaler::DividedBy10"), 111
128 Prescaler::DividedBy12 => defmt::write!(fmt, "Prescaler::DividedBy12"), 112 T::regs().chselr_sq().write(|w| {
129 Prescaler::DividedBy16 => defmt::write!(fmt, "Prescaler::DividedBy16"), 113 for (i, ((channel, _), _sample_time)) in sequence.enumerate() {
130 Prescaler::DividedBy32 => defmt::write!(fmt, "Prescaler::DividedBy32"), 114 assert!(
131 Prescaler::DividedBy64 => defmt::write!(fmt, "Prescaler::DividedBy64"), 115 sample_time == _sample_time || i == 0,
132 Prescaler::DividedBy128 => defmt::write!(fmt, "Prescaler::DividedBy128"), 116 "C0 only supports one sample time for the sequence."
133 Prescaler::DividedBy256 => defmt::write!(fmt, "Prescaler::DividedBy256"), 117 );
118
119 sample_time = _sample_time;
120 needs_hw = needs_hw || channel > CHSELR_SQ_MAX_CHANNEL;
121 is_ordered_up = is_ordered_up && (channel > last_channel || i == 0);
122 is_ordered_down = is_ordered_down && (channel < last_channel || i == 0);
123 hw_channel_selection += 1 << channel;
124 last_channel = channel;
125
126 if !needs_hw {
127 w.set_sq(i, channel);
128 }
129 }
130
131 for i in sequence_len..CHSELR_SQ_SIZE {
132 w.set_sq(i, CHSELR_SQ_SEQUENCE_END_MARKER);
133 }
134 });
135
136 if needs_hw {
137 assert!(
138 sequence_len <= CHSELR_SQ_SIZE || is_ordered_up || is_ordered_down,
139 "Sequencer is required because of unordered channels, but read set cannot be more than {} in size.",
140 CHSELR_SQ_SIZE
141 );
142 assert!(
143 sequence_len > CHSELR_SQ_SIZE || is_ordered_up || is_ordered_down,
144 "Sequencer is required because of unordered channels, but only support HW channels smaller than {}.",
145 CHSELR_SQ_MAX_CHANNEL
146 );
147
148 // Set required channels for multi-convert.
149 unsafe { (T::regs().chselr().as_ptr() as *mut u32).write_volatile(hw_channel_selection) }
134 } 150 }
151
152 T::regs().smpr().modify(|w| {
153 w.smpsel(0);
154 w.set_smp1(sample_time);
155 });
156
157 T::regs().cfgr1().modify(|reg| {
158 reg.set_chselrmod(!needs_hw);
159 reg.set_align(Align::RIGHT);
160 reg.set_scandir(if is_ordered_up { Scandir::UP } else { Scandir::BACK });
161 });
162
163 // Trigger and wait for the channel selection procedure to complete.
164 T::regs().isr().modify(|w| w.set_ccrdy(false));
165 while !T::regs().isr().read().ccrdy() {}
135 } 166 }
136}
137 167
138/// Number of samples used for averaging. 168 fn convert() -> u16 {
139/// TODO: Implement hardware averaging setting. 169 // Set single conversion mode.
140#[allow(unused)] 170 T::regs().cfgr1().modify(|w| w.set_cont(false));
141#[derive(Copy, Clone, Debug)] 171
142#[cfg_attr(feature = "defmt", derive(defmt::Format))] 172 // Start conversion
143pub enum Averaging { 173 T::regs().cr().modify(|reg| {
144 Disabled, 174 reg.set_adstart(true);
145 Samples2, 175 });
146 Samples4, 176
147 Samples8, 177 // Waiting for End Of Conversion (EOC).
148 Samples16, 178 while !T::regs().isr().read().eoc() {}
149 Samples32, 179
150 Samples64, 180 T::regs().dr().read().data() as u16
151 Samples128, 181 }
152 Samples256,
153 Samples512,
154 Samples1024,
155} 182}
156 183
157impl<'d, T: Instance> Adc<'d, T> { 184impl<'d, T: AnyInstance> Adc<'d, T> {
158 /// Create a new ADC driver. 185 /// Create a new ADC driver.
159 pub fn new(adc: Peri<'d, T>, sample_time: SampleTime, resolution: Resolution) -> Self { 186 pub fn new(adc: Peri<'d, T>, resolution: Resolution) -> Self {
160 rcc::enable_and_reset::<T>(); 187 rcc::enable_and_reset::<T>();
161 188
162 T::regs().cfgr2().modify(|w| w.set_ckmode(Ckmode::SYSCLK)); 189 T::regs().cfgr2().modify(|w| w.set_ckmode(Ckmode::SYSCLK));
163 190
164 let prescaler = Prescaler::from_ker_ck(T::frequency()); 191 let prescaler = from_ker_ck(T::frequency());
165 T::common_regs().ccr().modify(|w| w.set_presc(prescaler.presc())); 192 T::common_regs().ccr().modify(|w| w.set_presc(prescaler));
166 193
167 let frequency = Hertz(T::frequency().0 / prescaler.divisor()); 194 let frequency = T::frequency() / prescaler;
168 debug!("ADC frequency set to {}", frequency); 195 debug!("ADC frequency set to {}", frequency);
169 196
170 if frequency > MAX_ADC_CLK_FREQ { 197 if frequency > MAX_ADC_CLK_FREQ {
@@ -174,37 +201,16 @@ impl<'d, T: Instance> Adc<'d, T> {
174 ); 201 );
175 } 202 }
176 203
177 let mut s = Self {
178 adc,
179 sample_time: SampleTime::from_bits(0),
180 };
181
182 s.power_up();
183
184 s.set_resolution(resolution);
185
186 s.calibrate();
187
188 s.enable();
189
190 s.configure_default();
191
192 s.set_sample_time_all_channels(sample_time);
193
194 s
195 }
196
197 fn power_up(&mut self) {
198 T::regs().cr().modify(|reg| { 204 T::regs().cr().modify(|reg| {
199 reg.set_advregen(true); 205 reg.set_advregen(true);
200 }); 206 });
201 207
202 // "The software must wait for the ADC voltage regulator startup time." 208 // "The software must wait for the ADC voltage regulator startup time."
203 // See datasheet for the value. 209 // See datasheet for the value.
204 blocking_delay_us(TIME_ADC_VOLTAGE_REGUALTOR_STARTUP_US + 1); 210 blocking_delay_us(TIME_ADC_VOLTAGE_REGUALTOR_STARTUP_US as u64 + 1);
205 } 211
212 T::regs().cfgr1().modify(|reg| reg.set_res(resolution));
206 213
207 fn calibrate(&mut self) {
208 // We have to make sure AUTOFF is OFF, but keep its value after calibration. 214 // We have to make sure AUTOFF is OFF, but keep its value after calibration.
209 let autoff_value = T::regs().cfgr1().read().autoff(); 215 let autoff_value = T::regs().cfgr1().read().autoff();
210 T::regs().cfgr1().modify(|w| w.set_autoff(false)); 216 T::regs().cfgr1().modify(|w| w.set_autoff(false));
@@ -218,255 +224,35 @@ impl<'d, T: Instance> Adc<'d, T> {
218 debug!("ADC calibration value: {}.", T::regs().dr().read().data()); 224 debug!("ADC calibration value: {}.", T::regs().dr().read().data());
219 225
220 T::regs().cfgr1().modify(|w| w.set_autoff(autoff_value)); 226 T::regs().cfgr1().modify(|w| w.set_autoff(autoff_value));
221 }
222 227
223 fn enable(&mut self) { 228 T::enable();
224 T::regs().isr().modify(|w| w.set_adrdy(true));
225 T::regs().cr().modify(|w| w.set_aden(true));
226 // ADRDY is "ADC ready". Wait until it will be True.
227 while !T::regs().isr().read().adrdy() {}
228 }
229 229
230 fn configure_default(&mut self) {
231 // single conversion mode, software trigger 230 // single conversion mode, software trigger
232 T::regs().cfgr1().modify(|w| { 231 T::regs().cfgr1().modify(|w| {
233 w.set_cont(false); 232 w.set_cont(false);
234 w.set_exten(Exten::DISABLED); 233 w.set_exten(Exten::DISABLED);
235 w.set_align(Align::RIGHT); 234 w.set_align(Align::RIGHT);
236 }); 235 });
236
237 Self { adc }
237 } 238 }
238 239
239 /// Enable reading the voltage reference internal channel. 240 /// Enable reading the voltage reference internal channel.
240 pub fn enable_vrefint(&self) -> VrefInt { 241 pub fn enable_vrefint(&self) -> super::VrefInt {
241 T::common_regs().ccr().modify(|reg| { 242 T::common_regs().ccr().modify(|reg| {
242 reg.set_vrefen(true); 243 reg.set_vrefen(true);
243 }); 244 });
244 245
245 VrefInt {} 246 super::VrefInt {}
246 } 247 }
247 248
248 /// Enable reading the temperature internal channel. 249 /// Enable reading the temperature internal channel.
249 pub fn enable_temperature(&self) -> Temperature { 250 pub fn enable_temperature(&self) -> super::Temperature {
250 debug!("Ensure that sample time is set to more than temperature sensor T_start from the datasheet!"); 251 debug!("Ensure that sample time is set to more than temperature sensor T_start from the datasheet!");
251 T::common_regs().ccr().modify(|reg| { 252 T::common_regs().ccr().modify(|reg| {
252 reg.set_tsen(true); 253 reg.set_tsen(true);
253 }); 254 });
254 255
255 Temperature {} 256 super::Temperature {}
256 }
257
258 /// Set the ADC sample time.
259 /// Shall only be called when ADC is not converting.
260 pub fn set_sample_time_all_channels(&mut self, sample_time: SampleTime) {
261 self.sample_time = sample_time;
262
263 // Set all channels to use SMP1 field as source.
264 T::regs().smpr().modify(|w| {
265 w.smpsel(0);
266 w.set_smp1(sample_time);
267 });
268 }
269
270 /// Set the ADC resolution.
271 pub fn set_resolution(&mut self, resolution: Resolution) {
272 T::regs().cfgr1().modify(|reg| reg.set_res(resolution));
273 }
274
275 /// Perform a single conversion.
276 fn convert(&mut self) -> u16 {
277 // Set single conversion mode.
278 T::regs().cfgr1().modify(|w| w.set_cont(false));
279
280 // Start conversion
281 T::regs().cr().modify(|reg| {
282 reg.set_adstart(true);
283 });
284
285 // Waiting for End Of Conversion (EOC).
286 while !T::regs().isr().read().eoc() {}
287
288 T::regs().dr().read().data() as u16
289 }
290
291 pub fn blocking_read(&mut self, channel: &mut impl AdcChannel<T>) -> u16 {
292 Self::configure_channel(channel);
293 T::regs().cfgr1().write(|reg| {
294 reg.set_chselrmod(false);
295 reg.set_align(Align::RIGHT);
296 });
297 self.convert()
298 }
299
300 fn setup_channel_sequencer<'a>(channel_sequence: impl ExactSizeIterator<Item = &'a mut AnyAdcChannel<T>>) {
301 assert!(
302 channel_sequence.len() <= CHSELR_SQ_SIZE,
303 "Seqenced read set cannot be more than {} in size.",
304 CHSELR_SQ_SIZE
305 );
306 let mut last_sq_set: usize = 0;
307 T::regs().chselr_sq().write(|w| {
308 for (i, channel) in channel_sequence.enumerate() {
309 assert!(
310 channel.channel() <= CHSELR_SQ_MAX_CHANNEL,
311 "Sequencer only support HW channels smaller than {}.",
312 CHSELR_SQ_MAX_CHANNEL
313 );
314 w.set_sq(i, channel.channel());
315 last_sq_set = i;
316 }
317
318 for i in (last_sq_set + 1)..CHSELR_SQ_SIZE {
319 w.set_sq(i, CHSELR_SQ_SEQUENCE_END_MARKER);
320 }
321 });
322
323 Self::apply_channel_conf()
324 }
325
326 async fn dma_convert(&mut self, rx_dma: Peri<'_, impl RxDma<T>>, readings: &mut [u16]) {
327 // Enable overrun control, so no new DMA requests will be generated until
328 // previous DR values is read.
329 T::regs().isr().modify(|reg| {
330 reg.set_ovr(true);
331 });
332
333 // Set continuous mode with oneshot dma.
334 T::regs().cfgr1().modify(|reg| {
335 reg.set_discen(false);
336 reg.set_cont(true);
337 reg.set_dmacfg(Dmacfg::DMA_ONE_SHOT);
338 reg.set_dmaen(true);
339 reg.set_ovrmod(Ovrmod::PRESERVE);
340 });
341
342 let request = rx_dma.request();
343 let transfer = unsafe {
344 Transfer::new_read(
345 rx_dma,
346 request,
347 T::regs().dr().as_ptr() as *mut u16,
348 readings,
349 Default::default(),
350 )
351 };
352
353 // Start conversion.
354 T::regs().cr().modify(|reg| {
355 reg.set_adstart(true);
356 });
357
358 // Wait for conversion sequence to finish.
359 transfer.await;
360
361 // Ensure conversions are finished.
362 Self::cancel_conversions();
363
364 // Reset configuration.
365 T::regs().cfgr1().modify(|reg| {
366 reg.set_cont(false);
367 reg.set_dmacfg(Dmacfg::from_bits(0));
368 reg.set_dmaen(false);
369 });
370 }
371
372 /// Read one or multiple ADC channels using DMA in hardware order.
373 /// Readings will be ordered based on **hardware** ADC channel number and `scandir` setting.
374 /// Readings won't be in the same order as in the `set`!
375 ///
376 /// In STM32C0, channels bigger than 14 cannot be read using sequencer, so you have to use
377 /// either blocking reads or use the mechanism to read in HW order (CHSELRMOD=0).
378 /// TODO(chudsaviet): externalize generic code and merge with read().
379 pub async fn read_in_hw_order(
380 &mut self,
381 rx_dma: Peri<'_, impl RxDma<T>>,
382 hw_channel_selection: u32,
383 scandir: Scandir,
384 readings: &mut [u16],
385 ) {
386 assert!(
387 hw_channel_selection != 0,
388 "Some bits in `hw_channel_selection` shall be set."
389 );
390 assert!(
391 (hw_channel_selection >> NUM_HW_CHANNELS) == 0,
392 "STM32C0 only have {} ADC channels. `hw_channel_selection` cannot have bits higher than this number set.",
393 NUM_HW_CHANNELS
394 );
395 // To check for correct readings slice size, we shall solve Hamming weight problem,
396 // which is either slow or memory consuming.
397 // Since we have limited resources, we don't do it here.
398 // Not doing this have a great potential for a bug through.
399
400 // Ensure no conversions are ongoing.
401 Self::cancel_conversions();
402
403 T::regs().cfgr1().modify(|reg| {
404 reg.set_chselrmod(false);
405 reg.set_scandir(scandir);
406 reg.set_align(Align::RIGHT);
407 });
408
409 // Set required channels for multi-convert.
410 unsafe { (T::regs().chselr().as_ptr() as *mut u32).write_volatile(hw_channel_selection) }
411
412 Self::apply_channel_conf();
413
414 self.dma_convert(rx_dma, readings).await
415 }
416
417 // Read ADC channels in specified order using DMA (CHSELRMOD = 1).
418 // In STM32C0, only lower 14 ADC channels can be read this way.
419 // For other channels, use `read_in_hw_order()` or blocking read.
420 pub async fn read(
421 &mut self,
422 rx_dma: Peri<'_, impl RxDma<T>>,
423 channel_sequence: impl ExactSizeIterator<Item = &mut AnyAdcChannel<T>>,
424 readings: &mut [u16],
425 ) {
426 assert!(
427 channel_sequence.len() != 0,
428 "Asynchronous read channel sequence cannot be empty."
429 );
430 assert!(
431 channel_sequence.len() == readings.len(),
432 "Channel sequence length must be equal to readings length."
433 );
434
435 // Ensure no conversions are ongoing.
436 Self::cancel_conversions();
437
438 T::regs().cfgr1().modify(|reg| {
439 reg.set_chselrmod(true);
440 reg.set_align(Align::RIGHT);
441 });
442
443 Self::setup_channel_sequencer(channel_sequence);
444
445 self.dma_convert(rx_dma, readings).await
446 }
447
448 fn configure_channel(channel: &mut impl AdcChannel<T>) {
449 channel.setup();
450 // write() because we want all other bits to be set to 0.
451 T::regs()
452 .chselr()
453 .write(|w| w.set_chsel(channel.channel().into(), true));
454
455 Self::apply_channel_conf();
456 }
457
458 fn apply_channel_conf() {
459 // Trigger and wait for the channel selection procedure to complete.
460 T::regs().isr().modify(|w| w.set_ccrdy(false));
461 while !T::regs().isr().read().ccrdy() {}
462 }
463
464 fn cancel_conversions() {
465 if T::regs().cr().read().adstart() && !T::regs().cr().read().addis() {
466 T::regs().cr().modify(|reg| {
467 reg.set_adstp(Adstp::STOP);
468 });
469 while T::regs().cr().read().adstart() {}
470 }
471 } 257 }
472} 258}
diff --git a/embassy-stm32/src/adc/f1.rs b/embassy-stm32/src/adc/f1.rs
index f9c23d72b..d6c6f480b 100644
--- a/embassy-stm32/src/adc/f1.rs
+++ b/embassy-stm32/src/adc/f1.rs
@@ -3,7 +3,7 @@ use core::marker::PhantomData;
3use core::task::Poll; 3use core::task::Poll;
4 4
5use super::blocking_delay_us; 5use super::blocking_delay_us;
6use crate::adc::{Adc, AdcChannel, Instance, SampleTime}; 6use crate::adc::{Adc, AdcChannel, Instance, SampleTime, VrefInt};
7use crate::interrupt::typelevel::Interrupt; 7use crate::interrupt::typelevel::Interrupt;
8use crate::interrupt::{self}; 8use crate::interrupt::{self};
9use crate::time::Hertz; 9use crate::time::Hertz;
@@ -28,20 +28,12 @@ impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandl
28 } 28 }
29} 29}
30 30
31pub struct Vref; 31impl<T: Instance> super::SealedSpecialConverter<VrefInt> for T {
32impl<T: Instance> AdcChannel<T> for Vref {} 32 const CHANNEL: u8 = 17;
33impl<T: Instance> super::SealedAdcChannel<T> for Vref {
34 fn channel(&self) -> u8 {
35 17
36 }
37} 33}
38 34
39pub struct Temperature; 35impl<T: Instance> super::SealedSpecialConverter<super::Temperature> for T {
40impl<T: Instance> AdcChannel<T> for Temperature {} 36 const CHANNEL: u8 = 16;
41impl<T: Instance> super::SealedAdcChannel<T> for Temperature {
42 fn channel(&self) -> u8 {
43 16
44 }
45} 37}
46 38
47impl<'d, T: Instance> Adc<'d, T> { 39impl<'d, T: Instance> Adc<'d, T> {
@@ -51,7 +43,7 @@ impl<'d, T: Instance> Adc<'d, T> {
51 43
52 // 11.4: Before starting a calibration, the ADC must have been in power-on state (ADON bit = ‘1’) 44 // 11.4: Before starting a calibration, the ADC must have been in power-on state (ADON bit = ‘1’)
53 // for at least two ADC clock cycles. 45 // for at least two ADC clock cycles.
54 blocking_delay_us((1_000_000 * 2) / Self::freq().0 + 1); 46 blocking_delay_us((1_000_000 * 2) / Self::freq().0 as u64 + 1);
55 47
56 // Reset calibration 48 // Reset calibration
57 T::regs().cr2().modify(|reg| reg.set_rstcal(true)); 49 T::regs().cr2().modify(|reg| reg.set_rstcal(true));
@@ -66,15 +58,12 @@ impl<'d, T: Instance> Adc<'d, T> {
66 } 58 }
67 59
68 // One cycle after calibration 60 // One cycle after calibration
69 blocking_delay_us((1_000_000 * 1) / Self::freq().0 + 1); 61 blocking_delay_us((1_000_000 * 1) / Self::freq().0 as u64 + 1);
70 62
71 T::Interrupt::unpend(); 63 T::Interrupt::unpend();
72 unsafe { T::Interrupt::enable() }; 64 unsafe { T::Interrupt::enable() };
73 65
74 Self { 66 Self { adc }
75 adc,
76 sample_time: SampleTime::from_bits(0),
77 }
78 } 67 }
79 68
80 fn freq() -> Hertz { 69 fn freq() -> Hertz {
@@ -94,22 +83,18 @@ impl<'d, T: Instance> Adc<'d, T> {
94 } 83 }
95 } 84 }
96 85
97 pub fn enable_vref(&self) -> Vref { 86 pub fn enable_vref(&self) -> super::VrefInt {
98 T::regs().cr2().modify(|reg| { 87 T::regs().cr2().modify(|reg| {
99 reg.set_tsvrefe(true); 88 reg.set_tsvrefe(true);
100 }); 89 });
101 Vref {} 90 super::VrefInt {}
102 } 91 }
103 92
104 pub fn enable_temperature(&self) -> Temperature { 93 pub fn enable_temperature(&self) -> super::Temperature {
105 T::regs().cr2().modify(|reg| { 94 T::regs().cr2().modify(|reg| {
106 reg.set_tsvrefe(true); 95 reg.set_tsvrefe(true);
107 }); 96 });
108 Temperature {} 97 super::Temperature {}
109 }
110
111 pub fn set_sample_time(&mut self, sample_time: SampleTime) {
112 self.sample_time = sample_time;
113 } 98 }
114 99
115 /// Perform a single conversion. 100 /// Perform a single conversion.
@@ -134,8 +119,8 @@ impl<'d, T: Instance> Adc<'d, T> {
134 T::regs().dr().read().0 as u16 119 T::regs().dr().read().0 as u16
135 } 120 }
136 121
137 pub async fn read(&mut self, channel: &mut impl AdcChannel<T>) -> u16 { 122 pub async fn read(&mut self, channel: &mut impl AdcChannel<T>, sample_time: SampleTime) -> u16 {
138 Self::set_channel_sample_time(channel.channel(), self.sample_time); 123 Self::set_channel_sample_time(channel.channel(), sample_time);
139 T::regs().cr1().modify(|reg| { 124 T::regs().cr1().modify(|reg| {
140 reg.set_scan(false); 125 reg.set_scan(false);
141 reg.set_discen(false); 126 reg.set_discen(false);
diff --git a/embassy-stm32/src/adc/f3.rs b/embassy-stm32/src/adc/f3.rs
index 73ceb087a..29bfdac97 100644
--- a/embassy-stm32/src/adc/f3.rs
+++ b/embassy-stm32/src/adc/f3.rs
@@ -3,7 +3,7 @@ use core::marker::PhantomData;
3use core::task::Poll; 3use core::task::Poll;
4 4
5use super::blocking_delay_us; 5use super::blocking_delay_us;
6use crate::adc::{Adc, AdcChannel, Instance, SampleTime}; 6use crate::adc::{Adc, AdcChannel, Instance, SampleTime, VrefInt};
7use crate::interrupt::typelevel::Interrupt; 7use crate::interrupt::typelevel::Interrupt;
8use crate::time::Hertz; 8use crate::time::Hertz;
9use crate::{Peri, interrupt, rcc}; 9use crate::{Peri, interrupt, rcc};
@@ -29,27 +29,12 @@ impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandl
29 } 29 }
30} 30}
31 31
32pub struct Vref; 32impl<T: Instance> super::SealedSpecialConverter<VrefInt> for T {
33impl<T: Instance> AdcChannel<T> for Vref {} 33 const CHANNEL: u8 = 18;
34impl<T: Instance> super::SealedAdcChannel<T> for Vref {
35 fn channel(&self) -> u8 {
36 18
37 }
38}
39
40impl Vref {
41 /// The value that vref would be if vdda was at 3300mv
42 pub fn value(&self) -> u16 {
43 crate::pac::VREFINTCAL.data().read()
44 }
45} 34}
46 35
47pub struct Temperature; 36impl<T: Instance> super::SealedSpecialConverter<super::Temperature> for T {
48impl<T: Instance> AdcChannel<T> for Temperature {} 37 const CHANNEL: u8 = 16;
49impl<T: Instance> super::SealedAdcChannel<T> for Temperature {
50 fn channel(&self) -> u8 {
51 16
52 }
53} 38}
54 39
55impl<'d, T: Instance> Adc<'d, T> { 40impl<'d, T: Instance> Adc<'d, T> {
@@ -77,7 +62,7 @@ impl<'d, T: Instance> Adc<'d, T> {
77 while T::regs().cr().read().adcal() {} 62 while T::regs().cr().read().adcal() {}
78 63
79 // Wait more than 4 clock cycles after adcal is cleared (RM0364 p. 223). 64 // Wait more than 4 clock cycles after adcal is cleared (RM0364 p. 223).
80 blocking_delay_us((1_000_000 * 4) / Self::freq().0 + 1); 65 blocking_delay_us((1_000_000 * 4) / Self::freq().0 as u64 + 1);
81 66
82 // Enable the adc 67 // Enable the adc
83 T::regs().cr().modify(|w| w.set_aden(true)); 68 T::regs().cr().modify(|w| w.set_aden(true));
@@ -90,10 +75,7 @@ impl<'d, T: Instance> Adc<'d, T> {
90 T::Interrupt::enable(); 75 T::Interrupt::enable();
91 } 76 }
92 77
93 Self { 78 Self { adc }
94 adc,
95 sample_time: SampleTime::from_bits(0),
96 }
97 } 79 }
98 80
99 fn freq() -> Hertz { 81 fn freq() -> Hertz {
@@ -112,20 +94,16 @@ impl<'d, T: Instance> Adc<'d, T> {
112 } 94 }
113 } 95 }
114 96
115 pub fn enable_vref(&self) -> Vref { 97 pub fn enable_vref(&self) -> super::VrefInt {
116 T::common_regs().ccr().modify(|w| w.set_vrefen(true)); 98 T::common_regs().ccr().modify(|w| w.set_vrefen(true));
117 99
118 Vref {} 100 super::VrefInt {}
119 } 101 }
120 102
121 pub fn enable_temperature(&self) -> Temperature { 103 pub fn enable_temperature(&self) -> super::Temperature {
122 T::common_regs().ccr().modify(|w| w.set_tsen(true)); 104 T::common_regs().ccr().modify(|w| w.set_tsen(true));
123 105
124 Temperature {} 106 super::Temperature {}
125 }
126
127 pub fn set_sample_time(&mut self, sample_time: SampleTime) {
128 self.sample_time = sample_time;
129 } 107 }
130 108
131 /// Perform a single conversion. 109 /// Perform a single conversion.
@@ -150,8 +128,8 @@ impl<'d, T: Instance> Adc<'d, T> {
150 T::regs().dr().read().rdata() 128 T::regs().dr().read().rdata()
151 } 129 }
152 130
153 pub async fn read(&mut self, channel: &mut impl AdcChannel<T>) -> u16 { 131 pub async fn read(&mut self, channel: &mut impl AdcChannel<T>, sample_time: SampleTime) -> u16 {
154 Self::set_channel_sample_time(channel.channel(), self.sample_time); 132 Self::set_channel_sample_time(channel.channel(), sample_time);
155 133
156 // Configure the channel to sample 134 // Configure the channel to sample
157 T::regs().sqr1().write(|w| w.set_sq(0, channel.channel())); 135 T::regs().sqr1().write(|w| w.set_sq(0, channel.channel()));
diff --git a/embassy-stm32/src/adc/f3_v1_1.rs b/embassy-stm32/src/adc/f3_v1_1.rs
index cd5de54f5..919ac3cc0 100644
--- a/embassy-stm32/src/adc/f3_v1_1.rs
+++ b/embassy-stm32/src/adc/f3_v1_1.rs
@@ -79,7 +79,7 @@ impl<T: Instance> Vref<T> {
79 } 79 }
80 80
81 pub async fn calibrate(&mut self, adc: &mut Adc<'_, T>) -> Calibration { 81 pub async fn calibrate(&mut self, adc: &mut Adc<'_, T>) -> Calibration {
82 let vref_val = adc.read(self).await; 82 let vref_val = adc.read(self, SampleTime::from(0)).await;
83 Calibration { 83 Calibration {
84 vref_cal: self.calibrated_value(), 84 vref_cal: self.calibrated_value(),
85 vref_val, 85 vref_val,
@@ -270,7 +270,8 @@ impl<'d, T: Instance> Adc<'d, T> {
270 } 270 }
271 } 271 }
272 272
273 pub async fn read(&mut self, channel: &mut impl AdcChannel<T>) -> u16 { 273 pub async fn read(&mut self, channel: &mut impl AdcChannel<T>, sample_time: SampleTime) -> u16 {
274 self.set_sample_time(channel, sample_time).await;
274 self.set_sample_sequence(&[channel.channel()]).await; 275 self.set_sample_sequence(&[channel.channel()]).await;
275 self.convert().await 276 self.convert().await
276 } 277 }
diff --git a/embassy-stm32/src/adc/g4.rs b/embassy-stm32/src/adc/g4.rs
index 3767820cf..bd8ccbf17 100644
--- a/embassy-stm32/src/adc/g4.rs
+++ b/embassy-stm32/src/adc/g4.rs
@@ -1,5 +1,5 @@
1use core::mem; 1#[cfg(stm32g4)]
2 2use pac::adc::regs::Difsel as DifselReg;
3#[allow(unused)] 3#[allow(unused)]
4#[cfg(stm32h7)] 4#[cfg(stm32h7)]
5use pac::adc::vals::{Adcaldif, Difsel, Exten}; 5use pac::adc::vals::{Adcaldif, Difsel, Exten};
@@ -10,15 +10,14 @@ pub use pac::adccommon::vals::Presc;
10pub use stm32_metapac::adc::vals::{Adstp, Dmacfg, Dmaen}; 10pub use stm32_metapac::adc::vals::{Adstp, Dmacfg, Dmaen};
11pub use stm32_metapac::adccommon::vals::Dual; 11pub use stm32_metapac::adccommon::vals::Dual;
12 12
13use super::{Adc, AdcChannel, AnyAdcChannel, Instance, Resolution, RxDma, SampleTime, blocking_delay_us}; 13use super::{
14use crate::adc::SealedAdcChannel; 14 Adc, AnyAdcChannel, ConversionMode, Instance, RegularConversionMode, Resolution, RxDma, SampleTime,
15use crate::dma::Transfer; 15 blocking_delay_us,
16};
17use crate::adc::{AnyInstance, SealedAdcChannel};
16use crate::time::Hertz; 18use crate::time::Hertz;
17use crate::{Peri, pac, rcc}; 19use crate::{Peri, pac, rcc};
18 20
19mod ringbuffered;
20pub use ringbuffered::RingBufferedAdc;
21
22mod injected; 21mod injected;
23pub use injected::InjectedAdc; 22pub use injected::InjectedAdc;
24 23
@@ -35,100 +34,31 @@ const MAX_ADC_CLK_FREQ: Hertz = Hertz::mhz(60);
35#[cfg(stm32h7)] 34#[cfg(stm32h7)]
36const MAX_ADC_CLK_FREQ: Hertz = Hertz::mhz(50); 35const MAX_ADC_CLK_FREQ: Hertz = Hertz::mhz(50);
37 36
38// NOTE: Vrefint/Temperature/Vbat are not available on all ADCs, this currently cannot be modeled with stm32-data, so these are available from the software on all ADCs 37fn from_ker_ck(frequency: Hertz) -> Presc {
39/// Internal voltage reference channel. 38 let raw_prescaler = frequency.0 / MAX_ADC_CLK_FREQ.0;
40pub struct VrefInt; 39 match raw_prescaler {
41impl<T: Instance + VrefChannel> AdcChannel<T> for VrefInt {} 40 0 => Presc::DIV1,
42impl<T: Instance + VrefChannel> super::SealedAdcChannel<T> for VrefInt { 41 1 => Presc::DIV2,
43 fn channel(&self) -> u8 { 42 2..=3 => Presc::DIV4,
44 T::CHANNEL 43 4..=5 => Presc::DIV6,
45 } 44 6..=7 => Presc::DIV8,
46} 45 8..=9 => Presc::DIV10,
47 46 10..=11 => Presc::DIV12,
48/// Internal temperature channel. 47 _ => unimplemented!(),
49pub struct Temperature;
50impl<T: Instance + TemperatureChannel> AdcChannel<T> for Temperature {}
51impl<T: Instance + TemperatureChannel> super::SealedAdcChannel<T> for Temperature {
52 fn channel(&self) -> u8 {
53 T::CHANNEL
54 } 48 }
55} 49}
56 50
57/// Internal battery voltage channel. 51/// ADC configuration
58pub struct Vbat; 52#[derive(Default)]
59impl<T: Instance + VBatChannel> AdcChannel<T> for Vbat {} 53pub struct AdcConfig {
60impl<T: Instance + VBatChannel> super::SealedAdcChannel<T> for Vbat { 54 pub dual_mode: Option<Dual>,
61 fn channel(&self) -> u8 { 55 pub resolution: Option<Resolution>,
62 T::CHANNEL 56 #[cfg(stm32g4)]
63 } 57 pub oversampling_shift: Option<u8>,
64} 58 #[cfg(stm32g4)]
65 59 pub oversampling_ratio: Option<u8>,
66// NOTE (unused): The prescaler enum closely copies the hardware capabilities, 60 #[cfg(stm32g4)]
67// but high prescaling doesn't make a lot of sense in the current implementation and is ommited. 61 pub oversampling_mode: Option<(Rovsm, Trovs, bool)>,
68#[allow(unused)]
69enum Prescaler {
70 NotDivided,
71 DividedBy2,
72 DividedBy4,
73 DividedBy6,
74 DividedBy8,
75 DividedBy10,
76 DividedBy12,
77 DividedBy16,
78 DividedBy32,
79 DividedBy64,
80 DividedBy128,
81 DividedBy256,
82}
83
84impl Prescaler {
85 fn from_ker_ck(frequency: Hertz) -> Self {
86 let raw_prescaler = frequency.0 / MAX_ADC_CLK_FREQ.0;
87 match raw_prescaler {
88 0 => Self::NotDivided,
89 1 => Self::DividedBy2,
90 2..=3 => Self::DividedBy4,
91 4..=5 => Self::DividedBy6,
92 6..=7 => Self::DividedBy8,
93 8..=9 => Self::DividedBy10,
94 10..=11 => Self::DividedBy12,
95 _ => unimplemented!(),
96 }
97 }
98
99 fn divisor(&self) -> u32 {
100 match self {
101 Prescaler::NotDivided => 1,
102 Prescaler::DividedBy2 => 2,
103 Prescaler::DividedBy4 => 4,
104 Prescaler::DividedBy6 => 6,
105 Prescaler::DividedBy8 => 8,
106 Prescaler::DividedBy10 => 10,
107 Prescaler::DividedBy12 => 12,
108 Prescaler::DividedBy16 => 16,
109 Prescaler::DividedBy32 => 32,
110 Prescaler::DividedBy64 => 64,
111 Prescaler::DividedBy128 => 128,
112 Prescaler::DividedBy256 => 256,
113 }
114 }
115
116 fn presc(&self) -> Presc {
117 match self {
118 Prescaler::NotDivided => Presc::DIV1,
119 Prescaler::DividedBy2 => Presc::DIV2,
120 Prescaler::DividedBy4 => Presc::DIV4,
121 Prescaler::DividedBy6 => Presc::DIV6,
122 Prescaler::DividedBy8 => Presc::DIV8,
123 Prescaler::DividedBy10 => Presc::DIV10,
124 Prescaler::DividedBy12 => Presc::DIV12,
125 Prescaler::DividedBy16 => Presc::DIV16,
126 Prescaler::DividedBy32 => Presc::DIV32,
127 Prescaler::DividedBy64 => Presc::DIV64,
128 Prescaler::DividedBy128 => Presc::DIV128,
129 Prescaler::DividedBy256 => Presc::DIV256,
130 }
131 }
132} 62}
133 63
134// Trigger source for ADC conversions¨ 64// Trigger source for ADC conversions¨
@@ -140,90 +70,12 @@ pub struct ConversionTrigger {
140 pub edge: Exten, 70 pub edge: Exten,
141} 71}
142 72
143// Conversion mode for regular ADC channels 73impl<T: Instance> super::SealedAnyInstance for T {
144#[derive(Copy, Clone)] 74 fn dr() -> *mut u16 {
145pub enum RegularConversionMode { 75 T::regs().dr().as_ptr() as *mut u16
146 // Samples as fast as possible
147 Continuous,
148 // Sample at rate determined by external trigger
149 Triggered(ConversionTrigger),
150}
151
152impl<'d, T: Instance> Adc<'d, T> {
153 /// Create a new ADC driver.
154 pub fn new(adc: Peri<'d, T>) -> Self {
155 rcc::enable_and_reset::<T>();
156
157 let prescaler = Prescaler::from_ker_ck(T::frequency());
158
159 T::common_regs().ccr().modify(|w| w.set_presc(prescaler.presc()));
160
161 let frequency = Hertz(T::frequency().0 / prescaler.divisor());
162 trace!("ADC frequency set to {}", frequency);
163
164 if frequency > MAX_ADC_CLK_FREQ {
165 panic!(
166 "Maximal allowed frequency for the ADC is {} MHz and it varies with different packages, refer to ST docs for more information.",
167 MAX_ADC_CLK_FREQ.0 / 1_000_000
168 );
169 }
170
171 let mut s = Self {
172 adc,
173 sample_time: SampleTime::from_bits(0),
174 };
175 s.power_up();
176 s.configure_differential_inputs();
177
178 s.calibrate();
179 blocking_delay_us(1);
180
181 s.enable();
182 s.configure();
183
184 s
185 }
186
187 fn power_up(&mut self) {
188 T::regs().cr().modify(|reg| {
189 reg.set_deeppwd(false);
190 reg.set_advregen(true);
191 });
192
193 blocking_delay_us(20);
194 }
195
196 fn configure_differential_inputs(&mut self) {
197 T::regs().difsel().modify(|w| {
198 for n in 0..18 {
199 w.set_difsel(n, Difsel::SINGLE_ENDED);
200 }
201 });
202 } 76 }
203 77
204 fn calibrate(&mut self) { 78 fn enable() {
205 T::regs().cr().modify(|w| {
206 w.set_adcaldif(Adcaldif::SINGLE_ENDED);
207 });
208
209 T::regs().cr().modify(|w| w.set_adcal(true));
210
211 while T::regs().cr().read().adcal() {}
212
213 blocking_delay_us(20);
214
215 T::regs().cr().modify(|w| {
216 w.set_adcaldif(Adcaldif::DIFFERENTIAL);
217 });
218
219 T::regs().cr().modify(|w| w.set_adcal(true));
220
221 while T::regs().cr().read().adcal() {}
222
223 blocking_delay_us(20);
224 }
225
226 fn enable(&mut self) {
227 // Make sure bits are off 79 // Make sure bits are off
228 while T::regs().cr().read().addis() { 80 while T::regs().cr().read().addis() {
229 // spin 81 // spin
@@ -244,124 +96,30 @@ impl<'d, T: Instance> Adc<'d, T> {
244 } 96 }
245 } 97 }
246 98
247 fn configure(&mut self) { 99 fn start() {
248 // single conversion mode, software trigger 100 T::regs().cr().modify(|reg| {
249 T::regs().cfgr().modify(|w| { 101 reg.set_adstart(true);
250 w.set_cont(false);
251 w.set_exten(Exten::DISABLED);
252 });
253 }
254
255 /// Enable reading the voltage reference internal channel.
256 pub fn enable_vrefint(&self) -> VrefInt
257 where
258 T: VrefChannel,
259 {
260 T::common_regs().ccr().modify(|reg| {
261 reg.set_vrefen(true);
262 });
263
264 VrefInt {}
265 }
266
267 /// Enable reading the temperature internal channel.
268 pub fn enable_temperature(&self) -> Temperature
269 where
270 T: TemperatureChannel,
271 {
272 T::common_regs().ccr().modify(|reg| {
273 reg.set_vsenseen(true);
274 }); 102 });
275
276 Temperature {}
277 } 103 }
278 104
279 /// Enable reading the vbat internal channel. 105 fn stop() {
280 pub fn enable_vbat(&self) -> Vbat 106 if T::regs().cr().read().adstart() && !T::regs().cr().read().addis() {
281 where 107 T::regs().cr().modify(|reg| {
282 T: VBatChannel, 108 reg.set_adstp(Adstp::STOP);
283 { 109 });
284 T::common_regs().ccr().modify(|reg| { 110 // The software must poll ADSTART until the bit is reset before assuming the
285 reg.set_vbaten(true); 111 // ADC is completely stopped
286 }); 112 while T::regs().cr().read().adstart() {}
287 113 }
288 Vbat {}
289 }
290 114
291 /// Enable differential channel. 115 // Disable dma control and continuous conversion, if enabled
292 /// Caution: 116 T::regs().cfgr().modify(|reg| {
293 /// : When configuring the channel “i” in differential input mode, its negative input voltage VINN[i] 117 reg.set_cont(false);
294 /// is connected to another channel. As a consequence, this channel is no longer usable in 118 reg.set_dmaen(Dmaen::DISABLE);
295 /// single-ended mode or in differential mode and must never be configured to be converted.
296 /// Some channels are shared between ADC1/ADC2/ADC3/ADC4/ADC5: this can make the
297 /// channel on the other ADC unusable. The only exception is when ADC master and the slave
298 /// operate in interleaved mode.
299 #[cfg(stm32g4)]
300 pub fn set_differential_channel(&mut self, ch: usize, enable: bool) {
301 T::regs().cr().modify(|w| w.set_aden(false)); // disable adc
302 T::regs().difsel().modify(|w| {
303 w.set_difsel(
304 ch,
305 if enable {
306 Difsel::DIFFERENTIAL
307 } else {
308 Difsel::SINGLE_ENDED
309 },
310 );
311 }); 119 });
312 T::regs().cr().modify(|w| w.set_aden(true));
313 }
314
315 #[cfg(stm32g4)]
316 pub fn set_differential(&mut self, channel: &mut impl AdcChannel<T>, enable: bool) {
317 self.set_differential_channel(channel.channel() as usize, enable);
318 }
319
320 /// Set oversampling shift.
321 #[cfg(stm32g4)]
322 pub fn set_oversampling_shift(&mut self, shift: u8) {
323 T::regs().cfgr2().modify(|reg| reg.set_ovss(shift));
324 }
325
326 /// Set oversampling ratio.
327 #[cfg(stm32g4)]
328 pub fn set_oversampling_ratio(&mut self, ratio: u8) {
329 T::regs().cfgr2().modify(|reg| reg.set_ovsr(ratio));
330 }
331
332 /// Enable oversampling in regular mode.
333 #[cfg(stm32g4)]
334 pub fn enable_regular_oversampling_mode(&mut self, mode: Rovsm, trig_mode: Trovs, enable: bool) {
335 T::regs().cfgr2().modify(|reg| reg.set_trovs(trig_mode));
336 T::regs().cfgr2().modify(|reg| reg.set_rovsm(mode));
337 T::regs().cfgr2().modify(|reg| reg.set_rovse(enable));
338 }
339
340 // Reads that are not implemented as INJECTED in "blocking_read"
341 // #[cfg(stm32g4)]
342 // pub fn enalble_injected_oversampling_mode(&mut self, enable: bool) {
343 // T::regs().cfgr2().modify(|reg| reg.set_jovse(enable));
344 // }
345
346 // #[cfg(stm32g4)]
347 // pub fn enable_oversampling_regular_injected_mode(&mut self, enable: bool) {
348 // // the regularoversampling mode is forced to resumed mode (ROVSM bit ignored),
349 // T::regs().cfgr2().modify(|reg| reg.set_rovse(enable));
350 // T::regs().cfgr2().modify(|reg| reg.set_jovse(enable));
351 // }
352
353 /// Set the ADC sample time.
354 pub fn set_sample_time(&mut self, sample_time: SampleTime) {
355 self.sample_time = sample_time;
356 }
357
358 /// Set the ADC resolution.
359 pub fn set_resolution(&mut self, resolution: Resolution) {
360 T::regs().cfgr().modify(|reg| reg.set_res(resolution.into()));
361 } 120 }
362 121
363 /// Perform a single conversion. 122 fn convert() -> u16 {
364 fn convert(&mut self) -> u16 {
365 T::regs().isr().modify(|reg| { 123 T::regs().isr().modify(|reg| {
366 reg.set_eos(true); 124 reg.set_eos(true);
367 reg.set_eoc(true); 125 reg.set_eoc(true);
@@ -379,277 +137,249 @@ impl<'d, T: Instance> Adc<'d, T> {
379 T::regs().dr().read().0 as u16 137 T::regs().dr().read().0 as u16
380 } 138 }
381 139
382 /// Read an ADC pin. 140 fn configure_dma(conversion_mode: ConversionMode) {
383 pub fn blocking_read(&mut self, channel: &mut impl AdcChannel<T>) -> u16 { 141 T::regs().isr().modify(|reg| {
384 channel.setup(); 142 reg.set_ovr(true);
385
386 self.read_channel(channel)
387 }
388
389 /// Start regular adc conversion
390 pub(super) fn start() {
391 T::regs().cr().modify(|reg| {
392 reg.set_adstart(true);
393 }); 143 });
394 }
395
396 /// Stop regular conversions
397 pub(super) fn stop() {
398 Self::stop_regular_conversions();
399 }
400
401 /// Teardown method for stopping regular ADC conversions
402 pub(super) fn teardown_adc() {
403 Self::stop_regular_conversions();
404 144
405 // Disable dma control
406 T::regs().cfgr().modify(|reg| { 145 T::regs().cfgr().modify(|reg| {
407 reg.set_dmaen(Dmaen::DISABLE); 146 reg.set_discen(false); // Convert all channels for each trigger
147 reg.set_dmacfg(match conversion_mode {
148 ConversionMode::Singular => Dmacfg::ONE_SHOT,
149 ConversionMode::Repeated(_) => Dmacfg::CIRCULAR,
150 });
151 reg.set_dmaen(Dmaen::ENABLE);
408 }); 152 });
409 }
410 153
411 /// Read one or multiple ADC regular channels using DMA. 154 if let ConversionMode::Repeated(mode) = conversion_mode {
412 /// 155 match mode {
413 /// `sequence` iterator and `readings` must have the same length. 156 RegularConversionMode::Continuous => {
414 /// 157 T::regs().cfgr().modify(|reg| {
415 /// Example 158 reg.set_cont(true);
416 /// ```rust,ignore 159 });
417 /// use embassy_stm32::adc::{Adc, AdcChannel} 160 }
418 /// 161 RegularConversionMode::Triggered(trigger) => {
419 /// let mut adc = Adc::new(p.ADC1); 162 T::regs().cfgr().modify(|r| {
420 /// let mut adc_pin0 = p.PA0.into(); 163 r.set_cont(false); // New trigger is neede for each sample to be read
421 /// let mut adc_pin1 = p.PA1.into(); 164 });
422 /// let mut measurements = [0u16; 2];
423 ///
424 /// adc.read(
425 /// p.DMA1_CH2.reborrow(),
426 /// [
427 /// (&mut *adc_pin0, SampleTime::CYCLES160_5),
428 /// (&mut *adc_pin1, SampleTime::CYCLES160_5),
429 /// ]
430 /// .into_iter(),
431 /// &mut measurements,
432 /// )
433 /// .await;
434 /// defmt::info!("measurements: {}", measurements);
435 /// ```
436 ///
437 /// Note: This is not very efficient as the ADC needs to be reconfigured for each read. Use
438 /// `into_ring_buffered`, `into_ring_buffered_and_injected`
439 pub async fn read(
440 &mut self,
441 rx_dma: Peri<'_, impl RxDma<T>>,
442 sequence: impl ExactSizeIterator<Item = (&mut AnyAdcChannel<T>, SampleTime)>,
443 readings: &mut [u16],
444 ) {
445 assert!(sequence.len() != 0, "Asynchronous read sequence cannot be empty");
446 assert!(
447 sequence.len() == readings.len(),
448 "Sequence length must be equal to readings length"
449 );
450 assert!(
451 sequence.len() <= 16,
452 "Asynchronous read sequence cannot be more than 16 in length"
453 );
454 165
455 // Ensure no conversions are ongoing and ADC is enabled. 166 T::regs().cfgr().modify(|r| {
456 Self::stop_regular_conversions(); 167 r.set_extsel(trigger.channel);
457 self.enable(); 168 r.set_exten(trigger.edge);
169 });
170
171 // Regular conversions uses DMA so no need to generate interrupt
172 T::regs().ier().modify(|r| r.set_eosie(false));
173 }
174 }
175 }
176 }
458 177
178 fn configure_sequence(sequence: impl ExactSizeIterator<Item = ((u8, bool), SampleTime)>) {
459 // Set sequence length 179 // Set sequence length
460 T::regs().sqr1().modify(|w| { 180 T::regs().sqr1().modify(|w| {
461 w.set_l(sequence.len() as u8 - 1); 181 w.set_l(sequence.len() as u8 - 1);
462 }); 182 });
183
184 #[cfg(stm32g4)]
185 let mut difsel = DifselReg::default();
186
463 // Configure channels and ranks 187 // Configure channels and ranks
464 for (_i, (channel, sample_time)) in sequence.enumerate() { 188 for (_i, ((ch, is_differential), sample_time)) in sequence.enumerate() {
465 Self::configure_channel(channel, sample_time); 189 let sample_time = sample_time.into();
190 if ch <= 9 {
191 T::regs().smpr().modify(|reg| reg.set_smp(ch as _, sample_time));
192 } else {
193 T::regs().smpr2().modify(|reg| reg.set_smp((ch - 10) as _, sample_time));
194 }
195
466 match _i { 196 match _i {
467 0..=3 => { 197 0..=3 => {
468 T::regs().sqr1().modify(|w| { 198 T::regs().sqr1().modify(|w| {
469 w.set_sq(_i, channel.channel()); 199 w.set_sq(_i, ch);
470 }); 200 });
471 } 201 }
472 4..=8 => { 202 4..=8 => {
473 T::regs().sqr2().modify(|w| { 203 T::regs().sqr2().modify(|w| {
474 w.set_sq(_i - 4, channel.channel()); 204 w.set_sq(_i - 4, ch);
475 }); 205 });
476 } 206 }
477 9..=13 => { 207 9..=13 => {
478 T::regs().sqr3().modify(|w| { 208 T::regs().sqr3().modify(|w| {
479 w.set_sq(_i - 9, channel.channel()); 209 w.set_sq(_i - 9, ch);
480 }); 210 });
481 } 211 }
482 14..=15 => { 212 14..=15 => {
483 T::regs().sqr4().modify(|w| { 213 T::regs().sqr4().modify(|w| {
484 w.set_sq(_i - 14, channel.channel()); 214 w.set_sq(_i - 14, ch);
485 }); 215 });
486 } 216 }
487 _ => unreachable!(), 217 _ => unreachable!(),
488 } 218 }
219
220 #[cfg(stm32g4)]
221 {
222 if ch < 18 {
223 difsel.set_difsel(
224 ch.into(),
225 if is_differential {
226 Difsel::DIFFERENTIAL
227 } else {
228 Difsel::SINGLE_ENDED
229 },
230 );
231 }
232 }
489 } 233 }
490 234
491 // Set continuous mode with oneshot dma. 235 #[cfg(stm32g4)]
492 // Clear overrun flag before starting transfer. 236 {
493 T::regs().isr().modify(|reg| { 237 T::regs().cr().modify(|w| w.set_aden(false));
494 reg.set_ovr(true); 238 T::regs().difsel().write_value(difsel);
495 }); 239 T::enable();
240 }
241 }
242}
496 243
497 T::regs().cfgr().modify(|reg| { 244impl<'d, T: Instance + AnyInstance> Adc<'d, T> {
498 reg.set_discen(false); 245 /// Create a new ADC driver.
499 reg.set_cont(true); 246 pub fn new(adc: Peri<'d, T>, config: AdcConfig) -> Self {
500 reg.set_dmacfg(Dmacfg::ONE_SHOT); 247 rcc::enable_and_reset::<T>();
501 reg.set_dmaen(Dmaen::ENABLE);
502 });
503 248
504 let request = rx_dma.request(); 249 let prescaler = from_ker_ck(T::frequency());
505 let transfer = unsafe { 250
506 Transfer::new_read( 251 T::common_regs().ccr().modify(|w| w.set_presc(prescaler));
507 rx_dma, 252
508 request, 253 let frequency = T::frequency() / prescaler;
509 T::regs().dr().as_ptr() as *mut u16, 254 trace!("ADC frequency set to {}", frequency);
510 readings, 255
511 Default::default(), 256 if frequency > MAX_ADC_CLK_FREQ {
512 ) 257 panic!(
513 }; 258 "Maximal allowed frequency for the ADC is {} MHz and it varies with different packages, refer to ST docs for more information.",
259 MAX_ADC_CLK_FREQ.0 / 1_000_000
260 );
261 }
514 262
515 // Start conversion
516 T::regs().cr().modify(|reg| { 263 T::regs().cr().modify(|reg| {
517 reg.set_adstart(true); 264 reg.set_deeppwd(false);
265 reg.set_advregen(true);
518 }); 266 });
519 267
520 // Wait for conversion sequence to finish. 268 blocking_delay_us(20);
521 transfer.await;
522 269
523 // Ensure conversions are finished. 270 T::regs().difsel().modify(|w| {
524 Self::stop_regular_conversions(); 271 for n in 0..18 {
272 w.set_difsel(n, Difsel::SINGLE_ENDED);
273 }
274 });
525 275
526 // Reset configuration. 276 T::regs().cr().modify(|w| {
527 T::regs().cfgr().modify(|reg| { 277 w.set_adcaldif(Adcaldif::SINGLE_ENDED);
528 reg.set_cont(false);
529 }); 278 });
530 }
531 279
532 /// Set external trigger for regular conversion sequence 280 T::regs().cr().modify(|w| w.set_adcal(true));
533 fn set_regular_conversion_trigger(&mut self, trigger: ConversionTrigger) { 281
534 T::regs().cfgr().modify(|r| { 282 while T::regs().cr().read().adcal() {}
535 r.set_extsel(trigger.channel); 283
536 r.set_exten(trigger.edge); 284 blocking_delay_us(20);
285
286 T::regs().cr().modify(|w| {
287 w.set_adcaldif(Adcaldif::DIFFERENTIAL);
537 }); 288 });
538 // Regular conversions uses DMA so no need to generate interrupt
539 T::regs().ier().modify(|r| r.set_eosie(false));
540 }
541 289
542 // Dual ADC mode selection 290 T::regs().cr().modify(|w| w.set_adcal(true));
543 pub fn configure_dual_mode(&mut self, val: Dual) {
544 T::common_regs().ccr().modify(|reg| {
545 reg.set_dual(val);
546 })
547 }
548 291
549 /// Configures the ADC to use a DMA ring buffer for continuous data acquisition. 292 while T::regs().cr().read().adcal() {}
550 ///
551 /// Use the [`read`] method to retrieve measurements from the DMA ring buffer. The read buffer
552 /// should be exactly half the size of `dma_buf`. When using triggered mode, it is recommended
553 /// to configure `dma_buf` as a double buffer so that one half can be read while the other half
554 /// is being filled by the DMA, preventing data loss. The trigger period of the ADC effectively
555 /// defines the period at which the buffer should be read.
556 ///
557 /// If continous conversion mode is selected, the provided `dma_buf` must be large enough to prevent
558 /// DMA buffer overruns. Its length should be a multiple of the number of ADC channels being measured.
559 /// For example, if 3 channels are measured and you want to store 40 samples per channel,
560 /// the buffer length should be `3 * 40 = 120`.
561 ///
562 /// # Parameters
563 /// - `dma`: The DMA peripheral used to transfer ADC data into the buffer.
564 /// - `dma_buf`: The buffer where DMA stores ADC samples.
565 /// - `regular_sequence`: Sequence of channels and sample times for regular ADC conversions.
566 /// - `regular_conversion_mode`: Mode for regular conversions (continuous or triggered).
567 ///
568 /// # Returns
569 /// A `RingBufferedAdc<'a, T>` instance configured for continuous DMA-based sampling.
570 pub fn into_ring_buffered<'a>(
571 mut self,
572 dma: Peri<'a, impl RxDma<T>>,
573 dma_buf: &'a mut [u16],
574 sequence: impl ExactSizeIterator<Item = (AnyAdcChannel<T>, SampleTime)>,
575 mode: RegularConversionMode,
576 ) -> RingBufferedAdc<'a, T> {
577 assert!(!dma_buf.is_empty() && dma_buf.len() <= 0xFFFF);
578 assert!(sequence.len() != 0, "Asynchronous read sequence cannot be empty");
579 assert!(
580 sequence.len() <= 16,
581 "Asynchronous read sequence cannot be more than 16 in length"
582 );
583 // reset conversions and enable the adc
584 Self::stop_regular_conversions();
585 self.enable();
586 293
587 //adc side setup 294 blocking_delay_us(20);
588 295
589 // Set sequence length 296 T::enable();
590 T::regs().sqr1().modify(|w| { 297
591 w.set_l(sequence.len() as u8 - 1); 298 // single conversion mode, software trigger
299 T::regs().cfgr().modify(|w| {
300 w.set_cont(false);
301 w.set_exten(Exten::DISABLED);
592 }); 302 });
593 303
594 // Configure channels and ranks 304 if let Some(dual) = config.dual_mode {
595 for (_i, (mut channel, sample_time)) in sequence.enumerate() { 305 T::common_regs().ccr().modify(|reg| {
596 Self::configure_channel(&mut channel, sample_time); 306 reg.set_dual(dual);
307 })
308 }
597 309
598 match _i { 310 if let Some(resolution) = config.resolution {
599 0..=3 => { 311 T::regs().cfgr().modify(|reg| reg.set_res(resolution.into()));
600 T::regs().sqr1().modify(|w| {
601 w.set_sq(_i, channel.channel());
602 });
603 }
604 4..=8 => {
605 T::regs().sqr2().modify(|w| {
606 w.set_sq(_i - 4, channel.channel());
607 });
608 }
609 9..=13 => {
610 T::regs().sqr3().modify(|w| {
611 w.set_sq(_i - 9, channel.channel());
612 });
613 }
614 14..=15 => {
615 T::regs().sqr4().modify(|w| {
616 w.set_sq(_i - 14, channel.channel());
617 });
618 }
619 _ => unreachable!(),
620 }
621 } 312 }
622 313
623 // Clear overrun flag before starting transfer. 314 #[cfg(stm32g4)]
624 T::regs().isr().modify(|reg| { 315 if let Some(shift) = config.oversampling_shift {
625 reg.set_ovr(true); 316 T::regs().cfgr2().modify(|reg| reg.set_ovss(shift));
317 }
318
319 #[cfg(stm32g4)]
320 if let Some(ratio) = config.oversampling_ratio {
321 T::regs().cfgr2().modify(|reg| reg.set_ovsr(ratio));
322 }
323
324 #[cfg(stm32g4)]
325 if let Some((mode, trig_mode, enable)) = config.oversampling_mode {
326 T::regs().cfgr2().modify(|reg| reg.set_trovs(trig_mode));
327 T::regs().cfgr2().modify(|reg| reg.set_rovsm(mode));
328 T::regs().cfgr2().modify(|reg| reg.set_rovse(enable));
329 }
330
331 Self { adc }
332 }
333
334 /// Enable reading the voltage reference internal channel.
335 pub fn enable_vrefint(&self) -> super::VrefInt
336 where
337 T: super::SpecialConverter<super::VrefInt>,
338 {
339 T::common_regs().ccr().modify(|reg| {
340 reg.set_vrefen(true);
626 }); 341 });
627 342
628 T::regs().cfgr().modify(|reg| { 343 super::VrefInt {}
629 reg.set_discen(false); // Convert all channels for each trigger 344 }
630 reg.set_dmacfg(Dmacfg::CIRCULAR); 345
631 reg.set_dmaen(Dmaen::ENABLE); 346 /// Enable reading the temperature internal channel.
347 pub fn enable_temperature(&self) -> super::Temperature
348 where
349 T: super::SpecialConverter<super::Temperature>,
350 {
351 T::common_regs().ccr().modify(|reg| {
352 reg.set_vsenseen(true);
632 }); 353 });
633 354
634 match mode { 355 super::Temperature {}
635 RegularConversionMode::Continuous => { 356 }
636 T::regs().cfgr().modify(|reg| {
637 reg.set_cont(true);
638 });
639 }
640 RegularConversionMode::Triggered(trigger) => {
641 T::regs().cfgr().modify(|r| {
642 r.set_cont(false); // New trigger is neede for each sample to be read
643 });
644 self.set_regular_conversion_trigger(trigger);
645 }
646 }
647 357
648 mem::forget(self); 358 /// Enable reading the vbat internal channel.
359 pub fn enable_vbat(&self) -> super::Vbat
360 where
361 T: super::SpecialConverter<super::Vbat>,
362 {
363 T::common_regs().ccr().modify(|reg| {
364 reg.set_vbaten(true);
365 });
649 366
650 RingBufferedAdc::new(dma, dma_buf) 367 super::Vbat {}
651 } 368 }
652 369
370 // Reads that are not implemented as INJECTED in "blocking_read"
371 // #[cfg(stm32g4)]
372 // pub fn enalble_injected_oversampling_mode(&mut self, enable: bool) {
373 // T::regs().cfgr2().modify(|reg| reg.set_jovse(enable));
374 // }
375
376 // #[cfg(stm32g4)]
377 // pub fn enable_oversampling_regular_injected_mode(&mut self, enable: bool) {
378 // // the regularoversampling mode is forced to resumed mode (ROVSM bit ignored),
379 // T::regs().cfgr2().modify(|reg| reg.set_rovse(enable));
380 // T::regs().cfgr2().modify(|reg| reg.set_jovse(enable));
381 // }
382
653 /// Configures the ADC for injected conversions. 383 /// Configures the ADC for injected conversions.
654 /// 384 ///
655 /// Injected conversions are separate from the regular conversion sequence and are typically 385 /// Injected conversions are separate from the regular conversion sequence and are typically
@@ -678,7 +408,7 @@ impl<'d, T: Instance> Adc<'d, T> {
678 /// - Accessing samples beyond `N` will result in a panic; use the returned type 408 /// - Accessing samples beyond `N` will result in a panic; use the returned type
679 /// `InjectedAdc<T, N>` to enforce bounds at compile time. 409 /// `InjectedAdc<T, N>` to enforce bounds at compile time.
680 pub fn setup_injected_conversions<'a, const N: usize>( 410 pub fn setup_injected_conversions<'a, const N: usize>(
681 mut self, 411 self,
682 sequence: [(AnyAdcChannel<T>, SampleTime); N], 412 sequence: [(AnyAdcChannel<T>, SampleTime); N],
683 trigger: ConversionTrigger, 413 trigger: ConversionTrigger,
684 interrupt: bool, 414 interrupt: bool,
@@ -690,13 +420,21 @@ impl<'d, T: Instance> Adc<'d, T> {
690 NR_INJECTED_RANKS 420 NR_INJECTED_RANKS
691 ); 421 );
692 422
693 Self::stop_regular_conversions(); 423 T::enable();
694 self.enable();
695 424
696 T::regs().jsqr().modify(|w| w.set_jl(N as u8 - 1)); 425 T::regs().jsqr().modify(|w| w.set_jl(N as u8 - 1));
697 426
698 for (n, (mut channel, sample_time)) in sequence.into_iter().enumerate() { 427 for (n, (channel, sample_time)) in sequence.into_iter().enumerate() {
699 Self::configure_channel(&mut channel, sample_time); 428 let sample_time = sample_time.into();
429 if channel.channel() <= 9 {
430 T::regs()
431 .smpr()
432 .modify(|reg| reg.set_smp(channel.channel() as _, sample_time));
433 } else {
434 T::regs()
435 .smpr2()
436 .modify(|reg| reg.set_smp((channel.channel() - 10) as _, sample_time));
437 }
700 438
701 let idx = match n { 439 let idx = match n {
702 0..=3 => n, 440 0..=3 => n,
@@ -711,8 +449,16 @@ impl<'d, T: Instance> Adc<'d, T> {
711 449
712 T::regs().cfgr().modify(|reg| reg.set_jdiscen(false)); 450 T::regs().cfgr().modify(|reg| reg.set_jdiscen(false));
713 451
714 self.set_injected_conversion_trigger(trigger); 452 // Set external trigger for injected conversion sequence
715 self.enable_injected_eos_interrupt(interrupt); 453 // Possible trigger values are seen in Table 167 in RM0440 Rev 9
454 T::regs().jsqr().modify(|r| {
455 r.set_jextsel(trigger.channel);
456 r.set_jexten(trigger.edge);
457 });
458
459 // Enable end of injected sequence interrupt
460 T::regs().ier().modify(|r| r.set_jeosie(interrupt));
461
716 Self::start_injected_conversions(); 462 Self::start_injected_conversions();
717 463
718 InjectedAdc::new(sequence) // InjectedAdc<'a, T, N> now borrows the channels 464 InjectedAdc::new(sequence) // InjectedAdc<'a, T, N> now borrows the channels
@@ -745,22 +491,20 @@ impl<'d, T: Instance> Adc<'d, T> {
745 self, 491 self,
746 dma: Peri<'a, impl RxDma<T>>, 492 dma: Peri<'a, impl RxDma<T>>,
747 dma_buf: &'a mut [u16], 493 dma_buf: &'a mut [u16],
748 regular_sequence: impl ExactSizeIterator<Item = (AnyAdcChannel<T>, SampleTime)>, 494 regular_sequence: impl ExactSizeIterator<Item = (AnyAdcChannel<T>, T::SampleTime)>,
749 regular_conversion_mode: RegularConversionMode, 495 regular_conversion_mode: RegularConversionMode,
750 injected_sequence: [(AnyAdcChannel<T>, SampleTime); N], 496 injected_sequence: [(AnyAdcChannel<T>, SampleTime); N],
751 injected_trigger: ConversionTrigger, 497 injected_trigger: ConversionTrigger,
752 injected_interrupt: bool, 498 injected_interrupt: bool,
753 ) -> (RingBufferedAdc<'a, T>, InjectedAdc<T, N>) { 499 ) -> (super::RingBufferedAdc<'a, T>, InjectedAdc<T, N>) {
754 unsafe { 500 unsafe {
755 ( 501 (
756 Self { 502 Self {
757 adc: self.adc.clone_unchecked(), 503 adc: self.adc.clone_unchecked(),
758 sample_time: self.sample_time,
759 } 504 }
760 .into_ring_buffered(dma, dma_buf, regular_sequence, regular_conversion_mode), 505 .into_ring_buffered(dma, dma_buf, regular_sequence, regular_conversion_mode),
761 Self { 506 Self {
762 adc: self.adc.clone_unchecked(), 507 adc: self.adc.clone_unchecked(),
763 sample_time: self.sample_time,
764 } 508 }
765 .setup_injected_conversions(injected_sequence, injected_trigger, injected_interrupt), 509 .setup_injected_conversions(injected_sequence, injected_trigger, injected_interrupt),
766 ) 510 )
@@ -785,64 +529,6 @@ impl<'d, T: Instance> Adc<'d, T> {
785 reg.set_jadstart(true); 529 reg.set_jadstart(true);
786 }); 530 });
787 } 531 }
788
789 /// Set external trigger for injected conversion sequence
790 /// Possible trigger values are seen in Table 167 in RM0440 Rev 9
791 fn set_injected_conversion_trigger(&mut self, trigger: ConversionTrigger) {
792 T::regs().jsqr().modify(|r| {
793 r.set_jextsel(trigger.channel);
794 r.set_jexten(trigger.edge);
795 });
796 }
797
798 /// Enable end of injected sequence interrupt
799 fn enable_injected_eos_interrupt(&mut self, enable: bool) {
800 T::regs().ier().modify(|r| r.set_jeosie(enable));
801 }
802
803 fn configure_channel(channel: &mut impl AdcChannel<T>, sample_time: SampleTime) {
804 // Configure channel
805 Self::set_channel_sample_time(channel.channel(), sample_time);
806 }
807
808 fn read_channel(&mut self, channel: &mut impl AdcChannel<T>) -> u16 {
809 Self::configure_channel(channel, self.sample_time);
810 #[cfg(stm32h7)]
811 {
812 T::regs().cfgr2().modify(|w| w.set_lshift(0));
813 T::regs()
814 .pcsel()
815 .write(|w| w.set_pcsel(channel.channel() as _, Pcsel::PRESELECTED));
816 }
817
818 T::regs().sqr1().write(|reg| {
819 reg.set_sq(0, channel.channel());
820 reg.set_l(0);
821 });
822
823 self.convert()
824 }
825
826 fn set_channel_sample_time(ch: u8, sample_time: SampleTime) {
827 let sample_time = sample_time.into();
828 if ch <= 9 {
829 T::regs().smpr().modify(|reg| reg.set_smp(ch as _, sample_time));
830 } else {
831 T::regs().smpr2().modify(|reg| reg.set_smp((ch - 10) as _, sample_time));
832 }
833 }
834
835 // Stop regular conversions
836 fn stop_regular_conversions() {
837 if T::regs().cr().read().adstart() && !T::regs().cr().read().addis() {
838 T::regs().cr().modify(|reg| {
839 reg.set_adstp(Adstp::STOP);
840 });
841 // The software must poll ADSTART until the bit is reset before assuming the
842 // ADC is completely stopped
843 while T::regs().cr().read().adstart() {}
844 }
845 }
846} 532}
847 533
848impl<T: Instance, const N: usize> InjectedAdc<T, N> { 534impl<T: Instance, const N: usize> InjectedAdc<T, N> {
@@ -860,62 +546,49 @@ impl<T: Instance, const N: usize> InjectedAdc<T, N> {
860 } 546 }
861} 547}
862 548
863/// Implemented for ADCs that have a Temperature channel
864pub trait TemperatureChannel {
865 const CHANNEL: u8;
866}
867/// Implemented for ADCs that have a Vref channel
868pub trait VrefChannel {
869 const CHANNEL: u8;
870}
871/// Implemented for ADCs that have a VBat channel
872pub trait VBatChannel {
873 const CHANNEL: u8;
874}
875
876#[cfg(stm32g4)] 549#[cfg(stm32g4)]
877mod g4 { 550mod g4 {
878 pub use super::*; 551 use crate::adc::{SealedSpecialConverter, Temperature, Vbat, VrefInt};
879 552
880 impl TemperatureChannel for crate::peripherals::ADC1 { 553 impl SealedSpecialConverter<Temperature> for crate::peripherals::ADC1 {
881 const CHANNEL: u8 = 16; 554 const CHANNEL: u8 = 16;
882 } 555 }
883 556
884 impl VrefChannel for crate::peripherals::ADC1 { 557 impl SealedSpecialConverter<VrefInt> for crate::peripherals::ADC1 {
885 const CHANNEL: u8 = 18; 558 const CHANNEL: u8 = 18;
886 } 559 }
887 560
888 impl VBatChannel for crate::peripherals::ADC1 { 561 impl SealedSpecialConverter<Vbat> for crate::peripherals::ADC1 {
889 const CHANNEL: u8 = 17; 562 const CHANNEL: u8 = 17;
890 } 563 }
891 564
892 #[cfg(peri_adc3_common)] 565 #[cfg(peri_adc3_common)]
893 impl VrefChannel for crate::peripherals::ADC3 { 566 impl SealedSpecialConverter<VrefInt> for crate::peripherals::ADC3 {
894 const CHANNEL: u8 = 18; 567 const CHANNEL: u8 = 18;
895 } 568 }
896 569
897 #[cfg(peri_adc3_common)] 570 #[cfg(peri_adc3_common)]
898 impl VBatChannel for crate::peripherals::ADC3 { 571 impl SealedSpecialConverter<Vbat> for crate::peripherals::ADC3 {
899 const CHANNEL: u8 = 17; 572 const CHANNEL: u8 = 17;
900 } 573 }
901 574
902 #[cfg(not(stm32g4x1))] 575 #[cfg(not(stm32g4x1))]
903 impl VrefChannel for crate::peripherals::ADC4 { 576 impl SealedSpecialConverter<VrefInt> for crate::peripherals::ADC4 {
904 const CHANNEL: u8 = 18; 577 const CHANNEL: u8 = 18;
905 } 578 }
906 579
907 #[cfg(not(stm32g4x1))] 580 #[cfg(not(stm32g4x1))]
908 impl TemperatureChannel for crate::peripherals::ADC5 { 581 impl SealedSpecialConverter<Temperature> for crate::peripherals::ADC5 {
909 const CHANNEL: u8 = 4; 582 const CHANNEL: u8 = 4;
910 } 583 }
911 584
912 #[cfg(not(stm32g4x1))] 585 #[cfg(not(stm32g4x1))]
913 impl VrefChannel for crate::peripherals::ADC5 { 586 impl SealedSpecialConverter<VrefInt> for crate::peripherals::ADC5 {
914 const CHANNEL: u8 = 18; 587 const CHANNEL: u8 = 18;
915 } 588 }
916 589
917 #[cfg(not(stm32g4x1))] 590 #[cfg(not(stm32g4x1))]
918 impl VBatChannel for crate::peripherals::ADC5 { 591 impl SealedSpecialConverter<Vbat> for crate::peripherals::ADC5 {
919 const CHANNEL: u8 = 17; 592 const CHANNEL: u8 = 17;
920 } 593 }
921} 594}
@@ -923,13 +596,13 @@ mod g4 {
923// TODO this should look at each ADC individually and impl the correct channels 596// TODO this should look at each ADC individually and impl the correct channels
924#[cfg(stm32h7)] 597#[cfg(stm32h7)]
925mod h7 { 598mod h7 {
926 impl<T: Instance> TemperatureChannel for T { 599 impl<T: Instance> SealedSpecialConverter<Temperature> for T {
927 const CHANNEL: u8 = 18; 600 const CHANNEL: u8 = 18;
928 } 601 }
929 impl<T: Instance> VrefChannel for T { 602 impl<T: Instance> SealedSpecialConverter<VrefInt> for T {
930 const CHANNEL: u8 = 19; 603 const CHANNEL: u8 = 19;
931 } 604 }
932 impl<T: Instance> VBatChannel for T { 605 impl<T: Instance> SealedSpecialConverter<Vbat> for T {
933 // TODO this should be 14 for H7a/b/35 606 // TODO this should be 14 for H7a/b/35
934 const CHANNEL: u8 = 17; 607 const CHANNEL: u8 = 17;
935 } 608 }
diff --git a/embassy-stm32/src/adc/injected.rs b/embassy-stm32/src/adc/injected.rs
index 0e4fe5847..ccaa5d1b2 100644
--- a/embassy-stm32/src/adc/injected.rs
+++ b/embassy-stm32/src/adc/injected.rs
@@ -5,9 +5,9 @@ use core::sync::atomic::{Ordering, compiler_fence};
5use embassy_hal_internal::Peri; 5use embassy_hal_internal::Peri;
6 6
7use super::{AnyAdcChannel, SampleTime}; 7use super::{AnyAdcChannel, SampleTime};
8use crate::adc::Adc;
9#[allow(unused_imports)] 8#[allow(unused_imports)]
10use crate::adc::Instance; 9use crate::adc::Instance;
10use crate::adc::{Adc, AnyInstance};
11 11
12/// Injected ADC sequence with owned channels. 12/// Injected ADC sequence with owned channels.
13pub struct InjectedAdc<T: Instance, const N: usize> { 13pub struct InjectedAdc<T: Instance, const N: usize> {
@@ -36,9 +36,9 @@ impl<T: Instance, const N: usize> InjectedAdc<T, N> {
36 } 36 }
37} 37}
38 38
39impl<T: Instance, const N: usize> Drop for InjectedAdc<T, N> { 39impl<T: Instance + AnyInstance, const N: usize> Drop for InjectedAdc<T, N> {
40 fn drop(&mut self) { 40 fn drop(&mut self) {
41 Adc::<T>::teardown_adc(); 41 T::stop();
42 compiler_fence(Ordering::SeqCst); 42 compiler_fence(Ordering::SeqCst);
43 } 43 }
44} 44}
diff --git a/embassy-stm32/src/adc/mod.rs b/embassy-stm32/src/adc/mod.rs
index ea7341f75..13f8a1544 100644
--- a/embassy-stm32/src/adc/mod.rs
+++ b/embassy-stm32/src/adc/mod.rs
@@ -17,6 +17,9 @@
17#[cfg_attr(adc_c0, path = "c0.rs")] 17#[cfg_attr(adc_c0, path = "c0.rs")]
18mod _version; 18mod _version;
19 19
20#[cfg(any(adc_v2, adc_g4, adc_v3, adc_g0, adc_u0))]
21mod ringbuffered;
22
20use core::marker::PhantomData; 23use core::marker::PhantomData;
21 24
22#[allow(unused)] 25#[allow(unused)]
@@ -25,30 +28,27 @@ pub use _version::*;
25use embassy_hal_internal::{PeripheralType, impl_peripheral}; 28use embassy_hal_internal::{PeripheralType, impl_peripheral};
26#[cfg(any(adc_f1, adc_f3v1, adc_v1, adc_l0, adc_f3v2))] 29#[cfg(any(adc_f1, adc_f3v1, adc_v1, adc_l0, adc_f3v2))]
27use embassy_sync::waitqueue::AtomicWaker; 30use embassy_sync::waitqueue::AtomicWaker;
31#[cfg(any(adc_v2, adc_g4, adc_v3, adc_g0, adc_u0))]
32pub use ringbuffered::RingBufferedAdc;
28 33
29#[cfg(any(adc_u5, adc_wba))] 34#[cfg(any(adc_u5, adc_wba))]
30#[path = "adc4.rs"] 35#[path = "adc4.rs"]
31pub mod adc4; 36pub mod adc4;
32 37
38#[allow(unused)]
39pub(self) use crate::block_for_us as blocking_delay_us;
33pub use crate::pac::adc::vals; 40pub use crate::pac::adc::vals;
34#[cfg(not(any(adc_f1, adc_f3v3)))] 41#[cfg(not(any(adc_f1, adc_f3v3)))]
35pub use crate::pac::adc::vals::Res as Resolution; 42pub use crate::pac::adc::vals::Res as Resolution;
36pub use crate::pac::adc::vals::SampleTime; 43pub use crate::pac::adc::vals::SampleTime;
37use crate::peripherals; 44use crate::peripherals;
38 45
39#[cfg(not(adc_wba))] 46dma_trait!(RxDma, AnyInstance);
40dma_trait!(RxDma, Instance);
41#[cfg(adc_u5)]
42dma_trait!(RxDma4, adc4::Instance);
43#[cfg(adc_wba)]
44dma_trait!(RxDma4, adc4::Instance);
45 47
46/// Analog to Digital driver. 48/// Analog to Digital driver.
47pub struct Adc<'d, T: Instance> { 49pub struct Adc<'d, T: AnyInstance> {
48 #[allow(unused)] 50 #[allow(unused)]
49 adc: crate::Peri<'d, T>, 51 adc: crate::Peri<'d, T>,
50 #[cfg(not(any(adc_f3v3, adc_f3v2, adc_wba)))]
51 sample_time: SampleTime,
52} 52}
53 53
54#[cfg(any(adc_f1, adc_f3v1, adc_v1, adc_l0, adc_f3v2))] 54#[cfg(any(adc_f1, adc_f3v1, adc_v1, adc_l0, adc_f3v2))]
@@ -82,26 +82,294 @@ pub(crate) trait SealedAdcChannel<T> {
82 82
83 #[allow(unused)] 83 #[allow(unused)]
84 fn channel(&self) -> u8; 84 fn channel(&self) -> u8;
85
86 #[allow(unused)]
87 fn is_differential(&self) -> bool {
88 false
89 }
85} 90}
86 91
87/// Performs a busy-wait delay for a specified number of microseconds. 92// Temporary patch for ADCs that have not implemented the standard iface yet
88#[allow(unused)] 93#[cfg(any(adc_v1, adc_l0, adc_f1, adc_f3v1, adc_f3v2, adc_f3v3, adc_v1))]
89pub(crate) fn blocking_delay_us(us: u32) { 94trait_set::trait_set! {
90 cfg_if::cfg_if! { 95 pub trait AnyInstance = Instance;
91 // this does strange things on stm32wlx in low power mode depending on exactly when it's called 96}
92 // as in sometimes 15 us (1 tick) would take > 20 seconds. 97
93 if #[cfg(all(feature = "time", all(not(feature = "low-power"), not(stm32wlex))))] { 98#[cfg(any(
94 let duration = embassy_time::Duration::from_micros(us as u64); 99 adc_v2, adc_v3, adc_g0, adc_h5, adc_h7rs, adc_u0, adc_v4, adc_u5, adc_wba, adc_g4, adc_c0
95 embassy_time::block_for(duration); 100))]
96 } else { 101pub trait BasicAnyInstance {
97 let freq = unsafe { crate::rcc::get_freqs() }.sys.to_hertz().unwrap().0 as u64; 102 type SampleTime;
98 let us = us as u64; 103}
99 let cycles = freq * us / 1_000_000; 104
100 cortex_m::asm::delay(cycles as u32); 105#[cfg(any(
101 } 106 adc_v2, adc_v3, adc_g0, adc_h5, adc_h7rs, adc_u0, adc_v4, adc_u5, adc_wba, adc_g4, adc_c0
107))]
108pub(self) trait SealedAnyInstance: BasicAnyInstance {
109 fn enable();
110 fn start();
111 fn stop();
112 fn convert() -> u16;
113 fn configure_dma(conversion_mode: ConversionMode);
114 fn configure_sequence(sequence: impl ExactSizeIterator<Item = ((u8, bool), Self::SampleTime)>);
115 #[allow(dead_code)]
116 fn dr() -> *mut u16;
117}
118
119// On chips without ADC4, AnyInstance is an Instance
120#[cfg(any(adc_v2, adc_v3, adc_g0, adc_h5, adc_h7rs, adc_u0, adc_g4, adc_c0))]
121#[allow(private_bounds)]
122pub trait AnyInstance: SealedAnyInstance + Instance {}
123
124// On chips with ADC4, AnyInstance is an Instance or adc4::Instance
125#[cfg(any(adc_v4, adc_u5, adc_wba))]
126#[allow(private_bounds)]
127pub trait AnyInstance: SealedAnyInstance + crate::PeripheralType + crate::rcc::RccPeripheral {}
128
129// Implement AnyInstance automatically for SealedAnyInstance
130#[cfg(any(
131 adc_v2, adc_v3, adc_g0, adc_h5, adc_h7rs, adc_u0, adc_v4, adc_u5, adc_wba, adc_g4, adc_c0
132))]
133impl<T: SealedAnyInstance + Instance> BasicAnyInstance for T {
134 type SampleTime = SampleTime;
135}
136
137#[cfg(any(
138 adc_v2, adc_v3, adc_g0, adc_h5, adc_h7rs, adc_u0, adc_v4, adc_u5, adc_wba, adc_g4, adc_c0
139))]
140impl<T: SealedAnyInstance + Instance> AnyInstance for T {}
141
142#[cfg(any(adc_c0, adc_v3, adc_g0, adc_h5, adc_h7rs, adc_u0, adc_v4, adc_u5))]
143/// Number of samples used for averaging.
144#[derive(Copy, Clone, Debug)]
145#[cfg_attr(feature = "defmt", derive(defmt::Format))]
146pub enum Averaging {
147 Disabled,
148 Samples2,
149 Samples4,
150 Samples8,
151 Samples16,
152 Samples32,
153 Samples64,
154 Samples128,
155 Samples256,
156 #[cfg(any(adc_c0, adc_v4, adc_u5))]
157 Samples512,
158 #[cfg(any(adc_c0, adc_v4, adc_u5))]
159 Samples1024,
160}
161
162#[cfg(any(
163 adc_v2, adc_g4, adc_v3, adc_g0, adc_h5, adc_h7rs, adc_u0, adc_v4, adc_u5, adc_wba, adc_c0
164))]
165pub(crate) enum ConversionMode {
166 // Should match the cfg on "read" below
167 #[cfg(any(adc_g4, adc_v3, adc_g0, adc_h5, adc_h7rs, adc_u0, adc_v4, adc_u5, adc_wba, adc_c0))]
168 Singular,
169 // Should match the cfg on "into_ring_buffered" below
170 #[cfg(any(adc_v2, adc_g4, adc_v3, adc_g0, adc_u0))]
171 Repeated(RegularConversionMode),
172}
173
174// Should match the cfg on "into_ring_buffered" below
175#[cfg(any(adc_v2, adc_g4, adc_v3, adc_g0, adc_u0))]
176// Conversion mode for regular ADC channels
177#[derive(Copy, Clone)]
178pub enum RegularConversionMode {
179 // Samples as fast as possible
180 Continuous,
181 #[cfg(adc_g4)]
182 // Sample at rate determined by external trigger
183 Triggered(ConversionTrigger),
184}
185
186impl<'d, T: AnyInstance> Adc<'d, T> {
187 #[cfg(any(
188 adc_v2, adc_g4, adc_v3, adc_g0, adc_h5, adc_h7rs, adc_u0, adc_u5, adc_v4, adc_wba, adc_c0
189 ))]
190 /// Read an ADC pin.
191 pub fn blocking_read(&mut self, channel: &mut impl AdcChannel<T>, sample_time: T::SampleTime) -> u16 {
192 #[cfg(any(adc_v1, adc_c0, adc_l0, adc_v2, adc_g4, adc_v4, adc_u5, adc_wba))]
193 channel.setup();
194
195 #[cfg(not(adc_v4))]
196 T::enable();
197 T::configure_sequence([((channel.channel(), channel.is_differential()), sample_time)].into_iter());
198
199 T::convert()
102 } 200 }
201
202 #[cfg(any(adc_g4, adc_v3, adc_g0, adc_h5, adc_h7rs, adc_u0, adc_v4, adc_u5, adc_wba, adc_c0))]
203 /// Read one or multiple ADC regular channels using DMA.
204 ///
205 /// `sequence` iterator and `readings` must have the same length.
206 ///
207 /// Example
208 /// ```rust,ignore
209 /// use embassy_stm32::adc::{Adc, AdcChannel}
210 ///
211 /// let mut adc = Adc::new(p.ADC1);
212 /// let mut adc_pin0 = p.PA0.into();
213 /// let mut adc_pin1 = p.PA1.into();
214 /// let mut measurements = [0u16; 2];
215 ///
216 /// adc.read(
217 /// p.DMA1_CH2.reborrow(),
218 /// [
219 /// (&mut *adc_pin0, SampleTime::CYCLES160_5),
220 /// (&mut *adc_pin1, SampleTime::CYCLES160_5),
221 /// ]
222 /// .into_iter(),
223 /// &mut measurements,
224 /// )
225 /// .await;
226 /// defmt::info!("measurements: {}", measurements);
227 /// ```
228 ///
229 /// Note: This is not very efficient as the ADC needs to be reconfigured for each read. Use
230 /// `into_ring_buffered`, `into_ring_buffered_and_injected`
231 ///
232 /// In STM32C0, channels bigger than 14 cannot be read using sequencer, so you have to use
233 /// either blocking reads or use the mechanism to read in HW order (CHSELRMOD=0).
234 ///
235 /// In addtion, on STM320, this method will panic if the channels are not passed in order
236 pub async fn read(
237 &mut self,
238 rx_dma: embassy_hal_internal::Peri<'_, impl RxDma<T>>,
239 sequence: impl ExactSizeIterator<Item = (&mut AnyAdcChannel<T>, T::SampleTime)>,
240 readings: &mut [u16],
241 ) {
242 assert!(sequence.len() != 0, "Asynchronous read sequence cannot be empty");
243 assert!(
244 sequence.len() == readings.len(),
245 "Sequence length must be equal to readings length"
246 );
247 assert!(
248 sequence.len() <= 16,
249 "Asynchronous read sequence cannot be more than 16 in length"
250 );
251
252 // Ensure no conversions are ongoing and ADC is enabled.
253 T::stop();
254 T::enable();
255
256 T::configure_sequence(
257 sequence.map(|(channel, sample_time)| ((channel.channel, channel.is_differential), sample_time)),
258 );
259
260 T::configure_dma(ConversionMode::Singular);
261
262 let request = rx_dma.request();
263 let transfer =
264 unsafe { crate::dma::Transfer::new_read(rx_dma, request, T::dr(), readings, Default::default()) };
265
266 T::start();
267
268 // Wait for conversion sequence to finish.
269 transfer.await;
270
271 // Ensure conversions are finished.
272 T::stop();
273 }
274
275 #[cfg(any(adc_v2, adc_g4, adc_v3, adc_g0, adc_u0))]
276 /// Configures the ADC to use a DMA ring buffer for continuous data acquisition.
277 ///
278 /// Use the [`read`] method to retrieve measurements from the DMA ring buffer. The read buffer
279 /// should be exactly half the size of `dma_buf`. When using triggered mode, it is recommended
280 /// to configure `dma_buf` as a double buffer so that one half can be read while the other half
281 /// is being filled by the DMA, preventing data loss. The trigger period of the ADC effectively
282 /// defines the period at which the buffer should be read.
283 ///
284 /// If continous conversion mode is selected, the provided `dma_buf` must be large enough to prevent
285 /// DMA buffer overruns. Its length should be a multiple of the number of ADC channels being measured.
286 /// For example, if 3 channels are measured and you want to store 40 samples per channel,
287 /// the buffer length should be `3 * 40 = 120`.
288 ///
289 /// # Parameters
290 /// - `dma`: The DMA peripheral used to transfer ADC data into the buffer.
291 /// - `dma_buf`: The buffer where DMA stores ADC samples.
292 /// - `regular_sequence`: Sequence of channels and sample times for regular ADC conversions.
293 /// - `regular_conversion_mode`: Mode for regular conversions (continuous or triggered).
294 ///
295 /// # Returns
296 /// A `RingBufferedAdc<'a, T>` instance configured for continuous DMA-based sampling.
297 pub fn into_ring_buffered<'a>(
298 self,
299 dma: embassy_hal_internal::Peri<'a, impl RxDma<T>>,
300 dma_buf: &'a mut [u16],
301 sequence: impl ExactSizeIterator<Item = (AnyAdcChannel<T>, T::SampleTime)>,
302 mode: RegularConversionMode,
303 ) -> RingBufferedAdc<'a, T> {
304 assert!(!dma_buf.is_empty() && dma_buf.len() <= 0xFFFF);
305 assert!(sequence.len() != 0, "Asynchronous read sequence cannot be empty");
306 assert!(
307 sequence.len() <= 16,
308 "Asynchronous read sequence cannot be more than 16 in length"
309 );
310 // reset conversions and enable the adc
311 T::stop();
312 T::enable();
313
314 //adc side setup
315 T::configure_sequence(
316 sequence.map(|(channel, sample_time)| ((channel.channel, channel.is_differential), sample_time)),
317 );
318
319 T::configure_dma(ConversionMode::Repeated(mode));
320
321 core::mem::forget(self);
322
323 RingBufferedAdc::new(dma, dma_buf)
324 }
325}
326
327pub(self) trait SpecialChannel {}
328
329/// Implemented for ADCs that have a special channel
330trait SealedSpecialConverter<T: SpecialChannel + Sized> {
331 const CHANNEL: u8;
103} 332}
104 333
334#[allow(private_bounds)]
335pub trait SpecialConverter<T: SpecialChannel + Sized>: SealedSpecialConverter<T> {}
336
337impl<C: SpecialChannel + Sized, T: SealedSpecialConverter<C>> SpecialConverter<C> for T {}
338
339impl<C: SpecialChannel, T: Instance + SealedSpecialConverter<C>> AdcChannel<T> for C {}
340impl<C: SpecialChannel, T: Instance + SealedSpecialConverter<C>> SealedAdcChannel<T> for C {
341 fn channel(&self) -> u8 {
342 T::CHANNEL
343 }
344}
345
346pub struct VrefInt;
347impl SpecialChannel for VrefInt {}
348
349impl VrefInt {
350 #[cfg(any(adc_f3v1, adc_f3v2))]
351 /// The value that vref would be if vdda was at 3300mv
352 pub fn calibrated_value(&self) -> u16 {
353 crate::pac::VREFINTCAL.data().read()
354 }
355}
356
357/// Internal temperature channel.
358pub struct Temperature;
359impl SpecialChannel for Temperature {}
360
361/// Internal battery voltage channel.
362pub struct Vbat;
363impl SpecialChannel for Vbat {}
364
365/// Vcore channel.
366pub struct Vcore;
367impl SpecialChannel for Vcore {}
368
369/// Internal dac channel.
370pub struct Dac;
371impl SpecialChannel for Dac {}
372
105/// ADC instance. 373/// ADC instance.
106#[cfg(not(any( 374#[cfg(not(any(
107 adc_f1, adc_v1, adc_l0, adc_v2, adc_v3, adc_v4, adc_g4, adc_f3v1, adc_f3v2, adc_g0, adc_u0, adc_h5, adc_h7rs, 375 adc_f1, adc_v1, adc_l0, adc_v2, adc_v3, adc_v4, adc_g4, adc_f3v1, adc_f3v2, adc_g0, adc_u0, adc_h5, adc_h7rs,
@@ -131,6 +399,7 @@ pub trait AdcChannel<T>: SealedAdcChannel<T> + Sized {
131 399
132 AnyAdcChannel { 400 AnyAdcChannel {
133 channel: self.channel(), 401 channel: self.channel(),
402 is_differential: self.is_differential(),
134 _phantom: PhantomData, 403 _phantom: PhantomData,
135 } 404 }
136 } 405 }
@@ -142,6 +411,7 @@ pub trait AdcChannel<T>: SealedAdcChannel<T> + Sized {
142/// storing them in an array. 411/// storing them in an array.
143pub struct AnyAdcChannel<T> { 412pub struct AnyAdcChannel<T> {
144 channel: u8, 413 channel: u8,
414 is_differential: bool,
145 _phantom: PhantomData<T>, 415 _phantom: PhantomData<T>,
146} 416}
147impl_peripheral!(AnyAdcChannel<T: Instance>); 417impl_peripheral!(AnyAdcChannel<T: Instance>);
@@ -150,6 +420,10 @@ impl<T: Instance> SealedAdcChannel<T> for AnyAdcChannel<T> {
150 fn channel(&self) -> u8 { 420 fn channel(&self) -> u8 {
151 self.channel 421 self.channel
152 } 422 }
423
424 fn is_differential(&self) -> bool {
425 self.is_differential
426 }
153} 427}
154 428
155impl<T> AnyAdcChannel<T> { 429impl<T> AnyAdcChannel<T> {
@@ -268,6 +542,39 @@ macro_rules! impl_adc_pin {
268 }; 542 };
269} 543}
270 544
545#[allow(unused_macros)]
546macro_rules! impl_adc_pair {
547 ($inst:ident, $pin:ident, $npin:ident, $ch:expr) => {
548 impl crate::adc::AdcChannel<peripherals::$inst>
549 for (
550 crate::Peri<'_, crate::peripherals::$pin>,
551 crate::Peri<'_, crate::peripherals::$npin>,
552 )
553 {
554 }
555 impl crate::adc::SealedAdcChannel<peripherals::$inst>
556 for (
557 crate::Peri<'_, crate::peripherals::$pin>,
558 crate::Peri<'_, crate::peripherals::$npin>,
559 )
560 {
561 #[cfg(any(adc_v1, adc_c0, adc_l0, adc_v2, adc_g4, adc_v4, adc_u5, adc_wba))]
562 fn setup(&mut self) {
563 <crate::peripherals::$pin as crate::gpio::SealedPin>::set_as_analog(&mut self.0);
564 <crate::peripherals::$npin as crate::gpio::SealedPin>::set_as_analog(&mut self.1);
565 }
566
567 fn channel(&self) -> u8 {
568 $ch
569 }
570
571 fn is_differential(&self) -> bool {
572 true
573 }
574 }
575 };
576}
577
271/// Get the maximum reading value for this resolution. 578/// Get the maximum reading value for this resolution.
272/// 579///
273/// This is `2**n - 1`. 580/// This is `2**n - 1`.
diff --git a/embassy-stm32/src/adc/ringbuffered.rs b/embassy-stm32/src/adc/ringbuffered.rs
index 971c8195c..a56f8ca0b 100644
--- a/embassy-stm32/src/adc/ringbuffered.rs
+++ b/embassy-stm32/src/adc/ringbuffered.rs
@@ -4,7 +4,7 @@ use core::sync::atomic::{Ordering, compiler_fence};
4#[allow(unused_imports)] 4#[allow(unused_imports)]
5use embassy_hal_internal::Peri; 5use embassy_hal_internal::Peri;
6 6
7use crate::adc::Adc; 7use crate::adc::AnyInstance;
8#[allow(unused_imports)] 8#[allow(unused_imports)]
9use crate::adc::{Instance, RxDma}; 9use crate::adc::{Instance, RxDma};
10#[allow(unused_imports)] 10#[allow(unused_imports)]
@@ -19,7 +19,7 @@ pub struct RingBufferedAdc<'d, T: Instance> {
19 ring_buf: ReadableRingBuffer<'d, u16>, 19 ring_buf: ReadableRingBuffer<'d, u16>,
20} 20}
21 21
22impl<'d, T: Instance> RingBufferedAdc<'d, T> { 22impl<'d, T: Instance + AnyInstance> RingBufferedAdc<'d, T> {
23 pub(crate) fn new(dma: Peri<'d, impl RxDma<T>>, dma_buf: &'d mut [u16]) -> Self { 23 pub(crate) fn new(dma: Peri<'d, impl RxDma<T>>, dma_buf: &'d mut [u16]) -> Self {
24 //dma side setup 24 //dma side setup
25 let opts = TransferOptions { 25 let opts = TransferOptions {
@@ -45,11 +45,11 @@ impl<'d, T: Instance> RingBufferedAdc<'d, T> {
45 compiler_fence(Ordering::SeqCst); 45 compiler_fence(Ordering::SeqCst);
46 self.ring_buf.start(); 46 self.ring_buf.start();
47 47
48 Adc::<T>::start(); 48 T::start();
49 } 49 }
50 50
51 pub fn stop(&mut self) { 51 pub fn stop(&mut self) {
52 Adc::<T>::stop(); 52 T::stop();
53 53
54 self.ring_buf.request_pause(); 54 self.ring_buf.request_pause();
55 55
@@ -170,9 +170,9 @@ impl<'d, T: Instance> RingBufferedAdc<'d, T> {
170 } 170 }
171} 171}
172 172
173impl<T: Instance> Drop for RingBufferedAdc<'_, T> { 173impl<T: Instance + AnyInstance> Drop for RingBufferedAdc<'_, T> {
174 fn drop(&mut self) { 174 fn drop(&mut self) {
175 Adc::<T>::teardown_adc(); 175 T::stop();
176 176
177 compiler_fence(Ordering::SeqCst); 177 compiler_fence(Ordering::SeqCst);
178 178
diff --git a/embassy-stm32/src/adc/v1.rs b/embassy-stm32/src/adc/v1.rs
index a5869d110..58c30935f 100644
--- a/embassy-stm32/src/adc/v1.rs
+++ b/embassy-stm32/src/adc/v1.rs
@@ -5,10 +5,11 @@ use core::task::Poll;
5#[cfg(adc_l0)] 5#[cfg(adc_l0)]
6use stm32_metapac::adc::vals::Ckmode; 6use stm32_metapac::adc::vals::Ckmode;
7 7
8use super::blocking_delay_us; 8#[cfg(not(adc_l0))]
9use super::Vbat;
10use super::{Temperature, VrefInt, blocking_delay_us};
9use crate::adc::{Adc, AdcChannel, Instance, Resolution, SampleTime}; 11use crate::adc::{Adc, AdcChannel, Instance, Resolution, SampleTime};
10use crate::interrupt::typelevel::Interrupt; 12use crate::interrupt::typelevel::Interrupt;
11use crate::peripherals::ADC1;
12use crate::{Peri, interrupt, rcc}; 13use crate::{Peri, interrupt, rcc};
13 14
14mod watchdog_v1; 15mod watchdog_v1;
@@ -42,32 +43,23 @@ impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandl
42} 43}
43 44
44#[cfg(not(adc_l0))] 45#[cfg(not(adc_l0))]
45pub struct Vbat; 46impl super::SealedSpecialConverter<super::Vbat> for crate::peripherals::ADC1 {
46 47 const CHANNEL: u8 = 18;
47#[cfg(not(adc_l0))] 48}
48impl AdcChannel<ADC1> for Vbat {}
49 49
50#[cfg(not(adc_l0))] 50#[cfg(not(adc_l0))]
51impl super::SealedAdcChannel<ADC1> for Vbat { 51impl super::SealedSpecialConverter<super::VrefInt> for crate::peripherals::ADC1 {
52 fn channel(&self) -> u8 { 52 const CHANNEL: u8 = 17;
53 18
54 }
55} 53}
56 54
57pub struct Vref; 55#[cfg(adc_l0)]
58impl AdcChannel<ADC1> for Vref {} 56impl super::SealedSpecialConverter<super::VrefInt> for crate::peripherals::ADC1 {
59impl super::SealedAdcChannel<ADC1> for Vref { 57 const CHANNEL: u8 = 18;
60 fn channel(&self) -> u8 {
61 17
62 }
63} 58}
64 59
65pub struct Temperature; 60#[cfg(not(adc_l0))]
66impl AdcChannel<ADC1> for Temperature {} 61impl super::SealedSpecialConverter<super::Temperature> for crate::peripherals::ADC1 {
67impl super::SealedAdcChannel<ADC1> for Temperature { 62 const CHANNEL: u8 = 16;
68 fn channel(&self) -> u8 {
69 if cfg!(adc_l0) { 18 } else { 16 }
70 }
71} 63}
72 64
73impl<'d, T: Instance> Adc<'d, T> { 65impl<'d, T: Instance> Adc<'d, T> {
@@ -114,10 +106,7 @@ impl<'d, T: Instance> Adc<'d, T> {
114 T::Interrupt::enable(); 106 T::Interrupt::enable();
115 } 107 }
116 108
117 Self { 109 Self { adc }
118 adc,
119 sample_time: SampleTime::from_bits(0),
120 }
121 } 110 }
122 111
123 #[cfg(not(adc_l0))] 112 #[cfg(not(adc_l0))]
@@ -130,12 +119,12 @@ impl<'d, T: Instance> Adc<'d, T> {
130 Vbat 119 Vbat
131 } 120 }
132 121
133 pub fn enable_vref(&self) -> Vref { 122 pub fn enable_vref(&self) -> VrefInt {
134 // Table 28. Embedded internal reference voltage 123 // Table 28. Embedded internal reference voltage
135 // tstart = 10μs 124 // tstart = 10μs
136 T::regs().ccr().modify(|reg| reg.set_vrefen(true)); 125 T::regs().ccr().modify(|reg| reg.set_vrefen(true));
137 blocking_delay_us(10); 126 blocking_delay_us(10);
138 Vref 127 VrefInt
139 } 128 }
140 129
141 pub fn enable_temperature(&self) -> Temperature { 130 pub fn enable_temperature(&self) -> Temperature {
@@ -149,10 +138,6 @@ impl<'d, T: Instance> Adc<'d, T> {
149 Temperature 138 Temperature
150 } 139 }
151 140
152 pub fn set_sample_time(&mut self, sample_time: SampleTime) {
153 self.sample_time = sample_time;
154 }
155
156 pub fn set_resolution(&mut self, resolution: Resolution) { 141 pub fn set_resolution(&mut self, resolution: Resolution) {
157 T::regs().cfgr1().modify(|reg| reg.set_res(resolution.into())); 142 T::regs().cfgr1().modify(|reg| reg.set_res(resolution.into()));
158 } 143 }
@@ -163,12 +148,13 @@ impl<'d, T: Instance> Adc<'d, T> {
163 T::regs().cfgr2().modify(|reg| reg.set_ckmode(ckmode)); 148 T::regs().cfgr2().modify(|reg| reg.set_ckmode(ckmode));
164 } 149 }
165 150
166 pub async fn read(&mut self, channel: &mut impl AdcChannel<T>) -> u16 { 151 pub async fn read(&mut self, channel: &mut impl AdcChannel<T>, sample_time: SampleTime) -> u16 {
167 let ch_num = channel.channel(); 152 let ch_num = channel.channel();
168 channel.setup(); 153 channel.setup();
169 154
170 // A.7.5 Single conversion sequence code example - Software trigger 155 // A.7.5 Single conversion sequence code example - Software trigger
171 T::regs().chselr().write(|reg| reg.set_chsel_x(ch_num as usize, true)); 156 T::regs().chselr().write(|reg| reg.set_chsel_x(ch_num as usize, true));
157 T::regs().smpr().modify(|reg| reg.set_smp(sample_time.into()));
172 158
173 self.convert().await 159 self.convert().await
174 } 160 }
@@ -179,7 +165,6 @@ impl<'d, T: Instance> Adc<'d, T> {
179 reg.set_eosmp(true); 165 reg.set_eosmp(true);
180 }); 166 });
181 167
182 T::regs().smpr().modify(|reg| reg.set_smp(self.sample_time.into()));
183 T::regs().ier().modify(|w| w.set_eocie(true)); 168 T::regs().ier().modify(|w| w.set_eocie(true));
184 T::regs().cr().modify(|reg| reg.set_adstart(true)); 169 T::regs().cr().modify(|reg| reg.set_adstart(true));
185 170
diff --git a/embassy-stm32/src/adc/v2.rs b/embassy-stm32/src/adc/v2.rs
index 90c6294d2..07eaebf7c 100644
--- a/embassy-stm32/src/adc/v2.rs
+++ b/embassy-stm32/src/adc/v2.rs
@@ -1,16 +1,12 @@
1use core::mem;
2use core::sync::atomic::{Ordering, compiler_fence}; 1use core::sync::atomic::{Ordering, compiler_fence};
3 2
4use super::blocking_delay_us; 3use super::{ConversionMode, Temperature, Vbat, VrefInt, blocking_delay_us};
5use crate::adc::{Adc, AdcChannel, AnyAdcChannel, Instance, Resolution, RxDma, SampleTime, SealedAdcChannel}; 4use crate::adc::{Adc, Instance, Resolution, SampleTime};
6use crate::pac::adc::vals; 5use crate::pac::adc::vals;
7use crate::peripherals::ADC1; 6pub use crate::pac::adccommon::vals::Adcpre;
8use crate::time::Hertz; 7use crate::time::Hertz;
9use crate::{Peri, rcc}; 8use crate::{Peri, rcc};
10 9
11mod ringbuffered;
12pub use ringbuffered::RingBufferedAdc;
13
14fn clear_interrupt_flags(r: crate::pac::adc::Adc) { 10fn clear_interrupt_flags(r: crate::pac::adc::Adc) {
15 r.sr().modify(|regs| { 11 r.sr().modify(|regs| {
16 regs.set_eoc(false); 12 regs.set_eoc(false);
@@ -23,12 +19,22 @@ pub const VREF_DEFAULT_MV: u32 = 3300;
23/// VREF voltage used for factory calibration of VREFINTCAL register. 19/// VREF voltage used for factory calibration of VREFINTCAL register.
24pub const VREF_CALIB_MV: u32 = 3300; 20pub const VREF_CALIB_MV: u32 = 3300;
25 21
26pub struct VrefInt; 22impl super::SealedSpecialConverter<super::VrefInt> for crate::peripherals::ADC1 {
27impl AdcChannel<ADC1> for VrefInt {} 23 const CHANNEL: u8 = 17;
28impl super::SealedAdcChannel<ADC1> for VrefInt { 24}
29 fn channel(&self) -> u8 { 25
30 17 26#[cfg(any(stm32f2, stm32f40x, stm32f41x))]
31 } 27impl super::SealedSpecialConverter<super::Temperature> for crate::peripherals::ADC1 {
28 const CHANNEL: u8 = 16;
29}
30
31#[cfg(not(any(stm32f2, stm32f40x, stm32f41x)))]
32impl super::SealedSpecialConverter<super::Temperature> for crate::peripherals::ADC1 {
33 const CHANNEL: u8 = 18;
34}
35
36impl super::SealedSpecialConverter<super::Vbat> for crate::peripherals::ADC1 {
37 const CHANNEL: u8 = 18;
32} 38}
33 39
34impl VrefInt { 40impl VrefInt {
@@ -38,20 +44,6 @@ impl VrefInt {
38 } 44 }
39} 45}
40 46
41pub struct Temperature;
42impl AdcChannel<ADC1> for Temperature {}
43impl super::SealedAdcChannel<ADC1> for Temperature {
44 fn channel(&self) -> u8 {
45 cfg_if::cfg_if! {
46 if #[cfg(any(stm32f2, stm32f40x, stm32f41x))] {
47 16
48 } else {
49 18
50 }
51 }
52 }
53}
54
55impl Temperature { 47impl Temperature {
56 /// Time needed for temperature sensor readings to stabilize 48 /// Time needed for temperature sensor readings to stabilize
57 pub fn start_time_us() -> u32 { 49 pub fn start_time_us() -> u32 {
@@ -59,168 +51,175 @@ impl Temperature {
59 } 51 }
60} 52}
61 53
62pub struct Vbat; 54fn from_pclk2(freq: Hertz) -> Adcpre {
63impl AdcChannel<ADC1> for Vbat {} 55 // Datasheet for F2 specifies min frequency 0.6 MHz, and max 30 MHz (with VDDA 2.4-3.6V).
64impl super::SealedAdcChannel<ADC1> for Vbat { 56 #[cfg(stm32f2)]
65 fn channel(&self) -> u8 { 57 const MAX_FREQUENCY: Hertz = Hertz(30_000_000);
66 18 58 // Datasheet for both F4 and F7 specifies min frequency 0.6 MHz, typ freq. 30 MHz and max 36 MHz.
59 #[cfg(not(stm32f2))]
60 const MAX_FREQUENCY: Hertz = Hertz(36_000_000);
61 let raw_div = freq.0 / MAX_FREQUENCY.0;
62 match raw_div {
63 0..=1 => Adcpre::DIV2,
64 2..=3 => Adcpre::DIV4,
65 4..=5 => Adcpre::DIV6,
66 6..=7 => Adcpre::DIV8,
67 _ => panic!("Selected PCLK2 frequency is too high for ADC with largest possible prescaler."),
67 } 68 }
68} 69}
69 70
70enum Prescaler { 71/// ADC configuration
71 Div2, 72#[derive(Default)]
72 Div4, 73pub struct AdcConfig {
73 Div6, 74 resolution: Option<Resolution>,
74 Div8,
75} 75}
76 76
77impl Prescaler { 77impl<T: Instance> super::SealedAnyInstance for T {
78 fn from_pclk2(freq: Hertz) -> Self { 78 fn dr() -> *mut u16 {
79 // Datasheet for F2 specifies min frequency 0.6 MHz, and max 30 MHz (with VDDA 2.4-3.6V). 79 T::regs().dr().as_ptr() as *mut u16
80 #[cfg(stm32f2)]
81 const MAX_FREQUENCY: Hertz = Hertz(30_000_000);
82 // Datasheet for both F4 and F7 specifies min frequency 0.6 MHz, typ freq. 30 MHz and max 36 MHz.
83 #[cfg(not(stm32f2))]
84 const MAX_FREQUENCY: Hertz = Hertz(36_000_000);
85 let raw_div = freq.0 / MAX_FREQUENCY.0;
86 match raw_div {
87 0..=1 => Self::Div2,
88 2..=3 => Self::Div4,
89 4..=5 => Self::Div6,
90 6..=7 => Self::Div8,
91 _ => panic!("Selected PCLK2 frequency is too high for ADC with largest possible prescaler."),
92 }
93 } 80 }
94 81
95 fn adcpre(&self) -> crate::pac::adccommon::vals::Adcpre { 82 fn enable() {}
96 match self {
97 Prescaler::Div2 => crate::pac::adccommon::vals::Adcpre::DIV2,
98 Prescaler::Div4 => crate::pac::adccommon::vals::Adcpre::DIV4,
99 Prescaler::Div6 => crate::pac::adccommon::vals::Adcpre::DIV6,
100 Prescaler::Div8 => crate::pac::adccommon::vals::Adcpre::DIV8,
101 }
102 }
103}
104 83
105impl<'d, T> Adc<'d, T> 84 fn start() {
106where 85 // Begin ADC conversions
107 T: Instance,
108{
109 pub fn new(adc: Peri<'d, T>) -> Self {
110 rcc::enable_and_reset::<T>();
111
112 let presc = Prescaler::from_pclk2(T::frequency());
113 T::common_regs().ccr().modify(|w| w.set_adcpre(presc.adcpre()));
114 T::regs().cr2().modify(|reg| { 86 T::regs().cr2().modify(|reg| {
115 reg.set_adon(true); 87 reg.set_adon(true);
88 reg.set_swstart(true);
116 }); 89 });
117
118 blocking_delay_us(3);
119
120 Self {
121 adc,
122 sample_time: SampleTime::from_bits(0),
123 }
124 } 90 }
125 91
126 /// Configures the ADC to use a DMA ring buffer for continuous data acquisition. 92 fn stop() {
127 /// 93 let r = T::regs();
128 /// The `dma_buf` should be large enough to prevent DMA buffer overrun.
129 /// The length of the `dma_buf` should be a multiple of the ADC channel count.
130 /// For example, if 3 channels are measured, its length can be 3 * 40 = 120 measurements.
131 ///
132 /// `read` method is used to read out measurements from the DMA ring buffer, and its buffer should be exactly half of the `dma_buf` length.
133 /// It is critical to call `read` frequently to prevent DMA buffer overrun.
134 ///
135 /// [`read`]: #method.read
136 pub fn into_ring_buffered<'a>(
137 self,
138 dma: Peri<'d, impl RxDma<T>>,
139 dma_buf: &'d mut [u16],
140 sequence: impl ExactSizeIterator<Item = (&'a mut AnyAdcChannel<T>, SampleTime)>,
141 ) -> RingBufferedAdc<'d, T> {
142 assert!(!dma_buf.is_empty() && dma_buf.len() <= 0xFFFF);
143 94
144 T::regs().cr2().modify(|reg| { 95 // Stop ADC
145 reg.set_adon(true); 96 r.cr2().modify(|reg| {
97 // Stop ADC
98 reg.set_swstart(false);
99 // Stop ADC
100 reg.set_adon(false);
101 // Stop DMA
102 reg.set_dma(false);
146 }); 103 });
147 104
148 // Check the sequence is long enough 105 r.cr1().modify(|w| {
149 T::regs().sqr1().modify(|r| { 106 // Disable interrupt for end of conversion
150 r.set_l((sequence.len() - 1).try_into().unwrap()); 107 w.set_eocie(false);
108 // Disable interrupt for overrun
109 w.set_ovrie(false);
151 }); 110 });
152 111
153 for (i, (channel, sample_time)) in sequence.enumerate() { 112 clear_interrupt_flags(r);
154 // Set this GPIO as an analog input.
155 channel.setup();
156
157 // Set the channel in the right sequence field.
158 T::regs().sqr3().modify(|w| w.set_sq(i, channel.channel()));
159
160 Self::set_channel_sample_time(channel.channel(), sample_time);
161 }
162 113
163 compiler_fence(Ordering::SeqCst); 114 compiler_fence(Ordering::SeqCst);
115 }
164 116
165 let r = T::regs(); 117 fn convert() -> u16 {
166 118 // clear end of conversion flag
167 // Clear all interrupts 119 T::regs().sr().modify(|reg| {
168 r.sr().modify(|regs| { 120 reg.set_eoc(false);
169 regs.set_eoc(false);
170 regs.set_ovr(false);
171 regs.set_strt(false);
172 }); 121 });
173 122
174 r.cr1().modify(|w| { 123 // Start conversion
175 // Enable interrupt for end of conversion 124 T::regs().cr2().modify(|reg| {
176 w.set_eocie(true); 125 reg.set_swstart(true);
177 // Enable interrupt for overrun
178 w.set_ovrie(true);
179 // Scanning converisons of multiple channels
180 w.set_scan(true);
181 // Continuous conversion mode
182 w.set_discen(false);
183 }); 126 });
184 127
185 r.cr2().modify(|w| { 128 while T::regs().sr().read().strt() == false {
186 // Enable DMA mode 129 // spin //wait for actual start
187 w.set_dma(true); 130 }
188 // Enable continuous conversions 131 while T::regs().sr().read().eoc() == false {
189 w.set_cont(true); 132 // spin //wait for finish
190 // DMA requests are issues as long as DMA=1 and data are converted. 133 }
191 w.set_dds(vals::Dds::CONTINUOUS);
192 // EOC flag is set at the end of each conversion.
193 w.set_eocs(vals::Eocs::EACH_CONVERSION);
194 });
195 134
196 // Don't disable the clock 135 T::regs().dr().read().0 as u16
197 mem::forget(self); 136 }
198 137
199 RingBufferedAdc::new(dma, dma_buf) 138 fn configure_dma(conversion_mode: ConversionMode) {
139 match conversion_mode {
140 ConversionMode::Repeated(_) => {
141 let r = T::regs();
142
143 // Clear all interrupts
144 r.sr().modify(|regs| {
145 regs.set_eoc(false);
146 regs.set_ovr(false);
147 regs.set_strt(false);
148 });
149
150 r.cr1().modify(|w| {
151 // Enable interrupt for end of conversion
152 w.set_eocie(true);
153 // Enable interrupt for overrun
154 w.set_ovrie(true);
155 // Scanning converisons of multiple channels
156 w.set_scan(true);
157 // Continuous conversion mode
158 w.set_discen(false);
159 });
160
161 r.cr2().modify(|w| {
162 // Enable DMA mode
163 w.set_dma(true);
164 // Enable continuous conversions
165 w.set_cont(true);
166 // DMA requests are issues as long as DMA=1 and data are converted.
167 w.set_dds(vals::Dds::CONTINUOUS);
168 // EOC flag is set at the end of each conversion.
169 w.set_eocs(vals::Eocs::EACH_CONVERSION);
170 });
171 }
172 }
200 } 173 }
201 174
202 pub(super) fn start() { 175 fn configure_sequence(sequence: impl ExactSizeIterator<Item = ((u8, bool), SampleTime)>) {
203 // Begin ADC conversions
204 T::regs().cr2().modify(|reg| { 176 T::regs().cr2().modify(|reg| {
205 reg.set_adon(true); 177 reg.set_adon(true);
206 reg.set_swstart(true);
207 }); 178 });
208 }
209 179
210 pub(super) fn stop() { 180 // Check the sequence is long enough
211 // Stop ADC 181 T::regs().sqr1().modify(|r| {
212 T::regs().cr2().modify(|reg| { 182 r.set_l((sequence.len() - 1).try_into().unwrap());
213 // Stop ADC
214 reg.set_swstart(false);
215 }); 183 });
184
185 for (i, ((ch, _), sample_time)) in sequence.enumerate() {
186 // Set the channel in the right sequence field.
187 T::regs().sqr3().modify(|w| w.set_sq(i, ch));
188
189 let sample_time = sample_time.into();
190 if ch <= 9 {
191 T::regs().smpr2().modify(|reg| reg.set_smp(ch as _, sample_time));
192 } else {
193 T::regs().smpr1().modify(|reg| reg.set_smp((ch - 10) as _, sample_time));
194 }
195 }
216 } 196 }
197}
217 198
218 pub fn set_sample_time(&mut self, sample_time: SampleTime) { 199impl<'d, T> Adc<'d, T>
219 self.sample_time = sample_time; 200where
201 T: Instance,
202{
203 pub fn new(adc: Peri<'d, T>) -> Self {
204 Self::new_with_config(adc, Default::default())
220 } 205 }
221 206
222 pub fn set_resolution(&mut self, resolution: Resolution) { 207 pub fn new_with_config(adc: Peri<'d, T>, config: AdcConfig) -> Self {
223 T::regs().cr1().modify(|reg| reg.set_res(resolution.into())); 208 rcc::enable_and_reset::<T>();
209
210 let presc = from_pclk2(T::frequency());
211 T::common_regs().ccr().modify(|w| w.set_adcpre(presc));
212 T::regs().cr2().modify(|reg| {
213 reg.set_adon(true);
214 });
215
216 blocking_delay_us(3);
217
218 if let Some(resolution) = config.resolution {
219 T::regs().cr1().modify(|reg| reg.set_res(resolution.into()));
220 }
221
222 Self { adc }
224 } 223 }
225 224
226 /// Enables internal voltage reference and returns [VrefInt], which can be used in 225 /// Enables internal voltage reference and returns [VrefInt], which can be used in
@@ -255,77 +254,6 @@ where
255 254
256 Vbat {} 255 Vbat {}
257 } 256 }
258
259 /// Perform a single conversion.
260 fn convert(&mut self) -> u16 {
261 // clear end of conversion flag
262 T::regs().sr().modify(|reg| {
263 reg.set_eoc(false);
264 });
265
266 // Start conversion
267 T::regs().cr2().modify(|reg| {
268 reg.set_swstart(true);
269 });
270
271 while T::regs().sr().read().strt() == false {
272 // spin //wait for actual start
273 }
274 while T::regs().sr().read().eoc() == false {
275 // spin //wait for finish
276 }
277
278 T::regs().dr().read().0 as u16
279 }
280
281 pub fn blocking_read(&mut self, channel: &mut impl AdcChannel<T>) -> u16 {
282 channel.setup();
283
284 // Configure ADC
285 let channel = channel.channel();
286
287 // Select channel
288 T::regs().sqr3().write(|reg| reg.set_sq(0, channel));
289
290 // Configure channel
291 Self::set_channel_sample_time(channel, self.sample_time);
292
293 self.convert()
294 }
295
296 fn set_channel_sample_time(ch: u8, sample_time: SampleTime) {
297 let sample_time = sample_time.into();
298 if ch <= 9 {
299 T::regs().smpr2().modify(|reg| reg.set_smp(ch as _, sample_time));
300 } else {
301 T::regs().smpr1().modify(|reg| reg.set_smp((ch - 10) as _, sample_time));
302 }
303 }
304
305 pub(super) fn teardown_adc() {
306 let r = T::regs();
307
308 // Stop ADC
309 r.cr2().modify(|reg| {
310 // Stop ADC
311 reg.set_swstart(false);
312 // Stop ADC
313 reg.set_adon(false);
314 // Stop DMA
315 reg.set_dma(false);
316 });
317
318 r.cr1().modify(|w| {
319 // Disable interrupt for end of conversion
320 w.set_eocie(false);
321 // Disable interrupt for overrun
322 w.set_ovrie(false);
323 });
324
325 clear_interrupt_flags(r);
326
327 compiler_fence(Ordering::SeqCst);
328 }
329} 257}
330 258
331impl<'d, T: Instance> Drop for Adc<'d, T> { 259impl<'d, T: Instance> Drop for Adc<'d, T> {
diff --git a/embassy-stm32/src/adc/v3.rs b/embassy-stm32/src/adc/v3.rs
index 170b08a25..81eb1e3ee 100644
--- a/embassy-stm32/src/adc/v3.rs
+++ b/embassy-stm32/src/adc/v3.rs
@@ -1,25 +1,18 @@
1use cfg_if::cfg_if; 1use cfg_if::cfg_if;
2#[cfg(adc_g0)] 2#[cfg(adc_g0)]
3use heapless::Vec; 3use heapless::Vec;
4use pac::adc::vals::Dmacfg;
5#[cfg(adc_g0)] 4#[cfg(adc_g0)]
6use pac::adc::vals::{Ckmode, Smpsel}; 5use pac::adc::vals::Ckmode;
6use pac::adc::vals::Dmacfg;
7#[cfg(adc_v3)] 7#[cfg(adc_v3)]
8use pac::adc::vals::{OversamplingRatio, OversamplingShift, Rovsm, Trovs}; 8use pac::adc::vals::{OversamplingRatio, OversamplingShift, Rovsm, Trovs};
9#[cfg(adc_g0)] 9#[cfg(adc_g0)]
10pub use pac::adc::vals::{Ovsr, Ovss, Presc}; 10pub use pac::adc::vals::{Ovsr, Ovss, Presc};
11 11
12use super::{ 12#[allow(unused_imports)]
13 Adc, AdcChannel, AnyAdcChannel, Instance, Resolution, RxDma, SampleTime, SealedAdcChannel, blocking_delay_us, 13use super::SealedAdcChannel;
14}; 14use super::{Adc, Averaging, Instance, Resolution, SampleTime, Temperature, Vbat, VrefInt, blocking_delay_us};
15 15use crate::adc::ConversionMode;
16#[cfg(any(adc_v3, adc_g0, adc_u0))]
17mod ringbuffered;
18
19#[cfg(any(adc_v3, adc_g0, adc_u0))]
20use ringbuffered::RingBufferedAdc;
21
22use crate::dma::Transfer;
23use crate::{Peri, pac, rcc}; 16use crate::{Peri, pac, rcc};
24 17
25/// Default VREF voltage used for sample conversion to millivolts. 18/// Default VREF voltage used for sample conversion to millivolts.
@@ -32,70 +25,64 @@ pub const VREF_CALIB_MV: u32 = 3000;
32// TODO: Use [#![feature(variant_count)]](https://github.com/rust-lang/rust/issues/73662) when stable 25// TODO: Use [#![feature(variant_count)]](https://github.com/rust-lang/rust/issues/73662) when stable
33const SAMPLE_TIMES_CAPACITY: usize = 2; 26const SAMPLE_TIMES_CAPACITY: usize = 2;
34 27
35pub struct VrefInt; 28#[cfg(adc_g0)]
36impl<T: Instance> AdcChannel<T> for VrefInt {} 29impl<T: Instance> super::SealedSpecialConverter<super::VrefInt> for T {
37impl<T: Instance> SealedAdcChannel<T> for VrefInt { 30 const CHANNEL: u8 = 13;
38 fn channel(&self) -> u8 { 31}
39 cfg_if! { 32#[cfg(any(adc_h5, adc_h7rs))]
40 if #[cfg(adc_g0)] { 33impl<T: Instance> super::SealedSpecialConverter<super::VrefInt> for T {
41 let val = 13; 34 const CHANNEL: u8 = 17;
42 } else if #[cfg(any(adc_h5, adc_h7rs))] { 35}
43 let val = 17; 36#[cfg(adc_u0)]
44 } else if #[cfg(adc_u0)] { 37impl<T: Instance> super::SealedSpecialConverter<super::VrefInt> for T {
45 let val = 12; 38 const CHANNEL: u8 = 12;
46 } else { 39}
47 let val = 0; 40#[cfg(not(any(adc_g0, adc_h5, adc_h7rs, adc_u0)))]
48 } 41impl<T: Instance> super::SealedSpecialConverter<super::VrefInt> for T {
49 } 42 const CHANNEL: u8 = 0;
50 val
51 }
52} 43}
53 44
54pub struct Temperature; 45#[cfg(adc_g0)]
55impl<T: Instance> AdcChannel<T> for Temperature {} 46impl<T: Instance> super::SealedSpecialConverter<super::Temperature> for T {
56impl<T: Instance> SealedAdcChannel<T> for Temperature { 47 const CHANNEL: u8 = 12;
57 fn channel(&self) -> u8 { 48}
58 cfg_if! { 49#[cfg(any(adc_h5, adc_h7rs))]
59 if #[cfg(adc_g0)] { 50impl<T: Instance> super::SealedSpecialConverter<super::Temperature> for T {
60 let val = 12; 51 const CHANNEL: u8 = 16;
61 } else if #[cfg(any(adc_h5, adc_h7rs))] { 52}
62 let val = 16; 53#[cfg(adc_u0)]
63 } else if #[cfg(adc_u0)] { 54impl<T: Instance> super::SealedSpecialConverter<super::Temperature> for T {
64 let val = 11; 55 const CHANNEL: u8 = 11;
65 } else { 56}
66 let val = 17; 57#[cfg(not(any(adc_g0, adc_h5, adc_h7rs, adc_u0)))]
67 } 58impl<T: Instance> super::SealedSpecialConverter<super::Temperature> for T {
68 } 59 const CHANNEL: u8 = 17;
69 val
70 }
71} 60}
72 61
73pub struct Vbat; 62#[cfg(adc_g0)]
74impl<T: Instance> AdcChannel<T> for Vbat {} 63impl<T: Instance> super::SealedSpecialConverter<super::Vbat> for T {
75impl<T: Instance> SealedAdcChannel<T> for Vbat { 64 const CHANNEL: u8 = 14;
76 fn channel(&self) -> u8 { 65}
77 cfg_if! { 66#[cfg(any(adc_h5, adc_h7rs))]
78 if #[cfg(adc_g0)] { 67impl<T: Instance> super::SealedSpecialConverter<super::Vbat> for T {
79 let val = 14; 68 const CHANNEL: u8 = 16;
80 } else if #[cfg(any(adc_h5, adc_h7rs))] { 69}
81 let val = 2; 70#[cfg(adc_u0)]
82 } else if #[cfg(any(adc_h5, adc_h7rs))] { 71impl<T: Instance> super::SealedSpecialConverter<super::Vbat> for T {
83 let val = 13; 72 const CHANNEL: u8 = 13;
84 } else { 73}
85 let val = 18; 74#[cfg(not(any(adc_g0, adc_h5, adc_h7rs, adc_u0)))]
86 } 75impl<T: Instance> super::SealedSpecialConverter<super::Vbat> for T {
87 } 76 const CHANNEL: u8 = 18;
88 val
89 }
90} 77}
91 78
92cfg_if! { 79cfg_if! {
93 if #[cfg(any(adc_h5, adc_h7rs))] { 80 if #[cfg(any(adc_h5, adc_h7rs))] {
94 pub struct VddCore; 81 pub struct VddCore;
95 impl<T: Instance> AdcChannel<T> for VddCore {} 82 impl<T: Instance> super::AdcChannel<T> for VddCore {}
96 impl<T: Instance> super::SealedAdcChannel<T> for VddCore { 83 impl<T: Instance> super::SealedAdcChannel<T> for VddCore {
97 fn channel(&self) -> u8 { 84 fn channel(&self) -> u8 {
98 6 85 17
99 } 86 }
100 } 87 }
101 } 88 }
@@ -104,7 +91,7 @@ cfg_if! {
104cfg_if! { 91cfg_if! {
105 if #[cfg(adc_u0)] { 92 if #[cfg(adc_u0)] {
106 pub struct DacOut; 93 pub struct DacOut;
107 impl<T: Instance> AdcChannel<T> for DacOut {} 94 impl<T: Instance> super::AdcChannel<T> for DacOut {}
108 impl<T: Instance> super::SealedAdcChannel<T> for DacOut { 95 impl<T: Instance> super::SealedAdcChannel<T> for DacOut {
109 fn channel(&self) -> u8 { 96 fn channel(&self) -> u8 {
110 19 97 19
@@ -113,21 +100,6 @@ cfg_if! {
113 } 100 }
114} 101}
115 102
116/// Number of samples used for averaging.
117#[derive(Copy, Clone, Debug)]
118#[cfg_attr(feature = "defmt", derive(defmt::Format))]
119pub enum Averaging {
120 Disabled,
121 Samples2,
122 Samples4,
123 Samples8,
124 Samples16,
125 Samples32,
126 Samples64,
127 Samples128,
128 Samples256,
129}
130
131cfg_if! { if #[cfg(adc_g0)] { 103cfg_if! { if #[cfg(adc_g0)] {
132 104
133/// Synchronous PCLK prescaler 105/// Synchronous PCLK prescaler
@@ -148,327 +120,146 @@ pub enum Clock {
148 120
149}} 121}}
150 122
151impl<'d, T: Instance> Adc<'d, T> { 123#[cfg(adc_u0)]
152 /// Enable the voltage regulator 124type Ovss = u8;
153 fn init_regulator() { 125#[cfg(adc_u0)]
154 rcc::enable_and_reset::<T>(); 126type Ovsr = u8;
155 T::regs().cr().modify(|reg| { 127#[cfg(adc_v3)]
156 #[cfg(not(any(adc_g0, adc_u0)))] 128type Ovss = OversamplingShift;
157 reg.set_deeppwd(false); 129#[cfg(adc_v3)]
158 reg.set_advregen(true); 130type Ovsr = OversamplingRatio;
159 }); 131
160 132/// Adc configuration
161 // If this is false then each ADC_CHSELR bit enables an input channel. 133#[derive(Default)]
162 // This is the reset value, so has no effect. 134pub struct AdcConfig {
163 #[cfg(any(adc_g0, adc_u0))] 135 #[cfg(any(adc_u0, adc_g0, adc_v3))]
164 T::regs().cfgr1().modify(|reg| { 136 pub oversampling_shift: Option<Ovss>,
165 reg.set_chselrmod(false); 137 #[cfg(any(adc_u0, adc_g0, adc_v3))]
166 }); 138 pub oversampling_ratio: Option<Ovsr>,
139 #[cfg(any(adc_u0, adc_g0))]
140 pub oversampling_enable: Option<bool>,
141 #[cfg(adc_v3)]
142 pub oversampling_mode: Option<(Rovsm, Trovs, bool)>,
143 #[cfg(adc_g0)]
144 pub clock: Option<Clock>,
145 pub resolution: Option<Resolution>,
146 pub averaging: Option<Averaging>,
147}
167 148
168 blocking_delay_us(20); 149impl<T: Instance> super::SealedAnyInstance for T {
150 fn dr() -> *mut u16 {
151 T::regs().dr().as_ptr() as *mut u16
169 } 152 }
170 153
171 /// Calibrate to remove conversion offset 154 // Enable ADC only when it is not already running.
172 fn init_calibrate() { 155 fn enable() {
173 T::regs().cr().modify(|reg| { 156 // Make sure bits are off
174 reg.set_adcal(true); 157 while T::regs().cr().read().addis() {
175 });
176
177 while T::regs().cr().read().adcal() {
178 // spin 158 // spin
179 } 159 }
180 160
181 blocking_delay_us(1); 161 if !T::regs().cr().read().aden() {
162 // Enable ADC
163 T::regs().isr().modify(|reg| {
164 reg.set_adrdy(true);
165 });
166 T::regs().cr().modify(|reg| {
167 reg.set_aden(true);
168 });
169
170 while !T::regs().isr().read().adrdy() {
171 // spin
172 }
173 }
182 } 174 }
183 175
184 #[cfg(any(adc_v3, adc_g0, adc_u0))] 176 fn start() {
185 pub(super) fn start() {
186 // Start adc conversion
187 T::regs().cr().modify(|reg| { 177 T::regs().cr().modify(|reg| {
188 reg.set_adstart(true); 178 reg.set_adstart(true);
189 }); 179 });
190 } 180 }
191 181
192 #[cfg(any(adc_v3, adc_g0, adc_u0))] 182 fn stop() {
193 pub(super) fn stop() { 183 // Ensure conversions are finished.
194 // Stop adc conversion
195 if T::regs().cr().read().adstart() && !T::regs().cr().read().addis() { 184 if T::regs().cr().read().adstart() && !T::regs().cr().read().addis() {
196 T::regs().cr().modify(|reg| { 185 T::regs().cr().modify(|reg| {
197 reg.set_adstp(true); 186 reg.set_adstp(true);
198 }); 187 });
199 while T::regs().cr().read().adstart() {} 188 while T::regs().cr().read().adstart() {}
200 } 189 }
201 }
202 190
203 #[cfg(any(adc_v3, adc_g0, adc_u0))] 191 // Reset configuration.
204 pub(super) fn teardown_adc() {
205 //disable dma control
206 #[cfg(not(any(adc_g0, adc_u0)))] 192 #[cfg(not(any(adc_g0, adc_u0)))]
207 T::regs().cfgr().modify(|reg| { 193 T::regs().cfgr().modify(|reg| {
194 reg.set_cont(false);
208 reg.set_dmaen(false); 195 reg.set_dmaen(false);
209 }); 196 });
210 #[cfg(any(adc_g0, adc_u0))] 197 #[cfg(any(adc_g0, adc_u0))]
211 T::regs().cfgr1().modify(|reg| { 198 T::regs().cfgr1().modify(|reg| {
199 reg.set_cont(false);
212 reg.set_dmaen(false); 200 reg.set_dmaen(false);
213 }); 201 });
214 } 202 }
215 203
216 /// Initialize the ADC leaving any analog clock at reset value. 204 /// Perform a single conversion.
217 /// For G0 and WL, this is the async clock without prescaler. 205 fn convert() -> u16 {
218 pub fn new(adc: Peri<'d, T>) -> Self { 206 // Some models are affected by an erratum:
219 Self::init_regulator(); 207 // If we perform conversions slower than 1 kHz, the first read ADC value can be
220 Self::init_calibrate(); 208 // corrupted, so we discard it and measure again.
221 Self { 209 //
222 adc, 210 // STM32L471xx: Section 2.7.3
223 sample_time: SampleTime::from_bits(0), 211 // STM32G4: Section 2.7.3
224 } 212 #[cfg(any(rcc_l4, rcc_g4))]
225 } 213 let len = 2;
226
227 #[cfg(adc_g0)]
228 /// Initialize ADC with explicit clock for the analog ADC
229 pub fn new_with_clock(adc: Peri<'d, T>, clock: Clock) -> Self {
230 Self::init_regulator();
231
232 #[cfg(any(stm32wl5x))]
233 {
234 // Reset value 0 is actually _No clock selected_ in the STM32WL5x reference manual
235 let async_clock_available = pac::RCC.ccipr().read().adcsel() != pac::rcc::vals::Adcsel::_RESERVED_0;
236 match clock {
237 Clock::Async { div: _ } => {
238 assert!(async_clock_available);
239 }
240 Clock::Sync { div: _ } => {
241 if async_clock_available {
242 warn!("Not using configured ADC clock");
243 }
244 }
245 }
246 }
247 match clock {
248 Clock::Async { div } => T::regs().ccr().modify(|reg| reg.set_presc(div)),
249 Clock::Sync { div } => T::regs().cfgr2().modify(|reg| {
250 reg.set_ckmode(match div {
251 CkModePclk::DIV1 => Ckmode::PCLK,
252 CkModePclk::DIV2 => Ckmode::PCLK_DIV2,
253 CkModePclk::DIV4 => Ckmode::PCLK_DIV4,
254 })
255 }),
256 }
257
258 Self::init_calibrate();
259
260 Self {
261 adc,
262 sample_time: SampleTime::from_bits(0),
263 }
264 }
265 214
266 // Enable ADC only when it is not already running. 215 #[cfg(not(any(rcc_l4, rcc_g4)))]
267 fn enable(&mut self) { 216 let len = 1;
268 // Make sure bits are off
269 while T::regs().cr().read().addis() {
270 // spin
271 }
272 217
273 if !T::regs().cr().read().aden() { 218 for _ in 0..len {
274 // Enable ADC
275 T::regs().isr().modify(|reg| { 219 T::regs().isr().modify(|reg| {
276 reg.set_adrdy(true); 220 reg.set_eos(true);
221 reg.set_eoc(true);
277 }); 222 });
223
224 // Start conversion
278 T::regs().cr().modify(|reg| { 225 T::regs().cr().modify(|reg| {
279 reg.set_aden(true); 226 reg.set_adstart(true);
280 }); 227 });
281 228
282 while !T::regs().isr().read().adrdy() { 229 while !T::regs().isr().read().eos() {
283 // spin 230 // spin
284 } 231 }
285 } 232 }
286 }
287
288 pub fn enable_vrefint(&self) -> VrefInt {
289 #[cfg(not(any(adc_g0, adc_u0)))]
290 T::common_regs().ccr().modify(|reg| {
291 reg.set_vrefen(true);
292 });
293 #[cfg(any(adc_g0, adc_u0))]
294 T::regs().ccr().modify(|reg| {
295 reg.set_vrefen(true);
296 });
297
298 // "Table 24. Embedded internal voltage reference" states that it takes a maximum of 12 us
299 // to stabilize the internal voltage reference.
300 blocking_delay_us(15);
301
302 VrefInt {}
303 }
304
305 pub fn enable_temperature(&self) -> Temperature {
306 cfg_if! {
307 if #[cfg(any(adc_g0, adc_u0))] {
308 T::regs().ccr().modify(|reg| {
309 reg.set_tsen(true);
310 });
311 } else if #[cfg(any(adc_h5, adc_h7rs))] {
312 T::common_regs().ccr().modify(|reg| {
313 reg.set_tsen(true);
314 });
315 } else {
316 T::common_regs().ccr().modify(|reg| {
317 reg.set_ch17sel(true);
318 });
319 }
320 }
321
322 Temperature {}
323 }
324
325 pub fn enable_vbat(&self) -> Vbat {
326 cfg_if! {
327 if #[cfg(any(adc_g0, adc_u0))] {
328 T::regs().ccr().modify(|reg| {
329 reg.set_vbaten(true);
330 });
331 } else if #[cfg(any(adc_h5, adc_h7rs))] {
332 T::common_regs().ccr().modify(|reg| {
333 reg.set_vbaten(true);
334 });
335 } else {
336 T::common_regs().ccr().modify(|reg| {
337 reg.set_ch18sel(true);
338 });
339 }
340 }
341
342 Vbat {}
343 }
344
345 /// Set the ADC sample time.
346 pub fn set_sample_time(&mut self, sample_time: SampleTime) {
347 self.sample_time = sample_time;
348 }
349
350 /// Get the ADC sample time.
351 pub fn sample_time(&self) -> SampleTime {
352 self.sample_time
353 }
354 233
355 /// Set the ADC resolution. 234 T::regs().dr().read().0 as u16
356 pub fn set_resolution(&mut self, resolution: Resolution) {
357 #[cfg(not(any(adc_g0, adc_u0)))]
358 T::regs().cfgr().modify(|reg| reg.set_res(resolution.into()));
359 #[cfg(any(adc_g0, adc_u0))]
360 T::regs().cfgr1().modify(|reg| reg.set_res(resolution.into()));
361 }
362
363 pub fn set_averaging(&mut self, averaging: Averaging) {
364 let (enable, samples, right_shift) = match averaging {
365 Averaging::Disabled => (false, 0, 0),
366 Averaging::Samples2 => (true, 0, 1),
367 Averaging::Samples4 => (true, 1, 2),
368 Averaging::Samples8 => (true, 2, 3),
369 Averaging::Samples16 => (true, 3, 4),
370 Averaging::Samples32 => (true, 4, 5),
371 Averaging::Samples64 => (true, 5, 6),
372 Averaging::Samples128 => (true, 6, 7),
373 Averaging::Samples256 => (true, 7, 8),
374 };
375 T::regs().cfgr2().modify(|reg| {
376 #[cfg(not(any(adc_g0, adc_u0)))]
377 reg.set_rovse(enable);
378 #[cfg(any(adc_g0, adc_u0))]
379 reg.set_ovse(enable);
380 #[cfg(any(adc_h5, adc_h7rs))]
381 reg.set_ovsr(samples.into());
382 #[cfg(not(any(adc_h5, adc_h7rs)))]
383 reg.set_ovsr(samples.into());
384 reg.set_ovss(right_shift.into());
385 })
386 }
387 /*
388 /// Convert a raw sample from the `Temperature` to deg C
389 pub fn to_degrees_centigrade(sample: u16) -> f32 {
390 (130.0 - 30.0) / (VtempCal130::get().read() as f32 - VtempCal30::get().read() as f32)
391 * (sample as f32 - VtempCal30::get().read() as f32)
392 + 30.0
393 } 235 }
394 */
395 236
396 /// Perform a single conversion. 237 fn configure_dma(conversion_mode: ConversionMode) {
397 fn convert(&mut self) -> u16 { 238 // Set continuous mode with oneshot dma.
239 // Clear overrun flag before starting transfer.
398 T::regs().isr().modify(|reg| { 240 T::regs().isr().modify(|reg| {
399 reg.set_eos(true); 241 reg.set_ovr(true);
400 reg.set_eoc(true);
401 });
402
403 // Start conversion
404 T::regs().cr().modify(|reg| {
405 reg.set_adstart(true);
406 }); 242 });
407 243
408 while !T::regs().isr().read().eos() { 244 #[cfg(not(any(adc_g0, adc_u0)))]
409 // spin 245 let regs = T::regs().cfgr();
410 }
411 246
412 T::regs().dr().read().0 as u16 247 #[cfg(any(adc_g0, adc_u0))]
413 } 248 let regs = T::regs().cfgr1();
414 249
415 /// Read an ADC channel. 250 regs.modify(|reg| {
416 pub fn blocking_read(&mut self, channel: &mut impl AdcChannel<T>) -> u16 { 251 reg.set_discen(false);
417 self.read_channel(channel) 252 reg.set_cont(true);
253 reg.set_dmacfg(match conversion_mode {
254 ConversionMode::Singular => Dmacfg::ONE_SHOT,
255 #[cfg(any(adc_v2, adc_g4, adc_v3, adc_g0, adc_u0))]
256 ConversionMode::Repeated(_) => Dmacfg::CIRCULAR,
257 });
258 reg.set_dmaen(true);
259 });
418 } 260 }
419 261
420 /// Read one or multiple ADC channels using DMA. 262 fn configure_sequence(sequence: impl ExactSizeIterator<Item = ((u8, bool), SampleTime)>) {
421 ///
422 /// `readings` must have a length that is a multiple of the length of the
423 /// `sequence` iterator.
424 ///
425 /// Note: The order of values in `readings` is defined by the pin ADC
426 /// channel number and not the pin order in `sequence`.
427 ///
428 /// Example
429 /// ```rust,ignore
430 /// use embassy_stm32::adc::{Adc, AdcChannel}
431 ///
432 /// let mut adc = Adc::new(p.ADC1);
433 /// let mut adc_pin0 = p.PA0.degrade_adc();
434 /// let mut adc_pin1 = p.PA1.degrade_adc();
435 /// let mut measurements = [0u16; 2];
436 ///
437 /// adc.read(
438 /// p.DMA1_CH2.reborrow(),
439 /// [
440 /// (&mut *adc_pin0, SampleTime::CYCLES160_5),
441 /// (&mut *adc_pin1, SampleTime::CYCLES160_5),
442 /// ]
443 /// .into_iter(),
444 /// &mut measurements,
445 /// )
446 /// .await;
447 /// defmt::info!("measurements: {}", measurements);
448 /// ```
449 pub async fn read(
450 &mut self,
451 rx_dma: Peri<'_, impl RxDma<T>>,
452 sequence: impl ExactSizeIterator<Item = (&mut AnyAdcChannel<T>, SampleTime)>,
453 readings: &mut [u16],
454 ) {
455 assert!(sequence.len() != 0, "Asynchronous read sequence cannot be empty");
456 assert!(
457 readings.len() % sequence.len() == 0,
458 "Readings length must be a multiple of sequence length"
459 );
460 assert!(
461 sequence.len() <= 16,
462 "Asynchronous read sequence cannot be more than 16 in length"
463 );
464
465 #[cfg(all(feature = "low-power", stm32wlex))]
466 let _device_busy = crate::low_power::DeviceBusy::new_stop1();
467
468 // Ensure no conversions are ongoing and ADC is enabled.
469 Self::cancel_conversions();
470 self.enable();
471
472 // Set sequence length 263 // Set sequence length
473 #[cfg(not(any(adc_g0, adc_u0)))] 264 #[cfg(not(any(adc_g0, adc_u0)))]
474 T::regs().sqr1().modify(|w| { 265 T::regs().sqr1().modify(|w| {
@@ -481,10 +272,10 @@ impl<'d, T: Instance> Adc<'d, T> {
481 272
482 T::regs().chselr().write(|chselr| { 273 T::regs().chselr().write(|chselr| {
483 T::regs().smpr().write(|smpr| { 274 T::regs().smpr().write(|smpr| {
484 for (channel, sample_time) in sequence { 275 for ((channel, _), sample_time) in sequence {
485 chselr.set_chsel(channel.channel.into(), true); 276 chselr.set_chsel(channel.into(), true);
486 if let Some(i) = sample_times.iter().position(|&t| t == sample_time) { 277 if let Some(i) = sample_times.iter().position(|&t| t == sample_time) {
487 smpr.set_smpsel(channel.channel.into(), (i as u8).into()); 278 smpr.set_smpsel(channel.into(), (i as u8).into());
488 } else { 279 } else {
489 smpr.set_sample_time(sample_times.len(), sample_time); 280 smpr.set_sample_time(sample_times.len(), sample_time);
490 if let Err(_) = sample_times.push(sample_time) { 281 if let Err(_) = sample_times.push(sample_time) {
@@ -504,30 +295,63 @@ impl<'d, T: Instance> Adc<'d, T> {
504 let mut channel_mask = 0; 295 let mut channel_mask = 0;
505 296
506 // Configure channels and ranks 297 // Configure channels and ranks
507 for (_i, (channel, sample_time)) in sequence.enumerate() { 298 for (_i, ((channel, _), sample_time)) in sequence.enumerate() {
508 Self::configure_channel(channel, sample_time); 299 // RM0492, RM0481, etc.
300 // "This option bit must be set to 1 when ADCx_INP0 or ADCx_INN1 channel is selected."
301 #[cfg(any(adc_h5, adc_h7rs))]
302 if channel == 0 {
303 T::regs().or().modify(|reg| reg.set_op0(true));
304 }
305
306 // Configure channel
307 cfg_if! {
308 if #[cfg(adc_u0)] {
309 // On G0 and U6 all channels use the same sampling time.
310 T::regs().smpr().modify(|reg| reg.set_smp1(sample_time.into()));
311 } else if #[cfg(any(adc_h5, adc_h7rs))] {
312 match channel {
313 0..=9 => T::regs().smpr1().modify(|w| w.set_smp(channel as usize % 10, sample_time.into())),
314 _ => T::regs().smpr2().modify(|w| w.set_smp(channel as usize % 10, sample_time.into())),
315 }
316 } else {
317 let sample_time = sample_time.into();
318 T::regs()
319 .smpr(channel as usize / 10)
320 .modify(|reg| reg.set_smp(channel as usize % 10, sample_time));
321 }
322 }
323
324 #[cfg(stm32h7)]
325 {
326 use crate::pac::adc::vals::Pcsel;
327
328 T::regs().cfgr2().modify(|w| w.set_lshift(0));
329 T::regs()
330 .pcsel()
331 .write(|w| w.set_pcsel(channel.channel() as _, Pcsel::PRESELECTED));
332 }
509 333
510 // Each channel is sampled according to sequence 334 // Each channel is sampled according to sequence
511 #[cfg(not(any(adc_g0, adc_u0)))] 335 #[cfg(not(any(adc_g0, adc_u0)))]
512 match _i { 336 match _i {
513 0..=3 => { 337 0..=3 => {
514 T::regs().sqr1().modify(|w| { 338 T::regs().sqr1().modify(|w| {
515 w.set_sq(_i, channel.channel()); 339 w.set_sq(_i, channel);
516 }); 340 });
517 } 341 }
518 4..=8 => { 342 4..=8 => {
519 T::regs().sqr2().modify(|w| { 343 T::regs().sqr2().modify(|w| {
520 w.set_sq(_i - 4, channel.channel()); 344 w.set_sq(_i - 4, channel);
521 }); 345 });
522 } 346 }
523 9..=13 => { 347 9..=13 => {
524 T::regs().sqr3().modify(|w| { 348 T::regs().sqr3().modify(|w| {
525 w.set_sq(_i - 9, channel.channel()); 349 w.set_sq(_i - 9, channel);
526 }); 350 });
527 } 351 }
528 14..=15 => { 352 14..=15 => {
529 T::regs().sqr4().modify(|w| { 353 T::regs().sqr4().modify(|w| {
530 w.set_sq(_i - 14, channel.channel()); 354 w.set_sq(_i - 14, channel);
531 }); 355 });
532 } 356 }
533 _ => unreachable!(), 357 _ => unreachable!(),
@@ -535,7 +359,7 @@ impl<'d, T: Instance> Adc<'d, T> {
535 359
536 #[cfg(adc_u0)] 360 #[cfg(adc_u0)]
537 { 361 {
538 channel_mask |= 1 << channel.channel(); 362 channel_mask |= 1 << channel;
539 } 363 }
540 } 364 }
541 365
@@ -547,312 +371,234 @@ impl<'d, T: Instance> Adc<'d, T> {
547 reg.set_chsel(channel_mask); 371 reg.set_chsel(channel_mask);
548 }); 372 });
549 } 373 }
550 // Set continuous mode with oneshot dma. 374 }
551 // Clear overrun flag before starting transfer. 375}
552 T::regs().isr().modify(|reg| {
553 reg.set_ovr(true);
554 });
555 376
556 #[cfg(not(any(adc_g0, adc_u0)))] 377impl<'d, T: Instance> Adc<'d, T> {
557 T::regs().cfgr().modify(|reg| { 378 /// Enable the voltage regulator
558 reg.set_discen(false); 379 fn init_regulator() {
559 reg.set_cont(true); 380 rcc::enable_and_reset::<T>();
560 reg.set_dmacfg(Dmacfg::ONE_SHOT); 381 T::regs().cr().modify(|reg| {
561 reg.set_dmaen(true); 382 #[cfg(not(any(adc_g0, adc_u0)))]
383 reg.set_deeppwd(false);
384 reg.set_advregen(true);
562 }); 385 });
386
387 // If this is false then each ADC_CHSELR bit enables an input channel.
388 // This is the reset value, so has no effect.
563 #[cfg(any(adc_g0, adc_u0))] 389 #[cfg(any(adc_g0, adc_u0))]
564 T::regs().cfgr1().modify(|reg| { 390 T::regs().cfgr1().modify(|reg| {
565 reg.set_discen(false); 391 reg.set_chselrmod(false);
566 reg.set_cont(true);
567 reg.set_dmacfg(Dmacfg::ONE_SHOT);
568 reg.set_dmaen(true);
569 }); 392 });
570 393
571 let request = rx_dma.request(); 394 blocking_delay_us(20);
572 let transfer = unsafe { 395 }
573 Transfer::new_read(
574 rx_dma,
575 request,
576 T::regs().dr().as_ptr() as *mut u16,
577 readings,
578 Default::default(),
579 )
580 };
581 396
582 // Start conversion 397 /// Calibrate to remove conversion offset
398 fn init_calibrate() {
583 T::regs().cr().modify(|reg| { 399 T::regs().cr().modify(|reg| {
584 reg.set_adstart(true); 400 reg.set_adcal(true);
585 }); 401 });
586 402
587 // Wait for conversion sequence to finish. 403 while T::regs().cr().read().adcal() {
588 transfer.await; 404 // spin
589 405 }
590 // Ensure conversions are finished.
591 Self::cancel_conversions();
592 406
593 // Reset configuration. 407 blocking_delay_us(1);
594 #[cfg(not(any(adc_g0, adc_u0)))]
595 T::regs().cfgr().modify(|reg| {
596 reg.set_cont(false);
597 });
598 #[cfg(any(adc_g0, adc_u0))]
599 T::regs().cfgr1().modify(|reg| {
600 reg.set_cont(false);
601 });
602 } 408 }
603 409
604 /// Configures the ADC to use a DMA ring buffer for continuous data acquisition. 410 /// Initialize the ADC leaving any analog clock at reset value.
605 /// 411 /// For G0 and WL, this is the async clock without prescaler.
606 /// The `dma_buf` should be large enough to prevent DMA buffer overrun. 412 pub fn new(adc: Peri<'d, T>) -> Self {
607 /// The length of the `dma_buf` should be a multiple of the ADC channel count. 413 Self::init_regulator();
608 /// For example, if 3 channels are measured, its length can be 3 * 40 = 120 measurements. 414 Self::init_calibrate();
609 /// 415 Self { adc }
610 /// `read` method is used to read out measurements from the DMA ring buffer, and its buffer should be exactly half of the `dma_buf` length. 416 }
611 /// It is critical to call `read` frequently to prevent DMA buffer overrun.
612 ///
613 /// [`read`]: #method.read
614 #[cfg(any(adc_v3, adc_g0, adc_u0))]
615 pub fn into_ring_buffered<'a>(
616 &mut self,
617 dma: Peri<'a, impl RxDma<T>>,
618 dma_buf: &'a mut [u16],
619 sequence: impl ExactSizeIterator<Item = (&'a mut AnyAdcChannel<T>, SampleTime)>,
620 ) -> RingBufferedAdc<'a, T> {
621 assert!(!dma_buf.is_empty() && dma_buf.len() <= 0xFFFF);
622 assert!(sequence.len() != 0, "Asynchronous read sequence cannot be empty");
623 assert!(
624 sequence.len() <= 16,
625 "Asynchronous read sequence cannot be more than 16 in length"
626 );
627 // reset conversions and enable the adc
628 Self::cancel_conversions();
629 self.enable();
630
631 //adc side setup
632 417
633 // Set sequence length 418 pub fn new_with_config(adc: Peri<'d, T>, config: AdcConfig) -> Self {
634 #[cfg(not(any(adc_g0, adc_u0)))] 419 #[cfg(not(adc_g0))]
635 T::regs().sqr1().modify(|w| { 420 let s = Self::new(adc);
636 w.set_l(sequence.len() as u8 - 1);
637 });
638 421
639 #[cfg(adc_g0)] 422 #[cfg(adc_g0)]
640 { 423 let s = match config.clock {
641 let mut sample_times = Vec::<SampleTime, SAMPLE_TIMES_CAPACITY>::new(); 424 Some(clock) => Self::new_with_clock(adc, clock),
425 None => Self::new(adc),
426 };
642 427
643 T::regs().chselr().write(|chselr| { 428 #[cfg(any(adc_g0, adc_u0, adc_v3))]
644 T::regs().smpr().write(|smpr| { 429 if let Some(shift) = config.oversampling_shift {
645 for (channel, sample_time) in sequence { 430 T::regs().cfgr2().modify(|reg| reg.set_ovss(shift));
646 chselr.set_chsel(channel.channel.into(), true);
647 if let Some(i) = sample_times.iter().position(|&t| t == sample_time) {
648 smpr.set_smpsel(channel.channel.into(), (i as u8).into());
649 } else {
650 smpr.set_sample_time(sample_times.len(), sample_time);
651 if let Err(_) = sample_times.push(sample_time) {
652 panic!(
653 "Implementation is limited to {} unique sample times among all channels.",
654 SAMPLE_TIMES_CAPACITY
655 );
656 }
657 }
658 }
659 })
660 });
661 } 431 }
662 #[cfg(not(adc_g0))]
663 {
664 #[cfg(adc_u0)]
665 let mut channel_mask = 0;
666 432
667 // Configure channels and ranks 433 #[cfg(any(adc_g0, adc_u0, adc_v3))]
668 for (_i, (channel, sample_time)) in sequence.enumerate() { 434 if let Some(ratio) = config.oversampling_ratio {
669 Self::configure_channel(channel, sample_time); 435 T::regs().cfgr2().modify(|reg| reg.set_ovsr(ratio));
436 }
670 437
671 // Each channel is sampled according to sequence 438 #[cfg(any(adc_g0, adc_u0))]
672 #[cfg(not(any(adc_g0, adc_u0)))] 439 if let Some(enable) = config.oversampling_enable {
673 match _i { 440 T::regs().cfgr2().modify(|reg| reg.set_ovse(enable));
674 0..=3 => { 441 }
675 T::regs().sqr1().modify(|w| {
676 w.set_sq(_i, channel.channel());
677 });
678 }
679 4..=8 => {
680 T::regs().sqr2().modify(|w| {
681 w.set_sq(_i - 4, channel.channel());
682 });
683 }
684 9..=13 => {
685 T::regs().sqr3().modify(|w| {
686 w.set_sq(_i - 9, channel.channel());
687 });
688 }
689 14..=15 => {
690 T::regs().sqr4().modify(|w| {
691 w.set_sq(_i - 14, channel.channel());
692 });
693 }
694 _ => unreachable!(),
695 }
696 442
697 #[cfg(adc_u0)] 443 #[cfg(adc_v3)]
698 { 444 if let Some((mode, trig_mode, enable)) = config.oversampling_mode {
699 channel_mask |= 1 << channel.channel(); 445 T::regs().cfgr2().modify(|reg| reg.set_trovs(trig_mode));
700 } 446 T::regs().cfgr2().modify(|reg| reg.set_rovsm(mode));
701 } 447 T::regs().cfgr2().modify(|reg| reg.set_rovse(enable));
448 }
702 449
703 // On G0 and U0 enabled channels are sampled from 0 to last channel. 450 if let Some(resolution) = config.resolution {
704 // It is possible to add up to 8 sequences if CHSELRMOD = 1. 451 #[cfg(not(any(adc_g0, adc_u0)))]
705 // However for supporting more than 8 channels alternative CHSELRMOD = 0 approach is used. 452 T::regs().cfgr().modify(|reg| reg.set_res(resolution.into()));
706 #[cfg(adc_u0)] 453 #[cfg(any(adc_g0, adc_u0))]
707 T::regs().chselr().modify(|reg| { 454 T::regs().cfgr1().modify(|reg| reg.set_res(resolution.into()));
708 reg.set_chsel(channel_mask);
709 });
710 } 455 }
711 // Set continuous mode with Circular dma.
712 // Clear overrun flag before starting transfer.
713 T::regs().isr().modify(|reg| {
714 reg.set_ovr(true);
715 });
716 456
717 #[cfg(not(any(adc_g0, adc_u0)))] 457 if let Some(averaging) = config.averaging {
718 T::regs().cfgr().modify(|reg| { 458 let (enable, samples, right_shift) = match averaging {
719 reg.set_discen(false); 459 Averaging::Disabled => (false, 0, 0),
720 reg.set_cont(true); 460 Averaging::Samples2 => (true, 0, 1),
721 reg.set_dmacfg(Dmacfg::CIRCULAR); 461 Averaging::Samples4 => (true, 1, 2),
722 reg.set_dmaen(true); 462 Averaging::Samples8 => (true, 2, 3),
723 }); 463 Averaging::Samples16 => (true, 3, 4),
724 #[cfg(any(adc_g0, adc_u0))] 464 Averaging::Samples32 => (true, 4, 5),
725 T::regs().cfgr1().modify(|reg| { 465 Averaging::Samples64 => (true, 5, 6),
726 reg.set_discen(false); 466 Averaging::Samples128 => (true, 6, 7),
727 reg.set_cont(true); 467 Averaging::Samples256 => (true, 7, 8),
728 reg.set_dmacfg(Dmacfg::CIRCULAR); 468 };
729 reg.set_dmaen(true); 469 T::regs().cfgr2().modify(|reg| {
730 }); 470 #[cfg(not(any(adc_g0, adc_u0)))]
471 reg.set_rovse(enable);
472 #[cfg(any(adc_g0, adc_u0))]
473 reg.set_ovse(enable);
474 #[cfg(any(adc_h5, adc_h7rs))]
475 reg.set_ovsr(samples.into());
476 #[cfg(not(any(adc_h5, adc_h7rs)))]
477 reg.set_ovsr(samples.into());
478 reg.set_ovss(right_shift.into());
479 })
480 }
731 481
732 RingBufferedAdc::new(dma, dma_buf) 482 s
733 } 483 }
734 484
735 #[cfg(not(adc_g0))] 485 #[cfg(adc_g0)]
736 fn configure_channel(channel: &mut impl AdcChannel<T>, sample_time: SampleTime) { 486 /// Initialize ADC with explicit clock for the analog ADC
737 // RM0492, RM0481, etc. 487 pub fn new_with_clock(adc: Peri<'d, T>, clock: Clock) -> Self {
738 // "This option bit must be set to 1 when ADCx_INP0 or ADCx_INN1 channel is selected." 488 Self::init_regulator();
739 #[cfg(any(adc_h5, adc_h7rs))] 489
740 if channel.channel() == 0 { 490 #[cfg(any(stm32wl5x))]
741 T::regs().or().modify(|reg| reg.set_op0(true)); 491 {
492 // Reset value 0 is actually _No clock selected_ in the STM32WL5x reference manual
493 let async_clock_available = pac::RCC.ccipr().read().adcsel() != pac::rcc::vals::Adcsel::_RESERVED_0;
494 match clock {
495 Clock::Async { div: _ } => {
496 assert!(async_clock_available);
497 }
498 Clock::Sync { div: _ } => {
499 if async_clock_available {
500 warn!("Not using configured ADC clock");
501 }
502 }
503 }
742 } 504 }
505 match clock {
506 Clock::Async { div } => T::regs().ccr().modify(|reg| reg.set_presc(div)),
507 Clock::Sync { div } => T::regs().cfgr2().modify(|reg| {
508 reg.set_ckmode(match div {
509 CkModePclk::DIV1 => Ckmode::PCLK,
510 CkModePclk::DIV2 => Ckmode::PCLK_DIV2,
511 CkModePclk::DIV4 => Ckmode::PCLK_DIV4,
512 })
513 }),
514 }
515
516 Self::init_calibrate();
743 517
744 // Configure channel 518 Self { adc }
745 Self::set_channel_sample_time(channel.channel(), sample_time);
746 } 519 }
747 520
748 fn read_channel(&mut self, channel: &mut impl AdcChannel<T>) -> u16 { 521 pub fn enable_vrefint(&self) -> VrefInt {
749 self.enable();
750 #[cfg(not(adc_g0))]
751 Self::configure_channel(channel, self.sample_time);
752 #[cfg(adc_g0)]
753 T::regs().smpr().write(|reg| {
754 reg.set_sample_time(0, self.sample_time);
755 reg.set_smpsel(channel.channel().into(), Smpsel::SMP1);
756 });
757 // Select channel
758 #[cfg(not(any(adc_g0, adc_u0)))] 522 #[cfg(not(any(adc_g0, adc_u0)))]
759 T::regs().sqr1().write(|reg| reg.set_sq(0, channel.channel())); 523 T::common_regs().ccr().modify(|reg| {
524 reg.set_vrefen(true);
525 });
760 #[cfg(any(adc_g0, adc_u0))] 526 #[cfg(any(adc_g0, adc_u0))]
761 T::regs().chselr().write(|reg| { 527 T::regs().ccr().modify(|reg| {
762 #[cfg(adc_g0)] 528 reg.set_vrefen(true);
763 reg.set_chsel(channel.channel().into(), true);
764 #[cfg(adc_u0)]
765 reg.set_chsel(1 << channel.channel());
766 }); 529 });
767 530
768 // Some models are affected by an erratum: 531 // "Table 24. Embedded internal voltage reference" states that it takes a maximum of 12 us
769 // If we perform conversions slower than 1 kHz, the first read ADC value can be 532 // to stabilize the internal voltage reference.
770 // corrupted, so we discard it and measure again. 533 blocking_delay_us(15);
771 //
772 // STM32L471xx: Section 2.7.3
773 // STM32G4: Section 2.7.3
774 #[cfg(any(rcc_l4, rcc_g4))]
775 let _ = self.convert();
776 let val = self.convert();
777
778 T::regs().cr().modify(|reg| reg.set_addis(true));
779
780 // RM0492, RM0481, etc.
781 // "This option bit must be set to 1 when ADCx_INP0 or ADCx_INN1 channel is selected."
782 #[cfg(any(adc_h5, adc_h7rs))]
783 if channel.channel() == 0 {
784 T::regs().or().modify(|reg| reg.set_op0(false));
785 }
786
787 val
788 }
789
790 #[cfg(adc_g0)]
791 pub fn set_oversampling_shift(&mut self, shift: Ovss) {
792 T::regs().cfgr2().modify(|reg| reg.set_ovss(shift));
793 }
794 #[cfg(adc_u0)]
795 pub fn set_oversampling_shift(&mut self, shift: u8) {
796 T::regs().cfgr2().modify(|reg| reg.set_ovss(shift));
797 }
798 534
799 #[cfg(adc_g0)] 535 VrefInt {}
800 pub fn set_oversampling_ratio(&mut self, ratio: Ovsr) {
801 T::regs().cfgr2().modify(|reg| reg.set_ovsr(ratio));
802 }
803 #[cfg(adc_u0)]
804 pub fn set_oversampling_ratio(&mut self, ratio: u8) {
805 T::regs().cfgr2().modify(|reg| reg.set_ovsr(ratio));
806 } 536 }
807 537
808 #[cfg(any(adc_g0, adc_u0))] 538 pub fn enable_temperature(&self) -> Temperature {
809 pub fn oversampling_enable(&mut self, enable: bool) { 539 cfg_if! {
810 T::regs().cfgr2().modify(|reg| reg.set_ovse(enable)); 540 if #[cfg(any(adc_g0, adc_u0))] {
811 } 541 T::regs().ccr().modify(|reg| {
542 reg.set_tsen(true);
543 });
544 } else if #[cfg(any(adc_h5, adc_h7rs))] {
545 T::common_regs().ccr().modify(|reg| {
546 reg.set_tsen(true);
547 });
548 } else {
549 T::common_regs().ccr().modify(|reg| {
550 reg.set_ch17sel(true);
551 });
552 }
553 }
812 554
813 #[cfg(adc_v3)] 555 Temperature {}
814 pub fn enable_regular_oversampling_mode(&mut self, mode: Rovsm, trig_mode: Trovs, enable: bool) {
815 T::regs().cfgr2().modify(|reg| reg.set_trovs(trig_mode));
816 T::regs().cfgr2().modify(|reg| reg.set_rovsm(mode));
817 T::regs().cfgr2().modify(|reg| reg.set_rovse(enable));
818 } 556 }
819 557
820 #[cfg(adc_v3)] 558 pub fn enable_vbat(&self) -> Vbat {
821 pub fn set_oversampling_ratio(&mut self, ratio: OversamplingRatio) { 559 cfg_if! {
822 T::regs().cfgr2().modify(|reg| reg.set_ovsr(ratio)); 560 if #[cfg(any(adc_g0, adc_u0))] {
823 } 561 T::regs().ccr().modify(|reg| {
562 reg.set_vbaten(true);
563 });
564 } else if #[cfg(any(adc_h5, adc_h7rs))] {
565 T::common_regs().ccr().modify(|reg| {
566 reg.set_vbaten(true);
567 });
568 } else {
569 T::common_regs().ccr().modify(|reg| {
570 reg.set_ch18sel(true);
571 });
572 }
573 }
824 574
825 #[cfg(adc_v3)] 575 Vbat {}
826 pub fn set_oversampling_shift(&mut self, shift: OversamplingShift) {
827 T::regs().cfgr2().modify(|reg| reg.set_ovss(shift));
828 } 576 }
829 577
830 #[cfg(not(adc_g0))] 578 pub fn disable_vbat(&self) {
831 fn set_channel_sample_time(_ch: u8, sample_time: SampleTime) {
832 cfg_if! { 579 cfg_if! {
833 if #[cfg(adc_u0)] { 580 if #[cfg(any(adc_g0, adc_u0))] {
834 // On G0 and U6 all channels use the same sampling time. 581 T::regs().ccr().modify(|reg| {
835 T::regs().smpr().modify(|reg| reg.set_smp1(sample_time.into())); 582 reg.set_vbaten(false);
583 });
836 } else if #[cfg(any(adc_h5, adc_h7rs))] { 584 } else if #[cfg(any(adc_h5, adc_h7rs))] {
837 match _ch { 585 T::common_regs().ccr().modify(|reg| {
838 0..=9 => T::regs().smpr1().modify(|w| w.set_smp(_ch as usize % 10, sample_time.into())), 586 reg.set_vbaten(false);
839 _ => T::regs().smpr2().modify(|w| w.set_smp(_ch as usize % 10, sample_time.into())), 587 });
840 }
841 } else { 588 } else {
842 let sample_time = sample_time.into(); 589 T::common_regs().ccr().modify(|reg| {
843 T::regs() 590 reg.set_ch18sel(false);
844 .smpr(_ch as usize / 10) 591 });
845 .modify(|reg| reg.set_smp(_ch as usize % 10, sample_time));
846 } 592 }
847 } 593 }
848 } 594 }
849 595
850 fn cancel_conversions() { 596 /*
851 if T::regs().cr().read().adstart() && !T::regs().cr().read().addis() { 597 /// Convert a raw sample from the `Temperature` to deg C
852 T::regs().cr().modify(|reg| { 598 pub fn to_degrees_centigrade(sample: u16) -> f32 {
853 reg.set_adstp(true); 599 (130.0 - 30.0) / (VtempCal130::get().read() as f32 - VtempCal30::get().read() as f32)
854 }); 600 * (sample as f32 - VtempCal30::get().read() as f32)
855 while T::regs().cr().read().adstart() {} 601 + 30.0
856 }
857 } 602 }
603 */
858} 604}
diff --git a/embassy-stm32/src/adc/v4.rs b/embassy-stm32/src/adc/v4.rs
index c7d0103a6..804e63db6 100644
--- a/embassy-stm32/src/adc/v4.rs
+++ b/embassy-stm32/src/adc/v4.rs
@@ -4,10 +4,8 @@ use pac::adc::vals::{Adcaldif, Boost};
4use pac::adc::vals::{Adstp, Difsel, Dmngt, Exten, Pcsel}; 4use pac::adc::vals::{Adstp, Difsel, Dmngt, Exten, Pcsel};
5use pac::adccommon::vals::Presc; 5use pac::adccommon::vals::Presc;
6 6
7use super::{ 7use super::{Adc, Averaging, Instance, Resolution, SampleTime, Temperature, Vbat, VrefInt, blocking_delay_us};
8 Adc, AdcChannel, AnyAdcChannel, Instance, Resolution, RxDma, SampleTime, SealedAdcChannel, blocking_delay_us, 8use crate::adc::ConversionMode;
9};
10use crate::dma::Transfer;
11use crate::time::Hertz; 9use crate::time::Hertz;
12use crate::{Peri, pac, rcc}; 10use crate::{Peri, pac, rcc};
13 11
@@ -25,149 +23,227 @@ const MAX_ADC_CLK_FREQ: Hertz = Hertz::mhz(50);
25const MAX_ADC_CLK_FREQ: Hertz = Hertz::mhz(55); 23const MAX_ADC_CLK_FREQ: Hertz = Hertz::mhz(55);
26 24
27#[cfg(stm32g4)] 25#[cfg(stm32g4)]
28const VREF_CHANNEL: u8 = 18; 26impl<T: Instance> super::SealedSpecialConverter<super::VrefInt> for T {
27 const CHANNEL: u8 = 18;
28}
29#[cfg(stm32g4)] 29#[cfg(stm32g4)]
30const TEMP_CHANNEL: u8 = 16; 30impl<T: Instance> super::SealedSpecialConverter<super::Temperature> for T {
31 const CHANNEL: u8 = 16;
32}
31 33
32#[cfg(stm32h7)] 34#[cfg(stm32h7)]
33const VREF_CHANNEL: u8 = 19; 35impl<T: Instance> super::SealedSpecialConverter<super::VrefInt> for T {
36 const CHANNEL: u8 = 19;
37}
34#[cfg(stm32h7)] 38#[cfg(stm32h7)]
35const TEMP_CHANNEL: u8 = 18; 39impl<T: Instance> super::SealedSpecialConverter<super::Temperature> for T {
40 const CHANNEL: u8 = 18;
41}
36 42
37// TODO this should be 14 for H7a/b/35 43// TODO this should be 14 for H7a/b/35
38#[cfg(not(stm32u5))] 44#[cfg(not(stm32u5))]
39const VBAT_CHANNEL: u8 = 17; 45impl<T: Instance> super::SealedSpecialConverter<super::Vbat> for T {
46 const CHANNEL: u8 = 17;
47}
40 48
41#[cfg(stm32u5)] 49#[cfg(stm32u5)]
42const VREF_CHANNEL: u8 = 0; 50impl<T: Instance> super::SealedSpecialConverter<super::VrefInt> for T {
51 const CHANNEL: u8 = 0;
52}
43#[cfg(stm32u5)] 53#[cfg(stm32u5)]
44const TEMP_CHANNEL: u8 = 19; 54impl<T: Instance> super::SealedSpecialConverter<super::Temperature> for T {
55 const CHANNEL: u8 = 19;
56}
45#[cfg(stm32u5)] 57#[cfg(stm32u5)]
46const VBAT_CHANNEL: u8 = 18; 58impl<T: Instance> super::SealedSpecialConverter<super::Vbat> for T {
47 59 const CHANNEL: u8 = 18;
48// NOTE: Vrefint/Temperature/Vbat are not available on all ADCs, this currently cannot be modeled with stm32-data, so these are available from the software on all ADCs
49/// Internal voltage reference channel.
50pub struct VrefInt;
51impl<T: Instance> AdcChannel<T> for VrefInt {}
52impl<T: Instance> SealedAdcChannel<T> for VrefInt {
53 fn channel(&self) -> u8 {
54 VREF_CHANNEL
55 }
56} 60}
57 61
58/// Internal temperature channel. 62fn from_ker_ck(frequency: Hertz) -> Presc {
59pub struct Temperature; 63 let raw_prescaler = frequency.0 / MAX_ADC_CLK_FREQ.0;
60impl<T: Instance> AdcChannel<T> for Temperature {} 64 match raw_prescaler {
61impl<T: Instance> SealedAdcChannel<T> for Temperature { 65 0 => Presc::DIV1,
62 fn channel(&self) -> u8 { 66 1 => Presc::DIV2,
63 TEMP_CHANNEL 67 2..=3 => Presc::DIV4,
68 4..=5 => Presc::DIV6,
69 6..=7 => Presc::DIV8,
70 8..=9 => Presc::DIV10,
71 10..=11 => Presc::DIV12,
72 _ => unimplemented!(),
64 } 73 }
65} 74}
66 75
67/// Internal battery voltage channel. 76/// Adc configuration
68pub struct Vbat; 77#[derive(Default)]
69impl<T: Instance> AdcChannel<T> for Vbat {} 78pub struct AdcConfig {
70impl<T: Instance> SealedAdcChannel<T> for Vbat { 79 pub resolution: Option<Resolution>,
71 fn channel(&self) -> u8 { 80 pub averaging: Option<Averaging>,
72 VBAT_CHANNEL
73 }
74} 81}
75 82
76// NOTE (unused): The prescaler enum closely copies the hardware capabilities, 83impl<T: Instance> super::SealedAnyInstance for T {
77// but high prescaling doesn't make a lot of sense in the current implementation and is ommited. 84 fn dr() -> *mut u16 {
78#[allow(unused)] 85 T::regs().dr().as_ptr() as *mut u16
79enum Prescaler { 86 }
80 NotDivided, 87
81 DividedBy2, 88 fn enable() {
82 DividedBy4, 89 T::regs().isr().write(|w| w.set_adrdy(true));
83 DividedBy6, 90 T::regs().cr().modify(|w| w.set_aden(true));
84 DividedBy8, 91 while !T::regs().isr().read().adrdy() {}
85 DividedBy10, 92 T::regs().isr().write(|w| w.set_adrdy(true));
86 DividedBy12, 93 }
87 DividedBy16,
88 DividedBy32,
89 DividedBy64,
90 DividedBy128,
91 DividedBy256,
92}
93 94
94impl Prescaler { 95 fn start() {
95 fn from_ker_ck(frequency: Hertz) -> Self { 96 // Start conversion
96 let raw_prescaler = frequency.0 / MAX_ADC_CLK_FREQ.0; 97 T::regs().cr().modify(|reg| {
97 match raw_prescaler { 98 reg.set_adstart(true);
98 0 => Self::NotDivided, 99 });
99 1 => Self::DividedBy2, 100 }
100 2..=3 => Self::DividedBy4, 101
101 4..=5 => Self::DividedBy6, 102 fn stop() {
102 6..=7 => Self::DividedBy8, 103 if T::regs().cr().read().adstart() && !T::regs().cr().read().addis() {
103 8..=9 => Self::DividedBy10, 104 T::regs().cr().modify(|reg| {
104 10..=11 => Self::DividedBy12, 105 reg.set_adstp(Adstp::STOP);
105 _ => unimplemented!(), 106 });
107 while T::regs().cr().read().adstart() {}
106 } 108 }
109
110 // Reset configuration.
111 T::regs().cfgr().modify(|reg| {
112 reg.set_cont(false);
113 reg.set_dmngt(Dmngt::from_bits(0));
114 });
107 } 115 }
108 116
109 fn divisor(&self) -> u32 { 117 fn convert() -> u16 {
110 match self { 118 T::regs().isr().modify(|reg| {
111 Prescaler::NotDivided => 1, 119 reg.set_eos(true);
112 Prescaler::DividedBy2 => 2, 120 reg.set_eoc(true);
113 Prescaler::DividedBy4 => 4, 121 });
114 Prescaler::DividedBy6 => 6, 122
115 Prescaler::DividedBy8 => 8, 123 // Start conversion
116 Prescaler::DividedBy10 => 10, 124 T::regs().cr().modify(|reg| {
117 Prescaler::DividedBy12 => 12, 125 reg.set_adstart(true);
118 Prescaler::DividedBy16 => 16, 126 });
119 Prescaler::DividedBy32 => 32, 127
120 Prescaler::DividedBy64 => 64, 128 while !T::regs().isr().read().eos() {
121 Prescaler::DividedBy128 => 128, 129 // spin
122 Prescaler::DividedBy256 => 256,
123 } 130 }
131
132 T::regs().dr().read().0 as u16
124 } 133 }
125 134
126 fn presc(&self) -> Presc { 135 fn configure_dma(conversion_mode: ConversionMode) {
127 match self { 136 match conversion_mode {
128 Prescaler::NotDivided => Presc::DIV1, 137 ConversionMode::Singular => {
129 Prescaler::DividedBy2 => Presc::DIV2, 138 T::regs().isr().modify(|reg| {
130 Prescaler::DividedBy4 => Presc::DIV4, 139 reg.set_ovr(true);
131 Prescaler::DividedBy6 => Presc::DIV6, 140 });
132 Prescaler::DividedBy8 => Presc::DIV8, 141 T::regs().cfgr().modify(|reg| {
133 Prescaler::DividedBy10 => Presc::DIV10, 142 reg.set_cont(true);
134 Prescaler::DividedBy12 => Presc::DIV12, 143 reg.set_dmngt(Dmngt::DMA_ONE_SHOT);
135 Prescaler::DividedBy16 => Presc::DIV16, 144 });
136 Prescaler::DividedBy32 => Presc::DIV32, 145 }
137 Prescaler::DividedBy64 => Presc::DIV64, 146 #[cfg(any(adc_v2, adc_g4, adc_v3, adc_g0, adc_u0))]
138 Prescaler::DividedBy128 => Presc::DIV128, 147 _ => unreachable!(),
139 Prescaler::DividedBy256 => Presc::DIV256,
140 } 148 }
141 } 149 }
142}
143 150
144/// Number of samples used for averaging. 151 fn configure_sequence(sequence: impl ExactSizeIterator<Item = ((u8, bool), SampleTime)>) {
145#[derive(Copy, Clone, Debug)] 152 // Set sequence length
146#[cfg_attr(feature = "defmt", derive(defmt::Format))] 153 T::regs().sqr1().modify(|w| {
147pub enum Averaging { 154 w.set_l(sequence.len() as u8 - 1);
148 Disabled, 155 });
149 Samples2, 156
150 Samples4, 157 // Configure channels and ranks
151 Samples8, 158 for (i, ((channel, _), sample_time)) in sequence.enumerate() {
152 Samples16, 159 let sample_time = sample_time.into();
153 Samples32, 160 if channel <= 9 {
154 Samples64, 161 T::regs().smpr(0).modify(|reg| reg.set_smp(channel as _, sample_time));
155 Samples128, 162 } else {
156 Samples256, 163 T::regs()
157 Samples512, 164 .smpr(1)
158 Samples1024, 165 .modify(|reg| reg.set_smp((channel - 10) as _, sample_time));
166 }
167
168 #[cfg(any(stm32h7, stm32u5))]
169 {
170 T::regs().cfgr2().modify(|w| w.set_lshift(0));
171 T::regs()
172 .pcsel()
173 .modify(|w| w.set_pcsel(channel as _, Pcsel::PRESELECTED));
174 }
175
176 match i {
177 0..=3 => {
178 T::regs().sqr1().modify(|w| {
179 w.set_sq(i, channel);
180 });
181 }
182 4..=8 => {
183 T::regs().sqr2().modify(|w| {
184 w.set_sq(i - 4, channel);
185 });
186 }
187 9..=13 => {
188 T::regs().sqr3().modify(|w| {
189 w.set_sq(i - 9, channel);
190 });
191 }
192 14..=15 => {
193 T::regs().sqr4().modify(|w| {
194 w.set_sq(i - 14, channel);
195 });
196 }
197 _ => unreachable!(),
198 }
199 }
200 }
159} 201}
160 202
161impl<'d, T: Instance> Adc<'d, T> { 203impl<'d, T: Instance + super::AnyInstance> Adc<'d, T> {
204 pub fn new_with_config(adc: Peri<'d, T>, config: AdcConfig) -> Self {
205 let s = Self::new(adc);
206
207 // Set the ADC resolution.
208 if let Some(resolution) = config.resolution {
209 T::regs().cfgr().modify(|reg| reg.set_res(resolution.into()));
210 }
211
212 // Set hardware averaging.
213 if let Some(averaging) = config.averaging {
214 let (enable, samples, right_shift) = match averaging {
215 Averaging::Disabled => (false, 0, 0),
216 Averaging::Samples2 => (true, 1, 1),
217 Averaging::Samples4 => (true, 3, 2),
218 Averaging::Samples8 => (true, 7, 3),
219 Averaging::Samples16 => (true, 15, 4),
220 Averaging::Samples32 => (true, 31, 5),
221 Averaging::Samples64 => (true, 63, 6),
222 Averaging::Samples128 => (true, 127, 7),
223 Averaging::Samples256 => (true, 255, 8),
224 Averaging::Samples512 => (true, 511, 9),
225 Averaging::Samples1024 => (true, 1023, 10),
226 };
227
228 T::regs().cfgr2().modify(|reg| {
229 reg.set_rovse(enable);
230 reg.set_ovsr(samples);
231 reg.set_ovss(right_shift);
232 })
233 }
234
235 s
236 }
237
162 /// Create a new ADC driver. 238 /// Create a new ADC driver.
163 pub fn new(adc: Peri<'d, T>) -> Self { 239 pub fn new(adc: Peri<'d, T>) -> Self {
164 rcc::enable_and_reset::<T>(); 240 rcc::enable_and_reset::<T>();
165 241
166 let prescaler = Prescaler::from_ker_ck(T::frequency()); 242 let prescaler = from_ker_ck(T::frequency());
167 243
168 T::common_regs().ccr().modify(|w| w.set_presc(prescaler.presc())); 244 T::common_regs().ccr().modify(|w| w.set_presc(prescaler));
169 245
170 let frequency = Hertz(T::frequency().0 / prescaler.divisor()); 246 let frequency = T::frequency() / prescaler;
171 info!("ADC frequency set to {}", frequency); 247 info!("ADC frequency set to {}", frequency);
172 248
173 if frequency > MAX_ADC_CLK_FREQ { 249 if frequency > MAX_ADC_CLK_FREQ {
@@ -190,40 +266,20 @@ impl<'d, T: Instance> Adc<'d, T> {
190 }; 266 };
191 T::regs().cr().modify(|w| w.set_boost(boost)); 267 T::regs().cr().modify(|w| w.set_boost(boost));
192 } 268 }
193 let mut s = Self {
194 adc,
195 sample_time: SampleTime::from_bits(0),
196 };
197 s.power_up();
198 s.configure_differential_inputs();
199
200 s.calibrate();
201 blocking_delay_us(1);
202
203 s.enable();
204 s.configure();
205
206 s
207 }
208 269
209 fn power_up(&mut self) {
210 T::regs().cr().modify(|reg| { 270 T::regs().cr().modify(|reg| {
211 reg.set_deeppwd(false); 271 reg.set_deeppwd(false);
212 reg.set_advregen(true); 272 reg.set_advregen(true);
213 }); 273 });
214 274
215 blocking_delay_us(10); 275 blocking_delay_us(10);
216 }
217 276
218 fn configure_differential_inputs(&mut self) {
219 T::regs().difsel().modify(|w| { 277 T::regs().difsel().modify(|w| {
220 for n in 0..20 { 278 for n in 0..20 {
221 w.set_difsel(n, Difsel::SINGLE_ENDED); 279 w.set_difsel(n, Difsel::SINGLE_ENDED);
222 } 280 }
223 }); 281 });
224 }
225 282
226 fn calibrate(&mut self) {
227 T::regs().cr().modify(|w| { 283 T::regs().cr().modify(|w| {
228 #[cfg(not(adc_u5))] 284 #[cfg(not(adc_u5))]
229 w.set_adcaldif(Adcaldif::SINGLE_ENDED); 285 w.set_adcaldif(Adcaldif::SINGLE_ENDED);
@@ -233,21 +289,18 @@ impl<'d, T: Instance> Adc<'d, T> {
233 T::regs().cr().modify(|w| w.set_adcal(true)); 289 T::regs().cr().modify(|w| w.set_adcal(true));
234 290
235 while T::regs().cr().read().adcal() {} 291 while T::regs().cr().read().adcal() {}
236 }
237 292
238 fn enable(&mut self) { 293 blocking_delay_us(1);
239 T::regs().isr().write(|w| w.set_adrdy(true)); 294
240 T::regs().cr().modify(|w| w.set_aden(true)); 295 T::enable();
241 while !T::regs().isr().read().adrdy() {}
242 T::regs().isr().write(|w| w.set_adrdy(true));
243 }
244 296
245 fn configure(&mut self) {
246 // single conversion mode, software trigger 297 // single conversion mode, software trigger
247 T::regs().cfgr().modify(|w| { 298 T::regs().cfgr().modify(|w| {
248 w.set_cont(false); 299 w.set_cont(false);
249 w.set_exten(Exten::DISABLED); 300 w.set_exten(Exten::DISABLED);
250 }); 301 });
302
303 Self { adc }
251 } 304 }
252 305
253 /// Enable reading the voltage reference internal channel. 306 /// Enable reading the voltage reference internal channel.
@@ -276,228 +329,4 @@ impl<'d, T: Instance> Adc<'d, T> {
276 329
277 Vbat {} 330 Vbat {}
278 } 331 }
279
280 /// Set the ADC sample time.
281 pub fn set_sample_time(&mut self, sample_time: SampleTime) {
282 self.sample_time = sample_time;
283 }
284
285 /// Get the ADC sample time.
286 pub fn sample_time(&self) -> SampleTime {
287 self.sample_time
288 }
289
290 /// Set the ADC resolution.
291 pub fn set_resolution(&mut self, resolution: Resolution) {
292 T::regs().cfgr().modify(|reg| reg.set_res(resolution.into()));
293 }
294
295 /// Set hardware averaging.
296 pub fn set_averaging(&mut self, averaging: Averaging) {
297 let (enable, samples, right_shift) = match averaging {
298 Averaging::Disabled => (false, 0, 0),
299 Averaging::Samples2 => (true, 1, 1),
300 Averaging::Samples4 => (true, 3, 2),
301 Averaging::Samples8 => (true, 7, 3),
302 Averaging::Samples16 => (true, 15, 4),
303 Averaging::Samples32 => (true, 31, 5),
304 Averaging::Samples64 => (true, 63, 6),
305 Averaging::Samples128 => (true, 127, 7),
306 Averaging::Samples256 => (true, 255, 8),
307 Averaging::Samples512 => (true, 511, 9),
308 Averaging::Samples1024 => (true, 1023, 10),
309 };
310
311 T::regs().cfgr2().modify(|reg| {
312 reg.set_rovse(enable);
313 reg.set_ovsr(samples);
314 reg.set_ovss(right_shift);
315 })
316 }
317
318 /// Perform a single conversion.
319 fn convert(&mut self) -> u16 {
320 T::regs().isr().modify(|reg| {
321 reg.set_eos(true);
322 reg.set_eoc(true);
323 });
324
325 // Start conversion
326 T::regs().cr().modify(|reg| {
327 reg.set_adstart(true);
328 });
329
330 while !T::regs().isr().read().eos() {
331 // spin
332 }
333
334 T::regs().dr().read().0 as u16
335 }
336
337 /// Read an ADC channel.
338 pub fn blocking_read(&mut self, channel: &mut impl AdcChannel<T>) -> u16 {
339 self.read_channel(channel)
340 }
341
342 /// Read one or multiple ADC channels using DMA.
343 ///
344 /// `sequence` iterator and `readings` must have the same length.
345 ///
346 /// Example
347 /// ```rust,ignore
348 /// use embassy_stm32::adc::{Adc, AdcChannel}
349 ///
350 /// let mut adc = Adc::new(p.ADC1);
351 /// let mut adc_pin0 = p.PA0.into();
352 /// let mut adc_pin2 = p.PA2.into();
353 /// let mut measurements = [0u16; 2];
354 ///
355 /// adc.read(
356 /// p.DMA2_CH0.reborrow(),
357 /// [
358 /// (&mut *adc_pin0, SampleTime::CYCLES112),
359 /// (&mut *adc_pin2, SampleTime::CYCLES112),
360 /// ]
361 /// .into_iter(),
362 /// &mut measurements,
363 /// )
364 /// .await;
365 /// defmt::info!("measurements: {}", measurements);
366 /// ```
367 pub async fn read(
368 &mut self,
369 rx_dma: Peri<'_, impl RxDma<T>>,
370 sequence: impl ExactSizeIterator<Item = (&mut AnyAdcChannel<T>, SampleTime)>,
371 readings: &mut [u16],
372 ) {
373 assert!(sequence.len() != 0, "Asynchronous read sequence cannot be empty");
374 assert!(
375 sequence.len() == readings.len(),
376 "Sequence length must be equal to readings length"
377 );
378 assert!(
379 sequence.len() <= 16,
380 "Asynchronous read sequence cannot be more than 16 in length"
381 );
382
383 // Ensure no conversions are ongoing
384 Self::cancel_conversions();
385
386 // Set sequence length
387 T::regs().sqr1().modify(|w| {
388 w.set_l(sequence.len() as u8 - 1);
389 });
390
391 // Configure channels and ranks
392 for (i, (channel, sample_time)) in sequence.enumerate() {
393 Self::configure_channel(channel, sample_time);
394 match i {
395 0..=3 => {
396 T::regs().sqr1().modify(|w| {
397 w.set_sq(i, channel.channel());
398 });
399 }
400 4..=8 => {
401 T::regs().sqr2().modify(|w| {
402 w.set_sq(i - 4, channel.channel());
403 });
404 }
405 9..=13 => {
406 T::regs().sqr3().modify(|w| {
407 w.set_sq(i - 9, channel.channel());
408 });
409 }
410 14..=15 => {
411 T::regs().sqr4().modify(|w| {
412 w.set_sq(i - 14, channel.channel());
413 });
414 }
415 _ => unreachable!(),
416 }
417 }
418
419 // Set continuous mode with oneshot dma.
420 // Clear overrun flag before starting transfer.
421
422 T::regs().isr().modify(|reg| {
423 reg.set_ovr(true);
424 });
425 T::regs().cfgr().modify(|reg| {
426 reg.set_cont(true);
427 reg.set_dmngt(Dmngt::DMA_ONE_SHOT);
428 });
429
430 let request = rx_dma.request();
431 let transfer = unsafe {
432 Transfer::new_read(
433 rx_dma,
434 request,
435 T::regs().dr().as_ptr() as *mut u16,
436 readings,
437 Default::default(),
438 )
439 };
440
441 // Start conversion
442 T::regs().cr().modify(|reg| {
443 reg.set_adstart(true);
444 });
445
446 // Wait for conversion sequence to finish.
447 transfer.await;
448
449 // Ensure conversions are finished.
450 Self::cancel_conversions();
451
452 // Reset configuration.
453 T::regs().cfgr().modify(|reg| {
454 reg.set_cont(false);
455 reg.set_dmngt(Dmngt::from_bits(0));
456 });
457 }
458
459 fn configure_channel(channel: &mut impl AdcChannel<T>, sample_time: SampleTime) {
460 channel.setup();
461
462 let channel = channel.channel();
463
464 Self::set_channel_sample_time(channel, sample_time);
465
466 #[cfg(any(stm32h7, stm32u5))]
467 {
468 T::regs().cfgr2().modify(|w| w.set_lshift(0));
469 T::regs()
470 .pcsel()
471 .modify(|w| w.set_pcsel(channel as _, Pcsel::PRESELECTED));
472 }
473 }
474
475 fn read_channel(&mut self, channel: &mut impl AdcChannel<T>) -> u16 {
476 Self::configure_channel(channel, self.sample_time);
477
478 T::regs().sqr1().modify(|reg| {
479 reg.set_sq(0, channel.channel());
480 reg.set_l(0);
481 });
482
483 self.convert()
484 }
485
486 fn set_channel_sample_time(ch: u8, sample_time: SampleTime) {
487 let sample_time = sample_time.into();
488 if ch <= 9 {
489 T::regs().smpr(0).modify(|reg| reg.set_smp(ch as _, sample_time));
490 } else {
491 T::regs().smpr(1).modify(|reg| reg.set_smp((ch - 10) as _, sample_time));
492 }
493 }
494
495 fn cancel_conversions() {
496 if T::regs().cr().read().adstart() && !T::regs().cr().read().addis() {
497 T::regs().cr().modify(|reg| {
498 reg.set_adstp(Adstp::STOP);
499 });
500 while T::regs().cr().read().adstart() {}
501 }
502 }
503} 332}
diff --git a/embassy-stm32/src/adc/watchdog_v1.rs b/embassy-stm32/src/adc/watchdog_v1.rs
index bbe8e1971..b12e0d333 100644
--- a/embassy-stm32/src/adc/watchdog_v1.rs
+++ b/embassy-stm32/src/adc/watchdog_v1.rs
@@ -1,7 +1,7 @@
1use core::future::poll_fn; 1use core::future::poll_fn;
2use core::task::Poll; 2use core::task::Poll;
3 3
4use stm32_metapac::adc::vals::{Align, Awdsgl, Res}; 4use stm32_metapac::adc::vals::{Align, Awdsgl, Res, SampleTime};
5 5
6use crate::adc::{Adc, AdcChannel, Instance}; 6use crate::adc::{Adc, AdcChannel, Instance};
7 7
@@ -67,7 +67,7 @@ impl<'d, T: Instance> Adc<'d, T> {
67 /// let v_high = adc.monitor_watchdog().await; 67 /// let v_high = adc.monitor_watchdog().await;
68 /// info!("ADC sample is high {}", v_high); 68 /// info!("ADC sample is high {}", v_high);
69 /// ``` 69 /// ```
70 pub async fn monitor_watchdog(&mut self) -> u16 { 70 pub async fn monitor_watchdog(&mut self, sample_time: SampleTime) -> u16 {
71 assert!( 71 assert!(
72 match T::regs().cfgr1().read().awdsgl() { 72 match T::regs().cfgr1().read().awdsgl() {
73 Awdsgl::SINGLE_CHANNEL => T::regs().cfgr1().read().awdch() != 0, 73 Awdsgl::SINGLE_CHANNEL => T::regs().cfgr1().read().awdch() != 0,
@@ -76,7 +76,7 @@ impl<'d, T: Instance> Adc<'d, T> {
76 "`set_channel` should be called before `monitor`", 76 "`set_channel` should be called before `monitor`",
77 ); 77 );
78 assert!(T::regs().chselr().read().0 != 0); 78 assert!(T::regs().chselr().read().0 != 0);
79 T::regs().smpr().modify(|reg| reg.set_smp(self.sample_time.into())); 79 T::regs().smpr().modify(|reg| reg.set_smp(sample_time.into()));
80 Self::start_awd(); 80 Self::start_awd();
81 81
82 let sample = poll_fn(|cx| { 82 let sample = poll_fn(|cx| {
diff --git a/embassy-stm32/src/dma/gpdma/mod.rs b/embassy-stm32/src/dma/gpdma/mod.rs
index 3e117c331..106558d20 100644
--- a/embassy-stm32/src/dma/gpdma/mod.rs
+++ b/embassy-stm32/src/dma/gpdma/mod.rs
@@ -136,6 +136,7 @@ pub(crate) unsafe fn init(cs: critical_section::CriticalSection, irq_priority: c
136 136
137impl AnyChannel { 137impl AnyChannel {
138 /// Safety: Must be called with a matching set of parameters for a valid dma channel 138 /// Safety: Must be called with a matching set of parameters for a valid dma channel
139 #[cfg(not(stm32n6))]
139 pub(crate) unsafe fn on_irq(&self) { 140 pub(crate) unsafe fn on_irq(&self) {
140 let info = self.info(); 141 let info = self.info();
141 #[cfg(feature = "_dual-core")] 142 #[cfg(feature = "_dual-core")]
diff --git a/embassy-stm32/src/dma/mod.rs b/embassy-stm32/src/dma/mod.rs
index 297fa3674..de7a2c175 100644
--- a/embassy-stm32/src/dma/mod.rs
+++ b/embassy-stm32/src/dma/mod.rs
@@ -46,9 +46,11 @@ pub type Request = u8;
46pub type Request = (); 46pub type Request = ();
47 47
48pub(crate) trait SealedChannel { 48pub(crate) trait SealedChannel {
49 #[cfg(not(stm32n6))]
49 fn id(&self) -> u8; 50 fn id(&self) -> u8;
50} 51}
51 52
53#[cfg(not(stm32n6))]
52pub(crate) trait ChannelInterrupt { 54pub(crate) trait ChannelInterrupt {
53 #[cfg_attr(not(feature = "rt"), allow(unused))] 55 #[cfg_attr(not(feature = "rt"), allow(unused))]
54 unsafe fn on_irq(); 56 unsafe fn on_irq();
@@ -58,6 +60,7 @@ pub(crate) trait ChannelInterrupt {
58#[allow(private_bounds)] 60#[allow(private_bounds)]
59pub trait Channel: SealedChannel + PeripheralType + Into<AnyChannel> + 'static {} 61pub trait Channel: SealedChannel + PeripheralType + Into<AnyChannel> + 'static {}
60 62
63#[cfg(not(stm32n6))]
61macro_rules! dma_channel_impl { 64macro_rules! dma_channel_impl {
62 ($channel_peri:ident, $index:expr) => { 65 ($channel_peri:ident, $index:expr) => {
63 impl crate::dma::SealedChannel for crate::peripherals::$channel_peri { 66 impl crate::dma::SealedChannel for crate::peripherals::$channel_peri {
@@ -96,6 +99,7 @@ impl AnyChannel {
96} 99}
97 100
98impl SealedChannel for AnyChannel { 101impl SealedChannel for AnyChannel {
102 #[cfg(not(stm32n6))]
99 fn id(&self) -> u8 { 103 fn id(&self) -> u8 {
100 self.id 104 self.id
101 } 105 }
diff --git a/embassy-stm32/src/dsihost.rs b/embassy-stm32/src/dsihost.rs
index 59a2cbcdb..b8945820c 100644
--- a/embassy-stm32/src/dsihost.rs
+++ b/embassy-stm32/src/dsihost.rs
@@ -5,18 +5,11 @@ use core::marker::PhantomData;
5use embassy_hal_internal::PeripheralType; 5use embassy_hal_internal::PeripheralType;
6 6
7//use crate::gpio::{AnyPin, SealedPin}; 7//use crate::gpio::{AnyPin, SealedPin};
8use crate::block_for_us;
8use crate::gpio::{AfType, AnyPin, OutputType, Speed}; 9use crate::gpio::{AfType, AnyPin, OutputType, Speed};
9use crate::rcc::{self, RccPeripheral}; 10use crate::rcc::{self, RccPeripheral};
10use crate::{Peri, peripherals}; 11use crate::{Peri, peripherals};
11 12
12/// Performs a busy-wait delay for a specified number of microseconds.
13pub fn blocking_delay_ms(ms: u32) {
14 #[cfg(feature = "time")]
15 embassy_time::block_for(embassy_time::Duration::from_millis(ms as u64));
16 #[cfg(not(feature = "time"))]
17 cortex_m::asm::delay(unsafe { crate::rcc::get_freqs() }.sys.to_hertz().unwrap().0 / 1_000 * ms);
18}
19
20/// PacketTypes extracted from CubeMX 13/// PacketTypes extracted from CubeMX
21#[repr(u8)] 14#[repr(u8)]
22#[allow(dead_code)] 15#[allow(dead_code)]
@@ -334,7 +327,7 @@ impl<'d, T: Instance> DsiHost<'d, T> {
334 if T::regs().gpsr().read().cmdfe() { 327 if T::regs().gpsr().read().cmdfe() {
335 return Ok(()); 328 return Ok(());
336 } 329 }
337 blocking_delay_ms(1); 330 block_for_us(1_000);
338 } 331 }
339 Err(Error::FifoTimeout) 332 Err(Error::FifoTimeout)
340 } 333 }
@@ -345,7 +338,7 @@ impl<'d, T: Instance> DsiHost<'d, T> {
345 if !T::regs().gpsr().read().cmdff() { 338 if !T::regs().gpsr().read().cmdff() {
346 return Ok(()); 339 return Ok(());
347 } 340 }
348 blocking_delay_ms(1); 341 block_for_us(1_000);
349 } 342 }
350 Err(Error::FifoTimeout) 343 Err(Error::FifoTimeout)
351 } 344 }
@@ -356,7 +349,7 @@ impl<'d, T: Instance> DsiHost<'d, T> {
356 if !self.read_busy() { 349 if !self.read_busy() {
357 return Ok(()); 350 return Ok(());
358 } 351 }
359 blocking_delay_ms(1); 352 block_for_us(1_000);
360 } 353 }
361 Err(Error::ReadTimeout) 354 Err(Error::ReadTimeout)
362 } 355 }
@@ -367,7 +360,7 @@ impl<'d, T: Instance> DsiHost<'d, T> {
367 if !T::regs().gpsr().read().prdfe() { 360 if !T::regs().gpsr().read().prdfe() {
368 return Ok(()); 361 return Ok(());
369 } 362 }
370 blocking_delay_ms(1); 363 block_for_us(1_000);
371 } 364 }
372 Err(Error::FifoTimeout) 365 Err(Error::FifoTimeout)
373 } 366 }
diff --git a/embassy-stm32/src/dts/tsel.rs b/embassy-stm32/src/dts/tsel.rs
index 99eab6dd8..79c697c8d 100644
--- a/embassy-stm32/src/dts/tsel.rs
+++ b/embassy-stm32/src/dts/tsel.rs
@@ -49,3 +49,20 @@ pub enum TriggerSel {
49 /// EXTI13 49 /// EXTI13
50 Exti13 = 4, 50 Exti13 = 4,
51} 51}
52
53/// Trigger selection for N6
54#[cfg(stm32n6)]
55#[derive(Debug, Copy, Clone, Eq, PartialEq)]
56#[cfg_attr(feature = "defmt", derive(defmt::Format))]
57pub enum TriggerSel {
58 /// Software triggering. Performs continuous measurements.
59 Software = 0,
60 /// LPTIM4 OUT
61 Lptim4 = 1,
62 /// LPTIM2 CH1
63 Lptim2 = 2,
64 /// LPTIM3 CH1
65 Lptim3 = 3,
66 /// EXTI13
67 Exti13 = 4,
68}
diff --git a/embassy-stm32/src/eth/generic_phy.rs b/embassy-stm32/src/eth/generic_phy.rs
index 774beef80..947874d7f 100644
--- a/embassy-stm32/src/eth/generic_phy.rs
+++ b/embassy-stm32/src/eth/generic_phy.rs
@@ -8,6 +8,7 @@ use embassy_time::{Duration, Timer};
8use futures_util::FutureExt; 8use futures_util::FutureExt;
9 9
10use super::{Phy, StationManagement}; 10use super::{Phy, StationManagement};
11use crate::block_for_us as blocking_delay_us;
11 12
12#[allow(dead_code)] 13#[allow(dead_code)]
13mod phy_consts { 14mod phy_consts {
@@ -76,19 +77,6 @@ impl GenericPhy {
76 } 77 }
77} 78}
78 79
79// TODO: Factor out to shared functionality
80fn blocking_delay_us(us: u32) {
81 #[cfg(feature = "time")]
82 embassy_time::block_for(Duration::from_micros(us as u64));
83 #[cfg(not(feature = "time"))]
84 {
85 let freq = unsafe { crate::rcc::get_freqs() }.sys.to_hertz().unwrap().0 as u64;
86 let us = us as u64;
87 let cycles = freq * us / 1_000_000;
88 cortex_m::asm::delay(cycles as u32);
89 }
90}
91
92impl Phy for GenericPhy { 80impl Phy for GenericPhy {
93 fn phy_reset<S: StationManagement>(&mut self, sm: &mut S) { 81 fn phy_reset<S: StationManagement>(&mut self, sm: &mut S) {
94 // Detect SMI address 82 // Detect SMI address
diff --git a/embassy-stm32/src/exti.rs b/embassy-stm32/src/exti.rs
index 2f5c3406a..cb46d362c 100644
--- a/embassy-stm32/src/exti.rs
+++ b/embassy-stm32/src/exti.rs
@@ -8,7 +8,7 @@ use core::task::{Context, Poll};
8use embassy_hal_internal::{PeripheralType, impl_peripheral}; 8use embassy_hal_internal::{PeripheralType, impl_peripheral};
9use embassy_sync::waitqueue::AtomicWaker; 9use embassy_sync::waitqueue::AtomicWaker;
10 10
11use crate::gpio::{AnyPin, Input, Level, Pin as GpioPin, Pull}; 11use crate::gpio::{AnyPin, Input, Level, Pin as GpioPin, PinNumber, Pull};
12use crate::pac::EXTI; 12use crate::pac::EXTI;
13use crate::pac::exti::regs::Lines; 13use crate::pac::exti::regs::Lines;
14use crate::{Peri, interrupt, pac, peripherals}; 14use crate::{Peri, interrupt, pac, peripherals};
@@ -31,11 +31,11 @@ fn cpu_regs() -> pac::exti::Exti {
31 EXTI 31 EXTI
32} 32}
33 33
34#[cfg(not(any(exti_c0, exti_g0, exti_u0, exti_l5, gpio_v1, exti_u5, exti_h5, exti_h50)))] 34#[cfg(not(any(exti_c0, exti_g0, exti_u0, exti_l5, gpio_v1, exti_u5, exti_h5, exti_h50, exti_n6)))]
35fn exticr_regs() -> pac::syscfg::Syscfg { 35fn exticr_regs() -> pac::syscfg::Syscfg {
36 pac::SYSCFG 36 pac::SYSCFG
37} 37}
38#[cfg(any(exti_c0, exti_g0, exti_u0, exti_l5, exti_u5, exti_h5, exti_h50))] 38#[cfg(any(exti_c0, exti_g0, exti_u0, exti_l5, exti_u5, exti_h5, exti_h50, exti_n6))]
39fn exticr_regs() -> pac::exti::Exti { 39fn exticr_regs() -> pac::exti::Exti {
40 EXTI 40 EXTI
41} 41}
@@ -45,9 +45,9 @@ fn exticr_regs() -> pac::afio::Afio {
45} 45}
46 46
47unsafe fn on_irq() { 47unsafe fn on_irq() {
48 #[cfg(not(any(exti_c0, exti_g0, exti_u0, exti_l5, exti_u5, exti_h5, exti_h50)))] 48 #[cfg(not(any(exti_c0, exti_g0, exti_u0, exti_l5, exti_u5, exti_h5, exti_h50, exti_n6)))]
49 let bits = EXTI.pr(0).read().0; 49 let bits = EXTI.pr(0).read().0;
50 #[cfg(any(exti_c0, exti_g0, exti_u0, exti_l5, exti_u5, exti_h5, exti_h50))] 50 #[cfg(any(exti_c0, exti_g0, exti_u0, exti_l5, exti_u5, exti_h5, exti_h50, exti_n6))]
51 let bits = EXTI.rpr(0).read().0 | EXTI.fpr(0).read().0; 51 let bits = EXTI.rpr(0).read().0 | EXTI.fpr(0).read().0;
52 52
53 // We don't handle or change any EXTI lines above 16. 53 // We don't handle or change any EXTI lines above 16.
@@ -62,9 +62,9 @@ unsafe fn on_irq() {
62 } 62 }
63 63
64 // Clear pending 64 // Clear pending
65 #[cfg(not(any(exti_c0, exti_g0, exti_u0, exti_l5, exti_u5, exti_h5, exti_h50)))] 65 #[cfg(not(any(exti_c0, exti_g0, exti_u0, exti_l5, exti_u5, exti_h5, exti_h50, exti_n6)))]
66 EXTI.pr(0).write_value(Lines(bits)); 66 EXTI.pr(0).write_value(Lines(bits));
67 #[cfg(any(exti_c0, exti_g0, exti_u0, exti_l5, exti_u5, exti_h5, exti_h50))] 67 #[cfg(any(exti_c0, exti_g0, exti_u0, exti_l5, exti_u5, exti_h5, exti_h50, exti_n6))]
68 { 68 {
69 EXTI.rpr(0).write_value(Lines(bits)); 69 EXTI.rpr(0).write_value(Lines(bits));
70 EXTI.fpr(0).write_value(Lines(bits)); 70 EXTI.fpr(0).write_value(Lines(bits));
@@ -226,12 +226,12 @@ impl<'d> embedded_hal_async::digital::Wait for ExtiInput<'d> {
226 226
227#[must_use = "futures do nothing unless you `.await` or poll them"] 227#[must_use = "futures do nothing unless you `.await` or poll them"]
228struct ExtiInputFuture<'a> { 228struct ExtiInputFuture<'a> {
229 pin: u8, 229 pin: PinNumber,
230 phantom: PhantomData<&'a mut AnyPin>, 230 phantom: PhantomData<&'a mut AnyPin>,
231} 231}
232 232
233impl<'a> ExtiInputFuture<'a> { 233impl<'a> ExtiInputFuture<'a> {
234 fn new(pin: u8, port: u8, rising: bool, falling: bool) -> Self { 234 fn new(pin: PinNumber, port: PinNumber, rising: bool, falling: bool) -> Self {
235 critical_section::with(|_| { 235 critical_section::with(|_| {
236 let pin = pin as usize; 236 let pin = pin as usize;
237 exticr_regs().exticr(pin / 4).modify(|w| w.set_exti(pin % 4, port)); 237 exticr_regs().exticr(pin / 4).modify(|w| w.set_exti(pin % 4, port));
@@ -239,9 +239,9 @@ impl<'a> ExtiInputFuture<'a> {
239 EXTI.ftsr(0).modify(|w| w.set_line(pin, falling)); 239 EXTI.ftsr(0).modify(|w| w.set_line(pin, falling));
240 240
241 // clear pending bit 241 // clear pending bit
242 #[cfg(not(any(exti_c0, exti_g0, exti_u0, exti_l5, exti_u5, exti_h5, exti_h50)))] 242 #[cfg(not(any(exti_c0, exti_g0, exti_u0, exti_l5, exti_u5, exti_h5, exti_h50, exti_n6)))]
243 EXTI.pr(0).write(|w| w.set_line(pin, true)); 243 EXTI.pr(0).write(|w| w.set_line(pin, true));
244 #[cfg(any(exti_c0, exti_g0, exti_u0, exti_l5, exti_u5, exti_h5, exti_h50))] 244 #[cfg(any(exti_c0, exti_g0, exti_u0, exti_l5, exti_u5, exti_h5, exti_h50, exti_n6))]
245 { 245 {
246 EXTI.rpr(0).write(|w| w.set_line(pin, true)); 246 EXTI.rpr(0).write(|w| w.set_line(pin, true));
247 EXTI.fpr(0).write(|w| w.set_line(pin, true)); 247 EXTI.fpr(0).write(|w| w.set_line(pin, true));
@@ -334,20 +334,20 @@ trait SealedChannel {}
334#[allow(private_bounds)] 334#[allow(private_bounds)]
335pub trait Channel: PeripheralType + SealedChannel + Sized { 335pub trait Channel: PeripheralType + SealedChannel + Sized {
336 /// Get the EXTI channel number. 336 /// Get the EXTI channel number.
337 fn number(&self) -> u8; 337 fn number(&self) -> PinNumber;
338} 338}
339 339
340/// Type-erased EXTI channel. 340/// Type-erased EXTI channel.
341/// 341///
342/// This represents ownership over any EXTI channel, known at runtime. 342/// This represents ownership over any EXTI channel, known at runtime.
343pub struct AnyChannel { 343pub struct AnyChannel {
344 number: u8, 344 number: PinNumber,
345} 345}
346 346
347impl_peripheral!(AnyChannel); 347impl_peripheral!(AnyChannel);
348impl SealedChannel for AnyChannel {} 348impl SealedChannel for AnyChannel {}
349impl Channel for AnyChannel { 349impl Channel for AnyChannel {
350 fn number(&self) -> u8 { 350 fn number(&self) -> PinNumber {
351 self.number 351 self.number
352 } 352 }
353} 353}
@@ -356,7 +356,7 @@ macro_rules! impl_exti {
356 ($type:ident, $number:expr) => { 356 ($type:ident, $number:expr) => {
357 impl SealedChannel for peripherals::$type {} 357 impl SealedChannel for peripherals::$type {}
358 impl Channel for peripherals::$type { 358 impl Channel for peripherals::$type {
359 fn number(&self) -> u8 { 359 fn number(&self) -> PinNumber {
360 $number 360 $number
361 } 361 }
362 } 362 }
@@ -364,7 +364,7 @@ macro_rules! impl_exti {
364 impl From<peripherals::$type> for AnyChannel { 364 impl From<peripherals::$type> for AnyChannel {
365 fn from(val: peripherals::$type) -> Self { 365 fn from(val: peripherals::$type) -> Self {
366 Self { 366 Self {
367 number: val.number() as u8, 367 number: val.number() as PinNumber,
368 } 368 }
369 } 369 }
370 } 370 }
diff --git a/embassy-stm32/src/flash/c.rs b/embassy-stm32/src/flash/c.rs
new file mode 100644
index 000000000..0ad1002b0
--- /dev/null
+++ b/embassy-stm32/src/flash/c.rs
@@ -0,0 +1,131 @@
1use core::ptr::write_volatile;
2use core::sync::atomic::{Ordering, fence};
3
4use cortex_m::interrupt;
5
6use super::{FlashSector, WRITE_SIZE};
7use crate::flash::Error;
8use crate::pac;
9
10pub(crate) unsafe fn lock() {
11 pac::FLASH.cr().modify(|w| w.set_lock(true));
12}
13pub(crate) unsafe fn unlock() {
14 // Wait, while the memory interface is busy.
15 wait_busy();
16
17 // Unlock flash
18 if pac::FLASH.cr().read().lock() {
19 pac::FLASH.keyr().write_value(0x4567_0123);
20 pac::FLASH.keyr().write_value(0xCDEF_89AB);
21 }
22}
23
24pub(crate) unsafe fn enable_blocking_write() {
25 assert_eq!(0, WRITE_SIZE % 4);
26 pac::FLASH.cr().write(|w| w.set_pg(true));
27}
28
29pub(crate) unsafe fn disable_blocking_write() {
30 pac::FLASH.cr().write(|w| w.set_pg(false));
31}
32
33pub(crate) unsafe fn blocking_write(start_address: u32, buf: &[u8; WRITE_SIZE]) -> Result<(), Error> {
34 let mut address = start_address;
35 for val in buf.chunks(4) {
36 write_volatile(address as *mut u32, u32::from_le_bytes(unwrap!(val.try_into())));
37 address += val.len() as u32;
38
39 // prevents parallelism errors
40 fence(Ordering::SeqCst);
41 }
42
43 wait_ready_blocking()
44}
45
46pub(crate) unsafe fn blocking_erase_sector(sector: &FlashSector) -> Result<(), Error> {
47 let idx = (sector.start - super::FLASH_BASE as u32) / super::BANK1_REGION.erase_size as u32;
48
49 #[cfg(feature = "defmt")]
50 defmt::trace!(
51 "STM32C0 Erase: addr=0x{:08x}, idx={}, erase_size={}",
52 sector.start,
53 idx,
54 super::BANK1_REGION.erase_size
55 );
56
57 wait_busy();
58 clear_all_err();
59
60 // Explicitly unlock before erase
61 unlock();
62
63 interrupt::free(|_| {
64 #[cfg(feature = "defmt")]
65 {
66 let cr_before = pac::FLASH.cr().read();
67 defmt::trace!("FLASH_CR before: 0x{:08x}", cr_before.0);
68 }
69
70 pac::FLASH.cr().modify(|w| {
71 w.set_per(true);
72 w.set_pnb(idx as u8);
73 w.set_strt(true);
74 });
75
76 #[cfg(feature = "defmt")]
77 {
78 let cr_after = pac::FLASH.cr().read();
79 defmt::trace!(
80 "FLASH_CR after: 0x{:08x}, PER={}, PNB={}, STRT={}",
81 cr_after.0,
82 cr_after.per(),
83 cr_after.pnb(),
84 cr_after.strt()
85 );
86 }
87 });
88
89 let ret: Result<(), Error> = wait_ready_blocking();
90
91 // Clear erase bit
92 pac::FLASH.cr().modify(|w| w.set_per(false));
93
94 // Explicitly lock after erase
95 lock();
96
97 // Extra wait to ensure operation completes
98 wait_busy();
99
100 ret
101}
102
103pub(crate) unsafe fn wait_ready_blocking() -> Result<(), Error> {
104 while pac::FLASH.sr().read().bsy() {}
105
106 let sr = pac::FLASH.sr().read();
107
108 if sr.progerr() {
109 return Err(Error::Prog);
110 }
111
112 if sr.wrperr() {
113 return Err(Error::Protected);
114 }
115
116 if sr.pgaerr() {
117 return Err(Error::Unaligned);
118 }
119
120 Ok(())
121}
122
123pub(crate) unsafe fn clear_all_err() {
124 // read and write back the same value.
125 // This clears all "write 1 to clear" bits.
126 pac::FLASH.sr().modify(|_| {});
127}
128
129fn wait_busy() {
130 while pac::FLASH.sr().read().bsy() {}
131}
diff --git a/embassy-stm32/src/flash/common.rs b/embassy-stm32/src/flash/common.rs
index b595938a6..60d00e766 100644
--- a/embassy-stm32/src/flash/common.rs
+++ b/embassy-stm32/src/flash/common.rs
@@ -102,7 +102,13 @@ pub(super) unsafe fn blocking_write(
102 } 102 }
103 103
104 let mut address = base + offset; 104 let mut address = base + offset;
105 trace!("Writing {} bytes at 0x{:x}", bytes.len(), address); 105 trace!(
106 "Writing {} bytes at 0x{:x} (base=0x{:x}, offset=0x{:x})",
107 bytes.len(),
108 address,
109 base,
110 offset
111 );
106 112
107 for chunk in bytes.chunks(WRITE_SIZE) { 113 for chunk in bytes.chunks(WRITE_SIZE) {
108 write_chunk(address, chunk)?; 114 write_chunk(address, chunk)?;
diff --git a/embassy-stm32/src/flash/g.rs b/embassy-stm32/src/flash/g.rs
index d026541a4..d7ba2f571 100644
--- a/embassy-stm32/src/flash/g.rs
+++ b/embassy-stm32/src/flash/g.rs
@@ -44,7 +44,6 @@ pub(crate) unsafe fn blocking_write(start_address: u32, buf: &[u8; WRITE_SIZE])
44} 44}
45 45
46pub(crate) unsafe fn blocking_erase_sector(sector: &FlashSector) -> Result<(), Error> { 46pub(crate) unsafe fn blocking_erase_sector(sector: &FlashSector) -> Result<(), Error> {
47 let idx = (sector.start - super::FLASH_BASE as u32) / super::BANK1_REGION.erase_size as u32;
48 wait_busy(); 47 wait_busy();
49 clear_all_err(); 48 clear_all_err();
50 49
@@ -54,9 +53,9 @@ pub(crate) unsafe fn blocking_erase_sector(sector: &FlashSector) -> Result<(), E
54 #[cfg(any(flash_g0x0, flash_g0x1, flash_g4c3))] 53 #[cfg(any(flash_g0x0, flash_g0x1, flash_g4c3))]
55 w.set_bker(sector.bank == crate::flash::FlashBank::Bank2); 54 w.set_bker(sector.bank == crate::flash::FlashBank::Bank2);
56 #[cfg(flash_g0x0)] 55 #[cfg(flash_g0x0)]
57 w.set_pnb(idx as u16); 56 w.set_pnb(sector.index_in_bank as u16);
58 #[cfg(not(flash_g0x0))] 57 #[cfg(not(flash_g0x0))]
59 w.set_pnb(idx as u8); 58 w.set_pnb(sector.index_in_bank as u8);
60 w.set_strt(true); 59 w.set_strt(true);
61 }); 60 });
62 }); 61 });
diff --git a/embassy-stm32/src/flash/mod.rs b/embassy-stm32/src/flash/mod.rs
index 3e74d857a..39cd9b3a9 100644
--- a/embassy-stm32/src/flash/mod.rs
+++ b/embassy-stm32/src/flash/mod.rs
@@ -99,6 +99,7 @@ compile_error!("The 'eeprom' cfg is enabled for a non-L0/L1 chip family. This is
99#[cfg_attr(flash_f4, path = "f4.rs")] 99#[cfg_attr(flash_f4, path = "f4.rs")]
100#[cfg_attr(flash_f7, path = "f7.rs")] 100#[cfg_attr(flash_f7, path = "f7.rs")]
101#[cfg_attr(any(flash_g0x0, flash_g0x1, flash_g4c2, flash_g4c3, flash_g4c4), path = "g.rs")] 101#[cfg_attr(any(flash_g0x0, flash_g0x1, flash_g4c2, flash_g4c3, flash_g4c4), path = "g.rs")]
102#[cfg_attr(flash_c0, path = "c.rs")]
102#[cfg_attr(flash_h7, path = "h7.rs")] 103#[cfg_attr(flash_h7, path = "h7.rs")]
103#[cfg_attr(flash_h7ab, path = "h7.rs")] 104#[cfg_attr(flash_h7ab, path = "h7.rs")]
104#[cfg_attr(any(flash_u5, flash_wba), path = "u5.rs")] 105#[cfg_attr(any(flash_u5, flash_wba), path = "u5.rs")]
@@ -108,7 +109,7 @@ compile_error!("The 'eeprom' cfg is enabled for a non-L0/L1 chip family. This is
108#[cfg_attr( 109#[cfg_attr(
109 not(any( 110 not(any(
110 flash_l0, flash_l1, flash_l4, flash_l5, flash_wl, flash_wb, flash_f0, flash_f1, flash_f2, flash_f3, flash_f4, 111 flash_l0, flash_l1, flash_l4, flash_l5, flash_wl, flash_wb, flash_f0, flash_f1, flash_f2, flash_f3, flash_f4,
111 flash_f7, flash_g0x0, flash_g0x1, flash_g4c2, flash_g4c3, flash_g4c4, flash_h7, flash_h7ab, flash_u5, 112 flash_f7, flash_g0x0, flash_g0x1, flash_g4c2, flash_g4c3, flash_g4c4, flash_c0, flash_h7, flash_h7ab, flash_u5,
112 flash_wba, flash_h50, flash_u0, flash_h5, 113 flash_wba, flash_h50, flash_u0, flash_h5,
113 )), 114 )),
114 path = "other.rs" 115 path = "other.rs"
diff --git a/embassy-stm32/src/gpio.rs b/embassy-stm32/src/gpio.rs
index b55baffdc..17c5a9962 100644
--- a/embassy-stm32/src/gpio.rs
+++ b/embassy-stm32/src/gpio.rs
@@ -592,7 +592,7 @@ impl AfType {
592 592
593#[inline(never)] 593#[inline(never)]
594#[cfg(gpio_v1)] 594#[cfg(gpio_v1)]
595fn set_as_af(pin_port: u8, af_type: AfType) { 595fn set_as_af(pin_port: PinNumber, af_type: AfType) {
596 let pin = unsafe { AnyPin::steal(pin_port) }; 596 let pin = unsafe { AnyPin::steal(pin_port) };
597 let r = pin.block(); 597 let r = pin.block();
598 let n = pin._pin() as usize; 598 let n = pin._pin() as usize;
@@ -649,7 +649,7 @@ impl AfType {
649 649
650#[inline(never)] 650#[inline(never)]
651#[cfg(gpio_v2)] 651#[cfg(gpio_v2)]
652fn set_as_af(pin_port: u8, af_num: u8, af_type: AfType) { 652fn set_as_af(pin_port: PinNumber, af_num: u8, af_type: AfType) {
653 let pin = unsafe { AnyPin::steal(pin_port) }; 653 let pin = unsafe { AnyPin::steal(pin_port) };
654 let r = pin.block(); 654 let r = pin.block();
655 let n = pin._pin() as usize; 655 let n = pin._pin() as usize;
@@ -663,7 +663,7 @@ fn set_as_af(pin_port: u8, af_num: u8, af_type: AfType) {
663 663
664#[inline(never)] 664#[inline(never)]
665#[cfg(gpio_v2)] 665#[cfg(gpio_v2)]
666fn set_speed(pin_port: u8, speed: Speed) { 666fn set_speed(pin_port: PinNumber, speed: Speed) {
667 let pin = unsafe { AnyPin::steal(pin_port) }; 667 let pin = unsafe { AnyPin::steal(pin_port) };
668 let r = pin.block(); 668 let r = pin.block();
669 let n = pin._pin() as usize; 669 let n = pin._pin() as usize;
@@ -672,7 +672,7 @@ fn set_speed(pin_port: u8, speed: Speed) {
672} 672}
673 673
674#[inline(never)] 674#[inline(never)]
675fn set_as_analog(pin_port: u8) { 675fn set_as_analog(pin_port: PinNumber) {
676 let pin = unsafe { AnyPin::steal(pin_port) }; 676 let pin = unsafe { AnyPin::steal(pin_port) };
677 let r = pin.block(); 677 let r = pin.block();
678 let n = pin._pin() as usize; 678 let n = pin._pin() as usize;
@@ -688,7 +688,7 @@ fn set_as_analog(pin_port: u8) {
688} 688}
689 689
690#[inline(never)] 690#[inline(never)]
691fn get_pull(pin_port: u8) -> Pull { 691fn get_pull(pin_port: PinNumber) -> Pull {
692 let pin = unsafe { AnyPin::steal(pin_port) }; 692 let pin = unsafe { AnyPin::steal(pin_port) };
693 let r = pin.block(); 693 let r = pin.block();
694 let n = pin._pin() as usize; 694 let n = pin._pin() as usize;
@@ -727,15 +727,15 @@ pub struct AfioRemapBool<const V: bool>;
727pub struct AfioRemapNotApplicable; 727pub struct AfioRemapNotApplicable;
728 728
729pub(crate) trait SealedPin { 729pub(crate) trait SealedPin {
730 fn pin_port(&self) -> u8; 730 fn pin_port(&self) -> PinNumber;
731 731
732 #[inline] 732 #[inline]
733 fn _pin(&self) -> u8 { 733 fn _pin(&self) -> PinNumber {
734 self.pin_port() % 16 734 self.pin_port() % 16
735 } 735 }
736 736
737 #[inline] 737 #[inline]
738 fn _port(&self) -> u8 { 738 fn _port(&self) -> PinNumber {
739 self.pin_port() / 16 739 self.pin_port() / 16
740 } 740 }
741 741
@@ -798,6 +798,20 @@ pub(crate) trait SealedPin {
798 } 798 }
799} 799}
800 800
801/// GPIO pin number type.
802///
803/// Some chips have a total number of ports that exceeds 8, a larger integer
804/// is needed to hold the total pin number `(ports * number)`.
805#[cfg(not(stm32n6))]
806pub type PinNumber = u8;
807
808/// GPIO pin number type.
809///
810/// Some chips have a total number of ports that exceeds 8, a larger integer
811/// is needed to hold the total pin number `(ports * number)`.
812#[cfg(stm32n6)]
813pub type PinNumber = u16;
814
801/// GPIO pin trait. 815/// GPIO pin trait.
802#[allow(private_bounds)] 816#[allow(private_bounds)]
803pub trait Pin: PeripheralType + Into<AnyPin> + SealedPin + Sized + 'static { 817pub trait Pin: PeripheralType + Into<AnyPin> + SealedPin + Sized + 'static {
@@ -809,20 +823,20 @@ pub trait Pin: PeripheralType + Into<AnyPin> + SealedPin + Sized + 'static {
809 823
810 /// Number of the pin within the port (0..31) 824 /// Number of the pin within the port (0..31)
811 #[inline] 825 #[inline]
812 fn pin(&self) -> u8 { 826 fn pin(&self) -> PinNumber {
813 self._pin() 827 self._pin()
814 } 828 }
815 829
816 /// Port of the pin 830 /// Port of the pin
817 #[inline] 831 #[inline]
818 fn port(&self) -> u8 { 832 fn port(&self) -> PinNumber {
819 self._port() 833 self._port()
820 } 834 }
821} 835}
822 836
823/// Type-erased GPIO pin 837/// Type-erased GPIO pin
824pub struct AnyPin { 838pub struct AnyPin {
825 pin_port: u8, 839 pin_port: PinNumber,
826} 840}
827 841
828impl AnyPin { 842impl AnyPin {
@@ -830,12 +844,12 @@ impl AnyPin {
830 /// 844 ///
831 /// `pin_port` is `port_num * 16 + pin_num`, where `port_num` is 0 for port `A`, 1 for port `B`, etc... 845 /// `pin_port` is `port_num * 16 + pin_num`, where `port_num` is 0 for port `A`, 1 for port `B`, etc...
832 #[inline] 846 #[inline]
833 pub unsafe fn steal(pin_port: u8) -> Peri<'static, Self> { 847 pub unsafe fn steal(pin_port: PinNumber) -> Peri<'static, Self> {
834 Peri::new_unchecked(Self { pin_port }) 848 Peri::new_unchecked(Self { pin_port })
835 } 849 }
836 850
837 #[inline] 851 #[inline]
838 fn _port(&self) -> u8 { 852 fn _port(&self) -> PinNumber {
839 self.pin_port / 16 853 self.pin_port / 16
840 } 854 }
841 855
@@ -854,7 +868,7 @@ impl Pin for AnyPin {
854} 868}
855impl SealedPin for AnyPin { 869impl SealedPin for AnyPin {
856 #[inline] 870 #[inline]
857 fn pin_port(&self) -> u8 { 871 fn pin_port(&self) -> PinNumber {
858 self.pin_port 872 self.pin_port
859 } 873 }
860} 874}
@@ -869,7 +883,7 @@ foreach_pin!(
869 } 883 }
870 impl SealedPin for peripherals::$pin_name { 884 impl SealedPin for peripherals::$pin_name {
871 #[inline] 885 #[inline]
872 fn pin_port(&self) -> u8 { 886 fn pin_port(&self) -> PinNumber {
873 $port_num * 16 + $pin_num 887 $port_num * 16 + $pin_num
874 } 888 }
875 } 889 }
diff --git a/embassy-stm32/src/i2c/v2.rs b/embassy-stm32/src/i2c/v2.rs
index 57a7acee7..61e550ad4 100644
--- a/embassy-stm32/src/i2c/v2.rs
+++ b/embassy-stm32/src/i2c/v2.rs
@@ -98,6 +98,27 @@ pub(crate) unsafe fn on_interrupt<T: Instance>() {
98} 98}
99 99
100impl<'d, M: Mode, IM: MasterMode> I2c<'d, M, IM> { 100impl<'d, M: Mode, IM: MasterMode> I2c<'d, M, IM> {
101 #[inline]
102 fn to_reload(reload: bool) -> i2c::vals::Reload {
103 if reload {
104 i2c::vals::Reload::NOT_COMPLETED
105 } else {
106 i2c::vals::Reload::COMPLETED
107 }
108 }
109
110 /// Calculate total bytes in a group of operations
111 #[inline]
112 fn total_operation_bytes(operations: &[Operation<'_>]) -> usize {
113 operations
114 .iter()
115 .map(|op| match op {
116 Operation::Write(buf) => buf.len(),
117 Operation::Read(buf) => buf.len(),
118 })
119 .sum()
120 }
121
101 pub(crate) fn init(&mut self, config: Config) { 122 pub(crate) fn init(&mut self, config: Config) {
102 self.info.regs.cr1().modify(|reg| { 123 self.info.regs.cr1().modify(|reg| {
103 reg.set_pe(false); 124 reg.set_pe(false);
@@ -147,12 +168,6 @@ impl<'d, M: Mode, IM: MasterMode> I2c<'d, M, IM> {
147 // `buffer`. The START bit can be set even if the bus 168 // `buffer`. The START bit can be set even if the bus
148 // is BUSY or I2C is in slave mode. 169 // is BUSY or I2C is in slave mode.
149 170
150 let reload = if reload {
151 i2c::vals::Reload::NOT_COMPLETED
152 } else {
153 i2c::vals::Reload::COMPLETED
154 };
155
156 info.regs.cr2().modify(|w| { 171 info.regs.cr2().modify(|w| {
157 w.set_sadd(address.addr() << 1); 172 w.set_sadd(address.addr() << 1);
158 w.set_add10(address.add_mode()); 173 w.set_add10(address.add_mode());
@@ -160,7 +175,7 @@ impl<'d, M: Mode, IM: MasterMode> I2c<'d, M, IM> {
160 w.set_nbytes(length as u8); 175 w.set_nbytes(length as u8);
161 w.set_start(true); 176 w.set_start(true);
162 w.set_autoend(stop.autoend()); 177 w.set_autoend(stop.autoend());
163 w.set_reload(reload); 178 w.set_reload(Self::to_reload(reload));
164 }); 179 });
165 180
166 Ok(()) 181 Ok(())
@@ -172,28 +187,25 @@ impl<'d, M: Mode, IM: MasterMode> I2c<'d, M, IM> {
172 length: usize, 187 length: usize,
173 stop: Stop, 188 stop: Stop,
174 reload: bool, 189 reload: bool,
190 restart: bool,
175 timeout: Timeout, 191 timeout: Timeout,
176 ) -> Result<(), Error> { 192 ) -> Result<(), Error> {
177 assert!(length < 256); 193 assert!(length < 256);
178 194
179 // Wait for any previous address sequence to end 195 if !restart {
180 // automatically. This could be up to 50% of a bus 196 // Wait for any previous address sequence to end
181 // cycle (ie. up to 0.5/freq) 197 // automatically. This could be up to 50% of a bus
182 while info.regs.cr2().read().start() { 198 // cycle (ie. up to 0.5/freq)
183 timeout.check()?; 199 while info.regs.cr2().read().start() {
184 } 200 timeout.check()?;
201 }
185 202
186 // Wait for the bus to be free 203 // Wait for the bus to be free
187 while info.regs.isr().read().busy() { 204 while info.regs.isr().read().busy() {
188 timeout.check()?; 205 timeout.check()?;
206 }
189 } 207 }
190 208
191 let reload = if reload {
192 i2c::vals::Reload::NOT_COMPLETED
193 } else {
194 i2c::vals::Reload::COMPLETED
195 };
196
197 // Set START and prepare to send `bytes`. The 209 // Set START and prepare to send `bytes`. The
198 // START bit can be set even if the bus is BUSY or 210 // START bit can be set even if the bus is BUSY or
199 // I2C is in slave mode. 211 // I2C is in slave mode.
@@ -204,28 +216,36 @@ impl<'d, M: Mode, IM: MasterMode> I2c<'d, M, IM> {
204 w.set_nbytes(length as u8); 216 w.set_nbytes(length as u8);
205 w.set_start(true); 217 w.set_start(true);
206 w.set_autoend(stop.autoend()); 218 w.set_autoend(stop.autoend());
207 w.set_reload(reload); 219 w.set_reload(Self::to_reload(reload));
208 }); 220 });
209 221
210 Ok(()) 222 Ok(())
211 } 223 }
212 224
213 fn reload(info: &'static Info, length: usize, will_reload: bool, timeout: Timeout) -> Result<(), Error> { 225 fn reload(
226 info: &'static Info,
227 length: usize,
228 will_reload: bool,
229 stop: Stop,
230 timeout: Timeout,
231 ) -> Result<(), Error> {
214 assert!(length < 256 && length > 0); 232 assert!(length < 256 && length > 0);
215 233
216 while !info.regs.isr().read().tcr() { 234 // Wait for either TCR (Transfer Complete Reload) or TC (Transfer Complete)
235 // TCR occurs when RELOAD=1, TC occurs when RELOAD=0
236 // Both indicate the peripheral is ready for the next transfer
237 loop {
238 let isr = info.regs.isr().read();
239 if isr.tcr() || isr.tc() {
240 break;
241 }
217 timeout.check()?; 242 timeout.check()?;
218 } 243 }
219 244
220 let will_reload = if will_reload {
221 i2c::vals::Reload::NOT_COMPLETED
222 } else {
223 i2c::vals::Reload::COMPLETED
224 };
225
226 info.regs.cr2().modify(|w| { 245 info.regs.cr2().modify(|w| {
227 w.set_nbytes(length as u8); 246 w.set_nbytes(length as u8);
228 w.set_reload(will_reload); 247 w.set_reload(Self::to_reload(will_reload));
248 w.set_autoend(stop.autoend());
229 }); 249 });
230 250
231 Ok(()) 251 Ok(())
@@ -369,7 +389,9 @@ impl<'d, M: Mode, IM: MasterMode> I2c<'d, M, IM> {
369 loop { 389 loop {
370 let isr = self.info.regs.isr().read(); 390 let isr = self.info.regs.isr().read();
371 self.error_occurred(&isr, timeout)?; 391 self.error_occurred(&isr, timeout)?;
372 if isr.tc() { 392 // Wait for either TC or TCR - both indicate transfer completion
393 // TCR occurs when RELOAD=1, TC occurs when RELOAD=0
394 if isr.tc() || isr.tcr() {
373 return Ok(()); 395 return Ok(());
374 } 396 }
375 timeout.check()?; 397 timeout.check()?;
@@ -396,14 +418,20 @@ impl<'d, M: Mode, IM: MasterMode> I2c<'d, M, IM> {
396 address, 418 address,
397 read.len().min(255), 419 read.len().min(255),
398 Stop::Automatic, 420 Stop::Automatic,
399 last_chunk_idx != 0, 421 last_chunk_idx != 0, // reload
400 restart, 422 restart,
401 timeout, 423 timeout,
402 )?; 424 )?;
403 425
404 for (number, chunk) in read.chunks_mut(255).enumerate() { 426 for (number, chunk) in read.chunks_mut(255).enumerate() {
405 if number != 0 { 427 if number != 0 {
406 Self::reload(self.info, chunk.len(), number != last_chunk_idx, timeout)?; 428 Self::reload(
429 self.info,
430 chunk.len(),
431 number != last_chunk_idx,
432 Stop::Automatic,
433 timeout,
434 )?;
407 } 435 }
408 436
409 for byte in chunk { 437 for byte in chunk {
@@ -441,6 +469,7 @@ impl<'d, M: Mode, IM: MasterMode> I2c<'d, M, IM> {
441 write.len().min(255), 469 write.len().min(255),
442 Stop::Software, 470 Stop::Software,
443 last_chunk_idx != 0, 471 last_chunk_idx != 0,
472 false, // restart
444 timeout, 473 timeout,
445 ) { 474 ) {
446 if send_stop { 475 if send_stop {
@@ -451,7 +480,13 @@ impl<'d, M: Mode, IM: MasterMode> I2c<'d, M, IM> {
451 480
452 for (number, chunk) in write.chunks(255).enumerate() { 481 for (number, chunk) in write.chunks(255).enumerate() {
453 if number != 0 { 482 if number != 0 {
454 Self::reload(self.info, chunk.len(), number != last_chunk_idx, timeout)?; 483 Self::reload(
484 self.info,
485 chunk.len(),
486 number != last_chunk_idx,
487 Stop::Software,
488 timeout,
489 )?;
455 } 490 }
456 491
457 for byte in chunk { 492 for byte in chunk {
@@ -507,9 +542,215 @@ impl<'d, M: Mode, IM: MasterMode> I2c<'d, M, IM> {
507 /// 542 ///
508 /// [transaction contract]: embedded_hal_1::i2c::I2c::transaction 543 /// [transaction contract]: embedded_hal_1::i2c::I2c::transaction
509 pub fn blocking_transaction(&mut self, addr: u8, operations: &mut [Operation<'_>]) -> Result<(), Error> { 544 pub fn blocking_transaction(&mut self, addr: u8, operations: &mut [Operation<'_>]) -> Result<(), Error> {
510 let _ = addr; 545 if operations.is_empty() {
511 let _ = operations; 546 return Err(Error::ZeroLengthTransfer);
512 todo!() 547 }
548
549 let address = addr.into();
550 let timeout = self.timeout();
551
552 // Group consecutive operations of the same type
553 let mut op_idx = 0;
554 let mut is_first_group = true;
555
556 while op_idx < operations.len() {
557 // Determine the type of current group and find all consecutive operations of same type
558 let is_read = matches!(operations[op_idx], Operation::Read(_));
559 let group_start = op_idx;
560
561 // Find end of this group (consecutive operations of same type)
562 while op_idx < operations.len() && matches!(operations[op_idx], Operation::Read(_)) == is_read {
563 op_idx += 1;
564 }
565 let group_end = op_idx;
566 let is_last_group = op_idx >= operations.len();
567
568 // Execute this group of operations
569 if is_read {
570 self.execute_read_group(
571 address,
572 &mut operations[group_start..group_end],
573 is_first_group,
574 is_last_group,
575 timeout,
576 )?;
577 } else {
578 self.execute_write_group(
579 address,
580 &operations[group_start..group_end],
581 is_first_group,
582 is_last_group,
583 timeout,
584 )?;
585 }
586
587 is_first_group = false;
588 }
589
590 Ok(())
591 }
592
593 fn execute_write_group(
594 &mut self,
595 address: Address,
596 operations: &[Operation<'_>],
597 is_first_group: bool,
598 is_last_group: bool,
599 timeout: Timeout,
600 ) -> Result<(), Error> {
601 // Calculate total bytes across all operations in this group
602 let total_bytes = Self::total_operation_bytes(operations);
603
604 if total_bytes == 0 {
605 // Handle empty write group - just send address
606 if is_first_group {
607 Self::master_write(self.info, address, 0, Stop::Software, false, !is_first_group, timeout)?;
608 }
609 if is_last_group {
610 self.master_stop();
611 }
612 return Ok(());
613 }
614
615 let mut total_remaining = total_bytes;
616 let mut first_chunk = true;
617
618 for operation in operations {
619 if let Operation::Write(buffer) = operation {
620 for chunk in buffer.chunks(255) {
621 let chunk_len = chunk.len();
622 total_remaining -= chunk_len;
623 let is_last_chunk = total_remaining == 0;
624 let will_reload = !is_last_chunk;
625
626 if first_chunk {
627 // First chunk: initiate transfer
628 // If not first group, use RESTART instead of START
629 Self::master_write(
630 self.info,
631 address,
632 chunk_len,
633 Stop::Software,
634 will_reload,
635 !is_first_group,
636 timeout,
637 )?;
638 first_chunk = false;
639 } else {
640 // Subsequent chunks: use reload
641 // Always use Software stop for writes
642 Self::reload(self.info, chunk_len, will_reload, Stop::Software, timeout)?;
643 }
644
645 // Send data bytes
646 for byte in chunk {
647 self.wait_txis(timeout)?;
648 self.info.regs.txdr().write(|w| w.set_txdata(*byte));
649 }
650 }
651 }
652 }
653
654 // Wait for transfer to complete
655 if is_last_group {
656 self.wait_tc(timeout)?;
657 self.master_stop();
658 self.wait_stop(timeout)?;
659 } else {
660 // Wait for TC before next group (enables RESTART)
661 self.wait_tc(timeout)?;
662 }
663
664 Ok(())
665 }
666
667 fn execute_read_group(
668 &mut self,
669 address: Address,
670 operations: &mut [Operation<'_>],
671 is_first_group: bool,
672 is_last_group: bool,
673 timeout: Timeout,
674 ) -> Result<(), Error> {
675 // Calculate total bytes across all operations in this group
676 let total_bytes = Self::total_operation_bytes(operations);
677
678 if total_bytes == 0 {
679 // Handle empty read group
680 if is_first_group {
681 Self::master_read(
682 self.info,
683 address,
684 0,
685 if is_last_group { Stop::Automatic } else { Stop::Software },
686 false, // reload
687 !is_first_group,
688 timeout,
689 )?;
690 }
691 if is_last_group {
692 self.wait_stop(timeout)?;
693 }
694 return Ok(());
695 }
696
697 let mut total_remaining = total_bytes;
698 let mut first_chunk = true;
699
700 for operation in operations {
701 if let Operation::Read(buffer) = operation {
702 for chunk in buffer.chunks_mut(255) {
703 let chunk_len = chunk.len();
704 total_remaining -= chunk_len;
705 let is_last_chunk = total_remaining == 0;
706 let will_reload = !is_last_chunk;
707
708 if first_chunk {
709 // First chunk: initiate transfer
710 let stop = if is_last_group && is_last_chunk {
711 Stop::Automatic
712 } else {
713 Stop::Software
714 };
715
716 Self::master_read(
717 self.info,
718 address,
719 chunk_len,
720 stop,
721 will_reload,
722 !is_first_group, // restart if not first group
723 timeout,
724 )?;
725 first_chunk = false;
726 } else {
727 // Subsequent chunks: use reload
728 let stop = if is_last_group && is_last_chunk {
729 Stop::Automatic
730 } else {
731 Stop::Software
732 };
733 Self::reload(self.info, chunk_len, will_reload, stop, timeout)?;
734 }
735
736 // Receive data bytes
737 for byte in chunk {
738 self.wait_rxne(timeout)?;
739 *byte = self.info.regs.rxdr().read().rxdata();
740 }
741 }
742 }
743 }
744
745 // Wait for transfer to complete
746 if is_last_group {
747 self.wait_stop(timeout)?;
748 }
749 // For non-last read groups, don't wait for TC - the peripheral may hold SCL low
750 // in Software AUTOEND mode until the next START is issued. Just proceed directly
751 // to the next group which will issue RESTART and release the clock.
752
753 Ok(())
513 } 754 }
514 755
515 /// Blocking write multiple buffers. 756 /// Blocking write multiple buffers.
@@ -531,6 +772,7 @@ impl<'d, M: Mode, IM: MasterMode> I2c<'d, M, IM> {
531 first_length.min(255), 772 first_length.min(255),
532 Stop::Software, 773 Stop::Software,
533 (first_length > 255) || (last_slice_index != 0), 774 (first_length > 255) || (last_slice_index != 0),
775 false, // restart
534 timeout, 776 timeout,
535 ) { 777 ) {
536 self.master_stop(); 778 self.master_stop();
@@ -552,6 +794,7 @@ impl<'d, M: Mode, IM: MasterMode> I2c<'d, M, IM> {
552 self.info, 794 self.info,
553 slice_len.min(255), 795 slice_len.min(255),
554 (idx != last_slice_index) || (slice_len > 255), 796 (idx != last_slice_index) || (slice_len > 255),
797 Stop::Software,
555 timeout, 798 timeout,
556 ) { 799 ) {
557 if err != Error::Nack { 800 if err != Error::Nack {
@@ -567,6 +810,7 @@ impl<'d, M: Mode, IM: MasterMode> I2c<'d, M, IM> {
567 self.info, 810 self.info,
568 chunk.len(), 811 chunk.len(),
569 (number != last_chunk_idx) || (idx != last_slice_index), 812 (number != last_chunk_idx) || (idx != last_slice_index),
813 Stop::Software,
570 timeout, 814 timeout,
571 ) { 815 ) {
572 if err != Error::Nack { 816 if err != Error::Nack {
@@ -610,6 +854,7 @@ impl<'d, IM: MasterMode> I2c<'d, Async, IM> {
610 first_slice: bool, 854 first_slice: bool,
611 last_slice: bool, 855 last_slice: bool,
612 send_stop: bool, 856 send_stop: bool,
857 restart: bool,
613 timeout: Timeout, 858 timeout: Timeout,
614 ) -> Result<(), Error> { 859 ) -> Result<(), Error> {
615 let total_len = write.len(); 860 let total_len = write.len();
@@ -676,10 +921,17 @@ impl<'d, IM: MasterMode> I2c<'d, Async, IM> {
676 total_len.min(255), 921 total_len.min(255),
677 Stop::Software, 922 Stop::Software,
678 (total_len > 255) || !last_slice, 923 (total_len > 255) || !last_slice,
924 restart,
679 timeout, 925 timeout,
680 )?; 926 )?;
681 } else { 927 } else {
682 Self::reload(self.info, total_len.min(255), (total_len > 255) || !last_slice, timeout)?; 928 Self::reload(
929 self.info,
930 total_len.min(255),
931 (total_len > 255) || !last_slice,
932 Stop::Software,
933 timeout,
934 )?;
683 self.info.regs.cr1().modify(|w| w.set_tcie(true)); 935 self.info.regs.cr1().modify(|w| w.set_tcie(true));
684 } 936 }
685 } else if !(isr.tcr() || isr.tc()) { 937 } else if !(isr.tcr() || isr.tc()) {
@@ -688,9 +940,13 @@ impl<'d, IM: MasterMode> I2c<'d, Async, IM> {
688 } else if remaining_len == 0 { 940 } else if remaining_len == 0 {
689 return Poll::Ready(Ok(())); 941 return Poll::Ready(Ok(()));
690 } else { 942 } else {
691 let last_piece = (remaining_len <= 255) && last_slice; 943 if let Err(e) = Self::reload(
692 944 self.info,
693 if let Err(e) = Self::reload(self.info, remaining_len.min(255), !last_piece, timeout) { 945 remaining_len.min(255),
946 (remaining_len > 255) || !last_slice,
947 Stop::Software,
948 timeout,
949 ) {
694 return Poll::Ready(Err(e)); 950 return Poll::Ready(Err(e));
695 } 951 }
696 self.info.regs.cr1().modify(|w| w.set_tcie(true)); 952 self.info.regs.cr1().modify(|w| w.set_tcie(true));
@@ -702,10 +958,9 @@ impl<'d, IM: MasterMode> I2c<'d, Async, IM> {
702 .await?; 958 .await?;
703 959
704 dma_transfer.await; 960 dma_transfer.await;
705 if last_slice { 961
706 // This should be done already 962 // Always wait for TC after DMA completes - needed for consecutive buffers
707 self.wait_tc(timeout)?; 963 self.wait_tc(timeout)?;
708 }
709 964
710 if last_slice & send_stop { 965 if last_slice & send_stop {
711 self.master_stop(); 966 self.master_stop();
@@ -780,7 +1035,7 @@ impl<'d, IM: MasterMode> I2c<'d, Async, IM> {
780 address, 1035 address,
781 total_len.min(255), 1036 total_len.min(255),
782 Stop::Automatic, 1037 Stop::Automatic,
783 total_len > 255, 1038 total_len > 255, // reload
784 restart, 1039 restart,
785 timeout, 1040 timeout,
786 )?; 1041 )?;
@@ -788,12 +1043,10 @@ impl<'d, IM: MasterMode> I2c<'d, Async, IM> {
788 return Poll::Ready(Ok(())); 1043 return Poll::Ready(Ok(()));
789 } 1044 }
790 } else if isr.tcr() { 1045 } else if isr.tcr() {
791 // poll_fn was woken without an interrupt present 1046 // Transfer Complete Reload - need to set up next chunk
792 return Poll::Pending;
793 } else {
794 let last_piece = remaining_len <= 255; 1047 let last_piece = remaining_len <= 255;
795 1048
796 if let Err(e) = Self::reload(self.info, remaining_len.min(255), !last_piece, timeout) { 1049 if let Err(e) = Self::reload(self.info, remaining_len.min(255), !last_piece, Stop::Automatic, timeout) {
797 return Poll::Ready(Err(e)); 1050 return Poll::Ready(Err(e));
798 } 1051 }
799 // Return here if we are on last chunk, 1052 // Return here if we are on last chunk,
@@ -802,6 +1055,9 @@ impl<'d, IM: MasterMode> I2c<'d, Async, IM> {
802 return Poll::Ready(Ok(())); 1055 return Poll::Ready(Ok(()));
803 } 1056 }
804 self.info.regs.cr1().modify(|w| w.set_tcie(true)); 1057 self.info.regs.cr1().modify(|w| w.set_tcie(true));
1058 } else {
1059 // poll_fn was woken without TCR interrupt
1060 return Poll::Pending;
805 } 1061 }
806 1062
807 remaining_len = remaining_len.saturating_sub(255); 1063 remaining_len = remaining_len.saturating_sub(255);
@@ -826,7 +1082,7 @@ impl<'d, IM: MasterMode> I2c<'d, Async, IM> {
826 self.write_internal(address.into(), write, true, timeout) 1082 self.write_internal(address.into(), write, true, timeout)
827 } else { 1083 } else {
828 timeout 1084 timeout
829 .with(self.write_dma_internal(address.into(), write, true, true, true, timeout)) 1085 .with(self.write_dma_internal(address.into(), write, true, true, true, false, timeout))
830 .await 1086 .await
831 } 1087 }
832 } 1088 }
@@ -842,16 +1098,24 @@ impl<'d, IM: MasterMode> I2c<'d, Async, IM> {
842 if write.is_empty() { 1098 if write.is_empty() {
843 return Err(Error::ZeroLengthTransfer); 1099 return Err(Error::ZeroLengthTransfer);
844 } 1100 }
845 let mut iter = write.iter();
846 1101
1102 let mut iter = write.iter();
847 let mut first = true; 1103 let mut first = true;
848 let mut current = iter.next(); 1104 let mut current = iter.next();
1105
849 while let Some(c) = current { 1106 while let Some(c) = current {
850 let next = iter.next(); 1107 let next = iter.next();
851 let is_last = next.is_none(); 1108 let is_last = next.is_none();
852 1109
853 let fut = self.write_dma_internal(address, c, first, is_last, is_last, timeout); 1110 let fut = self.write_dma_internal(
1111 address, c, first, // first_slice
1112 is_last, // last_slice
1113 is_last, // send_stop (only on last buffer)
1114 false, // restart (false for all - they're one continuous write)
1115 timeout,
1116 );
854 timeout.with(fut).await?; 1117 timeout.with(fut).await?;
1118
855 first = false; 1119 first = false;
856 current = next; 1120 current = next;
857 } 1121 }
@@ -881,7 +1145,7 @@ impl<'d, IM: MasterMode> I2c<'d, Async, IM> {
881 if write.is_empty() { 1145 if write.is_empty() {
882 self.write_internal(address.into(), write, false, timeout)?; 1146 self.write_internal(address.into(), write, false, timeout)?;
883 } else { 1147 } else {
884 let fut = self.write_dma_internal(address.into(), write, true, true, false, timeout); 1148 let fut = self.write_dma_internal(address.into(), write, true, true, false, false, timeout);
885 timeout.with(fut).await?; 1149 timeout.with(fut).await?;
886 } 1150 }
887 1151
@@ -903,9 +1167,299 @@ impl<'d, IM: MasterMode> I2c<'d, Async, IM> {
903 pub async fn transaction(&mut self, addr: u8, operations: &mut [Operation<'_>]) -> Result<(), Error> { 1167 pub async fn transaction(&mut self, addr: u8, operations: &mut [Operation<'_>]) -> Result<(), Error> {
904 #[cfg(all(feature = "low-power", stm32wlex))] 1168 #[cfg(all(feature = "low-power", stm32wlex))]
905 let _device_busy = crate::low_power::DeviceBusy::new_stop1(); 1169 let _device_busy = crate::low_power::DeviceBusy::new_stop1();
906 let _ = addr; 1170
907 let _ = operations; 1171 if operations.is_empty() {
908 todo!() 1172 return Err(Error::ZeroLengthTransfer);
1173 }
1174
1175 let address = addr.into();
1176 let timeout = self.timeout();
1177
1178 // Group consecutive operations of the same type
1179 let mut op_idx = 0;
1180 let mut is_first_group = true;
1181
1182 while op_idx < operations.len() {
1183 // Determine the type of current group and find all consecutive operations of same type
1184 let is_read = matches!(operations[op_idx], Operation::Read(_));
1185 let group_start = op_idx;
1186
1187 // Find end of this group (consecutive operations of same type)
1188 while op_idx < operations.len() && matches!(operations[op_idx], Operation::Read(_)) == is_read {
1189 op_idx += 1;
1190 }
1191 let group_end = op_idx;
1192 let is_last_group = op_idx >= operations.len();
1193
1194 // Execute this group of operations
1195 if is_read {
1196 self.execute_read_group_async(
1197 address,
1198 &mut operations[group_start..group_end],
1199 is_first_group,
1200 is_last_group,
1201 timeout,
1202 )
1203 .await?;
1204 } else {
1205 self.execute_write_group_async(
1206 address,
1207 &operations[group_start..group_end],
1208 is_first_group,
1209 is_last_group,
1210 timeout,
1211 )
1212 .await?;
1213 }
1214
1215 is_first_group = false;
1216 }
1217
1218 Ok(())
1219 }
1220
1221 async fn execute_write_group_async(
1222 &mut self,
1223 address: Address,
1224 operations: &[Operation<'_>],
1225 is_first_group: bool,
1226 is_last_group: bool,
1227 timeout: Timeout,
1228 ) -> Result<(), Error> {
1229 // Calculate total bytes across all operations in this group
1230 let total_bytes = Self::total_operation_bytes(operations);
1231
1232 if total_bytes == 0 {
1233 // Handle empty write group using blocking call
1234 if is_first_group {
1235 Self::master_write(self.info, address, 0, Stop::Software, false, !is_first_group, timeout)?;
1236 }
1237 if is_last_group {
1238 self.master_stop();
1239 }
1240 return Ok(());
1241 }
1242
1243 // Collect all write buffers
1244 let mut write_buffers: heapless::Vec<&[u8], 16> = heapless::Vec::new();
1245 for operation in operations {
1246 if let Operation::Write(buffer) = operation {
1247 if !buffer.is_empty() {
1248 let _ = write_buffers.push(buffer);
1249 }
1250 }
1251 }
1252
1253 if write_buffers.is_empty() {
1254 return Ok(());
1255 }
1256
1257 // Send each buffer using DMA
1258 let num_buffers = write_buffers.len();
1259 for (idx, buffer) in write_buffers.iter().enumerate() {
1260 let is_first_buffer = idx == 0;
1261 let is_last_buffer = idx == num_buffers - 1;
1262
1263 let fut = self.write_dma_internal(
1264 address,
1265 buffer,
1266 is_first_buffer, // first_slice
1267 is_last_buffer, // last_slice
1268 is_last_buffer && is_last_group, // send_stop
1269 is_first_buffer && !is_first_group, // restart (only for first buffer if not first group)
1270 timeout,
1271 );
1272 timeout.with(fut).await?;
1273 }
1274
1275 Ok(())
1276 }
1277
1278 async fn execute_read_group_async(
1279 &mut self,
1280 address: Address,
1281 operations: &mut [Operation<'_>],
1282 is_first_group: bool,
1283 is_last_group: bool,
1284 timeout: Timeout,
1285 ) -> Result<(), Error> {
1286 // Calculate total bytes across all operations in this group
1287 let total_bytes = Self::total_operation_bytes(operations);
1288
1289 if total_bytes == 0 {
1290 // Handle empty read group using blocking call
1291 if is_first_group {
1292 Self::master_read(
1293 self.info,
1294 address,
1295 0,
1296 if is_last_group { Stop::Automatic } else { Stop::Software },
1297 false, // reload
1298 !is_first_group,
1299 timeout,
1300 )?;
1301 }
1302 if is_last_group {
1303 self.wait_stop(timeout)?;
1304 }
1305 return Ok(());
1306 }
1307
1308 // Use DMA for read operations - need to handle multiple buffers
1309 let restart = !is_first_group;
1310 let mut total_remaining = total_bytes;
1311 let mut is_first_in_group = true;
1312
1313 for operation in operations {
1314 if let Operation::Read(buffer) = operation {
1315 if buffer.is_empty() {
1316 // Skip empty buffers
1317 continue;
1318 }
1319
1320 let buf_len = buffer.len();
1321 total_remaining -= buf_len;
1322 let is_last_in_group = total_remaining == 0;
1323
1324 // Perform DMA read
1325 if is_first_in_group {
1326 // First buffer: use read_dma_internal which handles restart properly
1327 // Only use Automatic stop if this is the last buffer in the last group
1328 let stop_mode = if is_last_group && is_last_in_group {
1329 Stop::Automatic
1330 } else {
1331 Stop::Software
1332 };
1333
1334 // We need a custom DMA read that respects our stop mode
1335 self.read_dma_group_internal(address, buffer, restart, stop_mode, timeout)
1336 .await?;
1337 is_first_in_group = false;
1338 } else {
1339 // Subsequent buffers: need to reload and continue
1340 let stop_mode = if is_last_group && is_last_in_group {
1341 Stop::Automatic
1342 } else {
1343 Stop::Software
1344 };
1345
1346 self.read_dma_group_internal(
1347 address, buffer, false, // no restart for subsequent buffers in same group
1348 stop_mode, timeout,
1349 )
1350 .await?;
1351 }
1352 }
1353 }
1354
1355 // Wait for transfer to complete
1356 if is_last_group {
1357 self.wait_stop(timeout)?;
1358 }
1359
1360 Ok(())
1361 }
1362
1363 /// Internal DMA read helper for transaction groups
1364 async fn read_dma_group_internal(
1365 &mut self,
1366 address: Address,
1367 buffer: &mut [u8],
1368 restart: bool,
1369 stop_mode: Stop,
1370 timeout: Timeout,
1371 ) -> Result<(), Error> {
1372 let total_len = buffer.len();
1373
1374 let dma_transfer = unsafe {
1375 let regs = self.info.regs;
1376 regs.cr1().modify(|w| {
1377 w.set_rxdmaen(true);
1378 w.set_tcie(true);
1379 w.set_nackie(true);
1380 w.set_errie(true);
1381 });
1382 let src = regs.rxdr().as_ptr() as *mut u8;
1383
1384 self.rx_dma.as_mut().unwrap().read(src, buffer, Default::default())
1385 };
1386
1387 let mut remaining_len = total_len;
1388
1389 let on_drop = OnDrop::new(|| {
1390 let regs = self.info.regs;
1391 regs.cr1().modify(|w| {
1392 w.set_rxdmaen(false);
1393 w.set_tcie(false);
1394 w.set_nackie(false);
1395 w.set_errie(false);
1396 });
1397 regs.icr().write(|w| {
1398 w.set_nackcf(true);
1399 w.set_berrcf(true);
1400 w.set_arlocf(true);
1401 w.set_ovrcf(true);
1402 });
1403 });
1404
1405 poll_fn(|cx| {
1406 self.state.waker.register(cx.waker());
1407
1408 let isr = self.info.regs.isr().read();
1409
1410 if isr.nackf() {
1411 return Poll::Ready(Err(Error::Nack));
1412 }
1413 if isr.arlo() {
1414 return Poll::Ready(Err(Error::Arbitration));
1415 }
1416 if isr.berr() {
1417 return Poll::Ready(Err(Error::Bus));
1418 }
1419 if isr.ovr() {
1420 return Poll::Ready(Err(Error::Overrun));
1421 }
1422
1423 if remaining_len == total_len {
1424 Self::master_read(
1425 self.info,
1426 address,
1427 total_len.min(255),
1428 stop_mode,
1429 total_len > 255, // reload
1430 restart,
1431 timeout,
1432 )?;
1433 if total_len <= 255 {
1434 return Poll::Ready(Ok(()));
1435 }
1436 } else if isr.tcr() {
1437 // Transfer Complete Reload - need to set up next chunk
1438 let last_piece = remaining_len <= 255;
1439
1440 if let Err(e) = Self::reload(self.info, remaining_len.min(255), !last_piece, stop_mode, timeout) {
1441 return Poll::Ready(Err(e));
1442 }
1443 // Return here if we are on last chunk,
1444 // end of transfer will be awaited with the DMA below
1445 if last_piece {
1446 return Poll::Ready(Ok(()));
1447 }
1448 self.info.regs.cr1().modify(|w| w.set_tcie(true));
1449 } else {
1450 // poll_fn was woken without TCR interrupt
1451 return Poll::Pending;
1452 }
1453
1454 remaining_len = remaining_len.saturating_sub(255);
1455 Poll::Pending
1456 })
1457 .await?;
1458
1459 dma_transfer.await;
1460 drop(on_drop);
1461
1462 Ok(())
909 } 1463 }
910} 1464}
911 1465
@@ -1043,7 +1597,13 @@ impl<'d, M: Mode> I2c<'d, M, MultiMaster> {
1043 if number == 0 { 1597 if number == 0 {
1044 Self::slave_start(self.info, chunk.len(), number != last_chunk_idx); 1598 Self::slave_start(self.info, chunk.len(), number != last_chunk_idx);
1045 } else { 1599 } else {
1046 Self::reload(self.info, chunk.len(), number != last_chunk_idx, timeout)?; 1600 Self::reload(
1601 self.info,
1602 chunk.len(),
1603 number != last_chunk_idx,
1604 Stop::Software,
1605 timeout,
1606 )?;
1047 } 1607 }
1048 1608
1049 let mut index = 0; 1609 let mut index = 0;
@@ -1092,7 +1652,13 @@ impl<'d, M: Mode> I2c<'d, M, MultiMaster> {
1092 if number == 0 { 1652 if number == 0 {
1093 Self::slave_start(self.info, chunk.len(), number != last_chunk_idx); 1653 Self::slave_start(self.info, chunk.len(), number != last_chunk_idx);
1094 } else { 1654 } else {
1095 Self::reload(self.info, chunk.len(), number != last_chunk_idx, timeout)?; 1655 Self::reload(
1656 self.info,
1657 chunk.len(),
1658 number != last_chunk_idx,
1659 Stop::Software,
1660 timeout,
1661 )?;
1096 } 1662 }
1097 1663
1098 let mut index = 0; 1664 let mut index = 0;
@@ -1228,13 +1794,20 @@ impl<'d> I2c<'d, Async, MultiMaster> {
1228 Poll::Pending 1794 Poll::Pending
1229 } else if isr.tcr() { 1795 } else if isr.tcr() {
1230 let is_last_slice = remaining_len <= 255; 1796 let is_last_slice = remaining_len <= 255;
1231 if let Err(e) = Self::reload(self.info, remaining_len.min(255), !is_last_slice, timeout) { 1797 if let Err(e) = Self::reload(
1798 self.info,
1799 remaining_len.min(255),
1800 !is_last_slice,
1801 Stop::Software,
1802 timeout,
1803 ) {
1232 return Poll::Ready(Err(e)); 1804 return Poll::Ready(Err(e));
1233 } 1805 }
1234 remaining_len = remaining_len.saturating_sub(255); 1806 remaining_len = remaining_len.saturating_sub(255);
1235 regs.cr1().modify(|w| w.set_tcie(true)); 1807 regs.cr1().modify(|w| w.set_tcie(true));
1236 Poll::Pending 1808 Poll::Pending
1237 } else if isr.stopf() { 1809 } else if isr.stopf() {
1810 remaining_len = remaining_len.saturating_add(dma_transfer.get_remaining_transfers() as usize);
1238 regs.icr().write(|reg| reg.set_stopcf(true)); 1811 regs.icr().write(|reg| reg.set_stopcf(true));
1239 let poll = Poll::Ready(Ok(total_len - remaining_len)); 1812 let poll = Poll::Ready(Ok(total_len - remaining_len));
1240 poll 1813 poll
@@ -1274,7 +1847,8 @@ impl<'d> I2c<'d, Async, MultiMaster> {
1274 w.set_txdmaen(false); 1847 w.set_txdmaen(false);
1275 w.set_stopie(false); 1848 w.set_stopie(false);
1276 w.set_tcie(false); 1849 w.set_tcie(false);
1277 }) 1850 });
1851 regs.isr().write(|w| w.set_txe(true));
1278 }); 1852 });
1279 1853
1280 let state = self.state; 1854 let state = self.state;
@@ -1290,13 +1864,24 @@ impl<'d> I2c<'d, Async, MultiMaster> {
1290 Poll::Pending 1864 Poll::Pending
1291 } else if isr.tcr() { 1865 } else if isr.tcr() {
1292 let is_last_slice = remaining_len <= 255; 1866 let is_last_slice = remaining_len <= 255;
1293 if let Err(e) = Self::reload(self.info, remaining_len.min(255), !is_last_slice, timeout) { 1867 if let Err(e) = Self::reload(
1868 self.info,
1869 remaining_len.min(255),
1870 !is_last_slice,
1871 Stop::Software,
1872 timeout,
1873 ) {
1294 return Poll::Ready(Err(e)); 1874 return Poll::Ready(Err(e));
1295 } 1875 }
1296 remaining_len = remaining_len.saturating_sub(255); 1876 remaining_len = remaining_len.saturating_sub(255);
1297 self.info.regs.cr1().modify(|w| w.set_tcie(true)); 1877 self.info.regs.cr1().modify(|w| w.set_tcie(true));
1298 Poll::Pending 1878 Poll::Pending
1299 } else if isr.stopf() { 1879 } else if isr.stopf() {
1880 let mut leftover_bytes = dma_transfer.get_remaining_transfers();
1881 if !self.info.regs.isr().read().txe() {
1882 leftover_bytes = leftover_bytes.saturating_add(1);
1883 }
1884 remaining_len = remaining_len.saturating_add(leftover_bytes as usize);
1300 self.info.regs.icr().write(|reg| reg.set_stopcf(true)); 1885 self.info.regs.icr().write(|reg| reg.set_stopcf(true));
1301 if remaining_len > 0 { 1886 if remaining_len > 0 {
1302 dma_transfer.request_pause(); 1887 dma_transfer.request_pause();
diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs
index e08ab30e6..6e492946a 100644
--- a/embassy-stm32/src/lib.rs
+++ b/embassy-stm32/src/lib.rs
@@ -77,6 +77,7 @@ pub mod dts;
77pub mod eth; 77pub mod eth;
78#[cfg(feature = "exti")] 78#[cfg(feature = "exti")]
79pub mod exti; 79pub mod exti;
80#[cfg(flash)]
80pub mod flash; 81pub mod flash;
81#[cfg(fmc)] 82#[cfg(fmc)]
82pub mod fmc; 83pub mod fmc;
@@ -177,7 +178,6 @@ pub use crate::_generated::interrupt;
177/// } 178/// }
178/// ); 179/// );
179/// ``` 180/// ```
180
181// developer note: this macro can't be in `embassy-hal-internal` due to the use of `$crate`. 181// developer note: this macro can't be in `embassy-hal-internal` due to the use of `$crate`.
182#[macro_export] 182#[macro_export]
183macro_rules! bind_interrupts { 183macro_rules! bind_interrupts {
@@ -510,6 +510,16 @@ fn init_hw(config: Config) -> Peripherals {
510 critical_section::with(|cs| { 510 critical_section::with(|cs| {
511 let p = Peripherals::take_with_cs(cs); 511 let p = Peripherals::take_with_cs(cs);
512 512
513 #[cfg(dbgmcu_n6)]
514 {
515 crate::pac::RCC.miscensr().write(|w| w.set_dbgens(true));
516 crate::pac::RCC.miscenr().read(); // volatile read
517 crate::pac::DBGMCU
518 .cr()
519 .modify(|w| w.set_dbgclken(stm32_metapac::dbgmcu::vals::Dbgclken::B_0X1));
520 crate::pac::DBGMCU.cr().read();
521 }
522
513 #[cfg(dbgmcu)] 523 #[cfg(dbgmcu)]
514 crate::pac::DBGMCU.cr().modify(|cr| { 524 crate::pac::DBGMCU.cr().modify(|cr| {
515 #[cfg(dbgmcu_h5)] 525 #[cfg(dbgmcu_h5)]
@@ -524,7 +534,7 @@ fn init_hw(config: Config) -> Peripherals {
524 } 534 }
525 #[cfg(any( 535 #[cfg(any(
526 dbgmcu_f1, dbgmcu_f2, dbgmcu_f3, dbgmcu_f4, dbgmcu_f7, dbgmcu_g4, dbgmcu_f7, dbgmcu_l0, dbgmcu_l1, 536 dbgmcu_f1, dbgmcu_f2, dbgmcu_f3, dbgmcu_f4, dbgmcu_f7, dbgmcu_g4, dbgmcu_f7, dbgmcu_l0, dbgmcu_l1,
527 dbgmcu_l4, dbgmcu_wb, dbgmcu_wl 537 dbgmcu_l4, dbgmcu_wb, dbgmcu_wl, dbgmcu_n6
528 ))] 538 ))]
529 { 539 {
530 cr.set_dbg_sleep(config.enable_debug_during_sleep); 540 cr.set_dbg_sleep(config.enable_debug_during_sleep);
@@ -545,7 +555,7 @@ fn init_hw(config: Config) -> Peripherals {
545 rcc::enable_and_reset_with_cs::<peripherals::SYSCFG>(cs); 555 rcc::enable_and_reset_with_cs::<peripherals::SYSCFG>(cs);
546 #[cfg(not(any(stm32h5, stm32h7, stm32h7rs, stm32wb, stm32wl)))] 556 #[cfg(not(any(stm32h5, stm32h7, stm32h7rs, stm32wb, stm32wl)))]
547 rcc::enable_and_reset_with_cs::<peripherals::PWR>(cs); 557 rcc::enable_and_reset_with_cs::<peripherals::PWR>(cs);
548 #[cfg(not(any(stm32f2, stm32f4, stm32f7, stm32l0, stm32h5, stm32h7, stm32h7rs)))] 558 #[cfg(all(flash, not(any(stm32f2, stm32f4, stm32f7, stm32l0, stm32h5, stm32h7, stm32h7rs))))]
549 rcc::enable_and_reset_with_cs::<peripherals::FLASH>(cs); 559 rcc::enable_and_reset_with_cs::<peripherals::FLASH>(cs);
550 560
551 // Enable the VDDIO2 power supply on chips that have it. 561 // Enable the VDDIO2 power supply on chips that have it.
@@ -605,7 +615,7 @@ fn init_hw(config: Config) -> Peripherals {
605 #[cfg(ucpd)] 615 #[cfg(ucpd)]
606 ucpd::init( 616 ucpd::init(
607 cs, 617 cs,
608 #[cfg(peri_ucpd1)] 618 #[cfg(all(peri_ucpd1, not(stm32n6)))]
609 config.enable_ucpd1_dead_battery, 619 config.enable_ucpd1_dead_battery,
610 #[cfg(peri_ucpd2)] 620 #[cfg(peri_ucpd2)]
611 config.enable_ucpd2_dead_battery, 621 config.enable_ucpd2_dead_battery,
@@ -648,3 +658,17 @@ fn init_hw(config: Config) -> Peripherals {
648 p 658 p
649 }) 659 })
650} 660}
661
662/// Performs a busy-wait delay for a specified number of microseconds.
663#[allow(unused)]
664pub(crate) fn block_for_us(us: u64) {
665 cfg_if::cfg_if! {
666 // this does strange things on stm32wlx in low power mode depending on exactly when it's called
667 // as in sometimes 15 us (1 tick) would take > 20 seconds.
668 if #[cfg(all(feature = "time", all(not(feature = "low-power"), not(stm32wlex))))] {
669 embassy_time::block_for(embassy_time::Duration::from_micros(us));
670 } else {
671 cortex_m::asm::delay(unsafe { rcc::get_freqs().sys.to_hertz().unwrap().0 as u64 * us / 1_000_000 } as u32);
672 }
673 }
674}
diff --git a/embassy-stm32/src/opamp.rs b/embassy-stm32/src/opamp.rs
index ac8d5de21..4a55f5bd3 100644
--- a/embassy-stm32/src/opamp.rs
+++ b/embassy-stm32/src/opamp.rs
@@ -4,19 +4,12 @@
4use embassy_hal_internal::PeripheralType; 4use embassy_hal_internal::PeripheralType;
5 5
6use crate::Peri; 6use crate::Peri;
7#[cfg(opamp_v5)]
8use crate::block_for_us;
7use crate::pac::opamp::vals::*; 9use crate::pac::opamp::vals::*;
8#[cfg(not(any(stm32g4, stm32f3)))] 10#[cfg(not(any(stm32g4, stm32f3)))]
9use crate::rcc::RccInfo; 11use crate::rcc::RccInfo;
10 12
11/// Performs a busy-wait delay for a specified number of microseconds.
12#[cfg(opamp_v5)]
13fn blocking_delay_ms(ms: u32) {
14 #[cfg(feature = "time")]
15 embassy_time::block_for(embassy_time::Duration::from_millis(ms as u64));
16 #[cfg(not(feature = "time"))]
17 cortex_m::asm::delay(unsafe { crate::rcc::get_freqs() }.sys.to_hertz().unwrap().0 / 1_000 * ms);
18}
19
20/// Gain 13/// Gain
21#[allow(missing_docs)] 14#[allow(missing_docs)]
22#[derive(Clone, Copy)] 15#[derive(Clone, Copy)]
@@ -439,7 +432,7 @@ impl<'d, T: Instance> OpAmp<'d, T> {
439 432
440 // The closer the trimming value is to the optimum trimming value, the longer it takes to stabilize 433 // The closer the trimming value is to the optimum trimming value, the longer it takes to stabilize
441 // (with a maximum stabilization time remaining below 2 ms in any case) -- RM0440 25.3.7 434 // (with a maximum stabilization time remaining below 2 ms in any case) -- RM0440 25.3.7
442 blocking_delay_ms(2); 435 block_for_us(2_000);
443 436
444 if !T::regs().csr().read().calout() { 437 if !T::regs().csr().read().calout() {
445 if mid == 0 { 438 if mid == 0 {
diff --git a/embassy-stm32/src/rcc/bd.rs b/embassy-stm32/src/rcc/bd.rs
index 5b367c043..219be208f 100644
--- a/embassy-stm32/src/rcc/bd.rs
+++ b/embassy-stm32/src/rcc/bd.rs
@@ -1,5 +1,7 @@
1#[cfg(not(stm32n6))]
1use core::sync::atomic::{Ordering, compiler_fence}; 2use core::sync::atomic::{Ordering, compiler_fence};
2 3
4#[cfg(not(stm32n6))]
3use crate::pac::common::{RW, Reg}; 5use crate::pac::common::{RW, Reg};
4#[cfg(backup_sram)] 6#[cfg(backup_sram)]
5use crate::pac::pwr::vals::Retention; 7use crate::pac::pwr::vals::Retention;
@@ -54,7 +56,7 @@ impl From<LseDrive> for crate::pac::rcc::vals::Lsedrv {
54 } 56 }
55} 57}
56 58
57#[cfg(not(any(rtc_v2_l0, rtc_v2_l1, stm32c0)))] 59#[cfg(not(any(rtc_v2_l0, rtc_v2_l1, stm32c0, stm32n6)))]
58type Bdcr = crate::pac::rcc::regs::Bdcr; 60type Bdcr = crate::pac::rcc::regs::Bdcr;
59#[cfg(any(rtc_v2_l0, rtc_v2_l1))] 61#[cfg(any(rtc_v2_l0, rtc_v2_l1))]
60type Bdcr = crate::pac::rcc::regs::Csr; 62type Bdcr = crate::pac::rcc::regs::Csr;
@@ -64,19 +66,22 @@ type Bdcr = crate::pac::rcc::regs::Csr1;
64#[cfg(any(stm32c0))] 66#[cfg(any(stm32c0))]
65fn unlock() {} 67fn unlock() {}
66 68
67#[cfg(not(any(stm32c0)))] 69#[cfg(not(any(stm32c0, stm32n6)))]
68fn unlock() { 70fn unlock() {
69 #[cfg(any(stm32f0, stm32f1, stm32f2, stm32f3, stm32l0, stm32l1))] 71 #[cfg(any(stm32f0, stm32f1, stm32f2, stm32f3, stm32l0, stm32l1))]
70 let cr = crate::pac::PWR.cr(); 72 let cr = crate::pac::PWR.cr();
71 #[cfg(not(any(stm32f0, stm32f1, stm32f2, stm32f3, stm32l0, stm32l1, stm32u5, stm32h5, stm32wba)))] 73 #[cfg(not(any(
74 stm32f0, stm32f1, stm32f2, stm32f3, stm32l0, stm32l1, stm32u5, stm32h5, stm32wba, stm32n6
75 )))]
72 let cr = crate::pac::PWR.cr1(); 76 let cr = crate::pac::PWR.cr1();
73 #[cfg(any(stm32u5, stm32h5, stm32wba))] 77 #[cfg(any(stm32u5, stm32h5, stm32wba, stm32n6))]
74 let cr = crate::pac::PWR.dbpcr(); 78 let cr = crate::pac::PWR.dbpcr();
75 79
76 cr.modify(|w| w.set_dbp(true)); 80 cr.modify(|w| w.set_dbp(true));
77 while !cr.read().dbp() {} 81 while !cr.read().dbp() {}
78} 82}
79 83
84#[cfg(not(stm32n6))]
80fn bdcr() -> Reg<Bdcr, RW> { 85fn bdcr() -> Reg<Bdcr, RW> {
81 #[cfg(any(rtc_v2_l0, rtc_v2_l1))] 86 #[cfg(any(rtc_v2_l0, rtc_v2_l1))]
82 return crate::pac::RCC.csr(); 87 return crate::pac::RCC.csr();
@@ -150,6 +155,7 @@ impl Default for LsConfig {
150} 155}
151 156
152impl LsConfig { 157impl LsConfig {
158 #[cfg(not(stm32n6))]
153 pub(crate) fn init(&self) -> Option<Hertz> { 159 pub(crate) fn init(&self) -> Option<Hertz> {
154 let rtc_clk = match self.rtc { 160 let rtc_clk = match self.rtc {
155 RtcClockSource::LSI => { 161 RtcClockSource::LSI => {
@@ -185,14 +191,19 @@ impl LsConfig {
185 if self.lsi { 191 if self.lsi {
186 #[cfg(any(stm32u5, stm32h5, stm32wba))] 192 #[cfg(any(stm32u5, stm32h5, stm32wba))]
187 let csr = crate::pac::RCC.bdcr(); 193 let csr = crate::pac::RCC.bdcr();
188 #[cfg(not(any(stm32u5, stm32h5, stm32wba, stm32c0)))] 194 #[cfg(stm32n6)]
195 let csr = crate::pac::RCC.sr();
196 #[cfg(not(any(stm32u5, stm32h5, stm32wba, stm32c0, stm32n6)))]
189 let csr = crate::pac::RCC.csr(); 197 let csr = crate::pac::RCC.csr();
190 #[cfg(any(stm32c0))] 198 #[cfg(stm32c0)]
191 let csr = crate::pac::RCC.csr2(); 199 let csr = crate::pac::RCC.csr2();
192 200
193 #[cfg(not(any(rcc_wb, rcc_wba)))] 201 #[cfg(not(any(rcc_wb, rcc_wba, rcc_n6)))]
194 csr.modify(|w| w.set_lsion(true)); 202 csr.modify(|w| w.set_lsion(true));
195 203
204 #[cfg(rcc_n6)]
205 crate::pac::RCC.cr().modify(|w| w.set_lsion(true));
206
196 #[cfg(any(rcc_wb, rcc_wba))] 207 #[cfg(any(rcc_wb, rcc_wba))]
197 csr.modify(|w| w.set_lsi1on(true)); 208 csr.modify(|w| w.set_lsi1on(true));
198 209
@@ -222,25 +233,58 @@ impl LsConfig {
222 // backup domain configuration (LSEON, RTCEN, RTCSEL) is kept across resets. 233 // backup domain configuration (LSEON, RTCEN, RTCSEL) is kept across resets.
223 // once set, changing it requires a backup domain reset. 234 // once set, changing it requires a backup domain reset.
224 // first check if the configuration matches what we want. 235 // first check if the configuration matches what we want.
236 // N6 has all the fields spread across multiple registers under RCC.
225 237
226 // check if it's already enabled and in the source we want. 238 // check if it's already enabled and in the source we want.
239 #[cfg(not(rcc_n6))]
227 let reg = bdcr().read(); 240 let reg = bdcr().read();
241 #[cfg(rcc_n6)]
242 let reg = crate::pac::RCC.cr().read();
243 #[cfg(rcc_n6)]
244 let apb4lenr = crate::pac::RCC.apb4lenr().read();
245 #[cfg(rcc_n6)]
246 let ccipr7 = crate::pac::RCC.ccipr7().read();
247 #[cfg(rcc_n6)]
248 let lsecfgr = crate::pac::RCC.lsecfgr().read();
249
228 let mut ok = true; 250 let mut ok = true;
229 ok &= reg.rtcsel() == self.rtc; 251 #[cfg(not(rcc_n6))]
230 #[cfg(not(rcc_wba))] 252 {
253 ok &= reg.rtcsel() == self.rtc;
254 }
255 #[cfg(rcc_n6)]
256 {
257 ok &= ccipr7.rtcsel() == self.rtc;
258 }
259 #[cfg(not(any(rcc_wba, rcc_n6)))]
231 { 260 {
232 ok &= reg.rtcen() == (self.rtc != RtcClockSource::DISABLE); 261 ok &= reg.rtcen() == (self.rtc != RtcClockSource::DISABLE);
233 } 262 }
263 #[cfg(rcc_n6)]
264 {
265 ok &= apb4lenr.rtcen() == (self.rtc != RtcClockSource::DISABLE);
266 }
234 ok &= reg.lseon() == lse_en; 267 ok &= reg.lseon() == lse_en;
235 ok &= reg.lsebyp() == lse_byp; 268 #[cfg(not(rcc_n6))]
269 {
270 ok &= reg.lsebyp() == lse_byp;
271 }
272 #[cfg(rcc_n6)]
273 {
274 ok &= lsecfgr.lsebyp() == lse_byp;
275 }
236 #[cfg(any(rcc_l5, rcc_u5, rcc_wle, rcc_wl5, rcc_wba, rcc_u0))] 276 #[cfg(any(rcc_l5, rcc_u5, rcc_wle, rcc_wl5, rcc_wba, rcc_u0))]
237 if let Some(lse_sysen) = lse_sysen { 277 if let Some(lse_sysen) = lse_sysen {
238 ok &= reg.lsesysen() == lse_sysen; 278 ok &= reg.lsesysen() == lse_sysen;
239 } 279 }
240 #[cfg(not(any(rcc_f1, rcc_f1cl, rcc_f100, rcc_f2, rcc_f4, rcc_f410, rcc_l1)))] 280 #[cfg(not(any(rcc_f1, rcc_f1cl, rcc_f100, rcc_f2, rcc_f4, rcc_f410, rcc_l1, rcc_n6)))]
241 if let Some(lse_drv) = lse_drv { 281 if let Some(lse_drv) = lse_drv {
242 ok &= reg.lsedrv() == lse_drv.into(); 282 ok &= reg.lsedrv() == lse_drv.into();
243 } 283 }
284 #[cfg(rcc_n6)]
285 if let Some(lse_drv) = lse_drv {
286 ok &= lsecfgr.lsedrv() == lse_drv.into();
287 }
244 288
245 // if configuration is OK, we're done. 289 // if configuration is OK, we're done.
246 if ok { 290 if ok {
@@ -249,7 +293,7 @@ impl LsConfig {
249 } 293 }
250 294
251 // If not OK, reset backup domain and configure it. 295 // If not OK, reset backup domain and configure it.
252 #[cfg(not(any(rcc_l0, rcc_l0_v2, rcc_l1, stm32h5, stm32h7rs, stm32c0)))] 296 #[cfg(not(any(rcc_l0, rcc_l0_v2, rcc_l1, stm32h5, stm32h7rs, stm32c0, stm32n6)))]
253 { 297 {
254 bdcr().modify(|w| w.set_bdrst(true)); 298 bdcr().modify(|w| w.set_bdrst(true));
255 bdcr().modify(|w| w.set_bdrst(false)); 299 bdcr().modify(|w| w.set_bdrst(false));
@@ -262,7 +306,7 @@ impl LsConfig {
262 // STM32H503CB/EB/KB/RB device errata - 2.2.8 SRAM2 unduly erased upon a backup domain reset 306 // STM32H503CB/EB/KB/RB device errata - 2.2.8 SRAM2 unduly erased upon a backup domain reset
263 // STM32H562xx/563xx/573xx device errata - 2.2.14 SRAM2 is erased when the backup domain is reset 307 // STM32H562xx/563xx/573xx device errata - 2.2.14 SRAM2 is erased when the backup domain is reset
264 //#[cfg(any(stm32h5, stm32h7rs))] 308 //#[cfg(any(stm32h5, stm32h7rs))]
265 #[cfg(any(stm32h7rs))] 309 #[cfg(any(stm32h7rs, stm32n6))]
266 { 310 {
267 bdcr().modify(|w| w.set_vswrst(true)); 311 bdcr().modify(|w| w.set_vswrst(true));
268 bdcr().modify(|w| w.set_vswrst(false)); 312 bdcr().modify(|w| w.set_vswrst(false));
@@ -274,16 +318,31 @@ impl LsConfig {
274 } 318 }
275 319
276 if lse_en { 320 if lse_en {
277 bdcr().modify(|w| { 321 #[cfg(not(rcc_n6))]
278 #[cfg(not(any(rcc_f1, rcc_f1cl, rcc_f100, rcc_f2, rcc_f4, rcc_f410, rcc_l1)))] 322 {
279 if let Some(lse_drv) = lse_drv { 323 bdcr().modify(|w| {
280 w.set_lsedrv(lse_drv.into()); 324 #[cfg(not(any(rcc_f1, rcc_f1cl, rcc_f100, rcc_f2, rcc_f4, rcc_f410, rcc_l1)))]
281 } 325 if let Some(lse_drv) = lse_drv {
282 w.set_lsebyp(lse_byp); 326 w.set_lsedrv(lse_drv.into());
283 w.set_lseon(true); 327 }
284 }); 328 w.set_lsebyp(lse_byp);
329 w.set_lseon(true);
330 });
285 331
286 while !bdcr().read().lserdy() {} 332 while !bdcr().read().lserdy() {}
333 }
334 #[cfg(rcc_n6)]
335 {
336 crate::pac::RCC.lsecfgr().modify(|w| {
337 if let Some(lse_drv) = lse_drv {
338 w.set_lsedrv(lse_drv.into());
339 }
340 w.set_lsebyp(lse_byp);
341 });
342 crate::pac::RCC.cr().modify(|w| w.set_lseon(true));
343
344 while !crate::pac::RCC.sr().read().lserdy() {}
345 }
287 346
288 #[cfg(any(rcc_l5, rcc_u5, rcc_wle, rcc_wl5, rcc_wba, rcc_u0))] 347 #[cfg(any(rcc_l5, rcc_u5, rcc_wle, rcc_wl5, rcc_wba, rcc_u0))]
289 if let Some(lse_sysen) = lse_sysen { 348 if let Some(lse_sysen) = lse_sysen {
@@ -298,6 +357,7 @@ impl LsConfig {
298 } 357 }
299 358
300 if self.rtc != RtcClockSource::DISABLE { 359 if self.rtc != RtcClockSource::DISABLE {
360 #[cfg(not(rcc_n6))]
301 bdcr().modify(|w| { 361 bdcr().modify(|w| {
302 #[cfg(any(rtc_v2_h7, rtc_v2_l4, rtc_v2_wb, rtc_v3_base, rtc_v3_u5))] 362 #[cfg(any(rtc_v2_h7, rtc_v2_l4, rtc_v2_wb, rtc_v3_base, rtc_v3_u5))]
303 assert!(!w.lsecsson(), "RTC is not compatible with LSE CSS, yet."); 363 assert!(!w.lsecsson(), "RTC is not compatible with LSE CSS, yet.");
@@ -306,6 +366,12 @@ impl LsConfig {
306 w.set_rtcen(true); 366 w.set_rtcen(true);
307 w.set_rtcsel(self.rtc); 367 w.set_rtcsel(self.rtc);
308 }); 368 });
369
370 #[cfg(rcc_n6)]
371 {
372 crate::pac::RCC.ccipr7().modify(|w| w.set_rtcsel(self.rtc));
373 crate::pac::RCC.apb4lenr().modify(|w| w.set_rtcen(true))
374 }
309 } 375 }
310 376
311 trace!("BDCR configured: {:08x}", bdcr().read().0); 377 trace!("BDCR configured: {:08x}", bdcr().read().0);
diff --git a/embassy-stm32/src/rcc/mco.rs b/embassy-stm32/src/rcc/mco.rs
index 3d961df03..0624fdf26 100644
--- a/embassy-stm32/src/rcc/mco.rs
+++ b/embassy-stm32/src/rcc/mco.rs
@@ -16,7 +16,8 @@ pub use crate::pac::rcc::vals::Mcopre as McoPrescaler;
16 rcc_h7ab, 16 rcc_h7ab,
17 rcc_h7rm0433, 17 rcc_h7rm0433,
18 rcc_h7, 18 rcc_h7,
19 rcc_h7rs 19 rcc_h7rs,
20 rcc_n6
20)))] 21)))]
21pub use crate::pac::rcc::vals::Mcosel as McoSource; 22pub use crate::pac::rcc::vals::Mcosel as McoSource;
22#[cfg(any( 23#[cfg(any(
@@ -29,7 +30,8 @@ pub use crate::pac::rcc::vals::Mcosel as McoSource;
29 rcc_h7ab, 30 rcc_h7ab,
30 rcc_h7rm0433, 31 rcc_h7rm0433,
31 rcc_h7, 32 rcc_h7,
32 rcc_h7rs 33 rcc_h7rs,
34 rcc_n6
33))] 35))]
34pub use crate::pac::rcc::vals::{Mco1sel as Mco1Source, Mco2sel as Mco2Source}; 36pub use crate::pac::rcc::vals::{Mco1sel as Mco1Source, Mco2sel as Mco2Source};
35use crate::{Peri, peripherals}; 37use crate::{Peri, peripherals};
@@ -59,10 +61,12 @@ macro_rules! impl_peri {
59 type Source = $source; 61 type Source = $source;
60 62
61 unsafe fn _apply_clock_settings(source: Self::Source, _prescaler: McoPrescaler) { 63 unsafe fn _apply_clock_settings(source: Self::Source, _prescaler: McoPrescaler) {
62 #[cfg(not(any(stm32u5, stm32wba)))] 64 #[cfg(not(any(stm32u5, stm32wba, stm32n6)))]
63 let r = RCC.cfgr(); 65 let r = RCC.cfgr();
64 #[cfg(any(stm32u5, stm32wba))] 66 #[cfg(any(stm32u5, stm32wba))]
65 let r = RCC.cfgr1(); 67 let r = RCC.cfgr1();
68 #[cfg(any(stm32n6))]
69 let r = RCC.ccipr5();
66 70
67 r.modify(|w| { 71 r.modify(|w| {
68 w.$set_source(source); 72 w.$set_source(source);
diff --git a/embassy-stm32/src/rcc/mod.rs b/embassy-stm32/src/rcc/mod.rs
index 01fa3a475..592890777 100644
--- a/embassy-stm32/src/rcc/mod.rs
+++ b/embassy-stm32/src/rcc/mod.rs
@@ -28,6 +28,7 @@ pub use hsi48::*;
28#[cfg_attr(any(stm32l0, stm32l1, stm32l4, stm32l5, stm32wb, stm32wl, stm32u0), path = "l.rs")] 28#[cfg_attr(any(stm32l0, stm32l1, stm32l4, stm32l5, stm32wb, stm32wl, stm32u0), path = "l.rs")]
29#[cfg_attr(stm32u5, path = "u5.rs")] 29#[cfg_attr(stm32u5, path = "u5.rs")]
30#[cfg_attr(stm32wba, path = "wba.rs")] 30#[cfg_attr(stm32wba, path = "wba.rs")]
31#[cfg_attr(stm32n6, path = "n6.rs")]
31mod _version; 32mod _version;
32 33
33pub use _version::*; 34pub use _version::*;
diff --git a/embassy-stm32/src/rcc/n6.rs b/embassy-stm32/src/rcc/n6.rs
new file mode 100644
index 000000000..866851bbd
--- /dev/null
+++ b/embassy-stm32/src/rcc/n6.rs
@@ -0,0 +1,1046 @@
1use stm32_metapac::rcc::vals::{
2 Cpusw, Cpusws, Hseext, Hsitrim, Icint, Icsel, Msifreqsel, Plldivm, Pllmodssdis, Pllpdiv, Pllsel, Syssw, Syssws,
3 Timpre,
4};
5pub use stm32_metapac::rcc::vals::{
6 Hpre as AhbPrescaler, Hsidiv as HsiPrescaler, Hsitrim as HsiCalibration, Ppre as ApbPrescaler,
7};
8
9use crate::pac::{PWR, RCC, SYSCFG};
10use crate::time::Hertz;
11
12pub const HSI_FREQ: Hertz = Hertz(64_000_000);
13pub const LSE_FREQ: Hertz = Hertz(32_768);
14
15#[derive(Clone, Copy, Eq, PartialEq)]
16pub enum HseMode {
17 /// crystal/ceramic oscillator
18 Oscillator,
19 /// oscillator bypassed with external clock (analog)
20 Bypass,
21 /// oscillator bypassed with external digital clock
22 BypassDigital,
23}
24
25#[derive(Clone, Copy, Eq, PartialEq)]
26pub struct Hse {
27 /// HSE frequency.
28 pub freq: Hertz,
29 /// HSE oscillator mode.
30 pub mode: HseMode,
31}
32
33#[derive(Clone, Copy, Eq, PartialEq)]
34pub struct Hsi {
35 pub pre: HsiPrescaler,
36 pub trim: Hsitrim,
37}
38
39#[derive(Clone, Copy, PartialEq)]
40pub enum SupplyConfig {
41 Smps,
42 External,
43}
44
45#[derive(Clone, Copy, PartialEq)]
46pub enum CpuClk {
47 Hse,
48 Ic1 { source: Icsel, divider: Icint },
49 Msi,
50 Hsi,
51}
52
53impl CpuClk {
54 const fn to_bits(self) -> u8 {
55 match self {
56 Self::Hsi => 0x0,
57 Self::Msi => 0x1,
58 Self::Hse => 0x2,
59 Self::Ic1 { .. } => 0x3,
60 }
61 }
62}
63
64#[derive(Clone, Copy, PartialEq)]
65pub struct IcConfig {
66 source: Icsel,
67 divider: Icint,
68}
69
70#[derive(Clone, Copy, PartialEq)]
71pub enum SysClk {
72 Hse,
73 Ic2 {
74 ic2: IcConfig,
75 ic6: IcConfig,
76 ic11: IcConfig,
77 },
78 Msi,
79 Hsi,
80}
81
82impl SysClk {
83 const fn to_bits(self) -> u8 {
84 match self {
85 Self::Hsi => 0x0,
86 Self::Msi => 0x1,
87 Self::Hse => 0x2,
88 Self::Ic2 { .. } => 0x3,
89 }
90 }
91}
92
93#[derive(Clone, Copy, PartialEq)]
94pub struct Msi {
95 pub freq: Msifreqsel,
96 pub trim: u8,
97}
98
99#[derive(Clone, Copy, PartialEq)]
100pub enum Pll {
101 Oscillator {
102 source: Pllsel,
103 divm: Plldivm,
104 fractional: u32,
105 divn: u16,
106 divp1: Pllpdiv,
107 divp2: Pllpdiv,
108 },
109 Bypass {
110 source: Pllsel,
111 },
112}
113
114/// Configuration of the core clocks
115#[non_exhaustive]
116#[derive(Clone, Copy)]
117pub struct Config {
118 pub hsi: Option<Hsi>,
119 pub hse: Option<Hse>,
120 pub msi: Option<Msi>,
121 pub lsi: bool,
122 pub lse: bool,
123
124 pub sys: SysClk,
125 pub cpu: CpuClk,
126
127 pub pll1: Option<Pll>,
128 pub pll2: Option<Pll>,
129 pub pll3: Option<Pll>,
130 pub pll4: Option<Pll>,
131
132 pub ahb: AhbPrescaler,
133 pub apb1: ApbPrescaler,
134 pub apb2: ApbPrescaler,
135 pub apb4: ApbPrescaler,
136 pub apb5: ApbPrescaler,
137
138 pub supply_config: SupplyConfig,
139}
140
141impl Config {
142 pub const fn new() -> Self {
143 Self {
144 hsi: Some(Hsi {
145 pre: HsiPrescaler::DIV1,
146 trim: HsiCalibration::from_bits(32),
147 }),
148 hse: None,
149 msi: None,
150 lsi: true,
151 lse: false,
152 sys: SysClk::Hsi,
153 cpu: CpuClk::Hsi,
154 pll1: Some(Pll::Bypass { source: Pllsel::HSI }),
155 pll2: Some(Pll::Bypass { source: Pllsel::HSI }),
156 pll3: Some(Pll::Bypass { source: Pllsel::HSI }),
157 pll4: Some(Pll::Bypass { source: Pllsel::HSI }),
158
159 ahb: AhbPrescaler::DIV2,
160 apb1: ApbPrescaler::DIV1,
161 apb2: ApbPrescaler::DIV1,
162 apb4: ApbPrescaler::DIV1,
163 apb5: ApbPrescaler::DIV1,
164
165 supply_config: SupplyConfig::Smps,
166 }
167 }
168}
169
170#[allow(dead_code)]
171struct ClocksOutput {
172 cpuclk: Hertz,
173 sysclk: Hertz,
174 pclk_tim: Hertz,
175 ahb: Hertz,
176 apb1: Hertz,
177 apb2: Hertz,
178 apb4: Hertz,
179 apb5: Hertz,
180}
181
182struct ClocksInput {
183 hsi: Option<Hertz>,
184 msi: Option<Hertz>,
185 hse: Option<Hertz>,
186}
187
188fn init_clocks(config: Config, input: &ClocksInput) -> ClocksOutput {
189 // handle increasing dividers
190 debug!("configuring increasing pclk dividers");
191 RCC.cfgr2().modify(|w| {
192 if config.apb1 > w.ppre1() {
193 debug!(" - APB1");
194 w.set_ppre1(config.apb1);
195 }
196 if config.apb2 > w.ppre2() {
197 debug!(" - APB2");
198 w.set_ppre2(config.apb2);
199 }
200 if config.apb4 > w.ppre4() {
201 debug!(" - APB4");
202 w.set_ppre4(config.apb4);
203 }
204 if config.apb5 > w.ppre5() {
205 debug!(" - APB5");
206 w.set_ppre5(config.apb5);
207 }
208 if config.ahb > w.hpre() {
209 debug!(" - AHB");
210 w.set_hpre(config.ahb);
211 }
212 });
213 // cpuclk
214 debug!("configuring cpuclk");
215 match config.cpu {
216 CpuClk::Hse if !RCC.sr().read().hserdy() => panic!("HSE is not ready to be selected as CPU clock source"),
217 CpuClk::Ic1 { source, divider } => {
218 if !pll_sources_ready(RCC.iccfgr(0).read().icsel().to_bits(), source.to_bits()) {
219 panic!("ICx clock switch requires both origin and destination clock source to be active")
220 }
221
222 RCC.iccfgr(0).write(|w| {
223 w.set_icsel(source);
224 w.set_icint(divider);
225 });
226 RCC.divensr().modify(|w| w.set_ic1ens(true));
227 }
228 CpuClk::Msi if !RCC.sr().read().msirdy() => panic!("MSI is not ready to be selected as CPU clock source"),
229 CpuClk::Hsi if !RCC.sr().read().hsirdy() => panic!("HSI is not ready to be selected as CPU clock source"),
230 _ => {}
231 }
232 // set source
233 let cpusw = Cpusw::from_bits(config.cpu.to_bits());
234 RCC.cfgr().modify(|w| w.set_cpusw(cpusw));
235 // wait for changes to take effect
236 while RCC.cfgr().read().cpusws() != Cpusws::from_bits(config.cpu.to_bits()) {}
237
238 // sysclk
239 debug!("configuring sysclk");
240 match config.sys {
241 SysClk::Hse if !RCC.sr().read().hserdy() => panic!("HSE is not ready to be selected as CPU clock source"),
242 SysClk::Ic2 { ic2, ic6, ic11 } => {
243 if !pll_sources_ready(RCC.iccfgr(1).read().icsel().to_bits(), ic2.source.to_bits()) {
244 panic!("IC2 clock switch requires both origin and destination clock source to be active")
245 }
246 if !pll_sources_ready(RCC.iccfgr(5).read().icsel().to_bits(), ic6.source.to_bits()) {
247 panic!("IC6 clock switch requires both origin and destination clock source to be active")
248 }
249 if !pll_sources_ready(RCC.iccfgr(10).read().icsel().to_bits(), ic11.source.to_bits()) {
250 panic!("IC11 clock switch requires both origin and destination clock source to be active")
251 }
252
253 RCC.iccfgr(1).write(|w| {
254 w.set_icsel(ic2.source);
255 w.set_icint(ic2.divider);
256 });
257 RCC.iccfgr(5).write(|w| {
258 w.set_icsel(ic6.source);
259 w.set_icint(ic6.divider);
260 });
261 RCC.iccfgr(10).write(|w| {
262 w.set_icsel(ic11.source);
263 w.set_icint(ic11.divider);
264 });
265 RCC.divensr().modify(|w| {
266 w.set_ic2ens(true);
267 w.set_ic6ens(true);
268 w.set_ic11ens(true);
269 });
270 }
271 SysClk::Msi if !RCC.sr().read().msirdy() => panic!("MSI is not ready to be selected as CPU clock source"),
272 SysClk::Hsi if !RCC.sr().read().hsirdy() => panic!("HSI is not ready to be selected as CPU clock source"),
273 _ => {}
274 }
275 // switch the system bus clock
276 let syssw = Syssw::from_bits(config.sys.to_bits());
277 RCC.cfgr().modify(|w| w.set_syssw(syssw));
278 // wait for changes to be applied
279 while RCC.cfgr().read().syssws() != Syssws::from_bits(config.sys.to_bits()) {}
280
281 // decreasing dividers
282 debug!("configuring decreasing pclk dividers");
283 RCC.cfgr2().modify(|w| {
284 if config.ahb < w.hpre() {
285 debug!(" - AHB");
286 w.set_hpre(config.ahb);
287 }
288 if config.apb1 < w.ppre1() {
289 debug!(" - APB1");
290 w.set_ppre1(config.apb1);
291 }
292 if config.apb2 < w.ppre2() {
293 debug!(" - APB2");
294 w.set_ppre2(config.apb2);
295 }
296 if config.apb4 < w.ppre4() {
297 debug!(" - APB4");
298 w.set_ppre4(config.apb4);
299 }
300 if config.apb5 < w.ppre5() {
301 debug!(" - APB5");
302 w.set_ppre5(config.apb5);
303 }
304 });
305
306 let cpuclk = match config.cpu {
307 CpuClk::Hsi => unwrap!(input.hsi),
308 CpuClk::Msi => unwrap!(input.msi),
309 CpuClk::Hse => unwrap!(input.hse),
310 CpuClk::Ic1 { .. } => todo!(),
311 };
312
313 let sysclk = match config.sys {
314 SysClk::Hsi => unwrap!(input.hsi),
315 SysClk::Msi => unwrap!(input.msi),
316 SysClk::Hse => unwrap!(input.hse),
317 SysClk::Ic2 { .. } => todo!(),
318 };
319
320 let timpre: u32 = match RCC.cfgr2().read().timpre() {
321 Timpre::DIV1 => 1,
322 Timpre::DIV2 => 2,
323 Timpre::DIV4 => 4,
324 Timpre::_RESERVED_3 => 8,
325 };
326
327 let hpre = periph_prescaler_to_value(config.ahb.to_bits());
328 let ppre1 = periph_prescaler_to_value(config.apb1.to_bits());
329 let ppre2 = periph_prescaler_to_value(config.apb2.to_bits());
330 let ppre4 = periph_prescaler_to_value(config.apb4.to_bits());
331 let ppre5 = periph_prescaler_to_value(config.apb5.to_bits());
332
333 // enable all peripherals in sleep mode
334 enable_low_power_peripherals();
335
336 // enable interrupts
337 unsafe {
338 core::arch::asm!("cpsie i");
339 }
340
341 ClocksOutput {
342 sysclk,
343 cpuclk,
344 pclk_tim: sysclk / timpre,
345 ahb: Hertz(sysclk.0 / hpre as u32),
346 apb1: sysclk / hpre / ppre1,
347 apb2: sysclk / hpre / ppre2,
348 apb4: sysclk / hpre / ppre4,
349 apb5: sysclk / hpre / ppre5,
350 }
351}
352
353fn enable_low_power_peripherals() {
354 // AHB1-5
355 RCC.ahb1lpenr().modify(|w| {
356 w.set_adc12lpen(true);
357 w.set_gpdma1lpen(true);
358 });
359 RCC.ahb2lpenr().modify(|w| {
360 w.set_adf1lpen(true);
361 w.set_mdf1lpen(true);
362 w.set_ramcfglpen(true);
363 });
364 RCC.ahb3lpenr().modify(|w| {
365 w.set_risaflpen(true);
366 w.set_iaclpen(true);
367 w.set_rifsclpen(true);
368 w.set_pkalpen(true);
369 w.set_saeslpen(true);
370 w.set_cryplpen(true);
371 w.set_hashlpen(true);
372 w.set_rnglpen(true);
373 });
374 RCC.ahb4lpenr().modify(|w| {
375 w.set_crclpen(true);
376 w.set_pwrlpen(true);
377 w.set_gpioqlpen(true);
378 w.set_gpioplpen(true);
379 w.set_gpioolpen(true);
380 w.set_gpionlpen(true);
381 w.set_gpiohlpen(true);
382 w.set_gpioglpen(true);
383 w.set_gpioflpen(true);
384 w.set_gpioelpen(true);
385 w.set_gpiodlpen(true);
386 w.set_gpioclpen(true);
387 w.set_gpioblpen(true);
388 w.set_gpioalpen(true);
389 });
390 RCC.ahb5lpenr().modify(|w| {
391 w.set_npulpen(true);
392 w.set_npucachelpen(true);
393 w.set_otg2lpen(true);
394 w.set_otgphy2lpen(true);
395 w.set_otgphy1lpen(true);
396 w.set_otg1lpen(true);
397 w.set_eth1lpen(true);
398 w.set_eth1rxlpen(true);
399 w.set_eth1txlpen(true);
400 w.set_eth1maclpen(true);
401 w.set_gpulpen(true);
402 w.set_gfxmmulpen(true);
403 w.set_mce4lpen(true);
404 w.set_xspi3lpen(true);
405 w.set_mce3lpen(true);
406 w.set_mce2lpen(true);
407 w.set_mce1lpen(true);
408 w.set_xspimlpen(true);
409 w.set_xspi2lpen(true);
410 w.set_sdmmc1lpen(true);
411 w.set_sdmmc2lpen(true);
412 w.set_pssilpen(true);
413 w.set_xspi1lpen(true);
414 w.set_fmclpen(true);
415 w.set_jpeglpen(true);
416 w.set_dma2dlpen(true);
417 w.set_hpdma1lpen(true);
418 });
419
420 // APB1-5
421 RCC.apb1llpenr().modify(|w| {
422 w.set_uart8lpen(true);
423 w.set_uart7lpen(true);
424 w.set_i3c2lpen(true);
425 w.set_i3c1lpen(true);
426 w.set_i2c3lpen(true);
427 w.set_i2c2lpen(true);
428 w.set_i2c1lpen(true);
429 w.set_uart5lpen(true);
430 w.set_uart4lpen(true);
431 w.set_usart3lpen(true);
432 w.set_usart2lpen(true);
433 w.set_spdifrx1lpen(true);
434 w.set_spi3lpen(true);
435 w.set_spi2lpen(true);
436 w.set_tim11lpen(true);
437 w.set_tim10lpen(true);
438 w.set_wwdglpen(true);
439 w.set_lptim1lpen(true);
440 w.set_tim14lpen(true);
441 w.set_tim13lpen(true);
442 w.set_tim12lpen(true);
443 w.set_tim7lpen(true);
444 w.set_tim6lpen(true);
445 w.set_tim5lpen(true);
446 w.set_tim4lpen(true);
447 w.set_tim3lpen(true);
448 w.set_tim2lpen(true);
449 });
450 RCC.apb1hlpenr().modify(|w| {
451 w.set_ucpd1lpen(true);
452 w.set_fdcanlpen(true);
453 w.set_mdioslpen(true);
454 });
455 RCC.apb2lpenr().modify(|w| {
456 w.set_sai2lpen(true);
457 w.set_sai1lpen(true);
458 w.set_spi5lpen(true);
459 w.set_tim9lpen(true);
460 w.set_tim17lpen(true);
461 w.set_tim16lpen(true);
462 w.set_tim15lpen(true);
463 w.set_tim18lpen(true);
464 w.set_spi4lpen(true);
465 w.set_spi1lpen(true);
466 w.set_usart10lpen(true);
467 w.set_uart9lpen(true);
468 w.set_usart6lpen(true);
469 w.set_usart1lpen(true);
470 w.set_tim8lpen(true);
471 w.set_tim1lpen(true);
472 });
473 RCC.apb3lpenr().modify(|w| {
474 w.set_dftlpen(true);
475 });
476 RCC.apb4llpenr().modify(|w| {
477 w.set_rtcapblpen(true);
478 w.set_rtclpen(true);
479 w.set_vrefbuflpen(true);
480 w.set_lptim5lpen(true);
481 w.set_lptim4lpen(true);
482 w.set_lptim3lpen(true);
483 w.set_lptim2lpen(true);
484 w.set_i2c4lpen(true);
485 w.set_spi6lpen(true);
486 w.set_lpuart1lpen(true);
487 w.set_hdplpen(true);
488 });
489 RCC.apb4hlpenr().modify(|w| {
490 w.set_dtslpen(true);
491 w.set_bseclpen(true);
492 w.set_syscfglpen(true);
493 });
494 RCC.apb5lpenr().modify(|w| {
495 w.set_csilpen(true);
496 w.set_venclpen(true);
497 w.set_gfxtimlpen(true);
498 w.set_dcmilpen(true);
499 w.set_ltdclpen(true);
500 });
501
502 RCC.buslpenr().modify(|w| {
503 w.set_aclknclpen(true);
504 w.set_aclknlpen(true);
505 });
506
507 RCC.memlpenr().modify(|w| {
508 w.set_bootromlpen(true);
509 w.set_vencramlpen(true);
510 w.set_npucacheramlpen(true);
511 w.set_flexramlpen(true);
512 w.set_axisram2lpen(true);
513 w.set_axisram1lpen(true);
514 w.set_bkpsramlpen(true);
515 w.set_ahbsram2lpen(true);
516 w.set_ahbsram1lpen(true);
517 w.set_axisram6lpen(true);
518 w.set_axisram5lpen(true);
519 w.set_axisram4lpen(true);
520 w.set_axisram3lpen(true);
521 });
522
523 RCC.misclpenr().modify(|w| {
524 w.set_perlpen(true);
525 w.set_xspiphycomplpen(true);
526 w.set_dbglpen(true);
527 });
528}
529
530const fn periph_prescaler_to_value(bits: u8) -> u8 {
531 match bits {
532 0 => 1,
533 1 => 2,
534 2 => 4,
535 3 => 8,
536 4 => 16,
537 5 => 32,
538 6 => 64,
539 7.. => 128,
540 }
541}
542
543fn pll_source_ready(source: u8) -> bool {
544 match source {
545 0x0 if !RCC.sr().read().pllrdy(0) && !RCC.pllcfgr1(0).read().pllbyp() => false,
546 0x1 if !RCC.sr().read().pllrdy(1) && !RCC.pllcfgr1(1).read().pllbyp() => false,
547 0x2 if !RCC.sr().read().pllrdy(2) && !RCC.pllcfgr1(2).read().pllbyp() => false,
548 0x3 if !RCC.sr().read().pllrdy(3) && !RCC.pllcfgr1(3).read().pllbyp() => false,
549 _ => true,
550 }
551}
552
553fn pll_sources_ready(source1: u8, source2: u8) -> bool {
554 pll_source_ready(source1) && pll_source_ready(source2)
555}
556
557impl Default for Config {
558 fn default() -> Self {
559 Self::new()
560 }
561}
562
563fn power_supply_config(supply_config: SupplyConfig) {
564 // power supply config
565 PWR.cr1().modify(|w| {
566 w.set_sden(match supply_config {
567 SupplyConfig::External => false,
568 SupplyConfig::Smps => true,
569 });
570 });
571
572 // Validate supply configuration
573 while !PWR.voscr().read().actvosrdy() {}
574}
575
576struct PllInput {
577 hsi: Option<Hertz>,
578 msi: Option<Hertz>,
579 hse: Option<Hertz>,
580 i2s_ckin: Option<Hertz>,
581}
582
583#[derive(Clone, Copy, Default)]
584#[allow(dead_code)]
585struct PllOutput {
586 divm: Option<Hertz>,
587 divn: Option<Hertz>,
588 divp1: Option<Hertz>,
589 divp2: Option<Hertz>,
590 output: Option<Hertz>,
591}
592
593fn init_pll(pll_config: Option<Pll>, pll_index: usize, input: &PllInput) -> PllOutput {
594 let cfgr1 = RCC.pllcfgr1(pll_index);
595 let cfgr2 = RCC.pllcfgr2(pll_index);
596 let cfgr3 = RCC.pllcfgr3(pll_index);
597
598 match pll_config {
599 Some(Pll::Oscillator {
600 source,
601 divm,
602 fractional,
603 divn,
604 divp1,
605 divp2,
606 }) => {
607 // ensure pll is disabled
608 RCC.ccr().write(|w| w.set_pllonc(pll_index, true));
609 while RCC.sr().read().pllrdy(pll_index) {}
610
611 // ensure PLLxMODSSDIS=1 to work in fractional mode
612 cfgr3.modify(|w| w.set_pllmodssdis(Pllmodssdis::FRACTIONAL_DIVIDE));
613 // clear bypass mode
614 cfgr1.modify(|w| w.set_pllbyp(false));
615 // configure the pll clock source, mul and div factors
616 cfgr1.modify(|w| {
617 w.set_pllsel(source);
618 w.set_plldivm(divm);
619 w.set_plldivn(divn);
620 });
621
622 let in_clk = match source {
623 Pllsel::HSI => unwrap!(input.hsi),
624 Pllsel::MSI => unwrap!(input.msi),
625 Pllsel::HSE => unwrap!(input.hse),
626 Pllsel::I2S_CKIN => unwrap!(input.i2s_ckin),
627 _ => panic!("reserved PLL source not allowed"),
628 };
629
630 let m = divm.to_bits() as u32;
631 let n = divn as u32;
632
633 cfgr3.modify(|w| {
634 w.set_pllpdiv1(divp1);
635 w.set_pllpdiv2(divp2);
636 });
637
638 let p1 = divp1.to_bits() as u32;
639 let p2 = divp2.to_bits() as u32;
640
641 // configure pll divnfrac
642 cfgr2.modify(|w| w.set_plldivnfrac(fractional));
643 // clear pllxmoddsen
644 cfgr3.modify(|w| w.set_pllmoddsen(false));
645 // fractional mode
646 if fractional != 0 {
647 cfgr3.modify(|w| {
648 w.set_pllmoddsen(true);
649 w.set_plldacen(true);
650 })
651 }
652 // enable pll post divider output
653 cfgr3.modify(|w| {
654 w.set_pllmodssrst(true);
655 w.set_pllpdiven(true);
656 });
657 // enable the pll
658 RCC.csr().write(|w| w.pllons(pll_index));
659 // wait until ready
660 while RCC.sr().read().pllrdy(pll_index) {}
661
662 PllOutput {
663 divm: Some(Hertz(m)),
664 divn: Some(Hertz(n)),
665 divp1: Some(Hertz(p1)),
666 divp2: Some(Hertz(p2)),
667 output: Some(Hertz(in_clk.0 / m / n / p1 / p2)),
668 }
669 }
670 Some(Pll::Bypass { source }) => {
671 // check if source is ready
672 if !pll_source_ready(source.to_bits()) {
673 panic!("PLL source is not ready")
674 }
675
676 // ensure pll is disabled
677 RCC.ccr().write(|w| w.set_pllonc(pll_index, true));
678 while RCC.sr().read().pllrdy(pll_index) {}
679
680 cfgr1.modify(|w| {
681 w.set_pllbyp(true);
682 w.set_pllsel(source);
683 });
684
685 let in_clk = match source {
686 Pllsel::HSI => unwrap!(input.hsi),
687 Pllsel::MSI => unwrap!(input.msi),
688 Pllsel::HSE => unwrap!(input.hse),
689 Pllsel::I2S_CKIN => unwrap!(input.i2s_ckin),
690 _ => panic!("reserved PLL source not allowed"),
691 };
692
693 PllOutput {
694 output: Some(in_clk),
695 ..Default::default()
696 }
697 }
698 None => {
699 cfgr3.modify(|w| w.set_pllpdiven(false));
700 RCC.ccr().write(|w| w.set_pllonc(pll_index, true));
701 // wait till disabled
702 while RCC.sr().read().pllrdy(pll_index) {}
703
704 // clear bypass mode
705 cfgr1.modify(|w| w.set_pllbyp(false));
706
707 PllOutput::default()
708 }
709 }
710}
711
712#[allow(dead_code)]
713struct OscOutput {
714 hsi: Option<Hertz>,
715 hse: Option<Hertz>,
716 msi: Option<Hertz>,
717 lsi: Option<Hertz>,
718 lse: Option<Hertz>,
719 pll1: Option<Hertz>,
720 pll2: Option<Hertz>,
721 pll3: Option<Hertz>,
722 pll4: Option<Hertz>,
723 ic1sel: Icsel,
724 ic2sel: Icsel,
725 ic6sel: Icsel,
726 ic11sel: Icsel,
727}
728
729fn init_osc(config: Config) -> OscOutput {
730 let (cpu_src, sys_src) = {
731 let reg = RCC.cfgr().read();
732 (reg.cpusws(), reg.syssws())
733 };
734 let pll1_src = RCC.pllcfgr1(0).read().pllsel();
735 let pll2_src = RCC.pllcfgr1(1).read().pllsel();
736 let pll3_src = RCC.pllcfgr1(2).read().pllsel();
737 let pll4_src = RCC.pllcfgr1(3).read().pllsel();
738 let rcc_sr = RCC.sr().read();
739
740 debug!("configuring HSE");
741
742 // hse configuration
743 let hse = if let Some(hse) = config.hse {
744 match hse.mode {
745 HseMode::Oscillator => {
746 debug!("HSE in oscillator mode");
747 }
748 HseMode::Bypass => {
749 debug!("HSE in bypass mode");
750 RCC.hsecfgr().modify(|w| {
751 w.set_hsebyp(true);
752 w.set_hseext(Hseext::ANALOG);
753 });
754 }
755 HseMode::BypassDigital => {
756 debug!("HSE in bypass digital mode");
757 RCC.hsecfgr().modify(|w| {
758 w.set_hsebyp(true);
759 w.set_hseext(Hseext::DIGITAL);
760 });
761 }
762 }
763 RCC.csr().write(|w| w.set_hseons(true));
764
765 // wait until the hse is ready
766 while !RCC.sr().read().hserdy() {}
767
768 Some(hse.freq)
769 } else if cpu_src == Cpusws::HSE
770 || sys_src == Syssws::HSE
771 || (pll1_src == Pllsel::HSE && rcc_sr.pllrdy(0))
772 || (pll2_src == Pllsel::HSE && rcc_sr.pllrdy(1))
773 || (pll3_src == Pllsel::HSE && rcc_sr.pllrdy(2))
774 || (pll4_src == Pllsel::HSE && rcc_sr.pllrdy(3))
775 {
776 panic!(
777 "When the HSE is used as cpu/system bus clock or clock source for any PLL, it is not allowed to be disabled"
778 );
779 } else {
780 debug!("HSE off");
781
782 RCC.ccr().write(|w| w.set_hseonc(true));
783 RCC.hsecfgr().modify(|w| {
784 w.set_hseext(Hseext::ANALOG);
785 w.set_hsebyp(false);
786 });
787
788 // wait until the hse is disabled
789 while RCC.sr().read().hserdy() {}
790
791 None
792 };
793
794 // hsi configuration
795 debug!("configuring HSI");
796 let hsi = if let Some(hsi) = config.hsi {
797 RCC.csr().write(|w| w.set_hsions(true));
798 while !RCC.sr().read().hsirdy() {}
799
800 // set divider and calibration
801 RCC.hsicfgr().modify(|w| {
802 w.set_hsidiv(hsi.pre);
803 w.set_hsitrim(hsi.trim);
804 });
805
806 Some(HSI_FREQ / hsi.pre)
807 } else if cpu_src == Cpusws::HSI
808 || sys_src == Syssws::HSI
809 || (pll1_src == Pllsel::HSI && rcc_sr.pllrdy(0))
810 || (pll2_src == Pllsel::HSI && rcc_sr.pllrdy(1))
811 || (pll3_src == Pllsel::HSI && rcc_sr.pllrdy(2))
812 || (pll4_src == Pllsel::HSI && rcc_sr.pllrdy(3))
813 {
814 panic!(
815 "When the HSI is used as cpu/system bus clock or clock source for any PLL, it is not allowed to be disabled"
816 );
817 } else {
818 debug!("HSI off");
819
820 RCC.ccr().write(|w| w.set_hsionc(true));
821 while RCC.sr().read().hsirdy() {}
822
823 None
824 };
825
826 // msi configuration
827 debug!("configuring MSI");
828 let msi = if let Some(msi) = config.msi {
829 RCC.msicfgr().modify(|w| w.set_msifreqsel(msi.freq));
830 RCC.csr().write(|w| w.set_msions(true));
831 while !RCC.sr().read().msirdy() {}
832 RCC.msicfgr().modify(|w| w.set_msitrim(msi.trim));
833
834 Some(match msi.freq {
835 Msifreqsel::_4MHZ => Hertz::mhz(4),
836 Msifreqsel::_16MHZ => Hertz::mhz(16),
837 })
838 } else if cpu_src == Cpusws::MSI
839 || sys_src == Syssws::MSI
840 || (pll1_src == Pllsel::MSI && rcc_sr.pllrdy(0))
841 || (pll2_src == Pllsel::MSI && rcc_sr.pllrdy(1))
842 || (pll3_src == Pllsel::MSI && rcc_sr.pllrdy(2))
843 || (pll4_src == Pllsel::MSI && rcc_sr.pllrdy(3))
844 {
845 panic!(
846 "When the MSI is used as cpu/system bus clock or clock source for any PLL, it is not allowed to be disabled"
847 );
848 } else {
849 RCC.ccr().write(|w| w.set_msionc(true));
850 while RCC.sr().read().msirdy() {}
851
852 None
853 };
854
855 // lsi configuration
856 debug!("configuring LSI");
857 let lsi = if config.lsi {
858 RCC.csr().write(|w| w.set_lsions(true));
859 while !RCC.sr().read().lsirdy() {}
860 Some(super::LSI_FREQ)
861 } else {
862 RCC.ccr().write(|w| w.set_lsionc(true));
863 while RCC.sr().read().lsirdy() {}
864 None
865 };
866
867 // lse configuration
868 debug!("configuring LSE");
869 let lse = if config.lse {
870 RCC.csr().write(|w| w.set_lseons(true));
871 while !RCC.sr().read().lserdy() {}
872 Some(LSE_FREQ)
873 } else {
874 RCC.ccr().write(|w| w.set_lseonc(true));
875 while RCC.sr().read().lserdy() {}
876 None
877 };
878
879 let pll_input = PllInput {
880 hse,
881 msi,
882 hsi,
883 i2s_ckin: None,
884 };
885
886 // pll1,2,3,4 config
887 let pll_configs = [config.pll1, config.pll2, config.pll3, config.pll4];
888 let mut pll_outputs: [PllOutput; 4] = [PllOutput::default(); 4];
889
890 let ic1_src = RCC.iccfgr(0).read().icsel();
891 let ic2_src = RCC.iccfgr(1).read().icsel();
892 let ic6_src = RCC.iccfgr(5).read().icsel();
893 let ic11_src = RCC.iccfgr(10).read().icsel();
894
895 for (n, (&pll, out)) in pll_configs.iter().zip(pll_outputs.iter_mut()).enumerate() {
896 debug!("configuring PLL{}", n + 1);
897 let pll_ready = RCC.sr().read().pllrdy(n);
898
899 if is_new_pll_config(pll, 0) {
900 let this_pll = Icsel::from_bits(n as u8);
901
902 if cpu_src == Cpusws::IC1 && ic1_src == this_pll {
903 panic!("PLL should not be disabled / reconfigured if used for IC1 (cpuclksrc)")
904 }
905
906 if sys_src == Syssws::IC2 && (ic2_src == this_pll || ic6_src == this_pll || ic11_src == this_pll) {
907 panic!("PLL should not be disabled / reconfigured if used for IC2, IC6 or IC11 (sysclksrc)")
908 }
909
910 *out = init_pll(pll, 0, &pll_input);
911 } else if pll.is_some() && !pll_ready {
912 RCC.csr().write(|w| w.pllons(n));
913 while !RCC.sr().read().pllrdy(n) {}
914 }
915 }
916
917 OscOutput {
918 hsi,
919 hse,
920 msi,
921 lsi,
922 lse,
923 pll1: pll_outputs[0].output,
924 pll2: pll_outputs[1].output,
925 pll3: pll_outputs[2].output,
926 pll4: pll_outputs[3].output,
927 ic1sel: ic1_src,
928 ic2sel: ic2_src,
929 ic6sel: ic6_src,
930 ic11sel: ic11_src,
931 }
932}
933
934fn is_new_pll_config(pll: Option<Pll>, pll_index: usize) -> bool {
935 let cfgr1 = RCC.pllcfgr1(pll_index).read();
936 let cfgr2 = RCC.pllcfgr2(pll_index).read();
937 let cfgr3 = RCC.pllcfgr3(pll_index).read();
938
939 let ready = RCC.sr().read().pllrdy(pll_index);
940 let bypass = cfgr1.pllbyp();
941
942 match (pll, ready, bypass) {
943 (None, true, _) => return true,
944 (Some(_), false, _) => return true,
945 (Some(conf), true, bypass) => match (conf, bypass) {
946 (Pll::Bypass { .. }, false) => return true,
947 (Pll::Oscillator { .. }, true) => return true,
948 _ => {}
949 },
950 _ => {}
951 }
952
953 match pll {
954 Some(Pll::Bypass { source }) => cfgr1.pllsel() != source,
955 Some(Pll::Oscillator {
956 source,
957 divm: m,
958 fractional,
959 divn: n,
960 divp1: p1,
961 divp2: p2,
962 }) => {
963 cfgr1.pllsel() != source
964 || cfgr1.plldivm() != m
965 || cfgr1.plldivn() != n
966 || cfgr2.plldivnfrac() != fractional
967 || cfgr3.pllpdiv1() != p1
968 || cfgr3.pllpdiv2() != p2
969 }
970 None => false,
971 }
972}
973
974pub(crate) unsafe fn init(config: Config) {
975 debug!("enabling SYSCFG");
976 // system configuration setup
977 RCC.apb4hensr().write(|w| w.set_syscfgens(true));
978 // delay after RCC peripheral clock enabling
979 RCC.apb4hensr().read();
980
981 debug!("setting VTOR");
982
983 let vtor = unsafe {
984 let p = cortex_m::Peripherals::steal();
985 p.SCB.vtor.read()
986 };
987
988 // set default vector table location after reset or standby
989 SYSCFG.initsvtorcr().write(|w| w.set_svtor_addr(vtor));
990 // read back the value to ensure it is written before deactivating SYSCFG
991 SYSCFG.initsvtorcr().read();
992
993 debug!("deactivating SYSCFG");
994
995 // deactivate SYSCFG
996 RCC.apb4hensr().write(|w| w.set_syscfgens(false));
997
998 debug!("enabling FPU");
999
1000 // enable fpu
1001 unsafe {
1002 let p = cortex_m::Peripherals::steal();
1003 p.SCB.cpacr.modify(|w| w | (3 << 20) | (3 << 22));
1004 }
1005
1006 debug!("setting power supply config");
1007
1008 power_supply_config(config.supply_config);
1009
1010 let osc = init_osc(config);
1011 let clock_inputs = ClocksInput {
1012 hsi: osc.hsi,
1013 msi: osc.msi,
1014 hse: osc.hse,
1015 };
1016 let clocks = init_clocks(config, &clock_inputs);
1017
1018 // TODO: sysb, sysc, sysd must have the same clock source
1019
1020 set_clocks!(
1021 sys: Some(clocks.sysclk),
1022 hsi: osc.hsi,
1023 hsi_div: None,
1024 hse: osc.hse,
1025 msi: osc.msi,
1026 hclk1: Some(clocks.ahb),
1027 hclk2: Some(clocks.ahb),
1028 hclk3: Some(clocks.ahb),
1029 hclk4: Some(clocks.ahb),
1030 hclk5: Some(clocks.ahb),
1031 pclk1: Some(clocks.apb1),
1032 pclk2: Some(clocks.apb2),
1033 pclk1_tim: Some(clocks.pclk_tim),
1034 pclk2_tim: Some(clocks.pclk_tim),
1035 pclk4: Some(clocks.apb4),
1036 pclk5: Some(clocks.apb5),
1037 per: None,
1038 rtc: None,
1039 i2s_ckin: None,
1040 ic8: None,
1041 ic9: None,
1042 ic14: None,
1043 ic17: None,
1044 ic20: None,
1045 );
1046}
diff --git a/embassy-stm32/src/timer/simple_pwm.rs b/embassy-stm32/src/timer/simple_pwm.rs
index 06315d7f3..c338b0fd4 100644
--- a/embassy-stm32/src/timer/simple_pwm.rs
+++ b/embassy-stm32/src/timer/simple_pwm.rs
@@ -309,7 +309,9 @@ impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> {
309 /// Generate a sequence of PWM waveform 309 /// Generate a sequence of PWM waveform
310 /// 310 ///
311 /// Note: 311 /// Note:
312 /// you will need to provide corresponding TIMx_UP DMA channel to use this method. 312 /// You will need to provide corresponding `TIMx_UP` DMA channel to use this method.
313 /// Also be aware that embassy timers use one of timers internally. It is possible to
314 /// switch this timer by using `time-driver-timX` feature.
313 pub async fn waveform_up(&mut self, dma: Peri<'_, impl super::UpDma<T>>, channel: Channel, duty: &[u16]) { 315 pub async fn waveform_up(&mut self, dma: Peri<'_, impl super::UpDma<T>>, channel: Channel, duty: &[u16]) {
314 #[allow(clippy::let_unit_value)] // eg. stm32f334 316 #[allow(clippy::let_unit_value)] // eg. stm32f334
315 let req = dma.request(); 317 let req = dma.request();
@@ -339,14 +341,33 @@ impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> {
339 ..Default::default() 341 ..Default::default()
340 }; 342 };
341 343
342 Transfer::new_write( 344 match self.inner.bits() {
343 dma, 345 TimerBits::Bits16 => {
344 req, 346 Transfer::new_write(
345 duty, 347 dma,
346 self.inner.regs_1ch().ccr(channel.index()).as_ptr() as *mut u16, 348 req,
347 dma_transfer_option, 349 duty,
348 ) 350 self.inner.regs_1ch().ccr(channel.index()).as_ptr() as *mut u16,
349 .await 351 dma_transfer_option,
352 )
353 .await
354 }
355 #[cfg(not(any(stm32l0)))]
356 TimerBits::Bits32 => {
357 #[cfg(not(any(bdma, gpdma)))]
358 panic!("unsupported timer bits");
359
360 #[cfg(any(bdma, gpdma))]
361 Transfer::new_write(
362 dma,
363 req,
364 duty,
365 self.inner.regs_1ch().ccr(channel.index()).as_ptr() as *mut u32,
366 dma_transfer_option,
367 )
368 .await
369 }
370 };
350 }; 371 };
351 372
352 // restore output compare state 373 // restore output compare state
@@ -378,18 +399,23 @@ impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> {
378 /// 399 ///
379 /// For example, if using channels 1 through 4, a buffer of 4 update steps might look like: 400 /// For example, if using channels 1 through 4, a buffer of 4 update steps might look like:
380 /// 401 ///
402 /// ```rust,ignore
381 /// let dma_buf: [u16; 16] = [ 403 /// let dma_buf: [u16; 16] = [
382 /// ch1_duty_1, ch2_duty_1, ch3_duty_1, ch4_duty_1, // update 1 404 /// ch1_duty_1, ch2_duty_1, ch3_duty_1, ch4_duty_1, // update 1
383 /// ch1_duty_2, ch2_duty_2, ch3_duty_2, ch4_duty_2, // update 2 405 /// ch1_duty_2, ch2_duty_2, ch3_duty_2, ch4_duty_2, // update 2
384 /// ch1_duty_3, ch2_duty_3, ch3_duty_3, ch4_duty_3, // update 3 406 /// ch1_duty_3, ch2_duty_3, ch3_duty_3, ch4_duty_3, // update 3
385 /// ch1_duty_4, ch2_duty_4, ch3_duty_4, ch4_duty_4, // update 4 407 /// ch1_duty_4, ch2_duty_4, ch3_duty_4, ch4_duty_4, // update 4
386 /// ]; 408 /// ];
409 /// ```
387 /// 410 ///
388 /// Each group of N values (where N = number of channels) is transferred on one update event, 411 /// Each group of `N` values (where `N` is number of channels) is transferred on one update event,
389 /// updating the duty cycles of all selected channels simultaneously. 412 /// updating the duty cycles of all selected channels simultaneously.
390 /// 413 ///
391 /// Note: 414 /// Note:
392 /// you will need to provide corresponding TIMx_UP DMA channel to use this method. 415 /// You will need to provide corresponding `TIMx_UP` DMA channel to use this method.
416 /// Also be aware that embassy timers use one of timers internally. It is possible to
417 /// switch this timer by using `time-driver-timX` feature.
418 ///
393 pub async fn waveform_up_multi_channel( 419 pub async fn waveform_up_multi_channel(
394 &mut self, 420 &mut self,
395 dma: Peri<'_, impl super::UpDma<T>>, 421 dma: Peri<'_, impl super::UpDma<T>>,
diff --git a/embassy-stm32/src/ucpd.rs b/embassy-stm32/src/ucpd.rs
index 8f259a917..ae86d28f0 100644
--- a/embassy-stm32/src/ucpd.rs
+++ b/embassy-stm32/src/ucpd.rs
@@ -32,7 +32,7 @@ use crate::{Peri, interrupt};
32 32
33pub(crate) fn init( 33pub(crate) fn init(
34 _cs: critical_section::CriticalSection, 34 _cs: critical_section::CriticalSection,
35 #[cfg(peri_ucpd1)] ucpd1_db_enable: bool, 35 #[cfg(all(peri_ucpd1, not(stm32n6)))] ucpd1_db_enable: bool,
36 #[cfg(peri_ucpd2)] ucpd2_db_enable: bool, 36 #[cfg(peri_ucpd2)] ucpd2_db_enable: bool,
37) { 37) {
38 #[cfg(stm32g0x1)] 38 #[cfg(stm32g0x1)]
@@ -349,6 +349,7 @@ impl<'d, T: Instance> CcPhy<'d, T> {
349 critical_section::with(|cs| { 349 critical_section::with(|cs| {
350 init( 350 init(
351 cs, 351 cs,
352 #[cfg(not(stm32n6))]
352 false, 353 false,
353 #[cfg(peri_ucpd2)] 354 #[cfg(peri_ucpd2)]
354 false, 355 false,
diff --git a/embassy-usb/CHANGELOG.md b/embassy-usb/CHANGELOG.md
index 0a30bc24b..cfb1bf021 100644
--- a/embassy-usb/CHANGELOG.md
+++ b/embassy-usb/CHANGELOG.md
@@ -8,6 +8,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
8<!-- next-header --> 8<!-- next-header -->
9## Unreleased - ReleaseDate 9## Unreleased - ReleaseDate
10 10
11- Add support for USB HID Boot Protocol Mode
12
11## 0.5.1 - 2025-08-26 13## 0.5.1 - 2025-08-26
12 14
13## 0.5.0 - 2025-07-16 15## 0.5.0 - 2025-07-16
diff --git a/embassy-usb/src/class/hid.rs b/embassy-usb/src/class/hid.rs
index 182e1f83f..64e8fd59f 100644
--- a/embassy-usb/src/class/hid.rs
+++ b/embassy-usb/src/class/hid.rs
@@ -15,8 +15,6 @@ use crate::types::InterfaceNumber;
15use crate::{Builder, Handler}; 15use crate::{Builder, Handler};
16 16
17const USB_CLASS_HID: u8 = 0x03; 17const USB_CLASS_HID: u8 = 0x03;
18const USB_SUBCLASS_NONE: u8 = 0x00;
19const USB_PROTOCOL_NONE: u8 = 0x00;
20 18
21// HID 19// HID
22const HID_DESC_DESCTYPE_HID: u8 = 0x21; 20const HID_DESC_DESCTYPE_HID: u8 = 0x21;
@@ -31,6 +29,52 @@ const HID_REQ_SET_REPORT: u8 = 0x09;
31const HID_REQ_GET_PROTOCOL: u8 = 0x03; 29const HID_REQ_GET_PROTOCOL: u8 = 0x03;
32const HID_REQ_SET_PROTOCOL: u8 = 0x0b; 30const HID_REQ_SET_PROTOCOL: u8 = 0x0b;
33 31
32/// Get/Set Protocol mapping
33/// See (7.2.5 and 7.2.6): <https://www.usb.org/sites/default/files/hid1_11.pdf>
34#[derive(Copy, Clone, Debug, PartialEq, Eq)]
35#[cfg_attr(feature = "defmt", derive(defmt::Format))]
36#[repr(u8)]
37pub enum HidProtocolMode {
38 /// Hid Boot Protocol Mode
39 Boot = 0,
40 /// Hid Report Protocol Mode
41 Report = 1,
42}
43
44impl From<u8> for HidProtocolMode {
45 fn from(mode: u8) -> HidProtocolMode {
46 if mode == HidProtocolMode::Boot as u8 {
47 HidProtocolMode::Boot
48 } else {
49 HidProtocolMode::Report
50 }
51 }
52}
53
54/// USB HID interface subclass values.
55#[derive(Copy, Clone, Debug, PartialEq, Eq)]
56#[cfg_attr(feature = "defmt", derive(defmt::Format))]
57#[repr(u8)]
58pub enum HidSubclass {
59 /// No subclass, standard HID device.
60 No = 0,
61 /// Boot interface subclass, supports BIOS boot protocol.
62 Boot = 1,
63}
64
65/// USB HID protocol values.
66#[derive(Copy, Clone, Debug, PartialEq, Eq)]
67#[cfg_attr(feature = "defmt", derive(defmt::Format))]
68#[repr(u8)]
69pub enum HidBootProtocol {
70 /// No boot protocol.
71 None = 0,
72 /// Keyboard boot protocol.
73 Keyboard = 1,
74 /// Mouse boot protocol.
75 Mouse = 2,
76}
77
34/// Configuration for the HID class. 78/// Configuration for the HID class.
35pub struct Config<'d> { 79pub struct Config<'d> {
36 /// HID report descriptor. 80 /// HID report descriptor.
@@ -48,6 +92,12 @@ pub struct Config<'d> {
48 92
49 /// Max packet size for both the IN and OUT endpoints. 93 /// Max packet size for both the IN and OUT endpoints.
50 pub max_packet_size: u16, 94 pub max_packet_size: u16,
95
96 /// The HID subclass of this interface
97 pub hid_subclass: HidSubclass,
98
99 /// The HID boot protocol of this interface
100 pub hid_boot_protocol: HidBootProtocol,
51} 101}
52 102
53/// Report ID 103/// Report ID
@@ -109,10 +159,15 @@ fn build<'d, D: Driver<'d>>(
109) -> (Option<D::EndpointOut>, D::EndpointIn, &'d AtomicUsize) { 159) -> (Option<D::EndpointOut>, D::EndpointIn, &'d AtomicUsize) {
110 let len = config.report_descriptor.len(); 160 let len = config.report_descriptor.len();
111 161
112 let mut func = builder.function(USB_CLASS_HID, USB_SUBCLASS_NONE, USB_PROTOCOL_NONE); 162 let mut func = builder.function(USB_CLASS_HID, config.hid_subclass as u8, config.hid_boot_protocol as u8);
113 let mut iface = func.interface(); 163 let mut iface = func.interface();
114 let if_num = iface.interface_number(); 164 let if_num = iface.interface_number();
115 let mut alt = iface.alt_setting(USB_CLASS_HID, USB_SUBCLASS_NONE, USB_PROTOCOL_NONE, None); 165 let mut alt = iface.alt_setting(
166 USB_CLASS_HID,
167 config.hid_subclass as u8,
168 config.hid_boot_protocol as u8,
169 None,
170 );
116 171
117 // HID descriptor 172 // HID descriptor
118 alt.descriptor( 173 alt.descriptor(
@@ -389,6 +444,23 @@ pub trait RequestHandler {
389 OutResponse::Rejected 444 OutResponse::Rejected
390 } 445 }
391 446
447 /// Gets the current hid protocol.
448 ///
449 /// Returns `Report` protocol by default.
450 fn get_protocol(&self) -> HidProtocolMode {
451 HidProtocolMode::Report
452 }
453
454 /// Sets the current hid protocol to `protocol`.
455 ///
456 /// Accepts only `Report` protocol by default.
457 fn set_protocol(&mut self, protocol: HidProtocolMode) -> OutResponse {
458 match protocol {
459 HidProtocolMode::Report => OutResponse::Accepted,
460 HidProtocolMode::Boot => OutResponse::Rejected,
461 }
462 }
463
392 /// Get the idle rate for `id`. 464 /// Get the idle rate for `id`.
393 /// 465 ///
394 /// If `id` is `None`, get the idle rate for all reports. Returning `None` 466 /// If `id` is `None`, get the idle rate for all reports. Returning `None`
@@ -482,11 +554,14 @@ impl<'d> Handler for Control<'d> {
482 _ => Some(OutResponse::Rejected), 554 _ => Some(OutResponse::Rejected),
483 }, 555 },
484 HID_REQ_SET_PROTOCOL => { 556 HID_REQ_SET_PROTOCOL => {
485 if req.value == 1 { 557 let hid_protocol = HidProtocolMode::from(req.value as u8);
486 Some(OutResponse::Accepted) 558 match (self.request_handler.as_mut(), hid_protocol) {
487 } else { 559 (Some(request_handler), hid_protocol) => Some(request_handler.set_protocol(hid_protocol)),
488 warn!("HID Boot Protocol is unsupported."); 560 (None, HidProtocolMode::Report) => Some(OutResponse::Accepted),
489 Some(OutResponse::Rejected) // UNSUPPORTED: Boot Protocol 561 (None, HidProtocolMode::Boot) => {
562 info!("Received request to switch to Boot protocol mode, but it is disabled by default.");
563 Some(OutResponse::Rejected)
564 }
490 } 565 }
491 } 566 }
492 _ => Some(OutResponse::Rejected), 567 _ => Some(OutResponse::Rejected),
@@ -539,8 +614,12 @@ impl<'d> Handler for Control<'d> {
539 } 614 }
540 } 615 }
541 HID_REQ_GET_PROTOCOL => { 616 HID_REQ_GET_PROTOCOL => {
542 // UNSUPPORTED: Boot Protocol 617 if let Some(request_handler) = self.request_handler.as_mut() {
543 buf[0] = 1; 618 buf[0] = request_handler.get_protocol() as u8;
619 } else {
620 // Return `Report` protocol mode by default
621 buf[0] = HidProtocolMode::Report as u8;
622 }
544 Some(InResponse::Accepted(&buf[0..1])) 623 Some(InResponse::Accepted(&buf[0..1]))
545 } 624 }
546 _ => Some(InResponse::Rejected), 625 _ => Some(InResponse::Rejected),
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
4use core::sync::atomic::{AtomicBool, Ordering}; 4use core::sync::atomic::{AtomicBool, AtomicU8, Ordering};
5 5
6use defmt::*; 6use defmt::*;
7use embassy_executor::Spawner; 7use embassy_executor::Spawner;
@@ -13,7 +13,9 @@ use embassy_nrf::usb::vbus_detect::HardwareVbusDetect;
13use embassy_nrf::{bind_interrupts, pac, peripherals, usb}; 13use embassy_nrf::{bind_interrupts, pac, peripherals, usb};
14use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; 14use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
15use embassy_sync::signal::Signal; 15use embassy_sync::signal::Signal;
16use embassy_usb::class::hid::{HidReaderWriter, ReportId, RequestHandler, State}; 16use embassy_usb::class::hid::{
17 HidBootProtocol, HidProtocolMode, HidReaderWriter, HidSubclass, ReportId, RequestHandler, State,
18};
17use embassy_usb::control::OutResponse; 19use embassy_usb::control::OutResponse;
18use embassy_usb::{Builder, Config, Handler}; 20use embassy_usb::{Builder, Config, Handler};
19use usbd_hid::descriptor::{KeyboardReport, SerializedDescriptor}; 21use usbd_hid::descriptor::{KeyboardReport, SerializedDescriptor};
@@ -26,6 +28,8 @@ bind_interrupts!(struct Irqs {
26 28
27static SUSPENDED: AtomicBool = AtomicBool::new(false); 29static SUSPENDED: AtomicBool = AtomicBool::new(false);
28 30
31static HID_PROTOCOL_MODE: AtomicU8 = AtomicU8::new(HidProtocolMode::Boot as u8);
32
29#[embassy_executor::main] 33#[embassy_executor::main]
30async fn main(_spawner: Spawner) { 34async 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
4use core::sync::atomic::{AtomicU8, Ordering};
5
4use defmt::*; 6use defmt::*;
5use embassy_executor::Spawner; 7use embassy_executor::Spawner;
6use embassy_futures::join::join; 8use embassy_futures::join::join;
@@ -8,7 +10,9 @@ use embassy_nrf::usb::Driver;
8use embassy_nrf::usb::vbus_detect::HardwareVbusDetect; 10use embassy_nrf::usb::vbus_detect::HardwareVbusDetect;
9use embassy_nrf::{bind_interrupts, pac, peripherals, usb}; 11use embassy_nrf::{bind_interrupts, pac, peripherals, usb};
10use embassy_time::Timer; 12use embassy_time::Timer;
11use embassy_usb::class::hid::{HidWriter, ReportId, RequestHandler, State}; 13use embassy_usb::class::hid::{
14 HidBootProtocol, HidProtocolMode, HidSubclass, HidWriter, ReportId, RequestHandler, State,
15};
12use embassy_usb::control::OutResponse; 16use embassy_usb::control::OutResponse;
13use embassy_usb::{Builder, Config}; 17use embassy_usb::{Builder, Config};
14use usbd_hid::descriptor::{MouseReport, SerializedDescriptor}; 18use 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
26static HID_PROTOCOL_MODE: AtomicU8 = AtomicU8::new(HidProtocolMode::Boot as u8);
27
22#[embassy_executor::main] 28#[embassy_executor::main]
23async fn main(_spawner: Spawner) { 29async 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 @@
1MEMORY 1MEMORY
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
4use core::sync::atomic::{AtomicBool, Ordering}; 4use core::sync::atomic::{AtomicBool, AtomicU8, Ordering};
5 5
6use defmt::*; 6use defmt::*;
7use embassy_executor::Spawner; 7use embassy_executor::Spawner;
@@ -10,7 +10,9 @@ use embassy_rp::bind_interrupts;
10use embassy_rp::gpio::{Input, Pull}; 10use embassy_rp::gpio::{Input, Pull};
11use embassy_rp::peripherals::USB; 11use embassy_rp::peripherals::USB;
12use embassy_rp::usb::{Driver, InterruptHandler}; 12use embassy_rp::usb::{Driver, InterruptHandler};
13use embassy_usb::class::hid::{HidReaderWriter, ReportId, RequestHandler, State}; 13use embassy_usb::class::hid::{
14 HidBootProtocol, HidProtocolMode, HidReaderWriter, HidSubclass, ReportId, RequestHandler, State,
15};
14use embassy_usb::control::OutResponse; 16use embassy_usb::control::OutResponse;
15use embassy_usb::{Builder, Config, Handler}; 17use embassy_usb::{Builder, Config, Handler};
16use usbd_hid::descriptor::{KeyboardReport, SerializedDescriptor}; 18use 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
25static HID_PROTOCOL_MODE: AtomicU8 = AtomicU8::new(HidProtocolMode::Boot as u8);
26
23#[embassy_executor::main] 27#[embassy_executor::main]
24async fn main(_spawner: Spawner) { 28async 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
4use core::sync::atomic::{AtomicBool, Ordering}; 4use core::sync::atomic::{AtomicBool, AtomicU8, Ordering};
5 5
6use defmt::*; 6use defmt::*;
7use embassy_executor::Spawner; 7use embassy_executor::Spawner;
@@ -11,7 +11,9 @@ use embassy_rp::clocks::RoscRng;
11use embassy_rp::peripherals::USB; 11use embassy_rp::peripherals::USB;
12use embassy_rp::usb::{Driver, InterruptHandler}; 12use embassy_rp::usb::{Driver, InterruptHandler};
13use embassy_time::Timer; 13use embassy_time::Timer;
14use embassy_usb::class::hid::{HidReaderWriter, ReportId, RequestHandler, State}; 14use embassy_usb::class::hid::{
15 HidBootProtocol, HidProtocolMode, HidReaderWriter, HidSubclass, ReportId, RequestHandler, State,
16};
15use embassy_usb::control::OutResponse; 17use embassy_usb::control::OutResponse;
16use embassy_usb::{Builder, Config, Handler}; 18use embassy_usb::{Builder, Config, Handler};
17use rand::Rng; 19use rand::Rng;
@@ -22,6 +24,8 @@ bind_interrupts!(struct Irqs {
22 USBCTRL_IRQ => InterruptHandler<USB>; 24 USBCTRL_IRQ => InterruptHandler<USB>;
23}); 25});
24 26
27static HID_PROTOCOL_MODE: AtomicU8 = AtomicU8::new(HidProtocolMode::Boot as u8);
28
25#[embassy_executor::main] 29#[embassy_executor::main]
26async fn main(_spawner: Spawner) { 30async 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
4use core::sync::atomic::{AtomicBool, Ordering}; 4use core::sync::atomic::{AtomicBool, AtomicU8, Ordering};
5 5
6use defmt::*; 6use defmt::*;
7use embassy_executor::Spawner; 7use embassy_executor::Spawner;
@@ -10,7 +10,9 @@ use embassy_rp::bind_interrupts;
10use embassy_rp::gpio::{Input, Pull}; 10use embassy_rp::gpio::{Input, Pull};
11use embassy_rp::peripherals::USB; 11use embassy_rp::peripherals::USB;
12use embassy_rp::usb::{Driver as UsbDriver, InterruptHandler}; 12use embassy_rp::usb::{Driver as UsbDriver, InterruptHandler};
13use embassy_usb::class::hid::{HidReaderWriter, ReportId, RequestHandler, State as HidState}; 13use embassy_usb::class::hid::{
14 HidBootProtocol, HidProtocolMode, HidReaderWriter, HidSubclass, ReportId, RequestHandler, State as HidState,
15};
14use embassy_usb::control::OutResponse; 16use embassy_usb::control::OutResponse;
15use embassy_usb::{Builder, Config, Handler}; 17use embassy_usb::{Builder, Config, Handler};
16use usbd_hid::descriptor::{KeyboardReport, SerializedDescriptor}; 18use 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
25static HID_PROTOCOL_MODE: AtomicU8 = AtomicU8::new(HidProtocolMode::Boot as u8);
26
23#[embassy_executor::main] 27#[embassy_executor::main]
24async fn main(_spawner: Spawner) { 28async 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
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::adc::vals::Scandir;
7use embassy_stm32::adc::{Adc, AdcChannel, AnyAdcChannel, Resolution, SampleTime}; 6use embassy_stm32::adc::{Adc, AdcChannel, AnyAdcChannel, Resolution, SampleTime};
8use embassy_stm32::peripherals::ADC1; 7use embassy_stm32::peripherals::ADC1;
9use embassy_time::Timer; 8use 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"] }
16embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } 16embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] }
17embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } 17embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] }
18embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } 18embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
19embedded-hal-1 = { package = "embedded-hal", version = "1.0" }
19static_cell = "2" 20static_cell = "2"
20portable-atomic = { version = "1.5", features = ["unsafe-assume-single-core"] } 21portable-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
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::adc::{self, Adc, WatchdogChannels}; 6use embassy_stm32::adc::{self, Adc, SampleTime, WatchdogChannels};
7use embassy_stm32::bind_interrupts; 7use embassy_stm32::bind_interrupts;
8use embassy_stm32::peripherals::ADC1; 8use embassy_stm32::peripherals::ADC1;
9use {defmt_rtt as _, panic_probe as _}; 9use {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
18use defmt::*;
19use embassy_executor::Spawner;
20use embassy_stm32::i2c::{Config, I2c, Master};
21use embassy_stm32::mode::{Async, Blocking};
22use embassy_stm32::time::Hertz;
23use embassy_stm32::{bind_interrupts, i2c, peripherals};
24use embassy_time::Timer;
25use embedded_hal_1::i2c::Operation;
26use {defmt_rtt as _, panic_probe as _};
27
28bind_interrupts!(struct Irqs {
29 I2C1 => i2c::EventInterruptHandler<peripherals::I2C1>, i2c::ErrorInterruptHandler<peripherals::I2C1>;
30});
31
32#[embassy_executor::main]
33async 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
157fn 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
169fn 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
181fn 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
198fn 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
213fn 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
241fn 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
263fn 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
290fn 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
310fn 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
330fn 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
361fn 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
389async 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
401async 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
413async 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
430async 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
445async 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
473async 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
493async 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
518async 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
537async 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
556async 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
585async 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
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::adc::Adc; 6use embassy_stm32::adc::{Adc, SampleTime};
7use embassy_stm32::peripherals::ADC1; 7use embassy_stm32::peripherals::ADC1;
8use embassy_stm32::{adc, bind_interrupts}; 8use embassy_stm32::{adc, bind_interrupts};
9use embassy_time::Timer; 9use 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 @@
4use cortex_m::prelude::_embedded_hal_blocking_delay_DelayUs; 4use cortex_m::prelude::_embedded_hal_blocking_delay_DelayUs;
5use defmt::*; 5use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::adc::{Adc, Temperature, VrefInt}; 7use embassy_stm32::adc::{Adc, SampleTime, Temperature, VrefInt};
8use embassy_time::{Delay, Timer}; 8use embassy_time::{Delay, Timer};
9use {defmt_rtt as _, panic_probe as _}; 9use {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;
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::Peripherals; 6use embassy_stm32::Peripherals;
7use embassy_stm32::adc::{Adc, AdcChannel, RingBufferedAdc, SampleTime}; 7use embassy_stm32::adc::{Adc, AdcChannel, RegularConversionMode, RingBufferedAdc, SampleTime};
8use embassy_time::Instant; 8use embassy_time::Instant;
9use {defmt_rtt as _, panic_probe as _}; 9use {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
4use core::sync::atomic::{AtomicBool, Ordering}; 4use core::sync::atomic::{AtomicBool, AtomicU8, Ordering};
5 5
6use defmt::*; 6use defmt::*;
7use embassy_executor::Spawner; 7use embassy_executor::Spawner;
@@ -11,7 +11,9 @@ use embassy_stm32::gpio::Pull;
11use embassy_stm32::time::Hertz; 11use embassy_stm32::time::Hertz;
12use embassy_stm32::usb::Driver; 12use embassy_stm32::usb::Driver;
13use embassy_stm32::{Config, bind_interrupts, peripherals, usb}; 13use embassy_stm32::{Config, bind_interrupts, peripherals, usb};
14use embassy_usb::class::hid::{HidReaderWriter, ReportId, RequestHandler, State}; 14use embassy_usb::class::hid::{
15 HidBootProtocol, HidProtocolMode, HidReaderWriter, HidSubclass, ReportId, RequestHandler, State,
16};
15use embassy_usb::control::OutResponse; 17use embassy_usb::control::OutResponse;
16use embassy_usb::{Builder, Handler}; 18use embassy_usb::{Builder, Handler};
17use usbd_hid::descriptor::{KeyboardReport, SerializedDescriptor}; 19use 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
26static 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
4use core::sync::atomic::{AtomicU8, Ordering};
5
4use defmt::*; 6use defmt::*;
5use embassy_executor::Spawner; 7use embassy_executor::Spawner;
6use embassy_futures::join::join; 8use embassy_futures::join::join;
@@ -9,7 +11,9 @@ use embassy_stm32::usb::Driver;
9use embassy_stm32::{Config, bind_interrupts, peripherals, usb}; 11use embassy_stm32::{Config, bind_interrupts, peripherals, usb};
10use embassy_time::Timer; 12use embassy_time::Timer;
11use embassy_usb::Builder; 13use embassy_usb::Builder;
12use embassy_usb::class::hid::{HidWriter, ReportId, RequestHandler, State}; 14use embassy_usb::class::hid::{
15 HidBootProtocol, HidProtocolMode, HidSubclass, HidWriter, ReportId, RequestHandler, State,
16};
13use embassy_usb::control::OutResponse; 17use embassy_usb::control::OutResponse;
14use usbd_hid::descriptor::{MouseReport, SerializedDescriptor}; 18use usbd_hid::descriptor::{MouseReport, SerializedDescriptor};
15use {defmt_rtt as _, panic_probe as _}; 19use {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
25static 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
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::dsihost::{DsiHost, PacketType, blocking_delay_ms}; 6use embassy_stm32::dsihost::{DsiHost, PacketType};
7use embassy_stm32::gpio::{Level, Output, Speed}; 7use embassy_stm32::gpio::{Level, Output, Speed};
8use embassy_stm32::ltdc::Ltdc; 8use embassy_stm32::ltdc::Ltdc;
9use embassy_stm32::pac::dsihost::regs::{Ier0, Ier1}; 9use 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};
15use embassy_stm32::time::mhz; 15use embassy_stm32::time::mhz;
16use embassy_time::Timer; 16use embassy_time::{Duration, Timer, block_for};
17use {defmt_rtt as _, panic_probe as _}; 17use {defmt_rtt as _, panic_probe as _};
18 18
19enum _Orientation { 19enum _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
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::adc::Adc; 6use embassy_stm32::adc::{Adc, SampleTime};
7use embassy_time::Timer; 7use embassy_time::Timer;
8use {defmt_rtt as _, panic_probe as _}; 8use {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
8use defmt::*; 8use defmt::*;
9use embassy_executor::Spawner; 9use embassy_executor::Spawner;
10use embassy_stm32::adc::{Adc, Clock, Ovsr, Ovss, Presc, SampleTime}; 10use embassy_stm32::adc::{Adc, AdcConfig, Clock, Ovsr, Ovss, Presc, SampleTime};
11use embassy_time::Timer; 11use embassy_time::Timer;
12use {defmt_rtt as _, panic_probe as _}; 12use {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::*;
9use embassy_executor::Spawner; 9use embassy_executor::Spawner;
10use embassy_stm32::Config; 10use embassy_stm32::Config;
11use embassy_stm32::adc::vals::{Rovsm, Trovs}; 11use embassy_stm32::adc::vals::{Rovsm, Trovs};
12use embassy_stm32::adc::{Adc, SampleTime}; 12use embassy_stm32::adc::{Adc, AdcConfig, SampleTime};
13use embassy_time::Timer; 13use embassy_time::Timer;
14use {defmt_rtt as _, panic_probe as _}; 14use {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;
6use embassy_stm32::adc::{self, Adc, AdcChannel, RxDma, SampleTime}; 6use embassy_stm32::adc::{self, Adc, AdcChannel, RxDma, SampleTime};
7use embassy_stm32::peripherals::{ADC1, ADC2, GPDMA1_CH0, GPDMA1_CH1, PA0, PA1, PA2, PA3}; 7use embassy_stm32::peripherals::{ADC1, ADC2, GPDMA1_CH0, GPDMA1_CH1, PA0, PA1, PA2, PA3};
8use embassy_stm32::{Config, Peri}; 8use embassy_stm32::{Config, Peri};
9use embassy_time::Instant; 9use embassy_time::{Duration, Instant, Ticker};
10use {defmt_rtt as _, panic_probe as _}; 10use {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
4use defmt::*; 4use defmt::*;
5use embassy_stm32::Config; 5use embassy_stm32::Config;
6use embassy_stm32::adc::{Adc, Resolution}; 6use embassy_stm32::adc::{Adc, AdcConfig, Resolution, SampleTime};
7use {defmt_rtt as _, panic_probe as _}; 7use {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 @@
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::Config; 6use embassy_stm32::Config;
7use embassy_stm32::adc::{Adc, AdcChannel, SampleTime}; 7use embassy_stm32::adc::{Adc, AdcChannel, RegularConversionMode, SampleTime};
8use {defmt_rtt as _, panic_probe as _}; 8use {defmt_rtt as _, panic_probe as _};
9 9
10const DMA_BUF_LEN: usize = 512; 10const 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
4use core::sync::atomic::{AtomicU8, Ordering};
5
4use defmt::*; 6use defmt::*;
5use embassy_executor::Spawner; 7use embassy_executor::Spawner;
6use embassy_futures::join::join; 8use embassy_futures::join::join;
@@ -8,7 +10,9 @@ use embassy_stm32::usb::Driver;
8use embassy_stm32::{Config, bind_interrupts, peripherals, usb}; 10use embassy_stm32::{Config, bind_interrupts, peripherals, usb};
9use embassy_time::Timer; 11use embassy_time::Timer;
10use embassy_usb::Builder; 12use embassy_usb::Builder;
11use embassy_usb::class::hid::{HidWriter, ReportId, RequestHandler, State}; 13use embassy_usb::class::hid::{
14 HidBootProtocol, HidProtocolMode, HidSubclass, HidWriter, ReportId, RequestHandler, State,
15};
12use embassy_usb::control::OutResponse; 16use embassy_usb::control::OutResponse;
13use usbd_hid::descriptor::{MouseReport, SerializedDescriptor}; 17use usbd_hid::descriptor::{MouseReport, SerializedDescriptor};
14use {defmt_rtt as _, panic_probe as _}; 18use {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
24static HID_PROTOCOL_MODE: AtomicU8 = AtomicU8::new(HidProtocolMode::Boot as u8);
25
20#[embassy_executor::main] 26#[embassy_executor::main]
21async fn main(_spawner: Spawner) { 27async 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]
2runner = 'probe-rs run --chip STM32N657'
3
4[build]
5target = "thumbv8m.main-none-eabihf"
6
7[env]
8DEFMT_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]
2edition = "2021"
3name = "embassy-stm32n6-examples"
4version = "0.1.0"
5license = "MIT OR Apache-2.0"
6publish = false
7
8[dependencies]
9# Change stm32h563zi to your chip name, if necessary.
10embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = ["defmt", "stm32n657x0", "time-driver-any", "exti", "unstable-pac"] }
11embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] }
12embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] }
13embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
14embassy-net = { version = "0.7.1", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", "proto-ipv6"] }
15embassy-usb = { version = "0.5.1", path = "../../embassy-usb", features = ["defmt"] }
16embassy-futures = { version = "0.1.2", path = "../../embassy-futures" }
17
18defmt = "1.0.1"
19defmt-rtt = "1.0.0"
20
21cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
22cortex-m-rt = "0.7.0"
23embedded-hal = "0.2.6"
24embedded-hal-1 = { package = "embedded-hal", version = "1.0" }
25embedded-hal-async = { version = "1.0" }
26embedded-io-async = { version = "0.6.1" }
27embedded-nal-async = "0.8.0"
28panic-probe = { version = "1.0.0", features = ["print-defmt"] }
29heapless = { version = "0.8", default-features = false }
30critical-section = "1.1"
31micromath = "2.0.0"
32stm32-fmc = "0.3.0"
33embedded-storage = "0.3.1"
34static_cell = "2"
35
36
37# cargo build/run
38[profile.dev]
39codegen-units = 1
40debug = 2
41debug-assertions = true # <-
42incremental = false
43opt-level = 3 # <-
44overflow-checks = true # <-
45
46# cargo test
47[profile.test]
48codegen-units = 1
49debug = 2
50debug-assertions = true # <-
51incremental = false
52opt-level = 3 # <-
53overflow-checks = true # <-
54
55# cargo build/run --release
56[profile.release]
57codegen-units = 1
58debug = 2
59debug-assertions = false # <-
60incremental = false
61lto = 'fat'
62opt-level = 3 # <-
63overflow-checks = false # <-
64
65# cargo test --release
66[profile.bench]
67codegen-units = 1
68debug = 2
69debug-assertions = false # <-
70incremental = false
71lto = 'fat'
72opt-level = 3 # <-
73overflow-checks = false # <-
74
75[package.metadata.embassy]
76build = [
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 @@
1fn 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 @@
1MEMORY
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
4use defmt::*;
5use embassy_executor::Spawner;
6use embassy_stm32::exti::ExtiInput;
7use embassy_stm32::gpio::{Level, Output, Pull, Speed};
8use embassy_time::Timer;
9use {defmt_rtt as _, panic_probe as _};
10
11#[embassy_executor::task]
12async 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]
20async 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
4use defmt::*; 4use defmt::*;
5use embassy_stm32::Config; 5use embassy_stm32::Config;
6use embassy_stm32::adc::{Adc, Resolution}; 6use embassy_stm32::adc::{Adc, AdcConfig, Resolution, SampleTime};
7use embassy_time::Duration; 7use embassy_time::Duration;
8use {defmt_rtt as _, panic_probe as _}; 8use {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
4use defmt::*; 4use defmt::*;
5use embassy_stm32::adc; 5use embassy_stm32::adc::{self, Adc, AdcChannel, AdcConfig, SampleTime, adc4};
6use embassy_stm32::adc::{AdcChannel, adc4};
7use {defmt_rtt as _, panic_probe as _}; 6use {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
4use defmt::*; 4use defmt::*;
5use embassy_stm32::adc::{AdcChannel, adc4}; 5use embassy_stm32::adc::{Adc, AdcChannel, SampleTime, adc4};
6use {defmt_rtt as _, panic_probe as _}; 6use {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
4use defmt::*; 4use defmt::*;
5use embassy_stm32::adc::{AdcChannel, adc4}; 5use embassy_stm32::adc::{Adc, AdcChannel, SampleTime, adc4};
6use {defmt_rtt as _, panic_probe as _}; 6use {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 }
diff --git a/tests/stm32/src/bin/dac.rs b/tests/stm32/src/bin/dac.rs
index d34bbb255..747b11e7f 100644
--- a/tests/stm32/src/bin/dac.rs
+++ b/tests/stm32/src/bin/dac.rs
@@ -10,7 +10,7 @@ use core::f32::consts::PI;
10use common::*; 10use common::*;
11use defmt::assert; 11use defmt::assert;
12use embassy_executor::Spawner; 12use embassy_executor::Spawner;
13use embassy_stm32::adc::Adc; 13use embassy_stm32::adc::{Adc, SampleTime};
14use embassy_stm32::dac::{DacCh1, Value}; 14use embassy_stm32::dac::{DacCh1, Value};
15use embassy_time::Timer; 15use embassy_time::Timer;
16use micromath::F32Ext; 16use micromath::F32Ext;
@@ -37,7 +37,7 @@ async fn main(_spawner: Spawner) {
37 dac.set(Value::Bit8(0)); 37 dac.set(Value::Bit8(0));
38 // Now wait a little to obtain a stable value 38 // Now wait a little to obtain a stable value
39 Timer::after_millis(30).await; 39 Timer::after_millis(30).await;
40 let offset = adc.blocking_read(&mut adc_pin); 40 let offset = adc.blocking_read(&mut adc_pin, SampleTime::from_bits(0));
41 41
42 for v in 0..=255 { 42 for v in 0..=255 {
43 // First set the DAC output value 43 // First set the DAC output value
@@ -48,7 +48,10 @@ async fn main(_spawner: Spawner) {
48 Timer::after_millis(30).await; 48 Timer::after_millis(30).await;
49 49
50 // Need to steal the peripherals here because PA4 is obviously in use already 50 // Need to steal the peripherals here because PA4 is obviously in use already
51 let measured = adc.blocking_read(&mut unsafe { embassy_stm32::Peripherals::steal() }.PA4); 51 let measured = adc.blocking_read(
52 &mut unsafe { embassy_stm32::Peripherals::steal() }.PA4,
53 SampleTime::from_bits(0),
54 );
52 // Calibrate and normalize the measurement to get close to the dac_output_val 55 // Calibrate and normalize the measurement to get close to the dac_output_val
53 let measured_normalized = ((measured as i32 - offset as i32) / normalization_factor) as i16; 56 let measured_normalized = ((measured as i32 - offset as i32) / normalization_factor) as i16;
54 57
diff --git a/tests/stm32/src/bin/dac_l1.rs b/tests/stm32/src/bin/dac_l1.rs
index e6400f28e..2fe0cf1f1 100644
--- a/tests/stm32/src/bin/dac_l1.rs
+++ b/tests/stm32/src/bin/dac_l1.rs
@@ -10,7 +10,7 @@ use core::f32::consts::PI;
10use common::*; 10use common::*;
11use defmt::assert; 11use defmt::assert;
12use embassy_executor::Spawner; 12use embassy_executor::Spawner;
13use embassy_stm32::adc::Adc; 13use embassy_stm32::adc::{Adc, SampleTime};
14use embassy_stm32::dac::{DacCh1, Value}; 14use embassy_stm32::dac::{DacCh1, Value};
15use embassy_stm32::{bind_interrupts, peripherals}; 15use embassy_stm32::{bind_interrupts, peripherals};
16use embassy_time::Timer; 16use embassy_time::Timer;
@@ -47,7 +47,7 @@ async fn main(_spawner: Spawner) {
47 dac.set(Value::Bit8(0)); 47 dac.set(Value::Bit8(0));
48 // Now wait a little to obtain a stable value 48 // Now wait a little to obtain a stable value
49 Timer::after_millis(30).await; 49 Timer::after_millis(30).await;
50 let offset = adc.read(&mut adc_pin).await; 50 let offset = adc.read(&mut adc_pin, SampleTime::from_bits(0)).await;
51 51
52 for v in 0..=255 { 52 for v in 0..=255 {
53 // First set the DAC output value 53 // First set the DAC output value
@@ -58,7 +58,12 @@ async fn main(_spawner: Spawner) {
58 Timer::after_millis(30).await; 58 Timer::after_millis(30).await;
59 59
60 // Need to steal the peripherals here because PA4 is obviously in use already 60 // Need to steal the peripherals here because PA4 is obviously in use already
61 let measured = adc.read(&mut unsafe { embassy_stm32::Peripherals::steal() }.PA4).await; 61 let measured = adc
62 .read(
63 &mut unsafe { embassy_stm32::Peripherals::steal() }.PA4,
64 SampleTime::from_bits(0),
65 )
66 .await;
62 // Calibrate and normalize the measurement to get close to the dac_output_val 67 // Calibrate and normalize the measurement to get close to the dac_output_val
63 let measured_normalized = ((measured as i32 - offset as i32) / normalization_factor) as i16; 68 let measured_normalized = ((measured as i32 - offset as i32) / normalization_factor) as i16;
64 69