feat(nrf): add rtc support for nRF54L

Signed-off-by: Haobo Gu <haobogu@outlook.com>
This commit is contained in:
Haobo Gu 2025-10-14 23:39:52 +08:00
parent 4d6763364d
commit 6fef28da94
5 changed files with 102 additions and 1 deletions

View File

@ -80,6 +80,8 @@ 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"]
## Enable embassy-net 802.15.4 driver

View File

@ -249,6 +249,45 @@ embassy_hal_internal::peripherals! {
P2_09,
P2_10,
// RTC
RTC10,
RTC30,
// SERIAL
SERIAL00,
SERIAL20,
SERIAL21,
SERIAL22,
SERIAL30,
// SAADC
SAADC,
// RADIO
RADIO,
// TIMER
TIMER00,
TIMER10,
TIMER20,
// PPI BRIDGE
PPIB00,
PPIB01,
PPIB10,
PPIB11,
PPIB20,
PPIB21,
PPIB22,
PPIB30,
// GPIOTE
GPIOTE20,
GPIOTE30,
// CRACEN
CRACEN,
#[cfg(feature = "_s")]
// RRAMC
RRAMC,
@ -303,6 +342,9 @@ impl_pin!(P2_08, 2, 8);
impl_pin!(P2_09, 2, 9);
impl_pin!(P2_10, 2, 10);
impl_rtc!(RTC10, RTC10, RTC10);
impl_rtc!(RTC30, RTC30, RTC30);
#[cfg(feature = "_ns")]
impl_wdt!(WDT, WDT31, WDT31, 0);
#[cfg(feature = "_s")]

View File

@ -155,7 +155,6 @@ pub mod reset;
#[cfg(not(feature = "_nrf54l"))] // TODO
#[cfg(not(any(feature = "_nrf5340-app", feature = "_nrf91")))]
pub mod rng;
#[cfg(not(feature = "_nrf54l"))] // TODO
pub mod rtc;
#[cfg(not(feature = "_nrf54l"))] // TODO
#[cfg(not(any(feature = "_nrf51", feature = "nrf52820", feature = "_nrf5340-net")))]

View File

@ -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

View File

@ -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<CriticalSectionRawMutex, RefCell<Option<Rtc<'static>>>> = 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);
});
}