aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy-nrf-examples/.cargo/config6
-rw-r--r--embassy-nrf-examples/src/bin/buffered_uart.rs11
-rw-r--r--embassy-nrf/src/buffered_uarte.rs303
-rw-r--r--embassy-nrf/src/lib.rs1
-rw-r--r--embassy-nrf/src/util/mod.rs2
-rw-r--r--embassy-nrf/src/util/peripheral.rs107
-rw-r--r--embassy-nrf/src/util/ring_buffer.rs80
7 files changed, 298 insertions, 212 deletions
diff --git a/embassy-nrf-examples/.cargo/config b/embassy-nrf-examples/.cargo/config
index 3f319ae55..591288879 100644
--- a/embassy-nrf-examples/.cargo/config
+++ b/embassy-nrf-examples/.cargo/config
@@ -20,8 +20,4 @@ rustflags = [
20] 20]
21 21
22[build] 22[build]
23# Pick ONE of these compilation targets 23target = "thumbv7em-none-eabi"
24# target = "thumbv6m-none-eabi" # Cortex-M0 and Cortex-M0+
25# target = "thumbv7m-none-eabi" # Cortex-M3
26# target = "thumbv7em-none-eabi" # Cortex-M4 and Cortex-M7 (no FPU)
27target = "thumbv7em-none-eabihf" # Cortex-M4F and Cortex-M7F (with FPU)
diff --git a/embassy-nrf-examples/src/bin/buffered_uart.rs b/embassy-nrf-examples/src/bin/buffered_uart.rs
index 6e15fbcfa..68a76f71e 100644
--- a/embassy-nrf-examples/src/bin/buffered_uart.rs
+++ b/embassy-nrf-examples/src/bin/buffered_uart.rs
@@ -8,15 +8,17 @@ use example_common::*;
8 8
9use cortex_m_rt::entry; 9use cortex_m_rt::entry;
10use defmt::panic; 10use defmt::panic;
11use futures::pin_mut;
12use nrf52840_hal::gpio; 11use nrf52840_hal::gpio;
13 12
14use embassy::executor::{task, Executor}; 13use embassy::executor::{task, Executor};
15use embassy::io::{AsyncBufRead, AsyncBufReadExt, AsyncWrite, AsyncWriteExt}; 14use embassy::io::{AsyncBufReadExt, AsyncWriteExt};
16use embassy::util::Forever; 15use embassy::util::Forever;
17use embassy_nrf::buffered_uarte; 16use embassy_nrf::buffered_uarte;
18use embassy_nrf::interrupt; 17use embassy_nrf::interrupt;
19 18
19static mut TX_BUFFER: [u8; 4096] = [0; 4096];
20static mut RX_BUFFER: [u8; 4096] = [0; 4096];
21
20#[task] 22#[task]
21async fn run() { 23async fn run() {
22 let p = unwrap!(embassy_nrf::pac::Peripherals::take()); 24 let p = unwrap!(embassy_nrf::pac::Peripherals::take());
@@ -34,14 +36,15 @@ async fn run() {
34 }; 36 };
35 37
36 let irq = interrupt::take!(UARTE0_UART0); 38 let irq = interrupt::take!(UARTE0_UART0);
37 let u = buffered_uarte::BufferedUarte::new( 39 let mut u = buffered_uarte::BufferedUarte::new(
38 p.UARTE0, 40 p.UARTE0,
39 irq, 41 irq,
42 unsafe { &mut RX_BUFFER },
43 unsafe { &mut TX_BUFFER },
40 pins, 44 pins,
41 buffered_uarte::Parity::EXCLUDED, 45 buffered_uarte::Parity::EXCLUDED,
42 buffered_uarte::Baudrate::BAUD115200, 46 buffered_uarte::Baudrate::BAUD115200,
43 ); 47 );
44 pin_mut!(u);
45 48
46 info!("uarte initialized!"); 49 info!("uarte initialized!");
47 50
diff --git a/embassy-nrf/src/buffered_uarte.rs b/embassy-nrf/src/buffered_uarte.rs
index 9863e3fab..4749c3b45 100644
--- a/embassy-nrf/src/buffered_uarte.rs
+++ b/embassy-nrf/src/buffered_uarte.rs
@@ -4,107 +4,29 @@
4//! 4//!
5//! - nrf52832: Section 35 5//! - nrf52832: Section 35
6//! - nrf52840: Section 6.34 6//! - nrf52840: Section 6.34
7use core::cell::UnsafeCell;
8use core::cmp::min; 7use core::cmp::min;
9use core::marker::PhantomPinned; 8use core::marker::PhantomData;
9use core::mem;
10use core::ops::Deref; 10use core::ops::Deref;
11use core::pin::Pin; 11use core::pin::Pin;
12use core::ptr;
13use core::sync::atomic::{compiler_fence, Ordering}; 12use core::sync::atomic::{compiler_fence, Ordering};
14use core::task::{Context, Poll}; 13use core::task::{Context, Poll};
15use embassy::io::{AsyncBufRead, AsyncWrite, Result}; 14use embassy::io::{AsyncBufRead, AsyncWrite, Result};
16use embassy::util::WakerRegistration; 15use embassy::util::WakerRegistration;
17use embedded_hal::digital::v2::OutputPin; 16use embedded_hal::digital::v2::OutputPin;
18 17
19use crate::fmt::{assert, panic, todo, *}; 18use crate::fmt::{panic, todo, *};
20use crate::hal::gpio::Port as GpioPort; 19use crate::hal::gpio::Port as GpioPort;
21use crate::interrupt::{self, CriticalSection, OwnedInterrupt}; 20use crate::interrupt::{self, OwnedInterrupt};
21use crate::pac;
22use crate::pac::uarte0; 22use crate::pac::uarte0;
23use crate::util::peripheral;
24use crate::util::ring_buffer::RingBuffer;
23 25
24// Re-export SVD variants to allow user to directly set values 26// Re-export SVD variants to allow user to directly set values
25pub use crate::hal::uarte::Pins; 27pub use crate::hal::uarte::Pins;
26pub use uarte0::{baudrate::BAUDRATE_A as Baudrate, config::PARITY_A as Parity}; 28pub use uarte0::{baudrate::BAUDRATE_A as Baudrate, config::PARITY_A as Parity};
27 29
28const RINGBUF_SIZE: usize = 512;
29struct RingBuf {
30 buf: [u8; RINGBUF_SIZE],
31 start: usize,
32 end: usize,
33 empty: bool,
34}
35
36impl RingBuf {
37 fn new() -> Self {
38 RingBuf {
39 buf: [0; RINGBUF_SIZE],
40 start: 0,
41 end: 0,
42 empty: true,
43 }
44 }
45
46 fn push_buf(&mut self) -> &mut [u8] {
47 if self.start == self.end && !self.empty {
48 trace!(" ringbuf: push_buf empty");
49 return &mut self.buf[..0];
50 }
51
52 let n = if self.start <= self.end {
53 RINGBUF_SIZE - self.end
54 } else {
55 self.start - self.end
56 };
57
58 trace!(" ringbuf: push_buf {:?}..{:?}", self.end, self.end + n);
59 &mut self.buf[self.end..self.end + n]
60 }
61
62 fn push(&mut self, n: usize) {
63 trace!(" ringbuf: push {:?}", n);
64 if n == 0 {
65 return;
66 }
67
68 self.end = Self::wrap(self.end + n);
69 self.empty = false;
70 }
71
72 fn pop_buf(&mut self) -> &mut [u8] {
73 if self.empty {
74 trace!(" ringbuf: pop_buf empty");
75 return &mut self.buf[..0];
76 }
77
78 let n = if self.end <= self.start {
79 RINGBUF_SIZE - self.start
80 } else {
81 self.end - self.start
82 };
83
84 trace!(" ringbuf: pop_buf {:?}..{:?}", self.start, self.start + n);
85 &mut self.buf[self.start..self.start + n]
86 }
87
88 fn pop(&mut self, n: usize) {
89 trace!(" ringbuf: pop {:?}", n);
90 if n == 0 {
91 return;
92 }
93
94 self.start = Self::wrap(self.start + n);
95 self.empty = self.start == self.end;
96 }
97
98 fn wrap(n: usize) -> usize {
99 assert!(n <= RINGBUF_SIZE);
100 if n == RINGBUF_SIZE {
101 0
102 } else {
103 n
104 }
105 }
106}
107
108#[derive(Copy, Clone, Debug, PartialEq)] 30#[derive(Copy, Clone, Debug, PartialEq)]
109enum RxState { 31enum RxState {
110 Idle, 32 Idle,
@@ -126,28 +48,12 @@ enum TxState {
126/// are disabled before using `Uarte`. See product specification: 48/// are disabled before using `Uarte`. See product specification:
127/// - nrf52832: Section 15.2 49/// - nrf52832: Section 15.2
128/// - nrf52840: Section 6.1.2 50/// - nrf52840: Section 6.1.2
129pub struct BufferedUarte<T: Instance> { 51pub struct BufferedUarte<'a, T: Instance> {
130 started: bool, 52 reg: peripheral::Registration<State<'a, T>>,
131 state: UnsafeCell<UarteState<T>>, 53 wtf: PhantomData<&'a ()>,
132} 54}
133 55
134// public because it needs to be used in Instance::{get_state, set_state}, but 56impl<'a, T: Instance> Unpin for BufferedUarte<'a, T> {}
135// should not be used outside the module
136#[doc(hidden)]
137pub struct UarteState<T: Instance> {
138 inner: T,
139 irq: T::Interrupt,
140
141 rx: RingBuf,
142 rx_state: RxState,
143 rx_waker: WakerRegistration,
144
145 tx: RingBuf,
146 tx_state: TxState,
147 tx_waker: WakerRegistration,
148
149 _pin: PhantomPinned,
150}
151 57
152#[cfg(any(feature = "52833", feature = "52840"))] 58#[cfg(any(feature = "52833", feature = "52840"))]
153fn port_bit(port: GpioPort) -> bool { 59fn port_bit(port: GpioPort) -> bool {
@@ -157,10 +63,12 @@ fn port_bit(port: GpioPort) -> bool {
157 } 63 }
158} 64}
159 65
160impl<T: Instance> BufferedUarte<T> { 66impl<'a, T: Instance> BufferedUarte<'a, T> {
161 pub fn new( 67 pub fn new(
162 uarte: T, 68 uarte: T,
163 irq: T::Interrupt, 69 irq: T::Interrupt,
70 rx_buffer: &'a mut [u8],
71 tx_buffer: &'a mut [u8],
164 mut pins: Pins, 72 mut pins: Pins,
165 parity: Parity, 73 parity: Parity,
166 baudrate: Baudrate, 74 baudrate: Baudrate,
@@ -218,87 +126,79 @@ impl<T: Instance> BufferedUarte<T> {
218 // Configure frequency 126 // Configure frequency
219 uarte.baudrate.write(|w| w.baudrate().variant(baudrate)); 127 uarte.baudrate.write(|w| w.baudrate().variant(baudrate));
220 128
129 irq.pend();
130
221 BufferedUarte { 131 BufferedUarte {
222 started: false, 132 reg: peripheral::Registration::new(
223 state: UnsafeCell::new(UarteState {
224 inner: uarte,
225 irq, 133 irq,
226 134 State {
227 rx: RingBuf::new(), 135 inner: uarte,
228 rx_state: RxState::Idle, 136
229 rx_waker: WakerRegistration::new(), 137 rx: RingBuffer::new(rx_buffer),
230 138 rx_state: RxState::Idle,
231 tx: RingBuf::new(), 139 rx_waker: WakerRegistration::new(),
232 tx_state: TxState::Idle, 140
233 tx_waker: WakerRegistration::new(), 141 tx: RingBuffer::new(tx_buffer),
234 142 tx_state: TxState::Idle,
235 _pin: PhantomPinned, 143 tx_waker: WakerRegistration::new(),
236 }), 144 },
145 ),
146 wtf: PhantomData,
237 } 147 }
238 } 148 }
239
240 fn with_state<'a, R>(
241 self: Pin<&'a mut Self>,
242 f: impl FnOnce(Pin<&'a mut UarteState<T>>) -> R,
243 ) -> R {
244 let Self { state, started } = unsafe { self.get_unchecked_mut() };
245
246 interrupt::free(|cs| {
247 let ptr = state.get();
248
249 if !*started {
250 T::set_state(cs, ptr);
251
252 *started = true;
253
254 // safety: safe because critical section ensures only one *mut UartState
255 // exists at the same time.
256 unsafe { Pin::new_unchecked(&mut *ptr) }.start();
257 }
258
259 // safety: safe because critical section ensures only one *mut UartState
260 // exists at the same time.
261 f(unsafe { Pin::new_unchecked(&mut *ptr) })
262 })
263 }
264} 149}
265 150
266impl<T: Instance> Drop for BufferedUarte<T> { 151impl<'a, T: Instance> Drop for BufferedUarte<'a, T> {
267 fn drop(&mut self) { 152 fn drop(&mut self) {
268 // stop DMA before dropping, because DMA is using the buffer in `self`. 153 // stop DMA before dropping, because DMA is using the buffer in `self`.
269 todo!() 154 todo!()
270 } 155 }
271} 156}
272 157
273impl<T: Instance> AsyncBufRead for BufferedUarte<T> { 158impl<'a, T: Instance> AsyncBufRead for BufferedUarte<'a, T> {
274 fn poll_fill_buf(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<&[u8]>> { 159 fn poll_fill_buf(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<&[u8]>> {
275 self.with_state(|s| s.poll_fill_buf(cx)) 160 let this = unsafe { self.get_unchecked_mut() };
161 this.reg.with(|state, _| {
162 let z: Poll<Result<&[u8]>> = state.poll_fill_buf(cx);
163 let z: Poll<Result<&[u8]>> = unsafe { mem::transmute(z) };
164 z
165 })
276 } 166 }
277 167
278 fn consume(self: Pin<&mut Self>, amt: usize) { 168 fn consume(self: Pin<&mut Self>, amt: usize) {
279 self.with_state(|s| s.consume(amt)) 169 let this = unsafe { self.get_unchecked_mut() };
170 this.reg.with(|state, irq| state.consume(irq, amt))
280 } 171 }
281} 172}
282 173
283impl<T: Instance> AsyncWrite for BufferedUarte<T> { 174impl<'a, T: Instance> AsyncWrite for BufferedUarte<'a, T> {
284 fn poll_write(self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &[u8]) -> Poll<Result<usize>> { 175 fn poll_write(self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &[u8]) -> Poll<Result<usize>> {
285 self.with_state(|s| s.poll_write(cx, buf)) 176 let this = unsafe { self.get_unchecked_mut() };
177 this.reg.with(|state, irq| state.poll_write(irq, cx, buf))
286 } 178 }
287} 179}
288 180
289impl<T: Instance> UarteState<T> { 181// ====================================
290 pub fn start(self: Pin<&mut Self>) { 182// ====================================
291 self.irq.set_handler(|| unsafe { 183// ====================================
292 interrupt::free(|cs| T::get_state(cs).as_mut().unwrap().on_interrupt());
293 });
294 184
295 self.irq.pend(); 185// public because it needs to be used in Instance trait, but
296 self.irq.enable(); 186// should not be used outside the module
297 } 187#[doc(hidden)]
188pub struct State<'a, T: Instance> {
189 inner: T,
298 190
299 fn poll_fill_buf(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<&[u8]>> { 191 rx: RingBuffer<'a>,
300 let this = unsafe { self.get_unchecked_mut() }; 192 rx_state: RxState,
193 rx_waker: WakerRegistration,
194
195 tx: RingBuffer<'a>,
196 tx_state: TxState,
197 tx_waker: WakerRegistration,
198}
301 199
200impl<'a, T: Instance> State<'a, T> {
201 fn poll_fill_buf(&mut self, cx: &mut Context<'_>) -> Poll<Result<&[u8]>> {
302 // Conservative compiler fence to prevent optimizations that do not 202 // Conservative compiler fence to prevent optimizations that do not
303 // take in to account actions by DMA. The fence has been placed here, 203 // take in to account actions by DMA. The fence has been placed here,
304 // before any DMA action has started 204 // before any DMA action has started
@@ -306,7 +206,7 @@ impl<T: Instance> UarteState<T> {
306 trace!("poll_read"); 206 trace!("poll_read");
307 207
308 // We have data ready in buffer? Return it. 208 // We have data ready in buffer? Return it.
309 let buf = this.rx.pop_buf(); 209 let buf = self.rx.pop_buf();
310 if buf.len() != 0 { 210 if buf.len() != 0 {
311 trace!(" got {:?} {:?}", buf.as_ptr() as u32, buf.len()); 211 trace!(" got {:?} {:?}", buf.as_ptr() as u32, buf.len());
312 return Poll::Ready(Ok(buf)); 212 return Poll::Ready(Ok(buf));
@@ -314,38 +214,40 @@ impl<T: Instance> UarteState<T> {
314 214
315 trace!(" empty"); 215 trace!(" empty");
316 216
317 if this.rx_state == RxState::ReceivingReady { 217 if self.rx_state == RxState::ReceivingReady {
318 trace!(" stopping"); 218 trace!(" stopping");
319 this.rx_state = RxState::Stopping; 219 self.rx_state = RxState::Stopping;
320 this.inner.tasks_stoprx.write(|w| unsafe { w.bits(1) }); 220 self.inner.tasks_stoprx.write(|w| unsafe { w.bits(1) });
321 } 221 }
322 222
323 this.rx_waker.register(cx.waker()); 223 self.rx_waker.register(cx.waker());
324 Poll::Pending 224 Poll::Pending
325 } 225 }
326 226
327 fn consume(self: Pin<&mut Self>, amt: usize) { 227 fn consume(&mut self, irq: &mut T::Interrupt, amt: usize) {
328 let this = unsafe { self.get_unchecked_mut() };
329 trace!("consume {:?}", amt); 228 trace!("consume {:?}", amt);
330 this.rx.pop(amt); 229 self.rx.pop(amt);
331 this.irq.pend(); 230 irq.pend();
332 } 231 }
333 232
334 fn poll_write(self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &[u8]) -> Poll<Result<usize>> { 233 fn poll_write(
335 let this = unsafe { self.get_unchecked_mut() }; 234 &mut self,
336 235 irq: &mut T::Interrupt,
236 cx: &mut Context<'_>,
237 buf: &[u8],
238 ) -> Poll<Result<usize>> {
337 trace!("poll_write: {:?}", buf.len()); 239 trace!("poll_write: {:?}", buf.len());
338 240
339 let tx_buf = this.tx.push_buf(); 241 let tx_buf = self.tx.push_buf();
340 if tx_buf.len() == 0 { 242 if tx_buf.len() == 0 {
341 trace!("poll_write: pending"); 243 trace!("poll_write: pending");
342 this.tx_waker.register(cx.waker()); 244 self.tx_waker.register(cx.waker());
343 return Poll::Pending; 245 return Poll::Pending;
344 } 246 }
345 247
346 let n = min(tx_buf.len(), buf.len()); 248 let n = min(tx_buf.len(), buf.len());
347 tx_buf[..n].copy_from_slice(&buf[..n]); 249 tx_buf[..n].copy_from_slice(&buf[..n]);
348 this.tx.push(n); 250 self.tx.push(n);
349 251
350 trace!("poll_write: queued {:?}", n); 252 trace!("poll_write: queued {:?}", n);
351 253
@@ -354,10 +256,17 @@ impl<T: Instance> UarteState<T> {
354 // before any DMA action has started 256 // before any DMA action has started
355 compiler_fence(Ordering::SeqCst); 257 compiler_fence(Ordering::SeqCst);
356 258
357 this.irq.pend(); 259 irq.pend();
358 260
359 Poll::Ready(Ok(n)) 261 Poll::Ready(Ok(n))
360 } 262 }
263}
264
265impl<'a, T: Instance> peripheral::State for State<'a, T> {
266 type Interrupt = T::Interrupt;
267 fn store<'b>() -> &'b peripheral::Store<Self> {
268 unsafe { mem::transmute(T::storage()) }
269 }
361 270
362 fn on_interrupt(&mut self) { 271 fn on_interrupt(&mut self) {
363 trace!("irq: start"); 272 trace!("irq: start");
@@ -505,39 +414,27 @@ mod private {
505 impl Sealed for crate::pac::UARTE1 {} 414 impl Sealed for crate::pac::UARTE1 {}
506} 415}
507 416
508pub trait Instance: Deref<Target = uarte0::RegisterBlock> + Sized + private::Sealed { 417pub trait Instance:
418 Deref<Target = uarte0::RegisterBlock> + Sized + private::Sealed + 'static
419{
509 type Interrupt: OwnedInterrupt; 420 type Interrupt: OwnedInterrupt;
510 421 fn storage() -> &'static peripheral::Store<State<'static, Self>>;
511 #[doc(hidden)]
512 fn get_state(_cs: &CriticalSection) -> *mut UarteState<Self>;
513
514 #[doc(hidden)]
515 fn set_state(_cs: &CriticalSection, state: *mut UarteState<Self>);
516} 422}
517 423
518static mut UARTE0_STATE: *mut UarteState<crate::pac::UARTE0> = ptr::null_mut(); 424impl Instance for pac::UARTE0 {
519#[cfg(any(feature = "52833", feature = "52840", feature = "9160"))]
520static mut UARTE1_STATE: *mut UarteState<crate::pac::UARTE1> = ptr::null_mut();
521
522impl Instance for crate::pac::UARTE0 {
523 type Interrupt = interrupt::UARTE0_UART0Interrupt; 425 type Interrupt = interrupt::UARTE0_UART0Interrupt;
524 426 fn storage() -> &'static peripheral::Store<State<'static, Self>> {
525 fn get_state(_cs: &CriticalSection) -> *mut UarteState<Self> { 427 static STORAGE: peripheral::Store<State<'static, crate::pac::UARTE0>> =
526 unsafe { UARTE0_STATE } // Safe because of CriticalSection 428 peripheral::Store::uninit();
527 } 429 &STORAGE
528 fn set_state(_cs: &CriticalSection, state: *mut UarteState<Self>) {
529 unsafe { UARTE0_STATE = state } // Safe because of CriticalSection
530 } 430 }
531} 431}
532 432
533#[cfg(any(feature = "52833", feature = "52840", feature = "9160"))] 433impl Instance for pac::UARTE1 {
534impl Instance for crate::pac::UARTE1 {
535 type Interrupt = interrupt::UARTE1Interrupt; 434 type Interrupt = interrupt::UARTE1Interrupt;
536 435 fn storage() -> &'static peripheral::Store<State<'static, Self>> {
537 fn get_state(_cs: &CriticalSection) -> *mut UarteState<Self> { 436 static STORAGE: peripheral::Store<State<'static, crate::pac::UARTE1>> =
538 unsafe { UARTE1_STATE } // Safe because of CriticalSection 437 peripheral::Store::uninit();
539 } 438 &STORAGE
540 fn set_state(_cs: &CriticalSection, state: *mut UarteState<Self>) {
541 unsafe { UARTE1_STATE = state } // Safe because of CriticalSection
542 } 439 }
543} 440}
diff --git a/embassy-nrf/src/lib.rs b/embassy-nrf/src/lib.rs
index e97002a20..ac2371766 100644
--- a/embassy-nrf/src/lib.rs
+++ b/embassy-nrf/src/lib.rs
@@ -50,6 +50,7 @@ pub use nrf52840_hal as hal;
50 50
51// This mod MUST go first, so that the others see its macros. 51// This mod MUST go first, so that the others see its macros.
52pub(crate) mod fmt; 52pub(crate) mod fmt;
53pub(crate) mod util;
53 54
54pub mod buffered_uarte; 55pub mod buffered_uarte;
55pub mod gpiote; 56pub mod gpiote;
diff --git a/embassy-nrf/src/util/mod.rs b/embassy-nrf/src/util/mod.rs
new file mode 100644
index 000000000..2fd5453d3
--- /dev/null
+++ b/embassy-nrf/src/util/mod.rs
@@ -0,0 +1,2 @@
1pub mod peripheral;
2pub mod ring_buffer;
diff --git a/embassy-nrf/src/util/peripheral.rs b/embassy-nrf/src/util/peripheral.rs
new file mode 100644
index 000000000..85de3419e
--- /dev/null
+++ b/embassy-nrf/src/util/peripheral.rs
@@ -0,0 +1,107 @@
1use core::mem;
2use core::mem::MaybeUninit;
3use core::ptr;
4use core::sync::atomic::{compiler_fence, Ordering};
5use core::{cell::UnsafeCell, marker::PhantomData};
6
7use crate::interrupt::OwnedInterrupt;
8
9pub struct Store<T>(MaybeUninit<UnsafeCell<T>>);
10impl<T> Store<T> {
11 pub const fn uninit() -> Self {
12 Self(MaybeUninit::uninit())
13 }
14
15 unsafe fn as_mut_ptr(&self) -> *mut T {
16 (*self.0.as_ptr()).get()
17 }
18
19 unsafe fn as_mut(&self) -> &mut T {
20 &mut *self.as_mut_ptr()
21 }
22
23 unsafe fn write(&self, val: T) {
24 ptr::write(self.as_mut_ptr(), val)
25 }
26
27 unsafe fn drop_in_place(&self) {
28 ptr::drop_in_place(self.as_mut_ptr())
29 }
30
31 unsafe fn read(&self) -> T {
32 ptr::read(self.as_mut_ptr())
33 }
34}
35unsafe impl<T> Send for Store<T> {}
36unsafe impl<T> Sync for Store<T> {}
37
38pub trait State: Sized {
39 type Interrupt: OwnedInterrupt;
40 fn on_interrupt(&mut self);
41 #[doc(hidden)]
42 fn store<'a>() -> &'a Store<Self>;
43}
44
45pub struct Registration<P: State> {
46 irq: P::Interrupt,
47 not_send: PhantomData<*mut P>,
48}
49
50impl<P: State> Registration<P> {
51 pub fn new(irq: P::Interrupt, state: P) -> Self {
52 // safety:
53 // - No other PeripheralRegistration can already exist because we have the owned interrupt
54 // - therefore, storage is uninitialized
55 // - therefore it's safe to overwrite it without dropping the previous contents
56 unsafe { P::store().write(state) }
57
58 irq.set_handler(|| {
59 // safety:
60 // - If a PeripheralRegistration instance exists, P::storage() is initialized.
61 // - It's OK to get a &mut to it since the irq is disabled.
62 unsafe { P::store().as_mut() }.on_interrupt();
63 });
64
65 compiler_fence(Ordering::SeqCst);
66 irq.enable();
67
68 Self {
69 irq,
70 not_send: PhantomData,
71 }
72 }
73
74 pub fn with<R>(&mut self, f: impl FnOnce(&mut P, &mut P::Interrupt) -> R) -> R {
75 self.irq.disable();
76 compiler_fence(Ordering::SeqCst);
77
78 // safety:
79 // - If a PeripheralRegistration instance exists, P::storage() is initialized.
80 // - It's OK to get a &mut to it since the irq is disabled.
81 let r = f(unsafe { P::store().as_mut() }, &mut self.irq);
82
83 compiler_fence(Ordering::SeqCst);
84 self.irq.enable();
85
86 r
87 }
88
89 pub fn free(self) -> (P::Interrupt, P) {
90 let irq = unsafe { ptr::read(&self.irq) };
91 irq.disable();
92 irq.set_handler(|| ());
93 mem::forget(self);
94 let storage = P::store();
95 (irq, unsafe { storage.read() })
96 }
97}
98
99impl<P: State> Drop for Registration<P> {
100 fn drop(&mut self) {
101 self.irq.disable();
102 self.irq.set_handler(|| ());
103
104 let storage = P::store();
105 unsafe { storage.drop_in_place() };
106 }
107}
diff --git a/embassy-nrf/src/util/ring_buffer.rs b/embassy-nrf/src/util/ring_buffer.rs
new file mode 100644
index 000000000..f395785a5
--- /dev/null
+++ b/embassy-nrf/src/util/ring_buffer.rs
@@ -0,0 +1,80 @@
1use crate::fmt::{assert, panic, todo, *};
2
3pub struct RingBuffer<'a> {
4 buf: &'a mut [u8],
5 start: usize,
6 end: usize,
7 empty: bool,
8}
9
10impl<'a> RingBuffer<'a> {
11 pub fn new(buf: &'a mut [u8]) -> Self {
12 Self {
13 buf,
14 start: 0,
15 end: 0,
16 empty: true,
17 }
18 }
19
20 pub fn push_buf(&mut self) -> &mut [u8] {
21 if self.start == self.end && !self.empty {
22 trace!(" ringbuf: push_buf empty");
23 return &mut self.buf[..0];
24 }
25
26 let n = if self.start <= self.end {
27 self.buf.len() - self.end
28 } else {
29 self.start - self.end
30 };
31
32 trace!(" ringbuf: push_buf {:?}..{:?}", self.end, self.end + n);
33 &mut self.buf[self.end..self.end + n]
34 }
35
36 pub fn push(&mut self, n: usize) {
37 trace!(" ringbuf: push {:?}", n);
38 if n == 0 {
39 return;
40 }
41
42 self.end = self.wrap(self.end + n);
43 self.empty = false;
44 }
45
46 pub fn pop_buf(&mut self) -> &mut [u8] {
47 if self.empty {
48 trace!(" ringbuf: pop_buf empty");
49 return &mut self.buf[..0];
50 }
51
52 let n = if self.end <= self.start {
53 self.buf.len() - self.start
54 } else {
55 self.end - self.start
56 };
57
58 trace!(" ringbuf: pop_buf {:?}..{:?}", self.start, self.start + n);
59 &mut self.buf[self.start..self.start + n]
60 }
61
62 pub fn pop(&mut self, n: usize) {
63 trace!(" ringbuf: pop {:?}", n);
64 if n == 0 {
65 return;
66 }
67
68 self.start = self.wrap(self.start + n);
69 self.empty = self.start == self.end;
70 }
71
72 fn wrap(&self, n: usize) -> usize {
73 assert!(n <= self.buf.len());
74 if n == self.buf.len() {
75 0
76 } else {
77 n
78 }
79 }
80}