aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy-nrf/src/lib.rs78
1 files changed, 65 insertions, 13 deletions
diff --git a/embassy-nrf/src/lib.rs b/embassy-nrf/src/lib.rs
index 0fa1c0f66..a9683df44 100644
--- a/embassy-nrf/src/lib.rs
+++ b/embassy-nrf/src/lib.rs
@@ -235,10 +235,26 @@ mod consts {
235 pub const APPROTECT_DISABLED: u32 = 0x0000_005a; 235 pub const APPROTECT_DISABLED: u32 = 0x0000_005a;
236} 236}
237 237
238unsafe fn uicr_write(address: *mut u32, value: u32) -> bool { 238#[derive(Debug, Copy, Clone, Eq, PartialEq)]
239#[cfg_attr(feature = "defmt", derive(defmt::Format))]
240enum WriteResult {
241 /// Word was written successfully, needs reset.
242 Written,
243 /// Word was already set to the value we wanted to write, nothing was done.
244 Noop,
245 /// Word is already set to something else, we couldn't write the desired value.
246 Failed,
247}
248
249unsafe fn uicr_write(address: *mut u32, value: u32) -> WriteResult {
239 let curr_val = address.read_volatile(); 250 let curr_val = address.read_volatile();
240 if curr_val == value { 251 if curr_val == value {
241 return false; 252 return WriteResult::Noop;
253 }
254
255 // We can only change `1` bits to `0` bits.
256 if curr_val & value != value {
257 return WriteResult::Failed;
242 } 258 }
243 259
244 // Writing to UICR can only change `1` bits to `0` bits. 260 // Writing to UICR can only change `1` bits to `0` bits.
@@ -257,7 +273,7 @@ unsafe fn uicr_write(address: *mut u32, value: u32) -> bool {
257 nvmc.config.reset(); 273 nvmc.config.reset();
258 while nvmc.ready.read().ready().is_busy() {} 274 while nvmc.ready.read().ready().is_busy() {}
259 275
260 true 276 WriteResult::Written
261} 277}
262 278
263/// Initialize peripherals with the provided configuration. This should only be called once at startup. 279/// Initialize peripherals with the provided configuration. This should only be called once at startup.
@@ -283,7 +299,8 @@ pub fn init(config: config::Config) -> Peripherals {
283 // which needs explicit action by the firmware to keep it unlocked 299 // which needs explicit action by the firmware to keep it unlocked
284 300
285 // UICR.APPROTECT = SwDisabled 301 // UICR.APPROTECT = SwDisabled
286 needs_reset |= uicr_write(consts::UICR_APPROTECT, consts::APPROTECT_DISABLED); 302 let res = uicr_write(consts::UICR_APPROTECT, consts::APPROTECT_DISABLED);
303 needs_reset |= res == WriteResult::Written;
287 // APPROTECT.DISABLE = SwDisabled 304 // APPROTECT.DISABLE = SwDisabled
288 (0x4000_0558 as *mut u32).write_volatile(consts::APPROTECT_DISABLED); 305 (0x4000_0558 as *mut u32).write_volatile(consts::APPROTECT_DISABLED);
289 } else { 306 } else {
@@ -295,12 +312,14 @@ pub fn init(config: config::Config) -> Peripherals {
295 unsafe { 312 unsafe {
296 let p = &*pac::CTRLAP::ptr(); 313 let p = &*pac::CTRLAP::ptr();
297 314
298 needs_reset |= uicr_write(consts::UICR_APPROTECT, consts::APPROTECT_DISABLED); 315 let res = uicr_write(consts::UICR_APPROTECT, consts::APPROTECT_DISABLED);
316 needs_reset |= res == WriteResult::Written;
299 p.approtect.disable.write(|w| w.bits(consts::APPROTECT_DISABLED)); 317 p.approtect.disable.write(|w| w.bits(consts::APPROTECT_DISABLED));
300 318
301 #[cfg(feature = "_nrf5340-app")] 319 #[cfg(feature = "_nrf5340-app")]
302 { 320 {
303 needs_reset |= uicr_write(consts::UICR_SECUREAPPROTECT, consts::APPROTECT_DISABLED); 321 let res = uicr_write(consts::UICR_SECUREAPPROTECT, consts::APPROTECT_DISABLED);
322 needs_reset |= res == WriteResult::Written;
304 p.secureapprotect.disable.write(|w| w.bits(consts::APPROTECT_DISABLED)); 323 p.secureapprotect.disable.write(|w| w.bits(consts::APPROTECT_DISABLED));
305 } 324 }
306 } 325 }
@@ -309,24 +328,57 @@ pub fn init(config: config::Config) -> Peripherals {
309 } 328 }
310 config::Debug::Disallowed => unsafe { 329 config::Debug::Disallowed => unsafe {
311 // UICR.APPROTECT = Enabled 330 // UICR.APPROTECT = Enabled
312 needs_reset |= uicr_write(consts::UICR_APPROTECT, consts::APPROTECT_ENABLED); 331 let res = uicr_write(consts::UICR_APPROTECT, consts::APPROTECT_ENABLED);
332 needs_reset |= res == WriteResult::Written;
313 #[cfg(any(feature = "_nrf5340-app", feature = "_nrf9160"))] 333 #[cfg(any(feature = "_nrf5340-app", feature = "_nrf9160"))]
314 { 334 {
315 needs_reset |= uicr_write(consts::UICR_SECUREAPPROTECT, consts::APPROTECT_ENABLED); 335 let res = uicr_write(consts::UICR_SECUREAPPROTECT, consts::APPROTECT_ENABLED);
336 needs_reset |= res == WriteResult::Written;
316 } 337 }
317 }, 338 },
318 config::Debug::NotConfigured => {} 339 config::Debug::NotConfigured => {}
319 } 340 }
320 341
321 #[cfg(all(feature = "_nrf52", not(feature = "reset-pin-as-gpio")))] 342 #[cfg(feature = "_nrf52")]
322 unsafe { 343 unsafe {
323 needs_reset |= uicr_write(consts::UICR_PSELRESET1, chip::RESET_PIN); 344 let value = if cfg!(feature = "reset-pin-as-gpio") {
324 needs_reset |= uicr_write(consts::UICR_PSELRESET2, chip::RESET_PIN); 345 !0
346 } else {
347 chip::RESET_PIN
348 };
349 let res1 = uicr_write(consts::UICR_PSELRESET1, value);
350 let res2 = uicr_write(consts::UICR_PSELRESET2, value);
351 needs_reset |= res1 == WriteResult::Written || res2 == WriteResult::Written;
352 if res1 == WriteResult::Failed || res2 == WriteResult::Failed {
353 #[cfg(not(feature = "reset-pin-as-gpio"))]
354 warn!(
355 "You have requested enabling chip reset functionality on the reset pin, by not enabling the Cargo feature `reset-pin-as-gpio`.\n\
356 However, UICR is already programmed to some other setting, and can't be changed without erasing it.\n\
357 To fix this, erase UICR manually, for example using `probe-rs-cli erase` or `nrfjprog --eraseuicr`."
358 );
359 #[cfg(feature = "reset-pin-as-gpio")]
360 warn!(
361 "You have requested using the reset pin as GPIO, by enabling the Cargo feature `reset-pin-as-gpio`.\n\
362 However, UICR is already programmed to some other setting, and can't be changed without erasing it.\n\
363 To fix this, erase UICR manually, for example using `probe-rs-cli erase` or `nrfjprog --eraseuicr`."
364 );
365 }
325 } 366 }
326 367
327 #[cfg(all(any(feature = "_nrf52", feature = "_nrf5340-app"), feature = "nfc-pins-as-gpio"))] 368 #[cfg(any(feature = "_nrf52", feature = "_nrf5340-app"))]
328 unsafe { 369 unsafe {
329 needs_reset |= uicr_write(consts::UICR_NFCPINS, 0); 370 let value = if cfg!(feature = "nfc-pins-as-gpio") { 0 } else { !0 };
371 let res = uicr_write(consts::UICR_NFCPINS, value);
372 needs_reset |= res == WriteResult::Written;
373 if res == WriteResult::Failed {
374 // with nfc-pins-as-gpio, this can never fail because we're writing all zero bits.
375 #[cfg(not(feature = "nfc-pins-as-gpio"))]
376 warn!(
377 "You have requested to use P0.09 and P0.10 pins for NFC, by not enabling the Cargo feature `nfc-pins-as-gpio`.\n\
378 However, UICR is already programmed to some other setting, and can't be changed without erasing it.\n\
379 To fix this, erase UICR manually, for example using `probe-rs-cli erase` or `nrfjprog --eraseuicr`."
380 );
381 }
330 } 382 }
331 383
332 if needs_reset { 384 if needs_reset {