436: Add support for temperature sensor peripheral r=lulf a=lulf

* Add TEMP peripheral to all nRF52 chips
* Add async HAL for reading temperature values
* Add example application reading temperature values

Co-authored-by: Ulf Lilleengen <lulf@redhat.com>
Co-authored-by: Ulf Lilleengen <ulf.lilleengen@gmail.com>
This commit is contained in:
bors[bot] 2021-10-19 18:50:37 +00:00 committed by GitHub
commit 675172f981
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 136 additions and 0 deletions

View File

@ -48,6 +48,7 @@ embedded-dma = "0.1.2"
futures = { version = "0.3.17", default-features = false }
critical-section = "0.2.3"
rand_core = "0.6.3"
fixed = "1.10.0"
nrf52805-pac = { version = "0.10.1", optional = true, features = [ "rt" ] }
nrf52810-pac = { version = "0.10.1", optional = true, features = [ "rt" ] }

View File

@ -114,6 +114,9 @@ embassy_hal_common::peripherals! {
P0_29,
P0_30,
P0_31,
// TEMP
TEMP,
}
impl_uarte!(UARTE0, UARTE0, UARTE0_UART0);

View File

@ -117,6 +117,9 @@ embassy_hal_common::peripherals! {
P0_29,
P0_30,
P0_31,
// TEMP
TEMP,
}
impl_uarte!(UARTE0, UARTE0, UARTE0_UART0);

View File

@ -117,6 +117,9 @@ embassy_hal_common::peripherals! {
P0_29,
P0_30,
P0_31,
// TEMP
TEMP,
}
impl_uarte!(UARTE0, UARTE0, UARTE0_UART0);

View File

@ -112,6 +112,9 @@ embassy_hal_common::peripherals! {
P0_29,
P0_30,
P0_31,
// TEMP
TEMP,
}
impl_uarte!(UARTE0, UARTE0, UARTE0_UART0);

View File

@ -124,6 +124,9 @@ embassy_hal_common::peripherals! {
P0_29,
P0_30,
P0_31,
// TEMP
TEMP,
}
impl_uarte!(UARTE0, UARTE0, UARTE0_UART0);

View File

@ -144,6 +144,9 @@ embassy_hal_common::peripherals! {
P1_13,
P1_14,
P1_15,
// TEMP
TEMP,
}
impl_uarte!(UARTE0, UARTE0, UARTE0_UART0);

View File

@ -147,6 +147,9 @@ embassy_hal_common::peripherals! {
P1_13,
P1_14,
P1_15,
// TEMP
TEMP,
}
impl_uarte!(UARTE0, UARTE0, UARTE0_UART0);

View File

@ -39,6 +39,8 @@ pub mod rng;
#[cfg(not(feature = "nrf52820"))]
pub mod saadc;
pub mod spim;
#[cfg(not(feature = "nrf9160"))]
pub mod temp;
pub mod timer;
pub mod twim;
pub mod uarte;

86
embassy-nrf/src/temp.rs Normal file
View File

@ -0,0 +1,86 @@
//! Temperature sensor interface.
use crate::interrupt;
use crate::pac;
use crate::peripherals::TEMP;
use core::marker::PhantomData;
use core::task::Poll;
use embassy::interrupt::InterruptExt;
use embassy::util::Unborrow;
use embassy::waitqueue::AtomicWaker;
use embassy_hal_common::{drop::OnDrop, unborrow};
use fixed::types::I30F2;
use futures::future::poll_fn;
/// Integrated temperature sensor.
pub struct Temp<'d> {
_temp: PhantomData<&'d TEMP>,
_irq: interrupt::TEMP,
}
static WAKER: AtomicWaker = AtomicWaker::new();
impl<'d> Temp<'d> {
pub fn new(
_t: impl Unborrow<Target = TEMP> + 'd,
irq: impl Unborrow<Target = interrupt::TEMP> + 'd,
) -> Self {
unborrow!(_t, irq);
// Enable interrupt that signals temperature values
irq.disable();
irq.set_handler(|_| {
let t = Self::regs();
t.intenclr.write(|w| w.datardy().clear());
WAKER.wake();
});
irq.enable();
Self {
_temp: PhantomData,
_irq: irq,
}
}
/// Perform an asynchronous temperature measurement. The returned future
/// can be awaited to obtain the measurement.
///
/// If the future is dropped, the measurement is cancelled.
///
/// # Example
///
/// ```no_run
/// let mut t = Temp::new(p.TEMP, interrupt::take!(TEMP));
/// let v: u16 = t.read().await.to_num::<u16>();
/// ```
pub async fn read(&mut self) -> I30F2 {
// In case the future is dropped, stop the task and reset events.
let on_drop = OnDrop::new(|| {
let t = Self::regs();
t.tasks_stop.write(|w| unsafe { w.bits(1) });
t.events_datardy.reset();
});
let t = Self::regs();
t.intenset.write(|w| w.datardy().set());
unsafe { t.tasks_start.write(|w| w.bits(1)) };
let value = poll_fn(|cx| {
WAKER.register(cx.waker());
if t.events_datardy.read().bits() == 0 {
return Poll::Pending;
} else {
t.events_datardy.reset();
let raw = t.temp.read().bits();
Poll::Ready(I30F2::from_bits(raw as i32))
}
})
.await;
on_drop.defuse();
value
}
fn regs() -> &'static pac::temp::RegisterBlock {
unsafe { &*pac::TEMP::ptr() }
}
}

View File

@ -0,0 +1,26 @@
#![no_std]
#![no_main]
#![feature(type_alias_impl_trait)]
#[path = "../example_common.rs"]
mod example_common;
use example_common::*;
use defmt::panic;
use embassy::{
executor::Spawner,
time::{Duration, Timer},
};
use embassy_nrf::{interrupt, temp::Temp, Peripherals};
#[embassy::main]
async fn main(_spawner: Spawner, p: Peripherals) {
let irq = interrupt::take!(TEMP);
let mut temp = Temp::new(p.TEMP, irq);
loop {
let value = temp.read().await;
info!("temperature: {}℃", value.to_num::<u16>());
Timer::after(Duration::from_secs(1)).await;
}
}