aboutsummaryrefslogtreecommitdiff
path: root/embassy-nrf
diff options
context:
space:
mode:
authorUlf Lilleengen <[email protected]>2025-11-04 13:10:45 +0100
committerUlf Lilleengen <[email protected]>2025-11-04 13:13:22 +0100
commit729a7c2cc5e5fe1d9badb0a0f1c758ba2c57b6aa (patch)
tree967f9fcb91f33b80fa7decc25a0c948927d607c0 /embassy-nrf
parent18a5872a2586335496aec056e24edacef6fd76cb (diff)
feat: initial support for nrf54 CRACEN peripheral
The CRACEN peripheral supports random number generation, digest and key generation, and key exchange. The initial support implements random number generation.
Diffstat (limited to 'embassy-nrf')
-rw-r--r--embassy-nrf/src/chips/nrf54l15_app.rs2
-rw-r--r--embassy-nrf/src/cracen.rs161
-rw-r--r--embassy-nrf/src/lib.rs4
3 files changed, 166 insertions, 1 deletions
diff --git a/embassy-nrf/src/chips/nrf54l15_app.rs b/embassy-nrf/src/chips/nrf54l15_app.rs
index d0068eb20..285cdec07 100644
--- a/embassy-nrf/src/chips/nrf54l15_app.rs
+++ b/embassy-nrf/src/chips/nrf54l15_app.rs
@@ -682,6 +682,8 @@ impl_saadc_input!(P1_12, 1, 12);
682impl_saadc_input!(P1_13, 1, 13); 682impl_saadc_input!(P1_13, 1, 13);
683impl_saadc_input!(P1_14, 1, 14); 683impl_saadc_input!(P1_14, 1, 14);
684 684
685impl_cracen!(CRACEN, CRACEN, CRACEN);
686
685embassy_hal_internal::interrupt_mod!( 687embassy_hal_internal::interrupt_mod!(
686 SWI00, 688 SWI00,
687 SWI01, 689 SWI01,
diff --git a/embassy-nrf/src/cracen.rs b/embassy-nrf/src/cracen.rs
new file mode 100644
index 000000000..ddc592689
--- /dev/null
+++ b/embassy-nrf/src/cracen.rs
@@ -0,0 +1,161 @@
1//! CRACEN - Cryptographic Accelerator Engine driver.
2
3#![macro_use]
4
5use crate::mode::{Async, Blocking, Mode};
6use crate::{Peri, interrupt, pac, peripherals};
7use core::marker::PhantomData;
8
9pub struct Cracen<'d, M: Mode> {
10 _peri: Peri<'d, peripherals::CRACEN>,
11 _p: PhantomData<M>,
12}
13
14impl<'d> Cracen<'d, Blocking> {
15 /// Create a new CRACEN driver.
16 pub fn new_blocking(_peri: Peri<'d, peripherals::CRACEN>) -> Self {
17 let r = pac::CRACEN;
18
19 let me = Self { _peri, _p: PhantomData };
20
21 me.stop();
22 me
23 }
24}
25
26impl<'d, M: Mode> Cracen<'d, M> {
27 fn regs() -> pac::cracen::Cracen {
28 pac::CRACEN
29 }
30
31 fn core() -> pac::cracencore::Cracencore {
32 pac::CRACENCORE
33 }
34
35 fn start_rng(&self) {
36 let r = Self::regs();
37 r.enable().write(|w| {
38 w.set_rng(true);
39 });
40
41 let r = Self::core();
42 r.rngcontrol().control().write(|w| {
43 w.set_enable(true);
44 });
45
46 while r.rngcontrol().status().read().state() == pac::cracencore::vals::State::STARTUP {}
47 }
48
49 fn stop(&self) {
50 let r = Self::regs();
51 r.enable().write(|w| {
52 w.set_cryptomaster(false);
53 w.set_rng(false);
54 w.set_pkeikg(false);
55 });
56 }
57
58 /// Fill the buffer with random bytes, blocking version.
59 pub fn blocking_fill_bytes(&mut self, dest: &mut [u8]) {
60 self.start_rng();
61
62 let r = Self::core();
63 for chunk in dest.chunks_mut(4) {
64 while r.rngcontrol().fifolevel().read() == 0 {}
65 let word = r.rngcontrol().fifo(0).read().to_ne_bytes();
66 let to_copy = word.len().min(chunk.len());
67 chunk[..to_copy].copy_from_slice(&word[..to_copy]);
68 }
69
70 self.stop();
71 }
72
73 /// Generate a random u32
74 pub fn blocking_next_u32(&mut self) -> u32 {
75 let mut bytes = [0; 4];
76 self.blocking_fill_bytes(&mut bytes);
77 // We don't care about the endianness, so just use the native one.
78 u32::from_ne_bytes(bytes)
79 }
80
81 /// Generate a random u64
82 pub fn blocking_next_u64(&mut self) -> u64 {
83 let mut bytes = [0; 8];
84 self.blocking_fill_bytes(&mut bytes);
85 u64::from_ne_bytes(bytes)
86 }
87}
88
89impl<'d, M: Mode> Drop for Cracen<'d, M> {
90 fn drop(&mut self) {
91 let r = Self::core();
92 r.rngcontrol().control().write(|w| {
93 w.set_enable(false);
94 });
95
96 while r.rngcontrol().status().read().state() != pac::cracencore::vals::State::RESET {}
97
98 let r = Self::regs();
99 r.enable().write(|w| {
100 w.set_cryptomaster(false);
101 w.set_rng(false);
102 w.set_pkeikg(false);
103 });
104 }
105}
106
107impl<'d, M: Mode> rand_core_06::RngCore for Cracen<'d, M> {
108 fn fill_bytes(&mut self, dest: &mut [u8]) {
109 self.blocking_fill_bytes(dest);
110 }
111 fn next_u32(&mut self) -> u32 {
112 self.blocking_next_u32()
113 }
114 fn next_u64(&mut self) -> u64 {
115 self.blocking_next_u64()
116 }
117 fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), rand_core_06::Error> {
118 self.blocking_fill_bytes(dest);
119 Ok(())
120 }
121}
122
123impl<'d, M: Mode> rand_core_06::CryptoRng for Cracen<'d, M> {}
124
125impl<'d, M: Mode> rand_core_09::RngCore for Cracen<'d, M> {
126 fn fill_bytes(&mut self, dest: &mut [u8]) {
127 self.blocking_fill_bytes(dest);
128 }
129 fn next_u32(&mut self) -> u32 {
130 self.blocking_next_u32()
131 }
132 fn next_u64(&mut self) -> u64 {
133 self.blocking_next_u64()
134 }
135}
136
137impl<'d, M: Mode> rand_core_09::CryptoRng for Cracen<'d, M> {}
138
139pub(crate) trait SealedInstance {
140 fn regs() -> pac::cracen::Cracen;
141}
142
143/// CRACEN peripheral instance.
144#[allow(private_bounds)]
145pub trait Instance: SealedInstance + 'static + Send {
146 /// Interrupt for this peripheral.
147 type Interrupt: interrupt::typelevel::Interrupt;
148}
149
150macro_rules! impl_cracen {
151 ($type:ident, $pac_type:ident, $irq:ident) => {
152 impl crate::cracen::SealedInstance for peripherals::$type {
153 fn regs() -> crate::pac::cracen::Cracen {
154 pac::$pac_type
155 }
156 }
157 impl crate::cracen::Instance for peripherals::$type {
158 type Interrupt = crate::interrupt::typelevel::$irq;
159 }
160 };
161}
diff --git a/embassy-nrf/src/lib.rs b/embassy-nrf/src/lib.rs
index 4c3b92a83..530964107 100644
--- a/embassy-nrf/src/lib.rs
+++ b/embassy-nrf/src/lib.rs
@@ -145,10 +145,12 @@ pub mod radio;
145#[cfg(feature = "_net-driver")] 145#[cfg(feature = "_net-driver")]
146pub mod embassy_net_802154_driver; 146pub mod embassy_net_802154_driver;
147 147
148#[cfg(feature = "_nrf54l")]
149pub mod cracen;
148#[cfg(not(feature = "_nrf54l"))] // TODO 150#[cfg(not(feature = "_nrf54l"))] // TODO
149#[cfg(feature = "_nrf5340")] 151#[cfg(feature = "_nrf5340")]
150pub mod reset; 152pub mod reset;
151#[cfg(not(feature = "_nrf54l"))] // TODO 153#[cfg(not(feature = "_nrf54l"))]
152#[cfg(not(any(feature = "_nrf5340-app", feature = "_nrf91")))] 154#[cfg(not(any(feature = "_nrf5340-app", feature = "_nrf91")))]
153pub mod rng; 155pub mod rng;
154pub mod rtc; 156pub mod rtc;