aboutsummaryrefslogtreecommitdiff
path: root/embassy-nrf/src
diff options
context:
space:
mode:
authorMatthew Tran <[email protected]>2025-10-05 03:16:18 -0500
committerMatthew Tran <[email protected]>2025-10-05 08:15:10 -0500
commitc0fd86d6c68ec5f66a4cd5a5ef36bcda7b9e1c0e (patch)
treef795496b927ffa15823782e4934e62e56a008587 /embassy-nrf/src
parente4e06ab5b136a21c98d42491ef1e31b6dc25e08e (diff)
nrf: apply FICR.TRIMCNF values
Diffstat (limited to 'embassy-nrf/src')
-rw-r--r--embassy-nrf/src/chips/nrf54l15_app.rs1
-rw-r--r--embassy-nrf/src/lib.rs64
-rw-r--r--embassy-nrf/src/radio/ieee802154.rs17
3 files changed, 69 insertions, 13 deletions
diff --git a/embassy-nrf/src/chips/nrf54l15_app.rs b/embassy-nrf/src/chips/nrf54l15_app.rs
index ff05bbec0..82d30104f 100644
--- a/embassy-nrf/src/chips/nrf54l15_app.rs
+++ b/embassy-nrf/src/chips/nrf54l15_app.rs
@@ -94,6 +94,7 @@ pub mod pac {
94 #[cfg(feature = "_s")] 94 #[cfg(feature = "_s")]
95 #[doc(no_inline)] 95 #[doc(no_inline)]
96 pub use nrf_pac::{ 96 pub use nrf_pac::{
97 FICR_NS as FICR,
97 SICR_S as SICR, 98 SICR_S as SICR,
98 ICACHEDATA_S as ICACHEDATA, 99 ICACHEDATA_S as ICACHEDATA,
99 ICACHEINFO_S as ICACHEINFO, 100 ICACHEINFO_S as ICACHEINFO,
diff --git a/embassy-nrf/src/lib.rs b/embassy-nrf/src/lib.rs
index 7c26a6184..716eec961 100644
--- a/embassy-nrf/src/lib.rs
+++ b/embassy-nrf/src/lib.rs
@@ -406,9 +406,10 @@ pub mod config {
406 /// Settings for the internal capacitors. 406 /// Settings for the internal capacitors.
407 #[cfg(feature = "nrf5340-app-s")] 407 #[cfg(feature = "nrf5340-app-s")]
408 pub struct InternalCapacitors { 408 pub struct InternalCapacitors {
409 /// Config for the internal capacitors on pins XC1 and XC2. 409 /// Config for the internal capacitors on pins XC1 and XC2. Pass `None` to not touch it.
410 pub hfxo: Option<HfxoCapacitance>, 410 pub hfxo: Option<HfxoCapacitance>,
411 /// Config for the internal capacitors between pins XL1 and XL2. 411 /// Config for the internal capacitors between pins XL1 and XL2. Pass `None` to not touch
412 /// it.
412 pub lfxo: Option<LfxoCapacitance>, 413 pub lfxo: Option<LfxoCapacitance>,
413 } 414 }
414 415
@@ -416,6 +417,8 @@ pub mod config {
416 #[cfg(feature = "nrf5340-app-s")] 417 #[cfg(feature = "nrf5340-app-s")]
417 #[derive(Copy, Clone)] 418 #[derive(Copy, Clone)]
418 pub enum HfxoCapacitance { 419 pub enum HfxoCapacitance {
420 /// Use external capacitors
421 External,
419 /// 7.0 pF 422 /// 7.0 pF
420 _7_0pF, 423 _7_0pF,
421 /// 7.5 pF 424 /// 7.5 pF
@@ -475,8 +478,9 @@ pub mod config {
475 #[cfg(feature = "nrf5340-app-s")] 478 #[cfg(feature = "nrf5340-app-s")]
476 impl HfxoCapacitance { 479 impl HfxoCapacitance {
477 /// The capacitance value times two. 480 /// The capacitance value times two.
478 pub(crate) const fn value2(self) -> i32 { 481 pub(crate) fn value2(self) -> i32 {
479 match self { 482 match self {
483 HfxoCapacitance::External => unreachable!(),
480 HfxoCapacitance::_7_0pF => 14, 484 HfxoCapacitance::_7_0pF => 14,
481 HfxoCapacitance::_7_5pF => 15, 485 HfxoCapacitance::_7_5pF => 15,
482 HfxoCapacitance::_8_0pF => 16, 486 HfxoCapacitance::_8_0pF => 16,
@@ -506,11 +510,17 @@ pub mod config {
506 HfxoCapacitance::_20_0pF => 40, 510 HfxoCapacitance::_20_0pF => 40,
507 } 511 }
508 } 512 }
513
514 pub(crate) fn external(self) -> bool {
515 matches!(self, Self::External)
516 }
509 } 517 }
510 518
511 /// Internal capacitance value for the LFXO. 519 /// Internal capacitance value for the LFXO.
512 #[cfg(feature = "nrf5340-app-s")] 520 #[cfg(feature = "nrf5340-app-s")]
513 pub enum LfxoCapacitance { 521 pub enum LfxoCapacitance {
522 /// Use external capacitors
523 External = 0,
514 /// 6 pF 524 /// 6 pF
515 _6pF = 1, 525 _6pF = 1,
516 /// 7 pF 526 /// 7 pF
@@ -523,6 +533,7 @@ pub mod config {
523 impl From<LfxoCapacitance> for super::pac::oscillators::vals::Intcap { 533 impl From<LfxoCapacitance> for super::pac::oscillators::vals::Intcap {
524 fn from(t: LfxoCapacitance) -> Self { 534 fn from(t: LfxoCapacitance) -> Self {
525 match t { 535 match t {
536 LfxoCapacitance::External => Self::EXTERNAL,
526 LfxoCapacitance::_6pF => Self::C6PF, 537 LfxoCapacitance::_6pF => Self::C6PF,
527 LfxoCapacitance::_7pF => Self::C7PF, 538 LfxoCapacitance::_7pF => Self::C7PF,
528 LfxoCapacitance::_9pF => Self::C9PF, 539 LfxoCapacitance::_9pF => Self::C9PF,
@@ -720,6 +731,29 @@ pub fn init(config: config::Config) -> Peripherals {
720 } 731 }
721 } 732 }
722 733
734 // Apply trimming values from the FICR.
735 #[cfg(any(
736 all(feature = "_nrf5340-app", feature = "_s"),
737 all(feature = "_nrf54l", feature = "_s"),
738 feature = "_nrf5340-net",
739 ))]
740 {
741 #[cfg(feature = "_nrf5340")]
742 let n = 32;
743 #[cfg(feature = "_nrf54l")]
744 let n = 64;
745 for i in 0..n {
746 let info = pac::FICR.trimcnf(i);
747 let addr = info.addr().read();
748 if addr == 0 || addr == 0xFFFF_FFFF {
749 break;
750 }
751 unsafe {
752 (addr as *mut u32).write_volatile(info.data().read());
753 }
754 }
755 }
756
723 // GLITCHDET is only accessible for secure code 757 // GLITCHDET is only accessible for secure code
724 #[cfg(all(feature = "_nrf54l", feature = "_s"))] 758 #[cfg(all(feature = "_nrf54l", feature = "_s"))]
725 { 759 {
@@ -953,17 +987,21 @@ pub fn init(config: config::Config) -> Peripherals {
953 #[cfg(feature = "nrf5340-app-s")] 987 #[cfg(feature = "nrf5340-app-s")]
954 { 988 {
955 if let Some(cap) = config.internal_capacitors.hfxo { 989 if let Some(cap) = config.internal_capacitors.hfxo {
956 let mut slope = pac::FICR.xosc32mtrim().read().slope() as i32; 990 if cap.external() {
957 let offset = pac::FICR.xosc32mtrim().read().offset() as i32; 991 pac::OSCILLATORS.xosc32mcaps().write(|w| w.set_enable(false));
958 // slope is a signed 5-bit integer 992 } else {
959 if slope >= 16 { 993 let mut slope = pac::FICR.xosc32mtrim().read().slope() as i32;
960 slope -= 32; 994 let offset = pac::FICR.xosc32mtrim().read().offset() as i32;
995 // slope is a signed 5-bit integer
996 if slope >= 16 {
997 slope -= 32;
998 }
999 let capvalue = (((slope + 56) * (cap.value2() - 14)) + ((offset - 8) << 4) + 32) >> 6;
1000 pac::OSCILLATORS.xosc32mcaps().write(|w| {
1001 w.set_capvalue(capvalue as u8);
1002 w.set_enable(true);
1003 });
961 } 1004 }
962 let capvalue = (((slope + 56) * (cap.value2() - 14)) + ((offset - 8) << 4) + 32) >> 6;
963 pac::OSCILLATORS.xosc32mcaps().write(|w| {
964 w.set_capvalue(capvalue as u8);
965 w.set_enable(true);
966 });
967 } 1005 }
968 if let Some(cap) = config.internal_capacitors.lfxo { 1006 if let Some(cap) = config.internal_capacitors.lfxo {
969 pac::OSCILLATORS.xosc32ki().intcap().write(|w| w.set_intcap(cap.into())); 1007 pac::OSCILLATORS.xosc32ki().intcap().write(|w| w.set_intcap(cap.into()));
diff --git a/embassy-nrf/src/radio/ieee802154.rs b/embassy-nrf/src/radio/ieee802154.rs
index 62af03a5a..844d3551e 100644
--- a/embassy-nrf/src/radio/ieee802154.rs
+++ b/embassy-nrf/src/radio/ieee802154.rs
@@ -52,6 +52,7 @@ impl<'d> Radio<'d> {
52 // Disable and enable to reset peripheral 52 // Disable and enable to reset peripheral
53 r.power().write(|w| w.set_power(false)); 53 r.power().write(|w| w.set_power(false));
54 r.power().write(|w| w.set_power(true)); 54 r.power().write(|w| w.set_power(true));
55 errata::post_power();
55 56
56 // Enable 802.15.4 mode 57 // Enable 802.15.4 mode
57 r.mode().write(|w| w.set_mode(vals::Mode::IEEE802154_250KBIT)); 58 r.mode().write(|w| w.set_mode(vals::Mode::IEEE802154_250KBIT));
@@ -541,3 +542,19 @@ fn dma_start_fence() {
541fn dma_end_fence() { 542fn dma_end_fence() {
542 compiler_fence(Ordering::Acquire); 543 compiler_fence(Ordering::Acquire);
543} 544}
545
546mod errata {
547 pub fn post_power() {
548 // Workaround for anomaly 158
549 #[cfg(feature = "_nrf5340-net")]
550 for i in 0..32 {
551 let info = crate::pac::FICR.trimcnf(i);
552 let addr = info.addr().read();
553 if addr & 0xFFFF_F000 == crate::pac::RADIO.as_ptr() as u32 {
554 unsafe {
555 (addr as *mut u32).write_volatile(info.data().read());
556 }
557 }
558 }
559 }
560}