Optionally type-erased GPIO drivers (#2075)

* 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
This commit is contained in:
Dániel Buga 2024-09-05 16:14:51 +02:00 committed by GitHub
parent a5ab73959e
commit f11c18a6b9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
21 changed files with 554 additions and 980 deletions

View File

@ -11,6 +11,9 @@ 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
@ -18,6 +21,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- `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)

View File

@ -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>>`
```

View File

@ -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,
@ -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,
@ -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;

View File

@ -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) {}

File diff suppressed because it is too large Load Diff

View File

@ -14,7 +14,7 @@
use esp_backtrace as _;
use esp_hal::{
delay::Delay,
gpio::{AnyInput, AnyOutput, Io, Level, Pull},
gpio::{ErasedPin, Input, Io, Level, Output, Pin, Pull},
prelude::*,
};
@ -25,17 +25,17 @@ fn main() -> ! {
let io = Io::new(peripherals.GPIO, peripherals.IO_MUX);
// Set LED GPIOs as an output:
let led1 = AnyOutput::new(io.pins.gpio2, Level::Low);
let led2 = AnyOutput::new(io.pins.gpio4, Level::Low);
let led3 = AnyOutput::new(io.pins.gpio5, Level::Low);
let led1 = Output::new(io.pins.gpio2.degrade(), Level::Low);
let led2 = Output::new(io.pins.gpio4.degrade(), Level::Low);
let led3 = Output::new(io.pins.gpio5.degrade(), Level::Low);
// Use boot button as an input:
#[cfg(any(feature = "esp32", feature = "esp32s2", feature = "esp32s3"))]
let button = io.pins.gpio0;
let button = io.pins.gpio0.degrade();
#[cfg(not(any(feature = "esp32", feature = "esp32s2", feature = "esp32s3")))]
let button = io.pins.gpio9;
let button = io.pins.gpio9.degrade();
let button = AnyInput::new(button, Pull::Up);
let button = Input::new(button, Pull::Up);
let mut pins = [led1, led2, led3];
@ -47,7 +47,7 @@ fn main() -> ! {
}
}
fn toggle_pins(leds: &mut [AnyOutput], button: &AnyInput) {
fn toggle_pins(leds: &mut [Output<ErasedPin>], button: &Input<ErasedPin>) {
for pin in leds.iter_mut() {
pin.toggle();
}

View File

@ -21,7 +21,7 @@ use esp_backtrace as _;
use esp_hal::{
cpu_control::{CpuControl, Stack},
get_core,
gpio::{AnyOutput, Io, Level},
gpio::{ErasedPin, Io, Level, Output, Pin},
timer::{timg::TimerGroup, ErasedTimer},
};
use esp_hal_embassy::Executor;
@ -34,7 +34,7 @@ static mut APP_CORE_STACK: Stack<8192> = Stack::new();
/// duration of time.
#[embassy_executor::task]
async fn control_led(
mut led: AnyOutput<'static>,
mut led: Output<'static, ErasedPin>,
control: &'static Signal<CriticalSectionRawMutex, bool>,
) {
println!("Starting control_led() on core {}", get_core() as usize);
@ -65,7 +65,7 @@ async fn main(_spawner: Spawner) {
static LED_CTRL: StaticCell<Signal<CriticalSectionRawMutex, bool>> = StaticCell::new();
let led_ctrl_signal = &*LED_CTRL.init(Signal::new());
let led = AnyOutput::new(io.pins.gpio0, Level::Low);
let led = Output::new(io.pins.gpio0.degrade(), Level::Low);
let _guard = cpu_control
.start_app_core(unsafe { &mut *addr_of_mut!(APP_CORE_STACK) }, move || {

View File

@ -20,7 +20,7 @@ use esp_backtrace as _;
use esp_hal::{
cpu_control::{CpuControl, Stack},
get_core,
gpio::{AnyOutput, Io, Level},
gpio::{ErasedPin, Io, Level, Output, Pin},
interrupt::{software::SoftwareInterruptControl, Priority},
prelude::*,
timer::{timg::TimerGroup, ErasedTimer},
@ -35,7 +35,7 @@ static mut APP_CORE_STACK: Stack<8192> = Stack::new();
/// duration of time.
#[embassy_executor::task]
async fn control_led(
mut led: AnyOutput<'static>,
mut led: Output<'static, ErasedPin>,
control: &'static Signal<CriticalSectionRawMutex, bool>,
) {
println!("Starting control_led() on core {}", get_core() as usize);
@ -87,7 +87,7 @@ fn main() -> ! {
static LED_CTRL: StaticCell<Signal<CriticalSectionRawMutex, bool>> = StaticCell::new();
let led_ctrl_signal = &*LED_CTRL.init(Signal::new());
let led = AnyOutput::new(io.pins.gpio0, Level::Low);
let led = Output::new(io.pins.gpio0.degrade(), Level::Low);
static EXECUTOR_CORE_1: StaticCell<InterruptExecutor<1>> = StaticCell::new();
let executor_core1 = InterruptExecutor::new(sw_ints.software_interrupt1);

View File

@ -13,7 +13,7 @@ use embassy_executor::Spawner;
use embassy_time::{Duration, Timer};
use esp_backtrace as _;
use esp_hal::{
gpio::{GpioPin, Io, Level, Output},
gpio::{Io, Level, Output},
prelude::*,
rmt::{asynch::RxChannelAsync, PulseCode, Rmt, RxChannelConfig, RxChannelCreatorAsync},
timer::timg::TimerGroup,
@ -26,7 +26,7 @@ const WIDTH: usize = 80;
compile_error!("Run this example in release mode");
#[embassy_executor::task]
async fn signal_task(mut pin: Output<'static, GpioPin<5>>) {
async fn signal_task(mut pin: Output<'static>) {
loop {
for _ in 0..10 {
pin.toggle();

View File

@ -17,20 +17,12 @@ use critical_section::Mutex;
use esp_backtrace as _;
use esp_hal::{
delay::Delay,
gpio::{Event, GpioPin, Input, Io, Level, Output, Pull},
gpio::{Event, Input, Io, Level, Output, Pull},
macros::ram,
prelude::*,
};
cfg_if::cfg_if! {
if #[cfg(any(feature = "esp32", feature = "esp32s2", feature = "esp32s3"))] {
const BUTTON_PIN: u8 = 0;
} else {
const BUTTON_PIN: u8 = 9;
}
}
static BUTTON: Mutex<RefCell<Option<Input<GpioPin<BUTTON_PIN>>>>> = Mutex::new(RefCell::new(None));
static BUTTON: Mutex<RefCell<Option<Input>>> = Mutex::new(RefCell::new(None));
#[entry]
fn main() -> ! {

View File

@ -34,7 +34,7 @@ use esp_hal::{
delay::Delay,
dma::{Dma, DmaPriority},
dma_buffers,
gpio::{GpioPin, Input, Io, Level, Output, Pull},
gpio::{Input, Io, Level, Output, Pull},
prelude::*,
spi::{
slave::{prelude::*, Spi},
@ -48,17 +48,16 @@ fn main() -> ! {
let peripherals = esp_hal::init(esp_hal::Config::default());
let io = Io::new(peripherals.GPIO, peripherals.IO_MUX);
let slave_sclk = io.pins.gpio0;
let mut master_sclk = Output::new(io.pins.gpio4, Level::Low);
let slave_miso = io.pins.gpio1;
let master_miso = Input::new(io.pins.gpio5, Pull::None);
let slave_mosi = io.pins.gpio2;
let mut master_mosi = Output::new(io.pins.gpio8, Level::Low);
let mut master_cs = Output::new(io.pins.gpio9, Level::High);
let slave_sclk = io.pins.gpio0;
let slave_miso = io.pins.gpio1;
let slave_mosi = io.pins.gpio2;
let slave_cs = io.pins.gpio3;
let mut master_cs = Output::new(io.pins.gpio9, Level::Low);
master_cs.set_high();
master_sclk.set_low();
master_mosi.set_low();
let dma = Dma::new(peripherals.DMA);
cfg_if::cfg_if! {
@ -189,10 +188,10 @@ fn main() -> ! {
fn bitbang_master(
master_send: &[u8],
master_receive: &mut [u8],
master_cs: &mut Output<GpioPin<9>>,
master_mosi: &mut Output<GpioPin<8>>,
master_sclk: &mut Output<GpioPin<4>>,
master_miso: &Input<GpioPin<5>>,
master_cs: &mut Output,
master_mosi: &mut Output,
master_sclk: &mut Output,
master_miso: &Input,
) {
// Bit-bang out the contents of master_send and read into master_receive
// as quickly as manageable. MSB first. Mode 0, so sampled on the rising

View File

@ -49,8 +49,7 @@ macro_rules! common_test_pins {
cfg_if::cfg_if! {
if #[cfg(any(esp32s2, esp32s3))] {
($io.pins.gpio9, $io.pins.gpio10)
}
else {
} else {
($io.pins.gpio2, $io.pins.gpio3)
}
}

View File

@ -14,7 +14,6 @@ use esp_hal::{
dma::{Dma, DmaPriority},
dma_buffers,
peripherals::Peripherals,
prelude::*,
};
use hil_test as _;

View File

@ -20,7 +20,7 @@ mod tests {
#[init]
fn init() -> Context {
let peripherals = esp_hal::init(esp_hal::Config::default());
let _peripherals = esp_hal::init(esp_hal::Config::default());
let delay = Delay::new();
Context { delay }

View File

@ -61,7 +61,7 @@ mod tests {
#[test]
#[timeout(3)]
fn test_current_time_construct_timg0(ctx: Context) {
time_moves_forward_during(ctx, |ctx| {
time_moves_forward_during(ctx, |_| {
// construct the timer in between calls to current_time
let _ = esp_hal::timer::timg::TimerGroup::new(unsafe {
esp_hal::peripherals::TIMG0::steal()

View File

@ -15,7 +15,7 @@ use core::cell::RefCell;
use critical_section::Mutex;
use esp_hal::{
delay::Delay,
gpio::{AnyPin, GpioPin, Input, Io, Level, Output, Pull},
gpio::{AnyPin, ErasedPin, Input, Io, Level, Output, Pin, Pull},
macros::handler,
timer::timg::TimerGroup,
InterruptConfigurable,
@ -23,22 +23,11 @@ use esp_hal::{
use hil_test as _;
static COUNTER: Mutex<RefCell<u32>> = Mutex::new(RefCell::new(0));
static INPUT_PIN: Mutex<RefCell<Option<Input<'static, TestGpio1>>>> =
Mutex::new(RefCell::new(None));
static INPUT_PIN: Mutex<RefCell<Option<Input>>> = Mutex::new(RefCell::new(None));
cfg_if::cfg_if! {
if #[cfg(not(any(esp32s2, esp32s3)))] {
pub type TestGpio1 = GpioPin<2>;
pub type TestGpio2 = GpioPin<3>;
} else if #[cfg(any(esp32s2, esp32s3))] {
pub type TestGpio1 = GpioPin<9>;
pub type TestGpio2 = GpioPin<10>;
}
}
struct Context<'d> {
test_gpio1: Input<'d, TestGpio1>,
test_gpio2: Output<'d, TestGpio2>,
struct Context {
test_gpio1: ErasedPin,
test_gpio2: ErasedPin,
delay: Delay,
}
@ -64,7 +53,7 @@ mod tests {
use super::*;
#[init]
fn init() -> Context<'static> {
fn init() -> Context {
let peripherals = esp_hal::init(esp_hal::Config::default());
let mut io = Io::new(peripherals.GPIO, peripherals.IO_MUX);
@ -78,20 +67,22 @@ mod tests {
esp_hal_embassy::init(timg0.timer0);
Context {
test_gpio1: Input::new(gpio1, Pull::Down),
test_gpio2: Output::new(gpio2, Level::Low),
test_gpio1: gpio1.degrade(),
test_gpio2: gpio2.degrade(),
delay,
}
}
#[test]
async fn test_async_edge(ctx: Context<'static>) {
async fn test_async_edge(ctx: Context) {
let counter = AtomicUsize::new(0);
let Context {
mut test_gpio1,
mut test_gpio2,
test_gpio1,
test_gpio2,
..
} = ctx;
let mut test_gpio1 = Input::new(test_gpio1, Pull::Down);
let mut test_gpio2 = Output::new(test_gpio2, Level::Low);
embassy_futures::select::select(
async {
loop {
@ -113,8 +104,8 @@ mod tests {
}
#[test]
async fn test_a_pin_can_wait(_ctx: Context<'static>) {
let mut first = Input::new(unsafe { GpioPin::<0>::steal() }, Pull::Down);
async fn test_a_pin_can_wait(ctx: Context) {
let mut first = Input::new(ctx.test_gpio1, Pull::Down);
embassy_futures::select::select(
first.wait_for_rising_edge(),
@ -126,69 +117,74 @@ mod tests {
}
#[test]
fn test_gpio_input(ctx: Context<'static>) {
fn test_gpio_input(ctx: Context) {
let test_gpio1 = Input::new(ctx.test_gpio1, Pull::Down);
// `InputPin`:
assert_eq!(ctx.test_gpio1.is_low(), true);
assert_eq!(ctx.test_gpio1.is_high(), false);
assert_eq!(test_gpio1.is_low(), true);
assert_eq!(test_gpio1.is_high(), false);
}
#[test]
fn test_gpio_output(mut ctx: Context<'static>) {
fn test_gpio_output(ctx: Context) {
let mut test_gpio2 = Output::new(ctx.test_gpio2, Level::Low);
// `StatefulOutputPin`:
assert_eq!(ctx.test_gpio2.is_set_low(), true);
assert_eq!(ctx.test_gpio2.is_set_high(), false);
ctx.test_gpio2.set_high();
assert_eq!(ctx.test_gpio2.is_set_low(), false);
assert_eq!(ctx.test_gpio2.is_set_high(), true);
assert_eq!(test_gpio2.is_set_low(), true);
assert_eq!(test_gpio2.is_set_high(), false);
test_gpio2.set_high();
assert_eq!(test_gpio2.is_set_low(), false);
assert_eq!(test_gpio2.is_set_high(), true);
// `ToggleableOutputPin`:
ctx.test_gpio2.toggle();
assert_eq!(ctx.test_gpio2.is_set_low(), true);
assert_eq!(ctx.test_gpio2.is_set_high(), false);
ctx.test_gpio2.toggle();
assert_eq!(ctx.test_gpio2.is_set_low(), false);
assert_eq!(ctx.test_gpio2.is_set_high(), true);
test_gpio2.toggle();
assert_eq!(test_gpio2.is_set_low(), true);
assert_eq!(test_gpio2.is_set_high(), false);
test_gpio2.toggle();
assert_eq!(test_gpio2.is_set_low(), false);
assert_eq!(test_gpio2.is_set_high(), true);
}
#[test]
fn test_gpio_interrupt(mut ctx: Context<'static>) {
fn test_gpio_interrupt(ctx: Context) {
let mut test_gpio1 = Input::new(ctx.test_gpio1, Pull::Down);
let mut test_gpio2 = Output::new(ctx.test_gpio2, Level::Low);
critical_section::with(|cs| {
*COUNTER.borrow_ref_mut(cs) = 0;
ctx.test_gpio1.listen(Event::AnyEdge);
INPUT_PIN.borrow_ref_mut(cs).replace(ctx.test_gpio1);
test_gpio1.listen(Event::AnyEdge);
INPUT_PIN.borrow_ref_mut(cs).replace(test_gpio1);
});
ctx.test_gpio2.set_high();
test_gpio2.set_high();
ctx.delay.delay_millis(1);
ctx.test_gpio2.set_low();
test_gpio2.set_low();
ctx.delay.delay_millis(1);
ctx.test_gpio2.set_high();
test_gpio2.set_high();
ctx.delay.delay_millis(1);
ctx.test_gpio2.set_low();
test_gpio2.set_low();
ctx.delay.delay_millis(1);
ctx.test_gpio2.set_high();
test_gpio2.set_high();
ctx.delay.delay_millis(1);
ctx.test_gpio2.set_low();
test_gpio2.set_low();
ctx.delay.delay_millis(1);
ctx.test_gpio2.set_high();
test_gpio2.set_high();
ctx.delay.delay_millis(1);
ctx.test_gpio2.set_low();
test_gpio2.set_low();
ctx.delay.delay_millis(1);
ctx.test_gpio2.set_high();
test_gpio2.set_high();
ctx.delay.delay_millis(1);
let count = critical_section::with(|cs| *COUNTER.borrow_ref(cs));
assert_eq!(count, 9);
ctx.test_gpio1 = critical_section::with(|cs| INPUT_PIN.borrow_ref_mut(cs).take().unwrap());
ctx.test_gpio1.unlisten();
}
#[test]
fn test_gpio_od(ctx: Context<'static>) {
let mut test_gpio1 =
OutputOpenDrain::new(unsafe { TestGpio1::steal() }, Level::High, Pull::Up);
let mut test_gpio2 =
OutputOpenDrain::new(unsafe { TestGpio2::steal() }, Level::High, Pull::Up);
critical_section::with(|cs| INPUT_PIN.borrow_ref_mut(cs).take().unwrap());
test_gpio1.unlisten();
}
#[test]
fn test_gpio_od(ctx: Context) {
let mut test_gpio1 = OutputOpenDrain::new(ctx.test_gpio1, Level::High, Pull::Up);
let mut test_gpio2 = OutputOpenDrain::new(ctx.test_gpio2, Level::High, Pull::Up);
ctx.delay.delay_millis(1);
@ -232,9 +228,9 @@ mod tests {
}
#[test]
fn test_gpio_flex(ctx: Context<'static>) {
let mut test_gpio1 = Flex::new(unsafe { TestGpio1::steal() });
let mut test_gpio2 = Flex::new(unsafe { TestGpio2::steal() });
fn test_gpio_flex(ctx: Context) {
let mut test_gpio1 = Flex::new(ctx.test_gpio1);
let mut test_gpio2 = Flex::new(ctx.test_gpio2);
test_gpio1.set_high();
test_gpio1.set_as_output();
@ -274,9 +270,9 @@ mod tests {
// Tests touch pin (GPIO2) as AnyPin and Output
// https://github.com/esp-rs/esp-hal/issues/1943
#[test]
fn test_gpio_touch_anypin_output() {
let any_pin2 = AnyPin::new(unsafe { TestGpio1::steal() });
let any_pin3 = AnyPin::new(unsafe { TestGpio2::steal() });
fn test_gpio_touch_anypin_output(ctx: Context) {
let any_pin2 = AnyPin::new(ctx.test_gpio1);
let any_pin3 = AnyPin::new(ctx.test_gpio2);
let out_pin = Output::new(any_pin2, Level::High);
let in_pin = Input::new(any_pin3, Pull::Down);
@ -288,9 +284,9 @@ mod tests {
// Tests touch pin (GPIO2) as AnyPin and Input
// https://github.com/esp-rs/esp-hal/issues/1943
#[test]
fn test_gpio_touch_anypin_input() {
let any_pin2 = AnyPin::new(unsafe { TestGpio1::steal() });
let any_pin3 = AnyPin::new(unsafe { TestGpio2::steal() });
fn test_gpio_touch_anypin_input(ctx: Context) {
let any_pin2 = AnyPin::new(ctx.test_gpio1);
let any_pin3 = AnyPin::new(ctx.test_gpio2);
let out_pin = Output::new(any_pin3, Level::Low);
let in_pin = Input::new(any_pin2, Pull::Down);

View File

@ -15,7 +15,7 @@
use esp_hal::{
dma::{Channel, Dma, DmaPriority, DmaRxBuf},
dma_buffers,
gpio::{AnyOutput, AnyPin, Io, Level},
gpio::{ErasedPin, Io, Level, Output},
prelude::*,
spi::{
master::{Address, Command, Spi, SpiDma},
@ -41,13 +41,13 @@ cfg_if::cfg_if! {
struct Context {
spi: esp_hal::peripherals::SPI2,
dma_channel: Channel<'static, DmaChannel0, Blocking>,
miso: AnyPin<'static>,
miso_mirror: AnyOutput<'static>,
miso: ErasedPin,
miso_mirror: Output<'static>,
}
fn execute(
mut spi: SpiDma<'static, esp_hal::peripherals::SPI2, DmaChannel0, HalfDuplexMode, Blocking>,
mut miso_mirror: AnyOutput<'static>,
mut miso_mirror: Output<'static>,
wanted: u8,
) {
const DMA_BUFFER_SIZE: usize = 4;
@ -103,8 +103,8 @@ mod tests {
let (miso, miso_mirror) = hil_test::common_test_pins!(io);
let miso = AnyPin::new(miso);
let miso_mirror = AnyOutput::new(miso_mirror, Level::High);
let miso = miso.degrade();
let miso_mirror = Output::new(miso_mirror, Level::High);
let dma = Dma::new(peripherals.DMA);

View File

@ -17,7 +17,7 @@
use esp_hal::{
dma::{Channel, Dma, DmaPriority, DmaRxBuf, DmaTxBuf},
dma_buffers,
gpio::{AnyOutput, AnyPin, Io, Level},
gpio::{ErasedPin, Io, Level, Output},
prelude::*,
spi::{
master::{Address, Command, Spi, SpiDma},
@ -43,13 +43,13 @@ cfg_if::cfg_if! {
struct Context {
spi: esp_hal::peripherals::SPI2,
dma_channel: Channel<'static, DmaChannel0, Blocking>,
mosi: AnyPin<'static>,
mosi_mirror: AnyOutput<'static>,
mosi: ErasedPin,
mosi_mirror: Output<'static>,
}
fn execute(
mut spi: SpiDma<'static, esp_hal::peripherals::SPI2, DmaChannel0, HalfDuplexMode, Blocking>,
mut mosi_mirror: AnyOutput<'static>,
mut mosi_mirror: Output<'static>,
wanted: u8,
) {
const DMA_BUFFER_SIZE: usize = 4;
@ -105,8 +105,8 @@ mod tests {
let (mosi, mosi_mirror) = hil_test::common_test_pins!(io);
let mosi = AnyPin::new(mosi);
let mosi_mirror = AnyOutput::new(mosi_mirror, Level::High);
let mosi = mosi.degrade();
let mosi_mirror = Output::new(mosi_mirror, Level::High);
let dma = Dma::new(peripherals.DMA);

View File

@ -24,7 +24,7 @@ use embedded_hal_async::spi::SpiBus;
use esp_hal::{
dma::{Dma, DmaPriority, DmaRxBuf, DmaTxBuf},
dma_buffers,
gpio::{AnyPin, GpioPin, Io, Level, Output, Pull},
gpio::{ErasedPin, Io, Level, Output, Pull},
pcnt::{
channel::{EdgeMode, PcntInputConfig, PcntSource},
unit::Unit,
@ -57,8 +57,8 @@ const DMA_BUFFER_SIZE: usize = 5;
struct Context {
spi: SpiDmaBus<'static, SPI2, DmaChannel0, FullDuplexMode, Async>,
pcnt_unit: Unit<'static, 0>,
out_pin: Output<'static, GpioPin<5>>,
mosi_mirror: AnyPin<'static>,
out_pin: Output<'static>,
mosi_mirror: ErasedPin,
}
#[cfg(test)]
@ -79,7 +79,7 @@ mod tests {
let (mosi_mirror, mosi) = hil_test::common_test_pins!(io);
let miso = io.pins.gpio4;
let cs = io.pins.gpio8;
let mosi_mirror = AnyPin::new(mosi_mirror);
let mosi_mirror = mosi_mirror.degrade();
let mut out_pin = Output::new(io.pins.gpio5, Level::Low);
out_pin.set_low();

View File

@ -20,7 +20,7 @@
use esp_hal::{
dma::{Dma, DmaPriority, DmaRxBuf, DmaTxBuf},
dma_buffers,
gpio::{AnyPin, GpioPin, Io, Level, Output, Pull},
gpio::{ErasedPin, Io, Level, Output, Pull},
pcnt::{
channel::{EdgeMode, PcntInputConfig, PcntSource},
unit::Unit,
@ -51,8 +51,8 @@ cfg_if::cfg_if! {
struct Context {
spi: SpiDma<'static, SPI2, DmaChannel0, FullDuplexMode, Blocking>,
pcnt_unit: Unit<'static, 0>,
out_pin: Output<'static, GpioPin<5>>,
mosi_mirror: AnyPin<'static>,
out_pin: Output<'static>,
mosi_mirror: ErasedPin,
}
#[cfg(test)]
@ -91,7 +91,7 @@ mod tests {
let mut out_pin = Output::new(io.pins.gpio5, Level::Low);
out_pin.set_low();
assert_eq!(out_pin.is_set_low(), true);
let mosi_mirror = AnyPin::new(mosi_mirror);
let mosi_mirror = mosi_mirror.degrade();
Context {
spi,

View File

@ -16,7 +16,7 @@
use esp_hal::{
dma::{Dma, DmaPriority, DmaRxBuf, DmaTxBuf},
dma_buffers,
gpio::{AnyOutput, Io, Level},
gpio::{Io, Level, Output},
peripherals::SPI2,
prelude::*,
spi::{
@ -42,7 +42,7 @@ cfg_if::cfg_if! {
struct Context {
spi: SpiDma<'static, SPI2, DmaChannel0, HalfDuplexMode, Blocking>,
miso_mirror: AnyOutput<'static>,
miso_mirror: Output<'static>,
}
#[cfg(test)]
@ -60,7 +60,7 @@ mod tests {
let sclk = io.pins.gpio0;
let (miso, miso_mirror) = hil_test::common_test_pins!(io);
let miso_mirror = AnyOutput::new(miso_mirror, Level::High);
let miso_mirror = Output::new(miso_mirror, Level::High);
let dma = Dma::new(peripherals.DMA);