mirror of
https://github.com/italicsjenga/rp-hal-boards.git
synced 2024-12-23 20:51:31 +11:00
implement embedded-hal 1.0.0-alpha.5 (#131)
* implement embedded-hal 1.0.0-alpha.5 * Depend on specific alpha version of embedded-hal. * enable feature eh1_0_alpha for CI check
This commit is contained in:
parent
da89888ccb
commit
2b6de3a3c9
2
.github/workflows/check.yml
vendored
2
.github/workflows/check.yml
vendored
|
@ -19,7 +19,7 @@ jobs:
|
||||||
- uses: actions-rs/cargo@v1
|
- uses: actions-rs/cargo@v1
|
||||||
with:
|
with:
|
||||||
command: check
|
command: check
|
||||||
args: --workspace --examples
|
args: --workspace --examples --features eh1_0_alpha
|
||||||
- uses: actions-rs/cargo@v1
|
- uses: actions-rs/cargo@v1
|
||||||
with:
|
with:
|
||||||
command: test
|
command: test
|
||||||
|
|
|
@ -12,6 +12,7 @@ license = "MIT OR Apache-2.0"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
cortex-m = "0.7.2"
|
cortex-m = "0.7.2"
|
||||||
embedded-hal = { version = "0.2.5", features = ["unproven"] }
|
embedded-hal = { version = "0.2.5", features = ["unproven"] }
|
||||||
|
eh1_0_alpha = { version = "=1.0.0-alpha.5", package="embedded-hal", optional=true }
|
||||||
embedded-time = "0.12.0"
|
embedded-time = "0.12.0"
|
||||||
itertools = { version = "0.10.1", default-features = false }
|
itertools = { version = "0.10.1", default-features = false }
|
||||||
nb = "1.0"
|
nb = "1.0"
|
||||||
|
|
|
@ -90,6 +90,18 @@ volatile until a 1.0.0 release.
|
||||||
See the [open issues](https://github.com/rp-rs/rp-hal/issues) for a list of
|
See the [open issues](https://github.com/rp-rs/rp-hal/issues) for a list of
|
||||||
proposed features (and known issues).
|
proposed features (and known issues).
|
||||||
|
|
||||||
|
### Support for embedded-hal 1.0
|
||||||
|
|
||||||
|
We plan to support embedded-hal 1.0 soon after it is released.
|
||||||
|
|
||||||
|
For now, there is preliminary support for alpha versions of embedded-hal, which can
|
||||||
|
be enabled with the feature `eh1_0_alpha`. Please note that this support does not
|
||||||
|
provide any semver compatibility guarantees: With that feature activated, there
|
||||||
|
will be breaking changes even in minor versions of rp2040-hal.
|
||||||
|
|
||||||
|
Support for embedded-hal 1.0(-alpha) exists in parallel to support for
|
||||||
|
embedded-hal 0.2: Traits of both versions are implemented and can be used
|
||||||
|
at the same time.
|
||||||
|
|
||||||
<!-- CONTRIBUTING -->
|
<!-- CONTRIBUTING -->
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|
|
@ -103,6 +103,15 @@ macro_rules! channel {
|
||||||
$channel
|
$channel
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "eh1_0_alpha")]
|
||||||
|
impl eh1_0_alpha::adc::nb::Channel<Adc> for Pin<$pin, FloatingInput> {
|
||||||
|
type ID = u8; // ADC channels are identified numerically
|
||||||
|
|
||||||
|
fn channel(&self) -> u8 {
|
||||||
|
$channel
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,6 +133,15 @@ impl Channel<Adc> for TempSense {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "eh1_0_alpha")]
|
||||||
|
impl eh1_0_alpha::adc::nb::Channel<Adc> for TempSense {
|
||||||
|
type ID = u8; // ADC channels are identified numerically
|
||||||
|
|
||||||
|
fn channel(&self) -> u8 {
|
||||||
|
TEMPERATURE_SENSOR_CHANNEL
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<WORD, PIN> OneShot<Adc, WORD, PIN> for Adc
|
impl<WORD, PIN> OneShot<Adc, WORD, PIN> for Adc
|
||||||
where
|
where
|
||||||
WORD: From<u16>,
|
WORD: From<u16>,
|
||||||
|
@ -153,3 +171,34 @@ where
|
||||||
Ok(self.device.result.read().result().bits().into())
|
Ok(self.device.result.read().result().bits().into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "eh1_0_alpha")]
|
||||||
|
impl<WORD, PIN> eh1_0_alpha::adc::nb::OneShot<Adc, WORD, PIN> for Adc
|
||||||
|
where
|
||||||
|
WORD: From<u16>,
|
||||||
|
PIN: eh1_0_alpha::adc::nb::Channel<Adc, ID = u8>,
|
||||||
|
{
|
||||||
|
type Error = ();
|
||||||
|
|
||||||
|
fn read(&mut self, pin: &mut PIN) -> nb::Result<WORD, Self::Error> {
|
||||||
|
let chan = PIN::channel(pin);
|
||||||
|
|
||||||
|
if chan == 4 {
|
||||||
|
self.device.cs.modify(|_, w| w.ts_en().set_bit())
|
||||||
|
}
|
||||||
|
|
||||||
|
while !self.device.cs.read().ready().bit_is_set() {
|
||||||
|
cortex_m::asm::nop();
|
||||||
|
}
|
||||||
|
|
||||||
|
self.device
|
||||||
|
.cs
|
||||||
|
.modify(|_, w| unsafe { w.ainsel().bits(chan).start_once().set_bit() });
|
||||||
|
|
||||||
|
while !self.device.cs.read().ready().bit_is_set() {
|
||||||
|
cortex_m::asm::nop();
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(self.device.result.read().result().bits().into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -78,6 +78,8 @@ use super::pin::{Pin, PinId, PinMode, ValidPinMode};
|
||||||
use super::reg::RegisterInterface;
|
use super::reg::RegisterInterface;
|
||||||
use core::convert::TryFrom;
|
use core::convert::TryFrom;
|
||||||
|
|
||||||
|
#[cfg(feature = "eh1_0_alpha")]
|
||||||
|
use eh1_0_alpha::digital::blocking as eh1;
|
||||||
use hal::digital::v2::{InputPin, OutputPin, StatefulOutputPin, ToggleableOutputPin};
|
use hal::digital::v2::{InputPin, OutputPin, StatefulOutputPin, ToggleableOutputPin};
|
||||||
|
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
|
@ -541,3 +543,50 @@ impl StatefulOutputPin for DynPin {
|
||||||
self._is_set_low()
|
self._is_set_low()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "eh1_0_alpha")]
|
||||||
|
impl eh1::OutputPin for DynPin {
|
||||||
|
type Error = Error;
|
||||||
|
#[inline]
|
||||||
|
fn set_high(&mut self) -> Result<(), Self::Error> {
|
||||||
|
self._set_high()
|
||||||
|
}
|
||||||
|
#[inline]
|
||||||
|
fn set_low(&mut self) -> Result<(), Self::Error> {
|
||||||
|
self._set_low()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "eh1_0_alpha")]
|
||||||
|
impl eh1::InputPin for DynPin {
|
||||||
|
type Error = Error;
|
||||||
|
#[inline]
|
||||||
|
fn is_high(&self) -> Result<bool, Self::Error> {
|
||||||
|
self._is_high()
|
||||||
|
}
|
||||||
|
#[inline]
|
||||||
|
fn is_low(&self) -> Result<bool, Self::Error> {
|
||||||
|
self._is_low()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "eh1_0_alpha")]
|
||||||
|
impl eh1::ToggleableOutputPin for DynPin {
|
||||||
|
type Error = Error;
|
||||||
|
#[inline]
|
||||||
|
fn toggle(&mut self) -> Result<(), Self::Error> {
|
||||||
|
self._toggle()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "eh1_0_alpha")]
|
||||||
|
impl eh1::StatefulOutputPin for DynPin {
|
||||||
|
#[inline]
|
||||||
|
fn is_set_high(&self) -> Result<bool, Self::Error> {
|
||||||
|
self._is_set_high()
|
||||||
|
}
|
||||||
|
#[inline]
|
||||||
|
fn is_set_low(&self) -> Result<bool, Self::Error> {
|
||||||
|
self._is_set_low()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -103,6 +103,8 @@ use core::convert::Infallible;
|
||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
|
|
||||||
use crate::gpio::dynpin::DynFunction;
|
use crate::gpio::dynpin::DynFunction;
|
||||||
|
#[cfg(feature = "eh1_0_alpha")]
|
||||||
|
use eh1_0_alpha::digital::blocking as eh1;
|
||||||
use hal::digital::v2::{InputPin, OutputPin, StatefulOutputPin, ToggleableOutputPin};
|
use hal::digital::v2::{InputPin, OutputPin, StatefulOutputPin, ToggleableOutputPin};
|
||||||
|
|
||||||
use core::mem::transmute;
|
use core::mem::transmute;
|
||||||
|
@ -792,6 +794,88 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "eh1_0_alpha")]
|
||||||
|
impl<I, C> eh1::OutputPin for Pin<I, Output<C>>
|
||||||
|
where
|
||||||
|
I: PinId,
|
||||||
|
C: OutputConfig,
|
||||||
|
{
|
||||||
|
type Error = Infallible;
|
||||||
|
#[inline]
|
||||||
|
fn set_high(&mut self) -> Result<(), Self::Error> {
|
||||||
|
self._set_high();
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
#[inline]
|
||||||
|
fn set_low(&mut self) -> Result<(), Self::Error> {
|
||||||
|
self._set_low();
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "eh1_0_alpha")]
|
||||||
|
impl<I> eh1::InputPin for Pin<I, ReadableOutput>
|
||||||
|
where
|
||||||
|
I: PinId,
|
||||||
|
{
|
||||||
|
type Error = Infallible;
|
||||||
|
#[inline]
|
||||||
|
fn is_high(&self) -> Result<bool, Self::Error> {
|
||||||
|
Ok(self._is_high())
|
||||||
|
}
|
||||||
|
#[inline]
|
||||||
|
fn is_low(&self) -> Result<bool, Self::Error> {
|
||||||
|
Ok(self._is_low())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "eh1_0_alpha")]
|
||||||
|
impl<I, C> eh1::InputPin for Pin<I, Input<C>>
|
||||||
|
where
|
||||||
|
I: PinId,
|
||||||
|
C: InputConfig,
|
||||||
|
{
|
||||||
|
type Error = Infallible;
|
||||||
|
#[inline]
|
||||||
|
fn is_high(&self) -> Result<bool, Self::Error> {
|
||||||
|
Ok(self._is_high())
|
||||||
|
}
|
||||||
|
#[inline]
|
||||||
|
fn is_low(&self) -> Result<bool, Self::Error> {
|
||||||
|
Ok(self._is_low())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "eh1_0_alpha")]
|
||||||
|
impl<I, C> eh1::ToggleableOutputPin for Pin<I, Output<C>>
|
||||||
|
where
|
||||||
|
I: PinId,
|
||||||
|
C: OutputConfig,
|
||||||
|
{
|
||||||
|
type Error = Infallible;
|
||||||
|
#[inline]
|
||||||
|
fn toggle(&mut self) -> Result<(), Self::Error> {
|
||||||
|
self._toggle();
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "eh1_0_alpha")]
|
||||||
|
impl<I, C> eh1::StatefulOutputPin for Pin<I, Output<C>>
|
||||||
|
where
|
||||||
|
I: PinId,
|
||||||
|
C: OutputConfig,
|
||||||
|
{
|
||||||
|
#[inline]
|
||||||
|
fn is_set_high(&self) -> Result<bool, Self::Error> {
|
||||||
|
Ok(self._is_set_high())
|
||||||
|
}
|
||||||
|
#[inline]
|
||||||
|
fn is_set_low(&self) -> Result<bool, Self::Error> {
|
||||||
|
Ok(self._is_set_low())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
// Pin definitions
|
// Pin definitions
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
|
|
|
@ -52,6 +52,8 @@ use crate::{
|
||||||
resets::SubsystemReset,
|
resets::SubsystemReset,
|
||||||
typelevel::Sealed,
|
typelevel::Sealed,
|
||||||
};
|
};
|
||||||
|
#[cfg(feature = "eh1_0_alpha")]
|
||||||
|
use eh1_0_alpha::i2c::blocking as eh1;
|
||||||
use embedded_time::rate::Hertz;
|
use embedded_time::rate::Hertz;
|
||||||
use hal::blocking::i2c::{Read, Write, WriteRead};
|
use hal::blocking::i2c::{Read, Write, WriteRead};
|
||||||
use rp2040_pac::{I2C0, I2C1, RESETS};
|
use rp2040_pac::{I2C0, I2C1, RESETS};
|
||||||
|
@ -490,6 +492,30 @@ macro_rules! hal {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "eh1_0_alpha")]
|
||||||
|
impl<PINS> eh1::Write for I2C<$I2CX, PINS> {
|
||||||
|
type Error = Error;
|
||||||
|
|
||||||
|
fn write(&mut self, addr: u8, bytes: &[u8]) -> Result<(), Error> {
|
||||||
|
Write::write(self, addr, bytes)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[cfg(feature = "eh1_0_alpha")]
|
||||||
|
impl<PINS> eh1::WriteRead for I2C<$I2CX, PINS> {
|
||||||
|
type Error = Error;
|
||||||
|
fn write_read(&mut self, addr: u8, bytes: &[u8], buffer: &mut [u8]) -> Result<(), Error> {
|
||||||
|
WriteRead::write_read(self, addr, bytes, buffer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[cfg(feature = "eh1_0_alpha")]
|
||||||
|
impl<PINS> eh1::Read for I2C<$I2CX, PINS> {
|
||||||
|
type Error = Error;
|
||||||
|
|
||||||
|
fn read(&mut self, addr: u8, buffer: &mut [u8]) -> Result<(), Error> {
|
||||||
|
Read::read(self, addr, buffer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
)+
|
)+
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -87,6 +87,8 @@ use crate::{
|
||||||
resets::SubsystemReset,
|
resets::SubsystemReset,
|
||||||
typelevel::Sealed,
|
typelevel::Sealed,
|
||||||
};
|
};
|
||||||
|
#[cfg(feature = "eh1_0_alpha")]
|
||||||
|
use eh1_0_alpha::pwm::blocking as eh1;
|
||||||
use embedded_hal::PwmPin;
|
use embedded_hal::PwmPin;
|
||||||
use pac::PWM;
|
use pac::PWM;
|
||||||
|
|
||||||
|
@ -551,6 +553,38 @@ impl<S: SliceId, M: SliceMode> PwmPin for Channel<S, M, A> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "eh1_0_alpha")]
|
||||||
|
impl<S: SliceId, M: SliceMode> eh1::PwmPin for Channel<S, M, A> {
|
||||||
|
type Duty = u16;
|
||||||
|
type Error = core::convert::Infallible;
|
||||||
|
|
||||||
|
/// We cant disable the channel without disturbing the other channel.
|
||||||
|
/// So this just sets the duty cycle to zero
|
||||||
|
fn disable(&mut self) -> Result<(), Self::Error> {
|
||||||
|
self.duty_cycle = self.regs.read_cc_a();
|
||||||
|
self.regs.write_cc_a(0);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn enable(&mut self) -> Result<(), Self::Error> {
|
||||||
|
self.regs.write_cc_a(self.duty_cycle);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_duty(&self) -> Result<Self::Duty, Self::Error> {
|
||||||
|
Ok(self.regs.read_cc_a())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_max_duty(&self) -> Result<Self::Duty, Self::Error> {
|
||||||
|
Ok(self.regs.read_top())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_duty(&mut self, duty: Self::Duty) -> Result<(), Self::Error> {
|
||||||
|
self.regs.write_cc_a(duty);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<S: SliceId, M: SliceMode> PwmPin for Channel<S, M, B> {
|
impl<S: SliceId, M: SliceMode> PwmPin for Channel<S, M, B> {
|
||||||
type Duty = u16;
|
type Duty = u16;
|
||||||
|
|
||||||
|
@ -577,6 +611,37 @@ impl<S: SliceId, M: SliceMode> PwmPin for Channel<S, M, B> {
|
||||||
self.regs.write_cc_b(duty)
|
self.regs.write_cc_b(duty)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#[cfg(feature = "eh1_0_alpha")]
|
||||||
|
impl<S: SliceId, M: SliceMode> eh1::PwmPin for Channel<S, M, B> {
|
||||||
|
type Duty = u16;
|
||||||
|
type Error = core::convert::Infallible;
|
||||||
|
|
||||||
|
/// We cant disable the channel without disturbing the other channel.
|
||||||
|
/// So this just sets the duty cycle to zero
|
||||||
|
fn disable(&mut self) -> Result<(), Self::Error> {
|
||||||
|
self.duty_cycle = self.regs.read_cc_b();
|
||||||
|
self.regs.write_cc_b(0);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn enable(&mut self) -> Result<(), Self::Error> {
|
||||||
|
self.regs.write_cc_b(self.duty_cycle);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_duty(&self) -> Result<Self::Duty, Self::Error> {
|
||||||
|
Ok(self.regs.read_cc_b())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_max_duty(&self) -> Result<Self::Duty, Self::Error> {
|
||||||
|
Ok(self.regs.read_top())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_duty(&mut self, duty: Self::Duty) -> Result<(), Self::Error> {
|
||||||
|
self.regs.write_cc_b(duty);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<S: SliceId, M: SliceMode + ValidSliceMode<S>> Channel<S, M, A> {
|
impl<S: SliceId, M: SliceMode + ValidSliceMode<S>> Channel<S, M, A> {
|
||||||
/// Capture a gpio pin and use it as pwm output for channel A
|
/// Capture a gpio pin and use it as pwm output for channel A
|
||||||
|
|
|
@ -21,6 +21,8 @@
|
||||||
|
|
||||||
use crate::resets::SubsystemReset;
|
use crate::resets::SubsystemReset;
|
||||||
use core::{convert::Infallible, marker::PhantomData, ops::Deref};
|
use core::{convert::Infallible, marker::PhantomData, ops::Deref};
|
||||||
|
#[cfg(feature = "eh1_0_alpha")]
|
||||||
|
use eh1_0_alpha::spi as eh1;
|
||||||
use embedded_hal::blocking::spi;
|
use embedded_hal::blocking::spi;
|
||||||
use embedded_hal::spi::{FullDuplex, Mode, Phase, Polarity};
|
use embedded_hal::spi::{FullDuplex, Mode, Phase, Polarity};
|
||||||
use embedded_time::rate::*;
|
use embedded_time::rate::*;
|
||||||
|
@ -217,6 +219,32 @@ macro_rules! impl_write {
|
||||||
impl<D: SpiDevice> spi::transfer::Default<$type> for Spi<Enabled, D, $nr> {}
|
impl<D: SpiDevice> spi::transfer::Default<$type> for Spi<Enabled, D, $nr> {}
|
||||||
impl<D: SpiDevice> spi::write_iter::Default<$type> for Spi<Enabled, D, $nr> {}
|
impl<D: SpiDevice> spi::write_iter::Default<$type> for Spi<Enabled, D, $nr> {}
|
||||||
|
|
||||||
|
#[cfg(feature = "eh1_0_alpha")]
|
||||||
|
impl<D: SpiDevice> eh1::nb::FullDuplex<$type> for Spi<Enabled, D, $nr> {
|
||||||
|
type Error = Infallible;
|
||||||
|
|
||||||
|
fn read(&mut self) -> Result<$type, nb::Error<Infallible>> {
|
||||||
|
if !self.is_readable() {
|
||||||
|
return Err(nb::Error::WouldBlock);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(self.device.sspdr.read().data().bits() as $type)
|
||||||
|
}
|
||||||
|
fn write(&mut self, word: $type) -> Result<(), nb::Error<Infallible>> {
|
||||||
|
// Write to TX FIFO whilst ignoring RX, then clean up afterward. When RX
|
||||||
|
// is full, PL022 inhibits RX pushes, and sets a sticky flag on
|
||||||
|
// push-on-full, but continues shifting. Safe if SSPIMSC_RORIM is not set.
|
||||||
|
if !self.is_writable() {
|
||||||
|
return Err(nb::Error::WouldBlock);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.device
|
||||||
|
.sspdr
|
||||||
|
.write(|w| unsafe { w.data().bits(word as u16) });
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
)+
|
)+
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -77,7 +77,39 @@ impl embedded_hal::timer::CountDown for CountDown<'_> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "eh1_0_alpha")]
|
||||||
|
impl eh1_0_alpha::timer::nb::CountDown for CountDown<'_> {
|
||||||
|
type Time = embedded_time::duration::Microseconds<u64>;
|
||||||
|
type Error = &'static str;
|
||||||
|
|
||||||
|
fn start<T>(&mut self, count: T) -> Result<(), Self::Error>
|
||||||
|
where
|
||||||
|
T: Into<Self::Time>,
|
||||||
|
{
|
||||||
|
self.period = count.into();
|
||||||
|
self.next_end = Some(self.timer.get_counter().wrapping_add(self.period.0));
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn wait(&mut self) -> nb::Result<(), Self::Error> {
|
||||||
|
if let Some(end) = self.next_end {
|
||||||
|
let ts = self.timer.get_counter();
|
||||||
|
if ts >= end {
|
||||||
|
self.next_end = Some(end.wrapping_add(self.period.0));
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
Err(nb::Error::WouldBlock)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
panic!("CountDown is not running!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl embedded_hal::timer::Periodic for CountDown<'_> {}
|
impl embedded_hal::timer::Periodic for CountDown<'_> {}
|
||||||
|
#[cfg(feature = "eh1_0_alpha")]
|
||||||
|
impl eh1_0_alpha::timer::Periodic for CountDown<'_> {}
|
||||||
|
|
||||||
impl embedded_hal::timer::Cancel for CountDown<'_> {
|
impl embedded_hal::timer::Cancel for CountDown<'_> {
|
||||||
type Error = &'static str;
|
type Error = &'static str;
|
||||||
|
|
||||||
|
@ -90,3 +122,14 @@ impl embedded_hal::timer::Cancel for CountDown<'_> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#[cfg(feature = "eh1_0_alpha")]
|
||||||
|
impl eh1_0_alpha::timer::nb::Cancel for CountDown<'_> {
|
||||||
|
fn cancel(&mut self) -> Result<(), Self::Error> {
|
||||||
|
if self.next_end.is_none() {
|
||||||
|
Err("CountDown is not running.")
|
||||||
|
} else {
|
||||||
|
self.next_end = None;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -37,6 +37,8 @@ use embedded_time::fixed_point::FixedPoint;
|
||||||
use embedded_time::rate::Baud;
|
use embedded_time::rate::Baud;
|
||||||
use embedded_time::rate::Hertz;
|
use embedded_time::rate::Hertz;
|
||||||
|
|
||||||
|
#[cfg(feature = "eh1_0_alpha")]
|
||||||
|
use eh1_0_alpha::serial::nb as eh1;
|
||||||
use embedded_hal::serial::{Read, Write};
|
use embedded_hal::serial::{Read, Write};
|
||||||
|
|
||||||
use nb::Error::{Other, WouldBlock};
|
use nb::Error::{Other, WouldBlock};
|
||||||
|
@ -65,6 +67,7 @@ pub struct ReadError<'err> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Possible types of read errors. See Chapter 4, Section 2 §8 - Table 436: "UARTDR Register"
|
/// Possible types of read errors. See Chapter 4, Section 2 §8 - Table 436: "UARTDR Register"
|
||||||
|
#[cfg_attr(feature = "eh1_0_alpha", derive(Debug))]
|
||||||
pub enum ReadErrorType {
|
pub enum ReadErrorType {
|
||||||
/// Triggered when the FIFO (or shift-register) is overflowed.
|
/// Triggered when the FIFO (or shift-register) is overflowed.
|
||||||
Overrun,
|
Overrun,
|
||||||
|
@ -495,6 +498,23 @@ impl<D: UartDevice> Read<u8> for UartPeripheral<Enabled, D> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "eh1_0_alpha")]
|
||||||
|
impl<D: UartDevice> eh1::Read<u8> for UartPeripheral<Enabled, D> {
|
||||||
|
type Error = ReadErrorType;
|
||||||
|
|
||||||
|
fn read(&mut self) -> nb::Result<u8, Self::Error> {
|
||||||
|
let byte: &mut [u8] = &mut [0; 1];
|
||||||
|
|
||||||
|
match self.read_raw(byte) {
|
||||||
|
Ok(_) => Ok(byte[0]),
|
||||||
|
Err(e) => match e {
|
||||||
|
Other(inner) => Err(Other(inner.err_type)),
|
||||||
|
WouldBlock => Err(WouldBlock),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<D: UartDevice> Write<u8> for UartPeripheral<Enabled, D> {
|
impl<D: UartDevice> Write<u8> for UartPeripheral<Enabled, D> {
|
||||||
type Error = Infallible;
|
type Error = Infallible;
|
||||||
|
|
||||||
|
@ -511,6 +531,23 @@ impl<D: UartDevice> Write<u8> for UartPeripheral<Enabled, D> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "eh1_0_alpha")]
|
||||||
|
impl<D: UartDevice> eh1::Write<u8> for UartPeripheral<Enabled, D> {
|
||||||
|
type Error = Infallible;
|
||||||
|
|
||||||
|
fn write(&mut self, word: u8) -> nb::Result<(), Self::Error> {
|
||||||
|
if self.write_raw(&[word]).is_err() {
|
||||||
|
Err(WouldBlock)
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn flush(&mut self) -> nb::Result<(), Self::Error> {
|
||||||
|
self.transmit_flushed()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<D: UartDevice> fmt::Write for UartPeripheral<Enabled, D> {
|
impl<D: UartDevice> fmt::Write for UartPeripheral<Enabled, D> {
|
||||||
fn write_str(&mut self, s: &str) -> fmt::Result {
|
fn write_str(&mut self, s: &str) -> fmt::Result {
|
||||||
s.bytes()
|
s.bytes()
|
||||||
|
|
|
@ -35,6 +35,8 @@
|
||||||
//! See [examples/watchdog.rs](https://github.com/rp-rs/rp-hal/tree/main/rp2040-hal/examples/watchdog.rs) for a more complete example
|
//! See [examples/watchdog.rs](https://github.com/rp-rs/rp-hal/tree/main/rp2040-hal/examples/watchdog.rs) for a more complete example
|
||||||
|
|
||||||
use crate::pac::WATCHDOG;
|
use crate::pac::WATCHDOG;
|
||||||
|
#[cfg(feature = "eh1_0_alpha")]
|
||||||
|
use eh1_0_alpha::watchdog::blocking as eh1;
|
||||||
use embedded_hal::watchdog;
|
use embedded_hal::watchdog;
|
||||||
use embedded_time::{duration, fixed_point::FixedPoint};
|
use embedded_time::{duration, fixed_point::FixedPoint};
|
||||||
|
|
||||||
|
@ -97,6 +99,15 @@ impl watchdog::Watchdog for Watchdog {
|
||||||
self.load_counter(self.delay_ms)
|
self.load_counter(self.delay_ms)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#[cfg(feature = "eh1_0_alpha")]
|
||||||
|
impl eh1::Watchdog for Watchdog {
|
||||||
|
type Error = core::convert::Infallible;
|
||||||
|
|
||||||
|
fn feed(&mut self) -> Result<(), Self::Error> {
|
||||||
|
self.load_counter(self.delay_ms);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl watchdog::WatchdogEnable for Watchdog {
|
impl watchdog::WatchdogEnable for Watchdog {
|
||||||
type Time = duration::Microseconds;
|
type Time = duration::Microseconds;
|
||||||
|
@ -117,9 +128,41 @@ impl watchdog::WatchdogEnable for Watchdog {
|
||||||
self.enable(true);
|
self.enable(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#[cfg(feature = "eh1_0_alpha")]
|
||||||
|
impl eh1::Enable for Watchdog {
|
||||||
|
type Error = core::convert::Infallible;
|
||||||
|
type Target = Self;
|
||||||
|
type Time = duration::Microseconds;
|
||||||
|
|
||||||
|
fn start<T: Into<Self::Time>>(mut self, period: T) -> Result<Self::Target, Self::Error> {
|
||||||
|
const MAX_PERIOD: u32 = 0xFFFFFF;
|
||||||
|
|
||||||
|
// Due to a logic error, the watchdog decrements by 2 and
|
||||||
|
// the load value must be compensated; see RP2040-E1
|
||||||
|
self.delay_ms = period.into().integer() * 2;
|
||||||
|
|
||||||
|
if self.delay_ms > MAX_PERIOD {
|
||||||
|
panic!("Period cannot exceed maximum load value of {}", MAX_PERIOD);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.enable(false);
|
||||||
|
self.load_counter(self.delay_ms);
|
||||||
|
self.enable(true);
|
||||||
|
Ok(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl watchdog::WatchdogDisable for Watchdog {
|
impl watchdog::WatchdogDisable for Watchdog {
|
||||||
fn disable(&mut self) {
|
fn disable(&mut self) {
|
||||||
self.enable(false)
|
self.enable(false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#[cfg(feature = "eh1_0_alpha")]
|
||||||
|
impl eh1::Disable for Watchdog {
|
||||||
|
type Error = core::convert::Infallible;
|
||||||
|
type Target = Self;
|
||||||
|
fn disable(self) -> Result<Self::Target, Self::Error> {
|
||||||
|
self.enable(false);
|
||||||
|
Ok(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue