Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement embedded-hal 1.0 traits #431

Merged
merged 10 commits into from
Mar 6, 2024
9 changes: 8 additions & 1 deletion nrf-hal-common/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -76,10 +76,17 @@ version = "0.12.2"
version = "0.2.0"
optional = true

[dependencies.embedded-hal]
[dependencies.embedded-hal-02]
package = "embedded-hal"
features = ["unproven"]
version = "0.2.4"

[dependencies.embedded-hal]
version = "1.0.0"

[dependencies.embedded-io]
version = "0.6.1"

[features]
doc = []
51 = ["nrf51-pac"]
Expand Down
4 changes: 2 additions & 2 deletions nrf-hal-common/src/adc.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! API for the Analog to Digital converter.

use embedded_hal::adc::{Channel, OneShot};
use embedded_hal_02::adc::{Channel, OneShot};

use core::hint::unreachable_unchecked;

Expand Down Expand Up @@ -128,7 +128,7 @@ macro_rules! channel_mappings {
impl Channel<Adc> for $pin {
type ID = u8;

fn channel() -> <Self as embedded_hal::adc::Channel<Adc>>::ID {
fn channel() -> <Self as embedded_hal_02::adc::Channel<Adc>>::ID {
$n
}
}
Expand Down
49 changes: 29 additions & 20 deletions nrf-hal-common/src/delay.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
//! Delays.
use cast::u32;
use cortex_m::peripheral::syst::SystClkSource;
use cortex_m::peripheral::SYST;

use crate::clocks::HFCLK_FREQ;
use crate::hal::blocking::delay::{DelayMs, DelayUs};
use core::convert::TryInto;
use cortex_m::peripheral::syst::SystClkSource;
use cortex_m::peripheral::SYST;
use embedded_hal::delay::DelayNs;
use embedded_hal_02::blocking::delay::{DelayMs, DelayUs};

/// System timer (SysTick) as a delay provider.
pub struct Delay {
Expand All @@ -27,28 +28,48 @@ impl Delay {

impl DelayMs<u32> for Delay {
fn delay_ms(&mut self, ms: u32) {
self.delay_us(ms * 1_000);
DelayNs::delay_ms(self, ms);
}
}

impl DelayMs<u16> for Delay {
fn delay_ms(&mut self, ms: u16) {
self.delay_ms(u32(ms));
DelayNs::delay_ms(self, ms.into());
}
}

impl DelayMs<u8> for Delay {
fn delay_ms(&mut self, ms: u8) {
self.delay_ms(u32(ms));
DelayNs::delay_ms(self, ms.into());
}
}

impl DelayUs<u32> for Delay {
fn delay_us(&mut self, us: u32) {
DelayNs::delay_us(self, us);
}
}

impl DelayUs<u16> for Delay {
fn delay_us(&mut self, us: u16) {
DelayNs::delay_us(self, us.into());
}
}

impl DelayUs<u8> for Delay {
fn delay_us(&mut self, us: u8) {
DelayNs::delay_us(self, us.into());
}
}

impl DelayNs for Delay {
fn delay_ns(&mut self, ns: u32) {
// The SysTick Reload Value register supports values between 1 and 0x00FFFFFF.
const MAX_RVR: u32 = 0x00FF_FFFF;

let mut total_rvr = us * (HFCLK_FREQ / 1_000_000);
let mut total_rvr: u32 = (u64::from(ns) * u64::from(HFCLK_FREQ) / 1_000_000_000)
.try_into()
.unwrap();

while total_rvr != 0 {
let current_rvr = if total_rvr <= MAX_RVR {
Expand All @@ -70,15 +91,3 @@ impl DelayUs<u32> for Delay {
}
}
}

impl DelayUs<u16> for Delay {
fn delay_us(&mut self, us: u16) {
self.delay_us(u32(us))
}
}

impl DelayUs<u8> for Delay {
fn delay_us(&mut self, us: u8) {
self.delay_us(u32(us))
}
}
127 changes: 117 additions & 10 deletions nrf-hal-common/src/gpio.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use core::marker::PhantomData;
use core::{convert::Infallible, marker::PhantomData};

/// Disconnected pin in input mode (type state, reset value).
pub struct Disconnected;
Expand Down Expand Up @@ -85,7 +85,7 @@ use crate::pac::P1;
#[cfg(feature = "5340-net")]
use crate::pac::P1_NS as P1;

use crate::hal::digital::v2::{InputPin, OutputPin, StatefulOutputPin};
use embedded_hal::digital::{ErrorType, InputPin, OutputPin, StatefulOutputPin};
use void::Void;

impl<MODE> Pin<MODE> {
Expand Down Expand Up @@ -348,7 +348,63 @@ impl<MODE> Pin<MODE> {
}
}

impl<MODE> ErrorType for Pin<MODE> {
type Error = Infallible;
}

impl<MODE> InputPin for Pin<Input<MODE>> {
fn is_high(&mut self) -> Result<bool, Self::Error> {
self.is_low().map(|v| !v)
}

fn is_low(&mut self) -> Result<bool, Self::Error> {
Ok(self.block().in_.read().bits() & (1 << self.pin()) == 0)
}
}

impl InputPin for Pin<Output<OpenDrainIO>> {
fn is_high(&mut self) -> Result<bool, Self::Error> {
self.is_low().map(|v| !v)
}

fn is_low(&mut self) -> Result<bool, Self::Error> {
Ok(self.block().in_.read().bits() & (1 << self.pin()) == 0)
}
}

impl<MODE> OutputPin for Pin<Output<MODE>> {
fn set_high(&mut self) -> Result<(), Self::Error> {
// NOTE(unsafe) atomic write to a stateless register - TODO(AJM) verify?
// TODO - I wish I could do something like `.pins$i()`...
unsafe {
self.block().outset.write(|w| w.bits(1u32 << self.pin()));
}
Ok(())
}

fn set_low(&mut self) -> Result<(), Self::Error> {
// NOTE(unsafe) atomic write to a stateless register - TODO(AJM) verify?
// TODO - I wish I could do something like `.pins$i()`...
unsafe {
self.block().outclr.write(|w| w.bits(1u32 << self.pin()));
}
Ok(())
}
}

impl<MODE> StatefulOutputPin for Pin<Output<MODE>> {
fn is_set_high(&mut self) -> Result<bool, Self::Error> {
self.is_set_low().map(|v| !v)
}

fn is_set_low(&mut self) -> Result<bool, Self::Error> {
// NOTE(unsafe) atomic read with no side effects - TODO(AJM) verify?
// TODO - I wish I could do something like `.pins$i()`...
Ok(self.block().out.read().bits() & (1 << self.pin()) == 0)
}
}

impl<MODE> embedded_hal_02::digital::v2::InputPin for Pin<Input<MODE>> {
type Error = Void;

fn is_high(&self) -> Result<bool, Self::Error> {
Expand All @@ -360,7 +416,7 @@ impl<MODE> InputPin for Pin<Input<MODE>> {
}
}

impl InputPin for Pin<Output<OpenDrainIO>> {
impl embedded_hal_02::digital::v2::InputPin for Pin<Output<OpenDrainIO>> {
type Error = Void;

fn is_high(&self) -> Result<bool, Self::Error> {
Expand All @@ -372,7 +428,7 @@ impl InputPin for Pin<Output<OpenDrainIO>> {
}
}

impl<MODE> OutputPin for Pin<Output<MODE>> {
impl<MODE> embedded_hal_02::digital::v2::OutputPin for Pin<Output<MODE>> {
type Error = Void;

/// Set the output as high.
Expand All @@ -396,7 +452,7 @@ impl<MODE> OutputPin for Pin<Output<MODE>> {
}
}

impl<MODE> StatefulOutputPin for Pin<Output<MODE>> {
impl<MODE> embedded_hal_02::digital::v2::StatefulOutputPin for Pin<Output<MODE>> {
/// Is the output pin set as high?
fn is_set_high(&self) -> Result<bool, Self::Error> {
self.is_set_low().map(|v| !v)
Expand Down Expand Up @@ -482,10 +538,10 @@ macro_rules! gpio {
$PX
};

use crate::hal::digital::v2::{OutputPin, StatefulOutputPin, InputPin};
use core::convert::Infallible;
use embedded_hal::digital::{ErrorType, InputPin, OutputPin, StatefulOutputPin};
use void::Void;


// ===============================================================
// This chunk allows you to obtain an nrf-hal gpio from the
// upstream nrf52 gpio definitions by defining a trait
Expand Down Expand Up @@ -695,7 +751,58 @@ macro_rules! gpio {
}
}

impl<MODE> ErrorType for $PXi<MODE> {
type Error = Infallible;
}

impl<MODE> InputPin for $PXi<Input<MODE>> {
fn is_high(&mut self) -> Result<bool, Self::Error> {
self.is_low().map(|v| !v)
}

fn is_low(&mut self) -> Result<bool, Self::Error> {
Ok(unsafe { ((*$PX::ptr()).in_.read().bits() & (1 << $i)) == 0 })
}
}

impl InputPin for $PXi<Output<OpenDrainIO>> {
fn is_high(&mut self) -> Result<bool, Self::Error> {
self.is_low().map(|v| !v)
}

fn is_low(&mut self) -> Result<bool, Self::Error> {
Ok(unsafe { ((*$PX::ptr()).in_.read().bits() & (1 << $i)) == 0 })
}
}
impl<MODE> OutputPin for $PXi<Output<MODE>> {
fn set_high(&mut self) -> Result<(), Self::Error> {
// NOTE(unsafe) atomic write to a stateless register - TODO(AJM) verify?
// TODO - I wish I could do something like `.pins$i()`...
unsafe { (*$PX::ptr()).outset.write(|w| w.bits(1u32 << $i)); }
Ok(())
}

fn set_low(&mut self) -> Result<(), Self::Error> {
// NOTE(unsafe) atomic write to a stateless register - TODO(AJM) verify?
// TODO - I wish I could do something like `.pins$i()`...
unsafe { (*$PX::ptr()).outclr.write(|w| w.bits(1u32 << $i)); }
Ok(())
}
}

impl<MODE> StatefulOutputPin for $PXi<Output<MODE>> {
fn is_set_high(&mut self) -> Result<bool, Self::Error> {
self.is_set_low().map(|v| !v)
}

fn is_set_low(&mut self) -> Result<bool, Self::Error> {
// NOTE(unsafe) atomic read with no side effects - TODO(AJM) verify?
// TODO - I wish I could do something like `.pins$i()`...
Ok(unsafe { ((*$PX::ptr()).out.read().bits() & (1 << $i)) == 0 })
}
}

impl<MODE> embedded_hal_02::digital::v2::InputPin for $PXi<Input<MODE>> {
type Error = Void;

fn is_high(&self) -> Result<bool, Self::Error> {
Expand All @@ -707,7 +814,7 @@ macro_rules! gpio {
}
}

impl InputPin for $PXi<Output<OpenDrainIO>> {
impl embedded_hal_02::digital::v2::InputPin for $PXi<Output<OpenDrainIO>> {
type Error = Void;

fn is_high(&self) -> Result<bool, Self::Error> {
Expand All @@ -725,7 +832,7 @@ macro_rules! gpio {
}
}

impl<MODE> OutputPin for $PXi<Output<MODE>> {
impl<MODE> embedded_hal_02::digital::v2::OutputPin for $PXi<Output<MODE>> {
type Error = Void;

/// Set the output as high
Expand All @@ -745,7 +852,7 @@ macro_rules! gpio {
}
}

impl<MODE> StatefulOutputPin for $PXi<Output<MODE>> {
impl<MODE> embedded_hal_02::digital::v2::StatefulOutputPin for $PXi<Output<MODE>> {
/// Is the output pin set as high?
fn is_set_high(&self) -> Result<bool, Self::Error> {
self.is_set_low().map(|v| !v)
Expand Down
2 changes: 1 addition & 1 deletion nrf-hal-common/src/ieee802154.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use core::{
sync::atomic::{self, Ordering},
};

use embedded_hal::timer::CountDown as _;
use embedded_hal_02::timer::CountDown as _;

use crate::{
clocks::{Clocks, ExternalOscillator},
Expand Down
6 changes: 2 additions & 4 deletions nrf-hal-common/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@
#![doc(html_root_url = "https://docs.rs/nrf-hal-common/0.16.1")]
#![no_std]

use embedded_hal as hal;

#[cfg(feature = "51")]
pub use nrf51_pac as pac;

Expand Down Expand Up @@ -114,8 +112,8 @@ pub mod usbd;
pub mod wdt;

pub mod prelude {
pub use crate::hal::digital::v2::*;
pub use crate::hal::prelude::*;
pub use embedded_hal_02::digital::v2::*;
pub use embedded_hal_02::prelude::*;

#[cfg(not(any(feature = "9160", feature = "5340-app", feature = "5340-net")))]
pub use crate::ppi::{ConfigurablePpi, Ppi};
Expand Down
Loading
Loading