diff options
| author | Ulf Lilleengen <[email protected]> | 2021-10-18 15:24:31 +0200 |
|---|---|---|
| committer | Ulf Lilleengen <[email protected]> | 2021-10-19 07:18:56 +0200 |
| commit | 2ef4a45fa0e153cb6435c4dc52f19108ca808cc7 (patch) | |
| tree | 8681889a127109a49d592b2857232c18e64645a6 /embassy-nrf/src/temp.rs | |
| parent | 729b17bc25fed42b4348cae0fb3d781590572c3f (diff) | |
Add support for temperature sensor peripheral
* Add TEMP peripheral to all nRF52 chips
* Add async HAL for reading temperature values
* Add example application reading temperature values
Diffstat (limited to 'embassy-nrf/src/temp.rs')
| -rw-r--r-- | embassy-nrf/src/temp.rs | 84 |
1 files changed, 84 insertions, 0 deletions
diff --git a/embassy-nrf/src/temp.rs b/embassy-nrf/src/temp.rs new file mode 100644 index 000000000..6a334c64d --- /dev/null +++ b/embassy-nrf/src/temp.rs | |||
| @@ -0,0 +1,84 @@ | |||
| 1 | //! Temperature sensor interface. | ||
| 2 | |||
| 3 | use crate::interrupt; | ||
| 4 | use crate::pac; | ||
| 5 | use crate::peripherals::TEMP; | ||
| 6 | |||
| 7 | use core::future::Future; | ||
| 8 | use core::marker::PhantomData; | ||
| 9 | use embassy::channel::signal::Signal; | ||
| 10 | use embassy::interrupt::InterruptExt; | ||
| 11 | use embassy::util::Unborrow; | ||
| 12 | use embassy_hal_common::{drop::OnDrop, unborrow}; | ||
| 13 | use fixed::types::I30F2; | ||
| 14 | |||
| 15 | /// Integrated temperature sensor. | ||
| 16 | pub struct Temp<'d> { | ||
| 17 | _temp: PhantomData<&'d TEMP>, | ||
| 18 | _irq: interrupt::TEMP, | ||
| 19 | } | ||
| 20 | |||
| 21 | static IRQ: Signal<I30F2> = Signal::new(); | ||
| 22 | |||
| 23 | impl<'d> Temp<'d> { | ||
| 24 | pub fn new( | ||
| 25 | _t: impl Unborrow<Target = TEMP> + 'd, | ||
| 26 | irq: impl Unborrow<Target = interrupt::TEMP> + 'd, | ||
| 27 | ) -> Self { | ||
| 28 | unborrow!(_t, irq); | ||
| 29 | |||
| 30 | let t = Self::regs(); | ||
| 31 | |||
| 32 | // Enable interrupt that signals temperature values | ||
| 33 | t.intenset.write(|w| w.datardy().set()); | ||
| 34 | irq.disable(); | ||
| 35 | irq.set_handler(|_| { | ||
| 36 | let t = Self::regs(); | ||
| 37 | t.events_datardy.reset(); | ||
| 38 | let raw = t.temp.read().bits(); | ||
| 39 | IRQ.signal(I30F2::from_bits(raw as i32)); | ||
| 40 | }); | ||
| 41 | irq.enable(); | ||
| 42 | Self { | ||
| 43 | _temp: PhantomData, | ||
| 44 | _irq: irq, | ||
| 45 | } | ||
| 46 | } | ||
| 47 | |||
| 48 | /// Perform an asynchronous temperature measurement. The returned future | ||
| 49 | /// can be awaited to obtain the measurement. | ||
| 50 | /// | ||
| 51 | /// If the future is dropped, the measurement is cancelled. | ||
| 52 | /// | ||
| 53 | /// # Example | ||
| 54 | /// | ||
| 55 | /// ```no_run | ||
| 56 | /// let mut t = Temp::new(p.TEMP, interrupt::take!(TEMP)); | ||
| 57 | /// let v: u16 = t.read().await.to_num::<u16>(); | ||
| 58 | /// ``` | ||
| 59 | pub fn read(&mut self) -> impl Future<Output = I30F2> { | ||
| 60 | // In case the future is dropped, stop the task and reset events. | ||
| 61 | let on_drop = OnDrop::new(|| { | ||
| 62 | let t = Self::regs(); | ||
| 63 | unsafe { | ||
| 64 | t.tasks_stop.write(|w| w.bits(1)); | ||
| 65 | } | ||
| 66 | t.events_datardy.reset(); | ||
| 67 | }); | ||
| 68 | |||
| 69 | let t = Self::regs(); | ||
| 70 | // Empty signal channel and start measurement. | ||
| 71 | IRQ.reset(); | ||
| 72 | unsafe { t.tasks_start.write(|w| w.bits(1)) }; | ||
| 73 | |||
| 74 | async move { | ||
| 75 | let value = IRQ.wait().await; | ||
| 76 | on_drop.defuse(); | ||
| 77 | value | ||
| 78 | } | ||
| 79 | } | ||
| 80 | |||
| 81 | fn regs() -> &'static pac::temp::RegisterBlock { | ||
| 82 | unsafe { &*pac::TEMP::ptr() } | ||
| 83 | } | ||
| 84 | } | ||
