From c685d80578b0fea8f66f8f8c858c9d59857586b5 Mon Sep 17 00:00:00 2001 From: crispaudio Date: Fri, 29 Aug 2025 12:32:38 +0200 Subject: mspm0-i2c-target: add i2c target with example --- examples/mspm0g3507/src/bin/i2c_target.rs | 60 +++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 examples/mspm0g3507/src/bin/i2c_target.rs (limited to 'examples') diff --git a/examples/mspm0g3507/src/bin/i2c_target.rs b/examples/mspm0g3507/src/bin/i2c_target.rs new file mode 100644 index 000000000..b1336cdd2 --- /dev/null +++ b/examples/mspm0g3507/src/bin/i2c_target.rs @@ -0,0 +1,60 @@ +//! Example of using blocking I2C +//! +//! This uses the virtual COM port provided on the LP-MSPM0G3507 board. + +#![no_std] +#![no_main] + +use defmt::*; +use embassy_executor::Spawner; +use embassy_mspm0::i2c_target::{Command, I2cTarget, ReadStatus}; +use embassy_mspm0::peripherals::I2C1; +use embassy_mspm0::{bind_interrupts, i2c}; +use {defmt_rtt as _, panic_halt as _}; + +bind_interrupts!(struct Irqs { + I2C1 => i2c::InterruptHandler; +}); + +#[embassy_executor::main] +async fn main(_spawner: Spawner) -> ! { + let p = embassy_mspm0::init(Default::default()); + + let instance = p.I2C1; + let scl = p.PB2; + let sda = p.PB3; + + let mut config = i2c::Config::default(); + config.general_call = true; + let mut i2c = I2cTarget::new(instance, scl, sda, Irqs, config).unwrap(); + + let mut read = [0u8; 8]; + let data = [8u8; 2]; + let data_wr = [9u8; 2]; + + loop { + match i2c.listen(&mut read).await { + Ok(Command::GeneralCall(_)) => info!("General call received"), + Ok(Command::Read) => { + info!("Read command received"); + match i2c.respond_to_read(&data).await.unwrap() { + ReadStatus::Done => info!("Finished reading"), + ReadStatus::NeedMoreBytes => { + info!("Read needs more bytes - will reset"); + i2c.reset().unwrap(); + } + ReadStatus::LeftoverBytes(_) => { + info!("Leftover bytes received"); + i2c.flush_tx_fifo(); + } + } + } + Ok(Command::Write(_)) => info!("Write command received"), + Ok(Command::WriteRead(_)) => { + info!("Write-Read command received"); + i2c.respond_and_fill(&data_wr, 0xFE).await.unwrap(); + } + Err(e) => info!("Got error {}", e), + } + } +} -- cgit From a12299d35d4641a8dfee27c52ec274257815cb3f Mon Sep 17 00:00:00 2001 From: crispaudio Date: Fri, 29 Aug 2025 12:44:40 +0200 Subject: mspm0-i2c-target: fix comment in example --- examples/mspm0g3507/src/bin/i2c_target.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'examples') diff --git a/examples/mspm0g3507/src/bin/i2c_target.rs b/examples/mspm0g3507/src/bin/i2c_target.rs index b1336cdd2..cb1d315fe 100644 --- a/examples/mspm0g3507/src/bin/i2c_target.rs +++ b/examples/mspm0g3507/src/bin/i2c_target.rs @@ -1,4 +1,4 @@ -//! Example of using blocking I2C +//! Example of using async I2C target //! //! This uses the virtual COM port provided on the LP-MSPM0G3507 board. -- cgit From 7797cc0effa069b78be29ff19b81068b17f98ac2 Mon Sep 17 00:00:00 2001 From: Iooon Date: Wed, 1 Oct 2025 11:00:44 +0200 Subject: mspm0-i2c-target: add mspm0l1306 example and set target address explicitly in examples --- examples/mspm0g3507/src/bin/i2c_target.rs | 1 + examples/mspm0l1306/src/bin/i2c_target.rs | 61 +++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+) create mode 100644 examples/mspm0l1306/src/bin/i2c_target.rs (limited to 'examples') diff --git a/examples/mspm0g3507/src/bin/i2c_target.rs b/examples/mspm0g3507/src/bin/i2c_target.rs index cb1d315fe..ac7083a20 100644 --- a/examples/mspm0g3507/src/bin/i2c_target.rs +++ b/examples/mspm0g3507/src/bin/i2c_target.rs @@ -25,6 +25,7 @@ async fn main(_spawner: Spawner) -> ! { let sda = p.PB3; let mut config = i2c::Config::default(); + config.target_addr = 0x48; config.general_call = true; let mut i2c = I2cTarget::new(instance, scl, sda, Irqs, config).unwrap(); diff --git a/examples/mspm0l1306/src/bin/i2c_target.rs b/examples/mspm0l1306/src/bin/i2c_target.rs new file mode 100644 index 000000000..38d309e6b --- /dev/null +++ b/examples/mspm0l1306/src/bin/i2c_target.rs @@ -0,0 +1,61 @@ +//! Example of using async I2C target +//! +//! This uses the virtual COM port provided on the LP-MSPM0L1306 board. + +#![no_std] +#![no_main] + +use defmt::*; +use embassy_executor::Spawner; +use embassy_mspm0::i2c_target::{Command, I2cTarget, ReadStatus}; +use embassy_mspm0::peripherals::I2C0; +use embassy_mspm0::{bind_interrupts, i2c}; +use {defmt_rtt as _, panic_halt as _}; + +bind_interrupts!(struct Irqs { + I2C0 => i2c::InterruptHandler; +}); + +#[embassy_executor::main] +async fn main(_spawner: Spawner) -> ! { + let p = embassy_mspm0::init(Default::default()); + + let instance = p.I2C0; + let scl = p.PA1; + let sda = p.PA0; + + let mut config = i2c::Config::default(); + config.target_addr = 0x48; + config.general_call = true; + let mut i2c = I2cTarget::new(instance, scl, sda, Irqs, config).unwrap(); + + let mut read = [0u8; 8]; + let data = [8u8; 2]; + let data_wr = [9u8; 2]; + + loop { + match i2c.listen(&mut read).await { + Ok(Command::GeneralCall(_)) => info!("General call received"), + Ok(Command::Read) => { + info!("Read command received"); + match i2c.respond_to_read(&data).await.unwrap() { + ReadStatus::Done => info!("Finished reading"), + ReadStatus::NeedMoreBytes => { + info!("Read needs more bytes - will reset"); + i2c.reset().unwrap(); + } + ReadStatus::LeftoverBytes(_) => { + info!("Leftover bytes received"); + i2c.flush_tx_fifo(); + } + } + } + Ok(Command::Write(_)) => info!("Write command received"), + Ok(Command::WriteRead(_)) => { + info!("Write-Read command received"); + i2c.respond_and_fill(&data_wr, 0xFE).await.unwrap(); + } + Err(e) => info!("Got error {}", e), + } + } +} -- cgit From 4217a264dba3a77da38897537f90e1fdfe5b9ddb Mon Sep 17 00:00:00 2001 From: crispaudio Date: Mon, 6 Oct 2025 10:06:28 +0200 Subject: mspm0-i2c-target: update examples with split config --- examples/mspm0g3507/src/bin/i2c_target.rs | 12 +++++++----- examples/mspm0l1306/src/bin/i2c_target.rs | 12 +++++++----- 2 files changed, 14 insertions(+), 10 deletions(-) (limited to 'examples') diff --git a/examples/mspm0g3507/src/bin/i2c_target.rs b/examples/mspm0g3507/src/bin/i2c_target.rs index ac7083a20..5dd718eaf 100644 --- a/examples/mspm0g3507/src/bin/i2c_target.rs +++ b/examples/mspm0g3507/src/bin/i2c_target.rs @@ -7,7 +7,8 @@ use defmt::*; use embassy_executor::Spawner; -use embassy_mspm0::i2c_target::{Command, I2cTarget, ReadStatus}; +use embassy_mspm0::i2c::Config; +use embassy_mspm0::i2c_target::{Command, Config as TargetConfig, I2cTarget, ReadStatus}; use embassy_mspm0::peripherals::I2C1; use embassy_mspm0::{bind_interrupts, i2c}; use {defmt_rtt as _, panic_halt as _}; @@ -24,10 +25,11 @@ async fn main(_spawner: Spawner) -> ! { let scl = p.PB2; let sda = p.PB3; - let mut config = i2c::Config::default(); - config.target_addr = 0x48; - config.general_call = true; - let mut i2c = I2cTarget::new(instance, scl, sda, Irqs, config).unwrap(); + let config = Config::default(); + let mut target_config = TargetConfig::default(); + target_config.target_addr = 0x48; + target_config.general_call = true; + let mut i2c = I2cTarget::new(instance, scl, sda, Irqs, config, target_config).unwrap(); let mut read = [0u8; 8]; let data = [8u8; 2]; diff --git a/examples/mspm0l1306/src/bin/i2c_target.rs b/examples/mspm0l1306/src/bin/i2c_target.rs index 38d309e6b..4d147d08b 100644 --- a/examples/mspm0l1306/src/bin/i2c_target.rs +++ b/examples/mspm0l1306/src/bin/i2c_target.rs @@ -7,7 +7,8 @@ use defmt::*; use embassy_executor::Spawner; -use embassy_mspm0::i2c_target::{Command, I2cTarget, ReadStatus}; +use embassy_mspm0::i2c::Config; +use embassy_mspm0::i2c_target::{Command, Config as TargetConfig, I2cTarget, ReadStatus}; use embassy_mspm0::peripherals::I2C0; use embassy_mspm0::{bind_interrupts, i2c}; use {defmt_rtt as _, panic_halt as _}; @@ -24,10 +25,11 @@ async fn main(_spawner: Spawner) -> ! { let scl = p.PA1; let sda = p.PA0; - let mut config = i2c::Config::default(); - config.target_addr = 0x48; - config.general_call = true; - let mut i2c = I2cTarget::new(instance, scl, sda, Irqs, config).unwrap(); + let config = Config::default(); + let mut target_config = TargetConfig::default(); + target_config.target_addr = 0x48; + target_config.general_call = true; + let mut i2c = I2cTarget::new(instance, scl, sda, Irqs, config, target_config).unwrap(); let mut read = [0u8; 8]; let data = [8u8; 2]; -- cgit From 6fef28da94d133ce0cd36b5fb6ef2ef302c8eea0 Mon Sep 17 00:00:00 2001 From: Haobo Gu Date: Tue, 14 Oct 2025 23:39:52 +0800 Subject: feat(nrf): add rtc support for nRF54L Signed-off-by: Haobo Gu --- examples/nrf54l15/Cargo.toml | 2 ++ examples/nrf54l15/src/bin/rtc.rs | 56 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+) create mode 100644 examples/nrf54l15/src/bin/rtc.rs (limited to 'examples') diff --git a/examples/nrf54l15/Cargo.toml b/examples/nrf54l15/Cargo.toml index a053dd0ec..541e79fcb 100644 --- a/examples/nrf54l15/Cargo.toml +++ b/examples/nrf54l15/Cargo.toml @@ -8,6 +8,7 @@ publish = false [dependencies] embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } +embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } embassy-nrf = { version = "0.8.0", path = "../../embassy-nrf", features = ["defmt", "nrf54l15-app-s", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } defmt = "1.0.1" @@ -18,6 +19,7 @@ cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-sing cortex-m-rt = "0.7.0" embedded-storage = "0.3.1" +portable-atomic = "1" [profile.release] debug = 2 diff --git a/examples/nrf54l15/src/bin/rtc.rs b/examples/nrf54l15/src/bin/rtc.rs new file mode 100644 index 000000000..a45aaca52 --- /dev/null +++ b/examples/nrf54l15/src/bin/rtc.rs @@ -0,0 +1,56 @@ +#![no_std] +#![no_main] + +use core::cell::RefCell; + +use embassy_executor::Spawner; +use embassy_nrf::gpio::{Level, Output, OutputDrive}; +use embassy_nrf::interrupt; +use embassy_nrf::rtc::Rtc; +use embassy_sync::blocking_mutex::Mutex; +use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; +use portable_atomic::AtomicU64; +use {defmt_rtt as _, panic_probe as _}; + +// 64 bit counter which will never overflow. +static TICK_COUNTER: AtomicU64 = AtomicU64::new(0); +static RTC: Mutex>>> = Mutex::new(RefCell::new(None)); + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + defmt::println!("nRF54L15 RTC example"); + let p = embassy_nrf::init(Default::default()); + let mut led = Output::new(p.P2_09, Level::High, OutputDrive::Standard); + // Counter resolution is 125 ms. + let mut rtc = Rtc::new(p.RTC10, (1 << 12) - 1).unwrap(); + rtc.enable_interrupt(embassy_nrf::rtc::Interrupt::Tick, true); + rtc.enable_event(embassy_nrf::rtc::Interrupt::Tick); + rtc.enable(); + RTC.lock(|r| { + let mut rtc_borrow = r.borrow_mut(); + *rtc_borrow = Some(rtc); + }); + + let mut last_counter_val = 0; + loop { + let current = TICK_COUNTER.load(core::sync::atomic::Ordering::Relaxed); + if current != last_counter_val { + led.toggle(); + last_counter_val = current; + } + } +} + +#[interrupt] +fn RTC10() { + // For 64-bit, we do not need to worry about overflowing, at least not for realistic program + // lifetimes. + TICK_COUNTER.fetch_add(1, core::sync::atomic::Ordering::Relaxed); + RTC.lock(|r| { + let mut rtc_borrow = r.borrow_mut(); + rtc_borrow + .as_mut() + .unwrap() + .reset_event(embassy_nrf::rtc::Interrupt::Tick); + }); +} -- cgit From 369959e654d095d0e3d95597693bd64fcdb50ec5 Mon Sep 17 00:00:00 2001 From: Maarten de Vries Date: Wed, 15 Oct 2025 14:53:40 +0200 Subject: embassy_nrf: update examples --- examples/nrf52840/src/bin/i2s_monitor.rs | 9 ++++----- examples/nrf52840/src/bin/pwm.rs | 14 ++++++++------ examples/nrf52840/src/bin/pwm_servo.rs | 14 +++++++------- 3 files changed, 19 insertions(+), 18 deletions(-) (limited to 'examples') 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 @@ use defmt::{debug, error, info}; use embassy_executor::Spawner; use embassy_nrf::i2s::{self, Channels, Config, DoubleBuffering, I2S, MasterClock, Sample as _, SampleWidth}; -use embassy_nrf::pwm::{Prescaler, SimplePwm}; +use embassy_nrf::pwm::{DutyCycle, Prescaler, SimplePwm}; use embassy_nrf::{bind_interrupts, peripherals}; use {defmt_rtt as _, panic_probe as _}; @@ -34,7 +34,7 @@ async fn main(_spawner: Spawner) { I2S::new_master(p.I2S, Irqs, p.P0_25, p.P0_26, p.P0_27, master_clock, config).input(p.P0_29, buffers); // Configure the PWM to use the pins corresponding to the RGB leds - let mut pwm = SimplePwm::new_3ch(p.PWM0, p.P0_23, p.P0_22, p.P0_24); + let mut pwm = SimplePwm::new_3ch(p.PWM0, p.P0_23, p.P0_22, p.P0_24, &Default::default()); pwm.set_prescaler(Prescaler::Div1); pwm.set_max_duty(255); @@ -47,9 +47,8 @@ async fn main(_spawner: Spawner) { let rgb = rgb_from_rms(rms); debug!("RMS: {}, RGB: {:?}", rms, rgb); - for i in 0..3 { - pwm.set_duty(i, rgb[i].into()); - } + let duties = rgb.map(|byte| DutyCycle::normal(u16::from(byte))); + pwm.set_all_duties([duties[0], duties[1], duties[2], DutyCycle::normal(0)]); if let Err(err) = input_stream.receive().await { error!("{}", err); 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 @@ use defmt::*; use embassy_executor::Spawner; -use embassy_nrf::pwm::{Prescaler, SimplePwm}; +use embassy_nrf::pwm::{DutyCycle, Prescaler, SimplePwm}; use embassy_time::Timer; use {defmt_rtt as _, panic_probe as _}; @@ -71,7 +71,7 @@ static DUTY: [u16; 1024] = [ #[embassy_executor::main] async fn main(_spawner: Spawner) { let p = embassy_nrf::init(Default::default()); - let mut pwm = SimplePwm::new_4ch(p.PWM0, p.P0_13, p.P0_14, p.P0_16, p.P0_15); + let mut pwm = SimplePwm::new_4ch(p.PWM0, p.P0_13, p.P0_14, p.P0_16, p.P0_15, &Default::default()); pwm.set_prescaler(Prescaler::Div1); pwm.set_max_duty(32767); info!("pwm initialized!"); @@ -79,10 +79,12 @@ async fn main(_spawner: Spawner) { let mut i = 0; loop { i += 1; - pwm.set_duty(0, DUTY[i % 1024]); - pwm.set_duty(1, DUTY[(i + 256) % 1024]); - pwm.set_duty(2, DUTY[(i + 512) % 1024]); - pwm.set_duty(3, DUTY[(i + 768) % 1024]); + pwm.set_all_duties([ + DutyCycle::normal(DUTY[i % 1024]), + DutyCycle::normal(DUTY[(i + 256) % 1024]), + DutyCycle::normal(DUTY[(i + 512) % 1024]), + DutyCycle::normal(DUTY[(i + 768) % 1024]), + ]); Timer::after_millis(3).await; } } 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 @@ use defmt::*; use embassy_executor::Spawner; -use embassy_nrf::pwm::{Prescaler, SimplePwm}; +use embassy_nrf::pwm::{DutyCycle, Prescaler, SimplePwm}; use embassy_time::Timer; use {defmt_rtt as _, panic_probe as _}; #[embassy_executor::main] async fn main(_spawner: Spawner) { let p = embassy_nrf::init(Default::default()); - let mut pwm = SimplePwm::new_1ch(p.PWM0, p.P0_05); + let mut pwm = SimplePwm::new_1ch(p.PWM0, p.P0_05, &Default::default()); // sg90 microervo requires 50hz or 20ms period // set_period can only set down to 125khz so we cant use it directly // 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) { loop { info!("45 deg"); // poor mans inverting, subtract our value from max_duty - pwm.set_duty(0, 2500 - 156); + pwm.set_duty(0, DutyCycle::normal(2500 - 156)); Timer::after_millis(5000).await; info!("90 deg"); - pwm.set_duty(0, 2500 - 187); + pwm.set_duty(0, DutyCycle::normal(2500 - 187)); Timer::after_millis(5000).await; info!("135 deg"); - pwm.set_duty(0, 2500 - 218); + pwm.set_duty(0, DutyCycle::normal(2500 - 218)); Timer::after_millis(5000).await; info!("180 deg"); - pwm.set_duty(0, 2500 - 250); + pwm.set_duty(0, DutyCycle::normal(2500 - 250)); Timer::after_millis(5000).await; info!("0 deg"); - pwm.set_duty(0, 2500 - 125); + pwm.set_duty(0, DutyCycle::normal(2500 - 125)); Timer::after_millis(5000).await; } } -- cgit From 5ed604fc0453066f0d0cf0c161823df5f4b7900f Mon Sep 17 00:00:00 2001 From: Roi Bachynskyi Date: Thu, 25 Sep 2025 15:19:45 +0300 Subject: nxp/lpc55: pwm simple --- examples/lpc55s69/src/bin/pwm.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 examples/lpc55s69/src/bin/pwm.rs (limited to 'examples') 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 @@ +#![no_std] +#![no_main] + +use defmt::*; +use embassy_executor::Spawner; +use embassy_nxp::pwm::{Config, Pwm}; +use embassy_time::Timer; +use {defmt_rtt as _, panic_halt as _}; + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let p = embassy_nxp::init(Default::default()); + let pwm = Pwm::new_output(p.PWM_OUTPUT1, p.PIO0_18, Config::new(1_000_000_000, 2_000_000_000)); + loop { + info!("Counter: {}", pwm.counter()); + Timer::after_millis(50).await; + } +} -- cgit From de5760cc81a00966c61d668c41f6e3e4709f0283 Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Tue, 14 Oct 2025 13:23:50 +0200 Subject: feat: improve nrf54 support using new nrf-pac * Update nrf-pac to version that modifies nrf52 register layout to match nrf54 to reduce the amount of cfg needed for nrf54 support. * Make the following peripherals available on nrf54: twim, twis, spim, spis, uart, buffered uarte, dppi, gpiote, pwm, saadc * Add examples tested on the nrf54 dk Some code is based on or copied from other pull requests, modified to match the new nrf-pac layout. Co-authored-by: Dmitry Tarnyagin --- examples/nrf52840/src/bin/egu.rs | 15 +++-- examples/nrf52840/src/bin/gpiote_channel.rs | 26 ++------ examples/nrf52840/src/bin/ppi.rs | 34 ++++------- examples/nrf52840/src/bin/pwm_sequence_ppi.rs | 14 +---- examples/nrf5340/src/bin/gpiote_channel.rs | 26 ++------ examples/nrf54l15/Cargo.toml | 5 ++ examples/nrf54l15/src/bin/buffered_uart.rs | 49 +++++++++++++++ examples/nrf54l15/src/bin/gpiote_channel.rs | 49 +++++++++++++++ examples/nrf54l15/src/bin/gpiote_port.rs | 33 ++++++++++ examples/nrf54l15/src/bin/pwm.rs | 86 +++++++++++++++++++++++++++ examples/nrf54l15/src/bin/saadc.rs | 28 +++++++++ examples/nrf54l15/src/bin/spim.rs | 72 ++++++++++++++++++++++ examples/nrf54l15/src/bin/twim.rs | 37 ++++++++++++ examples/nrf54l15/src/bin/twis.rs | 47 +++++++++++++++ examples/nrf54l15/src/bin/uart.rs | 37 ++++++++++++ 15 files changed, 476 insertions(+), 82 deletions(-) create mode 100644 examples/nrf54l15/src/bin/buffered_uart.rs create mode 100644 examples/nrf54l15/src/bin/gpiote_channel.rs create mode 100644 examples/nrf54l15/src/bin/gpiote_port.rs create mode 100644 examples/nrf54l15/src/bin/pwm.rs create mode 100644 examples/nrf54l15/src/bin/saadc.rs create mode 100644 examples/nrf54l15/src/bin/spim.rs create mode 100644 examples/nrf54l15/src/bin/twim.rs create mode 100644 examples/nrf54l15/src/bin/twis.rs create mode 100644 examples/nrf54l15/src/bin/uart.rs (limited to 'examples') 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 @@ use embassy_executor::Spawner; use embassy_nrf::egu::{Egu, TriggerNumber}; -use embassy_nrf::gpio::{Input, Level, Output, OutputDrive, Pull}; +use embassy_nrf::gpio::{Level, OutputDrive, Pull}; use embassy_nrf::gpiote::{InputChannel, InputChannelPolarity, OutputChannel, OutputChannelPolarity}; use embassy_nrf::peripherals::{PPI_CH0, PPI_CH1, PPI_CH2}; use embassy_nrf::ppi::Ppi; @@ -17,12 +17,15 @@ use {defmt_rtt as _, panic_probe as _}; async fn main(_spawner: Spawner) { let p = embassy_nrf::init(Default::default()); - let led1 = Output::new(p.P0_13, Level::High, OutputDrive::Standard); - let btn1 = Input::new(p.P0_11, Pull::Up); - let mut egu1 = Egu::new(p.EGU0); - let led1 = OutputChannel::new(p.GPIOTE_CH0, led1, OutputChannelPolarity::Toggle); - let btn1 = InputChannel::new(p.GPIOTE_CH1, btn1, InputChannelPolarity::LoToHi); + let led1 = OutputChannel::new( + p.GPIOTE_CH0, + p.P0_13, + Level::High, + OutputDrive::Standard, + OutputChannelPolarity::Toggle, + ); + let btn1 = InputChannel::new(p.GPIOTE_CH1, p.P0_11, Pull::Up, InputChannelPolarity::LoToHi); let trigger0 = egu1.trigger(TriggerNumber::Trigger0); 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 @@ use defmt::info; use embassy_executor::Spawner; -use embassy_nrf::gpio::{Input, Pull}; +use embassy_nrf::gpio::Pull; use embassy_nrf::gpiote::{InputChannel, InputChannelPolarity}; use {defmt_rtt as _, panic_probe as _}; @@ -12,26 +12,10 @@ async fn main(_spawner: Spawner) { let p = embassy_nrf::init(Default::default()); info!("Starting!"); - let ch1 = InputChannel::new( - p.GPIOTE_CH0, - Input::new(p.P0_11, Pull::Up), - InputChannelPolarity::HiToLo, - ); - let ch2 = InputChannel::new( - p.GPIOTE_CH1, - Input::new(p.P0_12, Pull::Up), - InputChannelPolarity::LoToHi, - ); - let ch3 = InputChannel::new( - p.GPIOTE_CH2, - Input::new(p.P0_24, Pull::Up), - InputChannelPolarity::Toggle, - ); - let ch4 = InputChannel::new( - p.GPIOTE_CH3, - Input::new(p.P0_25, Pull::Up), - InputChannelPolarity::Toggle, - ); + let ch1 = InputChannel::new(p.GPIOTE_CH0, p.P0_11, Pull::Up, InputChannelPolarity::HiToLo); + let ch2 = InputChannel::new(p.GPIOTE_CH1, p.P0_12, Pull::Up, InputChannelPolarity::LoToHi); + let ch3 = InputChannel::new(p.GPIOTE_CH2, p.P0_24, Pull::Up, InputChannelPolarity::Toggle); + let ch4 = InputChannel::new(p.GPIOTE_CH3, p.P0_25, Pull::Up, InputChannelPolarity::Toggle); let button1 = async { loop { 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; use defmt::info; use embassy_executor::Spawner; -use embassy_nrf::gpio::{Input, Level, Output, OutputDrive, Pull}; +use embassy_nrf::gpio::{Level, OutputDrive, Pull}; use embassy_nrf::gpiote::{self, InputChannel, InputChannelPolarity}; use embassy_nrf::ppi::Ppi; use gpiote::{OutputChannel, OutputChannelPolarity}; @@ -16,36 +16,24 @@ async fn main(_spawner: Spawner) { let p = embassy_nrf::init(Default::default()); info!("Starting!"); - let button1 = InputChannel::new( - p.GPIOTE_CH0, - Input::new(p.P0_11, Pull::Up), - InputChannelPolarity::HiToLo, - ); - let button2 = InputChannel::new( - p.GPIOTE_CH1, - Input::new(p.P0_12, Pull::Up), - InputChannelPolarity::HiToLo, - ); - let button3 = InputChannel::new( - p.GPIOTE_CH2, - Input::new(p.P0_24, Pull::Up), - InputChannelPolarity::HiToLo, - ); - let button4 = InputChannel::new( - p.GPIOTE_CH3, - Input::new(p.P0_25, Pull::Up), - InputChannelPolarity::HiToLo, - ); + let button1 = InputChannel::new(p.GPIOTE_CH0, p.P0_11, Pull::Up, InputChannelPolarity::HiToLo); + let button2 = InputChannel::new(p.GPIOTE_CH1, p.P0_12, Pull::Up, InputChannelPolarity::HiToLo); + let button3 = InputChannel::new(p.GPIOTE_CH2, p.P0_24, Pull::Up, InputChannelPolarity::HiToLo); + let button4 = InputChannel::new(p.GPIOTE_CH3, p.P0_25, Pull::Up, InputChannelPolarity::HiToLo); let led1 = OutputChannel::new( p.GPIOTE_CH4, - Output::new(p.P0_13, Level::Low, OutputDrive::Standard), + p.P0_13, + Level::Low, + OutputDrive::Standard, OutputChannelPolarity::Toggle, ); let led2 = OutputChannel::new( p.GPIOTE_CH5, - Output::new(p.P0_14, Level::Low, OutputDrive::Standard), + p.P0_14, + Level::Low, + OutputDrive::Standard, OutputChannelPolarity::Toggle, ); 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; use defmt::*; use embassy_executor::Spawner; -use embassy_nrf::gpio::{Input, Pull}; +use embassy_nrf::gpio::Pull; use embassy_nrf::gpiote::{InputChannel, InputChannelPolarity}; use embassy_nrf::ppi::Ppi; use embassy_nrf::pwm::{Config, Prescaler, SequenceConfig, SequencePwm, SingleSequenceMode, SingleSequencer}; @@ -30,17 +30,9 @@ async fn main(_spawner: Spawner) { // pwm.stop() deconfigures pins, and then the task_start_seq0 task cant work // so its going to have to start running in order load the configuration - let button1 = InputChannel::new( - p.GPIOTE_CH0, - Input::new(p.P0_11, Pull::Up), - InputChannelPolarity::HiToLo, - ); + let button1 = InputChannel::new(p.GPIOTE_CH0, p.P0_11, Pull::Up, InputChannelPolarity::HiToLo); - let button2 = InputChannel::new( - p.GPIOTE_CH1, - Input::new(p.P0_12, Pull::Up), - InputChannelPolarity::HiToLo, - ); + let button2 = InputChannel::new(p.GPIOTE_CH1, p.P0_12, Pull::Up, InputChannelPolarity::HiToLo); // messing with the pwm tasks is ill advised // Times::Ininite and Times even are seq0, Times odd is seq1 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 @@ use defmt::info; use embassy_executor::Spawner; -use embassy_nrf::gpio::{Input, Pull}; +use embassy_nrf::gpio::Pull; use embassy_nrf::gpiote::{InputChannel, InputChannelPolarity}; use {defmt_rtt as _, panic_probe as _}; @@ -12,26 +12,10 @@ async fn main(_spawner: Spawner) { let p = embassy_nrf::init(Default::default()); info!("Starting!"); - let ch1 = InputChannel::new( - p.GPIOTE_CH0, - Input::new(p.P0_23, Pull::Up), - InputChannelPolarity::HiToLo, - ); - let ch2 = InputChannel::new( - p.GPIOTE_CH1, - Input::new(p.P0_24, Pull::Up), - InputChannelPolarity::LoToHi, - ); - let ch3 = InputChannel::new( - p.GPIOTE_CH2, - Input::new(p.P0_08, Pull::Up), - InputChannelPolarity::Toggle, - ); - let ch4 = InputChannel::new( - p.GPIOTE_CH3, - Input::new(p.P0_09, Pull::Up), - InputChannelPolarity::Toggle, - ); + let ch1 = InputChannel::new(p.GPIOTE_CH0, p.P0_23, Pull::Up, InputChannelPolarity::HiToLo); + let ch2 = InputChannel::new(p.GPIOTE_CH1, p.P0_24, Pull::Up, InputChannelPolarity::LoToHi); + let ch3 = InputChannel::new(p.GPIOTE_CH2, p.P0_08, Pull::Up, InputChannelPolarity::Toggle); + let ch4 = InputChannel::new(p.GPIOTE_CH3, p.P0_09, Pull::Up, InputChannelPolarity::Toggle); let button1 = async { loop { diff --git a/examples/nrf54l15/Cargo.toml b/examples/nrf54l15/Cargo.toml index 541e79fcb..14a80efe7 100644 --- a/examples/nrf54l15/Cargo.toml +++ b/examples/nrf54l15/Cargo.toml @@ -6,10 +6,13 @@ license = "MIT OR Apache-2.0" publish = false [dependencies] +embassy-futures = { version = "0.1.2", path = "../../embassy-futures" } embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } embassy-nrf = { version = "0.8.0", path = "../../embassy-nrf", features = ["defmt", "nrf54l15-app-s", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } +embedded-io = { version = "0.6.0", features = ["defmt-03"] } +embedded-io-async = { version = "0.6.1", features = ["defmt-03"] } defmt = "1.0.1" defmt-rtt = "1.0.0" @@ -21,6 +24,8 @@ cortex-m-rt = "0.7.0" embedded-storage = "0.3.1" portable-atomic = "1" +static_cell = "2" + [profile.release] debug = 2 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 @@ +#![no_std] +#![no_main] + +use defmt::*; +use embassy_executor::Spawner; +use embassy_nrf::buffered_uarte::{self, BufferedUarte}; +use embassy_nrf::{bind_interrupts, peripherals, uarte}; +use embedded_io_async::Write; +use {defmt_rtt as _, panic_probe as _}; + +bind_interrupts!(struct Irqs { + SERIAL20 => buffered_uarte::InterruptHandler; +}); + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let p = embassy_nrf::init(Default::default()); + let mut config = uarte::Config::default(); + config.parity = uarte::Parity::EXCLUDED; + config.baudrate = uarte::Baudrate::BAUD115200; + + let mut tx_buffer = [0u8; 4096]; + let mut rx_buffer = [0u8; 4096]; + + let mut u = BufferedUarte::new( + p.SERIAL20, + p.P1_12, + p.P1_13, + Irqs, + config, + &mut rx_buffer, + &mut tx_buffer, + ); + + info!("uarte initialized!"); + + unwrap!(u.write_all(b"Hello!\r\n").await); + info!("wrote hello in uart!"); + + loop { + info!("reading..."); + let buf = unwrap!(u.fill_buf().await); + info!("read done, got {}", buf); + + // Read bytes have to be explicitly consumed, otherwise fill_buf() will return them again + let n = buf.len(); + u.consume(n); + } +} diff --git a/examples/nrf54l15/src/bin/gpiote_channel.rs b/examples/nrf54l15/src/bin/gpiote_channel.rs new file mode 100644 index 000000000..3fa0972a7 --- /dev/null +++ b/examples/nrf54l15/src/bin/gpiote_channel.rs @@ -0,0 +1,49 @@ +#![no_std] +#![no_main] + +use defmt::info; +use embassy_executor::Spawner; +use embassy_nrf::gpio::Pull; +use embassy_nrf::gpiote::{InputChannel, InputChannelPolarity}; +use {defmt_rtt as _, panic_probe as _}; + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let p = embassy_nrf::init(Default::default()); + info!("Starting!"); + + let ch1 = InputChannel::new(p.GPIOTE_CH0, p.P1_13, Pull::Up, InputChannelPolarity::HiToLo); + let ch2 = InputChannel::new(p.GPIOTE_CH1, p.P1_09, Pull::Up, InputChannelPolarity::LoToHi); + let ch3 = InputChannel::new(p.GPIOTE_CH2, p.P1_08, Pull::Up, InputChannelPolarity::Toggle); + let ch4 = InputChannel::new(p.GPIOTE_CH8, p.P0_04, Pull::Up, InputChannelPolarity::Toggle); + + let button1 = async { + loop { + ch1.wait().await; + info!("Button 1 pressed") + } + }; + + let button2 = async { + loop { + ch2.wait().await; + info!("Button 2 released") + } + }; + + let button3 = async { + loop { + ch3.wait().await; + info!("Button 3 toggled") + } + }; + + let button4 = async { + loop { + ch4.wait().await; + info!("Button 4 toggled") + } + }; + + embassy_futures::join::join4(button1, button2, button3, button4).await; +} 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 @@ +#![no_std] +#![no_main] + +use defmt::{info, unwrap}; +use embassy_executor::Spawner; +use embassy_nrf::gpio::{Input, Pull}; +use {defmt_rtt as _, panic_probe as _}; + +#[embassy_executor::task(pool_size = 4)] +async fn button_task(n: usize, mut pin: Input<'static>) { + loop { + pin.wait_for_low().await; + info!("Button {:?} pressed!", n); + pin.wait_for_high().await; + info!("Button {:?} released!", n); + } +} + +#[embassy_executor::main] +async fn main(spawner: Spawner) { + let p = embassy_nrf::init(Default::default()); + info!("Starting!"); + + let btn1 = Input::new(p.P1_13, Pull::Up); + let btn2 = Input::new(p.P1_09, Pull::Up); + let btn3 = Input::new(p.P1_08, Pull::Up); + let btn4 = Input::new(p.P0_04, Pull::Up); + + spawner.spawn(unwrap!(button_task(1, btn1))); + spawner.spawn(unwrap!(button_task(2, btn2))); + spawner.spawn(unwrap!(button_task(3, btn3))); + spawner.spawn(unwrap!(button_task(4, btn4))); +} 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 @@ +#![no_std] +#![no_main] + +use defmt::*; +use embassy_executor::Spawner; +use embassy_nrf::pwm::{DutyCycle, Prescaler, SimplePwm}; +use embassy_time::Timer; +use {defmt_rtt as _, panic_probe as _}; + +// for i in range(1024): print(int((math.sin(i/512*math.pi)*0.4+0.5)**2*32767), ', ', end='') +static DUTY: [u16; 1024] = [ + 8191, 8272, 8353, 8434, 8516, 8598, 8681, 8764, 8847, 8931, 9015, 9099, 9184, 9269, 9354, 9440, 9526, 9613, 9700, + 9787, 9874, 9962, 10050, 10139, 10227, 10316, 10406, 10495, 10585, 10675, 10766, 10857, 10948, 11039, 11131, 11223, + 11315, 11407, 11500, 11592, 11685, 11779, 11872, 11966, 12060, 12154, 12248, 12343, 12438, 12533, 12628, 12723, + 12818, 12914, 13010, 13106, 13202, 13298, 13394, 13491, 13587, 13684, 13781, 13878, 13975, 14072, 14169, 14266, + 14364, 14461, 14558, 14656, 14754, 14851, 14949, 15046, 15144, 15242, 15339, 15437, 15535, 15632, 15730, 15828, + 15925, 16023, 16120, 16218, 16315, 16412, 16510, 16607, 16704, 16801, 16898, 16995, 17091, 17188, 17284, 17380, + 17477, 17572, 17668, 17764, 17859, 17955, 18050, 18145, 18239, 18334, 18428, 18522, 18616, 18710, 18803, 18896, + 18989, 19082, 19174, 19266, 19358, 19449, 19540, 19631, 19722, 19812, 19902, 19991, 20081, 20169, 20258, 20346, + 20434, 20521, 20608, 20695, 20781, 20867, 20952, 21037, 21122, 21206, 21290, 21373, 21456, 21538, 21620, 21701, + 21782, 21863, 21943, 22022, 22101, 22179, 22257, 22335, 22412, 22488, 22564, 22639, 22714, 22788, 22861, 22934, + 23007, 23079, 23150, 23220, 23290, 23360, 23429, 23497, 23564, 23631, 23698, 23763, 23828, 23892, 23956, 24019, + 24081, 24143, 24204, 24264, 24324, 24383, 24441, 24499, 24555, 24611, 24667, 24721, 24775, 24828, 24881, 24933, + 24983, 25034, 25083, 25132, 25180, 25227, 25273, 25319, 25363, 25407, 25451, 25493, 25535, 25575, 25615, 25655, + 25693, 25731, 25767, 25803, 25838, 25873, 25906, 25939, 25971, 26002, 26032, 26061, 26089, 26117, 26144, 26170, + 26195, 26219, 26242, 26264, 26286, 26307, 26327, 26346, 26364, 26381, 26397, 26413, 26427, 26441, 26454, 26466, + 26477, 26487, 26496, 26505, 26512, 26519, 26525, 26530, 26534, 26537, 26539, 26540, 26541, 26540, 26539, 26537, + 26534, 26530, 26525, 26519, 26512, 26505, 26496, 26487, 26477, 26466, 26454, 26441, 26427, 26413, 26397, 26381, + 26364, 26346, 26327, 26307, 26286, 26264, 26242, 26219, 26195, 26170, 26144, 26117, 26089, 26061, 26032, 26002, + 25971, 25939, 25906, 25873, 25838, 25803, 25767, 25731, 25693, 25655, 25615, 25575, 25535, 25493, 25451, 25407, + 25363, 25319, 25273, 25227, 25180, 25132, 25083, 25034, 24983, 24933, 24881, 24828, 24775, 24721, 24667, 24611, + 24555, 24499, 24441, 24383, 24324, 24264, 24204, 24143, 24081, 24019, 23956, 23892, 23828, 23763, 23698, 23631, + 23564, 23497, 23429, 23360, 23290, 23220, 23150, 23079, 23007, 22934, 22861, 22788, 22714, 22639, 22564, 22488, + 22412, 22335, 22257, 22179, 22101, 22022, 21943, 21863, 21782, 21701, 21620, 21538, 21456, 21373, 21290, 21206, + 21122, 21037, 20952, 20867, 20781, 20695, 20608, 20521, 20434, 20346, 20258, 20169, 20081, 19991, 19902, 19812, + 19722, 19631, 19540, 19449, 19358, 19266, 19174, 19082, 18989, 18896, 18803, 18710, 18616, 18522, 18428, 18334, + 18239, 18145, 18050, 17955, 17859, 17764, 17668, 17572, 17477, 17380, 17284, 17188, 17091, 16995, 16898, 16801, + 16704, 16607, 16510, 16412, 16315, 16218, 16120, 16023, 15925, 15828, 15730, 15632, 15535, 15437, 15339, 15242, + 15144, 15046, 14949, 14851, 14754, 14656, 14558, 14461, 14364, 14266, 14169, 14072, 13975, 13878, 13781, 13684, + 13587, 13491, 13394, 13298, 13202, 13106, 13010, 12914, 12818, 12723, 12628, 12533, 12438, 12343, 12248, 12154, + 12060, 11966, 11872, 11779, 11685, 11592, 11500, 11407, 11315, 11223, 11131, 11039, 10948, 10857, 10766, 10675, + 10585, 10495, 10406, 10316, 10227, 10139, 10050, 9962, 9874, 9787, 9700, 9613, 9526, 9440, 9354, 9269, 9184, 9099, + 9015, 8931, 8847, 8764, 8681, 8598, 8516, 8434, 8353, 8272, 8191, 8111, 8031, 7952, 7873, 7794, 7716, 7638, 7561, + 7484, 7407, 7331, 7255, 7180, 7105, 7031, 6957, 6883, 6810, 6738, 6665, 6594, 6522, 6451, 6381, 6311, 6241, 6172, + 6104, 6036, 5968, 5901, 5834, 5767, 5702, 5636, 5571, 5507, 5443, 5379, 5316, 5253, 5191, 5130, 5068, 5008, 4947, + 4888, 4828, 4769, 4711, 4653, 4596, 4539, 4482, 4426, 4371, 4316, 4261, 4207, 4153, 4100, 4047, 3995, 3943, 3892, + 3841, 3791, 3741, 3691, 3642, 3594, 3546, 3498, 3451, 3404, 3358, 3312, 3267, 3222, 3178, 3134, 3090, 3047, 3005, + 2962, 2921, 2879, 2839, 2798, 2758, 2719, 2680, 2641, 2603, 2565, 2528, 2491, 2454, 2418, 2382, 2347, 2312, 2278, + 2244, 2210, 2177, 2144, 2112, 2080, 2048, 2017, 1986, 1956, 1926, 1896, 1867, 1838, 1810, 1781, 1754, 1726, 1699, + 1673, 1646, 1620, 1595, 1570, 1545, 1520, 1496, 1472, 1449, 1426, 1403, 1380, 1358, 1336, 1315, 1294, 1273, 1252, + 1232, 1212, 1192, 1173, 1154, 1135, 1117, 1099, 1081, 1063, 1046, 1029, 1012, 996, 980, 964, 948, 933, 918, 903, + 888, 874, 860, 846, 833, 819, 806, 793, 781, 768, 756, 744, 733, 721, 710, 699, 688, 677, 667, 657, 647, 637, 627, + 618, 609, 599, 591, 582, 574, 565, 557, 549, 541, 534, 526, 519, 512, 505, 498, 492, 485, 479, 473, 467, 461, 455, + 450, 444, 439, 434, 429, 424, 419, 415, 410, 406, 402, 398, 394, 390, 386, 383, 379, 376, 373, 370, 367, 364, 361, + 359, 356, 354, 351, 349, 347, 345, 343, 342, 340, 338, 337, 336, 334, 333, 332, 331, 330, 330, 329, 328, 328, 328, + 327, 327, 327, 327, 327, 328, 328, 328, 329, 330, 330, 331, 332, 333, 334, 336, 337, 338, 340, 342, 343, 345, 347, + 349, 351, 354, 356, 359, 361, 364, 367, 370, 373, 376, 379, 383, 386, 390, 394, 398, 402, 406, 410, 415, 419, 424, + 429, 434, 439, 444, 450, 455, 461, 467, 473, 479, 485, 492, 498, 505, 512, 519, 526, 534, 541, 549, 557, 565, 574, + 582, 591, 599, 609, 618, 627, 637, 647, 657, 667, 677, 688, 699, 710, 721, 733, 744, 756, 768, 781, 793, 806, 819, + 833, 846, 860, 874, 888, 903, 918, 933, 948, 964, 980, 996, 1012, 1029, 1046, 1063, 1081, 1099, 1117, 1135, 1154, + 1173, 1192, 1212, 1232, 1252, 1273, 1294, 1315, 1336, 1358, 1380, 1403, 1426, 1449, 1472, 1496, 1520, 1545, 1570, + 1595, 1620, 1646, 1673, 1699, 1726, 1754, 1781, 1810, 1838, 1867, 1896, 1926, 1956, 1986, 2017, 2048, 2080, 2112, + 2144, 2177, 2210, 2244, 2278, 2312, 2347, 2382, 2418, 2454, 2491, 2528, 2565, 2603, 2641, 2680, 2719, 2758, 2798, + 2839, 2879, 2921, 2962, 3005, 3047, 3090, 3134, 3178, 3222, 3267, 3312, 3358, 3404, 3451, 3498, 3546, 3594, 3642, + 3691, 3741, 3791, 3841, 3892, 3943, 3995, 4047, 4100, 4153, 4207, 4261, 4316, 4371, 4426, 4482, 4539, 4596, 4653, + 4711, 4769, 4828, 4888, 4947, 5008, 5068, 5130, 5191, 5253, 5316, 5379, 5443, 5507, 5571, 5636, 5702, 5767, 5834, + 5901, 5968, 6036, 6104, 6172, 6241, 6311, 6381, 6451, 6522, 6594, 6665, 6738, 6810, 6883, 6957, 7031, 7105, 7180, + 7255, 7331, 7407, 7484, 7561, 7638, 7716, 7794, 7873, 7952, 8031, 8111, +]; + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let p = embassy_nrf::init(Default::default()); + let mut pwm = SimplePwm::new_2ch(p.PWM20, p.P1_10, p.P1_14, &Default::default()); + pwm.set_prescaler(Prescaler::Div1); + pwm.set_max_duty(32767); + info!("pwm initialized!"); + + let mut i = 0; + loop { + i += 1; + pwm.set_duty(0, DutyCycle::normal(DUTY[i % 1024])); + pwm.set_duty(1, DutyCycle::normal(DUTY[(i + 512) % 1024])); + Timer::after_millis(3).await; + } +} 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 @@ +#![no_std] +#![no_main] + +use defmt::info; +use embassy_executor::Spawner; +use embassy_nrf::saadc::{ChannelConfig, Config, Saadc}; +use embassy_nrf::{bind_interrupts, saadc}; +use embassy_time::Timer; +use {defmt_rtt as _, panic_probe as _}; + +bind_interrupts!(struct Irqs { + SAADC => saadc::InterruptHandler; +}); + +#[embassy_executor::main] +async fn main(_p: Spawner) { + let mut p = embassy_nrf::init(Default::default()); + let config = Config::default(); + let channel_config = ChannelConfig::single_ended(p.P1_04.reborrow()); + let mut saadc = Saadc::new(p.SAADC, Irqs, config, [channel_config]); + + loop { + let mut buf = [0; 1]; + saadc.sample(&mut buf).await; + info!("sample: {=i16}", &buf[0]); + Timer::after_millis(100).await; + } +} diff --git a/examples/nrf54l15/src/bin/spim.rs b/examples/nrf54l15/src/bin/spim.rs new file mode 100644 index 000000000..0520bf08c --- /dev/null +++ b/examples/nrf54l15/src/bin/spim.rs @@ -0,0 +1,72 @@ +#![no_std] +#![no_main] + +use defmt::{info, unwrap}; +use embassy_executor::Spawner; +use embassy_nrf::gpio::{Level, Output, OutputDrive}; +use embassy_nrf::{bind_interrupts, peripherals, spim}; +use {defmt_rtt as _, panic_probe as _}; + +bind_interrupts!(struct Irqs { + SERIAL00 => spim::InterruptHandler; +}); + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let p = embassy_nrf::init(Default::default()); + info!("running!"); + + let mut config = spim::Config::default(); + config.frequency = spim::Frequency::M16; + + let mut spim = spim::Spim::new(p.SERIAL00, Irqs, p.P0_01, p.P0_00, p.P0_02, config); + + // Example on how to talk to an ADXL343 + + let mut ncs = Output::new(p.P0_03, Level::High, OutputDrive::Standard); + + // Example on how to talk to an ENC28J60 chip + + // softreset + cortex_m::asm::delay(10); + ncs.set_low(); + cortex_m::asm::delay(5); + let tx = [0xFF]; + unwrap!(spim.transfer(&mut [], &tx).await); + cortex_m::asm::delay(10); + ncs.set_high(); + + cortex_m::asm::delay(100000); + + let mut rx = [0; 2]; + + // read ESTAT + cortex_m::asm::delay(5000); + ncs.set_low(); + cortex_m::asm::delay(5000); + let tx = [0b000_11101, 0]; + unwrap!(spim.transfer(&mut rx, &tx).await); + cortex_m::asm::delay(5000); + ncs.set_high(); + info!("estat: {=[?]}", rx); + + // Switch to bank 3 + cortex_m::asm::delay(10); + ncs.set_low(); + cortex_m::asm::delay(5); + let tx = [0b100_11111, 0b11]; + unwrap!(spim.transfer(&mut rx, &tx).await); + cortex_m::asm::delay(10); + ncs.set_high(); + + // read EREVID + cortex_m::asm::delay(10); + ncs.set_low(); + cortex_m::asm::delay(5); + let tx = [0b000_10010, 0]; + unwrap!(spim.transfer(&mut rx, &tx).await); + cortex_m::asm::delay(10); + ncs.set_high(); + + info!("erevid: {=[?]}", rx); +} 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 @@ +//! Example on how to read a 24C/24LC i2c eeprom. +//! +//! Connect SDA to P0.03, SCL to P0.04 + +#![no_std] +#![no_main] + +use defmt::*; +use embassy_executor::Spawner; +use embassy_nrf::twim::{self, Twim}; +use embassy_nrf::{bind_interrupts, peripherals}; +use static_cell::ConstStaticCell; +use {defmt_rtt as _, panic_probe as _}; + +const ADDRESS: u8 = 0x18; +const WHOAMI: u8 = 0x0F; + +bind_interrupts!(struct Irqs { + SERIAL20 => twim::InterruptHandler; +}); + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let p = embassy_nrf::init(Default::default()); + info!("Initializing TWI..."); + let config = twim::Config::default(); + static RAM_BUFFER: ConstStaticCell<[u8; 16]> = ConstStaticCell::new([0; 16]); + let mut twi = Twim::new(p.SERIAL20, Irqs, p.P1_13, p.P1_12, config, RAM_BUFFER.take()); + + info!("Reading..."); + + let mut data = [0u8; 1]; + match twi.write_read(ADDRESS, &[WHOAMI], &mut data).await { + Ok(()) => info!("Whoami: {}", data[0]), + Err(e) => error!("I2c Error: {:?}", e), + } +} 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 @@ +//! TWIS example + +#![no_std] +#![no_main] + +use defmt::*; +use embassy_executor::Spawner; +use embassy_nrf::twis::{self, Command, Twis}; +use embassy_nrf::{bind_interrupts, peripherals}; +use {defmt_rtt as _, panic_probe as _}; + +bind_interrupts!(struct Irqs { + SERIAL20 => twis::InterruptHandler; +}); + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let p = embassy_nrf::init(Default::default()); + + let mut config = twis::Config::default(); + config.address0 = 0x55; // Set i2c address + let mut i2c = Twis::new(p.SERIAL20, Irqs, p.P0_03, p.P0_04, config); + + info!("Listening..."); + loop { + let response = [1, 2, 3, 4, 5, 6, 7, 8]; + // This buffer is used if the i2c master performs a Write or WriteRead + let mut buf = [0u8; 16]; + match i2c.listen(&mut buf).await { + Ok(Command::Read) => { + info!("Got READ command. Respond with data:\n{:?}\n", response); + if let Err(e) = i2c.respond_to_read(&response).await { + error!("{:?}", e); + } + } + Ok(Command::Write(n)) => info!("Got WRITE command with data:\n{:?}\n", buf[..n]), + Ok(Command::WriteRead(n)) => { + info!("Got WRITE/READ command with data:\n{:?}", buf[..n]); + info!("Respond with data:\n{:?}\n", response); + if let Err(e) = i2c.respond_to_read(&response).await { + error!("{:?}", e); + } + } + Err(e) => error!("{:?}", e), + } + } +} 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 @@ +#![no_std] +#![no_main] + +use defmt::*; +use embassy_executor::Spawner; +use embassy_nrf::{bind_interrupts, peripherals, uarte}; +use {defmt_rtt as _, panic_probe as _}; + +bind_interrupts!(struct Irqs { + SERIAL20 => uarte::InterruptHandler; +}); + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let p = embassy_nrf::init(Default::default()); + let mut config = uarte::Config::default(); + config.parity = uarte::Parity::EXCLUDED; + config.baudrate = uarte::Baudrate::BAUD115200; + + let mut uart = uarte::Uarte::new(p.SERIAL20, p.P1_12, p.P1_13, Irqs, config); + + info!("uarte initialized!"); + + // Message must be in SRAM + let mut buf = [0; 8]; + buf.copy_from_slice(b"Hello!\r\n"); + + unwrap!(uart.write(&buf).await); + info!("wrote hello in uart!"); + + loop { + info!("reading..."); + unwrap!(uart.read(&mut buf).await); + info!("writing..."); + unwrap!(uart.write(&buf).await); + } +} -- cgit From e64fc05a91cc78f54c7a2440324d21dee54c0b04 Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Tue, 28 Oct 2025 13:36:49 +0100 Subject: chore: make it clear which gpiotec for a channel --- examples/nrf54l15/src/bin/gpiote_channel.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'examples') diff --git a/examples/nrf54l15/src/bin/gpiote_channel.rs b/examples/nrf54l15/src/bin/gpiote_channel.rs index 3fa0972a7..6333250ba 100644 --- a/examples/nrf54l15/src/bin/gpiote_channel.rs +++ b/examples/nrf54l15/src/bin/gpiote_channel.rs @@ -12,10 +12,10 @@ async fn main(_spawner: Spawner) { let p = embassy_nrf::init(Default::default()); info!("Starting!"); - let ch1 = InputChannel::new(p.GPIOTE_CH0, p.P1_13, Pull::Up, InputChannelPolarity::HiToLo); - let ch2 = InputChannel::new(p.GPIOTE_CH1, p.P1_09, Pull::Up, InputChannelPolarity::LoToHi); - let ch3 = InputChannel::new(p.GPIOTE_CH2, p.P1_08, Pull::Up, InputChannelPolarity::Toggle); - let ch4 = InputChannel::new(p.GPIOTE_CH8, p.P0_04, Pull::Up, InputChannelPolarity::Toggle); + let ch1 = InputChannel::new(p.GPIOTE20_CH0, p.P1_13, Pull::Up, InputChannelPolarity::HiToLo); + let ch2 = InputChannel::new(p.GPIOTE20_CH1, p.P1_09, Pull::Up, InputChannelPolarity::LoToHi); + let ch3 = InputChannel::new(p.GPIOTE20_CH2, p.P1_08, Pull::Up, InputChannelPolarity::Toggle); + let ch4 = InputChannel::new(p.GPIOTE30_CH0, p.P0_04, Pull::Up, InputChannelPolarity::Toggle); let button1 = async { loop { -- cgit From 83deef3672c651ac86e7ad497eccc52119b3a27f Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Tue, 28 Oct 2025 14:38:02 +0100 Subject: chore: simplify spim example to be testable on devkit --- examples/nrf54l15/src/bin/spim.rs | 70 ++++++++------------------------------- 1 file changed, 14 insertions(+), 56 deletions(-) (limited to 'examples') diff --git a/examples/nrf54l15/src/bin/spim.rs b/examples/nrf54l15/src/bin/spim.rs index 0520bf08c..3f5980647 100644 --- a/examples/nrf54l15/src/bin/spim.rs +++ b/examples/nrf54l15/src/bin/spim.rs @@ -1,9 +1,7 @@ #![no_std] #![no_main] -use defmt::{info, unwrap}; use embassy_executor::Spawner; -use embassy_nrf::gpio::{Level, Output, OutputDrive}; use embassy_nrf::{bind_interrupts, peripherals, spim}; use {defmt_rtt as _, panic_probe as _}; @@ -14,59 +12,19 @@ bind_interrupts!(struct Irqs { #[embassy_executor::main] async fn main(_spawner: Spawner) { let p = embassy_nrf::init(Default::default()); - info!("running!"); - let mut config = spim::Config::default(); - config.frequency = spim::Frequency::M16; - - let mut spim = spim::Spim::new(p.SERIAL00, Irqs, p.P0_01, p.P0_00, p.P0_02, config); - - // Example on how to talk to an ADXL343 - - let mut ncs = Output::new(p.P0_03, Level::High, OutputDrive::Standard); - - // Example on how to talk to an ENC28J60 chip - - // softreset - cortex_m::asm::delay(10); - ncs.set_low(); - cortex_m::asm::delay(5); - let tx = [0xFF]; - unwrap!(spim.transfer(&mut [], &tx).await); - cortex_m::asm::delay(10); - ncs.set_high(); - - cortex_m::asm::delay(100000); - - let mut rx = [0; 2]; - - // read ESTAT - cortex_m::asm::delay(5000); - ncs.set_low(); - cortex_m::asm::delay(5000); - let tx = [0b000_11101, 0]; - unwrap!(spim.transfer(&mut rx, &tx).await); - cortex_m::asm::delay(5000); - ncs.set_high(); - info!("estat: {=[?]}", rx); - - // Switch to bank 3 - cortex_m::asm::delay(10); - ncs.set_low(); - cortex_m::asm::delay(5); - let tx = [0b100_11111, 0b11]; - unwrap!(spim.transfer(&mut rx, &tx).await); - cortex_m::asm::delay(10); - ncs.set_high(); - - // read EREVID - cortex_m::asm::delay(10); - ncs.set_low(); - cortex_m::asm::delay(5); - let tx = [0b000_10010, 0]; - unwrap!(spim.transfer(&mut rx, &tx).await); - cortex_m::asm::delay(10); - ncs.set_high(); - - info!("erevid: {=[?]}", rx); + config.frequency = spim::Frequency::M32; + let mut spim = spim::Spim::new(p.SERIAL00, Irqs, p.P2_05, p.P2_09, p.P2_08, config.clone()); + let data = [ + 0x42, 0x43, 0x44, 0x45, 0x66, 0x12, 0x23, 0x34, 0x45, 0x19, 0x91, 0xaa, 0xff, 0xa5, 0x5a, 0x77, + ]; + let mut buf = [0u8; 16]; + + buf.fill(0); + spim.blocking_transfer(&mut buf, &data).unwrap(); + assert_eq!(data, buf); + + buf.fill(0); + spim.transfer(&mut buf, &data).await.unwrap(); + assert_eq!(data, buf); } -- cgit From 98de11e5e3ae437676198a105ffab8c0f4977513 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Wed, 29 Oct 2025 17:49:55 +0100 Subject: net-esp-hosted: add Interface trait. --- examples/nrf52840/src/bin/wifi_esp_hosted.rs | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) (limited to 'examples') 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 { async fn wifi_task( runner: hosted::Runner< 'static, - ExclusiveDevice, Output<'static>, Delay>, - Input<'static>, + hosted::SpiInterface, Output<'static>, Delay>, Input<'static>>, Output<'static>, >, ) -> ! { runner.run().await } - #[embassy_executor::task] async fn net_task(mut runner: embassy_net::Runner<'static, hosted::NetDriver<'static>>) -> ! { runner.run().await @@ -60,15 +58,11 @@ async fn main(spawner: Spawner) { let spi = spim::Spim::new(p.SPI3, Irqs, sck, miso, mosi, config); let spi = ExclusiveDevice::new(spi, cs, Delay); + let iface = hosted::SpiInterface::new(spi, handshake, ready); + static ESP_STATE: StaticCell = StaticCell::new(); - let (device, mut control, runner) = embassy_net_esp_hosted::new( - ESP_STATE.init(embassy_net_esp_hosted::State::new()), - spi, - handshake, - ready, - reset, - ) - .await; + let (device, mut control, runner) = + embassy_net_esp_hosted::new(ESP_STATE.init(embassy_net_esp_hosted::State::new()), iface, reset).await; spawner.spawn(unwrap!(wifi_task(runner))); -- cgit