From e79592c7af7b3476d2e51f5859c586b9ff8f5381 Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Tue, 2 Dec 2025 11:20:43 +0100 Subject: feat: support OTA commands in esp-hosted driver * Expose OTA functionality in control * Handle OTA swap wait in runner --- embassy-net-esp-hosted/src/control.rs | 46 ++++++++++++++++++++++++++++++++++- embassy-net-esp-hosted/src/ioctl.rs | 17 +++++++++++++ embassy-net-esp-hosted/src/lib.rs | 5 ++++ embassy-net-esp-hosted/src/proto.rs | 12 ++++----- 4 files changed, 73 insertions(+), 7 deletions(-) diff --git a/embassy-net-esp-hosted/src/control.rs b/embassy-net-esp-hosted/src/control.rs index 38ec648b4..d96a62daf 100644 --- a/embassy-net-esp-hosted/src/control.rs +++ b/embassy-net-esp-hosted/src/control.rs @@ -24,6 +24,11 @@ pub struct Control<'a> { shared: &'a Shared, } +/// Handle for managing firmware update. +pub struct UpdateControl<'a, 'd> { + control: &'a mut Control<'d>, +} + /// WiFi mode. #[allow(unused)] #[derive(Copy, Clone, PartialEq, Eq, Debug)] @@ -146,6 +151,13 @@ impl<'a> Control<'a> { Ok(()) } + /// Initiate a firmware update. + pub async fn update(&mut self) -> Result, Error> { + let req = proto::CtrlMsg_Req_OTABegin {}; + ioctl!(self, ReqOtaBegin, RespOtaBegin, req, resp); + Ok(UpdateControl { control: self }) + } + /// duration in seconds, clamped to [10, 3600] async fn set_heartbeat(&mut self, duration: u32) -> Result<(), Error> { let req = proto::CtrlMsg_Req_ConfigHeartbeat { @@ -175,7 +187,8 @@ impl<'a> Control<'a> { async fn ioctl(&mut self, msg: &mut CtrlMsg) -> Result<(), Error> { debug!("ioctl req: {:?}", &msg); - let mut buf = [0u8; 128]; + // Theoretical max overhead is 29 bytes. Biggest message is OTA write with 256 bytes. + let mut buf = [0u8; 256 + 29]; let buf_len = buf.len(); let mut encoder = PbEncoder::new(&mut buf[..]); @@ -216,6 +229,37 @@ impl<'a> Control<'a> { } } +impl<'a, 'd> UpdateControl<'a, 'd> { + /// Write slice of firmware to a device. + /// + /// The slice is split into chunks that can be sent across + /// the ioctl protocol to the wifi adapter. + pub async fn write(&mut self, data: &[u8]) -> Result<(), Error> { + let this = &mut self.control; + for chunk in data.chunks(256) { + let req = proto::CtrlMsg_Req_OTAWrite { + ota_data: heapless::Vec::from_slice(chunk).unwrap(), + }; + ioctl!(this, ReqOtaWrite, RespOtaWrite, req, resp); + } + Ok(()) + } + + /// End the OTA session. + /// + /// NOTE: Will reset the wifi adapter after 5 seconds. + pub async fn finish(self) -> Result<(), Error> { + let this = self.control; + let req = proto::CtrlMsg_Req_OTAEnd {}; + ioctl!(this, ReqOtaEnd, RespOtaEnd, req, resp); + // Ensures that run loop awaits reset + this.shared.ota_done(); + // Wait for re-init + this.init().await?; + Ok(()) + } +} + // WHY IS THIS A STRING? WHYYYY fn parse_mac(mac: &str) -> Result<[u8; 6], Error> { fn nibble_from_hex(b: u8) -> Result { diff --git a/embassy-net-esp-hosted/src/ioctl.rs b/embassy-net-esp-hosted/src/ioctl.rs index a516f80c7..7f462d528 100644 --- a/embassy-net-esp-hosted/src/ioctl.rs +++ b/embassy-net-esp-hosted/src/ioctl.rs @@ -24,6 +24,7 @@ pub struct Shared(RefCell); struct SharedInner { ioctl: IoctlState, is_init: bool, + is_ota: bool, control_waker: WakerRegistration, runner_waker: WakerRegistration, } @@ -33,6 +34,7 @@ impl Shared { Self(RefCell::new(SharedInner { ioctl: IoctlState::Done { resp_len: 0 }, is_init: false, + is_ota: false, control_waker: WakerRegistration::new(), runner_waker: WakerRegistration::new(), })) @@ -99,11 +101,26 @@ impl Shared { } } + // ota + pub fn ota_done(&self) { + let mut this = self.0.borrow_mut(); + this.is_ota = true; + this.is_init = false; + this.runner_waker.wake(); + } + + // check if ota is in progress + pub fn is_ota(&self) -> bool { + let this = self.0.borrow(); + this.is_ota + } + // // // // // // // // // // // // // // // // // // // // pub fn init_done(&self) { let mut this = self.0.borrow_mut(); this.is_init = true; + this.is_ota = false; this.control_waker.wake(); } diff --git a/embassy-net-esp-hosted/src/lib.rs b/embassy-net-esp-hosted/src/lib.rs index d882af8cf..7236e73e8 100644 --- a/embassy-net-esp-hosted/src/lib.rs +++ b/embassy-net-esp-hosted/src/lib.rs @@ -234,6 +234,11 @@ where tx_buf[..PayloadHeader::SIZE].fill(0); } Either4::Fourth(()) => { + // Extend the deadline if OTA + if self.shared.is_ota() { + self.heartbeat_deadline = Instant::now() + HEARTBEAT_MAX_GAP; + continue; + } panic!("heartbeat from esp32 stopped") } } diff --git a/embassy-net-esp-hosted/src/proto.rs b/embassy-net-esp-hosted/src/proto.rs index 74c67bd61..09bec8984 100644 --- a/embassy-net-esp-hosted/src/proto.rs +++ b/embassy-net-esp-hosted/src/proto.rs @@ -16,7 +16,7 @@ Switch to a proper script when https://github.com/YuhanLiin/micropb/issues/30 is // Special config for things that need to be larger g.configure( ".CtrlMsg_Req_OTAWrite.ota_data", - micropb_gen::Config::new().max_bytes(1024), + micropb_gen::Config::new().max_bytes(256), ); g.configure( ".CtrlMsg_Event_ESPInit.init_data", @@ -4296,28 +4296,28 @@ impl ::micropb::MessageEncode for CtrlMsg_Resp_OTABegin { #[derive(Debug, Default, PartialEq, Clone)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct CtrlMsg_Req_OTAWrite { - pub r#ota_data: ::micropb::heapless::Vec, + pub r#ota_data: ::micropb::heapless::Vec, } impl CtrlMsg_Req_OTAWrite { ///Return a reference to `ota_data` #[inline] - pub fn r#ota_data(&self) -> &::micropb::heapless::Vec { + pub fn r#ota_data(&self) -> &::micropb::heapless::Vec { &self.r#ota_data } ///Return a mutable reference to `ota_data` #[inline] - pub fn mut_ota_data(&mut self) -> &mut ::micropb::heapless::Vec { + pub fn mut_ota_data(&mut self) -> &mut ::micropb::heapless::Vec { &mut self.r#ota_data } ///Set the value of `ota_data` #[inline] - pub fn set_ota_data(&mut self, value: ::micropb::heapless::Vec) -> &mut Self { + pub fn set_ota_data(&mut self, value: ::micropb::heapless::Vec) -> &mut Self { self.r#ota_data = value.into(); self } ///Builder method that sets the value of `ota_data`. Useful for initializing the message. #[inline] - pub fn init_ota_data(mut self, value: ::micropb::heapless::Vec) -> Self { + pub fn init_ota_data(mut self, value: ::micropb::heapless::Vec) -> Self { self.r#ota_data = value.into(); self } -- cgit From 741b09ac8a0cb47285568e4e317ef8e4f7ac566e Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Tue, 2 Dec 2025 11:51:46 +0100 Subject: chore: update changelog --- embassy-net-esp-hosted/CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/embassy-net-esp-hosted/CHANGELOG.md b/embassy-net-esp-hosted/CHANGELOG.md index d8b912295..6991b39fd 100644 --- a/embassy-net-esp-hosted/CHANGELOG.md +++ b/embassy-net-esp-hosted/CHANGELOG.md @@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Add an `Interface` trait to allow using other interface transports. - Switch to `micropb` for protobuf. - Update protos to latest `esp-hosted-fg`. +- Add support for OTA firmware updates. ## 0.2.1 - 2025-08-26 -- cgit From 4e56caa71035ab236b11b31af618a7ae45792358 Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Tue, 2 Dec 2025 12:30:53 +0100 Subject: chore: refactor api to allow other control commands --- embassy-net-esp-hosted/src/control.rs | 81 +++++++++++++++++++---------------- embassy-net-esp-hosted/src/ioctl.rs | 1 - embassy-net-esp-hosted/src/lib.rs | 3 +- 3 files changed, 47 insertions(+), 38 deletions(-) diff --git a/embassy-net-esp-hosted/src/control.rs b/embassy-net-esp-hosted/src/control.rs index d96a62daf..255ad7045 100644 --- a/embassy-net-esp-hosted/src/control.rs +++ b/embassy-net-esp-hosted/src/control.rs @@ -1,3 +1,4 @@ +use core::marker::PhantomData; use embassy_net_driver_channel as ch; use embassy_net_driver_channel::driver::{HardwareAddress, LinkState}; use heapless::String; @@ -24,9 +25,15 @@ pub struct Control<'a> { shared: &'a Shared, } -/// Handle for managing firmware update. -pub struct UpdateControl<'a, 'd> { - control: &'a mut Control<'d>, +/// Token required for doing an update +pub struct OtaToken { + _d: PhantomData<()>, +} + +impl OtaToken { + fn new() -> Self { + Self { _d: PhantomData } + } } /// WiFi mode. @@ -152,10 +159,43 @@ impl<'a> Control<'a> { } /// Initiate a firmware update. - pub async fn update(&mut self) -> Result, Error> { + /// + /// Returns a token needed for writing and finishing. + pub async fn ota_begin(&mut self) -> Result { let req = proto::CtrlMsg_Req_OTABegin {}; ioctl!(self, ReqOtaBegin, RespOtaBegin, req, resp); - Ok(UpdateControl { control: self }) + Ok(OtaToken::new()) + } + + /// Write slice of firmware to a device. + /// + /// Token is required as proof that ota_begin was called. + /// + /// The slice is split into chunks that can be sent across + /// the ioctl protocol to the wifi adapter. + pub async fn ota_write(&mut self, _token: &OtaToken, data: &[u8]) -> Result<(), Error> { + for chunk in data.chunks(256) { + let req = proto::CtrlMsg_Req_OTAWrite { + ota_data: heapless::Vec::from_slice(chunk).unwrap(), + }; + ioctl!(self, ReqOtaWrite, RespOtaWrite, req, resp); + } + Ok(()) + } + + /// End the OTA session. + /// + /// Token is required as proof that ota_begin was called. + /// + /// NOTE: Will reset the wifi adapter after 5 seconds. + pub async fn ota_end(&mut self, _token: OtaToken) -> Result<(), Error> { + let req = proto::CtrlMsg_Req_OTAEnd {}; + ioctl!(self, ReqOtaEnd, RespOtaEnd, req, resp); + // Ensures that run loop awaits reset + self.shared.ota_done(); + // Wait for re-init + self.init().await?; + Ok(()) } /// duration in seconds, clamped to [10, 3600] @@ -229,37 +269,6 @@ impl<'a> Control<'a> { } } -impl<'a, 'd> UpdateControl<'a, 'd> { - /// Write slice of firmware to a device. - /// - /// The slice is split into chunks that can be sent across - /// the ioctl protocol to the wifi adapter. - pub async fn write(&mut self, data: &[u8]) -> Result<(), Error> { - let this = &mut self.control; - for chunk in data.chunks(256) { - let req = proto::CtrlMsg_Req_OTAWrite { - ota_data: heapless::Vec::from_slice(chunk).unwrap(), - }; - ioctl!(this, ReqOtaWrite, RespOtaWrite, req, resp); - } - Ok(()) - } - - /// End the OTA session. - /// - /// NOTE: Will reset the wifi adapter after 5 seconds. - pub async fn finish(self) -> Result<(), Error> { - let this = self.control; - let req = proto::CtrlMsg_Req_OTAEnd {}; - ioctl!(this, ReqOtaEnd, RespOtaEnd, req, resp); - // Ensures that run loop awaits reset - this.shared.ota_done(); - // Wait for re-init - this.init().await?; - Ok(()) - } -} - // WHY IS THIS A STRING? WHYYYY fn parse_mac(mac: &str) -> Result<[u8; 6], Error> { fn nibble_from_hex(b: u8) -> Result { diff --git a/embassy-net-esp-hosted/src/ioctl.rs b/embassy-net-esp-hosted/src/ioctl.rs index 7f462d528..8b9d582be 100644 --- a/embassy-net-esp-hosted/src/ioctl.rs +++ b/embassy-net-esp-hosted/src/ioctl.rs @@ -106,7 +106,6 @@ impl Shared { let mut this = self.0.borrow_mut(); this.is_ota = true; this.is_init = false; - this.runner_waker.wake(); } // check if ota is in progress diff --git a/embassy-net-esp-hosted/src/lib.rs b/embassy-net-esp-hosted/src/lib.rs index 7236e73e8..f0cf04d04 100644 --- a/embassy-net-esp-hosted/src/lib.rs +++ b/embassy-net-esp-hosted/src/lib.rs @@ -238,8 +238,9 @@ where if self.shared.is_ota() { self.heartbeat_deadline = Instant::now() + HEARTBEAT_MAX_GAP; continue; + } else { + panic!("heartbeat from esp32 stopped") } - panic!("heartbeat from esp32 stopped") } } -- cgit From 4e69d44d184f4920f2f167a6ba9411cea0759dab Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Tue, 2 Dec 2025 12:53:42 +0100 Subject: chore: refactor to not use token --- embassy-net-esp-hosted/src/control.rs | 26 ++++++-------------------- 1 file changed, 6 insertions(+), 20 deletions(-) diff --git a/embassy-net-esp-hosted/src/control.rs b/embassy-net-esp-hosted/src/control.rs index 255ad7045..227db0d09 100644 --- a/embassy-net-esp-hosted/src/control.rs +++ b/embassy-net-esp-hosted/src/control.rs @@ -1,4 +1,3 @@ -use core::marker::PhantomData; use embassy_net_driver_channel as ch; use embassy_net_driver_channel::driver::{HardwareAddress, LinkState}; use heapless::String; @@ -25,17 +24,6 @@ pub struct Control<'a> { shared: &'a Shared, } -/// Token required for doing an update -pub struct OtaToken { - _d: PhantomData<()>, -} - -impl OtaToken { - fn new() -> Self { - Self { _d: PhantomData } - } -} - /// WiFi mode. #[allow(unused)] #[derive(Copy, Clone, PartialEq, Eq, Debug)] @@ -159,21 +147,19 @@ impl<'a> Control<'a> { } /// Initiate a firmware update. - /// - /// Returns a token needed for writing and finishing. - pub async fn ota_begin(&mut self) -> Result { + pub async fn ota_begin(&mut self) -> Result<(), Error> { let req = proto::CtrlMsg_Req_OTABegin {}; ioctl!(self, ReqOtaBegin, RespOtaBegin, req, resp); - Ok(OtaToken::new()) + Ok(()) } /// Write slice of firmware to a device. /// - /// Token is required as proof that ota_begin was called. + /// [`ota_begin`] must be called first. /// /// The slice is split into chunks that can be sent across /// the ioctl protocol to the wifi adapter. - pub async fn ota_write(&mut self, _token: &OtaToken, data: &[u8]) -> Result<(), Error> { + pub async fn ota_write(&mut self, data: &[u8]) -> Result<(), Error> { for chunk in data.chunks(256) { let req = proto::CtrlMsg_Req_OTAWrite { ota_data: heapless::Vec::from_slice(chunk).unwrap(), @@ -185,10 +171,10 @@ impl<'a> Control<'a> { /// End the OTA session. /// - /// Token is required as proof that ota_begin was called. + /// [`ota_begin`] must be called first. /// /// NOTE: Will reset the wifi adapter after 5 seconds. - pub async fn ota_end(&mut self, _token: OtaToken) -> Result<(), Error> { + pub async fn ota_end(&mut self) -> Result<(), Error> { let req = proto::CtrlMsg_Req_OTAEnd {}; ioctl!(self, ReqOtaEnd, RespOtaEnd, req, resp); // Ensures that run loop awaits reset -- cgit From 220e8b5973efe0562f5d96cdd92b87badd313f00 Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Tue, 2 Dec 2025 13:54:42 +0100 Subject: chore: unify ota and init states --- embassy-net-esp-hosted/src/control.rs | 1 - embassy-net-esp-hosted/src/ioctl.rs | 29 ++++++++++++++++------------- embassy-net-esp-hosted/src/lib.rs | 7 +++---- 3 files changed, 19 insertions(+), 18 deletions(-) diff --git a/embassy-net-esp-hosted/src/control.rs b/embassy-net-esp-hosted/src/control.rs index 227db0d09..eb79593f6 100644 --- a/embassy-net-esp-hosted/src/control.rs +++ b/embassy-net-esp-hosted/src/control.rs @@ -177,7 +177,6 @@ impl<'a> Control<'a> { pub async fn ota_end(&mut self) -> Result<(), Error> { let req = proto::CtrlMsg_Req_OTAEnd {}; ioctl!(self, ReqOtaEnd, RespOtaEnd, req, resp); - // Ensures that run loop awaits reset self.shared.ota_done(); // Wait for re-init self.init().await?; diff --git a/embassy-net-esp-hosted/src/ioctl.rs b/embassy-net-esp-hosted/src/ioctl.rs index 8b9d582be..de0f867e8 100644 --- a/embassy-net-esp-hosted/src/ioctl.rs +++ b/embassy-net-esp-hosted/src/ioctl.rs @@ -23,18 +23,23 @@ pub struct Shared(RefCell); struct SharedInner { ioctl: IoctlState, - is_init: bool, - is_ota: bool, + state: ControlState, control_waker: WakerRegistration, runner_waker: WakerRegistration, } +#[derive(Clone, Copy)] +pub(crate) enum ControlState { + Init, + Reboot, + Ready, +} + impl Shared { pub fn new() -> Self { Self(RefCell::new(SharedInner { ioctl: IoctlState::Done { resp_len: 0 }, - is_init: false, - is_ota: false, + state: ControlState::Init, control_waker: WakerRegistration::new(), runner_waker: WakerRegistration::new(), })) @@ -104,29 +109,27 @@ impl Shared { // ota pub fn ota_done(&self) { let mut this = self.0.borrow_mut(); - this.is_ota = true; - this.is_init = false; + this.state = ControlState::Reboot; } + // // // // // // // // // // // // // // // // // // // // + // // check if ota is in progress - pub fn is_ota(&self) -> bool { + pub(crate) fn state(&self) -> ControlState { let this = self.0.borrow(); - this.is_ota + this.state } - // // // // // // // // // // // // // // // // // // // // - pub fn init_done(&self) { let mut this = self.0.borrow_mut(); - this.is_init = true; - this.is_ota = false; + this.state = ControlState::Ready; this.control_waker.wake(); } pub fn init_wait(&self) -> impl Future + '_ { poll_fn(|cx| { let mut this = self.0.borrow_mut(); - if this.is_init { + if let ControlState::Ready = this.state { Poll::Ready(()) } else { this.control_waker.register(cx.waker()); diff --git a/embassy-net-esp-hosted/src/lib.rs b/embassy-net-esp-hosted/src/lib.rs index f0cf04d04..2c7377281 100644 --- a/embassy-net-esp-hosted/src/lib.rs +++ b/embassy-net-esp-hosted/src/lib.rs @@ -234,13 +234,12 @@ where tx_buf[..PayloadHeader::SIZE].fill(0); } Either4::Fourth(()) => { - // Extend the deadline if OTA - if self.shared.is_ota() { + // Extend the deadline if initializing + if let ioctl::ControlState::Reboot = self.shared.state() { self.heartbeat_deadline = Instant::now() + HEARTBEAT_MAX_GAP; continue; - } else { - panic!("heartbeat from esp32 stopped") } + panic!("heartbeat from esp32 stopped") } } -- cgit From acedd9bd830bdcfe255369718d0a5dcfd4c296fd Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Tue, 2 Dec 2025 14:46:43 +0100 Subject: chore: update nrf-pac --- embassy-net-nrf91/Cargo.toml | 2 +- embassy-nrf/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/embassy-net-nrf91/Cargo.toml b/embassy-net-nrf91/Cargo.toml index 8cf11f1fb..cd9bf2987 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 = "176dc4afe1dd8df78f3cbda4479ab5151aa32252" } +nrf-pac = { version = "0.1.0", git = "https://github.com/embassy-rs/nrf-pac.git", rev = "52fd51ce762a3d3a81660dea62947e6d2d1e9d91" } 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 f73772682..05c88509a 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 = "176dc4afe1dd8df78f3cbda4479ab5151aa32252" } +nrf-pac = { version = "0.1.0", git = "https://github.com/embassy-rs/nrf-pac.git", rev = "52fd51ce762a3d3a81660dea62947e6d2d1e9d91" } defmt = { version = "1.0.1", optional = true } bitflags = "2.4.2" -- cgit From 4880218d7df148ee76f227318388624157e8e2cc Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Tue, 2 Dec 2025 14:56:26 +0100 Subject: feat: support nrf54l10 and nrf54l05 in HAL --- embassy-nrf/Cargo.toml | 16 + embassy-nrf/src/chips/nrf54l05_app.rs | 746 ++++++++++++++++++++++++++++++++++ embassy-nrf/src/chips/nrf54l10_app.rs | 746 ++++++++++++++++++++++++++++++++++ embassy-nrf/src/lib.rs | 14 +- 4 files changed, 1520 insertions(+), 2 deletions(-) create mode 100644 embassy-nrf/src/chips/nrf54l05_app.rs create mode 100644 embassy-nrf/src/chips/nrf54l10_app.rs diff --git a/embassy-nrf/Cargo.toml b/embassy-nrf/Cargo.toml index 05c88509a..c51af59d2 100644 --- a/embassy-nrf/Cargo.toml +++ b/embassy-nrf/Cargo.toml @@ -25,6 +25,10 @@ build = [ {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-grtc"]}, {target = "thumbv8m.main-none-eabihf", features = ["gpiote", "nrf54l15-app-ns", "time", "time-driver-grtc"]}, + {target = "thumbv8m.main-none-eabihf", features = ["gpiote", "nrf54l10-app-s", "time", "time-driver-grtc"]}, + {target = "thumbv8m.main-none-eabihf", features = ["gpiote", "nrf54l10-app-ns", "time", "time-driver-grtc"]}, + {target = "thumbv8m.main-none-eabihf", features = ["gpiote", "nrf54l05-app-s", "time", "time-driver-grtc"]}, + {target = "thumbv8m.main-none-eabihf", features = ["gpiote", "nrf54l05-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"]}, @@ -130,6 +134,14 @@ nrf5340-net = ["_nrf5340-net"] nrf54l15-app-s = ["_nrf54l15-app", "_s", "_multi_wdt"] ## nRF54L15 application core in Non-Secure mode nrf54l15-app-ns = ["_nrf54l15-app", "_ns"] +## nRF54L10 application core in Secure mode +nrf54l10-app-s = ["_nrf54l10-app", "_s", "_multi_wdt"] +## nRF54L10 application core in Non-Secure mode +nrf54l10-app-ns = ["_nrf54l10-app", "_ns"] +## nRF54L05 application core in Secure mode +nrf54l05-app-s = ["_nrf54l05-app", "_s", "_multi_wdt"] +## nRF54L05 application core in Non-Secure mode +nrf54l05-app-ns = ["_nrf54l05-app", "_ns"] ## nRF9160 in Secure mode nrf9160-s = ["_nrf9160", "_s", "_nrf91"] @@ -153,6 +165,10 @@ _nrf5340-net = ["_nrf5340", "nrf-pac/nrf5340-net"] _nrf5340 = ["_gpio-p1", "_dppi"] _nrf54l15-app = ["_nrf54l15", "nrf-pac/nrf54l15-app"] _nrf54l15 = ["_nrf54l", "_gpio-p1", "_gpio-p2"] +_nrf54l10-app = ["_nrf54l10", "nrf-pac/nrf54l10-app"] +_nrf54l10 = ["_nrf54l", "_gpio-p1", "_gpio-p2"] +_nrf54l05-app = ["_nrf54l05", "nrf-pac/nrf54l05-app"] +_nrf54l05 = ["_nrf54l", "_gpio-p1", "_gpio-p2"] _nrf54l = ["_dppi", "_grtc"] _nrf9160 = ["nrf-pac/nrf9160", "_dppi", "_spi-v1"] diff --git a/embassy-nrf/src/chips/nrf54l05_app.rs b/embassy-nrf/src/chips/nrf54l05_app.rs new file mode 100644 index 000000000..8e6595248 --- /dev/null +++ b/embassy-nrf/src/chips/nrf54l05_app.rs @@ -0,0 +1,746 @@ +/// Peripheral Access Crate +#[allow(unused_imports)] +#[rustfmt::skip] +pub mod pac { + pub use nrf_pac::*; + + #[cfg(feature = "_ns")] + #[doc(no_inline)] + pub use nrf_pac::{ + FICR_NS as FICR, + DPPIC00_NS as DPPIC00, + PPIB00_NS as PPIB00, + PPIB01_NS as PPIB01, + AAR00_NS as AAR00, + CCM00_NS as CCM00, + ECB00_NS as ECB00, + SPIM00_NS as SPIM00, + SPIS00_NS as SPIS00, + UARTE00_NS as UARTE00, + VPR00_NS as VPR00, + P2_NS as P2, + CTRLAP_NS as CTRLAP, + TAD_NS as TAD, + TIMER00_NS as TIMER00, + DPPIC10_NS as DPPIC10, + PPIB10_NS as PPIB10, + PPIB11_NS as PPIB11, + TIMER10_NS as TIMER10, + EGU10_NS as EGU10, + RADIO_NS as RADIO, + DPPIC20_NS as DPPIC20, + PPIB20_NS as PPIB20, + PPIB21_NS as PPIB21, + PPIB22_NS as PPIB22, + SPIM20_NS as SPIM20, + SPIS20_NS as SPIS20, + TWIM20_NS as TWIM20, + TWIS20_NS as TWIS20, + UARTE20_NS as UARTE20, + SPIM21_NS as SPIM21, + SPIS21_NS as SPIS21, + TWIM21_NS as TWIM21, + TWIS21_NS as TWIS21, + UARTE21_NS as UARTE21, + SPIM22_NS as SPIM22, + SPIS22_NS as SPIS22, + TWIM22_NS as TWIM22, + TWIS22_NS as TWIS22, + UARTE22_NS as UARTE22, + EGU20_NS as EGU20, + TIMER20_NS as TIMER20, + TIMER21_NS as TIMER21, + TIMER22_NS as TIMER22, + TIMER23_NS as TIMER23, + TIMER24_NS as TIMER24, + MEMCONF_NS as MEMCONF, + PDM20_NS as PDM20, + PDM21_NS as PDM21, + PWM20_NS as PWM20, + PWM21_NS as PWM21, + PWM22_NS as PWM22, + SAADC_NS as SAADC, + NFCT_NS as NFCT, + TEMP_NS as TEMP, + P1_NS as P1, + GPIOTE20_NS as GPIOTE20, + I2S20_NS as I2S20, + QDEC20_NS as QDEC20, + QDEC21_NS as QDEC21, + GRTC_NS as GRTC, + DPPIC30_NS as DPPIC30, + PPIB30_NS as PPIB30, + SPIM30_NS as SPIM30, + SPIS30_NS as SPIS30, + TWIM30_NS as TWIM30, + TWIS30_NS as TWIS30, + UARTE30_NS as UARTE30, + COMP_NS as COMP, + LPCOMP_NS as LPCOMP, + WDT31_NS as WDT31, + P0_NS as P0, + GPIOTE30_NS as GPIOTE30, + CLOCK_NS as CLOCK, + POWER_NS as POWER, + RESET_NS as RESET, + OSCILLATORS_NS as OSCILLATORS, + REGULATORS_NS as REGULATORS, + TPIU_NS as TPIU, + ETM_NS as ETM, + }; + + #[cfg(feature = "_s")] + #[doc(no_inline)] + pub use nrf_pac::{ + FICR_NS as FICR, + SICR_S as SICR, + ICACHEDATA_S as ICACHEDATA, + ICACHEINFO_S as ICACHEINFO, + SWI00_S as SWI00, + SWI01_S as SWI01, + SWI02_S as SWI02, + SWI03_S as SWI03, + SPU00_S as SPU00, + MPC00_S as MPC00, + DPPIC00_S as DPPIC00, + PPIB00_S as PPIB00, + PPIB01_S as PPIB01, + KMU_S as KMU, + AAR00_S as AAR00, + CCM00_S as CCM00, + ECB00_S as ECB00, + CRACEN_S as CRACEN, + SPIM00_S as SPIM00, + SPIS00_S as SPIS00, + UARTE00_S as UARTE00, + GLITCHDET_S as GLITCHDET, + RRAMC_S as RRAMC, + VPR00_S as VPR00, + P2_S as P2, + CTRLAP_S as CTRLAP, + TAD_S as TAD, + TIMER00_S as TIMER00, + SPU10_S as SPU10, + DPPIC10_S as DPPIC10, + PPIB10_S as PPIB10, + PPIB11_S as PPIB11, + TIMER10_S as TIMER10, + EGU10_S as EGU10, + RADIO_S as RADIO, + SPU20_S as SPU20, + DPPIC20_S as DPPIC20, + PPIB20_S as PPIB20, + PPIB21_S as PPIB21, + PPIB22_S as PPIB22, + SPIM20_S as SPIM20, + SPIS20_S as SPIS20, + TWIM20_S as TWIM20, + TWIS20_S as TWIS20, + UARTE20_S as UARTE20, + SPIM21_S as SPIM21, + SPIS21_S as SPIS21, + TWIM21_S as TWIM21, + TWIS21_S as TWIS21, + UARTE21_S as UARTE21, + SPIM22_S as SPIM22, + SPIS22_S as SPIS22, + TWIM22_S as TWIM22, + TWIS22_S as TWIS22, + UARTE22_S as UARTE22, + EGU20_S as EGU20, + TIMER20_S as TIMER20, + TIMER21_S as TIMER21, + TIMER22_S as TIMER22, + TIMER23_S as TIMER23, + TIMER24_S as TIMER24, + MEMCONF_S as MEMCONF, + PDM20_S as PDM20, + PDM21_S as PDM21, + PWM20_S as PWM20, + PWM21_S as PWM21, + PWM22_S as PWM22, + SAADC_S as SAADC, + NFCT_S as NFCT, + TEMP_S as TEMP, + P1_S as P1, + GPIOTE20_S as GPIOTE20, + TAMPC_S as TAMPC, + I2S20_S as I2S20, + QDEC20_S as QDEC20, + QDEC21_S as QDEC21, + GRTC_S as GRTC, + SPU30_S as SPU30, + DPPIC30_S as DPPIC30, + PPIB30_S as PPIB30, + SPIM30_S as SPIM30, + SPIS30_S as SPIS30, + TWIM30_S as TWIM30, + TWIS30_S as TWIS30, + UARTE30_S as UARTE30, + COMP_S as COMP, + LPCOMP_S as LPCOMP, + WDT30_S as WDT30, + WDT31_S as WDT31, + P0_S as P0, + GPIOTE30_S as GPIOTE30, + CLOCK_S as CLOCK, + POWER_S as POWER, + RESET_S as RESET, + OSCILLATORS_S as OSCILLATORS, + REGULATORS_S as REGULATORS, + CRACENCORE_S as CRACENCORE, + CPUC_S as CPUC, + ICACHE_S as ICACHE, + }; +} + +/// The maximum buffer size that the EasyDMA can send/recv in one operation. +pub const EASY_DMA_SIZE: usize = (1 << 16) - 1; +pub const FORCE_COPY_BUFFER_SIZE: usize = 1024; + +// 1.5 MB NVM +#[allow(unused)] +pub const FLASH_SIZE: usize = 1524 * 1024; + +embassy_hal_internal::peripherals! { + // PPI + PPI00_CH0, + PPI00_CH1, + PPI00_CH2, + PPI00_CH3, + PPI00_CH4, + PPI00_CH5, + PPI00_CH6, + PPI00_CH7, + + PPI10_CH0, + PPI10_CH1, + PPI10_CH2, + PPI10_CH3, + PPI10_CH4, + PPI10_CH5, + PPI10_CH6, + PPI10_CH7, + PPI10_CH8, + PPI10_CH9, + PPI10_CH10, + PPI10_CH11, + PPI10_CH12, + PPI10_CH13, + PPI10_CH14, + PPI10_CH15, + PPI10_CH16, + PPI10_CH17, + PPI10_CH18, + PPI10_CH19, + PPI10_CH20, + PPI10_CH21, + PPI10_CH22, + PPI10_CH23, + + PPI20_CH0, + PPI20_CH1, + PPI20_CH2, + PPI20_CH3, + PPI20_CH4, + PPI20_CH5, + PPI20_CH6, + PPI20_CH7, + PPI20_CH8, + PPI20_CH9, + PPI20_CH10, + PPI20_CH11, + PPI20_CH12, + PPI20_CH13, + PPI20_CH14, + PPI20_CH15, + + PPI30_CH0, + PPI30_CH1, + PPI30_CH2, + PPI30_CH3, + + PPI00_GROUP0, + PPI00_GROUP1, + + PPI10_GROUP0, + PPI10_GROUP1, + PPI10_GROUP2, + PPI10_GROUP3, + PPI10_GROUP4, + PPI10_GROUP5, + + PPI20_GROUP0, + PPI20_GROUP1, + PPI20_GROUP2, + PPI20_GROUP3, + PPI20_GROUP4, + PPI20_GROUP5, + + PPI30_GROUP0, + PPI30_GROUP1, + + // PPI BRIDGE channels + PPIB00_CH0, + PPIB00_CH1, + PPIB00_CH2, + PPIB00_CH3, + PPIB00_CH4, + PPIB00_CH5, + PPIB00_CH6, + PPIB00_CH7, + + PPIB01_CH0, + PPIB01_CH1, + PPIB01_CH2, + PPIB01_CH3, + PPIB01_CH4, + PPIB01_CH5, + PPIB01_CH6, + PPIB01_CH7, + + PPIB10_CH0, + PPIB10_CH1, + PPIB10_CH2, + PPIB10_CH3, + PPIB10_CH4, + PPIB10_CH5, + PPIB10_CH6, + PPIB10_CH7, + + PPIB11_CH0, + PPIB11_CH1, + PPIB11_CH2, + PPIB11_CH3, + PPIB11_CH4, + PPIB11_CH5, + PPIB11_CH6, + PPIB11_CH7, + PPIB11_CH8, + PPIB11_CH9, + PPIB11_CH10, + PPIB11_CH11, + PPIB11_CH12, + PPIB11_CH13, + PPIB11_CH14, + PPIB11_CH15, + + PPIB20_CH0, + PPIB20_CH1, + PPIB20_CH2, + PPIB20_CH3, + PPIB20_CH4, + PPIB20_CH5, + PPIB20_CH6, + PPIB20_CH7, + + PPIB21_CH0, + PPIB21_CH1, + PPIB21_CH2, + PPIB21_CH3, + PPIB21_CH4, + PPIB21_CH5, + PPIB21_CH6, + PPIB21_CH7, + PPIB21_CH8, + PPIB21_CH9, + PPIB21_CH10, + PPIB21_CH11, + PPIB21_CH12, + PPIB21_CH13, + PPIB21_CH14, + PPIB21_CH15, + + PPIB22_CH0, + PPIB22_CH1, + PPIB22_CH2, + PPIB22_CH3, + + PPIB30_CH0, + PPIB30_CH1, + PPIB30_CH2, + PPIB30_CH3, + + // Timers + TIMER00, + TIMER10, + TIMER20, + TIMER21, + TIMER22, + TIMER23, + TIMER24, + + // GPIO port 0 + P0_00, + P0_01, + P0_02, + P0_03, + P0_04, + P0_05, + P0_06, + + // GPIO port 1 + P1_00, + P1_01, + P1_02, + P1_03, + P1_04, + P1_05, + P1_06, + P1_07, + P1_08, + P1_09, + P1_10, + P1_11, + P1_12, + P1_13, + P1_14, + P1_15, + P1_16, + + + // GPIO port 2 + P2_00, + P2_01, + P2_02, + P2_03, + P2_04, + P2_05, + P2_06, + P2_07, + P2_08, + P2_09, + P2_10, + + // GRTC + 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, + PWM21, + PWM22, + + // SERIAL + SERIAL00, + SERIAL20, + SERIAL21, + SERIAL22, + SERIAL30, + + // SAADC + SAADC, + + // RADIO + RADIO, + + + // GPIOTE instances + GPIOTE20, + GPIOTE30, + + // GPIOTE channels + GPIOTE20_CH0, + GPIOTE20_CH1, + GPIOTE20_CH2, + GPIOTE20_CH3, + GPIOTE20_CH4, + GPIOTE20_CH5, + GPIOTE20_CH6, + GPIOTE20_CH7, + GPIOTE30_CH0, + GPIOTE30_CH1, + GPIOTE30_CH2, + GPIOTE30_CH3, + + // CRACEN + #[cfg(feature = "_s")] + CRACEN, + + #[cfg(feature = "_s")] + // RRAMC + RRAMC, + + // TEMP + TEMP, + + // WDT + #[cfg(feature = "_ns")] + WDT, + #[cfg(feature = "_s")] + WDT0, + #[cfg(feature = "_s")] + WDT1, +} + +impl_pin!(P0_00, 0, 0); +impl_pin!(P0_01, 0, 1); +impl_pin!(P0_02, 0, 2); +impl_pin!(P0_03, 0, 3); +impl_pin!(P0_04, 0, 4); +impl_pin!(P0_05, 0, 5); +impl_pin!(P0_06, 0, 6); + +impl_pin!(P1_00, 1, 0); +impl_pin!(P1_01, 1, 1); +impl_pin!(P1_02, 1, 2); +impl_pin!(P1_03, 1, 3); +impl_pin!(P1_04, 1, 4); +impl_pin!(P1_05, 1, 5); +impl_pin!(P1_06, 1, 6); +impl_pin!(P1_07, 1, 7); +impl_pin!(P1_08, 1, 8); +impl_pin!(P1_09, 1, 9); +impl_pin!(P1_10, 1, 10); +impl_pin!(P1_11, 1, 11); +impl_pin!(P1_12, 1, 12); +impl_pin!(P1_13, 1, 13); +impl_pin!(P1_14, 1, 14); +impl_pin!(P1_15, 1, 15); +impl_pin!(P1_16, 1, 16); + +impl_pin!(P2_00, 2, 0); +impl_pin!(P2_01, 2, 1); +impl_pin!(P2_02, 2, 2); +impl_pin!(P2_03, 2, 3); +impl_pin!(P2_04, 2, 4); +impl_pin!(P2_05, 2, 5); +impl_pin!(P2_06, 2, 6); +impl_pin!(P2_07, 2, 7); +impl_pin!(P2_08, 2, 8); +impl_pin!(P2_09, 2, 9); +impl_pin!(P2_10, 2, 10); + +cfg_if::cfg_if! { + if #[cfg(feature = "gpiote")] { + impl_gpiote_pin!(P0_00, GPIOTE30); + impl_gpiote_pin!(P0_01, GPIOTE30); + impl_gpiote_pin!(P0_02, GPIOTE30); + impl_gpiote_pin!(P0_03, GPIOTE30); + impl_gpiote_pin!(P0_04, GPIOTE30); + impl_gpiote_pin!(P0_05, GPIOTE30); + impl_gpiote_pin!(P0_06, GPIOTE30); + + impl_gpiote_pin!(P1_00, GPIOTE20); + impl_gpiote_pin!(P1_01, GPIOTE20); + impl_gpiote_pin!(P1_02, GPIOTE20); + impl_gpiote_pin!(P1_03, GPIOTE20); + impl_gpiote_pin!(P1_04, GPIOTE20); + impl_gpiote_pin!(P1_05, GPIOTE20); + impl_gpiote_pin!(P1_06, GPIOTE20); + impl_gpiote_pin!(P1_07, GPIOTE20); + impl_gpiote_pin!(P1_08, GPIOTE20); + impl_gpiote_pin!(P1_09, GPIOTE20); + impl_gpiote_pin!(P1_10, GPIOTE20); + impl_gpiote_pin!(P1_11, GPIOTE20); + impl_gpiote_pin!(P1_12, GPIOTE20); + impl_gpiote_pin!(P1_13, GPIOTE20); + impl_gpiote_pin!(P1_14, GPIOTE20); + impl_gpiote_pin!(P1_15, GPIOTE20); + impl_gpiote_pin!(P1_16, GPIOTE20); + } +} + +#[cfg(feature = "_ns")] +impl_wdt!(WDT, WDT31, WDT31, 0); +#[cfg(feature = "_s")] +impl_wdt!(WDT0, WDT31, WDT31, 0); +#[cfg(feature = "_s")] +impl_wdt!(WDT1, WDT30, WDT30, 1); +// DPPI00 channels +impl_ppi_channel!(PPI00_CH0, DPPIC00, 0 => configurable); +impl_ppi_channel!(PPI00_CH1, DPPIC00, 1 => configurable); +impl_ppi_channel!(PPI00_CH2, DPPIC00, 2 => configurable); +impl_ppi_channel!(PPI00_CH3, DPPIC00, 3 => configurable); +impl_ppi_channel!(PPI00_CH4, DPPIC00, 4 => configurable); +impl_ppi_channel!(PPI00_CH5, DPPIC00, 5 => configurable); +impl_ppi_channel!(PPI00_CH6, DPPIC00, 6 => configurable); +impl_ppi_channel!(PPI00_CH7, DPPIC00, 7 => configurable); + +// DPPI10 channels +impl_ppi_channel!(PPI10_CH0, DPPIC10, 0 => static); + +// DPPI20 channels +impl_ppi_channel!(PPI20_CH0, DPPIC20, 0 => configurable); +impl_ppi_channel!(PPI20_CH1, DPPIC20, 1 => configurable); +impl_ppi_channel!(PPI20_CH2, DPPIC20, 2 => configurable); +impl_ppi_channel!(PPI20_CH3, DPPIC20, 3 => configurable); +impl_ppi_channel!(PPI20_CH4, DPPIC20, 4 => configurable); +impl_ppi_channel!(PPI20_CH5, DPPIC20, 5 => configurable); +impl_ppi_channel!(PPI20_CH6, DPPIC20, 6 => configurable); +impl_ppi_channel!(PPI20_CH7, DPPIC20, 7 => configurable); +impl_ppi_channel!(PPI20_CH8, DPPIC20, 8 => configurable); +impl_ppi_channel!(PPI20_CH9, DPPIC20, 9 => configurable); +impl_ppi_channel!(PPI20_CH10, DPPIC20, 10 => configurable); +impl_ppi_channel!(PPI20_CH11, DPPIC20, 11 => configurable); +impl_ppi_channel!(PPI20_CH12, DPPIC20, 12 => configurable); +impl_ppi_channel!(PPI20_CH13, DPPIC20, 13 => configurable); +impl_ppi_channel!(PPI20_CH14, DPPIC20, 14 => configurable); +impl_ppi_channel!(PPI20_CH15, DPPIC20, 15 => configurable); + +// DPPI30 channels +impl_ppi_channel!(PPI30_CH0, DPPIC30, 0 => configurable); +impl_ppi_channel!(PPI30_CH1, DPPIC30, 1 => configurable); +impl_ppi_channel!(PPI30_CH2, DPPIC30, 2 => configurable); +impl_ppi_channel!(PPI30_CH3, DPPIC30, 3 => configurable); + +// DPPI00 groups +impl_ppi_group!(PPI00_GROUP0, DPPIC00, 0); +impl_ppi_group!(PPI00_GROUP1, DPPIC00, 1); + +// DPPI10 groups +impl_ppi_group!(PPI10_GROUP0, DPPIC10, 0); + +// DPPI20 groups +impl_ppi_group!(PPI20_GROUP0, DPPIC20, 0); +impl_ppi_group!(PPI20_GROUP1, DPPIC20, 1); +impl_ppi_group!(PPI20_GROUP2, DPPIC20, 2); +impl_ppi_group!(PPI20_GROUP3, DPPIC20, 3); +impl_ppi_group!(PPI20_GROUP4, DPPIC20, 4); +impl_ppi_group!(PPI20_GROUP5, DPPIC20, 5); + +// DPPI30 groups +impl_ppi_group!(PPI30_GROUP0, DPPIC30, 0); +impl_ppi_group!(PPI30_GROUP1, DPPIC30, 1); + +impl_timer!(TIMER00, TIMER00, TIMER00); +impl_timer!(TIMER10, TIMER10, TIMER10); +impl_timer!(TIMER20, TIMER20, TIMER20); +impl_timer!(TIMER21, TIMER21, TIMER21); +impl_timer!(TIMER22, TIMER22, TIMER22); +impl_timer!(TIMER23, TIMER23, TIMER23); +impl_timer!(TIMER24, TIMER24, TIMER24); + +impl_twim!(SERIAL20, TWIM20, SERIAL20); +impl_twim!(SERIAL21, TWIM21, SERIAL21); +impl_twim!(SERIAL22, TWIM22, SERIAL22); +impl_twim!(SERIAL30, TWIM30, SERIAL30); + +impl_twis!(SERIAL20, TWIS20, SERIAL20); +impl_twis!(SERIAL21, TWIS21, SERIAL21); +impl_twis!(SERIAL22, TWIS22, SERIAL22); +impl_twis!(SERIAL30, TWIS30, SERIAL30); + +impl_pwm!(PWM20, PWM20, PWM20); +impl_pwm!(PWM21, PWM21, PWM21); +impl_pwm!(PWM22, PWM22, PWM22); + +#[cfg(feature = "_s")] +impl_spim!( + SERIAL00, + SPIM00, + SERIAL00, + match pac::OSCILLATORS_S.pll().currentfreq().read().currentfreq() { + pac::oscillators::vals::Currentfreq::CK128M => 128_000_000, + pac::oscillators::vals::Currentfreq::CK64M => 64_000_000, + _ => unreachable!(), + } +); +#[cfg(feature = "_ns")] +impl_spim!( + SERIAL00, + SPIM00, + SERIAL00, + match pac::OSCILLATORS_NS.pll().currentfreq().read().currentfreq() { + pac::oscillators::vals::Currentfreq::CK128M => 128_000_000, + pac::oscillators::vals::Currentfreq::CK64M => 64_000_000, + _ => unreachable!(), + } +); +impl_spim!(SERIAL20, SPIM20, SERIAL20, 16_000_000); +impl_spim!(SERIAL21, SPIM21, SERIAL21, 16_000_000); +impl_spim!(SERIAL22, SPIM22, SERIAL22, 16_000_000); +impl_spim!(SERIAL30, SPIM30, SERIAL30, 16_000_000); + +impl_spis!(SERIAL20, SPIS20, SERIAL20); +impl_spis!(SERIAL21, SPIS21, SERIAL21); +impl_spis!(SERIAL22, SPIS22, SERIAL22); +impl_spis!(SERIAL30, SPIS30, SERIAL30); + +impl_uarte!(SERIAL00, UARTE00, SERIAL00); +impl_uarte!(SERIAL20, UARTE20, SERIAL20); +impl_uarte!(SERIAL21, UARTE21, SERIAL21); +impl_uarte!(SERIAL22, UARTE22, SERIAL22); +impl_uarte!(SERIAL30, UARTE30, SERIAL30); + +// NB: SAADC uses "pin" abstraction, not "AIN" +impl_saadc_input!(P1_04, 1, 4); +impl_saadc_input!(P1_05, 1, 5); +impl_saadc_input!(P1_06, 1, 6); +impl_saadc_input!(P1_07, 1, 7); +impl_saadc_input!(P1_11, 1, 11); +impl_saadc_input!(P1_12, 1, 12); +impl_saadc_input!(P1_13, 1, 13); +impl_saadc_input!(P1_14, 1, 14); + +#[cfg(feature = "_s")] +impl_cracen!(CRACEN, CRACEN, CRACEN); + +embassy_hal_internal::interrupt_mod!( + SWI00, + SWI01, + SWI02, + SWI03, + SPU00, + MPC00, + AAR00_CCM00, + ECB00, + CRACEN, + SERIAL00, + RRAMC, + VPR00, + CTRLAP, + TIMER00, + SPU10, + TIMER10, + EGU10, + RADIO_0, + RADIO_1, + SPU20, + SERIAL20, + SERIAL21, + SERIAL22, + EGU20, + TIMER20, + TIMER21, + TIMER22, + TIMER23, + TIMER24, + PDM20, + PDM21, + PWM20, + PWM21, + PWM22, + SAADC, + NFCT, + TEMP, + GPIOTE20_0, + GPIOTE20_1, + TAMPC, + I2S20, + QDEC20, + QDEC21, + GRTC_0, + GRTC_1, + GRTC_2, + GRTC_3, + SPU30, + SERIAL30, + COMP_LPCOMP, + WDT30, + WDT31, + GPIOTE30_0, + GPIOTE30_1, + CLOCK_POWER, +); diff --git a/embassy-nrf/src/chips/nrf54l10_app.rs b/embassy-nrf/src/chips/nrf54l10_app.rs new file mode 100644 index 000000000..8e6595248 --- /dev/null +++ b/embassy-nrf/src/chips/nrf54l10_app.rs @@ -0,0 +1,746 @@ +/// Peripheral Access Crate +#[allow(unused_imports)] +#[rustfmt::skip] +pub mod pac { + pub use nrf_pac::*; + + #[cfg(feature = "_ns")] + #[doc(no_inline)] + pub use nrf_pac::{ + FICR_NS as FICR, + DPPIC00_NS as DPPIC00, + PPIB00_NS as PPIB00, + PPIB01_NS as PPIB01, + AAR00_NS as AAR00, + CCM00_NS as CCM00, + ECB00_NS as ECB00, + SPIM00_NS as SPIM00, + SPIS00_NS as SPIS00, + UARTE00_NS as UARTE00, + VPR00_NS as VPR00, + P2_NS as P2, + CTRLAP_NS as CTRLAP, + TAD_NS as TAD, + TIMER00_NS as TIMER00, + DPPIC10_NS as DPPIC10, + PPIB10_NS as PPIB10, + PPIB11_NS as PPIB11, + TIMER10_NS as TIMER10, + EGU10_NS as EGU10, + RADIO_NS as RADIO, + DPPIC20_NS as DPPIC20, + PPIB20_NS as PPIB20, + PPIB21_NS as PPIB21, + PPIB22_NS as PPIB22, + SPIM20_NS as SPIM20, + SPIS20_NS as SPIS20, + TWIM20_NS as TWIM20, + TWIS20_NS as TWIS20, + UARTE20_NS as UARTE20, + SPIM21_NS as SPIM21, + SPIS21_NS as SPIS21, + TWIM21_NS as TWIM21, + TWIS21_NS as TWIS21, + UARTE21_NS as UARTE21, + SPIM22_NS as SPIM22, + SPIS22_NS as SPIS22, + TWIM22_NS as TWIM22, + TWIS22_NS as TWIS22, + UARTE22_NS as UARTE22, + EGU20_NS as EGU20, + TIMER20_NS as TIMER20, + TIMER21_NS as TIMER21, + TIMER22_NS as TIMER22, + TIMER23_NS as TIMER23, + TIMER24_NS as TIMER24, + MEMCONF_NS as MEMCONF, + PDM20_NS as PDM20, + PDM21_NS as PDM21, + PWM20_NS as PWM20, + PWM21_NS as PWM21, + PWM22_NS as PWM22, + SAADC_NS as SAADC, + NFCT_NS as NFCT, + TEMP_NS as TEMP, + P1_NS as P1, + GPIOTE20_NS as GPIOTE20, + I2S20_NS as I2S20, + QDEC20_NS as QDEC20, + QDEC21_NS as QDEC21, + GRTC_NS as GRTC, + DPPIC30_NS as DPPIC30, + PPIB30_NS as PPIB30, + SPIM30_NS as SPIM30, + SPIS30_NS as SPIS30, + TWIM30_NS as TWIM30, + TWIS30_NS as TWIS30, + UARTE30_NS as UARTE30, + COMP_NS as COMP, + LPCOMP_NS as LPCOMP, + WDT31_NS as WDT31, + P0_NS as P0, + GPIOTE30_NS as GPIOTE30, + CLOCK_NS as CLOCK, + POWER_NS as POWER, + RESET_NS as RESET, + OSCILLATORS_NS as OSCILLATORS, + REGULATORS_NS as REGULATORS, + TPIU_NS as TPIU, + ETM_NS as ETM, + }; + + #[cfg(feature = "_s")] + #[doc(no_inline)] + pub use nrf_pac::{ + FICR_NS as FICR, + SICR_S as SICR, + ICACHEDATA_S as ICACHEDATA, + ICACHEINFO_S as ICACHEINFO, + SWI00_S as SWI00, + SWI01_S as SWI01, + SWI02_S as SWI02, + SWI03_S as SWI03, + SPU00_S as SPU00, + MPC00_S as MPC00, + DPPIC00_S as DPPIC00, + PPIB00_S as PPIB00, + PPIB01_S as PPIB01, + KMU_S as KMU, + AAR00_S as AAR00, + CCM00_S as CCM00, + ECB00_S as ECB00, + CRACEN_S as CRACEN, + SPIM00_S as SPIM00, + SPIS00_S as SPIS00, + UARTE00_S as UARTE00, + GLITCHDET_S as GLITCHDET, + RRAMC_S as RRAMC, + VPR00_S as VPR00, + P2_S as P2, + CTRLAP_S as CTRLAP, + TAD_S as TAD, + TIMER00_S as TIMER00, + SPU10_S as SPU10, + DPPIC10_S as DPPIC10, + PPIB10_S as PPIB10, + PPIB11_S as PPIB11, + TIMER10_S as TIMER10, + EGU10_S as EGU10, + RADIO_S as RADIO, + SPU20_S as SPU20, + DPPIC20_S as DPPIC20, + PPIB20_S as PPIB20, + PPIB21_S as PPIB21, + PPIB22_S as PPIB22, + SPIM20_S as SPIM20, + SPIS20_S as SPIS20, + TWIM20_S as TWIM20, + TWIS20_S as TWIS20, + UARTE20_S as UARTE20, + SPIM21_S as SPIM21, + SPIS21_S as SPIS21, + TWIM21_S as TWIM21, + TWIS21_S as TWIS21, + UARTE21_S as UARTE21, + SPIM22_S as SPIM22, + SPIS22_S as SPIS22, + TWIM22_S as TWIM22, + TWIS22_S as TWIS22, + UARTE22_S as UARTE22, + EGU20_S as EGU20, + TIMER20_S as TIMER20, + TIMER21_S as TIMER21, + TIMER22_S as TIMER22, + TIMER23_S as TIMER23, + TIMER24_S as TIMER24, + MEMCONF_S as MEMCONF, + PDM20_S as PDM20, + PDM21_S as PDM21, + PWM20_S as PWM20, + PWM21_S as PWM21, + PWM22_S as PWM22, + SAADC_S as SAADC, + NFCT_S as NFCT, + TEMP_S as TEMP, + P1_S as P1, + GPIOTE20_S as GPIOTE20, + TAMPC_S as TAMPC, + I2S20_S as I2S20, + QDEC20_S as QDEC20, + QDEC21_S as QDEC21, + GRTC_S as GRTC, + SPU30_S as SPU30, + DPPIC30_S as DPPIC30, + PPIB30_S as PPIB30, + SPIM30_S as SPIM30, + SPIS30_S as SPIS30, + TWIM30_S as TWIM30, + TWIS30_S as TWIS30, + UARTE30_S as UARTE30, + COMP_S as COMP, + LPCOMP_S as LPCOMP, + WDT30_S as WDT30, + WDT31_S as WDT31, + P0_S as P0, + GPIOTE30_S as GPIOTE30, + CLOCK_S as CLOCK, + POWER_S as POWER, + RESET_S as RESET, + OSCILLATORS_S as OSCILLATORS, + REGULATORS_S as REGULATORS, + CRACENCORE_S as CRACENCORE, + CPUC_S as CPUC, + ICACHE_S as ICACHE, + }; +} + +/// The maximum buffer size that the EasyDMA can send/recv in one operation. +pub const EASY_DMA_SIZE: usize = (1 << 16) - 1; +pub const FORCE_COPY_BUFFER_SIZE: usize = 1024; + +// 1.5 MB NVM +#[allow(unused)] +pub const FLASH_SIZE: usize = 1524 * 1024; + +embassy_hal_internal::peripherals! { + // PPI + PPI00_CH0, + PPI00_CH1, + PPI00_CH2, + PPI00_CH3, + PPI00_CH4, + PPI00_CH5, + PPI00_CH6, + PPI00_CH7, + + PPI10_CH0, + PPI10_CH1, + PPI10_CH2, + PPI10_CH3, + PPI10_CH4, + PPI10_CH5, + PPI10_CH6, + PPI10_CH7, + PPI10_CH8, + PPI10_CH9, + PPI10_CH10, + PPI10_CH11, + PPI10_CH12, + PPI10_CH13, + PPI10_CH14, + PPI10_CH15, + PPI10_CH16, + PPI10_CH17, + PPI10_CH18, + PPI10_CH19, + PPI10_CH20, + PPI10_CH21, + PPI10_CH22, + PPI10_CH23, + + PPI20_CH0, + PPI20_CH1, + PPI20_CH2, + PPI20_CH3, + PPI20_CH4, + PPI20_CH5, + PPI20_CH6, + PPI20_CH7, + PPI20_CH8, + PPI20_CH9, + PPI20_CH10, + PPI20_CH11, + PPI20_CH12, + PPI20_CH13, + PPI20_CH14, + PPI20_CH15, + + PPI30_CH0, + PPI30_CH1, + PPI30_CH2, + PPI30_CH3, + + PPI00_GROUP0, + PPI00_GROUP1, + + PPI10_GROUP0, + PPI10_GROUP1, + PPI10_GROUP2, + PPI10_GROUP3, + PPI10_GROUP4, + PPI10_GROUP5, + + PPI20_GROUP0, + PPI20_GROUP1, + PPI20_GROUP2, + PPI20_GROUP3, + PPI20_GROUP4, + PPI20_GROUP5, + + PPI30_GROUP0, + PPI30_GROUP1, + + // PPI BRIDGE channels + PPIB00_CH0, + PPIB00_CH1, + PPIB00_CH2, + PPIB00_CH3, + PPIB00_CH4, + PPIB00_CH5, + PPIB00_CH6, + PPIB00_CH7, + + PPIB01_CH0, + PPIB01_CH1, + PPIB01_CH2, + PPIB01_CH3, + PPIB01_CH4, + PPIB01_CH5, + PPIB01_CH6, + PPIB01_CH7, + + PPIB10_CH0, + PPIB10_CH1, + PPIB10_CH2, + PPIB10_CH3, + PPIB10_CH4, + PPIB10_CH5, + PPIB10_CH6, + PPIB10_CH7, + + PPIB11_CH0, + PPIB11_CH1, + PPIB11_CH2, + PPIB11_CH3, + PPIB11_CH4, + PPIB11_CH5, + PPIB11_CH6, + PPIB11_CH7, + PPIB11_CH8, + PPIB11_CH9, + PPIB11_CH10, + PPIB11_CH11, + PPIB11_CH12, + PPIB11_CH13, + PPIB11_CH14, + PPIB11_CH15, + + PPIB20_CH0, + PPIB20_CH1, + PPIB20_CH2, + PPIB20_CH3, + PPIB20_CH4, + PPIB20_CH5, + PPIB20_CH6, + PPIB20_CH7, + + PPIB21_CH0, + PPIB21_CH1, + PPIB21_CH2, + PPIB21_CH3, + PPIB21_CH4, + PPIB21_CH5, + PPIB21_CH6, + PPIB21_CH7, + PPIB21_CH8, + PPIB21_CH9, + PPIB21_CH10, + PPIB21_CH11, + PPIB21_CH12, + PPIB21_CH13, + PPIB21_CH14, + PPIB21_CH15, + + PPIB22_CH0, + PPIB22_CH1, + PPIB22_CH2, + PPIB22_CH3, + + PPIB30_CH0, + PPIB30_CH1, + PPIB30_CH2, + PPIB30_CH3, + + // Timers + TIMER00, + TIMER10, + TIMER20, + TIMER21, + TIMER22, + TIMER23, + TIMER24, + + // GPIO port 0 + P0_00, + P0_01, + P0_02, + P0_03, + P0_04, + P0_05, + P0_06, + + // GPIO port 1 + P1_00, + P1_01, + P1_02, + P1_03, + P1_04, + P1_05, + P1_06, + P1_07, + P1_08, + P1_09, + P1_10, + P1_11, + P1_12, + P1_13, + P1_14, + P1_15, + P1_16, + + + // GPIO port 2 + P2_00, + P2_01, + P2_02, + P2_03, + P2_04, + P2_05, + P2_06, + P2_07, + P2_08, + P2_09, + P2_10, + + // GRTC + 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, + PWM21, + PWM22, + + // SERIAL + SERIAL00, + SERIAL20, + SERIAL21, + SERIAL22, + SERIAL30, + + // SAADC + SAADC, + + // RADIO + RADIO, + + + // GPIOTE instances + GPIOTE20, + GPIOTE30, + + // GPIOTE channels + GPIOTE20_CH0, + GPIOTE20_CH1, + GPIOTE20_CH2, + GPIOTE20_CH3, + GPIOTE20_CH4, + GPIOTE20_CH5, + GPIOTE20_CH6, + GPIOTE20_CH7, + GPIOTE30_CH0, + GPIOTE30_CH1, + GPIOTE30_CH2, + GPIOTE30_CH3, + + // CRACEN + #[cfg(feature = "_s")] + CRACEN, + + #[cfg(feature = "_s")] + // RRAMC + RRAMC, + + // TEMP + TEMP, + + // WDT + #[cfg(feature = "_ns")] + WDT, + #[cfg(feature = "_s")] + WDT0, + #[cfg(feature = "_s")] + WDT1, +} + +impl_pin!(P0_00, 0, 0); +impl_pin!(P0_01, 0, 1); +impl_pin!(P0_02, 0, 2); +impl_pin!(P0_03, 0, 3); +impl_pin!(P0_04, 0, 4); +impl_pin!(P0_05, 0, 5); +impl_pin!(P0_06, 0, 6); + +impl_pin!(P1_00, 1, 0); +impl_pin!(P1_01, 1, 1); +impl_pin!(P1_02, 1, 2); +impl_pin!(P1_03, 1, 3); +impl_pin!(P1_04, 1, 4); +impl_pin!(P1_05, 1, 5); +impl_pin!(P1_06, 1, 6); +impl_pin!(P1_07, 1, 7); +impl_pin!(P1_08, 1, 8); +impl_pin!(P1_09, 1, 9); +impl_pin!(P1_10, 1, 10); +impl_pin!(P1_11, 1, 11); +impl_pin!(P1_12, 1, 12); +impl_pin!(P1_13, 1, 13); +impl_pin!(P1_14, 1, 14); +impl_pin!(P1_15, 1, 15); +impl_pin!(P1_16, 1, 16); + +impl_pin!(P2_00, 2, 0); +impl_pin!(P2_01, 2, 1); +impl_pin!(P2_02, 2, 2); +impl_pin!(P2_03, 2, 3); +impl_pin!(P2_04, 2, 4); +impl_pin!(P2_05, 2, 5); +impl_pin!(P2_06, 2, 6); +impl_pin!(P2_07, 2, 7); +impl_pin!(P2_08, 2, 8); +impl_pin!(P2_09, 2, 9); +impl_pin!(P2_10, 2, 10); + +cfg_if::cfg_if! { + if #[cfg(feature = "gpiote")] { + impl_gpiote_pin!(P0_00, GPIOTE30); + impl_gpiote_pin!(P0_01, GPIOTE30); + impl_gpiote_pin!(P0_02, GPIOTE30); + impl_gpiote_pin!(P0_03, GPIOTE30); + impl_gpiote_pin!(P0_04, GPIOTE30); + impl_gpiote_pin!(P0_05, GPIOTE30); + impl_gpiote_pin!(P0_06, GPIOTE30); + + impl_gpiote_pin!(P1_00, GPIOTE20); + impl_gpiote_pin!(P1_01, GPIOTE20); + impl_gpiote_pin!(P1_02, GPIOTE20); + impl_gpiote_pin!(P1_03, GPIOTE20); + impl_gpiote_pin!(P1_04, GPIOTE20); + impl_gpiote_pin!(P1_05, GPIOTE20); + impl_gpiote_pin!(P1_06, GPIOTE20); + impl_gpiote_pin!(P1_07, GPIOTE20); + impl_gpiote_pin!(P1_08, GPIOTE20); + impl_gpiote_pin!(P1_09, GPIOTE20); + impl_gpiote_pin!(P1_10, GPIOTE20); + impl_gpiote_pin!(P1_11, GPIOTE20); + impl_gpiote_pin!(P1_12, GPIOTE20); + impl_gpiote_pin!(P1_13, GPIOTE20); + impl_gpiote_pin!(P1_14, GPIOTE20); + impl_gpiote_pin!(P1_15, GPIOTE20); + impl_gpiote_pin!(P1_16, GPIOTE20); + } +} + +#[cfg(feature = "_ns")] +impl_wdt!(WDT, WDT31, WDT31, 0); +#[cfg(feature = "_s")] +impl_wdt!(WDT0, WDT31, WDT31, 0); +#[cfg(feature = "_s")] +impl_wdt!(WDT1, WDT30, WDT30, 1); +// DPPI00 channels +impl_ppi_channel!(PPI00_CH0, DPPIC00, 0 => configurable); +impl_ppi_channel!(PPI00_CH1, DPPIC00, 1 => configurable); +impl_ppi_channel!(PPI00_CH2, DPPIC00, 2 => configurable); +impl_ppi_channel!(PPI00_CH3, DPPIC00, 3 => configurable); +impl_ppi_channel!(PPI00_CH4, DPPIC00, 4 => configurable); +impl_ppi_channel!(PPI00_CH5, DPPIC00, 5 => configurable); +impl_ppi_channel!(PPI00_CH6, DPPIC00, 6 => configurable); +impl_ppi_channel!(PPI00_CH7, DPPIC00, 7 => configurable); + +// DPPI10 channels +impl_ppi_channel!(PPI10_CH0, DPPIC10, 0 => static); + +// DPPI20 channels +impl_ppi_channel!(PPI20_CH0, DPPIC20, 0 => configurable); +impl_ppi_channel!(PPI20_CH1, DPPIC20, 1 => configurable); +impl_ppi_channel!(PPI20_CH2, DPPIC20, 2 => configurable); +impl_ppi_channel!(PPI20_CH3, DPPIC20, 3 => configurable); +impl_ppi_channel!(PPI20_CH4, DPPIC20, 4 => configurable); +impl_ppi_channel!(PPI20_CH5, DPPIC20, 5 => configurable); +impl_ppi_channel!(PPI20_CH6, DPPIC20, 6 => configurable); +impl_ppi_channel!(PPI20_CH7, DPPIC20, 7 => configurable); +impl_ppi_channel!(PPI20_CH8, DPPIC20, 8 => configurable); +impl_ppi_channel!(PPI20_CH9, DPPIC20, 9 => configurable); +impl_ppi_channel!(PPI20_CH10, DPPIC20, 10 => configurable); +impl_ppi_channel!(PPI20_CH11, DPPIC20, 11 => configurable); +impl_ppi_channel!(PPI20_CH12, DPPIC20, 12 => configurable); +impl_ppi_channel!(PPI20_CH13, DPPIC20, 13 => configurable); +impl_ppi_channel!(PPI20_CH14, DPPIC20, 14 => configurable); +impl_ppi_channel!(PPI20_CH15, DPPIC20, 15 => configurable); + +// DPPI30 channels +impl_ppi_channel!(PPI30_CH0, DPPIC30, 0 => configurable); +impl_ppi_channel!(PPI30_CH1, DPPIC30, 1 => configurable); +impl_ppi_channel!(PPI30_CH2, DPPIC30, 2 => configurable); +impl_ppi_channel!(PPI30_CH3, DPPIC30, 3 => configurable); + +// DPPI00 groups +impl_ppi_group!(PPI00_GROUP0, DPPIC00, 0); +impl_ppi_group!(PPI00_GROUP1, DPPIC00, 1); + +// DPPI10 groups +impl_ppi_group!(PPI10_GROUP0, DPPIC10, 0); + +// DPPI20 groups +impl_ppi_group!(PPI20_GROUP0, DPPIC20, 0); +impl_ppi_group!(PPI20_GROUP1, DPPIC20, 1); +impl_ppi_group!(PPI20_GROUP2, DPPIC20, 2); +impl_ppi_group!(PPI20_GROUP3, DPPIC20, 3); +impl_ppi_group!(PPI20_GROUP4, DPPIC20, 4); +impl_ppi_group!(PPI20_GROUP5, DPPIC20, 5); + +// DPPI30 groups +impl_ppi_group!(PPI30_GROUP0, DPPIC30, 0); +impl_ppi_group!(PPI30_GROUP1, DPPIC30, 1); + +impl_timer!(TIMER00, TIMER00, TIMER00); +impl_timer!(TIMER10, TIMER10, TIMER10); +impl_timer!(TIMER20, TIMER20, TIMER20); +impl_timer!(TIMER21, TIMER21, TIMER21); +impl_timer!(TIMER22, TIMER22, TIMER22); +impl_timer!(TIMER23, TIMER23, TIMER23); +impl_timer!(TIMER24, TIMER24, TIMER24); + +impl_twim!(SERIAL20, TWIM20, SERIAL20); +impl_twim!(SERIAL21, TWIM21, SERIAL21); +impl_twim!(SERIAL22, TWIM22, SERIAL22); +impl_twim!(SERIAL30, TWIM30, SERIAL30); + +impl_twis!(SERIAL20, TWIS20, SERIAL20); +impl_twis!(SERIAL21, TWIS21, SERIAL21); +impl_twis!(SERIAL22, TWIS22, SERIAL22); +impl_twis!(SERIAL30, TWIS30, SERIAL30); + +impl_pwm!(PWM20, PWM20, PWM20); +impl_pwm!(PWM21, PWM21, PWM21); +impl_pwm!(PWM22, PWM22, PWM22); + +#[cfg(feature = "_s")] +impl_spim!( + SERIAL00, + SPIM00, + SERIAL00, + match pac::OSCILLATORS_S.pll().currentfreq().read().currentfreq() { + pac::oscillators::vals::Currentfreq::CK128M => 128_000_000, + pac::oscillators::vals::Currentfreq::CK64M => 64_000_000, + _ => unreachable!(), + } +); +#[cfg(feature = "_ns")] +impl_spim!( + SERIAL00, + SPIM00, + SERIAL00, + match pac::OSCILLATORS_NS.pll().currentfreq().read().currentfreq() { + pac::oscillators::vals::Currentfreq::CK128M => 128_000_000, + pac::oscillators::vals::Currentfreq::CK64M => 64_000_000, + _ => unreachable!(), + } +); +impl_spim!(SERIAL20, SPIM20, SERIAL20, 16_000_000); +impl_spim!(SERIAL21, SPIM21, SERIAL21, 16_000_000); +impl_spim!(SERIAL22, SPIM22, SERIAL22, 16_000_000); +impl_spim!(SERIAL30, SPIM30, SERIAL30, 16_000_000); + +impl_spis!(SERIAL20, SPIS20, SERIAL20); +impl_spis!(SERIAL21, SPIS21, SERIAL21); +impl_spis!(SERIAL22, SPIS22, SERIAL22); +impl_spis!(SERIAL30, SPIS30, SERIAL30); + +impl_uarte!(SERIAL00, UARTE00, SERIAL00); +impl_uarte!(SERIAL20, UARTE20, SERIAL20); +impl_uarte!(SERIAL21, UARTE21, SERIAL21); +impl_uarte!(SERIAL22, UARTE22, SERIAL22); +impl_uarte!(SERIAL30, UARTE30, SERIAL30); + +// NB: SAADC uses "pin" abstraction, not "AIN" +impl_saadc_input!(P1_04, 1, 4); +impl_saadc_input!(P1_05, 1, 5); +impl_saadc_input!(P1_06, 1, 6); +impl_saadc_input!(P1_07, 1, 7); +impl_saadc_input!(P1_11, 1, 11); +impl_saadc_input!(P1_12, 1, 12); +impl_saadc_input!(P1_13, 1, 13); +impl_saadc_input!(P1_14, 1, 14); + +#[cfg(feature = "_s")] +impl_cracen!(CRACEN, CRACEN, CRACEN); + +embassy_hal_internal::interrupt_mod!( + SWI00, + SWI01, + SWI02, + SWI03, + SPU00, + MPC00, + AAR00_CCM00, + ECB00, + CRACEN, + SERIAL00, + RRAMC, + VPR00, + CTRLAP, + TIMER00, + SPU10, + TIMER10, + EGU10, + RADIO_0, + RADIO_1, + SPU20, + SERIAL20, + SERIAL21, + SERIAL22, + EGU20, + TIMER20, + TIMER21, + TIMER22, + TIMER23, + TIMER24, + PDM20, + PDM21, + PWM20, + PWM21, + PWM22, + SAADC, + NFCT, + TEMP, + GPIOTE20_0, + GPIOTE20_1, + TAMPC, + I2S20, + QDEC20, + QDEC21, + GRTC_0, + GRTC_1, + GRTC_2, + GRTC_3, + SPU30, + SERIAL30, + 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 e8762b00d..ac05d6c74 100644 --- a/embassy-nrf/src/lib.rs +++ b/embassy-nrf/src/lib.rs @@ -25,6 +25,10 @@ feature = "nrf5340-net", feature = "nrf54l15-app-s", feature = "nrf54l15-app-ns", + feature = "nrf54l10-app-s", + feature = "nrf54l10-app-ns", + feature = "nrf54l05-app-s", + feature = "nrf54l05-app-ns", feature = "nrf9160-s", feature = "nrf9160-ns", feature = "nrf9120-s", @@ -49,6 +53,10 @@ compile_error!( nrf5340-net, nrf54l15-app-s, nrf54l15-app-ns, + nrf54l10-app-s, + nrf54l10-app-ns, + nrf54l05-app-s, + nrf54l05-app-ns, nrf9160-s, nrf9160-ns, nrf9120-s, @@ -99,9 +107,9 @@ pub mod ipc; pub mod nfct; #[cfg(not(feature = "_nrf54l"))] pub mod nvmc; -#[cfg(feature = "nrf54l15-app-s")] +#[cfg(feature = "_nrf54l")] pub mod rramc; -#[cfg(feature = "nrf54l15-app-s")] +#[cfg(feature = "_nrf54l")] pub use rramc as nvmc; #[cfg(not(feature = "_nrf54l"))] // TODO #[cfg(any( @@ -192,6 +200,8 @@ pub mod wdt; #[cfg_attr(feature = "_nrf5340-app", path = "chips/nrf5340_app.rs")] #[cfg_attr(feature = "_nrf5340-net", path = "chips/nrf5340_net.rs")] #[cfg_attr(feature = "_nrf54l15-app", path = "chips/nrf54l15_app.rs")] +#[cfg_attr(feature = "_nrf54l10-app", path = "chips/nrf54l10_app.rs")] +#[cfg_attr(feature = "_nrf54l05-app", path = "chips/nrf54l05_app.rs")] #[cfg_attr(feature = "_nrf9160", path = "chips/nrf9160.rs")] #[cfg_attr(feature = "_nrf9120", path = "chips/nrf9120.rs")] mod chip; -- cgit From 7cd74f489f70cb6741e7c84da97e805bb9e8c040 Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Tue, 2 Dec 2025 14:59:28 +0100 Subject: docs: mention nrf54 support --- README.md | 2 +- docs/pages/overview.adoc | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 950d19a6d..1d6f3499d 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ Rust's [async/await](https://rust-lang.github.io/async-book/) allows for unprece - **Bluetooth** - The [trouble](https://github.com/embassy-rs/trouble) crate provides a Bluetooth Low Energy 4.x and 5.x Host that runs on any microcontroller implementing the [bt-hci](https://github.com/embassy-rs/bt-hci) traits (currently - `nRF52`, `rp2040`, `rp23xx` and `esp32` and `serial` controllers are supported). + `nRF52`, `nrf54`, `rp2040`, `rp23xx` and `esp32` and `serial` controllers are supported). - The [nrf-softdevice](https://github.com/embassy-rs/nrf-softdevice) crate provides Bluetooth Low Energy 4.x and 5.x support for nRF52 microcontrollers. - The [embassy-stm32-wpan](https://github.com/embassy-rs/embassy/tree/main/embassy-stm32-wpan) crate provides Bluetooth Low Energy 5.x support for stm32wb microcontrollers. diff --git a/docs/pages/overview.adoc b/docs/pages/overview.adoc index 18eaaeb75..894789d33 100644 --- a/docs/pages/overview.adoc +++ b/docs/pages/overview.adoc @@ -27,7 +27,7 @@ Embassy provides implementations of both async and blocking APIs where it makes The Embassy project maintains HALs for select hardware, but you can still use HALs from other projects with Embassy. * link:https://docs.embassy.dev/embassy-stm32/[embassy-stm32], for all STM32 microcontroller families. -* link:https://docs.embassy.dev/embassy-nrf/[embassy-nrf], for the Nordic Semiconductor nRF52, nRF53, nRF91 series. +* link:https://docs.embassy.dev/embassy-nrf/[embassy-nrf], for the Nordic Semiconductor nRF52, nRF53, nRF54, nRF91 series. * link:https://docs.embassy.dev/embassy-rp/[embassy-rp], for the Raspberry Pi RP2040 as well as RP235x microcontroller. * link:https://docs.embassy.dev/embassy-mspm0/[embassy-mspm0], for the Texas Instruments MSPM0 microcontrollers. * link:https://github.com/esp-rs/esp-hal[esp-hal], for the Espressif Systems ESP32 series of chips. @@ -42,7 +42,9 @@ as they implement both the link:https://github.com/rust-embedded/embedded-hal[Em The link:https://docs.embassy.dev/embassy-net/[embassy-net] network stack implements extensive networking functionality, including Ethernet, IP, TCP, UDP, ICMP and DHCP. Async drastically simplifies managing timeouts and serving multiple connections concurrently. Several drivers for WiFi and Ethernet chips can be found. === Bluetooth -The link:https://github.com/embassy-rs/nrf-softdevice[nrf-softdevice] crate provides Bluetooth Low Energy 4.x and 5.x support for nRF52 microcontrollers. + +* The link:https://github.com/embassy-rs/trouble[trouble] crate provides a Bluetooth Low Energy 4.x and 5.x Host that runs on any microcontroller implementing the link:https://github.com/embassy-rs/bt-hci[bt-hci] traits (currently `nRF52`, `nrf54`, `rp2040`, `rp23xx` and `esp32` and `serial` controllers are supported). +* The link:https://github.com/embassy-rs/nrf-softdevice[nrf-softdevice] crate provides Bluetooth Low Energy 4.x and 5.x support for nRF52 microcontrollers. === LoRa link:https://github.com/lora-rs/lora-rs[lora-rs] supports LoRa networking on a wide range of LoRa radios, fully integrated with a Rust LoRaWAN implementation. It provides four crates — lora-phy, lora-modulation, lorawan-encoding, and lorawan-device — and basic examples for various development boards. It has support for STM32WL wireless microcontrollers or Semtech SX127x transceivers, among others. -- cgit From 9c1c0b133ee06251dd31012aab4a2732cb6d1436 Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Tue, 2 Dec 2025 14:59:38 +0100 Subject: chore: update changelog --- embassy-nrf/CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/embassy-nrf/CHANGELOG.md b/embassy-nrf/CHANGELOG.md index 5657ddcfb..d26671674 100644 --- a/embassy-nrf/CHANGELOG.md +++ b/embassy-nrf/CHANGELOG.md @@ -29,6 +29,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - 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 +* added: support for nrf54l10 and nrf54l05 ## 0.8.0 - 2025-09-30 -- cgit From d3fda8cb4f5c6bb2ba75f3402572d1831ad03b2a Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Tue, 2 Dec 2025 15:35:29 +0100 Subject: fix: use correct cfg guard --- embassy-nrf/src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/embassy-nrf/src/lib.rs b/embassy-nrf/src/lib.rs index ac05d6c74..4cb291626 100644 --- a/embassy-nrf/src/lib.rs +++ b/embassy-nrf/src/lib.rs @@ -107,9 +107,9 @@ pub mod ipc; pub mod nfct; #[cfg(not(feature = "_nrf54l"))] pub mod nvmc; -#[cfg(feature = "_nrf54l")] +#[cfg(all(feature = "_nrf54l", feature = "_s"))] pub mod rramc; -#[cfg(feature = "_nrf54l")] +#[cfg(all(feature = "_nrf54l", feature = "_s"))] pub use rramc as nvmc; #[cfg(not(feature = "_nrf54l"))] // TODO #[cfg(any( -- cgit From 1965d5e6dbcb39775cacc06750702c27bdd4fda8 Mon Sep 17 00:00:00 2001 From: Simon Börjesson Date: Mon, 3 Nov 2025 21:42:19 +0100 Subject: Disable authentication before setting up Ap --- cyw43/src/control.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/cyw43/src/control.rs b/cyw43/src/control.rs index 49e3faee4..219198d1f 100644 --- a/cyw43/src/control.rs +++ b/cyw43/src/control.rs @@ -436,6 +436,9 @@ impl<'a> Control<'a> { // Set wifi up again self.up().await; + // Disable authentication + self.ioctl_set_u32(Ioctl::SetAuth, 0, AUTH_OPEN).await; + // Turn on AP mode self.ioctl_set_u32(Ioctl::SetAp, 0, 1).await; @@ -470,8 +473,6 @@ impl<'a> Control<'a> { pfi.passphrase[..passphrase.as_bytes().len()].copy_from_slice(passphrase.as_bytes()); self.ioctl(IoctlType::Set, Ioctl::SetWsecPmk, 0, &mut pfi.to_bytes()) .await; - } else { - self.ioctl_set_u32(Ioctl::SetAuth, 0, 0).await; } // Change mutlicast rate from 1 Mbps to 11 Mbps -- cgit From a32a9b609a244ac375bddc5b478b6856f452be72 Mon Sep 17 00:00:00 2001 From: Simon Börjesson Date: Tue, 2 Dec 2025 23:00:22 +0100 Subject: Add changelog entry --- cyw43/CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cyw43/CHANGELOG.md b/cyw43/CHANGELOG.md index 9fe341357..4f0dc896b 100644 --- a/cyw43/CHANGELOG.md +++ b/cyw43/CHANGELOG.md @@ -8,6 +8,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased - ReleaseDate +- Reset WPA security before creating secure AP + ## 0.6.0 - 2025-11-27 - Updated documentation for Control::join() #4678 -- cgit From df396688eb31da484db371632cb76ebf9143d8f7 Mon Sep 17 00:00:00 2001 From: 9names <60134748+9names@users.noreply.github.com> Date: Wed, 3 Dec 2025 22:19:40 +1100 Subject: docs: fix rp235x pio_i2s example comment --- examples/rp235x/src/bin/pio_i2s.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/rp235x/src/bin/pio_i2s.rs b/examples/rp235x/src/bin/pio_i2s.rs index cfcb0221d..7ed952a40 100644 --- a/examples/rp235x/src/bin/pio_i2s.rs +++ b/examples/rp235x/src/bin/pio_i2s.rs @@ -5,7 +5,7 @@ //! bclk : GPIO 18 //! lrc : GPIO 19 //! din : GPIO 20 -//! Then hold down the boot select button to trigger a rising triangle waveform. +//! Then short GPIO 0 to GND to trigger a rising triangle waveform. #![no_std] #![no_main] @@ -70,7 +70,7 @@ async fn main(_spawner: Spawner) { // but don't await the returned future, yet let dma_future = i2s.write(front_buffer); - // fade in audio when bootsel is pressed + // fade in audio when GPIO 0 pin is shorted to GND let fade_target = if fade_input.is_low() { i32::MAX } else { 0 }; // fill back buffer with fresh audio samples before awaiting the dma future -- cgit