aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xci.sh3
-rw-r--r--embassy-net-nrf91/Cargo.toml2
-rw-r--r--embassy-nrf/Cargo.toml12
-rw-r--r--embassy-nrf/src/chips/nrf54l15_app.rs346
-rw-r--r--embassy-nrf/src/gpio.rs131
-rw-r--r--embassy-nrf/src/lib.rs82
-rw-r--r--embassy-nrf/src/pwm.rs16
-rw-r--r--embassy-nrf/src/spim.rs4
-rw-r--r--embassy-nrf/src/spis.rs2
-rw-r--r--embassy-nrf/src/time_driver.rs25
-rw-r--r--examples/nrf54l15/.cargo/config.toml9
-rw-r--r--examples/nrf54l15/Cargo.toml20
-rw-r--r--examples/nrf54l15/build.rs35
-rw-r--r--examples/nrf54l15/memory.x5
-rw-r--r--examples/nrf54l15/src/bin/blinky.rs23
15 files changed, 667 insertions, 48 deletions
diff --git a/ci.sh b/ci.sh
index 9f7a7a037..307e268c4 100755
--- a/ci.sh
+++ b/ci.sh
@@ -70,6 +70,8 @@ cargo batch \
70 --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv8m.main-none-eabihf --features nrf5340-app-s,gpiote,time,time-driver-rtc1 \ 70 --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv8m.main-none-eabihf --features nrf5340-app-s,gpiote,time,time-driver-rtc1 \
71 --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv8m.main-none-eabihf --features nrf5340-app-ns,gpiote,time,time-driver-rtc1 \ 71 --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv8m.main-none-eabihf --features nrf5340-app-ns,gpiote,time,time-driver-rtc1 \
72 --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv8m.main-none-eabihf --features nrf5340-net,gpiote,time,time-driver-rtc1 \ 72 --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv8m.main-none-eabihf --features nrf5340-net,gpiote,time,time-driver-rtc1 \
73 --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv8m.main-none-eabihf --features nrf54l15-app-s,gpiote,time,time-driver-rtc1 \
74 --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv8m.main-none-eabihf --features nrf54l15-app-ns,gpiote,time,time-driver-rtc1 \
73 --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv7em-none-eabi --features nrf52840,gpiote,time \ 75 --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv7em-none-eabi --features nrf52840,gpiote,time \
74 --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv7em-none-eabi --features nrf52840,gpiote,time-driver-rtc1 \ 76 --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv7em-none-eabi --features nrf52840,gpiote,time-driver-rtc1 \
75 --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv7em-none-eabi --features nrf52840,gpiote,time,time-driver-rtc1 \ 77 --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv7em-none-eabi --features nrf52840,gpiote,time,time-driver-rtc1 \
@@ -197,6 +199,7 @@ cargo batch \
197 --- build --release --manifest-path examples/nrf52810/Cargo.toml --target thumbv7em-none-eabi --out-dir out/examples/nrf52810 \ 199 --- build --release --manifest-path examples/nrf52810/Cargo.toml --target thumbv7em-none-eabi --out-dir out/examples/nrf52810 \
198 --- build --release --manifest-path examples/nrf52840/Cargo.toml --target thumbv7em-none-eabi --out-dir out/examples/nrf52840 \ 200 --- build --release --manifest-path examples/nrf52840/Cargo.toml --target thumbv7em-none-eabi --out-dir out/examples/nrf52840 \
199 --- build --release --manifest-path examples/nrf5340/Cargo.toml --target thumbv8m.main-none-eabihf --out-dir out/examples/nrf5340 \ 201 --- build --release --manifest-path examples/nrf5340/Cargo.toml --target thumbv8m.main-none-eabihf --out-dir out/examples/nrf5340 \
202 --- build --release --manifest-path examples/nrf54l15/Cargo.toml --target thumbv8m.main-none-eabihf --out-dir out/examples/nrf54l15 \
200 --- build --release --manifest-path examples/nrf9160/Cargo.toml --target thumbv8m.main-none-eabihf --out-dir out/examples/nrf9160 \ 203 --- build --release --manifest-path examples/nrf9160/Cargo.toml --target thumbv8m.main-none-eabihf --out-dir out/examples/nrf9160 \
201 --- build --release --manifest-path examples/nrf9151/s/Cargo.toml --target thumbv8m.main-none-eabihf --out-dir out/examples/nrf9151/s \ 204 --- build --release --manifest-path examples/nrf9151/s/Cargo.toml --target thumbv8m.main-none-eabihf --out-dir out/examples/nrf9151/s \
202 --- build --release --manifest-path examples/nrf9151/ns/Cargo.toml --target thumbv8m.main-none-eabihf --out-dir out/examples/nrf9151/ns \ 205 --- build --release --manifest-path examples/nrf9151/ns/Cargo.toml --target thumbv8m.main-none-eabihf --out-dir out/examples/nrf9151/ns \
diff --git a/embassy-net-nrf91/Cargo.toml b/embassy-net-nrf91/Cargo.toml
index 77a1c4cb5..bc31f93f4 100644
--- a/embassy-net-nrf91/Cargo.toml
+++ b/embassy-net-nrf91/Cargo.toml
@@ -17,7 +17,7 @@ log = [ "dep:log" ]
17defmt = { version = "0.3", optional = true } 17defmt = { version = "0.3", optional = true }
18log = { version = "0.4.14", optional = true } 18log = { version = "0.4.14", optional = true }
19 19
20nrf-pac = { git = "https://github.com/embassy-rs/nrf-pac", rev = "12e2461859acb0bfea9b2ef5cd73f1283c139ac0" } 20nrf-pac = { git = "https://github.com/embassy-rs/nrf-pac", rev = "52e3a757f06035c94291bfc42b0c03f71e4d677e" }
21cortex-m = "0.7.7" 21cortex-m = "0.7.7"
22 22
23embassy-time = { version = "0.3.1", path = "../embassy-time" } 23embassy-time = { version = "0.3.1", path = "../embassy-time" }
diff --git a/embassy-nrf/Cargo.toml b/embassy-nrf/Cargo.toml
index 7b20d2643..ed9aba4e7 100644
--- a/embassy-nrf/Cargo.toml
+++ b/embassy-nrf/Cargo.toml
@@ -83,6 +83,11 @@ nrf5340-app-s = ["_nrf5340-app", "_s"]
83nrf5340-app-ns = ["_nrf5340-app", "_ns"] 83nrf5340-app-ns = ["_nrf5340-app", "_ns"]
84## nRF5340 network core 84## nRF5340 network core
85nrf5340-net = ["_nrf5340-net"] 85nrf5340-net = ["_nrf5340-net"]
86## nRF54L15 application core in Secure mode
87nrf54l15-app-s = ["_nrf54l15-app", "_s"]
88## nRF54L15 application core in Non-Secure mode
89nrf54l15-app-ns = ["_nrf54l15-app", "_ns"]
90
86## nRF9160 in Secure mode 91## nRF9160 in Secure mode
87nrf9160-s = ["_nrf9160", "_s", "_nrf91"] 92nrf9160-s = ["_nrf9160", "_s", "_nrf91"]
88## nRF9160 in Non-Secure mode 93## nRF9160 in Non-Secure mode
@@ -103,6 +108,10 @@ nrf9161-ns = ["nrf9120-ns"]
103_nrf5340-app = ["_nrf5340", "nrf-pac/nrf5340-app"] 108_nrf5340-app = ["_nrf5340", "nrf-pac/nrf5340-app"]
104_nrf5340-net = ["_nrf5340", "nrf-pac/nrf5340-net"] 109_nrf5340-net = ["_nrf5340", "nrf-pac/nrf5340-net"]
105_nrf5340 = ["_gpio-p1", "_dppi"] 110_nrf5340 = ["_gpio-p1", "_dppi"]
111_nrf54l15-app = ["_nrf54l15", "nrf-pac/nrf54l15-app"]
112_nrf54l15 = ["_nrf54l", "_gpio-p1", "_gpio-p2"]
113_nrf54l = ["_dppi"]
114
106_nrf9160 = ["nrf-pac/nrf9160", "_dppi"] 115_nrf9160 = ["nrf-pac/nrf9160", "_dppi"]
107_nrf9120 = ["nrf-pac/nrf9120", "_dppi"] 116_nrf9120 = ["nrf-pac/nrf9120", "_dppi"]
108_nrf52 = ["_ppi"] 117_nrf52 = ["_ppi"]
@@ -118,6 +127,7 @@ _ns = []
118_ppi = [] 127_ppi = []
119_dppi = [] 128_dppi = []
120_gpio-p1 = [] 129_gpio-p1 = []
130_gpio-p2 = []
121 131
122# Errata workarounds 132# Errata workarounds
123_nrf52832_anomaly_109 = [] 133_nrf52832_anomaly_109 = []
@@ -136,7 +146,7 @@ embedded-hal-async = { version = "1.0" }
136embedded-io = { version = "0.6.0" } 146embedded-io = { version = "0.6.0" }
137embedded-io-async = { version = "0.6.1" } 147embedded-io-async = { version = "0.6.1" }
138 148
139nrf-pac = { git = "https://github.com/embassy-rs/nrf-pac", rev = "12e2461859acb0bfea9b2ef5cd73f1283c139ac0" } 149nrf-pac = { git = "https://github.com/embassy-rs/nrf-pac", rev = "52e3a757f06035c94291bfc42b0c03f71e4d677e" }
140 150
141defmt = { version = "0.3", optional = true } 151defmt = { version = "0.3", optional = true }
142bitflags = "2.4.2" 152bitflags = "2.4.2"
diff --git a/embassy-nrf/src/chips/nrf54l15_app.rs b/embassy-nrf/src/chips/nrf54l15_app.rs
new file mode 100644
index 000000000..b133eb565
--- /dev/null
+++ b/embassy-nrf/src/chips/nrf54l15_app.rs
@@ -0,0 +1,346 @@
1/// Peripheral Access Crate
2#[allow(unused_imports)]
3#[rustfmt::skip]
4pub mod pac {
5 pub use nrf_pac::*;
6
7 #[cfg(feature = "_ns")]
8 #[doc(no_inline)]
9 pub use nrf_pac::{
10 FICR_NS as FICR,
11 DPPIC00_NS as DPPIC00,
12 PPIB00_NS as PPIB00,
13 PPIB01_NS as PPIB01,
14 AAR00_NS as AAR00,
15 CCM00_NS as CCM00,
16 ECB00_NS as ECB00,
17 SPIM00_NS as SPIM00,
18 SPIS00_NS as SPIS00,
19 UARTE00_NS as UARTE00,
20 VPR00_NS as VPR00,
21 P2_NS as P2,
22 CTRLAP_NS as CTRLAP,
23 TAD_NS as TAD,
24 TIMER00_NS as TIMER00,
25 DPPIC10_NS as DPPIC10,
26 PPIB10_NS as PPIB10,
27 PPIB11_NS as PPIB11,
28 TIMER10_NS as TIMER10,
29 RTC10_NS as RTC10,
30 EGU10_NS as EGU10,
31 RADIO_NS as RADIO,
32 DPPIC20_NS as DPPIC20,
33 PPIB20_NS as PPIB20,
34 PPIB21_NS as PPIB21,
35 PPIB22_NS as PPIB22,
36 SPIM20_NS as SPIM20,
37 SPIS20_NS as SPIS20,
38 TWIM20_NS as TWIM20,
39 TWIS20_NS as TWIS20,
40 UARTE20_NS as UARTE20,
41 SPIM21_NS as SPIM21,
42 SPIS21_NS as SPIS21,
43 TWIM21_NS as TWIM21,
44 TWIS21_NS as TWIS21,
45 UARTE21_NS as UARTE21,
46 SPIM22_NS as SPIM22,
47 SPIS22_NS as SPIS22,
48 TWIM22_NS as TWIM22,
49 TWIS22_NS as TWIS22,
50 UARTE22_NS as UARTE22,
51 EGU20_NS as EGU20,
52 TIMER20_NS as TIMER20,
53 TIMER21_NS as TIMER21,
54 TIMER22_NS as TIMER22,
55 TIMER23_NS as TIMER23,
56 TIMER24_NS as TIMER24,
57 MEMCONF_NS as MEMCONF,
58 PDM20_NS as PDM20,
59 PDM21_NS as PDM21,
60 PWM20_NS as PWM20,
61 PWM21_NS as PWM21,
62 PWM22_NS as PWM22,
63 SAADC_NS as SAADC,
64 NFCT_NS as NFCT,
65 TEMP_NS as TEMP,
66 P1_NS as P1,
67 GPIOTE20_NS as GPIOTE20,
68 I2S20_NS as I2S20,
69 QDEC20_NS as QDEC20,
70 QDEC21_NS as QDEC21,
71 GRTC_NS as GRTC,
72 DPPIC30_NS as DPPIC30,
73 PPIB30_NS as PPIB30,
74 SPIM30_NS as SPIM30,
75 SPIS30_NS as SPIS30,
76 TWIM30_NS as TWIM30,
77 TWIS30_NS as TWIS30,
78 UARTE30_NS as UARTE30,
79 RTC30_NS as RTC30,
80 COMP_NS as COMP,
81 LPCOMP_NS as LPCOMP,
82 WDT31_NS as WDT31,
83 P0_NS as P0,
84 GPIOTE30_NS as GPIOTE30,
85 CLOCK_NS as CLOCK,
86 POWER_NS as POWER,
87 RESET_NS as RESET,
88 OSCILLATORS_NS as OSCILLATORS,
89 REGULATORS_NS as REGULATORS,
90 TPIU_NS as TPIU,
91 ETM_NS as ETM,
92 };
93
94 #[cfg(feature = "_s")]
95 #[doc(no_inline)]
96 pub use nrf_pac::{
97 SICR_S as SICR,
98 ICACHEDATA_S as ICACHEDATA,
99 ICACHEINFO_S as ICACHEINFO,
100 SWI00_S as SWI00,
101 SWI01_S as SWI01,
102 SWI02_S as SWI02,
103 SWI03_S as SWI03,
104 SPU00_S as SPU00,
105 MPC00_S as MPC00,
106 DPPIC00_S as DPPIC00,
107 PPIB00_S as PPIB00,
108 PPIB01_S as PPIB01,
109 KMU_S as KMU,
110 AAR00_S as AAR00,
111 CCM00_S as CCM00,
112 ECB00_S as ECB00,
113 CRACEN_S as CRACEN,
114 SPIM00_S as SPIM00,
115 SPIS00_S as SPIS00,
116 UARTE00_S as UARTE00,
117 GLITCHDET_S as GLITCHDET,
118 RRAMC_S as RRAMC,
119 VPR00_S as VPR00,
120 P2_S as P2,
121 CTRLAP_S as CTRLAP,
122 TAD_S as TAD,
123 TIMER00_S as TIMER00,
124 SPU10_S as SPU10,
125 DPPIC10_S as DPPIC10,
126 PPIB10_S as PPIB10,
127 PPIB11_S as PPIB11,
128 TIMER10_S as TIMER10,
129 RTC10_S as RTC10,
130 EGU10_S as EGU10,
131 RADIO_S as RADIO,
132 SPU20_S as SPU20,
133 DPPIC20_S as DPPIC20,
134 PPIB20_S as PPIB20,
135 PPIB21_S as PPIB21,
136 PPIB22_S as PPIB22,
137 SPIM20_S as SPIM20,
138 SPIS20_S as SPIS20,
139 TWIM20_S as TWIM20,
140 TWIS20_S as TWIS20,
141 UARTE20_S as UARTE20,
142 SPIM21_S as SPIM21,
143 SPIS21_S as SPIS21,
144 TWIM21_S as TWIM21,
145 TWIS21_S as TWIS21,
146 UARTE21_S as UARTE21,
147 SPIM22_S as SPIM22,
148 SPIS22_S as SPIS22,
149 TWIM22_S as TWIM22,
150 TWIS22_S as TWIS22,
151 UARTE22_S as UARTE22,
152 EGU20_S as EGU20,
153 TIMER20_S as TIMER20,
154 TIMER21_S as TIMER21,
155 TIMER22_S as TIMER22,
156 TIMER23_S as TIMER23,
157 TIMER24_S as TIMER24,
158 MEMCONF_S as MEMCONF,
159 PDM20_S as PDM20,
160 PDM21_S as PDM21,
161 PWM20_S as PWM20,
162 PWM21_S as PWM21,
163 PWM22_S as PWM22,
164 SAADC_S as SAADC,
165 NFCT_S as NFCT,
166 TEMP_S as TEMP,
167 P1_S as P1,
168 GPIOTE20_S as GPIOTE20,
169 TAMPC_S as TAMPC,
170 I2S20_S as I2S20,
171 QDEC20_S as QDEC20,
172 QDEC21_S as QDEC21,
173 GRTC_S as GRTC,
174 SPU30_S as SPU30,
175 DPPIC30_S as DPPIC30,
176 PPIB30_S as PPIB30,
177 SPIM30_S as SPIM30,
178 SPIS30_S as SPIS30,
179 TWIM30_S as TWIM30,
180 TWIS30_S as TWIS30,
181 UARTE30_S as UARTE30,
182 RTC30_S as RTC30,
183 COMP_S as COMP,
184 LPCOMP_S as LPCOMP,
185 WDT30_S as WDT30,
186 WDT31_S as WDT31,
187 P0_S as P0,
188 GPIOTE30_S as GPIOTE30,
189 CLOCK_S as CLOCK,
190 POWER_S as POWER,
191 RESET_S as RESET,
192 OSCILLATORS_S as OSCILLATORS,
193 REGULATORS_S as REGULATORS,
194 CRACENCORE_S as CRACENCORE,
195 CPUC_S as CPUC,
196 ICACHE_S as ICACHE,
197 };
198}
199
200/// The maximum buffer size that the EasyDMA can send/recv in one operation.
201pub const EASY_DMA_SIZE: usize = (1 << 16) - 1;
202//pub const FORCE_COPY_BUFFER_SIZE: usize = 1024;
203
204//pub const FLASH_SIZE: usize = 1024 * 1024;
205
206embassy_hal_internal::peripherals! {
207 // GPIO port 0
208 P0_00,
209 P0_01,
210 P0_02,
211 P0_03,
212 P0_04,
213 P0_05,
214 P0_06,
215
216 // GPIO port 1
217 P1_00,
218 P1_01,
219 P1_02,
220 P1_03,
221 P1_04,
222 P1_05,
223 P1_06,
224 P1_07,
225 P1_08,
226 P1_09,
227 P1_10,
228 P1_11,
229 P1_12,
230 P1_13,
231 P1_14,
232 P1_15,
233 P1_16,
234
235
236 // GPIO port 2
237 P2_00,
238 P2_01,
239 P2_02,
240 P2_03,
241 P2_04,
242 P2_05,
243 P2_06,
244 P2_07,
245 P2_08,
246 P2_09,
247 P2_10,
248}
249
250impl_pin!(P0_00, 0, 0);
251impl_pin!(P0_01, 0, 1);
252impl_pin!(P0_02, 0, 2);
253impl_pin!(P0_03, 0, 3);
254impl_pin!(P0_04, 0, 4);
255impl_pin!(P0_05, 0, 5);
256impl_pin!(P0_06, 0, 6);
257
258impl_pin!(P1_00, 1, 0);
259impl_pin!(P1_01, 1, 1);
260impl_pin!(P1_02, 1, 2);
261impl_pin!(P1_03, 1, 3);
262impl_pin!(P1_04, 1, 4);
263impl_pin!(P1_05, 1, 5);
264impl_pin!(P1_06, 1, 6);
265impl_pin!(P1_07, 1, 7);
266impl_pin!(P1_08, 1, 8);
267impl_pin!(P1_09, 1, 9);
268impl_pin!(P1_10, 1, 10);
269impl_pin!(P1_11, 1, 11);
270impl_pin!(P1_12, 1, 12);
271impl_pin!(P1_13, 1, 13);
272impl_pin!(P1_14, 1, 14);
273impl_pin!(P1_15, 1, 15);
274impl_pin!(P1_16, 1, 16);
275
276impl_pin!(P2_00, 2, 0);
277impl_pin!(P2_01, 2, 1);
278impl_pin!(P2_02, 2, 2);
279impl_pin!(P2_03, 2, 3);
280impl_pin!(P2_04, 2, 4);
281impl_pin!(P2_05, 2, 5);
282impl_pin!(P2_06, 2, 6);
283impl_pin!(P2_07, 2, 7);
284impl_pin!(P2_08, 2, 8);
285impl_pin!(P2_09, 2, 9);
286impl_pin!(P2_10, 2, 10);
287
288embassy_hal_internal::interrupt_mod!(
289 SWI00,
290 SWI01,
291 SWI02,
292 SWI03,
293 SPU00,
294 MPC00,
295 AAR00_CCM00,
296 ECB00,
297 CRACEN,
298 SERIAL00,
299 RRAMC,
300 VPR00,
301 CTRLAP,
302 TIMER00,
303 SPU10,
304 TIMER10,
305 RTC10,
306 EGU10,
307 RADIO_0,
308 RADIO_1,
309 SPU20,
310 SERIAL20,
311 SERIAL21,
312 SERIAL22,
313 EGU20,
314 TIMER20,
315 TIMER21,
316 TIMER22,
317 TIMER23,
318 TIMER24,
319 PDM20,
320 PDM21,
321 PWM20,
322 PWM21,
323 PWM22,
324 SAADC,
325 NFCT,
326 TEMP,
327 GPIOTE20_0,
328 GPIOTE20_1,
329 TAMPC,
330 I2S20,
331 QDEC20,
332 QDEC21,
333 GRTC_0,
334 GRTC_1,
335 GRTC_2,
336 GRTC_3,
337 SPU30,
338 SERIAL30,
339 RTC30,
340 COMP_LPCOMP,
341 WDT30,
342 WDT31,
343 GPIOTE30_0,
344 GPIOTE30_1,
345 CLOCK_POWER,
346);
diff --git a/embassy-nrf/src/gpio.rs b/embassy-nrf/src/gpio.rs
index 35b0f2e7b..d271dbcff 100644
--- a/embassy-nrf/src/gpio.rs
+++ b/embassy-nrf/src/gpio.rs
@@ -23,6 +23,10 @@ pub enum Port {
23 /// Port 1, only available on some MCUs. 23 /// Port 1, only available on some MCUs.
24 #[cfg(feature = "_gpio-p1")] 24 #[cfg(feature = "_gpio-p1")]
25 Port1, 25 Port1,
26
27 /// Port 2, only available on some MCUs.
28 #[cfg(feature = "_gpio-p2")]
29 Port2,
26} 30}
27 31
28/// Pull setting for an input. 32/// Pull setting for an input.
@@ -99,8 +103,83 @@ impl From<Level> for bool {
99 } 103 }
100} 104}
101 105
106/// Drive strength settings for a given output level.
107// These numbers match vals::Drive exactly so hopefully the compiler will unify them.
108#[cfg(feature = "_nrf54l")]
109#[derive(Clone, Copy, Debug, PartialEq)]
110#[cfg_attr(feature = "defmt", derive(defmt::Format))]
111#[repr(u8)]
112pub enum LevelDrive {
113 /// Disconnect (do not drive the output at all)
114 Disconnect = 2,
115 /// Standard
116 Standard = 0,
117 /// High drive
118 High = 1,
119 /// Extra high drive
120 ExtraHigh = 3,
121}
122
123/// Drive strength settings for an output pin.
124///
125/// This is a combination of two drive levels, used when the pin is set
126/// low and high respectively.
127#[cfg(feature = "_nrf54l")]
128#[derive(Clone, Copy, Debug, PartialEq)]
129#[cfg_attr(feature = "defmt", derive(defmt::Format))]
130pub struct OutputDrive {
131 low: LevelDrive,
132 high: LevelDrive,
133}
134
135#[cfg(feature = "_nrf54l")]
136#[allow(non_upper_case_globals)]
137impl OutputDrive {
138 /// Standard '0', standard '1'
139 pub const Standard: Self = Self {
140 low: LevelDrive::Standard,
141 high: LevelDrive::Standard,
142 };
143 /// High drive '0', standard '1'
144 pub const HighDrive0Standard1: Self = Self {
145 low: LevelDrive::High,
146 high: LevelDrive::Standard,
147 };
148 /// Standard '0', high drive '1'
149 pub const Standard0HighDrive1: Self = Self {
150 low: LevelDrive::Standard,
151 high: LevelDrive::High,
152 };
153 /// High drive '0', high 'drive '1'
154 pub const HighDrive: Self = Self {
155 low: LevelDrive::High,
156 high: LevelDrive::High,
157 };
158 /// Disconnect '0' standard '1' (normally used for wired-or connections)
159 pub const Disconnect0Standard1: Self = Self {
160 low: LevelDrive::Disconnect,
161 high: LevelDrive::Standard,
162 };
163 /// Disconnect '0', high drive '1' (normally used for wired-or connections)
164 pub const Disconnect0HighDrive1: Self = Self {
165 low: LevelDrive::Disconnect,
166 high: LevelDrive::High,
167 };
168 /// Standard '0'. disconnect '1' (also known as "open drain", normally used for wired-and connections)
169 pub const Standard0Disconnect1: Self = Self {
170 low: LevelDrive::Standard,
171 high: LevelDrive::Disconnect,
172 };
173 /// High drive '0', disconnect '1' (also known as "open drain", normally used for wired-and connections)
174 pub const HighDrive0Disconnect1: Self = Self {
175 low: LevelDrive::High,
176 high: LevelDrive::Disconnect,
177 };
178}
179
102/// Drive strength settings for an output pin. 180/// Drive strength settings for an output pin.
103// These numbers match vals::Drive exactly so hopefully the compiler will unify them. 181// These numbers match vals::Drive exactly so hopefully the compiler will unify them.
182#[cfg(not(feature = "_nrf54l"))]
104#[derive(Clone, Copy, Debug, PartialEq)] 183#[derive(Clone, Copy, Debug, PartialEq)]
105#[cfg_attr(feature = "defmt", derive(defmt::Format))] 184#[cfg_attr(feature = "defmt", derive(defmt::Format))]
106#[repr(u8)] 185#[repr(u8)]
@@ -185,16 +264,35 @@ impl<'d> Output<'d> {
185 } 264 }
186} 265}
187 266
188pub(crate) fn convert_drive(drive: OutputDrive) -> vals::Drive { 267pub(crate) fn convert_drive(w: &mut pac::gpio::regs::PinCnf, drive: OutputDrive) {
189 match drive { 268 #[cfg(not(feature = "_nrf54l"))]
190 OutputDrive::Standard => vals::Drive::S0S1, 269 {
191 OutputDrive::HighDrive0Standard1 => vals::Drive::H0S1, 270 let drive = match drive {
192 OutputDrive::Standard0HighDrive1 => vals::Drive::S0H1, 271 OutputDrive::Standard => vals::Drive::S0S1,
193 OutputDrive::HighDrive => vals::Drive::H0H1, 272 OutputDrive::HighDrive0Standard1 => vals::Drive::H0S1,
194 OutputDrive::Disconnect0Standard1 => vals::Drive::D0S1, 273 OutputDrive::Standard0HighDrive1 => vals::Drive::S0H1,
195 OutputDrive::Disconnect0HighDrive1 => vals::Drive::D0H1, 274 OutputDrive::HighDrive => vals::Drive::H0H1,
196 OutputDrive::Standard0Disconnect1 => vals::Drive::S0D1, 275 OutputDrive::Disconnect0Standard1 => vals::Drive::D0S1,
197 OutputDrive::HighDrive0Disconnect1 => vals::Drive::H0D1, 276 OutputDrive::Disconnect0HighDrive1 => vals::Drive::D0H1,
277 OutputDrive::Standard0Disconnect1 => vals::Drive::S0D1,
278 OutputDrive::HighDrive0Disconnect1 => vals::Drive::H0D1,
279 };
280 w.set_drive(drive);
281 }
282
283 #[cfg(feature = "_nrf54l")]
284 {
285 fn convert(d: LevelDrive) -> vals::Drive {
286 match d {
287 LevelDrive::Disconnect => vals::Drive::D,
288 LevelDrive::Standard => vals::Drive::S,
289 LevelDrive::High => vals::Drive::H,
290 LevelDrive::ExtraHigh => vals::Drive::E,
291 }
292 }
293
294 w.set_drive0(convert(drive.low));
295 w.set_drive0(convert(drive.high));
198 } 296 }
199} 297}
200 298
@@ -234,7 +332,7 @@ impl<'d> Flex<'d> {
234 w.set_dir(vals::Dir::INPUT); 332 w.set_dir(vals::Dir::INPUT);
235 w.set_input(vals::Input::CONNECT); 333 w.set_input(vals::Input::CONNECT);
236 w.set_pull(convert_pull(pull)); 334 w.set_pull(convert_pull(pull));
237 w.set_drive(vals::Drive::S0S1); 335 convert_drive(w, OutputDrive::Standard);
238 w.set_sense(vals::Sense::DISABLED); 336 w.set_sense(vals::Sense::DISABLED);
239 }); 337 });
240 } 338 }
@@ -249,9 +347,10 @@ impl<'d> Flex<'d> {
249 w.set_dir(vals::Dir::OUTPUT); 347 w.set_dir(vals::Dir::OUTPUT);
250 w.set_input(vals::Input::DISCONNECT); 348 w.set_input(vals::Input::DISCONNECT);
251 w.set_pull(vals::Pull::DISABLED); 349 w.set_pull(vals::Pull::DISABLED);
252 w.set_drive(convert_drive(drive)); 350 convert_drive(w, drive);
253 w.set_sense(vals::Sense::DISABLED); 351 w.set_sense(vals::Sense::DISABLED);
254 }); 352 });
353 info!("pin_cnf: {:08x}", self.pin.conf().read().0);
255 } 354 }
256 355
257 /// Put the pin into input + output mode. 356 /// Put the pin into input + output mode.
@@ -269,7 +368,7 @@ impl<'d> Flex<'d> {
269 w.set_dir(vals::Dir::OUTPUT); 368 w.set_dir(vals::Dir::OUTPUT);
270 w.set_input(vals::Input::CONNECT); 369 w.set_input(vals::Input::CONNECT);
271 w.set_pull(convert_pull(pull)); 370 w.set_pull(convert_pull(pull));
272 w.set_drive(convert_drive(drive)); 371 convert_drive(w, drive);
273 w.set_sense(vals::Sense::DISABLED); 372 w.set_sense(vals::Sense::DISABLED);
274 }); 373 });
275 } 374 }
@@ -377,6 +476,8 @@ pub(crate) trait SealedPin {
377 0 => pac::P0, 476 0 => pac::P0,
378 #[cfg(feature = "_gpio-p1")] 477 #[cfg(feature = "_gpio-p1")]
379 1 => pac::P1, 478 1 => pac::P1,
479 #[cfg(feature = "_gpio-p2")]
480 2 => pac::P2,
380 _ => unsafe { unreachable_unchecked() }, 481 _ => unsafe { unreachable_unchecked() },
381 } 482 }
382 } 483 }
@@ -415,6 +516,8 @@ pub trait Pin: Peripheral<P = Self> + Into<AnyPin> + SealedPin + Sized + 'static
415 0 => Port::Port0, 516 0 => Port::Port0,
416 #[cfg(feature = "_gpio-p1")] 517 #[cfg(feature = "_gpio-p1")]
417 1 => Port::Port1, 518 1 => Port::Port1,
519 #[cfg(feature = "_gpio-p2")]
520 2 => Port::Port2,
418 _ => unsafe { unreachable_unchecked() }, 521 _ => unsafe { unreachable_unchecked() },
419 } 522 }
420 } 523 }
@@ -463,6 +566,7 @@ impl SealedPin for AnyPin {
463// ==================== 566// ====================
464 567
465#[cfg(not(feature = "_nrf51"))] 568#[cfg(not(feature = "_nrf51"))]
569#[cfg_attr(feature = "_nrf54l", allow(unused))] // TODO
466pub(crate) trait PselBits { 570pub(crate) trait PselBits {
467 fn psel_bits(&self) -> pac::shared::regs::Psel; 571 fn psel_bits(&self) -> pac::shared::regs::Psel;
468} 572}
@@ -479,6 +583,7 @@ impl<'a, P: Pin> PselBits for Option<PeripheralRef<'a, P>> {
479} 583}
480 584
481#[cfg(not(feature = "_nrf51"))] 585#[cfg(not(feature = "_nrf51"))]
586#[cfg_attr(feature = "_nrf54l", allow(unused))] // TODO
482pub(crate) const DISCONNECTED: Psel = Psel(1 << 31); 587pub(crate) const DISCONNECTED: Psel = Psel(1 << 31);
483 588
484#[cfg(not(feature = "_nrf51"))] 589#[cfg(not(feature = "_nrf51"))]
diff --git a/embassy-nrf/src/lib.rs b/embassy-nrf/src/lib.rs
index 8167b44f3..33111e1bd 100644
--- a/embassy-nrf/src/lib.rs
+++ b/embassy-nrf/src/lib.rs
@@ -22,6 +22,8 @@
22 feature = "nrf5340-app-s", 22 feature = "nrf5340-app-s",
23 feature = "nrf5340-app-ns", 23 feature = "nrf5340-app-ns",
24 feature = "nrf5340-net", 24 feature = "nrf5340-net",
25 feature = "nrf54l15-app-s",
26 feature = "nrf54l15-app-ns",
25 feature = "nrf9160-s", 27 feature = "nrf9160-s",
26 feature = "nrf9160-ns", 28 feature = "nrf9160-ns",
27 feature = "nrf9120-s", 29 feature = "nrf9120-s",
@@ -44,6 +46,8 @@ compile_error!(
44 nrf5340-app-s, 46 nrf5340-app-s,
45 nrf5340-app-ns, 47 nrf5340-app-ns,
46 nrf5340-net, 48 nrf5340-net,
49 nrf54l15-app-s,
50 nrf54l15-app-ns,
47 nrf9160-s, 51 nrf9160-s,
48 nrf9160-ns, 52 nrf9160-ns,
49 nrf9120-s, 53 nrf9120-s,
@@ -68,21 +72,22 @@ pub(crate) mod util;
68#[cfg(feature = "_time-driver")] 72#[cfg(feature = "_time-driver")]
69mod time_driver; 73mod time_driver;
70 74
75#[cfg(not(feature = "_nrf54l"))] // TODO
71#[cfg(not(feature = "_nrf51"))] 76#[cfg(not(feature = "_nrf51"))]
72pub mod buffered_uarte; 77pub mod buffered_uarte;
78#[cfg(not(feature = "_nrf54l"))] // TODO
79#[cfg(not(feature = "_nrf51"))]
80pub mod egu;
73pub mod gpio; 81pub mod gpio;
82#[cfg(not(feature = "_nrf54l"))] // TODO
74#[cfg(feature = "gpiote")] 83#[cfg(feature = "gpiote")]
75pub mod gpiote; 84pub mod gpiote;
76 85#[cfg(not(feature = "_nrf54l"))] // TODO
77// TODO: tested on other chips
78#[cfg(not(any(feature = "_nrf91", feature = "_nrf5340-app")))]
79pub mod radio;
80
81#[cfg(not(feature = "_nrf51"))]
82pub mod egu;
83#[cfg(any(feature = "nrf52832", feature = "nrf52833", feature = "nrf52840"))] 86#[cfg(any(feature = "nrf52832", feature = "nrf52833", feature = "nrf52840"))]
84pub mod i2s; 87pub mod i2s;
88#[cfg(not(feature = "_nrf54l"))] // TODO
85pub mod nvmc; 89pub mod nvmc;
90#[cfg(not(feature = "_nrf54l"))] // TODO
86#[cfg(any( 91#[cfg(any(
87 feature = "nrf52810", 92 feature = "nrf52810",
88 feature = "nrf52811", 93 feature = "nrf52811",
@@ -93,7 +98,9 @@ pub mod nvmc;
93 feature = "_nrf91", 98 feature = "_nrf91",
94))] 99))]
95pub mod pdm; 100pub mod pdm;
101#[cfg(not(feature = "_nrf54l"))] // TODO
96pub mod ppi; 102pub mod ppi;
103#[cfg(not(feature = "_nrf54l"))] // TODO
97#[cfg(not(any( 104#[cfg(not(any(
98 feature = "_nrf51", 105 feature = "_nrf51",
99 feature = "nrf52805", 106 feature = "nrf52805",
@@ -101,27 +108,42 @@ pub mod ppi;
101 feature = "_nrf5340-net" 108 feature = "_nrf5340-net"
102)))] 109)))]
103pub mod pwm; 110pub mod pwm;
111#[cfg(not(feature = "_nrf54l"))] // TODO
104#[cfg(not(any(feature = "_nrf51", feature = "_nrf91", feature = "_nrf5340-net")))] 112#[cfg(not(any(feature = "_nrf51", feature = "_nrf91", feature = "_nrf5340-net")))]
105pub mod qdec; 113pub mod qdec;
114#[cfg(not(feature = "_nrf54l"))] // TODO
106#[cfg(any(feature = "nrf52840", feature = "_nrf5340-app"))] 115#[cfg(any(feature = "nrf52840", feature = "_nrf5340-app"))]
107pub mod qspi; 116pub mod qspi;
117#[cfg(not(feature = "_nrf54l"))] // TODO
118#[cfg(not(any(feature = "_nrf91", feature = "_nrf5340-app")))]
119pub mod radio;
120#[cfg(not(feature = "_nrf54l"))] // TODO
108#[cfg(not(any(feature = "_nrf5340-app", feature = "_nrf91")))] 121#[cfg(not(any(feature = "_nrf5340-app", feature = "_nrf91")))]
109pub mod rng; 122pub mod rng;
123#[cfg(not(feature = "_nrf54l"))] // TODO
110#[cfg(not(any(feature = "_nrf51", feature = "nrf52820", feature = "_nrf5340-net")))] 124#[cfg(not(any(feature = "_nrf51", feature = "nrf52820", feature = "_nrf5340-net")))]
111pub mod saadc; 125pub mod saadc;
126#[cfg(not(feature = "_nrf54l"))] // TODO
112#[cfg(not(feature = "_nrf51"))] 127#[cfg(not(feature = "_nrf51"))]
113pub mod spim; 128pub mod spim;
129#[cfg(not(feature = "_nrf54l"))] // TODO
114#[cfg(not(feature = "_nrf51"))] 130#[cfg(not(feature = "_nrf51"))]
115pub mod spis; 131pub mod spis;
132#[cfg(not(feature = "_nrf54l"))] // TODO
116#[cfg(not(any(feature = "_nrf5340", feature = "_nrf91")))] 133#[cfg(not(any(feature = "_nrf5340", feature = "_nrf91")))]
117pub mod temp; 134pub mod temp;
135#[cfg(not(feature = "_nrf54l"))] // TODO
118pub mod timer; 136pub mod timer;
137#[cfg(not(feature = "_nrf54l"))] // TODO
119#[cfg(not(feature = "_nrf51"))] 138#[cfg(not(feature = "_nrf51"))]
120pub mod twim; 139pub mod twim;
140#[cfg(not(feature = "_nrf54l"))] // TODO
121#[cfg(not(feature = "_nrf51"))] 141#[cfg(not(feature = "_nrf51"))]
122pub mod twis; 142pub mod twis;
143#[cfg(not(feature = "_nrf54l"))] // TODO
123#[cfg(not(feature = "_nrf51"))] 144#[cfg(not(feature = "_nrf51"))]
124pub mod uarte; 145pub mod uarte;
146#[cfg(not(feature = "_nrf54l"))] // TODO
125#[cfg(any( 147#[cfg(any(
126 feature = "_nrf5340-app", 148 feature = "_nrf5340-app",
127 feature = "nrf52820", 149 feature = "nrf52820",
@@ -129,6 +151,7 @@ pub mod uarte;
129 feature = "nrf52840" 151 feature = "nrf52840"
130))] 152))]
131pub mod usb; 153pub mod usb;
154#[cfg(not(feature = "_nrf54l"))] // TODO
132#[cfg(not(feature = "_nrf5340"))] 155#[cfg(not(feature = "_nrf5340"))]
133pub mod wdt; 156pub mod wdt;
134 157
@@ -143,6 +166,7 @@ pub mod wdt;
143#[cfg_attr(feature = "nrf52840", path = "chips/nrf52840.rs")] 166#[cfg_attr(feature = "nrf52840", path = "chips/nrf52840.rs")]
144#[cfg_attr(feature = "_nrf5340-app", path = "chips/nrf5340_app.rs")] 167#[cfg_attr(feature = "_nrf5340-app", path = "chips/nrf5340_app.rs")]
145#[cfg_attr(feature = "_nrf5340-net", path = "chips/nrf5340_net.rs")] 168#[cfg_attr(feature = "_nrf5340-net", path = "chips/nrf5340_net.rs")]
169#[cfg_attr(feature = "_nrf54l15-app", path = "chips/nrf54l15_app.rs")]
146#[cfg_attr(feature = "_nrf9160", path = "chips/nrf9160.rs")] 170#[cfg_attr(feature = "_nrf9160", path = "chips/nrf9160.rs")]
147#[cfg_attr(feature = "_nrf9120", path = "chips/nrf9120.rs")] 171#[cfg_attr(feature = "_nrf9120", path = "chips/nrf9120.rs")]
148mod chip; 172mod chip;
@@ -249,10 +273,10 @@ pub mod config {
249 /// External source from xtal. 273 /// External source from xtal.
250 ExternalXtal, 274 ExternalXtal,
251 /// External source from xtal with low swing applied. 275 /// External source from xtal with low swing applied.
252 #[cfg(not(any(feature = "_nrf5340", feature = "_nrf91")))] 276 #[cfg(not(any(feature = "_nrf5340", feature = "_nrf91", feature = "_nrf54l")))]
253 ExternalLowSwing, 277 ExternalLowSwing,
254 /// External source from xtal with full swing applied. 278 /// External source from xtal with full swing applied.
255 #[cfg(not(any(feature = "_nrf5340", feature = "_nrf91")))] 279 #[cfg(not(any(feature = "_nrf5340", feature = "_nrf91", feature = "_nrf54l")))]
256 ExternalFullSwing, 280 ExternalFullSwing,
257 } 281 }
258 282
@@ -325,7 +349,7 @@ pub mod config {
325 pub hfclk_source: HfclkSource, 349 pub hfclk_source: HfclkSource,
326 /// Low frequency clock source. 350 /// Low frequency clock source.
327 pub lfclk_source: LfclkSource, 351 pub lfclk_source: LfclkSource,
328 #[cfg(not(feature = "_nrf5340-net"))] 352 #[cfg(not(any(feature = "_nrf5340-net", feature = "_nrf54l")))]
329 /// DCDC configuration. 353 /// DCDC configuration.
330 pub dcdc: DcdcConfig, 354 pub dcdc: DcdcConfig,
331 /// GPIOTE interrupt priority. Should be lower priority than softdevice if used. 355 /// GPIOTE interrupt priority. Should be lower priority than softdevice if used.
@@ -346,7 +370,7 @@ pub mod config {
346 // xtals if they know they have them. 370 // xtals if they know they have them.
347 hfclk_source: HfclkSource::Internal, 371 hfclk_source: HfclkSource::Internal,
348 lfclk_source: LfclkSource::InternalRC, 372 lfclk_source: LfclkSource::InternalRC,
349 #[cfg(not(any(feature = "_nrf5340", feature = "_nrf91")))] 373 #[cfg(not(any(feature = "_nrf5340", feature = "_nrf91", feature = "_nrf54l")))]
350 dcdc: DcdcConfig { 374 dcdc: DcdcConfig {
351 #[cfg(feature = "nrf52840")] 375 #[cfg(feature = "nrf52840")]
352 reg0: false, 376 reg0: false,
@@ -415,7 +439,7 @@ mod consts {
415 pub const APPROTECT_DISABLED: u32 = 0x0000_005a; 439 pub const APPROTECT_DISABLED: u32 = 0x0000_005a;
416} 440}
417 441
418#[cfg(not(feature = "_nrf51"))] 442#[cfg(not(any(feature = "_nrf51", feature = "_nrf54l")))]
419#[derive(Debug, Copy, Clone, Eq, PartialEq)] 443#[derive(Debug, Copy, Clone, Eq, PartialEq)]
420#[cfg_attr(feature = "defmt", derive(defmt::Format))] 444#[cfg_attr(feature = "defmt", derive(defmt::Format))]
421enum WriteResult { 445enum WriteResult {
@@ -427,12 +451,12 @@ enum WriteResult {
427 Failed, 451 Failed,
428} 452}
429 453
430#[cfg(not(feature = "_nrf51"))] 454#[cfg(not(any(feature = "_nrf51", feature = "_nrf54l")))]
431unsafe fn uicr_write(address: *mut u32, value: u32) -> WriteResult { 455unsafe fn uicr_write(address: *mut u32, value: u32) -> WriteResult {
432 uicr_write_masked(address, value, 0xFFFF_FFFF) 456 uicr_write_masked(address, value, 0xFFFF_FFFF)
433} 457}
434 458
435#[cfg(not(feature = "_nrf51"))] 459#[cfg(not(any(feature = "_nrf51", feature = "_nrf54l")))]
436unsafe fn uicr_write_masked(address: *mut u32, value: u32, mask: u32) -> WriteResult { 460unsafe fn uicr_write_masked(address: *mut u32, value: u32, mask: u32) -> WriteResult {
437 let curr_val = address.read_volatile(); 461 let curr_val = address.read_volatile();
438 if curr_val & mask == value & mask { 462 if curr_val & mask == value & mask {
@@ -469,6 +493,7 @@ pub fn init(config: config::Config) -> Peripherals {
469 let mut needs_reset = false; 493 let mut needs_reset = false;
470 494
471 // Setup debug protection. 495 // Setup debug protection.
496 #[cfg(not(feature = "_nrf54l"))] // TODO
472 #[cfg(not(feature = "_nrf51"))] 497 #[cfg(not(feature = "_nrf51"))]
473 match config.debug { 498 match config.debug {
474 config::Debug::Allowed => { 499 config::Debug::Allowed => {
@@ -592,15 +617,25 @@ pub fn init(config: config::Config) -> Peripherals {
592 match config.hfclk_source { 617 match config.hfclk_source {
593 config::HfclkSource::Internal => {} 618 config::HfclkSource::Internal => {}
594 config::HfclkSource::ExternalXtal => { 619 config::HfclkSource::ExternalXtal => {
595 // Datasheet says this is likely to take 0.36ms 620 #[cfg(feature = "_nrf54l")]
596 r.events_hfclkstarted().write_value(0); 621 {
597 r.tasks_hfclkstart().write_value(1); 622 r.events_xostarted().write_value(0);
598 while r.events_hfclkstarted().read() == 0 {} 623 r.tasks_xostart().write_value(1);
624 while r.events_xostarted().read() == 0 {}
625 }
626
627 #[cfg(not(feature = "_nrf54l"))]
628 {
629 // Datasheet says this is likely to take 0.36ms
630 r.events_hfclkstarted().write_value(0);
631 r.tasks_hfclkstart().write_value(1);
632 while r.events_hfclkstarted().read() == 0 {}
633 }
599 } 634 }
600 } 635 }
601 636
602 // Configure LFCLK. 637 // Configure LFCLK.
603 #[cfg(not(any(feature = "_nrf51", feature = "_nrf5340", feature = "_nrf91")))] 638 #[cfg(not(any(feature = "_nrf51", feature = "_nrf5340", feature = "_nrf91", feature = "_nrf54l")))]
604 match config.lfclk_source { 639 match config.lfclk_source {
605 config::LfclkSource::InternalRC => r.lfclksrc().write(|w| w.set_src(pac::clock::vals::Lfclksrc::RC)), 640 config::LfclkSource::InternalRC => r.lfclksrc().write(|w| w.set_src(pac::clock::vals::Lfclksrc::RC)),
606 config::LfclkSource::Synthesized => r.lfclksrc().write(|w| w.set_src(pac::clock::vals::Lfclksrc::SYNTH)), 641 config::LfclkSource::Synthesized => r.lfclksrc().write(|w| w.set_src(pac::clock::vals::Lfclksrc::SYNTH)),
@@ -621,6 +656,12 @@ pub fn init(config: config::Config) -> Peripherals {
621 config::LfclkSource::InternalRC => r.lfclksrc().write(|w| w.set_src(pac::clock::vals::Lfclksrc::LFRC)), 656 config::LfclkSource::InternalRC => r.lfclksrc().write(|w| w.set_src(pac::clock::vals::Lfclksrc::LFRC)),
622 config::LfclkSource::ExternalXtal => r.lfclksrc().write(|w| w.set_src(pac::clock::vals::Lfclksrc::LFXO)), 657 config::LfclkSource::ExternalXtal => r.lfclksrc().write(|w| w.set_src(pac::clock::vals::Lfclksrc::LFXO)),
623 } 658 }
659 #[cfg(feature = "_nrf54l")]
660 match config.lfclk_source {
661 config::LfclkSource::InternalRC => r.lfclk().src().write(|w| w.set_src(pac::clock::vals::Lfclksrc::LFRC)),
662 config::LfclkSource::Synthesized => r.lfclk().src().write(|w| w.set_src(pac::clock::vals::Lfclksrc::LFSYNT)),
663 config::LfclkSource::ExternalXtal => r.lfclk().src().write(|w| w.set_src(pac::clock::vals::Lfclksrc::LFXO)),
664 }
624 665
625 // Start LFCLK. 666 // Start LFCLK.
626 // Datasheet says this could take 100us from synth source 667 // Datasheet says this could take 100us from synth source
@@ -629,7 +670,7 @@ pub fn init(config: config::Config) -> Peripherals {
629 r.tasks_lfclkstart().write_value(1); 670 r.tasks_lfclkstart().write_value(1);
630 while r.events_lfclkstarted().read() == 0 {} 671 while r.events_lfclkstarted().read() == 0 {}
631 672
632 #[cfg(not(any(feature = "_nrf5340", feature = "_nrf91")))] 673 #[cfg(not(any(feature = "_nrf5340", feature = "_nrf91", feature = "_nrf54l")))]
633 { 674 {
634 // Setup DCDCs. 675 // Setup DCDCs.
635 #[cfg(feature = "nrf52840")] 676 #[cfg(feature = "nrf52840")]
@@ -663,6 +704,7 @@ pub fn init(config: config::Config) -> Peripherals {
663 } 704 }
664 705
665 // Init GPIOTE 706 // Init GPIOTE
707 #[cfg(not(feature = "_nrf54l"))] // TODO
666 #[cfg(feature = "gpiote")] 708 #[cfg(feature = "gpiote")]
667 gpiote::init(config.gpiote_interrupt_priority); 709 gpiote::init(config.gpiote_interrupt_priority);
668 710
diff --git a/embassy-nrf/src/pwm.rs b/embassy-nrf/src/pwm.rs
index 7f1f568f4..6247ff6a5 100644
--- a/embassy-nrf/src/pwm.rs
+++ b/embassy-nrf/src/pwm.rs
@@ -133,7 +133,7 @@ impl<'d, T: Instance> SequencePwm<'d, T> {
133 pin.conf().write(|w| { 133 pin.conf().write(|w| {
134 w.set_dir(gpiovals::Dir::OUTPUT); 134 w.set_dir(gpiovals::Dir::OUTPUT);
135 w.set_input(gpiovals::Input::DISCONNECT); 135 w.set_input(gpiovals::Input::DISCONNECT);
136 w.set_drive(convert_drive(config.ch0_drive)); 136 convert_drive(w, config.ch0_drive);
137 }); 137 });
138 } 138 }
139 if let Some(pin) = &ch1 { 139 if let Some(pin) = &ch1 {
@@ -141,7 +141,7 @@ impl<'d, T: Instance> SequencePwm<'d, T> {
141 pin.conf().write(|w| { 141 pin.conf().write(|w| {
142 w.set_dir(gpiovals::Dir::OUTPUT); 142 w.set_dir(gpiovals::Dir::OUTPUT);
143 w.set_input(gpiovals::Input::DISCONNECT); 143 w.set_input(gpiovals::Input::DISCONNECT);
144 w.set_drive(convert_drive(config.ch1_drive)); 144 convert_drive(w, config.ch1_drive);
145 }); 145 });
146 } 146 }
147 if let Some(pin) = &ch2 { 147 if let Some(pin) = &ch2 {
@@ -149,7 +149,7 @@ impl<'d, T: Instance> SequencePwm<'d, T> {
149 pin.conf().write(|w| { 149 pin.conf().write(|w| {
150 w.set_dir(gpiovals::Dir::OUTPUT); 150 w.set_dir(gpiovals::Dir::OUTPUT);
151 w.set_input(gpiovals::Input::DISCONNECT); 151 w.set_input(gpiovals::Input::DISCONNECT);
152 w.set_drive(convert_drive(config.ch2_drive)); 152 convert_drive(w, config.ch2_drive);
153 }); 153 });
154 } 154 }
155 if let Some(pin) = &ch3 { 155 if let Some(pin) = &ch3 {
@@ -157,7 +157,7 @@ impl<'d, T: Instance> SequencePwm<'d, T> {
157 pin.conf().write(|w| { 157 pin.conf().write(|w| {
158 w.set_dir(gpiovals::Dir::OUTPUT); 158 w.set_dir(gpiovals::Dir::OUTPUT);
159 w.set_input(gpiovals::Input::DISCONNECT); 159 w.set_input(gpiovals::Input::DISCONNECT);
160 w.set_drive(convert_drive(config.ch3_drive)); 160 convert_drive(w, config.ch3_drive);
161 }); 161 });
162 } 162 }
163 163
@@ -832,7 +832,7 @@ impl<'d, T: Instance> SimplePwm<'d, T> {
832 #[inline(always)] 832 #[inline(always)]
833 pub fn set_ch0_drive(&self, drive: OutputDrive) { 833 pub fn set_ch0_drive(&self, drive: OutputDrive) {
834 if let Some(pin) = &self.ch0 { 834 if let Some(pin) = &self.ch0 {
835 pin.conf().modify(|w| w.set_drive(convert_drive(drive))); 835 pin.conf().modify(|w| convert_drive(w, drive));
836 } 836 }
837 } 837 }
838 838
@@ -840,7 +840,7 @@ impl<'d, T: Instance> SimplePwm<'d, T> {
840 #[inline(always)] 840 #[inline(always)]
841 pub fn set_ch1_drive(&self, drive: OutputDrive) { 841 pub fn set_ch1_drive(&self, drive: OutputDrive) {
842 if let Some(pin) = &self.ch1 { 842 if let Some(pin) = &self.ch1 {
843 pin.conf().modify(|w| w.set_drive(convert_drive(drive))); 843 pin.conf().modify(|w| convert_drive(w, drive));
844 } 844 }
845 } 845 }
846 846
@@ -848,7 +848,7 @@ impl<'d, T: Instance> SimplePwm<'d, T> {
848 #[inline(always)] 848 #[inline(always)]
849 pub fn set_ch2_drive(&self, drive: OutputDrive) { 849 pub fn set_ch2_drive(&self, drive: OutputDrive) {
850 if let Some(pin) = &self.ch2 { 850 if let Some(pin) = &self.ch2 {
851 pin.conf().modify(|w| w.set_drive(convert_drive(drive))); 851 pin.conf().modify(|w| convert_drive(w, drive));
852 } 852 }
853 } 853 }
854 854
@@ -856,7 +856,7 @@ impl<'d, T: Instance> SimplePwm<'d, T> {
856 #[inline(always)] 856 #[inline(always)]
857 pub fn set_ch3_drive(&self, drive: OutputDrive) { 857 pub fn set_ch3_drive(&self, drive: OutputDrive) {
858 if let Some(pin) = &self.ch3 { 858 if let Some(pin) = &self.ch3 {
859 pin.conf().modify(|w| w.set_drive(convert_drive(drive))); 859 pin.conf().modify(|w| convert_drive(w, drive));
860 } 860 }
861 } 861 }
862} 862}
diff --git a/embassy-nrf/src/spim.rs b/embassy-nrf/src/spim.rs
index ffaee2dc5..bd193cfe8 100644
--- a/embassy-nrf/src/spim.rs
+++ b/embassy-nrf/src/spim.rs
@@ -173,13 +173,13 @@ impl<'d, T: Instance> Spim<'d, T> {
173 if let Some(sck) = &sck { 173 if let Some(sck) = &sck {
174 sck.conf().write(|w| { 174 sck.conf().write(|w| {
175 w.set_dir(gpiovals::Dir::OUTPUT); 175 w.set_dir(gpiovals::Dir::OUTPUT);
176 w.set_drive(convert_drive(config.sck_drive)) 176 convert_drive(w, config.sck_drive);
177 }); 177 });
178 } 178 }
179 if let Some(mosi) = &mosi { 179 if let Some(mosi) = &mosi {
180 mosi.conf().write(|w| { 180 mosi.conf().write(|w| {
181 w.set_dir(gpiovals::Dir::OUTPUT); 181 w.set_dir(gpiovals::Dir::OUTPUT);
182 w.set_drive(convert_drive(config.mosi_drive)) 182 convert_drive(w, config.mosi_drive);
183 }); 183 });
184 } 184 }
185 if let Some(miso) = &miso { 185 if let Some(miso) = &miso {
diff --git a/embassy-nrf/src/spis.rs b/embassy-nrf/src/spis.rs
index a363e5909..88230fa26 100644
--- a/embassy-nrf/src/spis.rs
+++ b/embassy-nrf/src/spis.rs
@@ -203,7 +203,7 @@ impl<'d, T: Instance> Spis<'d, T> {
203 if let Some(miso) = &miso { 203 if let Some(miso) = &miso {
204 miso.conf().write(|w| { 204 miso.conf().write(|w| {
205 w.set_dir(gpiovals::Dir::OUTPUT); 205 w.set_dir(gpiovals::Dir::OUTPUT);
206 w.set_drive(convert_drive(config.miso_drive)) 206 convert_drive(w, config.miso_drive);
207 }); 207 });
208 r.psel().miso().write_value(miso.psel_bits()); 208 r.psel().miso().write_value(miso.psel_bits());
209 } 209 }
diff --git a/embassy-nrf/src/time_driver.rs b/embassy-nrf/src/time_driver.rs
index b6492ac97..81aabb11c 100644
--- a/embassy-nrf/src/time_driver.rs
+++ b/embassy-nrf/src/time_driver.rs
@@ -10,6 +10,11 @@ use embassy_time_driver::{AlarmHandle, Driver};
10use crate::interrupt::InterruptExt; 10use crate::interrupt::InterruptExt;
11use crate::{interrupt, pac}; 11use crate::{interrupt, pac};
12 12
13#[cfg(feature = "_nrf54l")]
14fn rtc() -> pac::rtc::Rtc {
15 pac::RTC30
16}
17#[cfg(not(feature = "_nrf54l"))]
13fn rtc() -> pac::rtc::Rtc { 18fn rtc() -> pac::rtc::Rtc {
14 pac::RTC1 19 pac::RTC1
15} 20}
@@ -141,8 +146,16 @@ impl RtcDriver {
141 // Wait for clear 146 // Wait for clear
142 while r.counter().read().0 != 0 {} 147 while r.counter().read().0 != 0 {}
143 148
144 interrupt::RTC1.set_priority(irq_prio); 149 #[cfg(feature = "_nrf54l")]
145 unsafe { interrupt::RTC1.enable() }; 150 {
151 interrupt::RTC30.set_priority(irq_prio);
152 unsafe { interrupt::RTC30.enable() };
153 }
154 #[cfg(not(feature = "_nrf54l"))]
155 {
156 interrupt::RTC1.set_priority(irq_prio);
157 unsafe { interrupt::RTC1.enable() };
158 }
146 } 159 }
147 160
148 fn on_interrupt(&self) { 161 fn on_interrupt(&self) {
@@ -292,6 +305,14 @@ impl Driver for RtcDriver {
292 } 305 }
293} 306}
294 307
308#[cfg(feature = "_nrf54l")]
309#[cfg(feature = "rt")]
310#[interrupt]
311fn RTC30() {
312 DRIVER.on_interrupt()
313}
314
315#[cfg(not(feature = "_nrf54l"))]
295#[cfg(feature = "rt")] 316#[cfg(feature = "rt")]
296#[interrupt] 317#[interrupt]
297fn RTC1() { 318fn RTC1() {
diff --git a/examples/nrf54l15/.cargo/config.toml b/examples/nrf54l15/.cargo/config.toml
new file mode 100644
index 000000000..4a026ebbd
--- /dev/null
+++ b/examples/nrf54l15/.cargo/config.toml
@@ -0,0 +1,9 @@
1[target.'cfg(all(target_arch = "arm", target_os = "none"))']
2# replace nRF82840_xxAA with your chip as listed in `probe-rs chip list`
3runner = "../../sshprobe.sh"
4
5[build]
6target = "thumbv8m.main-none-eabihf"
7
8[env]
9DEFMT_LOG = "trace"
diff --git a/examples/nrf54l15/Cargo.toml b/examples/nrf54l15/Cargo.toml
new file mode 100644
index 000000000..6d11269f7
--- /dev/null
+++ b/examples/nrf54l15/Cargo.toml
@@ -0,0 +1,20 @@
1[package]
2edition = "2021"
3name = "embassy-nrf54l15-examples"
4version = "0.1.0"
5license = "MIT OR Apache-2.0"
6
7[dependencies]
8embassy-executor = { version = "0.6.3", path = "../../embassy-executor", features = ["task-arena-size-32768", "arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] }
9embassy-time = { version = "0.3.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] }
10embassy-nrf = { version = "0.2.0", path = "../../embassy-nrf", features = ["defmt", "nrf54l15-app-s", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] }
11
12defmt = "0.3"
13defmt-rtt = "0.4"
14panic-probe = { version = "0.3", features = ["print-defmt"] }
15
16cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
17cortex-m-rt = "0.7.0"
18
19[profile.release]
20debug = 2
diff --git a/examples/nrf54l15/build.rs b/examples/nrf54l15/build.rs
new file mode 100644
index 000000000..30691aa97
--- /dev/null
+++ b/examples/nrf54l15/build.rs
@@ -0,0 +1,35 @@
1//! This build script copies the `memory.x` file from the crate root into
2//! a directory where the linker can always find it at build time.
3//! For many projects this is optional, as the linker always searches the
4//! project root directory -- wherever `Cargo.toml` is. However, if you
5//! are using a workspace or have a more complicated build setup, this
6//! build script becomes required. Additionally, by requesting that
7//! Cargo re-run the build script whenever `memory.x` is changed,
8//! updating `memory.x` ensures a rebuild of the application with the
9//! new memory settings.
10
11use std::env;
12use std::fs::File;
13use std::io::Write;
14use std::path::PathBuf;
15
16fn main() {
17 // Put `memory.x` in our output directory and ensure it's
18 // on the linker search path.
19 let out = &PathBuf::from(env::var_os("OUT_DIR").unwrap());
20 File::create(out.join("memory.x"))
21 .unwrap()
22 .write_all(include_bytes!("memory.x"))
23 .unwrap();
24 println!("cargo:rustc-link-search={}", out.display());
25
26 // By default, Cargo will re-run a build script whenever
27 // any file in the project changes. By specifying `memory.x`
28 // here, we ensure the build script is only re-run when
29 // `memory.x` is changed.
30 println!("cargo:rerun-if-changed=memory.x");
31
32 println!("cargo:rustc-link-arg-bins=--nmagic");
33 println!("cargo:rustc-link-arg-bins=-Tlink.x");
34 println!("cargo:rustc-link-arg-bins=-Tdefmt.x");
35}
diff --git a/examples/nrf54l15/memory.x b/examples/nrf54l15/memory.x
new file mode 100644
index 000000000..1064c8a5c
--- /dev/null
+++ b/examples/nrf54l15/memory.x
@@ -0,0 +1,5 @@
1MEMORY
2{
3 FLASH : ORIGIN = 0x00000000, LENGTH = 1536K
4 RAM : ORIGIN = 0x20000000, LENGTH = 256K
5}
diff --git a/examples/nrf54l15/src/bin/blinky.rs b/examples/nrf54l15/src/bin/blinky.rs
new file mode 100644
index 000000000..71fcc461f
--- /dev/null
+++ b/examples/nrf54l15/src/bin/blinky.rs
@@ -0,0 +1,23 @@
1#![no_std]
2#![no_main]
3
4use defmt::info;
5use embassy_executor::Spawner;
6use embassy_nrf::gpio::{Level, Output, OutputDrive};
7use embassy_time::Timer;
8use {defmt_rtt as _, panic_probe as _};
9
10#[embassy_executor::main]
11async fn main(_spawner: Spawner) {
12 let p = embassy_nrf::init(Default::default());
13 let mut led = Output::new(p.P2_09, Level::Low, OutputDrive::Standard);
14
15 loop {
16 info!("high!");
17 led.set_high();
18 Timer::after_millis(300).await;
19 info!("low!");
20 led.set_low();
21 Timer::after_millis(300).await;
22 }
23}