aboutsummaryrefslogtreecommitdiff
path: root/examples
diff options
context:
space:
mode:
authoreverdrone <[email protected]>2025-11-10 02:01:56 +0100
committerGitHub <[email protected]>2025-11-10 02:01:56 +0100
commit5926690bfbd366beca13c8b5d0ab4b7a3519aa44 (patch)
tree4b0df8b2b36c3324364e8aa49b4d8fea93cc485c /examples
parente2807058ffc73bd0fc2f4ce9f29e5a56f3e5a18e (diff)
parent4ef7f91663b51e2cfeb6ef40d907bfff90737de8 (diff)
Merge branch 'main' into stm32_sai_frame_length
Diffstat (limited to 'examples')
-rw-r--r--examples/lpc55s69/src/bin/pwm.rs18
-rw-r--r--examples/nrf52840/src/bin/egu.rs15
-rw-r--r--examples/nrf52840/src/bin/gpiote_channel.rs26
-rw-r--r--examples/nrf52840/src/bin/i2s_monitor.rs9
-rw-r--r--examples/nrf52840/src/bin/ppi.rs34
-rw-r--r--examples/nrf52840/src/bin/pwm.rs14
-rw-r--r--examples/nrf52840/src/bin/pwm_sequence_ppi.rs14
-rw-r--r--examples/nrf52840/src/bin/pwm_servo.rs14
-rw-r--r--examples/nrf52840/src/bin/wifi_esp_hosted.rs16
-rw-r--r--examples/nrf5340/src/bin/gpiote_channel.rs26
-rw-r--r--examples/nrf54l15/Cargo.toml7
-rw-r--r--examples/nrf54l15/src/bin/buffered_uart.rs49
-rw-r--r--examples/nrf54l15/src/bin/gpiote_channel.rs49
-rw-r--r--examples/nrf54l15/src/bin/gpiote_port.rs33
-rw-r--r--examples/nrf54l15/src/bin/pwm.rs86
-rw-r--r--examples/nrf54l15/src/bin/rng.rs28
-rw-r--r--examples/nrf54l15/src/bin/saadc.rs28
-rw-r--r--examples/nrf54l15/src/bin/spim.rs30
-rw-r--r--examples/nrf54l15/src/bin/twim.rs37
-rw-r--r--examples/nrf54l15/src/bin/twis.rs47
-rw-r--r--examples/nrf54l15/src/bin/uart.rs37
-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/stm32c0/src/bin/rtc.rs4
-rw-r--r--examples/stm32f4/src/bin/adc_dma.rs29
-rw-r--r--examples/stm32f4/src/bin/eth_w5500.rs3
-rw-r--r--examples/stm32f4/src/bin/i2c_slave_async.rs135
-rw-r--r--examples/stm32f4/src/bin/i2c_slave_blocking.rs132
-rw-r--r--examples/stm32f4/src/bin/rtc.rs4
-rw-r--r--examples/stm32g0/src/bin/onewire_ds18b20.rs2
-rw-r--r--examples/stm32g0/src/bin/rtc.rs4
-rw-r--r--examples/stm32g4/Cargo.toml13
-rw-r--r--examples/stm32g4/src/bin/adc_dma.rs4
-rw-r--r--examples/stm32g4/src/bin/adc_injected_and_regular.rs154
-rw-r--r--examples/stm32h5/Cargo.toml2
-rw-r--r--examples/stm32h5/src/bin/backup_sram.rs31
-rw-r--r--examples/stm32h5/src/bin/stop.rs8
-rw-r--r--examples/stm32h7/Cargo.toml2
-rw-r--r--examples/stm32h7/src/bin/rtc.rs4
-rw-r--r--examples/stm32h7/src/bin/spi.rs2
-rw-r--r--examples/stm32h7/src/bin/spi_bdma.rs2
-rw-r--r--examples/stm32h7/src/bin/spi_dma.rs2
-rw-r--r--examples/stm32h755cm4/Cargo.toml2
-rw-r--r--examples/stm32h755cm7/Cargo.toml2
-rw-r--r--examples/stm32h7b0/Cargo.toml2
-rw-r--r--examples/stm32h7rs/Cargo.toml2
-rw-r--r--examples/stm32h7rs/src/bin/rtc.rs4
-rw-r--r--examples/stm32h7rs/src/bin/spi.rs2
-rw-r--r--examples/stm32h7rs/src/bin/spi_dma.rs2
-rw-r--r--examples/stm32l4/src/bin/adc_dma.rs51
-rw-r--r--examples/stm32l4/src/bin/rtc.rs4
-rw-r--r--examples/stm32l4/src/bin/spe_adin1110_http_server.rs3
-rw-r--r--examples/stm32l5/src/bin/stop.rs8
-rw-r--r--examples/stm32u0/src/bin/rtc.rs4
-rw-r--r--examples/stm32wl/src/bin/rtc.rs4
-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.rs94
-rw-r--r--examples/stm32wle5/src/bin/blinky.rs84
-rw-r--r--examples/stm32wle5/src/bin/button_exti.rs85
-rw-r--r--examples/stm32wle5/src/bin/i2c.rs104
-rw-r--r--examples/stm32wle5/stm32wle5.code-workspace13
66 files changed, 1558 insertions, 178 deletions
diff --git a/examples/lpc55s69/src/bin/pwm.rs b/examples/lpc55s69/src/bin/pwm.rs
new file mode 100644
index 000000000..93b898b9d
--- /dev/null
+++ b/examples/lpc55s69/src/bin/pwm.rs
@@ -0,0 +1,18 @@
1#![no_std]
2#![no_main]
3
4use defmt::*;
5use embassy_executor::Spawner;
6use embassy_nxp::pwm::{Config, Pwm};
7use embassy_time::Timer;
8use {defmt_rtt as _, panic_halt as _};
9
10#[embassy_executor::main]
11async fn main(_spawner: Spawner) {
12 let p = embassy_nxp::init(Default::default());
13 let pwm = Pwm::new_output(p.PWM_OUTPUT1, p.PIO0_18, Config::new(1_000_000_000, 2_000_000_000));
14 loop {
15 info!("Counter: {}", pwm.counter());
16 Timer::after_millis(50).await;
17 }
18}
diff --git a/examples/nrf52840/src/bin/egu.rs b/examples/nrf52840/src/bin/egu.rs
index 8bf712697..36eba8084 100644
--- a/examples/nrf52840/src/bin/egu.rs
+++ b/examples/nrf52840/src/bin/egu.rs
@@ -6,7 +6,7 @@
6 6
7use embassy_executor::Spawner; 7use embassy_executor::Spawner;
8use embassy_nrf::egu::{Egu, TriggerNumber}; 8use embassy_nrf::egu::{Egu, TriggerNumber};
9use embassy_nrf::gpio::{Input, Level, Output, OutputDrive, Pull}; 9use embassy_nrf::gpio::{Level, OutputDrive, Pull};
10use embassy_nrf::gpiote::{InputChannel, InputChannelPolarity, OutputChannel, OutputChannelPolarity}; 10use embassy_nrf::gpiote::{InputChannel, InputChannelPolarity, OutputChannel, OutputChannelPolarity};
11use embassy_nrf::peripherals::{PPI_CH0, PPI_CH1, PPI_CH2}; 11use embassy_nrf::peripherals::{PPI_CH0, PPI_CH1, PPI_CH2};
12use embassy_nrf::ppi::Ppi; 12use embassy_nrf::ppi::Ppi;
@@ -17,12 +17,15 @@ use {defmt_rtt as _, panic_probe as _};
17async fn main(_spawner: Spawner) { 17async fn main(_spawner: Spawner) {
18 let p = embassy_nrf::init(Default::default()); 18 let p = embassy_nrf::init(Default::default());
19 19
20 let led1 = Output::new(p.P0_13, Level::High, OutputDrive::Standard);
21 let btn1 = Input::new(p.P0_11, Pull::Up);
22
23 let mut egu1 = Egu::new(p.EGU0); 20 let mut egu1 = Egu::new(p.EGU0);
24 let led1 = OutputChannel::new(p.GPIOTE_CH0, led1, OutputChannelPolarity::Toggle); 21 let led1 = OutputChannel::new(
25 let btn1 = InputChannel::new(p.GPIOTE_CH1, btn1, InputChannelPolarity::LoToHi); 22 p.GPIOTE_CH0,
23 p.P0_13,
24 Level::High,
25 OutputDrive::Standard,
26 OutputChannelPolarity::Toggle,
27 );
28 let btn1 = InputChannel::new(p.GPIOTE_CH1, p.P0_11, Pull::Up, InputChannelPolarity::LoToHi);
26 29
27 let trigger0 = egu1.trigger(TriggerNumber::Trigger0); 30 let trigger0 = egu1.trigger(TriggerNumber::Trigger0);
28 let trigger1 = egu1.trigger(TriggerNumber::Trigger1); 31 let trigger1 = egu1.trigger(TriggerNumber::Trigger1);
diff --git a/examples/nrf52840/src/bin/gpiote_channel.rs b/examples/nrf52840/src/bin/gpiote_channel.rs
index dcfe7723a..c7ddc1d8d 100644
--- a/examples/nrf52840/src/bin/gpiote_channel.rs
+++ b/examples/nrf52840/src/bin/gpiote_channel.rs
@@ -3,7 +3,7 @@
3 3
4use defmt::info; 4use defmt::info;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_nrf::gpio::{Input, Pull}; 6use embassy_nrf::gpio::Pull;
7use embassy_nrf::gpiote::{InputChannel, InputChannelPolarity}; 7use embassy_nrf::gpiote::{InputChannel, InputChannelPolarity};
8use {defmt_rtt as _, panic_probe as _}; 8use {defmt_rtt as _, panic_probe as _};
9 9
@@ -12,26 +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( 15 let ch1 = InputChannel::new(p.GPIOTE_CH0, p.P0_11, Pull::Up, InputChannelPolarity::HiToLo);
16 p.GPIOTE_CH0, 16 let ch2 = InputChannel::new(p.GPIOTE_CH1, p.P0_12, Pull::Up, InputChannelPolarity::LoToHi);
17 Input::new(p.P0_11, Pull::Up), 17 let ch3 = InputChannel::new(p.GPIOTE_CH2, p.P0_24, Pull::Up, InputChannelPolarity::Toggle);
18 InputChannelPolarity::HiToLo, 18 let ch4 = InputChannel::new(p.GPIOTE_CH3, p.P0_25, Pull::Up, InputChannelPolarity::Toggle);
19 );
20 let ch2 = InputChannel::new(
21 p.GPIOTE_CH1,
22 Input::new(p.P0_12, Pull::Up),
23 InputChannelPolarity::LoToHi,
24 );
25 let ch3 = InputChannel::new(
26 p.GPIOTE_CH2,
27 Input::new(p.P0_24, Pull::Up),
28 InputChannelPolarity::Toggle,
29 );
30 let ch4 = InputChannel::new(
31 p.GPIOTE_CH3,
32 Input::new(p.P0_25, Pull::Up),
33 InputChannelPolarity::Toggle,
34 );
35 19
36 let button1 = async { 20 let button1 = async {
37 loop { 21 loop {
diff --git a/examples/nrf52840/src/bin/i2s_monitor.rs b/examples/nrf52840/src/bin/i2s_monitor.rs
index 66b429b09..a54659101 100644
--- a/examples/nrf52840/src/bin/i2s_monitor.rs
+++ b/examples/nrf52840/src/bin/i2s_monitor.rs
@@ -4,7 +4,7 @@
4use defmt::{debug, error, info}; 4use defmt::{debug, error, info};
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_nrf::i2s::{self, Channels, Config, DoubleBuffering, I2S, MasterClock, Sample as _, SampleWidth}; 6use embassy_nrf::i2s::{self, Channels, Config, DoubleBuffering, I2S, MasterClock, Sample as _, SampleWidth};
7use embassy_nrf::pwm::{Prescaler, SimplePwm}; 7use embassy_nrf::pwm::{DutyCycle, Prescaler, SimplePwm};
8use embassy_nrf::{bind_interrupts, peripherals}; 8use embassy_nrf::{bind_interrupts, peripherals};
9use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
10 10
@@ -34,7 +34,7 @@ async fn main(_spawner: Spawner) {
34 I2S::new_master(p.I2S, Irqs, p.P0_25, p.P0_26, p.P0_27, master_clock, config).input(p.P0_29, buffers); 34 I2S::new_master(p.I2S, Irqs, p.P0_25, p.P0_26, p.P0_27, master_clock, config).input(p.P0_29, buffers);
35 35
36 // Configure the PWM to use the pins corresponding to the RGB leds 36 // Configure the PWM to use the pins corresponding to the RGB leds
37 let mut pwm = SimplePwm::new_3ch(p.PWM0, p.P0_23, p.P0_22, p.P0_24); 37 let mut pwm = SimplePwm::new_3ch(p.PWM0, p.P0_23, p.P0_22, p.P0_24, &Default::default());
38 pwm.set_prescaler(Prescaler::Div1); 38 pwm.set_prescaler(Prescaler::Div1);
39 pwm.set_max_duty(255); 39 pwm.set_max_duty(255);
40 40
@@ -47,9 +47,8 @@ async fn main(_spawner: Spawner) {
47 let rgb = rgb_from_rms(rms); 47 let rgb = rgb_from_rms(rms);
48 48
49 debug!("RMS: {}, RGB: {:?}", rms, rgb); 49 debug!("RMS: {}, RGB: {:?}", rms, rgb);
50 for i in 0..3 { 50 let duties = rgb.map(|byte| DutyCycle::normal(u16::from(byte)));
51 pwm.set_duty(i, rgb[i].into()); 51 pwm.set_all_duties([duties[0], duties[1], duties[2], DutyCycle::normal(0)]);
52 }
53 52
54 if let Err(err) = input_stream.receive().await { 53 if let Err(err) = input_stream.receive().await {
55 error!("{}", err); 54 error!("{}", err);
diff --git a/examples/nrf52840/src/bin/ppi.rs b/examples/nrf52840/src/bin/ppi.rs
index 129ad06e7..177f6a06d 100644
--- a/examples/nrf52840/src/bin/ppi.rs
+++ b/examples/nrf52840/src/bin/ppi.rs
@@ -5,7 +5,7 @@ use core::future::pending;
5 5
6use defmt::info; 6use defmt::info;
7use embassy_executor::Spawner; 7use embassy_executor::Spawner;
8use embassy_nrf::gpio::{Input, Level, Output, OutputDrive, Pull}; 8use embassy_nrf::gpio::{Level, OutputDrive, Pull};
9use embassy_nrf::gpiote::{self, InputChannel, InputChannelPolarity}; 9use embassy_nrf::gpiote::{self, InputChannel, InputChannelPolarity};
10use embassy_nrf::ppi::Ppi; 10use embassy_nrf::ppi::Ppi;
11use gpiote::{OutputChannel, OutputChannelPolarity}; 11use gpiote::{OutputChannel, OutputChannelPolarity};
@@ -16,36 +16,24 @@ async fn main(_spawner: Spawner) {
16 let p = embassy_nrf::init(Default::default()); 16 let p = embassy_nrf::init(Default::default());
17 info!("Starting!"); 17 info!("Starting!");
18 18
19 let button1 = InputChannel::new( 19 let button1 = InputChannel::new(p.GPIOTE_CH0, p.P0_11, Pull::Up, InputChannelPolarity::HiToLo);
20 p.GPIOTE_CH0, 20 let button2 = InputChannel::new(p.GPIOTE_CH1, p.P0_12, Pull::Up, InputChannelPolarity::HiToLo);
21 Input::new(p.P0_11, Pull::Up), 21 let button3 = InputChannel::new(p.GPIOTE_CH2, p.P0_24, Pull::Up, InputChannelPolarity::HiToLo);
22 InputChannelPolarity::HiToLo, 22 let button4 = InputChannel::new(p.GPIOTE_CH3, p.P0_25, Pull::Up, InputChannelPolarity::HiToLo);
23 );
24 let button2 = InputChannel::new(
25 p.GPIOTE_CH1,
26 Input::new(p.P0_12, Pull::Up),
27 InputChannelPolarity::HiToLo,
28 );
29 let button3 = InputChannel::new(
30 p.GPIOTE_CH2,
31 Input::new(p.P0_24, Pull::Up),
32 InputChannelPolarity::HiToLo,
33 );
34 let button4 = InputChannel::new(
35 p.GPIOTE_CH3,
36 Input::new(p.P0_25, Pull::Up),
37 InputChannelPolarity::HiToLo,
38 );
39 23
40 let led1 = OutputChannel::new( 24 let led1 = OutputChannel::new(
41 p.GPIOTE_CH4, 25 p.GPIOTE_CH4,
42 Output::new(p.P0_13, Level::Low, OutputDrive::Standard), 26 p.P0_13,
27 Level::Low,
28 OutputDrive::Standard,
43 OutputChannelPolarity::Toggle, 29 OutputChannelPolarity::Toggle,
44 ); 30 );
45 31
46 let led2 = OutputChannel::new( 32 let led2 = OutputChannel::new(
47 p.GPIOTE_CH5, 33 p.GPIOTE_CH5,
48 Output::new(p.P0_14, Level::Low, OutputDrive::Standard), 34 p.P0_14,
35 Level::Low,
36 OutputDrive::Standard,
49 OutputChannelPolarity::Toggle, 37 OutputChannelPolarity::Toggle,
50 ); 38 );
51 39
diff --git a/examples/nrf52840/src/bin/pwm.rs b/examples/nrf52840/src/bin/pwm.rs
index a5bb1347a..02f9b4191 100644
--- a/examples/nrf52840/src/bin/pwm.rs
+++ b/examples/nrf52840/src/bin/pwm.rs
@@ -3,7 +3,7 @@
3 3
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_nrf::pwm::{Prescaler, SimplePwm}; 6use embassy_nrf::pwm::{DutyCycle, Prescaler, SimplePwm};
7use embassy_time::Timer; 7use embassy_time::Timer;
8use {defmt_rtt as _, panic_probe as _}; 8use {defmt_rtt as _, panic_probe as _};
9 9
@@ -71,7 +71,7 @@ static DUTY: [u16; 1024] = [
71#[embassy_executor::main] 71#[embassy_executor::main]
72async fn main(_spawner: Spawner) { 72async fn main(_spawner: Spawner) {
73 let p = embassy_nrf::init(Default::default()); 73 let p = embassy_nrf::init(Default::default());
74 let mut pwm = SimplePwm::new_4ch(p.PWM0, p.P0_13, p.P0_14, p.P0_16, p.P0_15); 74 let mut pwm = SimplePwm::new_4ch(p.PWM0, p.P0_13, p.P0_14, p.P0_16, p.P0_15, &Default::default());
75 pwm.set_prescaler(Prescaler::Div1); 75 pwm.set_prescaler(Prescaler::Div1);
76 pwm.set_max_duty(32767); 76 pwm.set_max_duty(32767);
77 info!("pwm initialized!"); 77 info!("pwm initialized!");
@@ -79,10 +79,12 @@ async fn main(_spawner: Spawner) {
79 let mut i = 0; 79 let mut i = 0;
80 loop { 80 loop {
81 i += 1; 81 i += 1;
82 pwm.set_duty(0, DUTY[i % 1024]); 82 pwm.set_all_duties([
83 pwm.set_duty(1, DUTY[(i + 256) % 1024]); 83 DutyCycle::normal(DUTY[i % 1024]),
84 pwm.set_duty(2, DUTY[(i + 512) % 1024]); 84 DutyCycle::normal(DUTY[(i + 256) % 1024]),
85 pwm.set_duty(3, DUTY[(i + 768) % 1024]); 85 DutyCycle::normal(DUTY[(i + 512) % 1024]),
86 DutyCycle::normal(DUTY[(i + 768) % 1024]),
87 ]);
86 Timer::after_millis(3).await; 88 Timer::after_millis(3).await;
87 } 89 }
88} 90}
diff --git a/examples/nrf52840/src/bin/pwm_sequence_ppi.rs b/examples/nrf52840/src/bin/pwm_sequence_ppi.rs
index 60ea712b5..fff7decb2 100644
--- a/examples/nrf52840/src/bin/pwm_sequence_ppi.rs
+++ b/examples/nrf52840/src/bin/pwm_sequence_ppi.rs
@@ -5,7 +5,7 @@ use core::future::pending;
5 5
6use defmt::*; 6use defmt::*;
7use embassy_executor::Spawner; 7use embassy_executor::Spawner;
8use embassy_nrf::gpio::{Input, Pull}; 8use embassy_nrf::gpio::Pull;
9use embassy_nrf::gpiote::{InputChannel, InputChannelPolarity}; 9use embassy_nrf::gpiote::{InputChannel, InputChannelPolarity};
10use embassy_nrf::ppi::Ppi; 10use embassy_nrf::ppi::Ppi;
11use embassy_nrf::pwm::{Config, Prescaler, SequenceConfig, SequencePwm, SingleSequenceMode, SingleSequencer}; 11use embassy_nrf::pwm::{Config, Prescaler, SequenceConfig, SequencePwm, SingleSequenceMode, SingleSequencer};
@@ -30,17 +30,9 @@ async fn main(_spawner: Spawner) {
30 // pwm.stop() deconfigures pins, and then the task_start_seq0 task cant work 30 // pwm.stop() deconfigures pins, and then the task_start_seq0 task cant work
31 // so its going to have to start running in order load the configuration 31 // so its going to have to start running in order load the configuration
32 32
33 let button1 = InputChannel::new( 33 let button1 = InputChannel::new(p.GPIOTE_CH0, p.P0_11, Pull::Up, InputChannelPolarity::HiToLo);
34 p.GPIOTE_CH0,
35 Input::new(p.P0_11, Pull::Up),
36 InputChannelPolarity::HiToLo,
37 );
38 34
39 let button2 = InputChannel::new( 35 let button2 = InputChannel::new(p.GPIOTE_CH1, p.P0_12, Pull::Up, InputChannelPolarity::HiToLo);
40 p.GPIOTE_CH1,
41 Input::new(p.P0_12, Pull::Up),
42 InputChannelPolarity::HiToLo,
43 );
44 36
45 // messing with the pwm tasks is ill advised 37 // messing with the pwm tasks is ill advised
46 // Times::Ininite and Times even are seq0, Times odd is seq1 38 // Times::Ininite and Times even are seq0, Times odd is seq1
diff --git a/examples/nrf52840/src/bin/pwm_servo.rs b/examples/nrf52840/src/bin/pwm_servo.rs
index d772d2f5d..93cb984e6 100644
--- a/examples/nrf52840/src/bin/pwm_servo.rs
+++ b/examples/nrf52840/src/bin/pwm_servo.rs
@@ -3,14 +3,14 @@
3 3
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_nrf::pwm::{Prescaler, SimplePwm}; 6use embassy_nrf::pwm::{DutyCycle, Prescaler, SimplePwm};
7use embassy_time::Timer; 7use embassy_time::Timer;
8use {defmt_rtt as _, panic_probe as _}; 8use {defmt_rtt as _, panic_probe as _};
9 9
10#[embassy_executor::main] 10#[embassy_executor::main]
11async fn main(_spawner: Spawner) { 11async fn main(_spawner: Spawner) {
12 let p = embassy_nrf::init(Default::default()); 12 let p = embassy_nrf::init(Default::default());
13 let mut pwm = SimplePwm::new_1ch(p.PWM0, p.P0_05); 13 let mut pwm = SimplePwm::new_1ch(p.PWM0, p.P0_05, &Default::default());
14 // sg90 microervo requires 50hz or 20ms period 14 // sg90 microervo requires 50hz or 20ms period
15 // set_period can only set down to 125khz so we cant use it directly 15 // set_period can only set down to 125khz so we cant use it directly
16 // Div128 is 125khz or 0.000008s or 0.008ms, 20/0.008 is 2500 is top 16 // Div128 is 125khz or 0.000008s or 0.008ms, 20/0.008 is 2500 is top
@@ -24,23 +24,23 @@ async fn main(_spawner: Spawner) {
24 loop { 24 loop {
25 info!("45 deg"); 25 info!("45 deg");
26 // poor mans inverting, subtract our value from max_duty 26 // poor mans inverting, subtract our value from max_duty
27 pwm.set_duty(0, 2500 - 156); 27 pwm.set_duty(0, DutyCycle::normal(2500 - 156));
28 Timer::after_millis(5000).await; 28 Timer::after_millis(5000).await;
29 29
30 info!("90 deg"); 30 info!("90 deg");
31 pwm.set_duty(0, 2500 - 187); 31 pwm.set_duty(0, DutyCycle::normal(2500 - 187));
32 Timer::after_millis(5000).await; 32 Timer::after_millis(5000).await;
33 33
34 info!("135 deg"); 34 info!("135 deg");
35 pwm.set_duty(0, 2500 - 218); 35 pwm.set_duty(0, DutyCycle::normal(2500 - 218));
36 Timer::after_millis(5000).await; 36 Timer::after_millis(5000).await;
37 37
38 info!("180 deg"); 38 info!("180 deg");
39 pwm.set_duty(0, 2500 - 250); 39 pwm.set_duty(0, DutyCycle::normal(2500 - 250));
40 Timer::after_millis(5000).await; 40 Timer::after_millis(5000).await;
41 41
42 info!("0 deg"); 42 info!("0 deg");
43 pwm.set_duty(0, 2500 - 125); 43 pwm.set_duty(0, DutyCycle::normal(2500 - 125));
44 Timer::after_millis(5000).await; 44 Timer::after_millis(5000).await;
45 } 45 }
46} 46}
diff --git a/examples/nrf52840/src/bin/wifi_esp_hosted.rs b/examples/nrf52840/src/bin/wifi_esp_hosted.rs
index 07752ffc4..2f9c06b56 100644
--- a/examples/nrf52840/src/bin/wifi_esp_hosted.rs
+++ b/examples/nrf52840/src/bin/wifi_esp_hosted.rs
@@ -27,14 +27,12 @@ bind_interrupts!(struct Irqs {
27async fn wifi_task( 27async fn wifi_task(
28 runner: hosted::Runner< 28 runner: hosted::Runner<
29 'static, 29 'static,
30 ExclusiveDevice<Spim<'static>, Output<'static>, Delay>, 30 hosted::SpiInterface<ExclusiveDevice<Spim<'static>, Output<'static>, Delay>, Input<'static>>,
31 Input<'static>,
32 Output<'static>, 31 Output<'static>,
33 >, 32 >,
34) -> ! { 33) -> ! {
35 runner.run().await 34 runner.run().await
36} 35}
37
38#[embassy_executor::task] 36#[embassy_executor::task]
39async fn net_task(mut runner: embassy_net::Runner<'static, hosted::NetDriver<'static>>) -> ! { 37async fn net_task(mut runner: embassy_net::Runner<'static, hosted::NetDriver<'static>>) -> ! {
40 runner.run().await 38 runner.run().await
@@ -60,15 +58,11 @@ async fn main(spawner: Spawner) {
60 let spi = spim::Spim::new(p.SPI3, Irqs, sck, miso, mosi, config); 58 let spi = spim::Spim::new(p.SPI3, Irqs, sck, miso, mosi, config);
61 let spi = ExclusiveDevice::new(spi, cs, Delay); 59 let spi = ExclusiveDevice::new(spi, cs, Delay);
62 60
61 let iface = hosted::SpiInterface::new(spi, handshake, ready);
62
63 static ESP_STATE: StaticCell<embassy_net_esp_hosted::State> = StaticCell::new(); 63 static ESP_STATE: StaticCell<embassy_net_esp_hosted::State> = StaticCell::new();
64 let (device, mut control, runner) = embassy_net_esp_hosted::new( 64 let (device, mut control, runner) =
65 ESP_STATE.init(embassy_net_esp_hosted::State::new()), 65 embassy_net_esp_hosted::new(ESP_STATE.init(embassy_net_esp_hosted::State::new()), iface, reset).await;
66 spi,
67 handshake,
68 ready,
69 reset,
70 )
71 .await;
72 66
73 spawner.spawn(unwrap!(wifi_task(runner))); 67 spawner.spawn(unwrap!(wifi_task(runner)));
74 68
diff --git a/examples/nrf5340/src/bin/gpiote_channel.rs b/examples/nrf5340/src/bin/gpiote_channel.rs
index 23f6fca98..a085310ce 100644
--- a/examples/nrf5340/src/bin/gpiote_channel.rs
+++ b/examples/nrf5340/src/bin/gpiote_channel.rs
@@ -3,7 +3,7 @@
3 3
4use defmt::info; 4use defmt::info;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_nrf::gpio::{Input, Pull}; 6use embassy_nrf::gpio::Pull;
7use embassy_nrf::gpiote::{InputChannel, InputChannelPolarity}; 7use embassy_nrf::gpiote::{InputChannel, InputChannelPolarity};
8use {defmt_rtt as _, panic_probe as _}; 8use {defmt_rtt as _, panic_probe as _};
9 9
@@ -12,26 +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( 15 let ch1 = InputChannel::new(p.GPIOTE_CH0, p.P0_23, Pull::Up, InputChannelPolarity::HiToLo);
16 p.GPIOTE_CH0, 16 let ch2 = InputChannel::new(p.GPIOTE_CH1, p.P0_24, Pull::Up, InputChannelPolarity::LoToHi);
17 Input::new(p.P0_23, Pull::Up), 17 let ch3 = InputChannel::new(p.GPIOTE_CH2, p.P0_08, Pull::Up, InputChannelPolarity::Toggle);
18 InputChannelPolarity::HiToLo, 18 let ch4 = InputChannel::new(p.GPIOTE_CH3, p.P0_09, Pull::Up, InputChannelPolarity::Toggle);
19 );
20 let ch2 = InputChannel::new(
21 p.GPIOTE_CH1,
22 Input::new(p.P0_24, Pull::Up),
23 InputChannelPolarity::LoToHi,
24 );
25 let ch3 = InputChannel::new(
26 p.GPIOTE_CH2,
27 Input::new(p.P0_08, Pull::Up),
28 InputChannelPolarity::Toggle,
29 );
30 let ch4 = InputChannel::new(
31 p.GPIOTE_CH3,
32 Input::new(p.P0_09, Pull::Up),
33 InputChannelPolarity::Toggle,
34 );
35 19
36 let button1 = async { 20 let button1 = async {
37 loop { 21 loop {
diff --git a/examples/nrf54l15/Cargo.toml b/examples/nrf54l15/Cargo.toml
index 541e79fcb..4ef77279f 100644
--- a/examples/nrf54l15/Cargo.toml
+++ b/examples/nrf54l15/Cargo.toml
@@ -6,10 +6,15 @@ license = "MIT OR Apache-2.0"
6publish = false 6publish = false
7 7
8[dependencies] 8[dependencies]
9embassy-futures = { version = "0.1.2", path = "../../embassy-futures" }
9embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } 10embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] }
10embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } 11embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] }
11embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } 12embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] }
12embassy-nrf = { version = "0.8.0", path = "../../embassy-nrf", features = ["defmt", "nrf54l15-app-s", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } 13embassy-nrf = { version = "0.8.0", path = "../../embassy-nrf", features = ["defmt", "nrf54l15-app-s", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] }
14embedded-io = { version = "0.6.0", features = ["defmt-03"] }
15embedded-io-async = { version = "0.6.1", features = ["defmt-03"] }
16
17rand = { version = "0.9.0", default-features = false }
13 18
14defmt = "1.0.1" 19defmt = "1.0.1"
15defmt-rtt = "1.0.0" 20defmt-rtt = "1.0.0"
@@ -21,6 +26,8 @@ cortex-m-rt = "0.7.0"
21embedded-storage = "0.3.1" 26embedded-storage = "0.3.1"
22portable-atomic = "1" 27portable-atomic = "1"
23 28
29static_cell = "2"
30
24[profile.release] 31[profile.release]
25debug = 2 32debug = 2
26 33
diff --git a/examples/nrf54l15/src/bin/buffered_uart.rs b/examples/nrf54l15/src/bin/buffered_uart.rs
new file mode 100644
index 000000000..41fa1ca4e
--- /dev/null
+++ b/examples/nrf54l15/src/bin/buffered_uart.rs
@@ -0,0 +1,49 @@
1#![no_std]
2#![no_main]
3
4use defmt::*;
5use embassy_executor::Spawner;
6use embassy_nrf::buffered_uarte::{self, BufferedUarte};
7use embassy_nrf::{bind_interrupts, peripherals, uarte};
8use embedded_io_async::Write;
9use {defmt_rtt as _, panic_probe as _};
10
11bind_interrupts!(struct Irqs {
12 SERIAL20 => buffered_uarte::InterruptHandler<peripherals::SERIAL20>;
13});
14
15#[embassy_executor::main]
16async fn main(_spawner: Spawner) {
17 let p = embassy_nrf::init(Default::default());
18 let mut config = uarte::Config::default();
19 config.parity = uarte::Parity::EXCLUDED;
20 config.baudrate = uarte::Baudrate::BAUD115200;
21
22 let mut tx_buffer = [0u8; 4096];
23 let mut rx_buffer = [0u8; 4096];
24
25 let mut u = BufferedUarte::new(
26 p.SERIAL20,
27 p.P1_12,
28 p.P1_13,
29 Irqs,
30 config,
31 &mut rx_buffer,
32 &mut tx_buffer,
33 );
34
35 info!("uarte initialized!");
36
37 unwrap!(u.write_all(b"Hello!\r\n").await);
38 info!("wrote hello in uart!");
39
40 loop {
41 info!("reading...");
42 let buf = unwrap!(u.fill_buf().await);
43 info!("read done, got {}", buf);
44
45 // Read bytes have to be explicitly consumed, otherwise fill_buf() will return them again
46 let n = buf.len();
47 u.consume(n);
48 }
49}
diff --git a/examples/nrf54l15/src/bin/gpiote_channel.rs b/examples/nrf54l15/src/bin/gpiote_channel.rs
new file mode 100644
index 000000000..6333250ba
--- /dev/null
+++ b/examples/nrf54l15/src/bin/gpiote_channel.rs
@@ -0,0 +1,49 @@
1#![no_std]
2#![no_main]
3
4use defmt::info;
5use embassy_executor::Spawner;
6use embassy_nrf::gpio::Pull;
7use embassy_nrf::gpiote::{InputChannel, InputChannelPolarity};
8use {defmt_rtt as _, panic_probe as _};
9
10#[embassy_executor::main]
11async fn main(_spawner: Spawner) {
12 let p = embassy_nrf::init(Default::default());
13 info!("Starting!");
14
15 let 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);
17 let 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);
19
20 let button1 = async {
21 loop {
22 ch1.wait().await;
23 info!("Button 1 pressed")
24 }
25 };
26
27 let button2 = async {
28 loop {
29 ch2.wait().await;
30 info!("Button 2 released")
31 }
32 };
33
34 let button3 = async {
35 loop {
36 ch3.wait().await;
37 info!("Button 3 toggled")
38 }
39 };
40
41 let button4 = async {
42 loop {
43 ch4.wait().await;
44 info!("Button 4 toggled")
45 }
46 };
47
48 embassy_futures::join::join4(button1, button2, button3, button4).await;
49}
diff --git a/examples/nrf54l15/src/bin/gpiote_port.rs b/examples/nrf54l15/src/bin/gpiote_port.rs
new file mode 100644
index 000000000..620cb2435
--- /dev/null
+++ b/examples/nrf54l15/src/bin/gpiote_port.rs
@@ -0,0 +1,33 @@
1#![no_std]
2#![no_main]
3
4use defmt::{info, unwrap};
5use embassy_executor::Spawner;
6use embassy_nrf::gpio::{Input, Pull};
7use {defmt_rtt as _, panic_probe as _};
8
9#[embassy_executor::task(pool_size = 4)]
10async fn button_task(n: usize, mut pin: Input<'static>) {
11 loop {
12 pin.wait_for_low().await;
13 info!("Button {:?} pressed!", n);
14 pin.wait_for_high().await;
15 info!("Button {:?} released!", n);
16 }
17}
18
19#[embassy_executor::main]
20async fn main(spawner: Spawner) {
21 let p = embassy_nrf::init(Default::default());
22 info!("Starting!");
23
24 let btn1 = Input::new(p.P1_13, Pull::Up);
25 let btn2 = Input::new(p.P1_09, Pull::Up);
26 let btn3 = Input::new(p.P1_08, Pull::Up);
27 let btn4 = Input::new(p.P0_04, Pull::Up);
28
29 spawner.spawn(unwrap!(button_task(1, btn1)));
30 spawner.spawn(unwrap!(button_task(2, btn2)));
31 spawner.spawn(unwrap!(button_task(3, btn3)));
32 spawner.spawn(unwrap!(button_task(4, btn4)));
33}
diff --git a/examples/nrf54l15/src/bin/pwm.rs b/examples/nrf54l15/src/bin/pwm.rs
new file mode 100644
index 000000000..b438978f1
--- /dev/null
+++ b/examples/nrf54l15/src/bin/pwm.rs
@@ -0,0 +1,86 @@
1#![no_std]
2#![no_main]
3
4use defmt::*;
5use embassy_executor::Spawner;
6use embassy_nrf::pwm::{DutyCycle, Prescaler, SimplePwm};
7use embassy_time::Timer;
8use {defmt_rtt as _, panic_probe as _};
9
10// for i in range(1024): print(int((math.sin(i/512*math.pi)*0.4+0.5)**2*32767), ', ', end='')
11static DUTY: [u16; 1024] = [
12 8191, 8272, 8353, 8434, 8516, 8598, 8681, 8764, 8847, 8931, 9015, 9099, 9184, 9269, 9354, 9440, 9526, 9613, 9700,
13 9787, 9874, 9962, 10050, 10139, 10227, 10316, 10406, 10495, 10585, 10675, 10766, 10857, 10948, 11039, 11131, 11223,
14 11315, 11407, 11500, 11592, 11685, 11779, 11872, 11966, 12060, 12154, 12248, 12343, 12438, 12533, 12628, 12723,
15 12818, 12914, 13010, 13106, 13202, 13298, 13394, 13491, 13587, 13684, 13781, 13878, 13975, 14072, 14169, 14266,
16 14364, 14461, 14558, 14656, 14754, 14851, 14949, 15046, 15144, 15242, 15339, 15437, 15535, 15632, 15730, 15828,
17 15925, 16023, 16120, 16218, 16315, 16412, 16510, 16607, 16704, 16801, 16898, 16995, 17091, 17188, 17284, 17380,
18 17477, 17572, 17668, 17764, 17859, 17955, 18050, 18145, 18239, 18334, 18428, 18522, 18616, 18710, 18803, 18896,
19 18989, 19082, 19174, 19266, 19358, 19449, 19540, 19631, 19722, 19812, 19902, 19991, 20081, 20169, 20258, 20346,
20 20434, 20521, 20608, 20695, 20781, 20867, 20952, 21037, 21122, 21206, 21290, 21373, 21456, 21538, 21620, 21701,
21 21782, 21863, 21943, 22022, 22101, 22179, 22257, 22335, 22412, 22488, 22564, 22639, 22714, 22788, 22861, 22934,
22 23007, 23079, 23150, 23220, 23290, 23360, 23429, 23497, 23564, 23631, 23698, 23763, 23828, 23892, 23956, 24019,
23 24081, 24143, 24204, 24264, 24324, 24383, 24441, 24499, 24555, 24611, 24667, 24721, 24775, 24828, 24881, 24933,
24 24983, 25034, 25083, 25132, 25180, 25227, 25273, 25319, 25363, 25407, 25451, 25493, 25535, 25575, 25615, 25655,
25 25693, 25731, 25767, 25803, 25838, 25873, 25906, 25939, 25971, 26002, 26032, 26061, 26089, 26117, 26144, 26170,
26 26195, 26219, 26242, 26264, 26286, 26307, 26327, 26346, 26364, 26381, 26397, 26413, 26427, 26441, 26454, 26466,
27 26477, 26487, 26496, 26505, 26512, 26519, 26525, 26530, 26534, 26537, 26539, 26540, 26541, 26540, 26539, 26537,
28 26534, 26530, 26525, 26519, 26512, 26505, 26496, 26487, 26477, 26466, 26454, 26441, 26427, 26413, 26397, 26381,
29 26364, 26346, 26327, 26307, 26286, 26264, 26242, 26219, 26195, 26170, 26144, 26117, 26089, 26061, 26032, 26002,
30 25971, 25939, 25906, 25873, 25838, 25803, 25767, 25731, 25693, 25655, 25615, 25575, 25535, 25493, 25451, 25407,
31 25363, 25319, 25273, 25227, 25180, 25132, 25083, 25034, 24983, 24933, 24881, 24828, 24775, 24721, 24667, 24611,
32 24555, 24499, 24441, 24383, 24324, 24264, 24204, 24143, 24081, 24019, 23956, 23892, 23828, 23763, 23698, 23631,
33 23564, 23497, 23429, 23360, 23290, 23220, 23150, 23079, 23007, 22934, 22861, 22788, 22714, 22639, 22564, 22488,
34 22412, 22335, 22257, 22179, 22101, 22022, 21943, 21863, 21782, 21701, 21620, 21538, 21456, 21373, 21290, 21206,
35 21122, 21037, 20952, 20867, 20781, 20695, 20608, 20521, 20434, 20346, 20258, 20169, 20081, 19991, 19902, 19812,
36 19722, 19631, 19540, 19449, 19358, 19266, 19174, 19082, 18989, 18896, 18803, 18710, 18616, 18522, 18428, 18334,
37 18239, 18145, 18050, 17955, 17859, 17764, 17668, 17572, 17477, 17380, 17284, 17188, 17091, 16995, 16898, 16801,
38 16704, 16607, 16510, 16412, 16315, 16218, 16120, 16023, 15925, 15828, 15730, 15632, 15535, 15437, 15339, 15242,
39 15144, 15046, 14949, 14851, 14754, 14656, 14558, 14461, 14364, 14266, 14169, 14072, 13975, 13878, 13781, 13684,
40 13587, 13491, 13394, 13298, 13202, 13106, 13010, 12914, 12818, 12723, 12628, 12533, 12438, 12343, 12248, 12154,
41 12060, 11966, 11872, 11779, 11685, 11592, 11500, 11407, 11315, 11223, 11131, 11039, 10948, 10857, 10766, 10675,
42 10585, 10495, 10406, 10316, 10227, 10139, 10050, 9962, 9874, 9787, 9700, 9613, 9526, 9440, 9354, 9269, 9184, 9099,
43 9015, 8931, 8847, 8764, 8681, 8598, 8516, 8434, 8353, 8272, 8191, 8111, 8031, 7952, 7873, 7794, 7716, 7638, 7561,
44 7484, 7407, 7331, 7255, 7180, 7105, 7031, 6957, 6883, 6810, 6738, 6665, 6594, 6522, 6451, 6381, 6311, 6241, 6172,
45 6104, 6036, 5968, 5901, 5834, 5767, 5702, 5636, 5571, 5507, 5443, 5379, 5316, 5253, 5191, 5130, 5068, 5008, 4947,
46 4888, 4828, 4769, 4711, 4653, 4596, 4539, 4482, 4426, 4371, 4316, 4261, 4207, 4153, 4100, 4047, 3995, 3943, 3892,
47 3841, 3791, 3741, 3691, 3642, 3594, 3546, 3498, 3451, 3404, 3358, 3312, 3267, 3222, 3178, 3134, 3090, 3047, 3005,
48 2962, 2921, 2879, 2839, 2798, 2758, 2719, 2680, 2641, 2603, 2565, 2528, 2491, 2454, 2418, 2382, 2347, 2312, 2278,
49 2244, 2210, 2177, 2144, 2112, 2080, 2048, 2017, 1986, 1956, 1926, 1896, 1867, 1838, 1810, 1781, 1754, 1726, 1699,
50 1673, 1646, 1620, 1595, 1570, 1545, 1520, 1496, 1472, 1449, 1426, 1403, 1380, 1358, 1336, 1315, 1294, 1273, 1252,
51 1232, 1212, 1192, 1173, 1154, 1135, 1117, 1099, 1081, 1063, 1046, 1029, 1012, 996, 980, 964, 948, 933, 918, 903,
52 888, 874, 860, 846, 833, 819, 806, 793, 781, 768, 756, 744, 733, 721, 710, 699, 688, 677, 667, 657, 647, 637, 627,
53 618, 609, 599, 591, 582, 574, 565, 557, 549, 541, 534, 526, 519, 512, 505, 498, 492, 485, 479, 473, 467, 461, 455,
54 450, 444, 439, 434, 429, 424, 419, 415, 410, 406, 402, 398, 394, 390, 386, 383, 379, 376, 373, 370, 367, 364, 361,
55 359, 356, 354, 351, 349, 347, 345, 343, 342, 340, 338, 337, 336, 334, 333, 332, 331, 330, 330, 329, 328, 328, 328,
56 327, 327, 327, 327, 327, 328, 328, 328, 329, 330, 330, 331, 332, 333, 334, 336, 337, 338, 340, 342, 343, 345, 347,
57 349, 351, 354, 356, 359, 361, 364, 367, 370, 373, 376, 379, 383, 386, 390, 394, 398, 402, 406, 410, 415, 419, 424,
58 429, 434, 439, 444, 450, 455, 461, 467, 473, 479, 485, 492, 498, 505, 512, 519, 526, 534, 541, 549, 557, 565, 574,
59 582, 591, 599, 609, 618, 627, 637, 647, 657, 667, 677, 688, 699, 710, 721, 733, 744, 756, 768, 781, 793, 806, 819,
60 833, 846, 860, 874, 888, 903, 918, 933, 948, 964, 980, 996, 1012, 1029, 1046, 1063, 1081, 1099, 1117, 1135, 1154,
61 1173, 1192, 1212, 1232, 1252, 1273, 1294, 1315, 1336, 1358, 1380, 1403, 1426, 1449, 1472, 1496, 1520, 1545, 1570,
62 1595, 1620, 1646, 1673, 1699, 1726, 1754, 1781, 1810, 1838, 1867, 1896, 1926, 1956, 1986, 2017, 2048, 2080, 2112,
63 2144, 2177, 2210, 2244, 2278, 2312, 2347, 2382, 2418, 2454, 2491, 2528, 2565, 2603, 2641, 2680, 2719, 2758, 2798,
64 2839, 2879, 2921, 2962, 3005, 3047, 3090, 3134, 3178, 3222, 3267, 3312, 3358, 3404, 3451, 3498, 3546, 3594, 3642,
65 3691, 3741, 3791, 3841, 3892, 3943, 3995, 4047, 4100, 4153, 4207, 4261, 4316, 4371, 4426, 4482, 4539, 4596, 4653,
66 4711, 4769, 4828, 4888, 4947, 5008, 5068, 5130, 5191, 5253, 5316, 5379, 5443, 5507, 5571, 5636, 5702, 5767, 5834,
67 5901, 5968, 6036, 6104, 6172, 6241, 6311, 6381, 6451, 6522, 6594, 6665, 6738, 6810, 6883, 6957, 7031, 7105, 7180,
68 7255, 7331, 7407, 7484, 7561, 7638, 7716, 7794, 7873, 7952, 8031, 8111,
69];
70
71#[embassy_executor::main]
72async fn main(_spawner: Spawner) {
73 let p = embassy_nrf::init(Default::default());
74 let mut pwm = SimplePwm::new_2ch(p.PWM20, p.P1_10, p.P1_14, &Default::default());
75 pwm.set_prescaler(Prescaler::Div1);
76 pwm.set_max_duty(32767);
77 info!("pwm initialized!");
78
79 let mut i = 0;
80 loop {
81 i += 1;
82 pwm.set_duty(0, DutyCycle::normal(DUTY[i % 1024]));
83 pwm.set_duty(1, DutyCycle::normal(DUTY[(i + 512) % 1024]));
84 Timer::after_millis(3).await;
85 }
86}
diff --git a/examples/nrf54l15/src/bin/rng.rs b/examples/nrf54l15/src/bin/rng.rs
new file mode 100644
index 000000000..b2d7f906b
--- /dev/null
+++ b/examples/nrf54l15/src/bin/rng.rs
@@ -0,0 +1,28 @@
1#![no_std]
2#![no_main]
3
4use embassy_executor::Spawner;
5use embassy_nrf::cracen::Cracen;
6use rand::Rng as _;
7use {defmt_rtt as _, panic_probe as _};
8
9#[embassy_executor::main]
10async fn main(_spawner: Spawner) {
11 let p = embassy_nrf::init(Default::default());
12 let mut rng = Cracen::new_blocking(p.CRACEN);
13
14 // Async API
15 let mut bytes = [0; 4];
16 rng.blocking_fill_bytes(&mut bytes);
17 defmt::info!("Some random bytes: {:?}", bytes);
18
19 // Sync API with `rand`
20 defmt::info!("A random number from 1 to 10: {:?}", rng.random_range(1..=10));
21
22 let mut bytes = [0; 1024];
23 rng.blocking_fill_bytes(&mut bytes);
24 let zero_count: u32 = bytes.iter().fold(0, |acc, val| acc + val.count_zeros());
25 let one_count: u32 = bytes.iter().fold(0, |acc, val| acc + val.count_ones());
26 defmt::info!("Chance of zero: {}%", zero_count * 100 / (bytes.len() as u32 * 8));
27 defmt::info!("Chance of one: {}%", one_count * 100 / (bytes.len() as u32 * 8));
28}
diff --git a/examples/nrf54l15/src/bin/saadc.rs b/examples/nrf54l15/src/bin/saadc.rs
new file mode 100644
index 000000000..567177894
--- /dev/null
+++ b/examples/nrf54l15/src/bin/saadc.rs
@@ -0,0 +1,28 @@
1#![no_std]
2#![no_main]
3
4use defmt::info;
5use embassy_executor::Spawner;
6use embassy_nrf::saadc::{ChannelConfig, Config, Saadc};
7use embassy_nrf::{bind_interrupts, saadc};
8use embassy_time::Timer;
9use {defmt_rtt as _, panic_probe as _};
10
11bind_interrupts!(struct Irqs {
12 SAADC => saadc::InterruptHandler;
13});
14
15#[embassy_executor::main]
16async fn main(_p: Spawner) {
17 let mut p = embassy_nrf::init(Default::default());
18 let config = Config::default();
19 let channel_config = ChannelConfig::single_ended(p.P1_04.reborrow());
20 let mut saadc = Saadc::new(p.SAADC, Irqs, config, [channel_config]);
21
22 loop {
23 let mut buf = [0; 1];
24 saadc.sample(&mut buf).await;
25 info!("sample: {=i16}", &buf[0]);
26 Timer::after_millis(100).await;
27 }
28}
diff --git a/examples/nrf54l15/src/bin/spim.rs b/examples/nrf54l15/src/bin/spim.rs
new file mode 100644
index 000000000..3f5980647
--- /dev/null
+++ b/examples/nrf54l15/src/bin/spim.rs
@@ -0,0 +1,30 @@
1#![no_std]
2#![no_main]
3
4use embassy_executor::Spawner;
5use embassy_nrf::{bind_interrupts, peripherals, spim};
6use {defmt_rtt as _, panic_probe as _};
7
8bind_interrupts!(struct Irqs {
9 SERIAL00 => spim::InterruptHandler<peripherals::SERIAL00>;
10});
11
12#[embassy_executor::main]
13async fn main(_spawner: Spawner) {
14 let p = embassy_nrf::init(Default::default());
15 let mut config = spim::Config::default();
16 config.frequency = spim::Frequency::M32;
17 let mut spim = spim::Spim::new(p.SERIAL00, Irqs, p.P2_05, p.P2_09, p.P2_08, config.clone());
18 let data = [
19 0x42, 0x43, 0x44, 0x45, 0x66, 0x12, 0x23, 0x34, 0x45, 0x19, 0x91, 0xaa, 0xff, 0xa5, 0x5a, 0x77,
20 ];
21 let mut buf = [0u8; 16];
22
23 buf.fill(0);
24 spim.blocking_transfer(&mut buf, &data).unwrap();
25 assert_eq!(data, buf);
26
27 buf.fill(0);
28 spim.transfer(&mut buf, &data).await.unwrap();
29 assert_eq!(data, buf);
30}
diff --git a/examples/nrf54l15/src/bin/twim.rs b/examples/nrf54l15/src/bin/twim.rs
new file mode 100644
index 000000000..53b85034e
--- /dev/null
+++ b/examples/nrf54l15/src/bin/twim.rs
@@ -0,0 +1,37 @@
1//! Example on how to read a 24C/24LC i2c eeprom.
2//!
3//! Connect SDA to P0.03, SCL to P0.04
4
5#![no_std]
6#![no_main]
7
8use defmt::*;
9use embassy_executor::Spawner;
10use embassy_nrf::twim::{self, Twim};
11use embassy_nrf::{bind_interrupts, peripherals};
12use static_cell::ConstStaticCell;
13use {defmt_rtt as _, panic_probe as _};
14
15const ADDRESS: u8 = 0x18;
16const WHOAMI: u8 = 0x0F;
17
18bind_interrupts!(struct Irqs {
19 SERIAL20 => twim::InterruptHandler<peripherals::SERIAL20>;
20});
21
22#[embassy_executor::main]
23async fn main(_spawner: Spawner) {
24 let p = embassy_nrf::init(Default::default());
25 info!("Initializing TWI...");
26 let config = twim::Config::default();
27 static RAM_BUFFER: ConstStaticCell<[u8; 16]> = ConstStaticCell::new([0; 16]);
28 let mut twi = Twim::new(p.SERIAL20, Irqs, p.P1_13, p.P1_12, config, RAM_BUFFER.take());
29
30 info!("Reading...");
31
32 let mut data = [0u8; 1];
33 match twi.write_read(ADDRESS, &[WHOAMI], &mut data).await {
34 Ok(()) => info!("Whoami: {}", data[0]),
35 Err(e) => error!("I2c Error: {:?}", e),
36 }
37}
diff --git a/examples/nrf54l15/src/bin/twis.rs b/examples/nrf54l15/src/bin/twis.rs
new file mode 100644
index 000000000..34c04aee3
--- /dev/null
+++ b/examples/nrf54l15/src/bin/twis.rs
@@ -0,0 +1,47 @@
1//! TWIS example
2
3#![no_std]
4#![no_main]
5
6use defmt::*;
7use embassy_executor::Spawner;
8use embassy_nrf::twis::{self, Command, Twis};
9use embassy_nrf::{bind_interrupts, peripherals};
10use {defmt_rtt as _, panic_probe as _};
11
12bind_interrupts!(struct Irqs {
13 SERIAL20 => twis::InterruptHandler<peripherals::SERIAL20>;
14});
15
16#[embassy_executor::main]
17async fn main(_spawner: Spawner) {
18 let p = embassy_nrf::init(Default::default());
19
20 let mut config = twis::Config::default();
21 config.address0 = 0x55; // Set i2c address
22 let mut i2c = Twis::new(p.SERIAL20, Irqs, p.P0_03, p.P0_04, config);
23
24 info!("Listening...");
25 loop {
26 let response = [1, 2, 3, 4, 5, 6, 7, 8];
27 // This buffer is used if the i2c master performs a Write or WriteRead
28 let mut buf = [0u8; 16];
29 match i2c.listen(&mut buf).await {
30 Ok(Command::Read) => {
31 info!("Got READ command. Respond with data:\n{:?}\n", response);
32 if let Err(e) = i2c.respond_to_read(&response).await {
33 error!("{:?}", e);
34 }
35 }
36 Ok(Command::Write(n)) => info!("Got WRITE command with data:\n{:?}\n", buf[..n]),
37 Ok(Command::WriteRead(n)) => {
38 info!("Got WRITE/READ command with data:\n{:?}", buf[..n]);
39 info!("Respond with data:\n{:?}\n", response);
40 if let Err(e) = i2c.respond_to_read(&response).await {
41 error!("{:?}", e);
42 }
43 }
44 Err(e) => error!("{:?}", e),
45 }
46 }
47}
diff --git a/examples/nrf54l15/src/bin/uart.rs b/examples/nrf54l15/src/bin/uart.rs
new file mode 100644
index 000000000..cc6528a6f
--- /dev/null
+++ b/examples/nrf54l15/src/bin/uart.rs
@@ -0,0 +1,37 @@
1#![no_std]
2#![no_main]
3
4use defmt::*;
5use embassy_executor::Spawner;
6use embassy_nrf::{bind_interrupts, peripherals, uarte};
7use {defmt_rtt as _, panic_probe as _};
8
9bind_interrupts!(struct Irqs {
10 SERIAL20 => uarte::InterruptHandler<peripherals::SERIAL20>;
11});
12
13#[embassy_executor::main]
14async fn main(_spawner: Spawner) {
15 let p = embassy_nrf::init(Default::default());
16 let mut config = uarte::Config::default();
17 config.parity = uarte::Parity::EXCLUDED;
18 config.baudrate = uarte::Baudrate::BAUD115200;
19
20 let mut uart = uarte::Uarte::new(p.SERIAL20, p.P1_12, p.P1_13, Irqs, config);
21
22 info!("uarte initialized!");
23
24 // Message must be in SRAM
25 let mut buf = [0; 8];
26 buf.copy_from_slice(b"Hello!\r\n");
27
28 unwrap!(uart.write(&buf).await);
29 info!("wrote hello in uart!");
30
31 loop {
32 info!("reading...");
33 unwrap!(uart.read(&mut buf).await);
34 info!("writing...");
35 unwrap!(uart.write(&buf).await);
36 }
37}
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/stm32c0/src/bin/rtc.rs b/examples/stm32c0/src/bin/rtc.rs
index feb27f6d9..5ff705ca2 100644
--- a/examples/stm32c0/src/bin/rtc.rs
+++ b/examples/stm32c0/src/bin/rtc.rs
@@ -21,12 +21,12 @@ async fn main(_spawner: Spawner) {
21 .and_hms_opt(10, 30, 15) 21 .and_hms_opt(10, 30, 15)
22 .unwrap(); 22 .unwrap();
23 23
24 let mut rtc = Rtc::new(p.RTC, RtcConfig::default()); 24 let (mut rtc, time_provider) = Rtc::new(p.RTC, RtcConfig::default());
25 25
26 rtc.set_datetime(now.into()).expect("datetime not set"); 26 rtc.set_datetime(now.into()).expect("datetime not set");
27 27
28 loop { 28 loop {
29 let now: NaiveDateTime = rtc.now().unwrap().into(); 29 let now: NaiveDateTime = time_provider.now().unwrap().into();
30 30
31 info!("{}", now.and_utc().timestamp()); 31 info!("{}", now.and_utc().timestamp());
32 32
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/stm32f4/src/bin/eth_w5500.rs b/examples/stm32f4/src/bin/eth_w5500.rs
index cccf20949..0adcda614 100644
--- a/examples/stm32f4/src/bin/eth_w5500.rs
+++ b/examples/stm32f4/src/bin/eth_w5500.rs
@@ -12,6 +12,7 @@ use embassy_stm32::gpio::{Level, Output, Pull, Speed};
12use embassy_stm32::mode::Async; 12use embassy_stm32::mode::Async;
13use embassy_stm32::rng::Rng; 13use embassy_stm32::rng::Rng;
14use embassy_stm32::spi::Spi; 14use embassy_stm32::spi::Spi;
15use embassy_stm32::spi::mode::Master;
15use embassy_stm32::time::Hertz; 16use embassy_stm32::time::Hertz;
16use embassy_stm32::{Config, bind_interrupts, peripherals, rng, spi}; 17use embassy_stm32::{Config, bind_interrupts, peripherals, rng, spi};
17use embassy_time::{Delay, Timer}; 18use embassy_time::{Delay, Timer};
@@ -24,7 +25,7 @@ bind_interrupts!(struct Irqs {
24 HASH_RNG => rng::InterruptHandler<peripherals::RNG>; 25 HASH_RNG => rng::InterruptHandler<peripherals::RNG>;
25}); 26});
26 27
27type EthernetSPI = ExclusiveDevice<Spi<'static, Async>, Output<'static>, Delay>; 28type EthernetSPI = ExclusiveDevice<Spi<'static, Async, Master>, Output<'static>, Delay>;
28#[embassy_executor::task] 29#[embassy_executor::task]
29async fn ethernet_task(runner: Runner<'static, W5500, EthernetSPI, ExtiInput<'static>, Output<'static>>) -> ! { 30async fn ethernet_task(runner: Runner<'static, W5500, EthernetSPI, ExtiInput<'static>, Output<'static>>) -> ! {
30 runner.run().await 31 runner.run().await
diff --git a/examples/stm32f4/src/bin/i2c_slave_async.rs b/examples/stm32f4/src/bin/i2c_slave_async.rs
new file mode 100644
index 000000000..5065bcdd8
--- /dev/null
+++ b/examples/stm32f4/src/bin/i2c_slave_async.rs
@@ -0,0 +1,135 @@
1//! I2C slave example using async operations with DMA
2//!
3//! This example demonstrates DMA-accelerated I2C slave operations,
4//! which provide better performance and lower CPU overhead for
5//! high-frequency I2C transactions.
6
7#![no_std]
8#![no_main]
9
10use defmt::{error, info};
11use embassy_executor::Spawner;
12use embassy_stm32::i2c::{self, Address, I2c, SlaveAddrConfig, SlaveCommand, SlaveCommandKind};
13use embassy_stm32::time::Hertz;
14use embassy_stm32::{bind_interrupts, peripherals};
15use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex;
16use embassy_sync::mutex::Mutex;
17use embassy_time::{Duration, Timer};
18use {defmt_rtt as _, panic_probe as _};
19
20pub const I2C_SLAVE_ADDR: u8 = 0x42;
21pub const BUFFER_SIZE: usize = 8;
22static I2C_BUFFER: Mutex<ThreadModeRawMutex, [u8; BUFFER_SIZE]> = Mutex::new([0; BUFFER_SIZE]);
23
24bind_interrupts!(struct Irqs {
25 I2C1_EV => i2c::EventInterruptHandler<peripherals::I2C1>;
26 I2C1_ER => i2c::ErrorInterruptHandler<peripherals::I2C1>;
27});
28
29#[embassy_executor::main]
30async fn main(spawner: Spawner) {
31 let p = embassy_stm32::init(Default::default());
32
33 // Configure I2C
34 let mut i2c_config = i2c::Config::default();
35 i2c_config.sda_pullup = false;
36 i2c_config.scl_pullup = false;
37 i2c_config.frequency = Hertz(100_000); // 100kHz I2C speed
38
39 // Initialize I2C as master first
40 let i2c_master = I2c::new(
41 p.I2C1, p.PB8, // SCL
42 p.PB9, // SDA
43 Irqs, p.DMA1_CH6, // TX DMA
44 p.DMA1_CH0, // RX DMA
45 i2c_config,
46 );
47
48 // Convert to MultiMaster mode
49 let slave_config = SlaveAddrConfig::basic(I2C_SLAVE_ADDR);
50 let i2c_slave = i2c_master.into_slave_multimaster(slave_config);
51
52 spawner.spawn(i2c_slave_task(i2c_slave).unwrap());
53}
54
55#[embassy_executor::task]
56pub async fn i2c_slave_task(mut i2c_slave: I2c<'static, embassy_stm32::mode::Async, i2c::mode::MultiMaster>) {
57 info!("Async I2C slave ready at address 0x{:02X}", I2C_SLAVE_ADDR);
58
59 loop {
60 match i2c_slave.listen().await {
61 Ok(SlaveCommand {
62 kind: SlaveCommandKind::Write,
63 address,
64 }) => {
65 let addr_val = match address {
66 Address::SevenBit(addr) => addr,
67 Address::TenBit(addr) => (addr & 0xFF) as u8,
68 };
69
70 info!("I2C: Received write command - Address 0x{:02X}", addr_val);
71
72 let mut data_buffer = I2C_BUFFER.lock().await;
73
74 match i2c_slave.respond_to_write(&mut *data_buffer).await {
75 Ok(_) => {
76 info!(
77 "I2C: Data received - Buffer now contains: 0x{:02X}, 0x{:02X}, 0x{:02X}, 0x{:02X}, 0x{:02X}, 0x{:02X}, 0x{:02X}, 0x{:02X}",
78 data_buffer[0],
79 data_buffer[1],
80 data_buffer[2],
81 data_buffer[3],
82 data_buffer[4],
83 data_buffer[5],
84 data_buffer[6],
85 data_buffer[7]
86 );
87 }
88 Err(e) => {
89 error!("I2C: Write error: {}", format_i2c_error(&e));
90 }
91 }
92 }
93
94 Ok(SlaveCommand {
95 kind: SlaveCommandKind::Read,
96 address,
97 }) => {
98 let addr_val = match address {
99 Address::SevenBit(addr) => addr,
100 Address::TenBit(addr) => (addr & 0xFF) as u8, // Show low byte for 10-bit
101 };
102
103 info!("I2C: Received read command - Address 0x{:02X}", addr_val);
104
105 let data_buffer = I2C_BUFFER.lock().await;
106
107 match i2c_slave.respond_to_read(&data_buffer[..BUFFER_SIZE]).await {
108 Ok(_) => {
109 info!("I2C: Responded to read command");
110 }
111 Err(e) => {
112 error!("I2C: Read error: {}", format_i2c_error(&e));
113 }
114 }
115 }
116
117 Err(e) => {
118 error!("I2C: Listen error: {}", format_i2c_error(&e));
119 Timer::after(Duration::from_millis(100)).await;
120 }
121 }
122 }
123}
124
125fn format_i2c_error(e: &embassy_stm32::i2c::Error) -> &'static str {
126 match e {
127 embassy_stm32::i2c::Error::Bus => "Bus",
128 embassy_stm32::i2c::Error::Arbitration => "Arbitration",
129 embassy_stm32::i2c::Error::Nack => "Nack",
130 embassy_stm32::i2c::Error::Timeout => "Timeout",
131 embassy_stm32::i2c::Error::Crc => "Crc",
132 embassy_stm32::i2c::Error::Overrun => "Overrun",
133 embassy_stm32::i2c::Error::ZeroLengthTransfer => "ZeroLengthTransfer",
134 }
135}
diff --git a/examples/stm32f4/src/bin/i2c_slave_blocking.rs b/examples/stm32f4/src/bin/i2c_slave_blocking.rs
new file mode 100644
index 000000000..ee06d4ac4
--- /dev/null
+++ b/examples/stm32f4/src/bin/i2c_slave_blocking.rs
@@ -0,0 +1,132 @@
1//! Complete I2C slave example using blocking operations
2//!
3//! This example shows how to set up an STM32F4 as an I2C slave device
4//! that can handle both read and write transactions from master devices.
5
6#![no_std]
7#![no_main]
8
9use defmt::{error, info};
10use embassy_executor::Spawner;
11use embassy_stm32::i2c::{self, Address, I2c, SlaveAddrConfig, SlaveCommand, SlaveCommandKind};
12use embassy_stm32::time::Hertz;
13use embassy_stm32::{bind_interrupts, peripherals};
14use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex;
15use embassy_sync::mutex::Mutex;
16use embassy_time::{Duration, Timer};
17use {defmt_rtt as _, panic_probe as _};
18
19pub const I2C_SLAVE_ADDR: u8 = 0x42;
20pub const BUFFER_SIZE: usize = 8;
21static I2C_BUFFER: Mutex<ThreadModeRawMutex, [u8; BUFFER_SIZE]> = Mutex::new([0; BUFFER_SIZE]);
22
23bind_interrupts!(struct Irqs {
24 I2C1_EV => i2c::EventInterruptHandler<peripherals::I2C1>;
25 I2C1_ER => i2c::ErrorInterruptHandler<peripherals::I2C1>;
26});
27
28#[embassy_executor::main]
29async fn main(spawner: Spawner) {
30 let p = embassy_stm32::init(Default::default());
31
32 // Configure I2C
33 let mut i2c_config = i2c::Config::default();
34 i2c_config.sda_pullup = false;
35 i2c_config.scl_pullup = false;
36 i2c_config.frequency = Hertz(100_000);
37 i2c_config.timeout = embassy_time::Duration::from_millis(30000);
38
39 // Initialize I2C as master first
40 let i2c_master = I2c::new_blocking(
41 p.I2C1, p.PB8, // SCL
42 p.PB9, // SDA
43 i2c_config,
44 );
45
46 // Convert to slave+master mode
47 let slave_config = SlaveAddrConfig::basic(I2C_SLAVE_ADDR);
48 let i2c_slave = i2c_master.into_slave_multimaster(slave_config);
49
50 spawner.spawn(i2c_slave_task(i2c_slave).unwrap());
51}
52
53#[embassy_executor::task]
54pub async fn i2c_slave_task(mut i2c_slave: I2c<'static, embassy_stm32::mode::Blocking, i2c::mode::MultiMaster>) {
55 info!("Blocking I2C slave ready at address 0x{:02X}", I2C_SLAVE_ADDR);
56
57 loop {
58 match i2c_slave.blocking_listen() {
59 Ok(SlaveCommand {
60 kind: SlaveCommandKind::Write,
61 address,
62 }) => {
63 let addr_val = match address {
64 Address::SevenBit(addr) => addr,
65 Address::TenBit(addr) => (addr & 0xFF) as u8,
66 };
67
68 info!("I2C: Received write command - Address 0x{:02X}", addr_val);
69 let mut data_buffer = I2C_BUFFER.lock().await;
70
71 match i2c_slave.blocking_respond_to_write(&mut *data_buffer) {
72 Ok(bytes_received) => {
73 info!(
74 "I2C: Received {} bytes - Buffer now contains: 0x{:02X}, 0x{:02X}, 0x{:02X}, 0x{:02X}, 0x{:02X}, 0x{:02X}, 0x{:02X}, 0x{:02X}",
75 bytes_received,
76 data_buffer[0],
77 data_buffer[1],
78 data_buffer[2],
79 data_buffer[3],
80 data_buffer[4],
81 data_buffer[5],
82 data_buffer[6],
83 data_buffer[7]
84 );
85 }
86 Err(e) => {
87 error!("I2C: Write error: {}", format_i2c_error(&e));
88 }
89 }
90 }
91
92 Ok(SlaveCommand {
93 kind: SlaveCommandKind::Read,
94 address,
95 }) => {
96 let addr_val = match address {
97 Address::SevenBit(addr) => addr,
98 Address::TenBit(addr) => (addr & 0xFF) as u8, // Show low byte for 10-bit
99 };
100
101 info!("I2C: Received read command - Address 0x{:02X}", addr_val);
102 let data_buffer = I2C_BUFFER.lock().await;
103
104 match i2c_slave.blocking_respond_to_read(&data_buffer[..BUFFER_SIZE]) {
105 Ok(bytes_sent) => {
106 info!("I2C: Responded to read - {} bytes sent", bytes_sent);
107 }
108 Err(e) => {
109 error!("I2C: Read error: {}", format_i2c_error(&e));
110 }
111 }
112 }
113
114 Err(e) => {
115 error!("I2C: Listen error: {}", format_i2c_error(&e));
116 Timer::after(Duration::from_millis(100)).await;
117 }
118 }
119 }
120}
121
122fn format_i2c_error(e: &embassy_stm32::i2c::Error) -> &'static str {
123 match e {
124 embassy_stm32::i2c::Error::Bus => "Bus",
125 embassy_stm32::i2c::Error::Arbitration => "Arbitration",
126 embassy_stm32::i2c::Error::Nack => "Nack",
127 embassy_stm32::i2c::Error::Timeout => "Timeout",
128 embassy_stm32::i2c::Error::Crc => "Crc",
129 embassy_stm32::i2c::Error::Overrun => "Overrun",
130 embassy_stm32::i2c::Error::ZeroLengthTransfer => "ZeroLengthTransfer",
131 }
132}
diff --git a/examples/stm32f4/src/bin/rtc.rs b/examples/stm32f4/src/bin/rtc.rs
index feb27f6d9..5ff705ca2 100644
--- a/examples/stm32f4/src/bin/rtc.rs
+++ b/examples/stm32f4/src/bin/rtc.rs
@@ -21,12 +21,12 @@ async fn main(_spawner: Spawner) {
21 .and_hms_opt(10, 30, 15) 21 .and_hms_opt(10, 30, 15)
22 .unwrap(); 22 .unwrap();
23 23
24 let mut rtc = Rtc::new(p.RTC, RtcConfig::default()); 24 let (mut rtc, time_provider) = Rtc::new(p.RTC, RtcConfig::default());
25 25
26 rtc.set_datetime(now.into()).expect("datetime not set"); 26 rtc.set_datetime(now.into()).expect("datetime not set");
27 27
28 loop { 28 loop {
29 let now: NaiveDateTime = rtc.now().unwrap().into(); 29 let now: NaiveDateTime = time_provider.now().unwrap().into();
30 30
31 info!("{}", now.and_utc().timestamp()); 31 info!("{}", now.and_utc().timestamp());
32 32
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/stm32g0/src/bin/rtc.rs b/examples/stm32g0/src/bin/rtc.rs
index 21da204cc..d8b58de22 100644
--- a/examples/stm32g0/src/bin/rtc.rs
+++ b/examples/stm32g0/src/bin/rtc.rs
@@ -17,12 +17,12 @@ async fn main(_spawner: Spawner) {
17 17
18 let now = DateTime::from(2023, 6, 14, DayOfWeek::Friday, 15, 59, 10, 0); 18 let now = DateTime::from(2023, 6, 14, DayOfWeek::Friday, 15, 59, 10, 0);
19 19
20 let mut rtc = Rtc::new(p.RTC, RtcConfig::default()); 20 let (mut rtc, time_provider) = Rtc::new(p.RTC, RtcConfig::default());
21 21
22 rtc.set_datetime(now.unwrap()).expect("datetime not set"); 22 rtc.set_datetime(now.unwrap()).expect("datetime not set");
23 23
24 loop { 24 loop {
25 let now: DateTime = rtc.now().unwrap().into(); 25 let now: DateTime = time_provider.now().unwrap().into();
26 26
27 info!("{}:{}:{}", now.hour(), now.minute(), now.second()); 27 info!("{}:{}:{}", now.hour(), now.minute(), now.second());
28 28
diff --git a/examples/stm32g4/Cargo.toml b/examples/stm32g4/Cargo.toml
index 6fd282d6d..8bbeb594c 100644
--- a/examples/stm32g4/Cargo.toml
+++ b/examples/stm32g4/Cargo.toml
@@ -7,12 +7,12 @@ publish = false
7 7
8[dependencies] 8[dependencies]
9# Change stm32g491re to your chip name, if necessary. 9# Change stm32g491re to your chip name, if necessary.
10embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = [ "defmt", "time-driver-any", "stm32g491re", "memory-x", "unstable-pac", "exti"] } 10embassy-stm32 = { path = "../../embassy-stm32", features = [ "defmt", "time-driver-any", "stm32g491re", "memory-x", "unstable-pac", "exti"] }
11embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } 11embassy-sync = { path = "../../embassy-sync", features = ["defmt"] }
12embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } 12embassy-executor = { 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"] } 13embassy-time = { path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
14embassy-usb = { version = "0.5.1", path = "../../embassy-usb", features = ["defmt"] } 14embassy-usb = { path = "../../embassy-usb", features = ["defmt"] }
15embassy-futures = { version = "0.1.2", path = "../../embassy-futures" } 15embassy-futures = { path = "../../embassy-futures" }
16usbd-hid = "0.8.1" 16usbd-hid = "0.8.1"
17 17
18defmt = "1.0.1" 18defmt = "1.0.1"
@@ -25,6 +25,7 @@ embedded-can = { version = "0.4" }
25panic-probe = { version = "1.0.0", features = ["print-defmt"] } 25panic-probe = { version = "1.0.0", features = ["print-defmt"] }
26heapless = { version = "0.8", default-features = false } 26heapless = { version = "0.8", default-features = false }
27static_cell = "2.0.0" 27static_cell = "2.0.0"
28critical-section = "1.1"
28 29
29[profile.release] 30[profile.release]
30debug = 2 31debug = 2
diff --git a/examples/stm32g4/src/bin/adc_dma.rs b/examples/stm32g4/src/bin/adc_dma.rs
index a82067049..ef8b0c3c2 100644
--- a/examples/stm32g4/src/bin/adc_dma.rs
+++ b/examples/stm32g4/src/bin/adc_dma.rs
@@ -12,7 +12,7 @@ static mut DMA_BUF: [u16; 2] = [0; 2];
12 12
13#[embassy_executor::main] 13#[embassy_executor::main]
14async fn main(_spawner: Spawner) { 14async fn main(_spawner: Spawner) {
15 let mut read_buffer = unsafe { &mut DMA_BUF[..] }; 15 let read_buffer = unsafe { &mut DMA_BUF[..] };
16 16
17 let mut config = Config::default(); 17 let mut config = Config::default();
18 { 18 {
@@ -47,7 +47,7 @@ async fn main(_spawner: Spawner) {
47 (&mut pa0, SampleTime::CYCLES247_5), 47 (&mut pa0, SampleTime::CYCLES247_5),
48 ] 48 ]
49 .into_iter(), 49 .into_iter(),
50 &mut read_buffer, 50 read_buffer,
51 ) 51 )
52 .await; 52 .await;
53 53
diff --git a/examples/stm32g4/src/bin/adc_injected_and_regular.rs b/examples/stm32g4/src/bin/adc_injected_and_regular.rs
new file mode 100644
index 000000000..3ae2ff064
--- /dev/null
+++ b/examples/stm32g4/src/bin/adc_injected_and_regular.rs
@@ -0,0 +1,154 @@
1//! adc injected and regular conversions
2//!
3//! This example both regular and injected ADC conversions at the same time
4//! p:pa0 n:pa2
5
6#![no_std]
7#![no_main]
8
9use core::cell::RefCell;
10
11use defmt::info;
12use embassy_stm32::adc::{
13 Adc, AdcChannel as _, ConversionTrigger, Exten, InjectedAdc, RegularConversionMode, SampleTime,
14};
15use embassy_stm32::interrupt::typelevel::{ADC1_2, Interrupt};
16use embassy_stm32::peripherals::ADC1;
17use embassy_stm32::time::Hertz;
18use embassy_stm32::timer::complementary_pwm::{ComplementaryPwm, Mms2};
19use embassy_stm32::timer::low_level::CountingMode;
20use embassy_stm32::{Config, interrupt};
21use embassy_sync::blocking_mutex::CriticalSectionMutex;
22use {defmt_rtt as _, panic_probe as _};
23
24static ADC1_HANDLE: CriticalSectionMutex<RefCell<Option<InjectedAdc<ADC1, 1>>>> =
25 CriticalSectionMutex::new(RefCell::new(None));
26
27/// This example showcases how to use both regular ADC conversions with DMA and injected ADC
28/// conversions with ADC interrupt simultaneously. Both conversion types can be configured with
29/// different triggers and thanks to DMA it is possible to use the measurements in different task
30/// without needing to access the ADC peripheral.
31///
32/// If you don't need both regular and injected conversions the example code can easily be reworked
33/// to only include one of the ADC conversion types.
34#[embassy_executor::main]
35async fn main(_spawner: embassy_executor::Spawner) {
36 // See Table 166 and 167 in RM0440 Rev 9 for ADC1/2 External triggers
37 // Note: Regular and Injected channels use different tables!!
38 const ADC1_INJECTED_TRIGGER_TIM1_TRGO2: u8 = 8;
39 const ADC1_REGULAR_TRIGGER_TIM1_TRGO2: u8 = 10;
40
41 // --- RCC config ---
42 let mut config = Config::default();
43 {
44 use embassy_stm32::rcc::*;
45 config.rcc.pll = Some(Pll {
46 source: PllSource::HSI,
47 prediv: PllPreDiv::DIV4,
48 mul: PllMul::MUL85,
49 divp: None,
50 divq: None,
51 divr: Some(PllRDiv::DIV2),
52 });
53 config.rcc.mux.adc12sel = mux::Adcsel::SYS;
54 config.rcc.sys = Sysclk::PLL1_R;
55 }
56 let p = embassy_stm32::init(config);
57
58 // In this example we use tim1_trgo2 event to trigger the ADC conversions
59 let tim1 = p.TIM1;
60 let pwm_freq = 1;
61 let mut pwm = ComplementaryPwm::new(
62 tim1,
63 None,
64 None,
65 None,
66 None,
67 None,
68 None,
69 None,
70 None,
71 Hertz::hz(pwm_freq),
72 CountingMode::EdgeAlignedUp,
73 );
74 pwm.set_master_output_enable(false);
75 // Mms2 is used to configure which timer event that is connected to tim1_trgo2.
76 // In this case we use the update event of the timer.
77 pwm.set_mms2(Mms2::UPDATE);
78
79 // Configure regular conversions with DMA
80 let adc1 = Adc::new(p.ADC1);
81
82 let vrefint_channel = adc1.enable_vrefint().degrade_adc();
83 let pa0 = p.PC1.degrade_adc();
84 let regular_sequence = [
85 (vrefint_channel, SampleTime::CYCLES247_5),
86 (pa0, SampleTime::CYCLES247_5),
87 ]
88 .into_iter();
89
90 // Configurations of Injected ADC measurements
91 let pa2 = p.PA2.degrade_adc();
92 let injected_sequence = [(pa2, SampleTime::CYCLES247_5)];
93
94 // Configure DMA for retrieving regular ADC measurements
95 let dma1_ch1 = p.DMA1_CH1;
96 // Using buffer of double size means the half-full interrupts will generate at the expected rate
97 let mut readings = [0u16; 4];
98
99 let injected_trigger = ConversionTrigger {
100 channel: ADC1_INJECTED_TRIGGER_TIM1_TRGO2,
101 edge: Exten::RISING_EDGE,
102 };
103 let regular_trigger = ConversionTrigger {
104 channel: ADC1_REGULAR_TRIGGER_TIM1_TRGO2,
105 edge: Exten::RISING_EDGE,
106 };
107
108 let (mut ring_buffered_adc, injected_adc) = adc1.into_ring_buffered_and_injected(
109 dma1_ch1,
110 &mut readings,
111 regular_sequence,
112 RegularConversionMode::Triggered(regular_trigger),
113 injected_sequence,
114 injected_trigger,
115 true,
116 );
117
118 // Store ADC globally to allow access from ADC interrupt
119 critical_section::with(|cs| {
120 ADC1_HANDLE.borrow(cs).replace(Some(injected_adc));
121 });
122 // Enable interrupt for ADC1_2
123 unsafe { ADC1_2::enable() };
124
125 // Main loop for reading regular ADC measurements periodically
126 let mut data = [0u16; 2];
127 loop {
128 {
129 match ring_buffered_adc.read(&mut data).await {
130 Ok(n) => {
131 defmt::info!("Regular ADC reading, VrefInt: {}, PA0: {}", data[0], data[1]);
132 defmt::info!("Remaining samples: {}", n,);
133 }
134 Err(e) => {
135 defmt::error!("DMA error: {:?}", e);
136 ring_buffered_adc.clear();
137 }
138 }
139 }
140 }
141}
142
143/// Use ADC1_2 interrupt to retrieve injected ADC measurements
144/// Interrupt must be unsafe as hardware can invoke it any-time. Critical sections ensure safety
145/// within the interrupt.
146#[interrupt]
147unsafe fn ADC1_2() {
148 critical_section::with(|cs| {
149 if let Some(injected_adc) = ADC1_HANDLE.borrow(cs).borrow_mut().as_mut() {
150 let injected_data = injected_adc.read_injected_samples();
151 info!("Injected reading of PA2: {}", injected_data[0]);
152 }
153 });
154}
diff --git a/examples/stm32h5/Cargo.toml b/examples/stm32h5/Cargo.toml
index 475ba7e8a..512186c3d 100644
--- a/examples/stm32h5/Cargo.toml
+++ b/examples/stm32h5/Cargo.toml
@@ -29,7 +29,7 @@ panic-probe = { version = "1.0.0", features = ["print-defmt"] }
29heapless = { version = "0.8", default-features = false } 29heapless = { version = "0.8", default-features = false }
30critical-section = "1.1" 30critical-section = "1.1"
31micromath = "2.0.0" 31micromath = "2.0.0"
32stm32-fmc = "0.3.0" 32stm32-fmc = "0.4.0"
33embedded-storage = "0.3.1" 33embedded-storage = "0.3.1"
34static_cell = "2" 34static_cell = "2"
35 35
diff --git a/examples/stm32h5/src/bin/backup_sram.rs b/examples/stm32h5/src/bin/backup_sram.rs
new file mode 100644
index 000000000..f8db1853e
--- /dev/null
+++ b/examples/stm32h5/src/bin/backup_sram.rs
@@ -0,0 +1,31 @@
1#![no_std]
2#![no_main]
3
4use defmt::*;
5use embassy_executor::Spawner;
6use embassy_stm32::Config;
7use embassy_stm32::backup_sram::BackupMemory;
8use embassy_time::Timer;
9use {defmt_rtt as _, panic_probe as _};
10
11#[embassy_executor::main]
12async fn main(_spawner: Spawner) {
13 let mut config = Config::default();
14 config.rcc.ls.enable_backup_sram = true;
15
16 let p = embassy_stm32::init(config);
17 info!("Started!");
18
19 let (bytes, status) = BackupMemory::new(p.BKPSRAM);
20
21 match status {
22 false => info!("BKPSRAM just enabled"),
23 true => info!("BKPSRAM already enabled"),
24 }
25
26 loop {
27 info!("byte0: {}", bytes[0]);
28 bytes[0] = bytes[0].wrapping_add(1);
29 Timer::after_millis(500).await;
30 }
31}
diff --git a/examples/stm32h5/src/bin/stop.rs b/examples/stm32h5/src/bin/stop.rs
index 3c4f49f64..caebc9daf 100644
--- a/examples/stm32h5/src/bin/stop.rs
+++ b/examples/stm32h5/src/bin/stop.rs
@@ -9,10 +9,8 @@ use embassy_executor::Spawner;
9use embassy_stm32::gpio::{AnyPin, Level, Output, Speed}; 9use embassy_stm32::gpio::{AnyPin, Level, Output, Speed};
10use embassy_stm32::low_power::Executor; 10use embassy_stm32::low_power::Executor;
11use embassy_stm32::rcc::{HSIPrescaler, LsConfig}; 11use embassy_stm32::rcc::{HSIPrescaler, LsConfig};
12use embassy_stm32::rtc::{Rtc, RtcConfig};
13use embassy_stm32::{Config, Peri}; 12use embassy_stm32::{Config, Peri};
14use embassy_time::Timer; 13use embassy_time::Timer;
15use static_cell::StaticCell;
16use {defmt_rtt as _, panic_probe as _}; 14use {defmt_rtt as _, panic_probe as _};
17 15
18#[cortex_m_rt::entry] 16#[cortex_m_rt::entry]
@@ -37,12 +35,6 @@ async fn async_main(spawner: Spawner) {
37 // config.enable_debug_during_sleep = false; 35 // config.enable_debug_during_sleep = false;
38 let p = embassy_stm32::init(config); 36 let p = embassy_stm32::init(config);
39 37
40 // give the RTC to the executor...
41 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);
45
46 spawner.spawn(unwrap!(blinky(p.PB4.into()))); 38 spawner.spawn(unwrap!(blinky(p.PB4.into())));
47 spawner.spawn(unwrap!(timeout())); 39 spawner.spawn(unwrap!(timeout()));
48} 40}
diff --git a/examples/stm32h7/Cargo.toml b/examples/stm32h7/Cargo.toml
index 5993110de..09b734054 100644
--- a/examples/stm32h7/Cargo.toml
+++ b/examples/stm32h7/Cargo.toml
@@ -30,7 +30,7 @@ panic-probe = { version = "1.0.0", features = ["print-defmt"] }
30heapless = { version = "0.8", default-features = false } 30heapless = { version = "0.8", default-features = false }
31critical-section = "1.1" 31critical-section = "1.1"
32micromath = "2.0.0" 32micromath = "2.0.0"
33stm32-fmc = "0.3.0" 33stm32-fmc = "0.4.0"
34embedded-storage = "0.3.1" 34embedded-storage = "0.3.1"
35static_cell = "2" 35static_cell = "2"
36chrono = { version = "^0.4", default-features = false } 36chrono = { version = "^0.4", default-features = false }
diff --git a/examples/stm32h7/src/bin/rtc.rs b/examples/stm32h7/src/bin/rtc.rs
index 1bd71637b..965716d23 100644
--- a/examples/stm32h7/src/bin/rtc.rs
+++ b/examples/stm32h7/src/bin/rtc.rs
@@ -23,7 +23,7 @@ async fn main(_spawner: Spawner) {
23 .and_hms_opt(10, 30, 15) 23 .and_hms_opt(10, 30, 15)
24 .unwrap(); 24 .unwrap();
25 25
26 let mut rtc = Rtc::new(p.RTC, RtcConfig::default()); 26 let (mut rtc, time_provider) = Rtc::new(p.RTC, RtcConfig::default());
27 info!("Got RTC! {:?}", now.and_utc().timestamp()); 27 info!("Got RTC! {:?}", now.and_utc().timestamp());
28 28
29 rtc.set_datetime(now.into()).expect("datetime not set"); 29 rtc.set_datetime(now.into()).expect("datetime not set");
@@ -31,6 +31,6 @@ async fn main(_spawner: Spawner) {
31 // In reality the delay would be much longer 31 // In reality the delay would be much longer
32 Timer::after_millis(20000).await; 32 Timer::after_millis(20000).await;
33 33
34 let then: NaiveDateTime = rtc.now().unwrap().into(); 34 let then: NaiveDateTime = time_provider.now().unwrap().into();
35 info!("Got RTC! {:?}", then.and_utc().timestamp()); 35 info!("Got RTC! {:?}", then.and_utc().timestamp());
36} 36}
diff --git a/examples/stm32h7/src/bin/spi.rs b/examples/stm32h7/src/bin/spi.rs
index 61f31be24..f7ab20cdd 100644
--- a/examples/stm32h7/src/bin/spi.rs
+++ b/examples/stm32h7/src/bin/spi.rs
@@ -15,7 +15,7 @@ use static_cell::StaticCell;
15use {defmt_rtt as _, panic_probe as _}; 15use {defmt_rtt as _, panic_probe as _};
16 16
17#[embassy_executor::task] 17#[embassy_executor::task]
18async fn main_task(mut spi: spi::Spi<'static, Blocking>) { 18async fn main_task(mut spi: spi::Spi<'static, Blocking, spi::mode::Master>) {
19 for n in 0u32.. { 19 for n in 0u32.. {
20 let mut write: String<128> = String::new(); 20 let mut write: String<128> = String::new();
21 core::write!(&mut write, "Hello DMA World {}!\r\n", n).unwrap(); 21 core::write!(&mut write, "Hello DMA World {}!\r\n", n).unwrap();
diff --git a/examples/stm32h7/src/bin/spi_bdma.rs b/examples/stm32h7/src/bin/spi_bdma.rs
index be6a26d82..cd9d6c789 100644
--- a/examples/stm32h7/src/bin/spi_bdma.rs
+++ b/examples/stm32h7/src/bin/spi_bdma.rs
@@ -20,7 +20,7 @@ use {defmt_rtt as _, panic_probe as _};
20static mut RAM_D3: GroundedArrayCell<u8, 256> = GroundedArrayCell::uninit(); 20static mut RAM_D3: GroundedArrayCell<u8, 256> = GroundedArrayCell::uninit();
21 21
22#[embassy_executor::task] 22#[embassy_executor::task]
23async fn main_task(mut spi: spi::Spi<'static, Async>) { 23async fn main_task(mut spi: spi::Spi<'static, Async, spi::mode::Master>) {
24 let (read_buffer, write_buffer) = unsafe { 24 let (read_buffer, write_buffer) = unsafe {
25 let ram = &mut *core::ptr::addr_of_mut!(RAM_D3); 25 let ram = &mut *core::ptr::addr_of_mut!(RAM_D3);
26 ram.initialize_all_copied(0); 26 ram.initialize_all_copied(0);
diff --git a/examples/stm32h7/src/bin/spi_dma.rs b/examples/stm32h7/src/bin/spi_dma.rs
index 20cb67ba0..3d3c2f43e 100644
--- a/examples/stm32h7/src/bin/spi_dma.rs
+++ b/examples/stm32h7/src/bin/spi_dma.rs
@@ -15,7 +15,7 @@ use static_cell::StaticCell;
15use {defmt_rtt as _, panic_probe as _}; 15use {defmt_rtt as _, panic_probe as _};
16 16
17#[embassy_executor::task] 17#[embassy_executor::task]
18async fn main_task(mut spi: spi::Spi<'static, Async>) { 18async fn main_task(mut spi: spi::Spi<'static, Async, spi::mode::Master>) {
19 for n in 0u32.. { 19 for n in 0u32.. {
20 let mut write: String<128> = String::new(); 20 let mut write: String<128> = String::new();
21 let mut read = [0; 128]; 21 let mut read = [0; 128];
diff --git a/examples/stm32h755cm4/Cargo.toml b/examples/stm32h755cm4/Cargo.toml
index b5c313523..d69f0228e 100644
--- a/examples/stm32h755cm4/Cargo.toml
+++ b/examples/stm32h755cm4/Cargo.toml
@@ -30,7 +30,7 @@ panic-probe = { version = "1.0.0", features = ["print-defmt"] }
30heapless = { version = "0.8", default-features = false } 30heapless = { version = "0.8", default-features = false }
31critical-section = "1.1" 31critical-section = "1.1"
32micromath = "2.0.0" 32micromath = "2.0.0"
33stm32-fmc = "0.3.0" 33stm32-fmc = "0.4.0"
34embedded-storage = "0.3.1" 34embedded-storage = "0.3.1"
35static_cell = "2" 35static_cell = "2"
36chrono = { version = "^0.4", default-features = false } 36chrono = { version = "^0.4", default-features = false }
diff --git a/examples/stm32h755cm7/Cargo.toml b/examples/stm32h755cm7/Cargo.toml
index 7a1519aae..f4e1e53b7 100644
--- a/examples/stm32h755cm7/Cargo.toml
+++ b/examples/stm32h755cm7/Cargo.toml
@@ -30,7 +30,7 @@ panic-probe = { version = "1.0.0", features = ["print-defmt"] }
30heapless = { version = "0.8", default-features = false } 30heapless = { version = "0.8", default-features = false }
31critical-section = "1.1" 31critical-section = "1.1"
32micromath = "2.0.0" 32micromath = "2.0.0"
33stm32-fmc = "0.3.0" 33stm32-fmc = "0.4.0"
34embedded-storage = "0.3.1" 34embedded-storage = "0.3.1"
35static_cell = "2" 35static_cell = "2"
36chrono = { version = "^0.4", default-features = false } 36chrono = { version = "^0.4", default-features = false }
diff --git a/examples/stm32h7b0/Cargo.toml b/examples/stm32h7b0/Cargo.toml
index 4cd7b84e5..0509d394d 100644
--- a/examples/stm32h7b0/Cargo.toml
+++ b/examples/stm32h7b0/Cargo.toml
@@ -29,7 +29,7 @@ panic-probe = { version = "1.0.0", features = ["print-defmt"] }
29heapless = { version = "0.8", default-features = false } 29heapless = { version = "0.8", default-features = false }
30critical-section = "1.1" 30critical-section = "1.1"
31micromath = "2.0.0" 31micromath = "2.0.0"
32stm32-fmc = "0.3.0" 32stm32-fmc = "0.4.0"
33embedded-storage = "0.3.1" 33embedded-storage = "0.3.1"
34static_cell = "2" 34static_cell = "2"
35chrono = { version = "^0.4", default-features = false } 35chrono = { version = "^0.4", default-features = false }
diff --git a/examples/stm32h7rs/Cargo.toml b/examples/stm32h7rs/Cargo.toml
index 445916972..ab525ad91 100644
--- a/examples/stm32h7rs/Cargo.toml
+++ b/examples/stm32h7rs/Cargo.toml
@@ -29,7 +29,7 @@ panic-probe = { version = "1.0.0", features = ["print-defmt"] }
29heapless = { version = "0.8", default-features = false } 29heapless = { version = "0.8", default-features = false }
30critical-section = "1.1" 30critical-section = "1.1"
31micromath = "2.0.0" 31micromath = "2.0.0"
32stm32-fmc = "0.3.0" 32stm32-fmc = "0.4.0"
33embedded-storage = "0.3.1" 33embedded-storage = "0.3.1"
34static_cell = "2" 34static_cell = "2"
35chrono = { version = "^0.4", default-features = false } 35chrono = { version = "^0.4", default-features = false }
diff --git a/examples/stm32h7rs/src/bin/rtc.rs b/examples/stm32h7rs/src/bin/rtc.rs
index 1bd71637b..965716d23 100644
--- a/examples/stm32h7rs/src/bin/rtc.rs
+++ b/examples/stm32h7rs/src/bin/rtc.rs
@@ -23,7 +23,7 @@ async fn main(_spawner: Spawner) {
23 .and_hms_opt(10, 30, 15) 23 .and_hms_opt(10, 30, 15)
24 .unwrap(); 24 .unwrap();
25 25
26 let mut rtc = Rtc::new(p.RTC, RtcConfig::default()); 26 let (mut rtc, time_provider) = Rtc::new(p.RTC, RtcConfig::default());
27 info!("Got RTC! {:?}", now.and_utc().timestamp()); 27 info!("Got RTC! {:?}", now.and_utc().timestamp());
28 28
29 rtc.set_datetime(now.into()).expect("datetime not set"); 29 rtc.set_datetime(now.into()).expect("datetime not set");
@@ -31,6 +31,6 @@ async fn main(_spawner: Spawner) {
31 // In reality the delay would be much longer 31 // In reality the delay would be much longer
32 Timer::after_millis(20000).await; 32 Timer::after_millis(20000).await;
33 33
34 let then: NaiveDateTime = rtc.now().unwrap().into(); 34 let then: NaiveDateTime = time_provider.now().unwrap().into();
35 info!("Got RTC! {:?}", then.and_utc().timestamp()); 35 info!("Got RTC! {:?}", then.and_utc().timestamp());
36} 36}
diff --git a/examples/stm32h7rs/src/bin/spi.rs b/examples/stm32h7rs/src/bin/spi.rs
index 8c280fdae..3253304eb 100644
--- a/examples/stm32h7rs/src/bin/spi.rs
+++ b/examples/stm32h7rs/src/bin/spi.rs
@@ -15,7 +15,7 @@ use static_cell::StaticCell;
15use {defmt_rtt as _, panic_probe as _}; 15use {defmt_rtt as _, panic_probe as _};
16 16
17#[embassy_executor::task] 17#[embassy_executor::task]
18async fn main_task(mut spi: spi::Spi<'static, Blocking>) { 18async fn main_task(mut spi: spi::Spi<'static, Blocking, spi::mode::Master>) {
19 for n in 0u32.. { 19 for n in 0u32.. {
20 let mut write: String<128> = String::new(); 20 let mut write: String<128> = String::new();
21 core::write!(&mut write, "Hello DMA World {}!\r\n", n).unwrap(); 21 core::write!(&mut write, "Hello DMA World {}!\r\n", n).unwrap();
diff --git a/examples/stm32h7rs/src/bin/spi_dma.rs b/examples/stm32h7rs/src/bin/spi_dma.rs
index 3fa69fd15..ca644c6a8 100644
--- a/examples/stm32h7rs/src/bin/spi_dma.rs
+++ b/examples/stm32h7rs/src/bin/spi_dma.rs
@@ -15,7 +15,7 @@ use static_cell::StaticCell;
15use {defmt_rtt as _, panic_probe as _}; 15use {defmt_rtt as _, panic_probe as _};
16 16
17#[embassy_executor::task] 17#[embassy_executor::task]
18async fn main_task(mut spi: spi::Spi<'static, Async>) { 18async fn main_task(mut spi: spi::Spi<'static, Async, spi::mode::Master>) {
19 for n in 0u32.. { 19 for n in 0u32.. {
20 let mut write: String<128> = String::new(); 20 let mut write: String<128> = String::new();
21 let mut read = [0; 128]; 21 let mut read = [0; 128];
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/stm32l4/src/bin/rtc.rs b/examples/stm32l4/src/bin/rtc.rs
index 1d26cd008..8b92075cc 100644
--- a/examples/stm32l4/src/bin/rtc.rs
+++ b/examples/stm32l4/src/bin/rtc.rs
@@ -39,7 +39,7 @@ async fn main(_spawner: Spawner) {
39 .and_hms_opt(10, 30, 15) 39 .and_hms_opt(10, 30, 15)
40 .unwrap(); 40 .unwrap();
41 41
42 let mut rtc = Rtc::new(p.RTC, RtcConfig::default()); 42 let (mut rtc, time_provider) = Rtc::new(p.RTC, RtcConfig::default());
43 info!("Got RTC! {:?}", now.and_utc().timestamp()); 43 info!("Got RTC! {:?}", now.and_utc().timestamp());
44 44
45 rtc.set_datetime(now.into()).expect("datetime not set"); 45 rtc.set_datetime(now.into()).expect("datetime not set");
@@ -47,6 +47,6 @@ async fn main(_spawner: Spawner) {
47 // In reality the delay would be much longer 47 // In reality the delay would be much longer
48 Timer::after_millis(20000).await; 48 Timer::after_millis(20000).await;
49 49
50 let then: NaiveDateTime = rtc.now().unwrap().into(); 50 let then: NaiveDateTime = time_provider.now().unwrap().into();
51 info!("Got RTC! {:?}", then.and_utc().timestamp()); 51 info!("Got RTC! {:?}", then.and_utc().timestamp());
52} 52}
diff --git a/examples/stm32l4/src/bin/spe_adin1110_http_server.rs b/examples/stm32l4/src/bin/spe_adin1110_http_server.rs
index 8e54938d1..0dbf515cf 100644
--- a/examples/stm32l4/src/bin/spe_adin1110_http_server.rs
+++ b/examples/stm32l4/src/bin/spe_adin1110_http_server.rs
@@ -28,6 +28,7 @@ use embassy_stm32::gpio::{Input, Level, Output, Pull, Speed};
28use embassy_stm32::i2c::{self, Config as I2C_Config, I2c}; 28use embassy_stm32::i2c::{self, Config as I2C_Config, I2c};
29use embassy_stm32::mode::Async; 29use embassy_stm32::mode::Async;
30use embassy_stm32::rng::{self, Rng}; 30use embassy_stm32::rng::{self, Rng};
31use embassy_stm32::spi::mode::Master;
31use embassy_stm32::spi::{Config as SPI_Config, Spi}; 32use embassy_stm32::spi::{Config as SPI_Config, Spi};
32use embassy_stm32::time::Hertz; 33use embassy_stm32::time::Hertz;
33use embassy_stm32::{bind_interrupts, exti, pac, peripherals}; 34use embassy_stm32::{bind_interrupts, exti, pac, peripherals};
@@ -54,7 +55,7 @@ const IP_ADDRESS: Ipv4Cidr = Ipv4Cidr::new(Ipv4Address::new(192, 168, 1, 5), 24)
54// Listen port for the webserver 55// Listen port for the webserver
55const HTTP_LISTEN_PORT: u16 = 80; 56const HTTP_LISTEN_PORT: u16 = 80;
56 57
57pub type SpeSpi = Spi<'static, Async>; 58pub type SpeSpi = Spi<'static, Async, Master>;
58pub type SpeSpiCs = ExclusiveDevice<SpeSpi, Output<'static>, Delay>; 59pub type SpeSpiCs = ExclusiveDevice<SpeSpi, Output<'static>, Delay>;
59pub type SpeInt = exti::ExtiInput<'static>; 60pub type SpeInt = exti::ExtiInput<'static>;
60pub type SpeRst = Output<'static>; 61pub type SpeRst = Output<'static>;
diff --git a/examples/stm32l5/src/bin/stop.rs b/examples/stm32l5/src/bin/stop.rs
index c34053190..3d119f90f 100644
--- a/examples/stm32l5/src/bin/stop.rs
+++ b/examples/stm32l5/src/bin/stop.rs
@@ -6,10 +6,8 @@ use embassy_executor::Spawner;
6use embassy_stm32::gpio::{AnyPin, Level, Output, Speed}; 6use embassy_stm32::gpio::{AnyPin, Level, Output, Speed};
7use embassy_stm32::low_power::Executor; 7use embassy_stm32::low_power::Executor;
8use embassy_stm32::rcc::LsConfig; 8use embassy_stm32::rcc::LsConfig;
9use embassy_stm32::rtc::{Rtc, RtcConfig};
10use embassy_stm32::{Config, Peri}; 9use embassy_stm32::{Config, Peri};
11use embassy_time::Timer; 10use embassy_time::Timer;
12use static_cell::StaticCell;
13use {defmt_rtt as _, panic_probe as _}; 11use {defmt_rtt as _, panic_probe as _};
14 12
15#[cortex_m_rt::entry] 13#[cortex_m_rt::entry]
@@ -28,12 +26,6 @@ async fn async_main(spawner: Spawner) {
28 // config.enable_debug_during_sleep = false; 26 // config.enable_debug_during_sleep = false;
29 let p = embassy_stm32::init(config); 27 let p = embassy_stm32::init(config);
30 28
31 // give the RTC to the executor...
32 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);
36
37 spawner.spawn(unwrap!(blinky(p.PC7.into()))); 29 spawner.spawn(unwrap!(blinky(p.PC7.into())));
38 spawner.spawn(unwrap!(timeout())); 30 spawner.spawn(unwrap!(timeout()));
39} 31}
diff --git a/examples/stm32u0/src/bin/rtc.rs b/examples/stm32u0/src/bin/rtc.rs
index d071cfbc7..56d16ccf7 100644
--- a/examples/stm32u0/src/bin/rtc.rs
+++ b/examples/stm32u0/src/bin/rtc.rs
@@ -36,7 +36,7 @@ async fn main(_spawner: Spawner) {
36 .and_hms_opt(10, 30, 15) 36 .and_hms_opt(10, 30, 15)
37 .unwrap(); 37 .unwrap();
38 38
39 let mut rtc = Rtc::new(p.RTC, RtcConfig::default()); 39 let (mut rtc, time_provider) = Rtc::new(p.RTC, RtcConfig::default());
40 info!("Got RTC! {:?}", now.and_utc().timestamp()); 40 info!("Got RTC! {:?}", now.and_utc().timestamp());
41 41
42 rtc.set_datetime(now.into()).expect("datetime not set"); 42 rtc.set_datetime(now.into()).expect("datetime not set");
@@ -44,6 +44,6 @@ async fn main(_spawner: Spawner) {
44 // In reality the delay would be much longer 44 // In reality the delay would be much longer
45 Timer::after_millis(20000).await; 45 Timer::after_millis(20000).await;
46 46
47 let then: NaiveDateTime = rtc.now().unwrap().into(); 47 let then: NaiveDateTime = time_provider.now().unwrap().into();
48 info!("Got RTC! {:?}", then.and_utc().timestamp()); 48 info!("Got RTC! {:?}", then.and_utc().timestamp());
49} 49}
diff --git a/examples/stm32wl/src/bin/rtc.rs b/examples/stm32wl/src/bin/rtc.rs
index d3709120f..2185142c9 100644
--- a/examples/stm32wl/src/bin/rtc.rs
+++ b/examples/stm32wl/src/bin/rtc.rs
@@ -44,7 +44,7 @@ async fn main(_spawner: Spawner) {
44 .and_hms_opt(10, 30, 15) 44 .and_hms_opt(10, 30, 15)
45 .unwrap(); 45 .unwrap();
46 46
47 let mut rtc = Rtc::new(p.RTC, RtcConfig::default()); 47 let (mut rtc, time_provider) = Rtc::new(p.RTC, RtcConfig::default());
48 info!("Got RTC! {:?}", now.and_utc().timestamp()); 48 info!("Got RTC! {:?}", now.and_utc().timestamp());
49 49
50 rtc.set_datetime(now.into()).expect("datetime not set"); 50 rtc.set_datetime(now.into()).expect("datetime not set");
@@ -52,6 +52,6 @@ async fn main(_spawner: Spawner) {
52 // In reality the delay would be much longer 52 // In reality the delay would be much longer
53 Timer::after_millis(20000).await; 53 Timer::after_millis(20000).await;
54 54
55 let then: NaiveDateTime = rtc.now().unwrap().into(); 55 let then: NaiveDateTime = time_provider.now().unwrap().into();
56 info!("Got RTC! {:?}", then.and_utc().timestamp()); 56 info!("Got RTC! {:?}", then.and_utc().timestamp());
57} 57}
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..8b830a1e6
--- /dev/null
+++ b/examples/stm32wle5/src/bin/adc.rs
@@ -0,0 +1,94 @@
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_time::Timer;
11use panic_probe as _;
12use static_cell::StaticCell;
13
14#[cortex_m_rt::entry]
15fn main() -> ! {
16 info!("main: Starting!");
17 Executor::take().run(|spawner| {
18 spawner.spawn(unwrap!(async_main(spawner)));
19 });
20}
21
22#[embassy_executor::task]
23async fn async_main(_spawner: Spawner) {
24 let mut config = embassy_stm32::Config::default();
25 // enable HSI clock
26 config.rcc.hsi = true;
27 // enable LSI clock for RTC
28 config.rcc.ls = embassy_stm32::rcc::LsConfig::default_lsi();
29 config.rcc.msi = Some(embassy_stm32::rcc::MSIRange::RANGE4M);
30 config.rcc.sys = embassy_stm32::rcc::Sysclk::MSI;
31 // enable ADC with HSI clock
32 config.rcc.mux.adcsel = embassy_stm32::pac::rcc::vals::Adcsel::HSI;
33 #[cfg(feature = "defmt-serial")]
34 {
35 // disable debug during sleep to reduce power consumption since we are
36 // using defmt-serial on LPUART1.
37 config.enable_debug_during_sleep = false;
38 // if we are using defmt-serial on LPUART1, we need to use HSI for the clock
39 // so that its registers are preserved during STOP modes.
40 config.rcc.mux.lpuart1sel = embassy_stm32::pac::rcc::vals::Lpuart1sel::HSI;
41 }
42 // Initialize STM32WL peripherals (use default config like wio-e5-async example)
43 let p = embassy_stm32::init(config);
44
45 // start with all GPIOs as analog to reduce power consumption
46 for r in [
47 embassy_stm32::pac::GPIOA,
48 embassy_stm32::pac::GPIOB,
49 embassy_stm32::pac::GPIOC,
50 embassy_stm32::pac::GPIOH,
51 ] {
52 r.moder().modify(|w| {
53 for i in 0..16 {
54 // don't reset these if probe-rs should stay connected!
55 #[cfg(feature = "defmt-rtt")]
56 if config.enable_debug_during_sleep && r == embassy_stm32::pac::GPIOA && [13, 14].contains(&i) {
57 continue;
58 }
59 w.set_moder(i, embassy_stm32::pac::gpio::vals::Moder::ANALOG);
60 }
61 });
62 }
63 #[cfg(feature = "defmt-serial")]
64 {
65 use embassy_stm32::mode::Blocking;
66 use embassy_stm32::usart::Uart;
67 let config = embassy_stm32::usart::Config::default();
68 let uart = Uart::new_blocking(p.LPUART1, p.PC0, p.PC1, config).expect("failed to configure UART!");
69 static SERIAL: StaticCell<Uart<'static, Blocking>> = StaticCell::new();
70 defmt_serial::defmt_serial(SERIAL.init(uart));
71 }
72
73 info!("Hello World!");
74
75 let mut adc = Adc::new(p.ADC1);
76 adc.set_sample_time(SampleTime::CYCLES79_5);
77 let mut pin = p.PA10;
78
79 let mut vrefint = adc.enable_vrefint();
80 let vrefint_sample = adc.blocking_read(&mut vrefint);
81 let convert_to_millivolts = |sample| {
82 // From https://www.st.com/resource/en/datasheet/stm32g031g8.pdf
83 // 6.3.3 Embedded internal reference voltage
84 const VREFINT_MV: u32 = 1212; // mV
85
86 (u32::from(sample) * VREFINT_MV / u32::from(vrefint_sample)) as u16
87 };
88
89 loop {
90 let v = adc.blocking_read(&mut pin);
91 info!("--> {} - {} mV", v, convert_to_millivolts(v));
92 Timer::after_secs(1).await;
93 }
94}
diff --git a/examples/stm32wle5/src/bin/blinky.rs b/examples/stm32wle5/src/bin/blinky.rs
new file mode 100644
index 000000000..b2745fdaf
--- /dev/null
+++ b/examples/stm32wle5/src/bin/blinky.rs
@@ -0,0 +1,84 @@
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_time::Timer;
11use panic_probe as _;
12use static_cell::StaticCell;
13
14#[cortex_m_rt::entry]
15fn main() -> ! {
16 info!("main: Starting!");
17 Executor::take().run(|spawner| {
18 spawner.spawn(unwrap!(async_main(spawner)));
19 });
20}
21
22#[embassy_executor::task]
23async fn async_main(_spawner: Spawner) {
24 let mut config = embassy_stm32::Config::default();
25 // enable HSI clock
26 config.rcc.hsi = true;
27 // enable LSI clock for RTC
28 config.rcc.ls = embassy_stm32::rcc::LsConfig::default_lsi();
29 config.rcc.msi = Some(embassy_stm32::rcc::MSIRange::RANGE4M);
30 config.rcc.sys = embassy_stm32::rcc::Sysclk::MSI;
31 #[cfg(feature = "defmt-serial")]
32 {
33 // disable debug during sleep to reduce power consumption since we are
34 // using defmt-serial on LPUART1.
35 config.enable_debug_during_sleep = false;
36 // if we are using defmt-serial on LPUART1, we need to use HSI for the clock
37 // so that its registers are preserved during STOP modes.
38 config.rcc.mux.lpuart1sel = embassy_stm32::pac::rcc::vals::Lpuart1sel::HSI;
39 }
40 // Initialize STM32WL peripherals (use default config like wio-e5-async example)
41 let p = embassy_stm32::init(config);
42
43 // start with all GPIOs as analog to reduce power consumption
44 for r in [
45 embassy_stm32::pac::GPIOA,
46 embassy_stm32::pac::GPIOB,
47 embassy_stm32::pac::GPIOC,
48 embassy_stm32::pac::GPIOH,
49 ] {
50 r.moder().modify(|w| {
51 for i in 0..16 {
52 // don't reset these if probe-rs should stay connected!
53 #[cfg(feature = "defmt-rtt")]
54 if config.enable_debug_during_sleep && r == embassy_stm32::pac::GPIOA && [13, 14].contains(&i) {
55 continue;
56 }
57 w.set_moder(i, embassy_stm32::pac::gpio::vals::Moder::ANALOG);
58 }
59 });
60 }
61 #[cfg(feature = "defmt-serial")]
62 {
63 use embassy_stm32::mode::Blocking;
64 use embassy_stm32::usart::Uart;
65 let config = embassy_stm32::usart::Config::default();
66 let uart = Uart::new_blocking(p.LPUART1, p.PC0, p.PC1, config).expect("failed to configure UART!");
67 static SERIAL: StaticCell<Uart<'static, Blocking>> = StaticCell::new();
68 defmt_serial::defmt_serial(SERIAL.init(uart));
69 }
70
71 info!("Hello World!");
72
73 let mut led = Output::new(p.PB5, Level::High, Speed::Low);
74
75 loop {
76 info!("low");
77 led.set_low();
78 Timer::after_millis(500).await;
79
80 info!("high");
81 led.set_high();
82 Timer::after_millis(500).await;
83 }
84}
diff --git a/examples/stm32wle5/src/bin/button_exti.rs b/examples/stm32wle5/src/bin/button_exti.rs
new file mode 100644
index 000000000..db1bff0be
--- /dev/null
+++ b/examples/stm32wle5/src/bin/button_exti.rs
@@ -0,0 +1,85 @@
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 panic_probe as _;
12use static_cell::StaticCell;
13
14#[cortex_m_rt::entry]
15fn main() -> ! {
16 info!("main: Starting!");
17 Executor::take().run(|spawner| {
18 spawner.spawn(unwrap!(async_main(spawner)));
19 });
20}
21
22#[embassy_executor::task]
23async fn async_main(_spawner: Spawner) {
24 let mut config = embassy_stm32::Config::default();
25 // enable HSI clock
26 config.rcc.hsi = true;
27 // enable LSI clock for RTC
28 config.rcc.ls = embassy_stm32::rcc::LsConfig::default_lsi();
29 config.rcc.msi = Some(embassy_stm32::rcc::MSIRange::RANGE4M);
30 config.rcc.sys = embassy_stm32::rcc::Sysclk::MSI;
31 // enable ADC with HSI clock
32 config.rcc.mux.adcsel = embassy_stm32::pac::rcc::vals::Adcsel::HSI;
33 #[cfg(feature = "defmt-serial")]
34 {
35 // disable debug during sleep to reduce power consumption since we are
36 // using defmt-serial on LPUART1.
37 config.enable_debug_during_sleep = false;
38 // if we are using defmt-serial on LPUART1, we need to use HSI for the clock
39 // so that its registers are preserved during STOP modes.
40 config.rcc.mux.lpuart1sel = embassy_stm32::pac::rcc::vals::Lpuart1sel::HSI;
41 }
42 // Initialize STM32WL peripherals (use default config like wio-e5-async example)
43 let p = embassy_stm32::init(config);
44
45 // start with all GPIOs as analog to reduce power consumption
46 for r in [
47 embassy_stm32::pac::GPIOA,
48 embassy_stm32::pac::GPIOB,
49 embassy_stm32::pac::GPIOC,
50 embassy_stm32::pac::GPIOH,
51 ] {
52 r.moder().modify(|w| {
53 for i in 0..16 {
54 // don't reset these if probe-rs should stay connected!
55 #[cfg(feature = "defmt-rtt")]
56 if config.enable_debug_during_sleep && r == embassy_stm32::pac::GPIOA && [13, 14].contains(&i) {
57 continue;
58 }
59 w.set_moder(i, embassy_stm32::pac::gpio::vals::Moder::ANALOG);
60 }
61 });
62 }
63 #[cfg(feature = "defmt-serial")]
64 {
65 use embassy_stm32::mode::Blocking;
66 use embassy_stm32::usart::Uart;
67 let config = embassy_stm32::usart::Config::default();
68 let uart = Uart::new_blocking(p.LPUART1, p.PC0, p.PC1, config).expect("failed to configure UART!");
69 static SERIAL: StaticCell<Uart<'static, Blocking>> = StaticCell::new();
70 defmt_serial::defmt_serial(SERIAL.init(uart));
71 }
72
73 info!("Hello World!");
74
75 let mut button = ExtiInput::new(p.PA0, p.EXTI0, Pull::Up);
76
77 info!("Press the USER button...");
78
79 loop {
80 button.wait_for_falling_edge().await;
81 info!("Pressed!");
82 button.wait_for_rising_edge().await;
83 info!("Released!");
84 }
85}
diff --git a/examples/stm32wle5/src/bin/i2c.rs b/examples/stm32wle5/src/bin/i2c.rs
new file mode 100644
index 000000000..c31c673c9
--- /dev/null
+++ b/examples/stm32wle5/src/bin/i2c.rs
@@ -0,0 +1,104 @@
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::time::Hertz;
11use embassy_stm32::{bind_interrupts, i2c, peripherals};
12use embassy_time::{Duration, Timer};
13use panic_probe as _;
14use static_cell::StaticCell;
15
16bind_interrupts!(struct IrqsI2C{
17 I2C2_EV => i2c::EventInterruptHandler<peripherals::I2C2>;
18 I2C2_ER => i2c::ErrorInterruptHandler<peripherals::I2C2>;
19});
20
21#[cortex_m_rt::entry]
22fn main() -> ! {
23 info!("main: Starting!");
24 Executor::take().run(|spawner| {
25 spawner.spawn(unwrap!(async_main(spawner)));
26 });
27}
28
29#[embassy_executor::task]
30async fn async_main(_spawner: Spawner) {
31 let mut config = embassy_stm32::Config::default();
32 // enable HSI clock
33 config.rcc.hsi = true;
34 // enable LSI clock for RTC
35 config.rcc.ls = embassy_stm32::rcc::LsConfig::default_lsi();
36 config.rcc.msi = Some(embassy_stm32::rcc::MSIRange::RANGE4M);
37 config.rcc.sys = embassy_stm32::rcc::Sysclk::MSI;
38 // enable ADC with HSI clock
39 config.rcc.mux.i2c2sel = embassy_stm32::pac::rcc::vals::I2c2sel::HSI;
40 #[cfg(feature = "defmt-serial")]
41 {
42 // disable debug during sleep to reduce power consumption since we are
43 // using defmt-serial on LPUART1.
44 config.enable_debug_during_sleep = false;
45 // if we are using defmt-serial on LPUART1, we need to use HSI for the clock
46 // so that its registers are preserved during STOP modes.
47 config.rcc.mux.lpuart1sel = embassy_stm32::pac::rcc::vals::Lpuart1sel::HSI;
48 }
49 // Initialize STM32WL peripherals (use default config like wio-e5-async example)
50 let p = embassy_stm32::init(config);
51
52 // start with all GPIOs as analog to reduce power consumption
53 for r in [
54 embassy_stm32::pac::GPIOA,
55 embassy_stm32::pac::GPIOB,
56 embassy_stm32::pac::GPIOC,
57 embassy_stm32::pac::GPIOH,
58 ] {
59 r.moder().modify(|w| {
60 for i in 0..16 {
61 // don't reset these if probe-rs should stay connected!
62 #[cfg(feature = "defmt-rtt")]
63 if config.enable_debug_during_sleep && r == embassy_stm32::pac::GPIOA && [13, 14].contains(&i) {
64 continue;
65 }
66 w.set_moder(i, embassy_stm32::pac::gpio::vals::Moder::ANALOG);
67 }
68 });
69 }
70 #[cfg(feature = "defmt-serial")]
71 {
72 use embassy_stm32::mode::Blocking;
73 use embassy_stm32::usart::Uart;
74 let config = embassy_stm32::usart::Config::default();
75 let uart = Uart::new_blocking(p.LPUART1, p.PC0, p.PC1, config).expect("failed to configure UART!");
76 static SERIAL: StaticCell<Uart<'static, Blocking>> = StaticCell::new();
77 defmt_serial::defmt_serial(SERIAL.init(uart));
78 }
79
80 info!("Hello World!");
81 let en3v3 = embassy_stm32::gpio::Output::new(
82 p.PA9,
83 embassy_stm32::gpio::Level::High,
84 embassy_stm32::gpio::Speed::High,
85 );
86 core::mem::forget(en3v3); // keep the output pin enabled
87
88 let mut i2c = I2c::new(p.I2C2, p.PB15, p.PA15, IrqsI2C, p.DMA1_CH6, p.DMA1_CH7, {
89 let mut config = i2c::Config::default();
90 config.frequency = Hertz::khz(100);
91 config.timeout = Duration::from_millis(500);
92 config
93 });
94
95 loop {
96 let mut buffer = [0; 2];
97 // read the temperature register of the onboard lm75
98 match i2c.read(0x48, &mut buffer).await {
99 Ok(_) => info!("--> {:?}", buffer),
100 Err(e) => info!("--> Error: {:?}", e),
101 }
102 Timer::after_secs(5).await;
103 }
104}
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}