aboutsummaryrefslogtreecommitdiff
path: root/examples
diff options
context:
space:
mode:
authorxoviat <[email protected]>2025-11-04 07:16:27 -0600
committerGitHub <[email protected]>2025-11-04 07:16:27 -0600
commitf8f7820ab98cc1f49d7b2a623566f836354916bc (patch)
tree8a26ba0e703d82ec70c0cc3487a8ebc56273d1b6 /examples
parentf85d709f140838cf0161206df01dd77abbac9c5d (diff)
parent51f8aeaa0dd2359a669a3c38d194a8a70f26441f (diff)
Merge branch 'main' into i2c
Diffstat (limited to 'examples')
-rw-r--r--examples/rp/src/bin/pio_onewire.rs2
-rw-r--r--examples/rp/src/bin/pio_onewire_parasite.rs2
-rw-r--r--examples/rp235x/src/bin/pio_onewire.rs2
-rw-r--r--examples/rp235x/src/bin/pio_onewire_parasite.rs2
-rw-r--r--examples/stm32f4/src/bin/adc_dma.rs29
-rw-r--r--examples/stm32g0/src/bin/onewire_ds18b20.rs2
-rw-r--r--examples/stm32h5/src/bin/stop.rs3
-rw-r--r--examples/stm32l4/src/bin/adc_dma.rs51
-rw-r--r--examples/stm32l5/src/bin/stop.rs3
-rw-r--r--examples/stm32wle5/.cargo/config.toml9
-rw-r--r--examples/stm32wle5/Cargo.toml38
-rw-r--r--examples/stm32wle5/README.md52
-rw-r--r--examples/stm32wle5/build.rs5
-rw-r--r--examples/stm32wle5/src/bin/adc.rs100
-rw-r--r--examples/stm32wle5/src/bin/blinky.rs90
-rw-r--r--examples/stm32wle5/src/bin/button_exti.rs91
-rw-r--r--examples/stm32wle5/src/bin/i2c.rs110
-rw-r--r--examples/stm32wle5/stm32wle5.code-workspace13
18 files changed, 584 insertions, 20 deletions
diff --git a/examples/rp/src/bin/pio_onewire.rs b/examples/rp/src/bin/pio_onewire.rs
index 102f13c45..6432edb8a 100644
--- a/examples/rp/src/bin/pio_onewire.rs
+++ b/examples/rp/src/bin/pio_onewire.rs
@@ -61,7 +61,7 @@ async fn main(_spawner: Spawner) {
61 let mut data = [0; 9]; 61 let mut data = [0; 9];
62 onewire.read_bytes(&mut data).await; 62 onewire.read_bytes(&mut data).await;
63 if crc8(&data) == 0 { 63 if crc8(&data) == 0 {
64 let temp = ((data[1] as u32) << 8 | data[0] as u32) as f32 / 16.; 64 let temp = ((data[1] as i16) << 8 | data[0] as i16) as f32 / 16.;
65 info!("Read device {:x}: {} deg C", device, temp); 65 info!("Read device {:x}: {} deg C", device, temp);
66 } else { 66 } else {
67 warn!("Reading device {:x} failed", device); 67 warn!("Reading device {:x} failed", device);
diff --git a/examples/rp/src/bin/pio_onewire_parasite.rs b/examples/rp/src/bin/pio_onewire_parasite.rs
index fd076dee0..78fb94b18 100644
--- a/examples/rp/src/bin/pio_onewire_parasite.rs
+++ b/examples/rp/src/bin/pio_onewire_parasite.rs
@@ -63,7 +63,7 @@ async fn main(_spawner: Spawner) {
63 let mut data = [0; 9]; 63 let mut data = [0; 9];
64 onewire.read_bytes(&mut data).await; 64 onewire.read_bytes(&mut data).await;
65 if crc8(&data) == 0 { 65 if crc8(&data) == 0 {
66 let temp = ((data[1] as u32) << 8 | data[0] as u32) as f32 / 16.; 66 let temp = ((data[1] as i16) << 8 | data[0] as i16) as f32 / 16.;
67 info!("Read device {:x}: {} deg C", device, temp); 67 info!("Read device {:x}: {} deg C", device, temp);
68 } else { 68 } else {
69 warn!("Reading device {:x} failed. {:02x}", device, data); 69 warn!("Reading device {:x} failed. {:02x}", device, data);
diff --git a/examples/rp235x/src/bin/pio_onewire.rs b/examples/rp235x/src/bin/pio_onewire.rs
index 102f13c45..6432edb8a 100644
--- a/examples/rp235x/src/bin/pio_onewire.rs
+++ b/examples/rp235x/src/bin/pio_onewire.rs
@@ -61,7 +61,7 @@ async fn main(_spawner: Spawner) {
61 let mut data = [0; 9]; 61 let mut data = [0; 9];
62 onewire.read_bytes(&mut data).await; 62 onewire.read_bytes(&mut data).await;
63 if crc8(&data) == 0 { 63 if crc8(&data) == 0 {
64 let temp = ((data[1] as u32) << 8 | data[0] as u32) as f32 / 16.; 64 let temp = ((data[1] as i16) << 8 | data[0] as i16) as f32 / 16.;
65 info!("Read device {:x}: {} deg C", device, temp); 65 info!("Read device {:x}: {} deg C", device, temp);
66 } else { 66 } else {
67 warn!("Reading device {:x} failed", device); 67 warn!("Reading device {:x} failed", device);
diff --git a/examples/rp235x/src/bin/pio_onewire_parasite.rs b/examples/rp235x/src/bin/pio_onewire_parasite.rs
index fd076dee0..78fb94b18 100644
--- a/examples/rp235x/src/bin/pio_onewire_parasite.rs
+++ b/examples/rp235x/src/bin/pio_onewire_parasite.rs
@@ -63,7 +63,7 @@ async fn main(_spawner: Spawner) {
63 let mut data = [0; 9]; 63 let mut data = [0; 9];
64 onewire.read_bytes(&mut data).await; 64 onewire.read_bytes(&mut data).await;
65 if crc8(&data) == 0 { 65 if crc8(&data) == 0 {
66 let temp = ((data[1] as u32) << 8 | data[0] as u32) as f32 / 16.; 66 let temp = ((data[1] as i16) << 8 | data[0] as i16) as f32 / 16.;
67 info!("Read device {:x}: {} deg C", device, temp); 67 info!("Read device {:x}: {} deg C", device, temp);
68 } else { 68 } else {
69 warn!("Reading device {:x} failed. {:02x}", device, data); 69 warn!("Reading device {:x} failed. {:02x}", device, data);
diff --git a/examples/stm32f4/src/bin/adc_dma.rs b/examples/stm32f4/src/bin/adc_dma.rs
index c24f01753..f8da91336 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, RingBufferedAdc, SampleTime, Sequence}; 7use embassy_stm32::adc::{Adc, AdcChannel, 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
@@ -15,7 +15,7 @@ async fn main(spawner: Spawner) {
15} 15}
16 16
17#[embassy_executor::task] 17#[embassy_executor::task]
18async fn adc_task(mut p: Peripherals) { 18async fn adc_task(p: Peripherals) {
19 const ADC_BUF_SIZE: usize = 1024; 19 const ADC_BUF_SIZE: usize = 1024;
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();
@@ -23,13 +23,24 @@ async fn adc_task(mut p: Peripherals) {
23 let adc = Adc::new(p.ADC1); 23 let adc = Adc::new(p.ADC1);
24 let adc2 = Adc::new(p.ADC2); 24 let adc2 = Adc::new(p.ADC2);
25 25
26 let mut adc: RingBufferedAdc<embassy_stm32::peripherals::ADC1> = adc.into_ring_buffered(p.DMA2_CH0, adc_data); 26 let mut adc: RingBufferedAdc<embassy_stm32::peripherals::ADC1> = adc.into_ring_buffered(
27 let mut adc2: RingBufferedAdc<embassy_stm32::peripherals::ADC2> = adc2.into_ring_buffered(p.DMA2_CH2, adc_data2); 27 p.DMA2_CH0,
28 28 adc_data,
29 adc.set_sample_sequence(Sequence::One, &mut p.PA0, SampleTime::CYCLES112); 29 [
30 adc.set_sample_sequence(Sequence::Two, &mut p.PA2, SampleTime::CYCLES112); 30 (&mut p.PA0.degrade_adc(), SampleTime::CYCLES112),
31 adc2.set_sample_sequence(Sequence::One, &mut p.PA1, SampleTime::CYCLES112); 31 (&mut p.PA2.degrade_adc(), SampleTime::CYCLES112),
32 adc2.set_sample_sequence(Sequence::Two, &mut p.PA3, SampleTime::CYCLES112); 32 ]
33 .into_iter(),
34 );
35 let mut adc2: RingBufferedAdc<embassy_stm32::peripherals::ADC2> = adc2.into_ring_buffered(
36 p.DMA2_CH2,
37 adc_data2,
38 [
39 (&mut p.PA1.degrade_adc(), SampleTime::CYCLES112),
40 (&mut p.PA3.degrade_adc(), SampleTime::CYCLES112),
41 ]
42 .into_iter(),
43 );
33 44
34 // Note that overrun is a big consideration in this implementation. Whatever task is running the adc.read() calls absolutely must circle back around 45 // Note that overrun is a big consideration in this implementation. Whatever task is running the adc.read() calls absolutely must circle back around
35 // to the adc.read() call before the DMA buffer is wrapped around > 1 time. At this point, the overrun is so significant that the context of 46 // to the adc.read() call before the DMA buffer is wrapped around > 1 time. At this point, the overrun is so significant that the context of
diff --git a/examples/stm32g0/src/bin/onewire_ds18b20.rs b/examples/stm32g0/src/bin/onewire_ds18b20.rs
index 62f8711a6..43ecca8c4 100644
--- a/examples/stm32g0/src/bin/onewire_ds18b20.rs
+++ b/examples/stm32g0/src/bin/onewire_ds18b20.rs
@@ -267,7 +267,7 @@ where
267 } 267 }
268 268
269 match Self::crc8(&data) == 0 { 269 match Self::crc8(&data) == 0 {
270 true => Ok(((data[1] as u16) << 8 | data[0] as u16) as f32 / 16.), 270 true => Ok(((data[1] as i16) << 8 | data[0] as i16) as f32 / 16.),
271 false => Err(()), 271 false => Err(()),
272 } 272 }
273 } 273 }
diff --git a/examples/stm32h5/src/bin/stop.rs b/examples/stm32h5/src/bin/stop.rs
index 3c4f49f64..2026d8f99 100644
--- a/examples/stm32h5/src/bin/stop.rs
+++ b/examples/stm32h5/src/bin/stop.rs
@@ -12,7 +12,6 @@ use embassy_stm32::rcc::{HSIPrescaler, LsConfig};
12use embassy_stm32::rtc::{Rtc, RtcConfig}; 12use embassy_stm32::rtc::{Rtc, RtcConfig};
13use embassy_stm32::{Config, Peri}; 13use embassy_stm32::{Config, Peri};
14use embassy_time::Timer; 14use embassy_time::Timer;
15use static_cell::StaticCell;
16use {defmt_rtt as _, panic_probe as _}; 15use {defmt_rtt as _, panic_probe as _};
17 16
18#[cortex_m_rt::entry] 17#[cortex_m_rt::entry]
@@ -39,8 +38,6 @@ async fn async_main(spawner: Spawner) {
39 38
40 // give the RTC to the executor... 39 // give the RTC to the executor...
41 let rtc = Rtc::new(p.RTC, RtcConfig::default()); 40 let rtc = Rtc::new(p.RTC, RtcConfig::default());
42 static RTC: StaticCell<Rtc> = StaticCell::new();
43 let rtc = RTC.init(rtc);
44 embassy_stm32::low_power::stop_with_rtc(rtc); 41 embassy_stm32::low_power::stop_with_rtc(rtc);
45 42
46 spawner.spawn(unwrap!(blinky(p.PB4.into()))); 43 spawner.spawn(unwrap!(blinky(p.PB4.into())));
diff --git a/examples/stm32l4/src/bin/adc_dma.rs b/examples/stm32l4/src/bin/adc_dma.rs
new file mode 100644
index 000000000..7a9200edd
--- /dev/null
+++ b/examples/stm32l4/src/bin/adc_dma.rs
@@ -0,0 +1,51 @@
1#![no_std]
2#![no_main]
3
4use defmt::*;
5use embassy_executor::Spawner;
6use embassy_stm32::Config;
7use embassy_stm32::adc::{Adc, AdcChannel, SampleTime};
8use {defmt_rtt as _, panic_probe as _};
9
10const DMA_BUF_LEN: usize = 512;
11
12#[embassy_executor::main]
13async fn main(_spawner: Spawner) {
14 info!("Hello World!");
15
16 let mut config = Config::default();
17 {
18 use embassy_stm32::rcc::*;
19 config.rcc.mux.adcsel = mux::Adcsel::SYS;
20 }
21 let p = embassy_stm32::init(config);
22
23 let mut adc = Adc::new(p.ADC1);
24 let mut adc_pin0 = p.PA0.degrade_adc();
25 let mut adc_pin1 = p.PA1.degrade_adc();
26 let mut adc_dma_buf = [0u16; DMA_BUF_LEN];
27 let mut measurements = [0u16; DMA_BUF_LEN / 2];
28 let mut ring_buffered_adc = adc.into_ring_buffered(
29 p.DMA1_CH1,
30 &mut adc_dma_buf,
31 [
32 (&mut adc_pin0, SampleTime::CYCLES640_5),
33 (&mut adc_pin1, SampleTime::CYCLES640_5),
34 ]
35 .into_iter(),
36 );
37
38 info!("starting measurement loop");
39 loop {
40 match ring_buffered_adc.read(&mut measurements).await {
41 Ok(_) => {
42 //note: originally there was a print here showing all the samples,
43 //but even that takes too much time and would cause adc overruns
44 info!("adc1 first 10 samples: {}", measurements[0..10]);
45 }
46 Err(e) => {
47 warn!("Error: {:?}", e);
48 }
49 }
50 }
51}
diff --git a/examples/stm32l5/src/bin/stop.rs b/examples/stm32l5/src/bin/stop.rs
index c34053190..7662dbfa8 100644
--- a/examples/stm32l5/src/bin/stop.rs
+++ b/examples/stm32l5/src/bin/stop.rs
@@ -9,7 +9,6 @@ use embassy_stm32::rcc::LsConfig;
9use embassy_stm32::rtc::{Rtc, RtcConfig}; 9use embassy_stm32::rtc::{Rtc, RtcConfig};
10use embassy_stm32::{Config, Peri}; 10use embassy_stm32::{Config, Peri};
11use embassy_time::Timer; 11use embassy_time::Timer;
12use static_cell::StaticCell;
13use {defmt_rtt as _, panic_probe as _}; 12use {defmt_rtt as _, panic_probe as _};
14 13
15#[cortex_m_rt::entry] 14#[cortex_m_rt::entry]
@@ -30,8 +29,6 @@ async fn async_main(spawner: Spawner) {
30 29
31 // give the RTC to the executor... 30 // give the RTC to the executor...
32 let rtc = Rtc::new(p.RTC, RtcConfig::default()); 31 let rtc = Rtc::new(p.RTC, RtcConfig::default());
33 static RTC: StaticCell<Rtc> = StaticCell::new();
34 let rtc = RTC.init(rtc);
35 embassy_stm32::low_power::stop_with_rtc(rtc); 32 embassy_stm32::low_power::stop_with_rtc(rtc);
36 33
37 spawner.spawn(unwrap!(blinky(p.PC7.into()))); 34 spawner.spawn(unwrap!(blinky(p.PC7.into())));
diff --git a/examples/stm32wle5/.cargo/config.toml b/examples/stm32wle5/.cargo/config.toml
new file mode 100644
index 000000000..0178d377c
--- /dev/null
+++ b/examples/stm32wle5/.cargo/config.toml
@@ -0,0 +1,9 @@
1[target.'cfg(all(target_arch = "arm", target_os = "none"))']
2# replace your chip as listed in `probe-rs chip list`
3runner = "probe-rs run --chip STM32WLE5JCIx --connect-under-reset"
4
5[build]
6target = "thumbv7em-none-eabi"
7
8[env]
9DEFMT_LOG = "info"
diff --git a/examples/stm32wle5/Cargo.toml b/examples/stm32wle5/Cargo.toml
new file mode 100644
index 000000000..f2fc4dd3d
--- /dev/null
+++ b/examples/stm32wle5/Cargo.toml
@@ -0,0 +1,38 @@
1[package]
2edition = "2024"
3name = "embassy-stm32wl-examples"
4version = "0.1.0"
5license = "MIT OR Apache-2.0"
6publish = false
7
8[dependencies]
9# Change stm32wl55jc-cm4 to your chip name, if necessary.
10embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = ["defmt", "stm32wle5jc", "time-driver-any", "memory-x", "unstable-pac", "exti", "low-power"] }
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-1_000"] }
14embassy-embedded-hal = { version = "0.5.0", path = "../../embassy-embedded-hal" }
15
16defmt = "1.0.1"
17defmt-rtt = { version = "1.1.0", optional = true }
18defmt-serial = { version = "0.10.0", optional = true }
19
20cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
21cortex-m-rt = "0.7.0"
22embedded-hal = "1.0.0"
23embedded-storage = "0.3.1"
24panic-probe = { version = "1.0.0", features = ["print-defmt"] }
25static_cell = { version = "2.1.1", default-features = false }
26
27[profile.release]
28debug = 2
29
30[package.metadata.embassy]
31build = [
32 { target = "thumbv7em-none-eabi", artifact-dir = "out/examples/stm32wl" }
33]
34
35[features]
36default = ["defmt-serial"]
37defmt-rtt = ["dep:defmt-rtt"]
38defmt-serial = ["dep:defmt-serial"]
diff --git a/examples/stm32wle5/README.md b/examples/stm32wle5/README.md
new file mode 100644
index 000000000..18c3b5071
--- /dev/null
+++ b/examples/stm32wle5/README.md
@@ -0,0 +1,52 @@
1# Low Power Examples for STM32WLEx family
2
3Examples in this repo should work with [LoRa-E5 Dev Board](https://www.st.com/en/partner-products-and-services/lora-e5-development-kit.html) board.
4
5## Prerequsits
6
7- Connect a usb serial adapter to LPUart1 (this is where ALL logging will go)
8- Optional: Connect an amp meter that ran measure down to 0.1uA to the power test pins
9- `cargo install defmt-print` so you can print log messahes from LPUart1
10
11## Example Notes
12
13All examples will set all pins to analog mode before configuring pins for the example, if any. This saves about 500uA!!!!
14
15- the `adc` example will sleep in STOP1 betwen samples and the chip will only draw about 13uA while sleeping
16- the `blinky` example will sleep in STOP2 and the chip will only draw 1uA or less while sleeping
17- the `button_exti` example will sleep in STOP2 and the chip will only draw 1uA or less while sleeping
18- the `i2c` examples will sleep in STOP1 between reads and the chip only draw about 10uA while sleeping
19
20For each example you will need to start `defmt-print` with the example binary and the correct serial port in a seperate terminal. Example:
21```
22defmt-print -w -v -e target/thumbv7em-none-eabi/debug/<module-name> serial --path /dev/cu.usbserial-00000000 --baud 115200
23```
24
25Run individual examples with
26```
27cargo flash --chip STM32WLE5JCIx --connect-under-reset --bin <module-name>
28```
29for example
30```
31cargo flash --chip STM32WLE5JCIx --connect-under-reset --bin blinky
32```
33
34You can also run them with with `run`. However in this case expect probe-rs to be disconnected as soon as flashing is done as all IO pins are set to analog input!
35```
36cargo run --bin blinky
37```
38
39## Checklist before running examples
40You might need to adjust `.cargo/config.toml`, `Cargo.toml` and possibly update pin numbers or peripherals to match the specific MCU or board you are using.
41
42* [ ] Update .cargo/config.toml with the correct probe-rs command to use your specific MCU. For example for L432KCU6 it should be `probe-rs run --chip STM32L432KCUx`. (use `probe-rs chip list` to find your chip)
43* [ ] Update Cargo.toml to have the correct `embassy-stm32` feature. For example for L432KCU6 it should be `stm32l432kc`. Look in the `Cargo.toml` file of the `embassy-stm32` project to find the correct feature flag for your chip.
44* [ ] If your board has a special clock or power configuration, make sure that it is set up appropriately.
45* [ ] If your board has different pin mapping, update any pin numbers or peripherals in the given example code to match your schematic
46
47If you are unsure, please drop by the Embassy Matrix chat for support, and let us know:
48
49* Which example you are trying to run
50* Which chip and board you are using
51
52Embassy Chat: https://matrix.to/#/#embassy-rs:matrix.org
diff --git a/examples/stm32wle5/build.rs b/examples/stm32wle5/build.rs
new file mode 100644
index 000000000..8cd32d7ed
--- /dev/null
+++ b/examples/stm32wle5/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/stm32wle5/src/bin/adc.rs b/examples/stm32wle5/src/bin/adc.rs
new file mode 100644
index 000000000..ff1a5fa16
--- /dev/null
+++ b/examples/stm32wle5/src/bin/adc.rs
@@ -0,0 +1,100 @@
1#![no_std]
2#![no_main]
3
4use defmt::*;
5#[cfg(feature = "defmt-rtt")]
6use defmt_rtt as _;
7use embassy_executor::Spawner;
8use embassy_stm32::adc::{Adc, SampleTime};
9use embassy_stm32::low_power::Executor;
10use embassy_stm32::rtc::{Rtc, RtcConfig};
11use embassy_time::Timer;
12use panic_probe as _;
13use static_cell::StaticCell;
14
15#[cortex_m_rt::entry]
16fn main() -> ! {
17 info!("main: Starting!");
18 Executor::take().run(|spawner| {
19 spawner.spawn(unwrap!(async_main(spawner)));
20 });
21}
22
23#[embassy_executor::task]
24async fn async_main(_spawner: Spawner) {
25 let mut config = embassy_stm32::Config::default();
26 // enable HSI clock
27 config.rcc.hsi = true;
28 // enable LSI clock for RTC
29 config.rcc.ls = embassy_stm32::rcc::LsConfig::default_lsi();
30 config.rcc.msi = Some(embassy_stm32::rcc::MSIRange::RANGE4M);
31 config.rcc.sys = embassy_stm32::rcc::Sysclk::MSI;
32 // enable ADC with HSI clock
33 config.rcc.mux.adcsel = embassy_stm32::pac::rcc::vals::Adcsel::HSI;
34 #[cfg(feature = "defmt-serial")]
35 {
36 // disable debug during sleep to reduce power consumption since we are
37 // using defmt-serial on LPUART1.
38 config.enable_debug_during_sleep = false;
39 // if we are using defmt-serial on LPUART1, we need to use HSI for the clock
40 // so that its registers are preserved during STOP modes.
41 config.rcc.mux.lpuart1sel = embassy_stm32::pac::rcc::vals::Lpuart1sel::HSI;
42 }
43 // Initialize STM32WL peripherals (use default config like wio-e5-async example)
44 let p = embassy_stm32::init(config);
45
46 // start with all GPIOs as analog to reduce power consumption
47 for r in [
48 embassy_stm32::pac::GPIOA,
49 embassy_stm32::pac::GPIOB,
50 embassy_stm32::pac::GPIOC,
51 embassy_stm32::pac::GPIOH,
52 ] {
53 r.moder().modify(|w| {
54 for i in 0..16 {
55 // don't reset these if probe-rs should stay connected!
56 #[cfg(feature = "defmt-rtt")]
57 if config.enable_debug_during_sleep && r == embassy_stm32::pac::GPIOA && [13, 14].contains(&i) {
58 continue;
59 }
60 w.set_moder(i, embassy_stm32::pac::gpio::vals::Moder::ANALOG);
61 }
62 });
63 }
64 #[cfg(feature = "defmt-serial")]
65 {
66 use embassy_stm32::mode::Blocking;
67 use embassy_stm32::usart::Uart;
68 let config = embassy_stm32::usart::Config::default();
69 let uart = Uart::new_blocking(p.LPUART1, p.PC0, p.PC1, config).expect("failed to configure UART!");
70 static SERIAL: StaticCell<Uart<'static, Blocking>> = StaticCell::new();
71 defmt_serial::defmt_serial(SERIAL.init(uart));
72 }
73
74 // give the RTC to the low_power executor...
75 let rtc_config = RtcConfig::default();
76 let rtc = Rtc::new(p.RTC, rtc_config);
77 embassy_stm32::low_power::stop_with_rtc(rtc);
78
79 info!("Hello World!");
80
81 let mut adc = Adc::new(p.ADC1);
82 adc.set_sample_time(SampleTime::CYCLES79_5);
83 let mut pin = p.PA10;
84
85 let mut vrefint = adc.enable_vrefint();
86 let vrefint_sample = adc.blocking_read(&mut vrefint);
87 let convert_to_millivolts = |sample| {
88 // From https://www.st.com/resource/en/datasheet/stm32g031g8.pdf
89 // 6.3.3 Embedded internal reference voltage
90 const VREFINT_MV: u32 = 1212; // mV
91
92 (u32::from(sample) * VREFINT_MV / u32::from(vrefint_sample)) as u16
93 };
94
95 loop {
96 let v = adc.blocking_read(&mut pin);
97 info!("--> {} - {} mV", v, convert_to_millivolts(v));
98 Timer::after_secs(1).await;
99 }
100}
diff --git a/examples/stm32wle5/src/bin/blinky.rs b/examples/stm32wle5/src/bin/blinky.rs
new file mode 100644
index 000000000..1191a1157
--- /dev/null
+++ b/examples/stm32wle5/src/bin/blinky.rs
@@ -0,0 +1,90 @@
1#![no_std]
2#![no_main]
3
4use defmt::*;
5#[cfg(feature = "defmt-rtt")]
6use defmt_rtt as _;
7use embassy_executor::Spawner;
8use embassy_stm32::gpio::{Level, Output, Speed};
9use embassy_stm32::low_power::Executor;
10use embassy_stm32::rtc::{Rtc, RtcConfig};
11use embassy_time::Timer;
12use panic_probe as _;
13use static_cell::StaticCell;
14
15#[cortex_m_rt::entry]
16fn main() -> ! {
17 info!("main: Starting!");
18 Executor::take().run(|spawner| {
19 spawner.spawn(unwrap!(async_main(spawner)));
20 });
21}
22
23#[embassy_executor::task]
24async fn async_main(_spawner: Spawner) {
25 let mut config = embassy_stm32::Config::default();
26 // enable HSI clock
27 config.rcc.hsi = true;
28 // enable LSI clock for RTC
29 config.rcc.ls = embassy_stm32::rcc::LsConfig::default_lsi();
30 config.rcc.msi = Some(embassy_stm32::rcc::MSIRange::RANGE4M);
31 config.rcc.sys = embassy_stm32::rcc::Sysclk::MSI;
32 #[cfg(feature = "defmt-serial")]
33 {
34 // disable debug during sleep to reduce power consumption since we are
35 // using defmt-serial on LPUART1.
36 config.enable_debug_during_sleep = false;
37 // if we are using defmt-serial on LPUART1, we need to use HSI for the clock
38 // so that its registers are preserved during STOP modes.
39 config.rcc.mux.lpuart1sel = embassy_stm32::pac::rcc::vals::Lpuart1sel::HSI;
40 }
41 // Initialize STM32WL peripherals (use default config like wio-e5-async example)
42 let p = embassy_stm32::init(config);
43
44 // start with all GPIOs as analog to reduce power consumption
45 for r in [
46 embassy_stm32::pac::GPIOA,
47 embassy_stm32::pac::GPIOB,
48 embassy_stm32::pac::GPIOC,
49 embassy_stm32::pac::GPIOH,
50 ] {
51 r.moder().modify(|w| {
52 for i in 0..16 {
53 // don't reset these if probe-rs should stay connected!
54 #[cfg(feature = "defmt-rtt")]
55 if config.enable_debug_during_sleep && r == embassy_stm32::pac::GPIOA && [13, 14].contains(&i) {
56 continue;
57 }
58 w.set_moder(i, embassy_stm32::pac::gpio::vals::Moder::ANALOG);
59 }
60 });
61 }
62 #[cfg(feature = "defmt-serial")]
63 {
64 use embassy_stm32::mode::Blocking;
65 use embassy_stm32::usart::Uart;
66 let config = embassy_stm32::usart::Config::default();
67 let uart = Uart::new_blocking(p.LPUART1, p.PC0, p.PC1, config).expect("failed to configure UART!");
68 static SERIAL: StaticCell<Uart<'static, Blocking>> = StaticCell::new();
69 defmt_serial::defmt_serial(SERIAL.init(uart));
70 }
71
72 // give the RTC to the low_power executor...
73 let rtc_config = RtcConfig::default();
74 let rtc = Rtc::new(p.RTC, rtc_config);
75 embassy_stm32::low_power::stop_with_rtc(rtc);
76
77 info!("Hello World!");
78
79 let mut led = Output::new(p.PB5, Level::High, Speed::Low);
80
81 loop {
82 info!("low");
83 led.set_low();
84 Timer::after_millis(500).await;
85
86 info!("high");
87 led.set_high();
88 Timer::after_millis(500).await;
89 }
90}
diff --git a/examples/stm32wle5/src/bin/button_exti.rs b/examples/stm32wle5/src/bin/button_exti.rs
new file mode 100644
index 000000000..f07f9724d
--- /dev/null
+++ b/examples/stm32wle5/src/bin/button_exti.rs
@@ -0,0 +1,91 @@
1#![no_std]
2#![no_main]
3
4use defmt::*;
5#[cfg(feature = "defmt-rtt")]
6use defmt_rtt as _;
7use embassy_executor::Spawner;
8use embassy_stm32::exti::ExtiInput;
9use embassy_stm32::gpio::Pull;
10use embassy_stm32::low_power::Executor;
11use embassy_stm32::rtc::{Rtc, RtcConfig};
12use panic_probe as _;
13use static_cell::StaticCell;
14
15#[cortex_m_rt::entry]
16fn main() -> ! {
17 info!("main: Starting!");
18 Executor::take().run(|spawner| {
19 spawner.spawn(unwrap!(async_main(spawner)));
20 });
21}
22
23#[embassy_executor::task]
24async fn async_main(_spawner: Spawner) {
25 let mut config = embassy_stm32::Config::default();
26 // enable HSI clock
27 config.rcc.hsi = true;
28 // enable LSI clock for RTC
29 config.rcc.ls = embassy_stm32::rcc::LsConfig::default_lsi();
30 config.rcc.msi = Some(embassy_stm32::rcc::MSIRange::RANGE4M);
31 config.rcc.sys = embassy_stm32::rcc::Sysclk::MSI;
32 // enable ADC with HSI clock
33 config.rcc.mux.adcsel = embassy_stm32::pac::rcc::vals::Adcsel::HSI;
34 #[cfg(feature = "defmt-serial")]
35 {
36 // disable debug during sleep to reduce power consumption since we are
37 // using defmt-serial on LPUART1.
38 config.enable_debug_during_sleep = false;
39 // if we are using defmt-serial on LPUART1, we need to use HSI for the clock
40 // so that its registers are preserved during STOP modes.
41 config.rcc.mux.lpuart1sel = embassy_stm32::pac::rcc::vals::Lpuart1sel::HSI;
42 }
43 // Initialize STM32WL peripherals (use default config like wio-e5-async example)
44 let p = embassy_stm32::init(config);
45
46 // start with all GPIOs as analog to reduce power consumption
47 for r in [
48 embassy_stm32::pac::GPIOA,
49 embassy_stm32::pac::GPIOB,
50 embassy_stm32::pac::GPIOC,
51 embassy_stm32::pac::GPIOH,
52 ] {
53 r.moder().modify(|w| {
54 for i in 0..16 {
55 // don't reset these if probe-rs should stay connected!
56 #[cfg(feature = "defmt-rtt")]
57 if config.enable_debug_during_sleep && r == embassy_stm32::pac::GPIOA && [13, 14].contains(&i) {
58 continue;
59 }
60 w.set_moder(i, embassy_stm32::pac::gpio::vals::Moder::ANALOG);
61 }
62 });
63 }
64 #[cfg(feature = "defmt-serial")]
65 {
66 use embassy_stm32::mode::Blocking;
67 use embassy_stm32::usart::Uart;
68 let config = embassy_stm32::usart::Config::default();
69 let uart = Uart::new_blocking(p.LPUART1, p.PC0, p.PC1, config).expect("failed to configure UART!");
70 static SERIAL: StaticCell<Uart<'static, Blocking>> = StaticCell::new();
71 defmt_serial::defmt_serial(SERIAL.init(uart));
72 }
73
74 // give the RTC to the low_power executor...
75 let rtc_config = RtcConfig::default();
76 let rtc = Rtc::new(p.RTC, rtc_config);
77 embassy_stm32::low_power::stop_with_rtc(rtc);
78
79 info!("Hello World!");
80
81 let mut button = ExtiInput::new(p.PA0, p.EXTI0, Pull::Up);
82
83 info!("Press the USER button...");
84
85 loop {
86 button.wait_for_falling_edge().await;
87 info!("Pressed!");
88 button.wait_for_rising_edge().await;
89 info!("Released!");
90 }
91}
diff --git a/examples/stm32wle5/src/bin/i2c.rs b/examples/stm32wle5/src/bin/i2c.rs
new file mode 100644
index 000000000..af07f911e
--- /dev/null
+++ b/examples/stm32wle5/src/bin/i2c.rs
@@ -0,0 +1,110 @@
1#![no_std]
2#![no_main]
3
4use defmt::*;
5#[cfg(feature = "defmt-rtt")]
6use defmt_rtt as _;
7use embassy_executor::Spawner;
8use embassy_stm32::i2c::I2c;
9use embassy_stm32::low_power::Executor;
10use embassy_stm32::rtc::{Rtc, RtcConfig};
11use embassy_stm32::time::Hertz;
12use embassy_stm32::{bind_interrupts, i2c, peripherals};
13use embassy_time::{Duration, Timer};
14use panic_probe as _;
15use static_cell::StaticCell;
16
17bind_interrupts!(struct IrqsI2C{
18 I2C2_EV => i2c::EventInterruptHandler<peripherals::I2C2>;
19 I2C2_ER => i2c::ErrorInterruptHandler<peripherals::I2C2>;
20});
21
22#[cortex_m_rt::entry]
23fn main() -> ! {
24 info!("main: Starting!");
25 Executor::take().run(|spawner| {
26 spawner.spawn(unwrap!(async_main(spawner)));
27 });
28}
29
30#[embassy_executor::task]
31async fn async_main(_spawner: Spawner) {
32 let mut config = embassy_stm32::Config::default();
33 // enable HSI clock
34 config.rcc.hsi = true;
35 // enable LSI clock for RTC
36 config.rcc.ls = embassy_stm32::rcc::LsConfig::default_lsi();
37 config.rcc.msi = Some(embassy_stm32::rcc::MSIRange::RANGE4M);
38 config.rcc.sys = embassy_stm32::rcc::Sysclk::MSI;
39 // enable ADC with HSI clock
40 config.rcc.mux.i2c2sel = embassy_stm32::pac::rcc::vals::I2c2sel::HSI;
41 #[cfg(feature = "defmt-serial")]
42 {
43 // disable debug during sleep to reduce power consumption since we are
44 // using defmt-serial on LPUART1.
45 config.enable_debug_during_sleep = false;
46 // if we are using defmt-serial on LPUART1, we need to use HSI for the clock
47 // so that its registers are preserved during STOP modes.
48 config.rcc.mux.lpuart1sel = embassy_stm32::pac::rcc::vals::Lpuart1sel::HSI;
49 }
50 // Initialize STM32WL peripherals (use default config like wio-e5-async example)
51 let p = embassy_stm32::init(config);
52
53 // start with all GPIOs as analog to reduce power consumption
54 for r in [
55 embassy_stm32::pac::GPIOA,
56 embassy_stm32::pac::GPIOB,
57 embassy_stm32::pac::GPIOC,
58 embassy_stm32::pac::GPIOH,
59 ] {
60 r.moder().modify(|w| {
61 for i in 0..16 {
62 // don't reset these if probe-rs should stay connected!
63 #[cfg(feature = "defmt-rtt")]
64 if config.enable_debug_during_sleep && r == embassy_stm32::pac::GPIOA && [13, 14].contains(&i) {
65 continue;
66 }
67 w.set_moder(i, embassy_stm32::pac::gpio::vals::Moder::ANALOG);
68 }
69 });
70 }
71 #[cfg(feature = "defmt-serial")]
72 {
73 use embassy_stm32::mode::Blocking;
74 use embassy_stm32::usart::Uart;
75 let config = embassy_stm32::usart::Config::default();
76 let uart = Uart::new_blocking(p.LPUART1, p.PC0, p.PC1, config).expect("failed to configure UART!");
77 static SERIAL: StaticCell<Uart<'static, Blocking>> = StaticCell::new();
78 defmt_serial::defmt_serial(SERIAL.init(uart));
79 }
80
81 // give the RTC to the low_power executor...
82 let rtc_config = RtcConfig::default();
83 let rtc = Rtc::new(p.RTC, rtc_config);
84 embassy_stm32::low_power::stop_with_rtc(rtc);
85
86 info!("Hello World!");
87 let en3v3 = embassy_stm32::gpio::Output::new(
88 p.PA9,
89 embassy_stm32::gpio::Level::High,
90 embassy_stm32::gpio::Speed::High,
91 );
92 core::mem::forget(en3v3); // keep the output pin enabled
93
94 let mut i2c = I2c::new(p.I2C2, p.PB15, p.PA15, IrqsI2C, p.DMA1_CH6, p.DMA1_CH7, {
95 let mut config = i2c::Config::default();
96 config.frequency = Hertz::khz(100);
97 config.timeout = Duration::from_millis(500);
98 config
99 });
100
101 loop {
102 let mut buffer = [0; 2];
103 // read the temperature register of the onboard lm75
104 match i2c.read(0x48, &mut buffer).await {
105 Ok(_) => info!("--> {:?}", buffer),
106 Err(e) => info!("--> Error: {:?}", e),
107 }
108 Timer::after_secs(5).await;
109 }
110}
diff --git a/examples/stm32wle5/stm32wle5.code-workspace b/examples/stm32wle5/stm32wle5.code-workspace
new file mode 100644
index 000000000..a7c4a0ebd
--- /dev/null
+++ b/examples/stm32wle5/stm32wle5.code-workspace
@@ -0,0 +1,13 @@
1{
2 "folders": [
3 {
4 "path": "."
5 }
6 ],
7 "settings": {
8 "rust-analyzer.cargo.target": "thumbv7em-none-eabi",
9 "rust-analyzer.cargo.allTargets": false,
10 "rust-analyzer.cargo.targetDir": "target/rust-analyzer",
11 "rust-analyzer.checkOnSave": true,
12 }
13}