embassy_nrf/
temp.rs

1//! Builtin temperature sensor driver.
2
3use core::future::poll_fn;
4use core::task::Poll;
5
6use embassy_hal_internal::drop::OnDrop;
7use embassy_hal_internal::{into_ref, PeripheralRef};
8use embassy_sync::waitqueue::AtomicWaker;
9use fixed::types::I30F2;
10
11use crate::interrupt::InterruptExt;
12use crate::peripherals::TEMP;
13use crate::{interrupt, pac, Peripheral};
14
15/// Interrupt handler.
16pub struct InterruptHandler {
17    _private: (),
18}
19
20impl interrupt::typelevel::Handler<interrupt::typelevel::TEMP> for InterruptHandler {
21    unsafe fn on_interrupt() {
22        let r = pac::TEMP;
23        r.intenclr().write(|w| w.set_datardy(true));
24        WAKER.wake();
25    }
26}
27
28/// Builtin temperature sensor driver.
29pub struct Temp<'d> {
30    _peri: PeripheralRef<'d, TEMP>,
31}
32
33static WAKER: AtomicWaker = AtomicWaker::new();
34
35impl<'d> Temp<'d> {
36    /// Create a new temperature sensor driver.
37    pub fn new(
38        _peri: impl Peripheral<P = TEMP> + 'd,
39        _irq: impl interrupt::typelevel::Binding<interrupt::typelevel::TEMP, InterruptHandler> + 'd,
40    ) -> Self {
41        into_ref!(_peri);
42
43        // Enable interrupt that signals temperature values
44        interrupt::TEMP.unpend();
45        unsafe { interrupt::TEMP.enable() };
46
47        Self { _peri }
48    }
49
50    /// Perform an asynchronous temperature measurement. The returned future
51    /// can be awaited to obtain the measurement.
52    ///
53    /// If the future is dropped, the measurement is cancelled.
54    ///
55    /// # Example
56    ///
57    /// ```no_run
58    /// use embassy_nrf::{bind_interrupts, temp};
59    /// use embassy_nrf::temp::Temp;
60    ///
61    /// bind_interrupts!(struct Irqs {
62    ///     TEMP => temp::InterruptHandler;
63    /// });
64    ///
65    /// # async {
66    /// # let p: embassy_nrf::Peripherals = todo!();
67    /// let mut t = Temp::new(p.TEMP, Irqs);
68    /// let v: u16 = t.read().await.to_num::<u16>();
69    /// # };
70    /// ```
71    pub async fn read(&mut self) -> I30F2 {
72        // In case the future is dropped, stop the task and reset events.
73        let on_drop = OnDrop::new(|| {
74            let t = Self::regs();
75            t.tasks_stop().write_value(1);
76            t.events_datardy().write_value(0);
77        });
78
79        let t = Self::regs();
80        t.intenset().write(|w| w.set_datardy(true));
81        t.tasks_start().write_value(1);
82
83        let value = poll_fn(|cx| {
84            WAKER.register(cx.waker());
85            if t.events_datardy().read() == 0 {
86                Poll::Pending
87            } else {
88                t.events_datardy().write_value(0);
89                let raw = t.temp().read();
90                Poll::Ready(I30F2::from_bits(raw as i32))
91            }
92        })
93        .await;
94        on_drop.defuse();
95        value
96    }
97
98    fn regs() -> pac::temp::Temp {
99        pac::TEMP
100    }
101}
OSZAR »