From 660fc4f7602c0be689e2c6cb4b20e55a26127636 Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Wed, 26 Nov 2025 14:35:18 +0100 Subject: feat: support nrf54 GRTC as time-driver * Refactor GRTC peripheral splitting it into multiple channels * Reserve channel 1 for time-driver if enabled * Implement time-driver using GRTC (RTC peripheral is now removed). * Add timer example to nrf54l15 --- embassy-nrf/Cargo.toml | 18 ++-- embassy-nrf/src/chips/nrf54l15_app.rs | 28 +++--- embassy-nrf/src/lib.rs | 1 + embassy-nrf/src/time_driver.rs | 157 ++++++++++++++++++++++++++-------- examples/nrf54l15/Cargo.toml | 2 +- examples/nrf54l15/src/bin/rtc.rs | 56 ------------ examples/nrf54l15/src/bin/timer.rs | 30 +++++++ 7 files changed, 178 insertions(+), 114 deletions(-) delete mode 100644 examples/nrf54l15/src/bin/rtc.rs create mode 100644 examples/nrf54l15/src/bin/timer.rs diff --git a/embassy-nrf/Cargo.toml b/embassy-nrf/Cargo.toml index 08f4b280b..0a71094eb 100644 --- a/embassy-nrf/Cargo.toml +++ b/embassy-nrf/Cargo.toml @@ -23,8 +23,8 @@ build = [ {target = "thumbv8m.main-none-eabihf", features = ["gpiote", "nrf5340-app-s", "time", "time-driver-rtc1"]}, {target = "thumbv8m.main-none-eabihf", features = ["gpiote", "nrf5340-app-ns", "time", "time-driver-rtc1"]}, {target = "thumbv8m.main-none-eabihf", features = ["gpiote", "nrf5340-net", "time", "time-driver-rtc1"]}, - {target = "thumbv8m.main-none-eabihf", features = ["gpiote", "nrf54l15-app-s", "time", "time-driver-rtc1"]}, - {target = "thumbv8m.main-none-eabihf", features = ["gpiote", "nrf54l15-app-ns", "time", "time-driver-rtc1"]}, + {target = "thumbv8m.main-none-eabihf", features = ["gpiote", "nrf54l15-app-s", "time", "time-driver-grtc"]}, + {target = "thumbv8m.main-none-eabihf", features = ["gpiote", "nrf54l15-app-ns", "time", "time-driver-grtc"]}, {target = "thumbv7em-none-eabi", features = ["gpiote", "nrf52840", "time"]}, {target = "thumbv7em-none-eabi", features = ["gpiote", "nrf52840", "time-driver-rtc1"]}, {target = "thumbv7em-none-eabi", features = ["gpiote", "nrf52840", "time", "time-driver-rtc1"]}, @@ -80,9 +80,10 @@ unstable-pac = [] gpiote = [] ## Use RTC1 as the time driver for `embassy-time`, with a tick rate of 32.768khz -## -## Note: For nRF54L, it's actually RTC30 -time-driver-rtc1 = ["_time-driver"] +time-driver-rtc1 = ["_time-driver", "embassy-time-driver?/tick-hz-32_768"] + +## Use GRTC (CC n=1, GRTC_1 irq) as the time driver for `embassy-time`, with a tick rate of 1 MHz +time-driver-grtc = ["_time-driver", "embassy-time-driver?/tick-hz-1_000_000"] ## Enable embassy-net 802.15.4 driver net-driver = ["_net-driver"] @@ -152,7 +153,7 @@ _nrf5340-net = ["_nrf5340", "nrf-pac/nrf5340-net"] _nrf5340 = ["_gpio-p1", "_dppi"] _nrf54l15-app = ["_nrf54l15", "nrf-pac/nrf54l15-app"] _nrf54l15 = ["_nrf54l", "_gpio-p1", "_gpio-p2"] -_nrf54l = ["_dppi"] +_nrf54l = ["_dppi", "_grtc"] _nrf9160 = ["nrf-pac/nrf9160", "_dppi", "_spi-v1"] _nrf9120 = ["nrf-pac/nrf9120", "_dppi", "_spi-v1"] @@ -160,7 +161,7 @@ _nrf52 = ["_ppi"] _nrf51 = ["_ppi", "_spi-v1"] _nrf91 = [] -_time-driver = ["dep:embassy-time-driver", "embassy-time-driver?/tick-hz-32_768", "dep:embassy-time-queue-utils", "embassy-embedded-hal/time"] +_time-driver = ["dep:embassy-time-driver", "dep:embassy-time-queue-utils", "embassy-embedded-hal/time"] _net-driver = ["dep:embassy-net-driver-channel","dep:embassy-futures"] @@ -173,6 +174,7 @@ _dppi = [] _gpio-p1 = [] _gpio-p2 = [] _spi-v1 = [] +_grtc = [] # Errata workarounds _nrf52832_anomaly_109 = [] @@ -200,7 +202,7 @@ embedded-io-async = { version = "0.6.1" } rand-core-06 = { package = "rand_core", version = "0.6" } rand-core-09 = { package = "rand_core", version = "0.9" } -nrf-pac = { version = "0.1.0", git = "https://github.com/embassy-rs/nrf-pac.git", rev = "58198c23bce72edc10b4e1656d1b54441fc74e7c" } +nrf-pac = { version = "0.1.0", git = "https://github.com/embassy-rs/nrf-pac.git", rev = "0068816c482932e3c59964817610ef41e79a6843" } defmt = { version = "1.0.1", optional = true } bitflags = "2.4.2" diff --git a/embassy-nrf/src/chips/nrf54l15_app.rs b/embassy-nrf/src/chips/nrf54l15_app.rs index 8846717db..b6c9fd110 100644 --- a/embassy-nrf/src/chips/nrf54l15_app.rs +++ b/embassy-nrf/src/chips/nrf54l15_app.rs @@ -26,7 +26,6 @@ pub mod pac { PPIB10_NS as PPIB10, PPIB11_NS as PPIB11, TIMER10_NS as TIMER10, - RTC10_NS as RTC10, EGU10_NS as EGU10, RADIO_NS as RADIO, DPPIC20_NS as DPPIC20, @@ -76,7 +75,6 @@ pub mod pac { TWIM30_NS as TWIM30, TWIS30_NS as TWIS30, UARTE30_NS as UARTE30, - RTC30_NS as RTC30, COMP_NS as COMP, LPCOMP_NS as LPCOMP, WDT31_NS as WDT31, @@ -127,7 +125,6 @@ pub mod pac { PPIB10_S as PPIB10, PPIB11_S as PPIB11, TIMER10_S as TIMER10, - RTC10_S as RTC10, EGU10_S as EGU10, RADIO_S as RADIO, SPU20_S as SPU20, @@ -180,7 +177,6 @@ pub mod pac { TWIM30_S as TWIM30, TWIS30_S as TWIS30, UARTE30_S as UARTE30, - RTC30_S as RTC30, COMP_S as COMP, LPCOMP_S as LPCOMP, WDT30_S as WDT30, @@ -417,11 +413,19 @@ embassy_hal_internal::peripherals! { P2_10, // GRTC - GRTC, - - // RTC - RTC10, - RTC30, + GRTC_CH0, + #[cfg(not(feature = "time-driver-grtc"))] + GRTC_CH1, + GRTC_CH2, + GRTC_CH3, + GRTC_CH4, + GRTC_CH5, + GRTC_CH6, + GRTC_CH7, + GRTC_CH8, + GRTC_CH9, + GRTC_CH10, + GRTC_CH11, // PWM PWM20, @@ -548,9 +552,6 @@ cfg_if::cfg_if! { } } -impl_rtc!(RTC10, RTC10, RTC10); -impl_rtc!(RTC30, RTC30, RTC30); - #[cfg(feature = "_ns")] impl_wdt!(WDT, WDT31, WDT31, 0); #[cfg(feature = "_s")] @@ -703,7 +704,6 @@ embassy_hal_internal::interrupt_mod!( TIMER00, SPU10, TIMER10, - RTC10, EGU10, RADIO_0, RADIO_1, @@ -737,11 +737,9 @@ embassy_hal_internal::interrupt_mod!( GRTC_3, SPU30, SERIAL30, - RTC30, COMP_LPCOMP, WDT30, WDT31, GPIOTE30_0, GPIOTE30_1, - CLOCK_POWER, ); diff --git a/embassy-nrf/src/lib.rs b/embassy-nrf/src/lib.rs index 28d2119ae..e8762b00d 100644 --- a/embassy-nrf/src/lib.rs +++ b/embassy-nrf/src/lib.rs @@ -153,6 +153,7 @@ pub mod reset; #[cfg(not(feature = "_nrf54l"))] #[cfg(not(any(feature = "_nrf5340-app", feature = "_nrf91")))] pub mod rng; +#[cfg(not(feature = "_nrf54l"))] pub mod rtc; #[cfg(not(any(feature = "_nrf51", feature = "nrf52820", feature = "_nrf5340-net")))] pub mod saadc; diff --git a/embassy-nrf/src/time_driver.rs b/embassy-nrf/src/time_driver.rs index b723e2334..de1974fb7 100644 --- a/embassy-nrf/src/time_driver.rs +++ b/embassy-nrf/src/time_driver.rs @@ -1,4 +1,5 @@ use core::cell::{Cell, RefCell}; +#[cfg(not(feature = "_grtc"))] use core::sync::atomic::{AtomicU32, Ordering, compiler_fence}; use critical_section::CriticalSection; @@ -8,21 +9,27 @@ use embassy_time_driver::Driver; use embassy_time_queue_utils::Queue; use crate::interrupt::InterruptExt; +#[cfg(feature = "_grtc")] +use crate::pac::grtc::vals::Busy; use crate::{interrupt, pac}; -#[cfg(feature = "_nrf54l")] -fn rtc() -> pac::rtc::Rtc { - pac::RTC30 +#[cfg(feature = "_grtc")] +fn rtc() -> pac::grtc::Grtc { + pac::GRTC } -#[cfg(not(feature = "_nrf54l"))] + +#[cfg(not(feature = "_grtc"))] fn rtc() -> pac::rtc::Rtc { pac::RTC1 } /// Calculate the timestamp from the period count and the tick count. /// -/// The RTC counter is 24 bit. Ticking at 32768hz, it overflows every ~8 minutes. This is -/// too short. We must make it "never" overflow. +/// For nRF54 devices and newer, the GRTC counter is 52 bits, so the time driver uses the +/// syscounter and ignores the periods handling, since it overflows every 142 years. +/// +/// For most other devices, the RTC counter is 24 bit. Ticking at 32768hz, it overflows every ~8 minutes. +/// This is too short. We must make it "never" overflow. /// /// The obvious way would be to count overflow periods. Every time the counter overflows, /// increase a `periods` variable. `now()` simply does `periods << 24 + counter`. So, the logic @@ -64,14 +71,39 @@ fn rtc() -> pac::rtc::Rtc { /// `period` is a 32bit integer, so It overflows on 2^32 * 2^23 / 32768 seconds of uptime, which is 34865 /// years. For comparison, flash memory like the one containing your firmware is usually rated to retain /// data for only 10-20 years. 34865 years is long enough! +#[cfg(not(feature = "_grtc"))] fn calc_now(period: u32, counter: u32) -> u64 { ((period as u64) << 23) + ((counter ^ ((period & 1) << 23)) as u64) } +#[cfg(feature = "_grtc")] +fn syscounter() -> u64 { + let r = rtc(); + r.syscounter(0).active().write(|w| w.set_active(true)); + loop { + let countl: u32 = r.syscounter(0).syscounterl().read(); + let counth = r.syscounter(0).syscounterh().read(); + + if counth.busy() == Busy::READY && !counth.overflow() { + let counth: u32 = counth.value(); + let count = countl as u64 | ((counth as u64) << 32); + r.syscounter(0).active().write(|w| w.set_active(false)); + return count; + } + // If overflow or not ready, loop will re-read both registers + } +} + +#[cfg(not(feature = "_grtc"))] fn compare_n(n: usize) -> u32 { 1 << (n + 16) } +#[cfg(feature = "_grtc")] +fn compare_n(n: usize) -> u32 { + 1 << n // GRTC uses bits 0-11 for COMPARE[0-11] +} + #[cfg(test)] mod test { use super::*; @@ -108,6 +140,7 @@ impl AlarmState { struct RtcDriver { /// Number of 2^23 periods elapsed since boot. + #[cfg(not(feature = "_grtc"))] period: AtomicU32, /// Timestamp at which to fire alarm. u64::MAX if no alarm is scheduled. alarms: Mutex, @@ -115,6 +148,7 @@ struct RtcDriver { } embassy_time_driver::time_driver_impl!(static DRIVER: RtcDriver = RtcDriver { + #[cfg(not(feature = "_grtc"))] period: AtomicU32::new(0), alarms: Mutex::const_new(CriticalSectionRawMutex::new(), AlarmState::new()), queue: Mutex::new(RefCell::new(Queue::new())), @@ -123,25 +157,48 @@ embassy_time_driver::time_driver_impl!(static DRIVER: RtcDriver = RtcDriver { impl RtcDriver { fn init(&'static self, irq_prio: crate::interrupt::Priority) { let r = rtc(); - r.cc(3).write(|w| w.set_compare(0x800000)); + // Chips without GRTC needs to deal with overflow + #[cfg(not(feature = "_grtc"))] + { + r.cc(3).write(|w| w.set_compare(0x800000)); - r.intenset().write(|w| { - w.set_ovrflw(true); - w.set_compare(3, true); - }); + r.intenset().write(|w| { + w.set_ovrflw(true); + w.set_compare(3, true); + }); + } + #[cfg(feature = "_grtc")] + { + r.mode().write(|w| { + w.set_syscounteren(true); + }); + } r.tasks_clear().write_value(1); r.tasks_start().write_value(1); // Wait for clear + #[cfg(not(feature = "_grtc"))] while r.counter().read().0 != 0 {} - #[cfg(feature = "_nrf54l")] + #[cfg(feature = "_grtc")] + { + // According to datasheet, we need to wait for STATUS.LFTIMER.READY + // before the timer is actually started + loop { + if r.status().lftimer().read().ready() { + break; + } + } + // Keep SYSCOUNTER[0] always active so we can read it anytime without BUSY waits + } + + #[cfg(feature = "_grtc")] { - interrupt::RTC30.set_priority(irq_prio); - unsafe { interrupt::RTC30.enable() }; + interrupt::GRTC_1.set_priority(irq_prio); + unsafe { interrupt::GRTC_1.enable() }; } - #[cfg(not(feature = "_nrf54l"))] + #[cfg(not(feature = "_grtc"))] { interrupt::RTC1.set_priority(irq_prio); unsafe { interrupt::RTC1.enable() }; @@ -150,11 +207,14 @@ impl RtcDriver { fn on_interrupt(&self) { let r = rtc(); + + #[cfg(not(feature = "_grtc"))] if r.events_ovrflw().read() == 1 { r.events_ovrflw().write_value(0); self.next_period(); } + #[cfg(not(feature = "_grtc"))] if r.events_compare(3).read() == 1 { r.events_compare(3).write_value(0); self.next_period(); @@ -169,6 +229,7 @@ impl RtcDriver { } } + #[cfg(not(feature = "_grtc"))] fn next_period(&self) { critical_section::with(|cs| { let r = rtc(); @@ -190,7 +251,10 @@ impl RtcDriver { fn trigger_alarm(&self, cs: CriticalSection) { let n = 0; let r = rtc(); + #[cfg(not(feature = "_grtc"))] r.intenclr().write(|w| w.0 = compare_n(n)); + #[cfg(feature = "_grtc")] + r.intenclr(1).write(|w| w.0 = compare_n(n)); let alarm = &self.alarms.borrow(cs); alarm.timestamp.set(u64::MAX); @@ -214,7 +278,10 @@ impl RtcDriver { if timestamp <= t { // If alarm timestamp has passed the alarm will not fire. // Disarm the alarm and return `false` to indicate that. + #[cfg(not(feature = "_grtc"))] r.intenclr().write(|w| w.0 = compare_n(n)); + #[cfg(feature = "_grtc")] + r.intenclr(1).write(|w| w.0 = compare_n(n)); alarm.timestamp.set(u64::MAX); @@ -226,7 +293,7 @@ impl RtcDriver { // Write the CC value regardless of whether we're going to enable it now or not. // This way, when we enable it later, the right value is already set. - // nrf52 docs say: + // nrf52 docs say : // If the COUNTER is N, writing N or N+1 to a CC register may not trigger a COMPARE event. // To workaround this, we never write a timestamp smaller than N+3. // N+2 is not safe because rtc can tick from N to N+1 between calling now() and writing cc. @@ -238,22 +305,39 @@ impl RtcDriver { // This means that an alarm can be delayed for up to 2 ticks (from t+1 to t+3), but this is allowed // by the Alarm trait contract. What's not allowed is triggering alarms *before* their scheduled time, // and we don't do that here. - let safe_timestamp = timestamp.max(t + 3); - r.cc(n).write(|w| w.set_compare(safe_timestamp as u32 & 0xFFFFFF)); - - let diff = timestamp - t; - if diff < 0xc00000 { - r.intenset().write(|w| w.0 = compare_n(n)); - - // If we have not passed the timestamp, we can be sure the alarm will be invoked. Otherwise, - // we need to retry setting the alarm. - if self.now() + 2 <= timestamp { + #[cfg(not(feature = "_grtc"))] + { + let safe_timestamp = timestamp.max(t + 3); + r.cc(n).write(|w| w.set_compare(safe_timestamp as u32 & 0xFFFFFF)); + let diff = timestamp - t; + if diff < 0xc00000 { + r.intenset().write(|w| w.0 = compare_n(n)); + + // If we have not passed the timestamp, we can be sure the alarm will be invoked. Otherwise, + // we need to retry setting the alarm. + if self.now() + 2 <= timestamp { + return true; + } + } else { + // If it's too far in the future, don't setup the compare channel yet. + // It will be setup later by `next_period`. + r.intenclr().write(|w| w.0 = compare_n(n)); return true; } - } else { - // If it's too far in the future, don't setup the compare channel yet. - // It will be setup later by `next_period`. - r.intenclr().write(|w| w.0 = compare_n(n)); + } + + // The nRF54 datasheet states that 'The EVENTS_COMPARE[n] event is generated immediately if the + // configured compare value at CC[n] is less than the current SYSCOUNTER value.'. This means we + // can write the expected timestamp and be sure the alarm is triggered. + #[cfg(feature = "_grtc")] + { + let ccl = timestamp as u32; + let cch = (timestamp >> 32) as u32 & 0xFFFFF; // 20 bits for CCH + + r.cc(n).ccl().write_value(ccl); + r.cc(n).cch().write(|w| w.set_cch(cch)); + r.intenset(1).write(|w| w.0 = compare_n(n)); + return true; } } @@ -261,6 +345,7 @@ impl RtcDriver { } impl Driver for RtcDriver { + #[cfg(not(feature = "_grtc"))] fn now(&self) -> u64 { // `period` MUST be read before `counter`, see comment at the top for details. let period = self.period.load(Ordering::Relaxed); @@ -269,10 +354,14 @@ impl Driver for RtcDriver { calc_now(period, counter) } + #[cfg(feature = "_grtc")] + fn now(&self) -> u64 { + syscounter() + } + fn schedule_wake(&self, at: u64, waker: &core::task::Waker) { critical_section::with(|cs| { let mut queue = self.queue.borrow(cs).borrow_mut(); - if queue.schedule_wake(at, waker) { let mut next = queue.next_expiration(self.now()); while !self.set_alarm(cs, next) { @@ -283,14 +372,14 @@ impl Driver for RtcDriver { } } -#[cfg(feature = "_nrf54l")] +#[cfg(feature = "_grtc")] #[cfg(feature = "rt")] #[interrupt] -fn RTC30() { +fn GRTC_1() { DRIVER.on_interrupt() } -#[cfg(not(feature = "_nrf54l"))] +#[cfg(not(feature = "_grtc"))] #[cfg(feature = "rt")] #[interrupt] fn RTC1() { diff --git a/examples/nrf54l15/Cargo.toml b/examples/nrf54l15/Cargo.toml index 4ef77279f..f34df0f26 100644 --- a/examples/nrf54l15/Cargo.toml +++ b/examples/nrf54l15/Cargo.toml @@ -10,7 +10,7 @@ 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"] } +embassy-nrf = { version = "0.8.0", path = "../../embassy-nrf", features = ["defmt", "nrf54l15-app-s", "time-driver-grtc", "gpiote", "unstable-pac", "time"] } embedded-io = { version = "0.6.0", features = ["defmt-03"] } embedded-io-async = { version = "0.6.1", features = ["defmt-03"] } diff --git a/examples/nrf54l15/src/bin/rtc.rs b/examples/nrf54l15/src/bin/rtc.rs deleted file mode 100644 index a45aaca52..000000000 --- a/examples/nrf54l15/src/bin/rtc.rs +++ /dev/null @@ -1,56 +0,0 @@ -#![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); - }); -} diff --git a/examples/nrf54l15/src/bin/timer.rs b/examples/nrf54l15/src/bin/timer.rs new file mode 100644 index 000000000..68acc91c1 --- /dev/null +++ b/examples/nrf54l15/src/bin/timer.rs @@ -0,0 +1,30 @@ +#![no_std] +#![no_main] + +use defmt::{info, unwrap}; +use embassy_executor::Spawner; +use embassy_time::Timer; +use {defmt_rtt as _, panic_probe as _}; + +#[embassy_executor::task] +async fn run1() { + loop { + info!("BIG INFREQUENT TICK"); + Timer::after_secs(10).await; + } +} + +#[embassy_executor::task] +async fn run2() { + loop { + info!("tick"); + Timer::after_secs(1).await; + } +} + +#[embassy_executor::main] +async fn main(spawner: Spawner) { + let _p = embassy_nrf::init(Default::default()); + spawner.spawn(unwrap!(run1())); + spawner.spawn(unwrap!(run2())); +} -- cgit From 9842b8b8927ff3de0bde2bf78a49b3d52bd20e5a Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Wed, 26 Nov 2025 14:36:57 +0100 Subject: fix: update saadc after API changes --- embassy-nrf/src/saadc.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/embassy-nrf/src/saadc.rs b/embassy-nrf/src/saadc.rs index ca8cbd73e..ab0e2b86a 100644 --- a/embassy-nrf/src/saadc.rs +++ b/embassy-nrf/src/saadc.rs @@ -771,7 +771,7 @@ pub(crate) trait SealedInput { fn port(&self) -> u8; #[cfg(feature = "_nrf54l")] - fn internal(&self) -> vals::Internal; + fn internal(&self) -> vals::PselpInternal; #[cfg(feature = "_nrf54l")] fn connect(&self) -> vals::PselpConnect; @@ -832,7 +832,7 @@ pub struct AnyInput<'a> { pub struct AnyInput<'a> { pin: u8, port: u8, - internal: vals::Internal, + internal: vals::PselpInternal, connect: vals::PselpConnect, _phantom: PhantomData<&'a ()>, } @@ -881,7 +881,7 @@ impl SealedInput for AnyInput<'_> { } #[cfg(feature = "_nrf54l")] - fn internal(&self) -> vals::Internal { + fn internal(&self) -> vals::PselpInternal { self.internal } @@ -923,8 +923,8 @@ macro_rules! impl_saadc_input { $port } - fn internal(&self) -> crate::pac::saadc::vals::Internal { - crate::pac::saadc::vals::Internal::$internal + fn internal(&self) -> crate::pac::saadc::vals::PselpInternal { + crate::pac::saadc::vals::PselpInternal::$internal } fn connect(&self) -> crate::pac::saadc::vals::PselpConnect { -- cgit From cb293d866ed26d2b6c8018450ece26d84089e137 Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Wed, 26 Nov 2025 14:41:11 +0100 Subject: chore: update changelog --- embassy-nrf/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/embassy-nrf/CHANGELOG.md b/embassy-nrf/CHANGELOG.md index cfb040ef5..5657ddcfb 100644 --- a/embassy-nrf/CHANGELOG.md +++ b/embassy-nrf/CHANGELOG.md @@ -8,7 +8,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased - ReleaseDate -- added: Add basic RTC support for nRF54L - changed: apply trimming values from FICR.TRIMCNF on nrf53/54l - changed: do not panic on BufferedUarte overrun - added: allow direct access to the input pin of `gpiote::InputChannel` @@ -29,6 +28,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - bugfix: use correct flash size for nRF54l - changed: add workaround for anomaly 66 on nrf52 - added: expose PPI events available on SPIS peripheral +- added: add basic GRTC time driver support for nRF54L ## 0.8.0 - 2025-09-30 -- cgit From da96ef9d51730975b52fa2c92ec27236b68f1daf Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Wed, 26 Nov 2025 14:42:46 +0100 Subject: chore: cleanup --- embassy-nrf/src/time_driver.rs | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/embassy-nrf/src/time_driver.rs b/embassy-nrf/src/time_driver.rs index de1974fb7..35f65bd64 100644 --- a/embassy-nrf/src/time_driver.rs +++ b/embassy-nrf/src/time_driver.rs @@ -182,15 +182,10 @@ impl RtcDriver { while r.counter().read().0 != 0 {} #[cfg(feature = "_grtc")] - { - // According to datasheet, we need to wait for STATUS.LFTIMER.READY - // before the timer is actually started - loop { - if r.status().lftimer().read().ready() { - break; - } + loop { + if r.status().lftimer().read().ready() { + break; } - // Keep SYSCOUNTER[0] always active so we can read it anytime without BUSY waits } #[cfg(feature = "_grtc")] -- cgit From 372e436985938d4a0de4403b31177e97762b2c79 Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Wed, 26 Nov 2025 15:07:50 +0100 Subject: fix: update pac version for nrf91-net --- embassy-net-nrf91/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/embassy-net-nrf91/Cargo.toml b/embassy-net-nrf91/Cargo.toml index 75b7aeeb2..5c0c2e6b2 100644 --- a/embassy-net-nrf91/Cargo.toml +++ b/embassy-net-nrf91/Cargo.toml @@ -18,7 +18,7 @@ log = ["dep:log"] defmt = { version = "1.0.1", optional = true } log = { version = "0.4.14", optional = true } -nrf-pac = { version = "0.1.0", git = "https://github.com/embassy-rs/nrf-pac.git", rev = "58198c23bce72edc10b4e1656d1b54441fc74e7c" } +nrf-pac = { version = "0.1.0", git = "https://github.com/embassy-rs/nrf-pac.git", rev = "0068816c482932e3c59964817610ef41e79a6843" } cortex-m = "0.7.7" embassy-time = { version = "0.5.0", path = "../embassy-time" } -- cgit From ec93a56a2e5ba4403a603b9015daa2e94712917b Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Thu, 27 Nov 2025 09:22:24 +0100 Subject: fix: patch back clock power irq --- embassy-net-nrf91/Cargo.toml | 2 +- embassy-nrf/Cargo.toml | 2 +- embassy-nrf/src/chips/nrf54l15_app.rs | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/embassy-net-nrf91/Cargo.toml b/embassy-net-nrf91/Cargo.toml index 5c0c2e6b2..8cf11f1fb 100644 --- a/embassy-net-nrf91/Cargo.toml +++ b/embassy-net-nrf91/Cargo.toml @@ -18,7 +18,7 @@ log = ["dep:log"] defmt = { version = "1.0.1", optional = true } log = { version = "0.4.14", optional = true } -nrf-pac = { version = "0.1.0", git = "https://github.com/embassy-rs/nrf-pac.git", rev = "0068816c482932e3c59964817610ef41e79a6843" } +nrf-pac = { version = "0.1.0", git = "https://github.com/embassy-rs/nrf-pac.git", rev = "176dc4afe1dd8df78f3cbda4479ab5151aa32252" } cortex-m = "0.7.7" embassy-time = { version = "0.5.0", path = "../embassy-time" } diff --git a/embassy-nrf/Cargo.toml b/embassy-nrf/Cargo.toml index 0a71094eb..f73772682 100644 --- a/embassy-nrf/Cargo.toml +++ b/embassy-nrf/Cargo.toml @@ -202,7 +202,7 @@ embedded-io-async = { version = "0.6.1" } rand-core-06 = { package = "rand_core", version = "0.6" } rand-core-09 = { package = "rand_core", version = "0.9" } -nrf-pac = { version = "0.1.0", git = "https://github.com/embassy-rs/nrf-pac.git", rev = "0068816c482932e3c59964817610ef41e79a6843" } +nrf-pac = { version = "0.1.0", git = "https://github.com/embassy-rs/nrf-pac.git", rev = "176dc4afe1dd8df78f3cbda4479ab5151aa32252" } defmt = { version = "1.0.1", optional = true } bitflags = "2.4.2" diff --git a/embassy-nrf/src/chips/nrf54l15_app.rs b/embassy-nrf/src/chips/nrf54l15_app.rs index b6c9fd110..8e6595248 100644 --- a/embassy-nrf/src/chips/nrf54l15_app.rs +++ b/embassy-nrf/src/chips/nrf54l15_app.rs @@ -742,4 +742,5 @@ embassy_hal_internal::interrupt_mod!( WDT31, GPIOTE30_0, GPIOTE30_1, + CLOCK_POWER, ); -- cgit