Skip to content

Commit

Permalink
Optionally type-erased GPIO drivers (#2075)
Browse files Browse the repository at this point in the history
* Remove type erased gpio structs

* Implement Peripheral for ErasedPin

* Simpler type erasing, accept ErasedPin in pin drivers, remove type erased drivers

* Reformulate pin drivers using Flex

* Erase gpio types by default

* Accept any pin in AnyPin

* Add changelog and migration guide

* Fix tests and examples

* Undo rename of clone_unchecked
  • Loading branch information
bugadani authored Sep 5, 2024
1 parent a5ab739 commit f11c18a
Show file tree
Hide file tree
Showing 21 changed files with 441 additions and 867 deletions.
4 changes: 4 additions & 0 deletions esp-hal/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

- Implement `embedded-hal` output pin traits for `DummyPin` (#2019)
- 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)
- `Flex` now implements `Wait`. (#2075)
- Added sleep and wakeup support for esp32c2 (#1922)

### Changed
- Make saving and restoring SHA digest state an explicit operation (#2049)

- `Delay::new()` is now a `const` function (#1999)
- You can now create an `AnyPin` out of an `ErasedPin`. (#2072)
- `Input`, `Output`, `OutputOpenDrain` and `Flex` are now type-erased by default. Use the new `new_typed` constructor to keep using the ZST pin types. (#2075)

### Fixed
- SHA driver can now be safely used in multiple contexts concurrently (#2049)
Expand Down
10 changes: 10 additions & 0 deletions esp-hal/MIGRATING-0.20.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,13 @@ Instead of manually grabbing peripherals and setting up clocks, you should now c
- The `GpioN` type aliasses are no longer available. You can use `GpioPin<N>` instead.
- The `AnyInputOnlyPin` has been removed. Replace any use with `AnyPin`.
- The `NoPinType` has been removed. You can use `DummyPin` in its place.

### Type-erased GPIO drivers

You no longer have to spell out the GPIO pin type for `Input`, `Output`, `OutputOpenDrain` or `Flex`.
However, if you want to, you can keep using their typed form!

```rust
let pin = Input::new(io.gpio0); // pin will have the type `Input<'some>` (or `Input<'some, ErasedPin>` if you want to be explicit about it)
let pin = Input::new_typed(io.gpio0); // pin will have the type `Input<'some, GpioPin<0>>`
```
17 changes: 11 additions & 6 deletions esp-hal/src/gpio/any_pin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,12 @@ pub struct AnyPin<'d> {
impl<'d> AnyPin<'d> {
/// Create wrapper for the given pin.
#[inline]
pub fn new<P: CreateErasedPin>(pin: impl crate::peripheral::Peripheral<P = P> + 'd) -> Self {
pub fn new<P>(pin: impl crate::peripheral::Peripheral<P = P> + 'd) -> Self
where
P: Pin,
{
crate::into_ref!(pin);
let pin = pin.erased_pin(private::Internal);
let pin = pin.degrade_internal(private::Internal);

Self {
pin,
Expand All @@ -27,11 +30,12 @@ impl<'d> AnyPin<'d> {
/// Create wrapper for the given pin. The peripheral signal will be
/// inverted.
#[inline]
pub fn new_inverted<P: OutputPin + InputPin + CreateErasedPin>(
pin: impl crate::peripheral::Peripheral<P = P> + 'd,
) -> Self {
pub fn new_inverted<P>(pin: impl crate::peripheral::Peripheral<P = P> + 'd) -> Self
where
P: Pin,
{
crate::into_ref!(pin);
let pin = pin.erased_pin(private::Internal);
let pin = pin.degrade_internal(private::Internal);

Self {
pin,
Expand Down Expand Up @@ -59,6 +63,7 @@ impl<'d> Pin for AnyPin<'d> {
delegate::delegate! {
to self.pin {
fn number(&self, _internal: private::Internal) -> u8;
fn degrade_internal(&self, _internal: private::Internal) -> ErasedPin;
fn sleep_mode(&mut self, on: bool, _internal: private::Internal);
fn set_alternate_function(&mut self, alternate: AlternateFunction, _internal: private::Internal);
fn is_listening(&self, _internal: private::Internal) -> bool;
Expand Down
4 changes: 4 additions & 0 deletions esp-hal/src/gpio/dummy_pin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ impl Pin for DummyPin {
panic!("DummyPin not supported here!");
}

fn degrade_internal(&self, _: private::Internal) -> ErasedPin {
panic!("Can not type erase the DummyPin!");
}

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

fn set_alternate_function(&mut self, _alternate: AlternateFunction, _: private::Internal) {}
Expand Down
Loading

0 comments on commit f11c18a

Please sign in to comment.