Skip to content

Commit

Permalink
SPI pins are no longer optional, rename DummyPin
Browse files Browse the repository at this point in the history
  • Loading branch information
bugadani committed Sep 11, 2024
1 parent 7a733a7 commit 3360bff
Show file tree
Hide file tree
Showing 18 changed files with 129 additions and 323 deletions.
4 changes: 4 additions & 0 deletions esp-hal/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

- Introduce traits for the DMA buffer objects (#1976)
- Implement `embedded-hal` output pin traits for `DummyPin` (#2019)
- Implement `embedded-hal` output pin traits for `NoPin` (#2019, #2133)
- Added `esp_hal::init` to simplify HAL initialisation (#1970, #1999)
- Added GpioPin::degrade to create ErasePins easily. Same for AnyPin by accident. (#2075)
- Added missing functions to `Flex`: `unlisten`, `is_interrupt_set`, `wakeup_enable`, `wait_for_high`, `wait_for_low`, `wait_for_rising_edge`, `wait_for_falling_edge`, `wait_for_any_edge`. (#2075)
Expand All @@ -39,6 +40,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Renamed and merged `Rtc::get_time_us` and `Rtc::get_time_ms` into `Rtc::time_since_boot` (#1883)
- ESP32: Added support for touch sensing on GPIO32 and 33 (#2109)
- Replaced `AnyPin` with `InputSignal` and `OutputSignal` and renamed `ErasedPin` to `AnyPin` (#2128)
- Changed the parameters of `Spi::with_pins` to no longer be optional (#2133)
- Renamed `DummyPin` to `NoPin` and removed all internal logic from it. (#2133)
- The `NO_PIN` constant has been removed. (#2133)

### Fixed

Expand Down
13 changes: 13 additions & 0 deletions esp-hal/MIGRATING-0.20.md
Original file line number Diff line number Diff line change
Expand Up @@ -124,3 +124,16 @@ let rtc = Rtc::new(peripherals.LPWR);
- let current_time_ms = rtc.get_time_ms();
+ let current_time_ms = rtc.current_time().and_utc().timestamp_millis(); // assuming UTC
```

## SPI pins and `NO_PIN`

Use `NoPin` in place of the now-removed `NO_PIN` constant.

SPI pins, when using the `with_pin` function, are no longer optional.
You can pass `NoPin` or `Level` as inputs, and `NoPin` as output if you don't need a particular pin.

```diff
let spi = Spi::new(peripherals.SPI2, 100.kHz(), SpiMode::Mode0)
- .with_pins(Some(sclk), Some(mosi), NO_PIN, NO_PIN);
+ .with_pins(sclk, mosi, Level::Low, NoPin);
```
2 changes: 1 addition & 1 deletion esp-hal/src/dma/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
//! 100.kHz(),
//! SpiMode::Mode0,
//! )
//! .with_pins(Some(sclk), Some(mosi), Some(miso), Some(cs))
//! .with_pins(sclk, mosi, miso, cs)
//! .with_dma(dma_channel.configure(
//! false,
//! DmaPriority::Priority0,
Expand Down
8 changes: 4 additions & 4 deletions esp-hal/src/gpio/interconnect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ use crate::{
self,
AlternateFunction,
AnyPin,
DummyPin,
GpioPin,
GpioProperties,
InputPin,
Level,
NoPin,
OutputSignalType,
PeripheralInput,
PeripheralOutput,
Expand Down Expand Up @@ -331,7 +331,7 @@ impl PeripheralOutput for OutputSignal {
enum AnyInputSignalInner {
Input(InputSignal),
Constant(Level),
Dummy(DummyPin),
Dummy(NoPin),
}

/// A type-erased input signal.
Expand All @@ -358,8 +358,8 @@ impl From<Level> for AnyInputSignal {
}
}

impl From<DummyPin> for AnyInputSignal {
fn from(pin: DummyPin) -> Self {
impl From<NoPin> for AnyInputSignal {
fn from(pin: NoPin) -> Self {
Self(AnyInputSignalInner::Dummy(pin))
}
}
Expand Down
9 changes: 4 additions & 5 deletions esp-hal/src/gpio/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@
//! - [Output] and [OutputOpenDrain] pins can be used as digital outputs.
//! - [Flex] pin is a pin that can be used as an input and output pin.
//! - [AnyPin] is a type-erased GPIO pin with support for inverted signalling.
//! - [DummyPin] is a useful for cases where peripheral driver requires a pin,
//! but real pin cannot be used.
//! - [NoPin] is a useful for cases where peripheral driver requires a pin, but
//! real pin cannot be used.
//!
//! ### GPIO interconnect
//!
Expand Down Expand Up @@ -77,10 +77,10 @@ use crate::{
InterruptConfigurable,
};

mod dummy_pin;
pub mod interconnect;
mod placeholder;

pub use dummy_pin::DummyPin;
pub use placeholder::NoPin;

#[cfg(soc_etm)]
pub mod etm;
Expand All @@ -90,7 +90,6 @@ pub mod lp_io;
pub mod rtc_io;

/// Convenience constant for `Option::None` pin
pub const NO_PIN: Option<DummyPin> = None;
static USER_INTERRUPT_HANDLER: CFnPtr = CFnPtr::NULL;

Expand Down
114 changes: 46 additions & 68 deletions esp-hal/src/gpio/dummy_pin.rs → esp-hal/src/gpio/placeholder.rs
Original file line number Diff line number Diff line change
@@ -1,34 +1,47 @@
//! Placeholder pins.
//! Placeholder pins/signals.
//!
//! These are useful to pass them into peripheral drivers where you don't want
//! an actual pin but one is required.
use super::*;

/// DummyPin, not useful everywhere as it panics if number() is called
#[derive(Default, Clone)]
pub struct DummyPin {
value: bool,
}
/// Placeholder pin, used when no pin is required when using a peripheral.
#[derive(Default, Clone, Copy)]
pub struct NoPin;

impl crate::peripheral::Peripheral for NoPin {
type P = Self;

impl DummyPin {
/// Create a dummy pin.
pub fn new() -> Self {
Self { value: false }
unsafe fn clone_unchecked(&mut self) -> Self::P {
Self
}
}

impl crate::peripheral::Peripheral for DummyPin {
type P = Self;
impl private::Sealed for NoPin {}

unsafe fn clone_unchecked(&mut self) -> Self::P {
Self { value: self.value }
impl PeripheralSignal for NoPin {
fn pull_direction(&self, _pull: Pull, _internal: private::Internal) {}
}

impl PeripheralInput for NoPin {
delegate::delegate! {
to Level::Low {
fn init_input(&self, _pull: Pull, _internal: private::Internal);
fn enable_input(&mut self, _on: bool, _internal: private::Internal);
fn enable_input_in_sleep_mode(&mut self, _on: bool, _internal: private::Internal);
fn is_input_high(&self, _internal: private::Internal) -> bool;
fn connect_input_to_peripheral(&mut self, _signal: InputSignal, _internal: private::Internal);
fn disconnect_input_from_peripheral(&mut self, _signal: InputSignal, _internal: private::Internal);
fn input_signals(&self, _internal: private::Internal) -> [Option<InputSignal>; 6];
}
}
}

impl private::Sealed for DummyPin {}
impl PeripheralSignal for Level {
fn pull_direction(&self, _pull: Pull, _internal: private::Internal) {}
}

impl PeripheralInput for DummyPin {
impl PeripheralInput for Level {
fn input_signals(&self, _: private::Internal) -> [Option<InputSignal>; 6] {
[None; 6]
}
Expand All @@ -40,11 +53,14 @@ impl PeripheralInput for DummyPin {
fn enable_input_in_sleep_mode(&mut self, _on: bool, _: private::Internal) {}

fn is_input_high(&self, _: private::Internal) -> bool {
self.value
*self == Level::High
}

fn connect_input_to_peripheral(&mut self, signal: InputSignal, _: private::Internal) {
let value = if self.value { ONE_INPUT } else { ZERO_INPUT };
let value = match self {
Level::High => ONE_INPUT,
Level::Low => ZERO_INPUT,
};

unsafe { &*GPIO::PTR }
.func_in_sel_cfg(signal as usize - FUNC_IN_SEL_OFFSET)
Expand All @@ -61,48 +77,14 @@ impl PeripheralInput for DummyPin {
fn disconnect_input_from_peripheral(&mut self, _signal: InputSignal, _: private::Internal) {}
}

impl PeripheralSignal for Level {
delegate::delegate! {
to match self {
Level::High => DummyPin { value: true },
Level::Low => DummyPin { value: false },
} {
fn pull_direction(&self, pull: Pull, _internal: private::Internal);
}
}
}

impl PeripheralInput for Level {
delegate::delegate! {
to match self {
Level::High => DummyPin { value: true },
Level::Low => DummyPin { value: false },
} {
fn init_input(&self, _pull: Pull, _internal: private::Internal);
fn enable_input(&mut self, _on: bool, _internal: private::Internal);
fn enable_input_in_sleep_mode(&mut self, _on: bool, _internal: private::Internal);
fn is_input_high(&self, _internal: private::Internal) -> bool;
fn connect_input_to_peripheral(&mut self, _signal: InputSignal, _internal: private::Internal);
fn disconnect_input_from_peripheral(&mut self, _signal: InputSignal, _internal: private::Internal);
fn input_signals(&self, _internal: private::Internal) -> [Option<InputSignal>; 6];
}
}
}

impl PeripheralSignal for DummyPin {
fn pull_direction(&self, _pull: Pull, _internal: private::Internal) {}
}

impl PeripheralOutput for DummyPin {
impl PeripheralOutput for NoPin {
fn set_to_open_drain_output(&mut self, _: private::Internal) {}

fn set_to_push_pull_output(&mut self, _: private::Internal) {}

fn enable_output(&mut self, _on: bool, _: private::Internal) {}

fn set_output_high(&mut self, on: bool, _: private::Internal) {
self.value = on;
}
fn set_output_high(&mut self, _on: bool, _: private::Internal) {}

fn set_drive_strength(&mut self, _strength: DriveStrength, _: private::Internal) {}

Expand All @@ -115,7 +97,7 @@ impl PeripheralOutput for DummyPin {
fn internal_pull_down_in_sleep_mode(&mut self, _on: bool, _: private::Internal) {}

fn is_set_high(&self, _: private::Internal) -> bool {
self.value
false
}

fn output_signals(&self, _: private::Internal) -> [Option<OutputSignal>; 6] {
Expand All @@ -127,49 +109,45 @@ impl PeripheralOutput for DummyPin {
fn disconnect_from_peripheral_output(&mut self, _signal: OutputSignal, _: private::Internal) {}
}

impl embedded_hal_02::digital::v2::OutputPin for DummyPin {
impl embedded_hal_02::digital::v2::OutputPin for NoPin {
type Error = core::convert::Infallible;

fn set_high(&mut self) -> Result<(), Self::Error> {
self.set_output_high(true, private::Internal);
Ok(())
}
fn set_low(&mut self) -> Result<(), Self::Error> {
self.set_output_high(false, private::Internal);
Ok(())
}
}
impl embedded_hal_02::digital::v2::StatefulOutputPin for DummyPin {
impl embedded_hal_02::digital::v2::StatefulOutputPin for NoPin {
fn is_set_high(&self) -> Result<bool, Self::Error> {
Ok(PeripheralOutput::is_set_high(self, private::Internal))
Ok(false)
}
fn is_set_low(&self) -> Result<bool, Self::Error> {
Ok(!PeripheralOutput::is_set_high(self, private::Internal))
Ok(false)
}
}

impl embedded_hal::digital::ErrorType for DummyPin {
impl embedded_hal::digital::ErrorType for NoPin {
type Error = core::convert::Infallible;
}

impl embedded_hal::digital::OutputPin for DummyPin {
impl embedded_hal::digital::OutputPin for NoPin {
fn set_low(&mut self) -> Result<(), Self::Error> {
self.set_output_high(true, private::Internal);
Ok(())
}

fn set_high(&mut self) -> Result<(), Self::Error> {
self.set_output_high(false, private::Internal);
Ok(())
}
}

impl embedded_hal::digital::StatefulOutputPin for DummyPin {
impl embedded_hal::digital::StatefulOutputPin for NoPin {
fn is_set_high(&mut self) -> Result<bool, Self::Error> {
Ok(PeripheralOutput::is_set_high(self, private::Internal))
Ok(false)
}

fn is_set_low(&mut self) -> Result<bool, Self::Error> {
Ok(!PeripheralOutput::is_set_high(self, private::Internal))
Ok(false)
}
}
Loading

0 comments on commit 3360bff

Please sign in to comment.