aboutsummaryrefslogtreecommitdiff
path: root/embassy-nrf/src
diff options
context:
space:
mode:
authorCaleb Garrett <[email protected]>2024-02-04 17:19:15 -0500
committerCaleb Garrett <[email protected]>2024-02-04 17:19:15 -0500
commit059d8a82228c0fa90f7709ce362d7629ca028f13 (patch)
tree2f238a6f97d0da953e98e7f8573fdaff0528f855 /embassy-nrf/src
parent66f44b95d70547be8e32daac1ab611eec5fbe28a (diff)
parent1f940bf9e868438090ea126eb2267f5e9325fbd4 (diff)
Merge commit '1f940bf9e868438090ea126eb2267f5e9325fbd4' into hash
Diffstat (limited to 'embassy-nrf/src')
-rw-r--r--embassy-nrf/src/chips/nrf51.rs169
-rw-r--r--embassy-nrf/src/gpio.rs10
-rw-r--r--embassy-nrf/src/lib.rs23
-rw-r--r--embassy-nrf/src/ppi/mod.rs1
-rw-r--r--embassy-nrf/src/ppi/ppi.rs5
-rw-r--r--embassy-nrf/src/rng.rs126
-rw-r--r--embassy-nrf/src/time_driver.rs18
-rw-r--r--embassy-nrf/src/timer.rs20
-rw-r--r--embassy-nrf/src/util.rs1
9 files changed, 294 insertions, 79 deletions
diff --git a/embassy-nrf/src/chips/nrf51.rs b/embassy-nrf/src/chips/nrf51.rs
new file mode 100644
index 000000000..016352fb8
--- /dev/null
+++ b/embassy-nrf/src/chips/nrf51.rs
@@ -0,0 +1,169 @@
1pub use nrf51_pac as pac;
2
3/// The maximum buffer size that the EasyDMA can send/recv in one operation.
4pub const EASY_DMA_SIZE: usize = (1 << 14) - 1;
5
6pub const FLASH_SIZE: usize = 128 * 1024;
7
8embassy_hal_internal::peripherals! {
9 // RTC
10 RTC0,
11 RTC1,
12
13 // WDT
14 WDT,
15
16 // NVMC
17 NVMC,
18
19 // RNG
20 RNG,
21
22 // UARTE
23 UART0,
24
25 // SPI/TWI
26 TWI0,
27 SPI0,
28
29 // ADC
30 ADC,
31
32 // TIMER
33 TIMER0,
34 TIMER1,
35 TIMER2,
36
37 // GPIOTE
38 GPIOTE_CH0,
39 GPIOTE_CH1,
40 GPIOTE_CH2,
41 GPIOTE_CH3,
42
43 // PPI
44 PPI_CH0,
45 PPI_CH1,
46 PPI_CH2,
47 PPI_CH3,
48 PPI_CH4,
49 PPI_CH5,
50 PPI_CH6,
51 PPI_CH7,
52 PPI_CH8,
53 PPI_CH9,
54 PPI_CH10,
55 PPI_CH11,
56 PPI_CH12,
57 PPI_CH13,
58 PPI_CH14,
59 PPI_CH15,
60
61 PPI_GROUP0,
62 PPI_GROUP1,
63 PPI_GROUP2,
64 PPI_GROUP3,
65
66 // GPIO port 0
67 P0_00,
68 P0_01,
69 P0_02,
70 P0_03,
71 P0_04,
72 P0_05,
73 P0_06,
74 P0_07,
75 P0_08,
76 P0_09,
77 P0_10,
78 P0_11,
79 P0_12,
80 P0_13,
81 P0_14,
82 P0_15,
83 P0_16,
84 P0_17,
85 P0_18,
86 P0_19,
87 P0_20,
88 P0_21,
89 P0_22,
90 P0_23,
91 P0_24,
92 P0_25,
93 P0_26,
94 P0_27,
95 P0_28,
96 P0_29,
97 P0_30,
98 P0_31,
99
100 // TEMP
101 TEMP,
102}
103
104impl_timer!(TIMER0, TIMER0, TIMER0);
105impl_timer!(TIMER1, TIMER1, TIMER1);
106impl_timer!(TIMER2, TIMER2, TIMER2);
107
108impl_rng!(RNG, RNG, RNG);
109
110impl_pin!(P0_00, 0, 0);
111impl_pin!(P0_01, 0, 1);
112impl_pin!(P0_02, 0, 2);
113impl_pin!(P0_03, 0, 3);
114impl_pin!(P0_04, 0, 4);
115impl_pin!(P0_05, 0, 5);
116impl_pin!(P0_06, 0, 6);
117impl_pin!(P0_07, 0, 7);
118impl_pin!(P0_08, 0, 8);
119impl_pin!(P0_09, 0, 9);
120impl_pin!(P0_10, 0, 10);
121impl_pin!(P0_11, 0, 11);
122impl_pin!(P0_12, 0, 12);
123impl_pin!(P0_13, 0, 13);
124impl_pin!(P0_14, 0, 14);
125impl_pin!(P0_15, 0, 15);
126impl_pin!(P0_16, 0, 16);
127impl_pin!(P0_17, 0, 17);
128impl_pin!(P0_18, 0, 18);
129impl_pin!(P0_19, 0, 19);
130impl_pin!(P0_20, 0, 20);
131impl_pin!(P0_21, 0, 21);
132impl_pin!(P0_22, 0, 22);
133impl_pin!(P0_23, 0, 23);
134impl_pin!(P0_24, 0, 24);
135impl_pin!(P0_25, 0, 25);
136impl_pin!(P0_26, 0, 26);
137impl_pin!(P0_27, 0, 27);
138impl_pin!(P0_28, 0, 28);
139impl_pin!(P0_29, 0, 29);
140impl_pin!(P0_30, 0, 30);
141impl_pin!(P0_31, 0, 31);
142
143embassy_hal_internal::interrupt_mod!(
144 POWER_CLOCK,
145 RADIO,
146 UART0,
147 SPI0_TWI0,
148 SPI1_TWI1,
149 GPIOTE,
150 ADC,
151 TIMER0,
152 TIMER1,
153 TIMER2,
154 RTC0,
155 TEMP,
156 RNG,
157 ECB,
158 CCM_AAR,
159 WDT,
160 RTC1,
161 QDEC,
162 LPCOMP,
163 SWI0,
164 SWI1,
165 SWI2,
166 SWI3,
167 SWI4,
168 SWI5,
169);
diff --git a/embassy-nrf/src/gpio.rs b/embassy-nrf/src/gpio.rs
index 287811e61..b2f987109 100644
--- a/embassy-nrf/src/gpio.rs
+++ b/embassy-nrf/src/gpio.rs
@@ -8,7 +8,13 @@ use cfg_if::cfg_if;
8use embassy_hal_internal::{impl_peripheral, into_ref, PeripheralRef}; 8use embassy_hal_internal::{impl_peripheral, into_ref, PeripheralRef};
9 9
10use self::sealed::Pin as _; 10use self::sealed::Pin as _;
11#[cfg(feature = "nrf51")]
12use crate::pac::gpio;
13#[cfg(feature = "nrf51")]
14use crate::pac::gpio::pin_cnf::{DRIVE_A, PULL_A};
15#[cfg(not(feature = "nrf51"))]
11use crate::pac::p0 as gpio; 16use crate::pac::p0 as gpio;
17#[cfg(not(feature = "nrf51"))]
12use crate::pac::p0::pin_cnf::{DRIVE_A, PULL_A}; 18use crate::pac::p0::pin_cnf::{DRIVE_A, PULL_A};
13use crate::{pac, Peripheral}; 19use crate::{pac, Peripheral};
14 20
@@ -376,6 +382,9 @@ pub(crate) mod sealed {
376 fn block(&self) -> &gpio::RegisterBlock { 382 fn block(&self) -> &gpio::RegisterBlock {
377 unsafe { 383 unsafe {
378 match self.pin_port() / 32 { 384 match self.pin_port() / 32 {
385 #[cfg(feature = "nrf51")]
386 0 => &*pac::GPIO::ptr(),
387 #[cfg(not(feature = "nrf51"))]
379 0 => &*pac::P0::ptr(), 388 0 => &*pac::P0::ptr(),
380 #[cfg(feature = "_gpio-p1")] 389 #[cfg(feature = "_gpio-p1")]
381 1 => &*pac::P1::ptr(), 390 1 => &*pac::P1::ptr(),
@@ -478,6 +487,7 @@ impl<'a, P: Pin> PselBits for Option<PeripheralRef<'a, P>> {
478 } 487 }
479} 488}
480 489
490#[allow(dead_code)]
481pub(crate) fn deconfigure_pin(psel_bits: u32) { 491pub(crate) fn deconfigure_pin(psel_bits: u32) {
482 if psel_bits & 0x8000_0000 != 0 { 492 if psel_bits & 0x8000_0000 != 0 {
483 return; 493 return;
diff --git a/embassy-nrf/src/lib.rs b/embassy-nrf/src/lib.rs
index d9c92a76d..358a7cc27 100644
--- a/embassy-nrf/src/lib.rs
+++ b/embassy-nrf/src/lib.rs
@@ -40,6 +40,7 @@ pub(crate) mod util;
40#[cfg(feature = "_time-driver")] 40#[cfg(feature = "_time-driver")]
41mod time_driver; 41mod time_driver;
42 42
43#[cfg(not(feature = "nrf51"))]
43pub mod buffered_uarte; 44pub mod buffered_uarte;
44pub mod gpio; 45pub mod gpio;
45#[cfg(feature = "gpiote")] 46#[cfg(feature = "gpiote")]
@@ -58,7 +59,12 @@ pub mod nvmc;
58))] 59))]
59pub mod pdm; 60pub mod pdm;
60pub mod ppi; 61pub mod ppi;
61#[cfg(not(any(feature = "nrf52805", feature = "nrf52820", feature = "_nrf5340-net")))] 62#[cfg(not(any(
63 feature = "nrf51",
64 feature = "nrf52805",
65 feature = "nrf52820",
66 feature = "_nrf5340-net"
67)))]
62pub mod pwm; 68pub mod pwm;
63#[cfg(not(any(feature = "nrf51", feature = "_nrf9160", feature = "_nrf5340-net")))] 69#[cfg(not(any(feature = "nrf51", feature = "_nrf9160", feature = "_nrf5340-net")))]
64pub mod qdec; 70pub mod qdec;
@@ -66,15 +72,20 @@ pub mod qdec;
66pub mod qspi; 72pub mod qspi;
67#[cfg(not(any(feature = "_nrf5340-app", feature = "_nrf9160")))] 73#[cfg(not(any(feature = "_nrf5340-app", feature = "_nrf9160")))]
68pub mod rng; 74pub mod rng;
69#[cfg(not(any(feature = "nrf52820", feature = "_nrf5340-net")))] 75#[cfg(not(any(feature = "nrf51", feature = "nrf52820", feature = "_nrf5340-net")))]
70pub mod saadc; 76pub mod saadc;
77#[cfg(not(feature = "nrf51"))]
71pub mod spim; 78pub mod spim;
79#[cfg(not(feature = "nrf51"))]
72pub mod spis; 80pub mod spis;
73#[cfg(not(any(feature = "_nrf5340", feature = "_nrf9160")))] 81#[cfg(not(any(feature = "_nrf5340", feature = "_nrf9160")))]
74pub mod temp; 82pub mod temp;
75pub mod timer; 83pub mod timer;
84#[cfg(not(feature = "nrf51"))]
76pub mod twim; 85pub mod twim;
86#[cfg(not(feature = "nrf51"))]
77pub mod twis; 87pub mod twis;
88#[cfg(not(feature = "nrf51"))]
78pub mod uarte; 89pub mod uarte;
79#[cfg(any( 90#[cfg(any(
80 feature = "_nrf5340-app", 91 feature = "_nrf5340-app",
@@ -87,6 +98,7 @@ pub mod usb;
87pub mod wdt; 98pub mod wdt;
88 99
89// This mod MUST go last, so that it sees all the `impl_foo!` macros 100// This mod MUST go last, so that it sees all the `impl_foo!` macros
101#[cfg_attr(feature = "nrf51", path = "chips/nrf51.rs")]
90#[cfg_attr(feature = "nrf52805", path = "chips/nrf52805.rs")] 102#[cfg_attr(feature = "nrf52805", path = "chips/nrf52805.rs")]
91#[cfg_attr(feature = "nrf52810", path = "chips/nrf52810.rs")] 103#[cfg_attr(feature = "nrf52810", path = "chips/nrf52810.rs")]
92#[cfg_attr(feature = "nrf52811", path = "chips/nrf52811.rs")] 104#[cfg_attr(feature = "nrf52811", path = "chips/nrf52811.rs")]
@@ -324,6 +336,7 @@ mod consts {
324 pub const APPROTECT_DISABLED: u32 = 0x0000_005a; 336 pub const APPROTECT_DISABLED: u32 = 0x0000_005a;
325} 337}
326 338
339#[cfg(not(feature = "nrf51"))]
327#[derive(Debug, Copy, Clone, Eq, PartialEq)] 340#[derive(Debug, Copy, Clone, Eq, PartialEq)]
328#[cfg_attr(feature = "defmt", derive(defmt::Format))] 341#[cfg_attr(feature = "defmt", derive(defmt::Format))]
329enum WriteResult { 342enum WriteResult {
@@ -335,10 +348,12 @@ enum WriteResult {
335 Failed, 348 Failed,
336} 349}
337 350
351#[cfg(not(feature = "nrf51"))]
338unsafe fn uicr_write(address: *mut u32, value: u32) -> WriteResult { 352unsafe fn uicr_write(address: *mut u32, value: u32) -> WriteResult {
339 uicr_write_masked(address, value, 0xFFFF_FFFF) 353 uicr_write_masked(address, value, 0xFFFF_FFFF)
340} 354}
341 355
356#[cfg(not(feature = "nrf51"))]
342unsafe fn uicr_write_masked(address: *mut u32, value: u32, mask: u32) -> WriteResult { 357unsafe fn uicr_write_masked(address: *mut u32, value: u32, mask: u32) -> WriteResult {
343 let curr_val = address.read_volatile(); 358 let curr_val = address.read_volatile();
344 if curr_val & mask == value & mask { 359 if curr_val & mask == value & mask {
@@ -371,9 +386,11 @@ pub fn init(config: config::Config) -> Peripherals {
371 // before doing anything important. 386 // before doing anything important.
372 let peripherals = Peripherals::take(); 387 let peripherals = Peripherals::take();
373 388
389 #[allow(unused_mut)]
374 let mut needs_reset = false; 390 let mut needs_reset = false;
375 391
376 // Setup debug protection. 392 // Setup debug protection.
393 #[cfg(not(feature = "nrf51"))]
377 match config.debug { 394 match config.debug {
378 config::Debug::Allowed => { 395 config::Debug::Allowed => {
379 #[cfg(feature = "_nrf52")] 396 #[cfg(feature = "_nrf52")]
@@ -489,7 +506,7 @@ pub fn init(config: config::Config) -> Peripherals {
489 } 506 }
490 507
491 // Configure LFCLK. 508 // Configure LFCLK.
492 #[cfg(not(any(feature = "_nrf5340", feature = "_nrf9160")))] 509 #[cfg(not(any(feature = "nrf51", feature = "_nrf5340", feature = "_nrf9160")))]
493 match config.lfclk_source { 510 match config.lfclk_source {
494 config::LfclkSource::InternalRC => r.lfclksrc.write(|w| w.src().rc()), 511 config::LfclkSource::InternalRC => r.lfclksrc.write(|w| w.src().rc()),
495 config::LfclkSource::Synthesized => r.lfclksrc.write(|w| w.src().synth()), 512 config::LfclkSource::Synthesized => r.lfclksrc.write(|w| w.src().synth()),
diff --git a/embassy-nrf/src/ppi/mod.rs b/embassy-nrf/src/ppi/mod.rs
index 5b4a64388..f5764b8b7 100644
--- a/embassy-nrf/src/ppi/mod.rs
+++ b/embassy-nrf/src/ppi/mod.rs
@@ -284,6 +284,7 @@ impl ConfigurableChannel for AnyConfigurableChannel {
284 } 284 }
285} 285}
286 286
287#[cfg(not(feature = "nrf51"))]
287macro_rules! impl_ppi_channel { 288macro_rules! impl_ppi_channel {
288 ($type:ident, $number:expr) => { 289 ($type:ident, $number:expr) => {
289 impl crate::ppi::sealed::Channel for peripherals::$type {} 290 impl crate::ppi::sealed::Channel for peripherals::$type {}
diff --git a/embassy-nrf/src/ppi/ppi.rs b/embassy-nrf/src/ppi/ppi.rs
index 3e9e9fc81..8ff52ece3 100644
--- a/embassy-nrf/src/ppi/ppi.rs
+++ b/embassy-nrf/src/ppi/ppi.rs
@@ -1,6 +1,6 @@
1use embassy_hal_internal::into_ref; 1use embassy_hal_internal::into_ref;
2 2
3use super::{Channel, ConfigurableChannel, Event, Ppi, StaticChannel, Task}; 3use super::{Channel, ConfigurableChannel, Event, Ppi, Task};
4use crate::{pac, Peripheral}; 4use crate::{pac, Peripheral};
5 5
6impl<'d> Task<'d> { 6impl<'d> Task<'d> {
@@ -19,7 +19,7 @@ pub(crate) fn regs() -> &'static pac::ppi::RegisterBlock {
19} 19}
20 20
21#[cfg(not(feature = "nrf51"))] // Not for nrf51 because of the fork task 21#[cfg(not(feature = "nrf51"))] // Not for nrf51 because of the fork task
22impl<'d, C: StaticChannel> Ppi<'d, C, 0, 1> { 22impl<'d, C: super::StaticChannel> Ppi<'d, C, 0, 1> {
23 /// Configure PPI channel to trigger `task`. 23 /// Configure PPI channel to trigger `task`.
24 pub fn new_zero_to_one(ch: impl Peripheral<P = C> + 'd, task: Task) -> Self { 24 pub fn new_zero_to_one(ch: impl Peripheral<P = C> + 'd, task: Task) -> Self {
25 into_ref!(ch); 25 into_ref!(ch);
@@ -84,6 +84,7 @@ impl<'d, C: Channel, const EVENT_COUNT: usize, const TASK_COUNT: usize> Drop for
84 let n = self.ch.number(); 84 let n = self.ch.number();
85 r.ch[n].eep.write(|w| unsafe { w.bits(0) }); 85 r.ch[n].eep.write(|w| unsafe { w.bits(0) });
86 r.ch[n].tep.write(|w| unsafe { w.bits(0) }); 86 r.ch[n].tep.write(|w| unsafe { w.bits(0) });
87 #[cfg(not(feature = "nrf51"))]
87 r.fork[n].tep.write(|w| unsafe { w.bits(0) }); 88 r.fork[n].tep.write(|w| unsafe { w.bits(0) });
88 } 89 }
89} 90}
diff --git a/embassy-nrf/src/rng.rs b/embassy-nrf/src/rng.rs
index e2803f0d3..40b73231b 100644
--- a/embassy-nrf/src/rng.rs
+++ b/embassy-nrf/src/rng.rs
@@ -5,12 +5,10 @@
5use core::future::poll_fn; 5use core::future::poll_fn;
6use core::marker::PhantomData; 6use core::marker::PhantomData;
7use core::ptr; 7use core::ptr;
8use core::sync::atomic::{AtomicPtr, Ordering};
9use core::task::Poll; 8use core::task::Poll;
10 9
11use embassy_hal_internal::drop::OnDrop; 10use embassy_hal_internal::drop::OnDrop;
12use embassy_hal_internal::{into_ref, PeripheralRef}; 11use embassy_hal_internal::{into_ref, PeripheralRef};
13use embassy_sync::waitqueue::AtomicWaker;
14 12
15use crate::interrupt::typelevel::Interrupt; 13use crate::interrupt::typelevel::Interrupt;
16use crate::{interrupt, Peripheral}; 14use crate::{interrupt, Peripheral};
@@ -22,7 +20,6 @@ pub struct InterruptHandler<T: Instance> {
22 20
23impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandler<T> { 21impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandler<T> {
24 unsafe fn on_interrupt() { 22 unsafe fn on_interrupt() {
25 let s = T::state();
26 let r = T::regs(); 23 let r = T::regs();
27 24
28 // Clear the event. 25 // Clear the event.
@@ -30,46 +27,25 @@ impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandl
30 27
31 // Mutate the slice within a critical section, 28 // Mutate the slice within a critical section,
32 // so that the future isn't dropped in between us loading the pointer and actually dereferencing it. 29 // so that the future isn't dropped in between us loading the pointer and actually dereferencing it.
33 let (ptr, end) = critical_section::with(|_| { 30 critical_section::with(|cs| {
34 let ptr = s.ptr.load(Ordering::Relaxed); 31 let mut state = T::state().borrow_mut(cs);
35 // We need to make sure we haven't already filled the whole slice, 32 // We need to make sure we haven't already filled the whole slice,
36 // in case the interrupt fired again before the executor got back to the future. 33 // in case the interrupt fired again before the executor got back to the future.
37 let end = s.end.load(Ordering::Relaxed); 34 if !state.ptr.is_null() && state.ptr != state.end {
38 if !ptr.is_null() && ptr != end {
39 // If the future was dropped, the pointer would have been set to null, 35 // If the future was dropped, the pointer would have been set to null,
40 // so we're still good to mutate the slice. 36 // so we're still good to mutate the slice.
41 // The safety contract of `Rng::new` means that the future can't have been dropped 37 // The safety contract of `Rng::new` means that the future can't have been dropped
42 // without calling its destructor. 38 // without calling its destructor.
43 unsafe { 39 unsafe {
44 *ptr = r.value.read().value().bits(); 40 *state.ptr = r.value.read().value().bits();
41 state.ptr = state.ptr.add(1);
45 } 42 }
46 }
47 (ptr, end)
48 });
49
50 if ptr.is_null() || ptr == end {
51 // If the future was dropped, there's nothing to do.
52 // If `ptr == end`, we were called by mistake, so return.
53 return;
54 }
55 43
56 let new_ptr = unsafe { ptr.add(1) }; 44 if state.ptr == state.end {
57 match s 45 state.waker.wake();
58 .ptr
59 .compare_exchange(ptr, new_ptr, Ordering::Relaxed, Ordering::Relaxed)
60 {
61 Ok(_) => {
62 let end = s.end.load(Ordering::Relaxed);
63 // It doesn't matter if `end` was changed under our feet, because then this will just be false.
64 if new_ptr == end {
65 s.waker.wake();
66 } 46 }
67 } 47 }
68 Err(_) => { 48 });
69 // If the future was dropped or finished, there's no point trying to wake it.
70 // It will have already stopped the RNG, so there's no need to do that either.
71 }
72 }
73 } 49 }
74} 50}
75 51
@@ -136,13 +112,14 @@ impl<'d, T: Instance> Rng<'d, T> {
136 return; // Nothing to fill 112 return; // Nothing to fill
137 } 113 }
138 114
139 let s = T::state();
140
141 let range = dest.as_mut_ptr_range(); 115 let range = dest.as_mut_ptr_range();
142 // Even if we've preempted the interrupt, it can't preempt us again, 116 // Even if we've preempted the interrupt, it can't preempt us again,
143 // so we don't need to worry about the order we write these in. 117 // so we don't need to worry about the order we write these in.
144 s.ptr.store(range.start, Ordering::Relaxed); 118 critical_section::with(|cs| {
145 s.end.store(range.end, Ordering::Relaxed); 119 let mut state = T::state().borrow_mut(cs);
120 state.ptr = range.start;
121 state.end = range.end;
122 });
146 123
147 self.enable_irq(); 124 self.enable_irq();
148 self.start(); 125 self.start();
@@ -151,24 +128,24 @@ impl<'d, T: Instance> Rng<'d, T> {
151 self.stop(); 128 self.stop();
152 self.disable_irq(); 129 self.disable_irq();
153 130
154 // The interrupt is now disabled and can't preempt us anymore, so the order doesn't matter here. 131 critical_section::with(|cs| {
155 s.ptr.store(ptr::null_mut(), Ordering::Relaxed); 132 let mut state = T::state().borrow_mut(cs);
156 s.end.store(ptr::null_mut(), Ordering::Relaxed); 133 state.ptr = ptr::null_mut();
134 state.end = ptr::null_mut();
135 });
157 }); 136 });
158 137
159 poll_fn(|cx| { 138 poll_fn(|cx| {
160 s.waker.register(cx.waker()); 139 critical_section::with(|cs| {
161 140 let mut s = T::state().borrow_mut(cs);
162 // The interrupt will never modify `end`, so load it first and then get the most up-to-date `ptr`. 141 s.waker.register(cx.waker());
163 let end = s.end.load(Ordering::Relaxed); 142 if s.ptr == s.end {
164 let ptr = s.ptr.load(Ordering::Relaxed); 143 // We're done.
165 144 Poll::Ready(())
166 if ptr == end { 145 } else {
167 // We're done. 146 Poll::Pending
168 Poll::Ready(()) 147 }
169 } else { 148 })
170 Poll::Pending
171 }
172 }) 149 })
173 .await; 150 .await;
174 151
@@ -194,9 +171,11 @@ impl<'d, T: Instance> Rng<'d, T> {
194impl<'d, T: Instance> Drop for Rng<'d, T> { 171impl<'d, T: Instance> Drop for Rng<'d, T> {
195 fn drop(&mut self) { 172 fn drop(&mut self) {
196 self.stop(); 173 self.stop();
197 let s = T::state(); 174 critical_section::with(|cs| {
198 s.ptr.store(ptr::null_mut(), Ordering::Relaxed); 175 let mut state = T::state().borrow_mut(cs);
199 s.end.store(ptr::null_mut(), Ordering::Relaxed); 176 state.ptr = ptr::null_mut();
177 state.end = ptr::null_mut();
178 });
200 } 179 }
201} 180}
202 181
@@ -227,21 +206,48 @@ impl<'d, T: Instance> rand_core::RngCore for Rng<'d, T> {
227impl<'d, T: Instance> rand_core::CryptoRng for Rng<'d, T> {} 206impl<'d, T: Instance> rand_core::CryptoRng for Rng<'d, T> {}
228 207
229pub(crate) mod sealed { 208pub(crate) mod sealed {
209 use core::cell::{Ref, RefCell, RefMut};
210
211 use critical_section::{CriticalSection, Mutex};
212 use embassy_sync::waitqueue::WakerRegistration;
213
230 use super::*; 214 use super::*;
231 215
232 /// Peripheral static state 216 /// Peripheral static state
233 pub struct State { 217 pub struct State {
234 pub ptr: AtomicPtr<u8>, 218 inner: Mutex<RefCell<InnerState>>,
235 pub end: AtomicPtr<u8>, 219 }
236 pub waker: AtomicWaker, 220
221 pub struct InnerState {
222 pub ptr: *mut u8,
223 pub end: *mut u8,
224 pub waker: WakerRegistration,
237 } 225 }
238 226
227 unsafe impl Send for InnerState {}
228
239 impl State { 229 impl State {
240 pub const fn new() -> Self { 230 pub const fn new() -> Self {
241 Self { 231 Self {
242 ptr: AtomicPtr::new(ptr::null_mut()), 232 inner: Mutex::new(RefCell::new(InnerState::new())),
243 end: AtomicPtr::new(ptr::null_mut()), 233 }
244 waker: AtomicWaker::new(), 234 }
235
236 pub fn borrow<'cs>(&'cs self, cs: CriticalSection<'cs>) -> Ref<'cs, InnerState> {
237 self.inner.borrow(cs).borrow()
238 }
239
240 pub fn borrow_mut<'cs>(&'cs self, cs: CriticalSection<'cs>) -> RefMut<'cs, InnerState> {
241 self.inner.borrow(cs).borrow_mut()
242 }
243 }
244
245 impl InnerState {
246 pub const fn new() -> Self {
247 Self {
248 ptr: ptr::null_mut(),
249 end: ptr::null_mut(),
250 waker: WakerRegistration::new(),
245 } 251 }
246 } 252 }
247 } 253 }
diff --git a/embassy-nrf/src/time_driver.rs b/embassy-nrf/src/time_driver.rs
index 042f7c5f7..3407c9504 100644
--- a/embassy-nrf/src/time_driver.rs
+++ b/embassy-nrf/src/time_driver.rs
@@ -171,7 +171,8 @@ impl RtcDriver {
171 fn next_period(&self) { 171 fn next_period(&self) {
172 critical_section::with(|cs| { 172 critical_section::with(|cs| {
173 let r = rtc(); 173 let r = rtc();
174 let period = self.period.fetch_add(1, Ordering::Relaxed) + 1; 174 let period = self.period.load(Ordering::Relaxed) + 1;
175 self.period.store(period, Ordering::Relaxed);
175 let t = (period as u64) << 23; 176 let t = (period as u64) << 23;
176 177
177 for n in 0..ALARM_COUNT { 178 for n in 0..ALARM_COUNT {
@@ -219,18 +220,15 @@ impl Driver for RtcDriver {
219 } 220 }
220 221
221 unsafe fn allocate_alarm(&self) -> Option<AlarmHandle> { 222 unsafe fn allocate_alarm(&self) -> Option<AlarmHandle> {
222 let id = self.alarm_count.fetch_update(Ordering::AcqRel, Ordering::Acquire, |x| { 223 critical_section::with(|_| {
223 if x < ALARM_COUNT as u8 { 224 let id = self.alarm_count.load(Ordering::Relaxed);
224 Some(x + 1) 225 if id < ALARM_COUNT as u8 {
226 self.alarm_count.store(id + 1, Ordering::Relaxed);
227 Some(AlarmHandle::new(id))
225 } else { 228 } else {
226 None 229 None
227 } 230 }
228 }); 231 })
229
230 match id {
231 Ok(id) => Some(AlarmHandle::new(id)),
232 Err(_) => None,
233 }
234 } 232 }
235 233
236 fn set_alarm_callback(&self, alarm: AlarmHandle, callback: fn(*mut ()), ctx: *mut ()) { 234 fn set_alarm_callback(&self, alarm: AlarmHandle, callback: fn(*mut ()), ctx: *mut ()) {
diff --git a/embassy-nrf/src/timer.rs b/embassy-nrf/src/timer.rs
index 3dbfdac42..3c35baee5 100644
--- a/embassy-nrf/src/timer.rs
+++ b/embassy-nrf/src/timer.rs
@@ -111,7 +111,7 @@ impl<'d, T: Instance> Timer<'d, T> {
111 Self::new_inner(timer, true) 111 Self::new_inner(timer, true)
112 } 112 }
113 113
114 fn new_inner(timer: impl Peripheral<P = T> + 'd, is_counter: bool) -> Self { 114 fn new_inner(timer: impl Peripheral<P = T> + 'd, _is_counter: bool) -> Self {
115 into_ref!(timer); 115 into_ref!(timer);
116 116
117 let regs = T::regs(); 117 let regs = T::regs();
@@ -122,12 +122,16 @@ impl<'d, T: Instance> Timer<'d, T> {
122 // since changing BITMODE while running can cause 'unpredictable behaviour' according to the specification. 122 // since changing BITMODE while running can cause 'unpredictable behaviour' according to the specification.
123 this.stop(); 123 this.stop();
124 124
125 if is_counter { 125 #[cfg(not(feature = "nrf51"))]
126 if _is_counter {
126 regs.mode.write(|w| w.mode().low_power_counter()); 127 regs.mode.write(|w| w.mode().low_power_counter());
127 } else { 128 } else {
128 regs.mode.write(|w| w.mode().timer()); 129 regs.mode.write(|w| w.mode().timer());
129 } 130 }
130 131
132 #[cfg(feature = "nrf51")]
133 regs.mode.write(|w| w.mode().timer());
134
131 // Make the counter's max value as high as possible. 135 // Make the counter's max value as high as possible.
132 // TODO: is there a reason someone would want to set this lower? 136 // TODO: is there a reason someone would want to set this lower?
133 regs.bitmode.write(|w| w.bitmode()._32bit()); 137 regs.bitmode.write(|w| w.bitmode()._32bit());
@@ -238,7 +242,11 @@ pub struct Cc<'d, T: Instance> {
238impl<'d, T: Instance> Cc<'d, T> { 242impl<'d, T: Instance> Cc<'d, T> {
239 /// Get the current value stored in the register. 243 /// Get the current value stored in the register.
240 pub fn read(&self) -> u32 { 244 pub fn read(&self) -> u32 {
241 T::regs().cc[self.n].read().cc().bits() 245 #[cfg(not(feature = "nrf51"))]
246 return T::regs().cc[self.n].read().cc().bits();
247
248 #[cfg(feature = "nrf51")]
249 return T::regs().cc[self.n].read().bits();
242 } 250 }
243 251
244 /// Set the value stored in the register. 252 /// Set the value stored in the register.
@@ -246,7 +254,11 @@ impl<'d, T: Instance> Cc<'d, T> {
246 /// `event_compare` will fire when the timer's counter reaches this value. 254 /// `event_compare` will fire when the timer's counter reaches this value.
247 pub fn write(&self, value: u32) { 255 pub fn write(&self, value: u32) {
248 // SAFETY: there are no invalid values for the CC register. 256 // SAFETY: there are no invalid values for the CC register.
249 T::regs().cc[self.n].write(|w| unsafe { w.cc().bits(value) }) 257 #[cfg(not(feature = "nrf51"))]
258 T::regs().cc[self.n].write(|w| unsafe { w.cc().bits(value) });
259
260 #[cfg(feature = "nrf51")]
261 T::regs().cc[self.n].write(|w| unsafe { w.bits(value) });
250 } 262 }
251 263
252 /// Capture the current value of the timer's counter in this register, and return it. 264 /// Capture the current value of the timer's counter in this register, and return it.
diff --git a/embassy-nrf/src/util.rs b/embassy-nrf/src/util.rs
index cd0f59490..b408c517b 100644
--- a/embassy-nrf/src/util.rs
+++ b/embassy-nrf/src/util.rs
@@ -1,3 +1,4 @@
1#![allow(dead_code)]
1use core::mem; 2use core::mem;
2 3
3const SRAM_LOWER: usize = 0x2000_0000; 4const SRAM_LOWER: usize = 0x2000_0000;